diff --git a/b_asic/scheduler_gui/__init__.py b/b_asic/scheduler_gui/__init__.py index ada1c2c7cc2ed9a9fe7f5b9b42c7b6d2bb899632..9aa32805ef21263f4fa794ac3472026c8326e115 100644 --- a/b_asic/scheduler_gui/__init__.py +++ b/b_asic/scheduler_gui/__init__.py @@ -5,7 +5,6 @@ Graphical user interface for B-ASIC scheduler. __author__ = "Andreas Bolin" # __all__ = ['main_window', 'graphics_graph', 'component_item', 'graphics_axes', 'graphics_timeline_item'] -from b_asic.scheduler_gui._version import * from b_asic.scheduler_gui.axes_item import * from b_asic.scheduler_gui.logger import * from b_asic.scheduler_gui.main_window import * diff --git a/b_asic/scheduler_gui/_version.py b/b_asic/scheduler_gui/_version.py deleted file mode 100644 index 0ef1deb513ce5da0942c04df423c3f9950f30251..0000000000000000000000000000000000000000 --- a/b_asic/scheduler_gui/_version.py +++ /dev/null @@ -1,2 +0,0 @@ -__version_info__ = ("0", "1") -__version__ = ".".join(__version_info__) diff --git a/b_asic/scheduler_gui/axes_item.py b/b_asic/scheduler_gui/axes_item.py index 62afca240ae2cead20865a2605ec4e99d9b5508c..a054a3291a8be43919a63d591bdfe1d1a7008634 100644 --- a/b_asic/scheduler_gui/axes_item.py +++ b/b_asic/scheduler_gui/axes_item.py @@ -25,7 +25,19 @@ from b_asic.scheduler_gui.timeline_item import TimelineItem class AxesItem(QGraphicsItemGroup): - """A class to represent axes in a graph.""" + """ + A class to represent axes in a graph. + + Parameters + ---------- + width + height + width_indent + height_indent + width_padding + height_padding + parent + """ _scale: float = 1.0 """Static, changed from MainWindow.""" @@ -59,7 +71,7 @@ class AxesItem(QGraphicsItemGroup): parent: Optional[QGraphicsItem] = None, ): """ - Construct an AxesItem. + Class for an AxesItem. *parent* is passed to QGraphicsItemGroup's constructor. """ super().__init__(parent=parent) diff --git a/b_asic/scheduler_gui/main_window.py b/b_asic/scheduler_gui/main_window.py index cdea2fb88cf890f51cd0a733fa5c47c6a7fd1516..80ff8ab7d9054fd68907e076d8cc643a9edde362 100644 --- a/b_asic/scheduler_gui/main_window.py +++ b/b_asic/scheduler_gui/main_window.py @@ -44,6 +44,7 @@ from qtpy.QtWidgets import ( # B-ASIC import b_asic.scheduler_gui.logger as logger +from b_asic._version import __version__ from b_asic.graph_component import GraphComponent, GraphID from b_asic.schedule import Schedule from b_asic.scheduler_gui.axes_item import AxesItem @@ -66,9 +67,9 @@ if __debug__: from qtpy import QtCore QT_API = os.environ.get("QT_API", "") - log.debug("Qt version (runtime): {}".format(QtCore.qVersion())) - log.debug("Qt version (compiletime): {}".format(QtCore.__version__)) - log.debug("QT_API: {}".format(QT_API)) + log.debug("Qt version (runtime): {}".format(QtCore.qVersion())) + log.debug("Qt version (compile time): {}".format(QtCore.__version__)) + log.debug("QT_API: {}".format(QT_API)) if QT_API.lower().startswith("pyside"): import PySide2 @@ -84,7 +85,9 @@ if __debug__: QCoreApplication.setOrganizationName("Linköping University") QCoreApplication.setOrganizationDomain("liu.se") QCoreApplication.setApplicationName("B-ASIC Scheduler") -# QCoreApplication.setApplicationVersion(__version__) # TODO: read from packet __version__ +QCoreApplication.setApplicationVersion( + __version__ +) # TODO: read from packet __version__ class MainWindow(QMainWindow, Ui_MainWindow): @@ -94,7 +97,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): _schedule: Union[Schedule, None] _graph: Union[SchedulerItem, None] _scale: float - _debug_rects: QGraphicsItemGroup + _debug_rectangles: QGraphicsItemGroup _splitter_pos: int _splitter_min: int _zoom: float @@ -105,7 +108,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): self._schedule = None self._graph = None self._scale = 75.0 - self._debug_rects = None + self._debug_rectangles = None self._zoom = 1.0 self.setupUi(self) @@ -159,7 +162,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): @property def schedule(self) -> Optional[Schedule]: - """Get the current schedule.""" + """The current schedule.""" return self._schedule ######### @@ -173,7 +176,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.schedule.plot() if self._graph is not None: print(f"filtersChildEvents(): {self._graph.filtersChildEvents()}") - # self._printButtonPressed('callback_pushButton()') + # self._print_button_pressed('callback_pushButton()') @Slot() def _open_documentation(self) -> None: @@ -181,14 +184,15 @@ class MainWindow(QMainWindow, Ui_MainWindow): @Slot() def _actionReorder(self) -> None: - # TODO: remove + """Callback to reorder all operations vertically based on start time. + """ if self.schedule is None: return if self._graph is not None: self._graph._redraw_from_start() - # self._printButtonPressed('callback_pushButton()') - def wheelEvent(self, event): + def wheelEvent(self, event) -> None: + """Zoom in or out using mouse wheel if control is pressed.""" if event.modifiers() == Qt.KeyboardModifier.ControlModifier: old_zoom = self._zoom self._zoom += event.angleDelta().y() / 2500 @@ -197,12 +201,14 @@ class MainWindow(QMainWindow, Ui_MainWindow): @Slot() def _load_schedule_from_pyfile(self) -> None: - """SLOT() for SIGNAL(menu_load_from_file.triggered) + """ + SLOT() for SIGNAL(menu_load_from_file.triggered) Load a python script as a module and search for a Schedule object. If - found, opens it.""" + found, opens it. + """ settings = QSettings() last_file = settings.value( - "mainwindow/last_opened_file", + "scheduler/last_opened_file", QStandardPaths.standardLocations(QStandardPaths.HomeLocation)[0], str, ) @@ -289,12 +295,14 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.open(schedule) del module - settings.setValue("mainwindow/last_opened_file", abs_path_filename) + settings.setValue("scheduler/last_opened_file", abs_path_filename) @Slot() def close_schedule(self) -> None: - """SLOT() for SIGNAL(menu_close_schedule.triggered) - Closes current schedule.""" + """ + SLOT() for SIGNAL(menu_close_schedule.triggered) + Closes current schedule. + """ if self._graph: self._graph._signals.component_selected.disconnect( self.info_table_update_component @@ -318,22 +326,26 @@ class MainWindow(QMainWindow, Ui_MainWindow): This method save a schedule. """ # TODO: all - self._printButtonPressed("save_schedule()") + self._print_button_pressed("save_schedule()") self.update_statusbar(self.tr("Schedule saved successfully")) @Slot() def save_as(self) -> None: - """SLOT() for SIGNAL(menu_save_as.triggered) - This method save as a schedule.""" + """ + SLOT() for SIGNAL(menu_save_as.triggered) + This method save as a schedule. + """ # TODO: all - self._printButtonPressed("save_schedule()") + self._print_button_pressed("save_schedule()") self.update_statusbar(self.tr("Schedule saved successfully")) @Slot(bool) def show_info_table(self, checked: bool) -> None: - """SLOT(bool) for SIGNAL(menu_node_info.triggered) + """ + SLOT(bool) for SIGNAL(menu_node_info.triggered) Takes in a boolean and hide or show the info table accordingly with - 'checked'.""" + 'checked'. + """ # Note: splitter handler index 0 is a hidden splitter handle far most left, use index 1 # settings = QSettings() _, max_ = self.splitter.getRange(1) # tuple(min, max) @@ -353,8 +365,8 @@ class MainWindow(QMainWindow, Ui_MainWindow): Takes in a boolean and stores 'checked' in 'hide_exit_dialog' item in settings. """ - s = QSettings() - s.setValue("mainwindow/hide_exit_dialog", checked) + settings = QSettings() + settings.setValue("scheduler/hide_exit_dialog", checked) @Slot(int, int) def _splitter_moved(self, pos: int, index: int) -> None: @@ -414,8 +426,8 @@ class MainWindow(QMainWindow, Ui_MainWindow): in a QCloseEvent and display an exit dialog, depending on 'hide_exit_dialog' in settings. """ - s = QSettings() - hide_dialog = s.value("mainwindow/hide_exit_dialog", False, bool) + settings = QSettings() + hide_dialog = settings.value("scheduler/hide_exit_dialog", False, bool) ret = QMessageBox.StandardButton.Yes if not hide_dialog: @@ -439,7 +451,9 @@ class MainWindow(QMainWindow, Ui_MainWindow): if ret == QMessageBox.StandardButton.Yes: if not hide_dialog: - s.setValue("mainwindow/hide_exit_dialog", checkbox.isChecked()) + settings.setValue( + "scheduler/hide_exit_dialog", checkbox.isChecked() + ) self._write_settings() log.info("Exit: {}".format(os.path.basename(__file__))) event.accept() @@ -449,7 +463,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): ########################### # Helper member functions # ########################### - def _printButtonPressed(self, func_name: str) -> None: + def _print_button_pressed(self, func_name: str) -> None: # TODO: remove alert = QMessageBox(self) @@ -475,53 +489,63 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.update_statusbar(self.tr("Schedule loaded successfully")) def update_statusbar(self, msg: str) -> None: - """Take a str and write *msg* to the statusbar with temporarily policy. + """ + Write *msg* to the statusbar with temporarily policy. + + Parameters + ---------- + msg : str + The message to write. """ self.statusbar.showMessage(msg) def _write_settings(self) -> None: """Write settings from MainWindow to Settings.""" - s = QSettings() - s.setValue( - "mainwindow/maximized", self.isMaximized() + settings = QSettings() + settings.setValue( + "scheduler/maximized", self.isMaximized() ) # window: maximized, in X11 - always False - s.setValue("mainwindow/pos", self.pos()) # window: pos - s.setValue("mainwindow/size", self.size()) # window: size - s.setValue( - "mainwindow/state", self.saveState() + settings.setValue("scheduler/pos", self.pos()) # window: pos + settings.setValue("scheduler/size", self.size()) # window: size + settings.setValue( + "scheduler/state", self.saveState() ) # toolbars, dockwidgets: pos, size - s.setValue( - "mainwindow/menu/node_info", self.menu_node_info.isChecked() + settings.setValue( + "scheduler/menu/node_info", self.menu_node_info.isChecked() ) - s.setValue("mainwindow/splitter/state", self.splitter.saveState()) - s.setValue("mainwindow/splitter/pos", self.splitter.sizes()[1]) + settings.setValue( + "scheduler/splitter/state", self.splitter.saveState() + ) + settings.setValue("scheduler/splitter/pos", self.splitter.sizes()[1]) - if s.isWritable(): - log.debug("Settings written to '{}'.".format(s.fileName())) + if settings.isWritable(): + log.debug("Settings written to '{}'.".format(settings.fileName())) else: log.warning("Settings cant be saved to file, read-only.") def _read_settings(self) -> None: """Read settings from Settings to MainWindow.""" - s = QSettings() - if s.value("mainwindow/maximized", defaultValue=False, type=bool): + settings = QSettings() + if settings.value( + "scheduler/maximized", defaultValue=False, type=bool + ): self.showMaximized() else: - self.move(s.value("mainwindow/pos", self.pos())) - self.resize(s.value("mainwindow/size", self.size())) - self.restoreState(s.value("mainwindow/state", QByteArray())) + self.move(settings.value("scheduler/pos", self.pos())) + self.resize(settings.value("scheduler/size", self.size())) + self.restoreState(settings.value("scheduler/state", QByteArray())) self.menu_node_info.setChecked( - s.value("mainwindow/menu/node_info", True, bool) + settings.value("scheduler/menu/node_info", True, bool) ) self.splitter.restoreState( - s.value("mainwindow/splitter/state", QByteArray()) + settings.value("scheduler/splitter/state", QByteArray()) ) - self._splitter_pos = s.value("mainwindow/splitter/pos", 200, int) + self._splitter_pos = settings.value("scheduler/splitter/pos", 200, int) self.menu_exit_dialog.setChecked( - s.value("mainwindow/hide_exit_dialog", False, bool) + settings.value("scheduler/hide_exit_dialog", False, bool) ) - log.debug("Settings read from '{}'.".format(s.fileName())) + log.debug("Settings read from '{}'.".format(settings.fileName())) def info_table_fill_schedule(self, schedule: Schedule) -> None: """ @@ -584,7 +608,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): "'Operator' not found in info table. It may have been renamed." ) - def exit_app(self): + def exit_app(self) -> None: """Exit application.""" log.info("Exiting the application.") QApplication.quit() @@ -602,7 +626,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): ) -def start_gui(): +def start_gui() -> None: app = QApplication(sys.argv) window = MainWindow() window.show() diff --git a/b_asic/scheduler_gui/operation_item.py b/b_asic/scheduler_gui/operation_item.py index 5321b7224dcd6d0575fc5a915b9edaecf626b30d..f728fe37dcfaddb9ba10f5a3c20a8e5068d59300 100644 --- a/b_asic/scheduler_gui/operation_item.py +++ b/b_asic/scheduler_gui/operation_item.py @@ -30,7 +30,15 @@ from b_asic.scheduler_gui._preferences import ( class OperationItem(QGraphicsItemGroup): - """Class to represent a component in a graph.""" + """ + Class to represent an operation in a graph. + + Parameters + ---------- + operation : Operation + height : float, default: 1.0 + parent : QGraphicsItem, optional + """ _scale: float = 1.0 """Static, changed from MainWindow.""" @@ -91,12 +99,12 @@ class OperationItem(QGraphicsItemGroup): @property def graph_id(self) -> GraphID: - """Get the op-id.""" + """The graph-id of the operation that the item corresponds to.""" return self._operation.graph_id @property def operation(self) -> Operation: - """Get the operation.""" + """The operation that the item corresponds to.""" return self._operation @property @@ -116,26 +124,40 @@ class OperationItem(QGraphicsItemGroup): @property def end_time(self) -> int: - """Get the relative end time.""" + """The relative end time.""" return self._end_time @property def event_items(self) -> List[QGraphicsItem]: - """Returns a list of objects, that receives events.""" + """List of objects that receives events.""" return [self] - def get_port_location(self, key) -> QPointF: + def get_port_location(self, key: str) -> QPointF: + """ + Return the location specified by *key*. + + Parameters + ---------- + key : str + The port key. + + Returns + ------- + The location as a QPointF. + """ return self.mapToParent(self._ports[key]["pos"]) - def set_active(self): + def set_active(self) -> None: + """Set the item as active, i.e., draw it in special colors.""" self._set_background(OPERATION_LATENCY_ACTIVE) self.setCursor(QCursor(Qt.CursorShape.ClosedHandCursor)) - def set_inactive(self): + def set_inactive(self) -> None: + """Set the item as inactive, i.e., draw it in standard colors.""" self._set_background(OPERATION_LATENCY_INACTIVE) self.setCursor(QCursor(Qt.CursorShape.OpenHandCursor)) - def _set_background(self, color: QColor): + def _set_background(self, color: QColor) -> None: brush = QBrush(color) self._latency_item.setBrush(brush) @@ -198,13 +220,13 @@ class OperationItem(QGraphicsItemGroup): key = f"{prefix}{i}" self._ports[key]["pos"] = pos port_pos = self.mapToParent(pos) - port = QGraphicsEllipseItem( + new_port = QGraphicsEllipseItem( -port_size / 2, -port_size / 2, port_size, port_size ) - port.setPen(port_outline_pen) - port.setBrush(port_filling_brush) - port.setPos(port_pos.x(), port_pos.y()) - self._port_items.append(port) + new_port.setPen(port_outline_pen) + new_port.setBrush(port_filling_brush) + new_port.setPos(port_pos.x(), port_pos.y()) + self._port_items.append(new_port) create_ports(inputs, "in") create_ports(outputs, "out") diff --git a/b_asic/scheduler_gui/scheduler_event.py b/b_asic/scheduler_gui/scheduler_event.py index ca40bd8a0d81437121ccf84bff2f61c81c053917..5e2f1272251e871118822bc42175e30a2739d231 100644 --- a/b_asic/scheduler_gui/scheduler_event.py +++ b/b_asic/scheduler_gui/scheduler_event.py @@ -68,9 +68,9 @@ class SchedulerEvent: # PyQt5 def set_item_inactive(self, item: OperationItem) -> None: raise NotImplementedError - ################# - #### Filters #### - ################# + ########### + # Filters # + ########### @overload def installSceneEventFilters(self, filterItems: QGraphicsItem) -> None: ... @@ -116,24 +116,23 @@ class SchedulerEvent: # PyQt5 If False is returned, the event is forwarded to the appropriate child in the event chain. """ - handler = None if isinstance(item, OperationItem): # one component switch = { - # QEvent.FocusIn: self.comp_focusInEvent, - # QEvent.GraphicsSceneContextMenu: self.comp_contextMenuEvent, - # QEvent.GraphicsSceneDragEnter: self.comp_dragEnterEvent, - # QEvent.GraphicsSceneDragMove: self.comp_dragMoveEvent, - # QEvent.GraphicsSceneDragLeave: self.comp_dragLeaveEvent, - # QEvent.GraphicsSceneDrop: self.comp_dropEvent, - # QEvent.GraphicsSceneHoverEnter: self.comp_hoverEnterEvent, - # QEvent.GraphicsSceneHoverMove: self.comp_hoverMoveEvent, - # QEvent.GraphicsSceneHoverLeave: self.comp_hoverLeaveEvent, - QEvent.GraphicsSceneMouseMove: self.comp_mouseMoveEvent, - QEvent.GraphicsSceneMousePress: self.comp_mousePressEvent, - QEvent.GraphicsSceneMouseRelease: self.comp_mouseReleaseEvent, - # QEvent.GraphicsSceneMouseDoubleClick: self.comp_mouseDoubleClickEvent, - # QEvent.GraphicsSceneWheel: self.comp_wheelEvent + # QEvent.FocusIn: self.operation_focusInEvent, + # QEvent.GraphicsSceneContextMenu: self.operation_contextMenuEvent, + # QEvent.GraphicsSceneDragEnter: self.operation_dragEnterEvent, + # QEvent.GraphicsSceneDragMove: self.operation_dragMoveEvent, + # QEvent.GraphicsSceneDragLeave: self.operation_dragLeaveEvent, + # QEvent.GraphicsSceneDrop: self.operation_dropEvent, + # QEvent.GraphicsSceneHoverEnter: self.operation_hoverEnterEvent, + # QEvent.GraphicsSceneHoverMove: self.operation_hoverMoveEvent, + # QEvent.GraphicsSceneHoverLeave: self.operation_hoverLeaveEvent, + QEvent.GraphicsSceneMouseMove: self.operation_mouseMoveEvent, + QEvent.GraphicsSceneMousePress: self.operation_mousePressEvent, + QEvent.GraphicsSceneMouseRelease: self.operation_mouseReleaseEvent, + # QEvent.GraphicsSceneMouseDoubleClick: self.operation_mouseDoubleClickEvent, + # QEvent.GraphicsSceneWheel: self.operation_wheelEvent } handler = switch.get(event.type()) @@ -153,67 +152,76 @@ class SchedulerEvent: # PyQt5 f"from an '{type(item).__name__}' object." ) - if handler is not None: - handler(event) - return True - return False # returns False if event is ignored and pass through event to its child - - # def sceneEvent(self, event: QEvent) -> bool: - # print(f'sceneEvent() --> {event.type()}') - # # event.accept() - # # QApplication.sendEvent(self.scene(), event) - # return False - - ############################################### - #### Event Handlers: OperationItem #### - ############################################### - def comp_focusInEvent(self, event: QFocusEvent) -> None: + handler(event) + return True + + ################################# + # Event Handlers: OperationItem # + ################################# + def operation_focusInEvent(self, event: QFocusEvent) -> None: ... - def comp_contextMenuEvent( + def operation_contextMenuEvent( self, event: QGraphicsSceneContextMenuEvent ) -> None: ... - def comp_dragEnterEvent(self, event: QGraphicsSceneDragDropEvent) -> None: + def operation_dragEnterEvent( + self, event: QGraphicsSceneDragDropEvent + ) -> None: ... - def comp_dragMoveEvent(self, event: QGraphicsSceneDragDropEvent) -> None: + def operation_dragMoveEvent( + self, event: QGraphicsSceneDragDropEvent + ) -> None: ... - def comp_dragLeaveEvent(self, event: QGraphicsSceneDragDropEvent) -> None: + def operation_dragLeaveEvent( + self, event: QGraphicsSceneDragDropEvent + ) -> None: ... - def comp_dropEvent(self, event: QGraphicsSceneDragDropEvent) -> None: + def operation_dropEvent(self, event: QGraphicsSceneDragDropEvent) -> None: ... - def comp_hoverEnterEvent(self, event: QGraphicsSceneHoverEvent) -> None: + def operation_hoverEnterEvent( + self, event: QGraphicsSceneHoverEvent + ) -> None: ... - def comp_hoverMoveEvent(self, event: QGraphicsSceneHoverEvent) -> None: + def operation_hoverMoveEvent( + self, event: QGraphicsSceneHoverEvent + ) -> None: ... - def comp_hoverLeaveEvent(self, event: QGraphicsSceneHoverEvent) -> None: + def operation_hoverLeaveEvent( + self, event: QGraphicsSceneHoverEvent + ) -> None: ... - def comp_mouseMoveEvent(self, event: QGraphicsSceneMouseEvent) -> None: + def operation_mouseMoveEvent( + self, event: QGraphicsSceneMouseEvent + ) -> None: """ Set the position of the graphical element in the graphic scene, translate coordinates of the cursor within the graphic element in the - coordinate system of the parent object. The object can only move - horizontally in x-axis scale steps. + coordinate system of the parent object. """ - def update_pos(item, dx, dy): - posx = item.x() + dx - posy = item.y() + dy * (OPERATION_GAP + OPERATION_HEIGHT) - if self.is_component_valid_pos(item, posx): - item.setX(posx) - item.setY(posy) + def update_pos(operation_item, dx, dy): + pos_x = operation_item.x() + dx + pos_y = operation_item.y() + dy * ( + OPERATION_GAP + OPERATION_HEIGHT + ) + if self.is_component_valid_pos(operation_item, pos_x): + operation_item.setX(pos_x) + operation_item.setY(pos_y) self._current_pos.setX(self._current_pos.x() + dx) self._current_pos.setY(self._current_pos.y() + dy) - self._redraw_lines(item) - self._schedule._y_locations[item.operation.graph_id] += dy + self._redraw_lines(operation_item) + self._schedule._y_locations[ + operation_item.operation.graph_id + ] += dy item: OperationItem = self.scene().mouseGrabberItem() delta_x = (item.mapToParent(event.pos()) - self._current_pos).x() @@ -227,7 +235,9 @@ class SchedulerEvent: # PyQt5 elif delta_y_steps != 0: update_pos(item, 0, delta_y_steps) - def comp_mousePressEvent(self, event: QGraphicsSceneMouseEvent) -> None: + def operation_mousePressEvent( + self, event: QGraphicsSceneMouseEvent + ) -> None: """ Changes the cursor to ClosedHandCursor when grabbing an object and stores the current position in item's parent coordinates. *event* will @@ -240,34 +250,36 @@ class SchedulerEvent: # PyQt5 self.set_item_active(item) event.accept() - def comp_mouseReleaseEvent(self, event: QGraphicsSceneMouseEvent) -> None: + def operation_mouseReleaseEvent( + self, event: QGraphicsSceneMouseEvent + ) -> None: """Change the cursor to OpenHandCursor when releasing an object.""" item: OperationItem = self.scene().mouseGrabberItem() self.set_item_inactive(item) self.set_new_starttime(item) - posx = item.x() + pos_x = item.x() redraw = False - if posx < 0: - posx += self._schedule.schedule_time + if pos_x < 0: + pos_x += self._schedule.schedule_time redraw = True - if posx > self._schedule.schedule_time: - posx = posx % self._schedule.schedule_time + if pos_x > self._schedule.schedule_time: + pos_x = pos_x % self._schedule.schedule_time redraw = True if redraw: - item.setX(posx) + item.setX(pos_x) self._redraw_lines(item) - def comp_mouseDoubleClickEvent( + def operation_mouseDoubleClickEvent( self, event: QGraphicsSceneMouseEvent ) -> None: ... - def comp_wheelEvent(self, event: QGraphicsSceneWheelEvent) -> None: + def operation_wheelEvent(self, event: QGraphicsSceneWheelEvent) -> None: ... - ############################################### - #### Event Handlers: GraphicsLineTem #### - ############################################### + ################################### + # Event Handlers: GraphicsLineTem # + ################################### def timeline_mouseMoveEvent(self, event: QGraphicsSceneMouseEvent) -> None: """ Set the position of the graphical element in the graphic scene, @@ -276,13 +288,13 @@ class SchedulerEvent: # PyQt5 horizontally in x-axis scale steps. """ - def update_pos(item, dx): - pos = item.x() + dx + def update_pos(timeline_item, dx): + pos = timeline_item.x() + dx if self.is_valid_delta_time(self._delta_time + dx): - item.setX(pos) + timeline_item.setX(pos) self._current_pos.setX(self._current_pos.x() + dx) self._delta_time += dx - item.set_text(self._delta_time) + timeline_item.set_text(self._delta_time) item: TimelineItem = self.scene().mouseGrabberItem() delta_x = (item.mapToParent(event.pos()) - self._current_pos).x() diff --git a/b_asic/scheduler_gui/scheduler_item.py b/b_asic/scheduler_gui/scheduler_item.py index c0b80a77b9bbb8aab76ac85f9b0aa94716fee93e..ddea53005c8a39e6ce789cb7a3c18ce1c7e0c0a9 100644 --- a/b_asic/scheduler_gui/scheduler_item.py +++ b/b_asic/scheduler_gui/scheduler_item.py @@ -56,7 +56,8 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5 def __init__( self, schedule: Schedule, parent: Optional[QGraphicsItem] = None ): - """Constructs a SchedulerItem. *parent* is passed to QGraphicsItemGroup's constructor. + """ + Construct a SchedulerItem. *parent* is passed to QGraphicsItemGroup's constructor. """ # QGraphicsItemGroup.__init__(self, self) # SchedulerEvent.__init__(self) @@ -75,7 +76,7 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5 def clear(self) -> None: """ - Sets all children's parent to 'None' and delete the children objects. + Set all children's parent to 'None' and delete the children objects. """ self._event_items = [] for item in self.childItems(): @@ -84,8 +85,8 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5 def is_component_valid_pos(self, item: OperationItem, pos: float) -> bool: """ - Takes in a component position and returns true if the component's new - position is valid, false otherwise. + Take in a component position and return True if the component's new + position is valid, False otherwise. Parameters ========== @@ -161,8 +162,8 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5 for signal in self._signal_dict[item]: signal.set_inactive() - def set_new_starttime(self, item: OperationItem) -> None: - """Set new starttime for *item*.""" + def set_new_start_time(self, item: OperationItem) -> None: + """Set new start time for *item*.""" pos = item.x() op_start_time = self.schedule.start_time_of_operation(item.graph_id) new_start_time = floor(pos) - floor(self._x_axis_indent) @@ -232,25 +233,25 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5 self._set_position(graph_id) self._redraw_all_lines() - def _update_axes(self, build=False): + def _update_axes(self, build=False) -> None: # build axes schedule_time = self.schedule.schedule_time max_pos_graph_id = max( self.schedule._y_locations, key=self.schedule._y_locations.get ) - yposmin = self.schedule._get_y_position( + y_pos_min = self.schedule._get_y_position( max_pos_graph_id, OPERATION_HEIGHT, OPERATION_GAP ) if self._axes is None or build: - self._axes = AxesItem(schedule_time, yposmin + 0.5) + self._axes = AxesItem(schedule_time, y_pos_min + 0.5) self._event_items += self._axes.event_items else: - self._axes.set_height(yposmin + 0.5) - self._axes.setPos(0, yposmin + OPERATION_HEIGHT + OPERATION_GAP) + self._axes.set_height(y_pos_min + 0.5) + self._axes.setPos(0, y_pos_min + OPERATION_HEIGHT + OPERATION_GAP) def _make_graph(self) -> None: - """Makes a new graph out of the stored attributes.""" + """Make a new graph out of the stored attributes.""" # build components for graph_id in self.schedule.start_times.keys(): operation = cast(Operation, self.schedule.sfg.find_by_id(graph_id)) @@ -274,15 +275,15 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5 for output_port in component.operation.outputs: for signal in output_port.signals: destination = cast(InputPort, signal.destination) - dest_component = self._operation_items[ + destination_component = self._operation_items[ destination.operation.graph_id ] gui_signal = SignalItem( - component, dest_component, signal, parent=self + component, destination_component, signal, parent=self ) self.addToGroup(gui_signal) self._signal_dict[component].add(gui_signal) - self._signal_dict[dest_component].add(gui_signal) + self._signal_dict[destination_component].add(gui_signal) pprint(SchedulerItem.__mro__) diff --git a/b_asic/scheduler_gui/signal_item.py b/b_asic/scheduler_gui/signal_item.py index 4529c475c6165fe90a5985b3142e7d93560f59b1..83bf9a47306be25d7ae9ec96eddea29dc5a90d25 100644 --- a/b_asic/scheduler_gui/signal_item.py +++ b/b_asic/scheduler_gui/signal_item.py @@ -54,7 +54,7 @@ class SignalItem(QGraphicsPathItem): self.set_inactive() self.update_path() - def update_path(self): + def update_path(self) -> None: """ Create a new path after moving connected operations. """ @@ -93,7 +93,7 @@ class SignalItem(QGraphicsPathItem): path.cubicTo(ctrl_point1, ctrl_point2, dest_point) self.setPath(path) - def refresh_pens(self): + def refresh_pens(self) -> None: """Create pens.""" pen = QPen(SIGNAL_ACTIVE) pen.setWidthF(SIGNAL_WIDTH) @@ -102,11 +102,12 @@ class SignalItem(QGraphicsPathItem): pen.setWidthF(SIGNAL_WIDTH) self._inactive_pen = pen - def set_active(self): - """Set the signal color to represent that a connected operation is selected. + def set_active(self) -> None: + """ + Set the signal color to represent that a connected operation is selected. """ self.setPen(self._active_pen) - def set_inactive(self): + def set_inactive(self) -> None: """Set the signal color to the default color.""" self.setPen(self._inactive_pen) diff --git a/b_asic/signal.py b/b_asic/signal.py index 3b6b42160cfda1927fdaa5b015b38703ac062bf5..e8aacbfc4a68ee9db22026e1b3ae2cdf302a2c1e 100644 --- a/b_asic/signal.py +++ b/b_asic/signal.py @@ -21,6 +21,10 @@ class Signal(AbstractGraphComponent): """ A connection between two ports. + .. note:: If a Signal is provided as *source* or *destination*, the + connected port is used. Hence, if the argument signal is later + changed, it will not affect the current Signal. + Parameters ========== @@ -33,10 +37,6 @@ class Signal(AbstractGraphComponent): name : Name, default: "" The signal name. - .. note:: If a Signal is provided as *source* or *destination*, the - connected port is used. Hence, if the argument signal is later - changed, it will not affect the current Signal. - See also ======== set_source, set_destination