Skip to content
Snippets Groups Projects
Commit 6beade66 authored by Andreas Bolin's avatar Andreas Bolin
Browse files

workspace dump

parent 33fad4ad
No related branches found
No related tags found
1 merge request!78Add scheduler GUI
Pipeline #73397 passed
This commit is part of merge request !78. Comments created here will be created in the context of that merge request.
......@@ -47,6 +47,7 @@ class GraphicsComponentItem(QGraphicsItemGroup):
_height: float
_ports: Dict[str, Dict[str, Union[float, QPointF]]] # ['port-id']['latency/pos']
_execution_time: Union[int, None]
_end_time: int
_component_item: QGraphicsPathItem
_execution_time_item: QGraphicsRectItem
_label_item: QGraphicsSimpleTextItem
......@@ -59,6 +60,9 @@ class GraphicsComponentItem(QGraphicsItemGroup):
self._op_id = op_id
self._height = height
self._ports = {k:{'latency':float(v)} for k,v in latency_offsets.items()}
self._end_time = 0
for latency in latency_offsets.values():
self._end_time = max(self._end_time, latency)
self._execution_time = execution_time
self._port_items = []
......@@ -70,11 +74,11 @@ class GraphicsComponentItem(QGraphicsItemGroup):
self._make_component()
def sceneEvent(self, event: QEvent) -> bool:
print(f'Component -->\t\t\t\t{event.type()}')
# event.accept()
# QApplication.sendEvent(self.scene(), event)
return True
# def sceneEvent(self, event: QEvent) -> bool:
# print(f'Component -->\t\t\t\t{event.type()}')
# # event.accept()
# # QApplication.sendEvent(self.scene(), event)
# return True
def clear(self) -> None:
......@@ -100,6 +104,11 @@ class GraphicsComponentItem(QGraphicsItemGroup):
self.clear()
self._height = height
self._make_component()
@property
def end_time(self) -> int:
"""Get the relative end time."""
return self._end_time
@property
......
......@@ -22,7 +22,7 @@ from qtpy import QtWidgets
# QGraphics and QPainter imports
from qtpy.QtCore import (
Qt, QObject, QRect, QRectF, QPoint, QSize, QSizeF, QByteArray, Slot, QEvent)
Qt, QObject, QRect, QRectF, QPoint, QSize, QSizeF, QByteArray, Signal, Slot, QEvent)
from qtpy.QtGui import (
QPaintEvent, QPainter, QPainterPath, QColor, QBrush, QPen, QFont, QPolygon, QIcon, QPixmap,
QLinearGradient, QTransform, QCursor, QFocusEvent)
......@@ -45,12 +45,23 @@ from graphics_timeline_item import GraphicsTimelineItem
# class GraphicsGraphEvent(ABC):
class GraphicsGraphEvent(QGraphicsItem):
class GraphicsGraphEvent(QGraphicsObject, QGraphicsItem):
"""Event filter and handlers for GraphicsGraphItem"""
_axes: GraphicsAxesItem
_current_pos: QPointF
_delta_time: int
component_selected = Signal(str)
@overload
def is_component_valid_pos(self, pos: float, end_time: int) -> bool: ...
@overload
def is_valid_delta_time(self, delta_time: int) -> bool: ...
@overload
def set_schedule_time(self, delta_time: int) -> None: ...
def __init__(self):
super().__init__()
#################
#### Filters ####
......@@ -158,17 +169,17 @@ class GraphicsGraphEvent(QGraphicsItem):
horizontally in x-axis scale steps."""
# Qt.DragMoveCursor
# button = event.button()
item = self.scene().mouseGrabberItem()
item: GraphicsComponentItem = self.scene().mouseGrabberItem()
dx = (item.mapToParent(event.pos()) - self._current_pos).x()
if dx > 0.505:
pos = item.x() + 1.0
if self.is_component_valid_pos(pos):
if self.is_component_valid_pos(pos, item.end_time):
# self.prepareGeometryChange()
item.setX(pos)
self._current_pos.setX(self._current_pos.x() + 1.0)
elif dx < -0.505:
pos = item.x() - 1.0
if self.is_component_valid_pos(pos):
if self.is_component_valid_pos(pos, item.end_time):
# self.prepareGeometryChange()
item.setX(pos)
self._current_pos.setX(self._current_pos.x() - 1.0)
......@@ -179,8 +190,10 @@ class GraphicsGraphEvent(QGraphicsItem):
by default be accepted, and this item is then the mouse grabber. This
allows the item to receive future move, release and double-click events."""
item: GraphicsComponentItem = self.scene().mouseGrabberItem()
self.component_selected.emit(item.op_id)
# op = self.schedule.sfg.find_by_id(item.op_id)
# emit fill_info_table_component(op)
self._current_pos = item.mapToParent(event.pos())
self.setCursor(QCursor(Qt.ClosedHandCursor))
event.accept()
......
......@@ -5,6 +5,7 @@
Contains the scheduler-gui GraphicsGraphItem class for drawing and
maintain a component in a graph.
"""
from math import floor
import os
import sys
from typing import Any, Optional
......@@ -79,18 +80,26 @@ class GraphicsGraphItem(QGraphicsItemGroup, GraphicsGraphEvent):
item.setParentItem(None)
del item
def is_component_valid_pos(self, pos: float) -> bool:
def is_component_valid_pos(self, pos: float, end_time: int) -> bool:
"""Takes in a component position and returns true if the component's new
position is valid, false otherwise."""
# TODO: implement
# item = self.scene().mouseGrabberItem()
assert self.schedule is not None , "No schedule installed."
start_time = floor(pos) - floor(self._x_axis_indent)
if pos < 0:
return False
elif (self.schedule.cyclic
and start_time > self.schedule.schedule_time):
return False
elif (not self.schedule.cyclic
and start_time + end_time > self.schedule.schedule_time):
return False
return True
def is_valid_delta_time(self, delta_time: int) -> bool:
"""Takes in a delta time and returns true if the new schedule time is valid
, false otherwise."""
"""Takes in a delta time and returns true if the new schedule time is
valid, false otherwise."""
# TODO: implement
# item = self.scene().mouseGrabberItem()
assert self.schedule is not None , "No schedule installed."
......@@ -101,17 +110,7 @@ class GraphicsGraphItem(QGraphicsItemGroup, GraphicsGraphEvent):
"""Set the schedule time and redraw the graph."""
assert self.schedule is not None , "No schedule installed."
self.schedule.set_schedule_time(self.schedule.schedule_time + delta_time)
# scene = self.scene()
# if scene is not None:
# self.removeSceneEventFilters(self._axes.event_items)
# self._axes.update_axes(width = self._axes.width + delta_time)
# if scene is not None:
# self.installSceneEventFilters(self._axes.event_items)
# print(f'self._axes.event_items {self._axes.event_items}')
# print(f'set_schedule_time({delta_time})')
self._axes.set_width(self._axes.width + delta_time)
# self.scene().views()[0].updateScene(QRectF(0, 0, 1, 1))
@property
......
......@@ -10,7 +10,7 @@ import os
import sys
from pathlib import Path
from types import ModuleType
from typing import Any, Iterable, List, Sequence, Type, Dict
from typing import Any, Iterable, List, Sequence, Type, Dict, Union
from pprint import pprint
#from matplotlib.pyplot import bar
#from diagram import *
......@@ -113,12 +113,11 @@ QCoreApplication.setApplicationName('B-ASIC Scheduler')
class MainWindow(QMainWindow, Ui_MainWindow):
"""Schedule of an SFG with scheduled Operations."""
_scene: QGraphicsScene
_graph: GraphicsGraphItem
_graph: Union[GraphicsGraphItem, None]
_scale: float
_debug_rects: QGraphicsItemGroup
_splitter_pos: int
_splitter_min: int
_table_items: Dict[str, QTableWidgetItem]
def __init__(self):
......@@ -128,14 +127,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self._open_file_dialog_opened = False
self._scale = 75
self._debug_rects = None
self._table_items: Dict[str, QTableWidgetItem]= {
'schedule_time': QTableWidgetItem(), # Schedule related part
'cyclic': QTableWidgetItem(),
'resolution': QTableWidgetItem(),
'id': QTableWidgetItem(), # Component realtaed part
'name': QTableWidgetItem(),
'inports': QTableWidgetItem(),
'outports': QTableWidgetItem()}
QIcon.setThemeName('breeze')
log.debug('themeName: \'{}\''.format(QIcon.themeName()))
......@@ -154,6 +145,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
# Connect signals to slots
self.menu_load_from_file.triggered .connect(self._load_schedule_from_pyfile)
self.menu_close_schedule.triggered .connect(self.close_schedule)
self.menu_save .triggered .connect(self.save)
self.menu_save_as .triggered .connect(self.save_as)
self.menu_quit .triggered .connect(self.close)
......@@ -191,84 +183,14 @@ class MainWindow(QMainWindow, Ui_MainWindow):
def _init_graphics(self) -> None:
"""Initialize the QGraphics framework"""
self._scene = QGraphicsScene()
self._scene.addRect(0, 0, 0, 0) # dummy rect to be able to setPos graph
self.view.setScene(self._scene)
self.view.scale(self._scale, self._scale)
GraphicsComponentItem._scale = self._scale
GraphicsAxesItem._scale = self._scale
self._scene.changed.connect(self.shrink_scene_to_min_size)
def fill_info_table_schedule(self, schedule: Schedule) -> None:
self._table_items['schedule_time'].setText(str(schedule.schedule_time))
self._table_items['cyclic'].setText(str(schedule.cyclic))
self._table_items['resolution'].setText(str(schedule.resolution))
self.info_table.insertRow(1)
self.info_table.insertRow(1)
self.info_table.insertRow(1)
self.info_table.setItem(1, 0, QTableWidgetItem('Schedule Time'))
self.info_table.setItem(2, 0, QTableWidgetItem('Cyclic'))
self.info_table.setItem(3, 0, QTableWidgetItem('Resolution'))
self.info_table.setItem(1, 1 ,self._table_items['schedule_time'])
self.info_table.setItem(2, 1 ,self._table_items['cyclic'])
self.info_table.setItem(3, 1 ,self._table_items['resolution'])
# self.info_table.setVerticalHeaderItem(0, mydict['test'])
# self._table_items['schedule_time'].setText('test item updated text')
for i in range(5,10):
self.info_table.insertRow(i)
item = QTableWidgetItem('this is a very very very very long string that says abolutly nothing')
self.info_table.setItem(i,0, QTableWidgetItem('property {}: '.format(i)))
self.info_table.setItem(i,1,item)
def fill_info_table_component(self, op: GraphComponent) -> None:
si = len(self._table_items) + 1 # si = start index
self.info_table.insertRow(si)
self.info_table.insertRow(si)
self.info_table.setItem(si + 0, 0, QTableWidgetItem('Graph ID'))
self.info_table.setItem(si + 0, 1, QTableWidgetItem(str(op.graph_id)))
self.info_table.setItem(si + 1, 0, QTableWidgetItem('Name'))
self.info_table.setItem(si + 1, 1, QTableWidgetItem(str(op.name)))
si += 2
params = [(k,v) for k,v in op.params]
for i in range(len(params)):
self.info_table.insertRow(si + i)
self.info_table.setItem(si + i, 0, QTableWidgetItem(params[i][0]))
self.info_table.setItem(si + i, 1, QTableWidgetItem(params[i][1]))
# graph_id
# name
# params (dict)
self._table_items['schedule_time'].setText(str(schedule.schedule_time))
self._table_items['cyclic'].setText(str(schedule.cyclic))
self._table_items['resolution'].setText(str(schedule.resolution))
self.info_table.insertRow(si)
self.info_table.insertRow(si)
self.info_table.insertRow(si)
self.info_table.setItem(si + 0, 0, QTableWidgetItem('ID'))
self.info_table.setItem(si + 1, 0, QTableWidgetItem('Name'))
self.info_table.setItem(si + 3, 0, QTableWidgetItem('Inports'))
self.info_table.setItem(si + 3, 0, QTableWidgetItem('Outports'))
self.info_table.setItem(si + 1, 1 ,self._table_items['id'])
self.info_table.setItem(si + 2, 1 ,self._table_items['name'])
self.info_table.setItem(si + 3, 1 ,self._table_items['inports'])
self.info_table.setItem(si + 3, 1 ,self._table_items['outports'])
# self.info_table.setVerticalHeaderItem(0, mydict['test'])
# self._table_items['schedule_time'].setText('test item updated text')
for i in range(5,10):
self.info_table.insertRow(i)
item = QTableWidgetItem('this is a very very very very long string that says abolutly nothing')
self.info_table.setItem(i,0, QTableWidgetItem('property {}: '.format(i)))
self.info_table.setItem(i,1,item)
def clear_info_table_schedule(self) -> None:
for _ in range(3): # Remove Schedule info
self.info_table.removeRow(1)
def clear_info_table_component(self) -> None:
for _ in range(5): # Remove component info
self.info_table.removeRow(2)
......@@ -339,43 +261,15 @@ class MainWindow(QMainWindow, Ui_MainWindow):
del module
settings.setValue("mainwindow/last_opened_file", abs_path_filename)
@Slot()
def close_schedule(self) -> None:
self._graph.removeSceneEventFilters(self._graph.event_items)
self._scene.removeItem(self._graph)
self.menu_close_schedule.setEnabled(False)
del self._graph
self._graph = None
self.clear_info_table()
#@Slot()
def open(self, schedule: Schedule) -> None:
"""Takes in an Schedule and creates a GraphicsGraphItem object."""
self._graph = GraphicsGraphItem(schedule)
self._scene.addItem(self._graph)
self._graph.installSceneEventFilters(self._graph.event_items)
# graph.prepareGeometryChange()
# graph.setPos(200, 20)
# self._scene.setSceneRect(self._scene.itemsBoundingRect()) # Forces the scene to it's minimum size
# # Debug rectangles
# if __debug__:
# # self._scene.setSceneRect(self._scene.itemsBoundingRect()) # Forces the scene to it's minimum size
# m = QMarginsF(1/self._scale, 1/self._scale, 0, 0)
# m2 = QMarginsF(1, 1, 1, 1)
# pen = QPen(Qt.red)
# pen.setStyle(Qt.DotLine)
# pen.setCosmetic(True)
# for component in graph.items:
# self._scene.addRect(component.mapRectToScene(component.boundingRect() - m), pen)
# pen.setColor(Qt.red)
# for axis in graph.axes.childItems():
# self._scene.addRect(axis.mapRectToScene(axes.boundingRect() - m), pen)
# pen.setColor(Qt.green)
# # self._scene.addRect(self._scene.itemsBoundingRect() - m, pen)
# self._scene.setSceneRect(self._scene.itemsBoundingRect())
self.update_statusbar(self.tr('Schedule loaded successfully'))
self.fill_info_table_schedule(self._graph.schedule)
@Slot()
def save(self) -> None:
"""This method save an schedule."""
......@@ -424,7 +318,14 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.menu_node_info.setChecked(True)
self._splitter_pos = width
@Slot(str)
def fill_info_table_component(self, op_id: str) -> None:
"""Taked in an operator-id, first clears the 'Operator' part of the info
table and then fill in the table with new values from the operator
associated with 'op_id'."""
self.clear_info_table_component()
self._fill_info_table_component(op_id)
@Slot('QList<QRectF>')
def shrink_scene_to_min_size(self, region: List[QRectF]) -> None:
self._scene.setSceneRect(self._scene.itemsBoundingRect())
......@@ -475,6 +376,20 @@ class MainWindow(QMainWindow, Ui_MainWindow):
alert = QMessageBox(self)
alert.setText("Called from " + func_name + '!')
alert.exec_()
def open(self, schedule: Schedule) -> None:
"""Takes in an Schedule and creates a GraphicsGraphItem object."""
if self._graph:
print('Graph opened!')
self.close_schedule()
self._graph = GraphicsGraphItem(schedule)
self._graph.setPos(1/self._scale, 1/self._scale)
self.menu_close_schedule.setEnabled(True)
self._scene.addItem(self._graph)
self._graph.installSceneEventFilters(self._graph.event_items)
self._graph.component_selected.connect(self.fill_info_table_component)
self.fill_info_table_schedule(self._graph.schedule)
self.update_statusbar(self.tr('Schedule loaded successfully'))
def update_statusbar(self, msg: str) -> None:
"""Write the given str to the statusbar with temporarily policy."""
......@@ -511,6 +426,59 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.menu_exit_dialog.setChecked( s.value('mainwindow/hide_exit_dialog', False, bool))
log.debug('Settings read from \'{}\'.'.format(s.fileName()))
def fill_info_table_schedule(self, schedule: Schedule) -> None:
"""Takes in a Schedule and fill in the 'Schedule' part of the info table
with values from 'schedule'"""
self.info_table.insertRow(1)
self.info_table.insertRow(1)
self.info_table.insertRow(1)
self.info_table.setItem(1, 0, QTableWidgetItem('Schedule Time'))
self.info_table.setItem(2, 0, QTableWidgetItem('Cyclic'))
self.info_table.setItem(3, 0, QTableWidgetItem('Resolution'))
self.info_table.setItem(1, 1, QTableWidgetItem(str(schedule.schedule_time)))
self.info_table.setItem(2, 1, QTableWidgetItem(str(schedule.cyclic)))
self.info_table.setItem(3, 1, QTableWidgetItem(str(schedule.resolution)))
def _fill_info_table_component(self, op_id: str) -> None:
"""Taked in an operator-id and fill in the 'Operator' part of the info
table with values from the operator associated with 'op_id'."""
op: GraphComponent = self._graph.schedule.sfg.find_by_id(op_id)
si = self.info_table.rowCount() # si = start index
if op.graph_id:
self.info_table.insertRow(si)
self.info_table.setItem(si, 0, QTableWidgetItem('ID'))
self.info_table.setItem(si, 1, QTableWidgetItem(str(op.graph_id)))
si += 1
if op.name:
self.info_table.insertRow(si)
self.info_table.setItem(si, 0, QTableWidgetItem('Name'))
self.info_table.setItem(si, 1, QTableWidgetItem(str(op.name)))
si += 1
# params: dict = op.params
print('Params:')
pprint(op.params)
for key, value in op.params:
self.info_table.insertRow(si)
self.info_table.setItem(si, 0, QTableWidgetItem(key))
self.info_table.setItem(si, 1, QTableWidgetItem(str(value)))
si += 1
def clear_info_table(self) -> None:
"""Clears the info table."""
self.clear_info_table_component()
if self.info_table.rowCount() > 2:
for _ in range(3):
self.info_table.removeRow(1)
def clear_info_table_component(self) -> None:
"""Clears only the component part of the info table, assuming that the table is filled."""
if self.info_table.rowCount() > 5:
for _ in range(self.info_table.rowCount() - 5):
self.info_table.removeRow(2)
......
......@@ -106,7 +106,7 @@
<x>0</x>
<y>0</y>
<width>800</width>
<height>22</height>
<height>20</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
......@@ -114,6 +114,7 @@
<string>&amp;File</string>
</property>
<addaction name="menu_load_from_file"/>
<addaction name="menu_close_schedule"/>
<addaction name="menu_save"/>
<addaction name="menu_save_as"/>
<addaction name="separator"/>
......@@ -178,6 +179,9 @@
</property>
</action>
<action name="menu_save">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset theme="document-save">
<normaloff>.</normaloff>.</iconset>
......@@ -230,6 +234,9 @@
</property>
</action>
<action name="menu_save_as">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset theme="document-save-as">
<normaloff>.</normaloff>.</iconset>
......@@ -254,6 +261,14 @@
<string>T</string>
</property>
</action>
<action name="menu_close_schedule">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Close Schedule</string>
</property>
</action>
</widget>
<resources>
<include location="icons/basic.qrc"/>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment