From fa15c7a435b196f15a956ddb82b2ff930d2a24b3 Mon Sep 17 00:00:00 2001
From: Oscar Gustafsson <oscar.gustafsson@gmail.com>
Date: Mon, 20 Feb 2023 11:00:50 +0100
Subject: [PATCH] Fix documentation for scheduler GUI

---
 b_asic/scheduler_gui/axes_item.py       | 54 ++++++---------
 b_asic/scheduler_gui/compile.py         | 59 ++++++++++++----
 b_asic/scheduler_gui/logger.py          |  7 +-
 b_asic/scheduler_gui/main_window.py     | 91 +++++++++----------------
 b_asic/scheduler_gui/operation_item.py  | 41 +++++------
 b_asic/scheduler_gui/scheduler_event.py | 76 ++++++---------------
 b_asic/scheduler_gui/scheduler_item.py  | 34 ++++-----
 b_asic/scheduler_gui/signal_item.py     | 17 +++--
 b_asic/scheduler_gui/timeline_item.py   | 10 ++-
 9 files changed, 173 insertions(+), 216 deletions(-)

diff --git a/b_asic/scheduler_gui/axes_item.py b/b_asic/scheduler_gui/axes_item.py
index 9d5216cf..d11b7a7c 100644
--- a/b_asic/scheduler_gui/axes_item.py
+++ b/b_asic/scheduler_gui/axes_item.py
@@ -1,8 +1,9 @@
 #!/usr/bin/env python3
 # -*- coding: utf-8 -*-
-"""B-ASIC Scheduler-gui Graphics Axes Item Module.
+"""
+B-ASIC Scheduler-gui Axes Item Module.
 
-Contains the scheduler-gui AxesItem class for drawing and maintain the
+Contains the scheduler-gui AxesItem class for drawing and maintaining the
 axes in a graph.
 """
 from math import pi, sin
@@ -25,18 +26,19 @@ from b_asic.scheduler_gui.timeline_item import TimelineItem
 
 
 class AxesItem(QGraphicsItemGroup):
-    """
+    f"""
     A class to represent axes in a graph.
 
     Parameters
     ----------
     width
     height
-    width_indent
-    height_indent
-    width_padding
-    height_padding
-    parent
+    width_indent : float, default: {SCHEDULE_INDENT}
+    height_indent : float, default: {SCHEDULE_INDENT}
+    width_padding : float, default: 0.6
+    height_padding : float, default: 0.5
+    parent : QGraphicsItem, optional
+        Passed to QGraphicsItemGroup.
     """
 
     _scale: float = 1.0
@@ -72,17 +74,14 @@ class AxesItem(QGraphicsItemGroup):
     ):
         """
         Class for an AxesItem.
+
         *parent* is passed to QGraphicsItemGroup's constructor.
         """
         super().__init__(parent=parent)
         if width < 0:
-            raise ValueError(
-                f"'width' greater or equal to 0 expected, got: {width}."
-            )
+            raise ValueError(f"'width' greater or equal to 0 expected, got: {width}.")
         if height < 0:
-            raise ValueError(
-                f"'height' greater or equal to 0 expected, got: {height}."
-            )
+            raise ValueError(f"'height' greater or equal to 0 expected, got: {height}.")
 
         self._width = width
         self._height = height
@@ -170,18 +169,14 @@ class AxesItem(QGraphicsItemGroup):
     def set_height(self, height: float) -> None:
         # TODO: docstring
         if height < 0:
-            raise ValueError(
-                f"'height' greater or equal to 0 expected, got: {height}."
-            )
+            raise ValueError(f"'height' greater or equal to 0 expected, got: {height}.")
         self._height = height
         self._update_yaxis()
 
     def set_width(self, width: int) -> None:
         # TODO: docstring
         if width < 0:
-            raise ValueError(
-                f"'width' greater or equal to 0 expected, got: {width}."
-            )
+            raise ValueError(f"'width' greater or equal to 0 expected, got: {width}.")
 
         delta_width = width - self._width
 
@@ -293,12 +288,7 @@ class AxesItem(QGraphicsItemGroup):
             0,
             0,
             0,
-            -(
-                self._height_indent
-                + self._height
-                + self._height_padding
-                + 0.05
-            ),
+            -(self._height_indent + self._height + self._height_padding + 0.05),
         )
         self._y_axis.setPen(self._base_pen)
 
@@ -325,15 +315,11 @@ class AxesItem(QGraphicsItemGroup):
         self._x_label.setScale(1 / self._scale)
         x_pos = self._width_indent + 0 + self._width_padding  # end of x-axis
         x_pos += (
-            self.mapRectFromItem(
-                self._x_arrow, self._x_arrow.boundingRect()
-            ).width()
+            self.mapRectFromItem(self._x_arrow, self._x_arrow.boundingRect()).width()
             / 2
         )  # + half arrow width
         x_pos -= (
-            self.mapRectFromItem(
-                self._x_label, self._x_label.boundingRect()
-            ).width()
+            self.mapRectFromItem(self._x_label, self._x_label.boundingRect()).width()
             / 2
         )  # - center of label
         self._x_label.setPos(x_pos, self._x_label_offset)
@@ -344,9 +330,7 @@ class AxesItem(QGraphicsItemGroup):
         for _ in range(self._width):
             self._append_x_tick()
         pos = self._x_ledger[-1].pos()
-        self._x_ledger[-1].setPos(
-            pos + QPointF(self._width, 0)
-        )  # move timeline
+        self._x_ledger[-1].setPos(pos + QPointF(self._width, 0))  # move timeline
 
         # y-axis
         self._update_yaxis()
diff --git a/b_asic/scheduler_gui/compile.py b/b_asic/scheduler_gui/compile.py
index 227828aa..388c884c 100644
--- a/b_asic/scheduler_gui/compile.py
+++ b/b_asic/scheduler_gui/compile.py
@@ -12,6 +12,7 @@ import os
 import shutil
 import subprocess
 import sys
+from pathlib import Path
 
 from qtpy import uic
 from setuptools_scm import get_version
@@ -31,31 +32,34 @@ def _check_filenames(*filenames: str) -> None:
     exception.
     """
     for filename in filenames:
-        if not os.path.exists(filename):
-            raise FileNotFoundError(filename)
+        Path(filename).resolve(strict=True)
 
 
 def _check_qt_version() -> None:
     """
-    Check if PySide2 or PyQt5 is installed, otherwise raise AssertionError
+    Check if PySide2, PyQt5, PySide6, or PyQt6 is installed, otherwise raise AssertionError
     exception.
     """
-    assert uic.PYSIDE2 or uic.PYQT5, "PySide2 or PyQt5 need to be installed"
+    assert (
+        uic.PYSIDE2 or uic.PYQT5 or uic.PYSIDE6 or uic.PYQT6
+    ), "Python QT bindings must be installed"
 
 
 def replace_qt_bindings(filename: str) -> None:
-    """Raplaces qt-binding api in 'filename' from PySide2/PyQt5 to qtpy."""
+    """Raplaces qt-binding api in *filename* from PySide2/6 or PyQt5/6 to qtpy."""
     with open(f"{filename}", "r") as file:
         filedata = file.read()
         filedata = filedata.replace("from PyQt5", "from qtpy")
         filedata = filedata.replace("from PySide2", "from qtpy")
+        filedata = filedata.replace("from PyQt6", "from qtpy")
+        filedata = filedata.replace("from PySide6", "from qtpy")
     with open(f"{filename}", "w") as file:
         file.write(filedata)
 
 
 def compile_rc(*filenames: str) -> None:
     """
-    Compile resource file(s) given by 'filenames'. If no arguments are given,
+    Compile resource file(s) given by *filenames*. If no arguments are given,
     the compiler will search for resource (.qrc) files and compile accordingly.
     """
     _check_qt_version()
@@ -70,10 +74,9 @@ def compile_rc(*filenames: str) -> None:
         if rcc is None:
             rcc = shutil.which("pyrcc5")
             arguments = f"-o {outfile} {filename}"
-        assert rcc, (
-            "Qt Resource compiler failed, cannot find pyside2-rcc, rcc, or"
-            " pyrcc5"
-        )
+        assert (
+            rcc
+        ), "Qt Resource compiler failed, cannot find pyside2-rcc, rcc, or pyrcc5"
 
         os_ = sys.platform
         if os_.startswith("linux"):  # Linux
@@ -124,7 +127,7 @@ def compile_rc(*filenames: str) -> None:
 
 def compile_ui(*filenames: str) -> None:
     """
-    Compile form file(s) given by 'filenames'. If no arguments are given, the
+    Compile form file(s) given by *filenames*. If no arguments are given, the
     compiler will search for form (.ui) files and compile accordingly.
     """
     _check_qt_version()
@@ -168,11 +171,43 @@ def compile_ui(*filenames: str) -> None:
                 log.error(f"{os_} UI compiler not supported")
                 raise NotImplementedError
 
-        else:  # uic.PYQT5
+        elif uic.PYQT5 or uic.PYQT6:
             from qtpy.uic import compileUi
 
             with open(outfile, "w") as ofile:
                 compileUi(filename, ofile)
+        elif uic.PYQT6:
+            uic_ = shutil.which("pyside6-uic")
+            arguments = f"-g python -o {outfile} {filename}"
+
+            if uic_ is None:
+                uic_ = shutil.which("uic")
+            if uic_ is None:
+                uic_ = shutil.which("pyuic6")
+                arguments = f"-o {outfile} {filename}"
+            assert uic_, (
+                "Qt User Interface Compiler failed, cannot find pyside6-uic,"
+                " uic, or pyuic6"
+            )
+
+            os_ = sys.platform
+            if os_.startswith("linux"):  # Linux
+                cmd = f"{uic_} {arguments}"
+                subprocess.call(cmd.split())
+
+            elif os_.startswith("win32"):  # Windows
+                # TODO: implement
+                log.error("Windows UI compiler not implemented")
+                raise NotImplementedError
+
+            elif os_.startswith("darwin"):  # macOS
+                # TODO: implement
+                log.error("macOS UI compiler not implemented")
+                raise NotImplementedError
+
+            else:  # other OS
+                log.error(f"{os_} UI compiler not supported")
+                raise NotImplementedError
 
         replace_qt_bindings(outfile)  # replace qt-bindings with qtpy
 
diff --git a/b_asic/scheduler_gui/logger.py b/b_asic/scheduler_gui/logger.py
index 1746ae6c..b0038589 100644
--- a/b_asic/scheduler_gui/logger.py
+++ b/b_asic/scheduler_gui/logger.py
@@ -1,6 +1,7 @@
 #!/usr/bin/env python3
 # -*- coding: utf-8 -*-
-"""B-ASIC Scheduler-gui Logger Module.
+"""
+B-ASIC Scheduler-gui Logger Module.
 
 Contains a logger that logs to the console and a file using levels. It is based
 on the :mod:`logging` module and has predefined levels of logging.
@@ -55,9 +56,7 @@ from types import TracebackType
 from typing import Type, Union
 
 
-def getLogger(
-    filename: str = "scheduler-gui.log", loglevel: str = "INFO"
-) -> Logger:
+def getLogger(filename: str = "scheduler-gui.log", loglevel: str = "INFO") -> Logger:
     """
     This function creates console- and filehandler and from those, creates a logger
     object.
diff --git a/b_asic/scheduler_gui/main_window.py b/b_asic/scheduler_gui/main_window.py
index 97a70d96..8d56996e 100644
--- a/b_asic/scheduler_gui/main_window.py
+++ b/b_asic/scheduler_gui/main_window.py
@@ -1,11 +1,11 @@
 #!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 """
-B-ASIC Scheduler-gui Module.
+B-ASIC Scheduler-GUI Module.
 
-Contains the scheduler-gui MainWindow class for scheduling operations in an SFG.
+Contains the scheduler_gui MainWindow class for scheduling operations in an SFG.
 
-Start main-window with start_gui().
+Start main-window with ``start_gui()``.
 """
 import inspect
 import os
@@ -104,7 +104,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
     _zoom: float
 
     def __init__(self):
-        """Initialize Scheduler-gui."""
+        """Initialize Scheduler-GUI."""
         super().__init__()
         self._schedule = None
         self._graph = None
@@ -121,9 +121,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
         """Initialize the ui"""
 
         # Connect signals to slots
-        self.menu_load_from_file.triggered.connect(
-            self._load_schedule_from_pyfile
-        )
+        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)
@@ -153,9 +151,7 @@ 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._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)
         OperationItem._scale = self._scale
@@ -182,12 +178,12 @@ class MainWindow(QMainWindow, Ui_MainWindow):
 
     @Slot()
     def _open_documentation(self) -> None:
+        """Callback to open documentation web page."""
         webbrowser.open_new_tab("https://da.gitlab-pages.liu.se/B-ASIC/")
 
     @Slot()
     def _actionReorder(self) -> None:
-        """Callback to reorder all operations vertically based on start time.
-        """
+        """Callback to reorder all operations vertically based on start time."""
         if self.schedule is None:
             return
         if self._graph is not None:
@@ -228,25 +224,17 @@ class MainWindow(QMainWindow, Ui_MainWindow):
             self.tr("Python Files (*.py *.py3)"),
         )
 
-        if (
-            not abs_path_filename
-        ):  # return if empty filename (QFileDialog was canceled)
+        if not abs_path_filename:  # return if empty filename (QFileDialog was canceled)
             return
         log.debug("abs_path_filename = {}.".format(abs_path_filename))
 
         module_name = inspect.getmodulename(abs_path_filename)
         if not module_name:  # return if empty module name
-            log.error(
-                "Could not load module from file '{}'.".format(
-                    abs_path_filename
-                )
-            )
+            log.error("Could not load module from file '{}'.".format(abs_path_filename))
             return
 
         try:
-            module = SourceFileLoader(
-                module_name, abs_path_filename
-            ).load_module()
+            module = SourceFileLoader(module_name, abs_path_filename).load_module()
         except Exception as e:
             log.exception(
                 "Exception occurred. Could not load module from file"
@@ -262,9 +250,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
             QMessageBox.warning(
                 self,
                 self.tr("File not found"),
-                self.tr(
-                    "Cannot find any Schedule object in file '{}'."
-                ).format(os.path.basename(abs_path_filename)),
+                self.tr("Cannot find any Schedule object in file '{}'.").format(
+                    os.path.basename(abs_path_filename)
+                ),
             )
             log.info(
                 "Cannot find any Schedule object in file '{}'.".format(
@@ -302,8 +290,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
     @Slot()
     def close_schedule(self) -> None:
         """
+        Close current schedule.
+
         SLOT() for SIGNAL(menu_close_schedule.triggered)
-        Closes current schedule.
         """
         if self._graph:
             self._graph._signals.component_selected.disconnect(
@@ -324,8 +313,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
     @Slot()
     def save(self) -> None:
         """
+        Save current schedule.
+
         SLOT() for SIGNAL(menu_save.triggered)
-        This method save a schedule.
         """
         # TODO: all
         self._print_button_pressed("save_schedule()")
@@ -334,19 +324,22 @@ class MainWindow(QMainWindow, Ui_MainWindow):
     @Slot()
     def save_as(self) -> None:
         """
+        Save current schedule asking for file name.
+
         SLOT() for SIGNAL(menu_save_as.triggered)
-        This method save as a schedule.
         """
-        # TODO: all
+        # TODO: Implement
         self._print_button_pressed("save_schedule()")
         self.update_statusbar(self.tr("Schedule saved successfully"))
 
     @Slot(bool)
     def show_info_table(self, checked: bool) -> None:
         """
+        Show or hide the info table.
+
         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
@@ -406,9 +399,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
         Updates the 'Schedule' part of the info table.
         """
         if self.schedule is not None:
-            self.info_table.item(1, 1).setText(
-                str(self.schedule.schedule_time)
-            )
+            self.info_table.item(1, 1).setText(str(self.schedule.schedule_time))
 
     @Slot(QRectF)
     def shrink_scene_to_min_size(self, rect: QRectF) -> None:
@@ -454,9 +445,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
 
         if ret == QMessageBox.StandardButton.Yes:
             if not hide_dialog:
-                settings.setValue(
-                    "scheduler/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()
@@ -489,9 +478,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
         self._graph._signals.component_selected.connect(
             self.info_table_update_component
         )
-        self._graph._signals.component_moved.connect(
-            self.info_table_update_component
-        )
+        self._graph._signals.component_moved.connect(self.info_table_update_component)
         self._graph._signals.schedule_time_changed.connect(
             self.info_table_update_schedule
         )
@@ -520,12 +507,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
         settings.setValue(
             "scheduler/state", self.saveState()
         )  # toolbars, dockwidgets: pos, size
-        settings.setValue(
-            "scheduler/menu/node_info", self.menu_node_info.isChecked()
-        )
-        settings.setValue(
-            "scheduler/splitter/state", self.splitter.saveState()
-        )
+        settings.setValue("scheduler/menu/node_info", self.menu_node_info.isChecked())
+        settings.setValue("scheduler/splitter/state", self.splitter.saveState())
         settings.setValue("scheduler/splitter/pos", self.splitter.sizes()[1])
 
         if settings.isWritable():
@@ -536,9 +519,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
     def _read_settings(self) -> None:
         """Read settings from Settings to MainWindow."""
         settings = QSettings()
-        if settings.value(
-            "scheduler/maximized", defaultValue=False, type=bool
-        ):
+        if settings.value("scheduler/maximized", defaultValue=False, type=bool):
             self.showMaximized()
         else:
             self.move(settings.value("scheduler/pos", self.pos()))
@@ -566,9 +547,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
         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(
-            1, 1, QTableWidgetItem(str(schedule.schedule_time))
-        )
+        self.info_table.setItem(1, 1, QTableWidgetItem(str(schedule.schedule_time)))
         self.info_table.setItem(2, 1, QTableWidgetItem(str(schedule.cyclic)))
 
     def _info_table_fill_component(self, graph_id: GraphID) -> None:
@@ -630,9 +609,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
                 for _ in range(3):
                     self.info_table.removeRow(1)
         else:
-            log.error(
-                "'Operator' not found in info table. It may have been renamed."
-            )
+            log.error("'Operator' not found in info table. It may have been renamed.")
 
     def exit_app(self) -> None:
         """Exit application."""
@@ -647,9 +624,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
             for _ in range(self.info_table.rowCount() - row + 1):
                 self.info_table.removeRow(row + 1)
         else:
-            log.error(
-                "'Operator' not found in info table. It may have been renamed."
-            )
+            log.error("'Operator' not found in info table. It may have been renamed.")
 
 
 def start_gui() -> None:
diff --git a/b_asic/scheduler_gui/operation_item.py b/b_asic/scheduler_gui/operation_item.py
index eb3b331d..244723ba 100644
--- a/b_asic/scheduler_gui/operation_item.py
+++ b/b_asic/scheduler_gui/operation_item.py
@@ -1,10 +1,10 @@
 #!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 """
-B-ASIC Scheduler-gui Graphics Component Item Module.
+B-ASIC Scheduler-GUI Operation Item Module.
 
-Contains the scheduler-gui OperationItem class for drawing and maintain a component
-in a graph.
+Contains the scheduler_gui OperationItem class for drawing and maintain an operation
+in the schedule.
 """
 from typing import TYPE_CHECKING, Dict, List, Union, cast
 
@@ -34,23 +34,24 @@ if TYPE_CHECKING:
 
 
 class OperationItem(QGraphicsItemGroup):
-    """
+    f"""
     Class to represent an operation in a graph.
 
     Parameters
     ----------
     operation : :class:`~b_asic.operation.Operation`
+        The operation.
     parent : :class:`~b_asic.scheduler_gui.scheduler_item.SchedulerItem`
-    height : float, default: 1.0
+        Parent passed to QGraphicsItemGroup
+    height : float, default: {OPERATION_HEIGHT}
+        The height of the operation.
     """
 
     _scale: float = 1.0
     """Static, changed from MainWindow."""
     _operation: Operation
     _height: float
-    _ports: Dict[
-        str, Dict[str, Union[float, QPointF]]
-    ]  # ['port-id']['latency/pos']
+    _ports: Dict[str, Dict[str, Union[float, QPointF]]]  # ['port-id']['latency/pos']
     _end_time: int
     _latency_item: QGraphicsPathItem
     _execution_time_item: QGraphicsPathItem
@@ -72,9 +73,7 @@ class OperationItem(QGraphicsItemGroup):
         self._height = height
         operation._check_all_latencies_set()
         latency_offsets = cast(Dict[str, int], operation.latency_offsets)
-        self._ports = {
-            k: {"latency": float(v)} for k, v in latency_offsets.items()
-        }
+        self._ports = {k: {"latency": float(v)} for k, v in latency_offsets.items()}
         self._end_time = max(latency_offsets.values())
         self._port_items = []
 
@@ -122,6 +121,14 @@ class OperationItem(QGraphicsItemGroup):
 
     @height.setter
     def height(self, height: float) -> None:
+        """
+        Set height.
+
+        Parameters
+        ----------
+        height : float
+            The new height.
+        """
         if self._height != height:
             self.clear()
             self._height = height
@@ -168,9 +175,7 @@ class OperationItem(QGraphicsItemGroup):
 
     def _make_component(self) -> None:
         """Makes a new component out of the stored attributes."""
-        latency_outline_pen = QPen(
-            Qt.GlobalColor.black
-        )  # used by component outline
+        latency_outline_pen = QPen(Qt.GlobalColor.black)  # used by component outline
         latency_outline_pen.setWidthF(2 / self._scale)
         # latency_outline_pen.setCapStyle(Qt.RoundCap)
         # Qt.FlatCap, Qt.SquareCap (default), Qt.RoundCap
@@ -178,9 +183,7 @@ class OperationItem(QGraphicsItemGroup):
             Qt.RoundJoin
         )  # Qt.MiterJoin, Qt.BevelJoin (default), Qt.RoundJoin, Qt.SvgMiterJoin
 
-        port_filling_brush = QBrush(
-            Qt.GlobalColor.black
-        )  # used by port filling
+        port_filling_brush = QBrush(Qt.GlobalColor.black)  # used by port filling
         port_outline_pen = QPen(Qt.GlobalColor.black)  # used by port outline
         port_outline_pen.setWidthF(0)
         # port_outline_pen.setCosmetic(True)
@@ -214,9 +217,7 @@ class OperationItem(QGraphicsItemGroup):
             self._execution_time_item.setPen(execution_time_pen)
 
         # component item
-        self._set_background(
-            OPERATION_LATENCY_INACTIVE
-        )  # used by component filling
+        self._set_background(OPERATION_LATENCY_INACTIVE)  # used by component filling
 
         inputs, outputs = self._operation.get_io_coordinates()
 
diff --git a/b_asic/scheduler_gui/scheduler_event.py b/b_asic/scheduler_gui/scheduler_event.py
index 36b99f5f..b1b9c75c 100644
--- a/b_asic/scheduler_gui/scheduler_event.py
+++ b/b_asic/scheduler_gui/scheduler_event.py
@@ -1,9 +1,9 @@
 #!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 """
-B-ASIC Scheduler-gui Graphics Graph Event Module.
+B-ASIC Scheduler-GUI Graphics Scheduler Event Module.
 
-Contains the scheduler-gui SchedulerEvent class containing event filters and
+Contains the scheduler_ui SchedulerEvent class containing event filters and
 handlers for SchedulerItem objects.
 """
 
@@ -61,7 +61,7 @@ class SchedulerEvent:  # PyQt5
     def is_valid_delta_time(self, delta_time: int) -> bool:
         raise NotImplementedError
 
-    def set_schedule_time(self, delta_time: int) -> None:
+    def change_schedule_time(self, delta_time: int) -> None:
         raise NotImplementedError
 
     def set_item_active(self, item: OperationItem) -> None:
@@ -78,9 +78,7 @@ class SchedulerEvent:  # PyQt5
         ...
 
     @overload
-    def installSceneEventFilters(
-        self, filterItems: List[QGraphicsItem]
-    ) -> None:
+    def installSceneEventFilters(self, filterItems: List[QGraphicsItem]) -> None:
         ...
 
     def installSceneEventFilters(self, filterItems) -> None:
@@ -98,9 +96,7 @@ class SchedulerEvent:  # PyQt5
         ...
 
     @overload
-    def removeSceneEventFilters(
-        self, filterItems: List[QGraphicsItem]
-    ) -> None:
+    def removeSceneEventFilters(self, filterItems: List[QGraphicsItem]) -> None:
         ...
 
     def removeSceneEventFilters(self, filterItems) -> None:
@@ -166,47 +162,31 @@ class SchedulerEvent:  # PyQt5
     def operation_focusInEvent(self, event: QFocusEvent) -> None:
         ...
 
-    def operation_contextMenuEvent(
-        self, event: QGraphicsSceneContextMenuEvent
-    ) -> None:
+    def operation_contextMenuEvent(self, event: QGraphicsSceneContextMenuEvent) -> None:
         ...
 
-    def operation_dragEnterEvent(
-        self, event: QGraphicsSceneDragDropEvent
-    ) -> None:
+    def operation_dragEnterEvent(self, event: QGraphicsSceneDragDropEvent) -> None:
         ...
 
-    def operation_dragMoveEvent(
-        self, event: QGraphicsSceneDragDropEvent
-    ) -> None:
+    def operation_dragMoveEvent(self, event: QGraphicsSceneDragDropEvent) -> None:
         ...
 
-    def operation_dragLeaveEvent(
-        self, event: QGraphicsSceneDragDropEvent
-    ) -> None:
+    def operation_dragLeaveEvent(self, event: QGraphicsSceneDragDropEvent) -> None:
         ...
 
     def operation_dropEvent(self, event: QGraphicsSceneDragDropEvent) -> None:
         ...
 
-    def operation_hoverEnterEvent(
-        self, event: QGraphicsSceneHoverEvent
-    ) -> None:
+    def operation_hoverEnterEvent(self, event: QGraphicsSceneHoverEvent) -> None:
         ...
 
-    def operation_hoverMoveEvent(
-        self, event: QGraphicsSceneHoverEvent
-    ) -> None:
+    def operation_hoverMoveEvent(self, event: QGraphicsSceneHoverEvent) -> None:
         ...
 
-    def operation_hoverLeaveEvent(
-        self, event: QGraphicsSceneHoverEvent
-    ) -> None:
+    def operation_hoverLeaveEvent(self, event: QGraphicsSceneHoverEvent) -> None:
         ...
 
-    def operation_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
@@ -215,18 +195,14 @@ class SchedulerEvent:  # PyQt5
 
         def update_pos(operation_item, dx, dy):
             pos_x = operation_item.x() + dx
-            pos_y = operation_item.y() + dy * (
-                OPERATION_GAP + OPERATION_HEIGHT
-            )
+            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(operation_item)
-                self._schedule._y_locations[
-                    operation_item.operation.graph_id
-                ] += dy
+                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()
@@ -240,9 +216,7 @@ class SchedulerEvent:  # PyQt5
         elif delta_y_steps != 0:
             update_pos(item, 0, delta_y_steps)
 
-    def operation_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
@@ -255,9 +229,7 @@ class SchedulerEvent:  # PyQt5
         self.set_item_active(item)
         event.accept()
 
-    def operation_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)
@@ -275,9 +247,7 @@ class SchedulerEvent:  # PyQt5
             self._redraw_lines(item)
         self._signals.component_moved.emit(item.graph_id)
 
-    def operation_mouseDoubleClickEvent(
-        self, event: QGraphicsSceneMouseEvent
-    ) -> None:
+    def operation_mouseDoubleClickEvent(self, event: QGraphicsSceneMouseEvent) -> None:
         ...
 
     def operation_wheelEvent(self, event: QGraphicsSceneWheelEvent) -> None:
@@ -309,9 +279,7 @@ class SchedulerEvent:  # PyQt5
         elif delta_x < -0.505:
             update_pos(item, -1)
 
-    def timeline_mousePressEvent(
-        self, event: QGraphicsSceneMouseEvent
-    ) -> None:
+    def timeline_mousePressEvent(self, event: QGraphicsSceneMouseEvent) -> None:
         """
         Store the current position in item's parent coordinates. *event* will
         by default be accepted, and this item is then the mouse grabber. This
@@ -324,12 +292,10 @@ class SchedulerEvent:  # PyQt5
         self._current_pos = item.mapToParent(event.pos())
         event.accept()
 
-    def timeline_mouseReleaseEvent(
-        self, event: QGraphicsSceneMouseEvent
-    ) -> None:
+    def timeline_mouseReleaseEvent(self, event: QGraphicsSceneMouseEvent) -> None:
         """Updates the schedule time."""
         item: TimelineItem = self.scene().mouseGrabberItem()
         item.hide_label()
         if self._delta_time != 0:
-            self.set_schedule_time(self._delta_time)
+            self.change_schedule_time(self._delta_time)
             self._signals.schedule_time_changed.emit()
diff --git a/b_asic/scheduler_gui/scheduler_item.py b/b_asic/scheduler_gui/scheduler_item.py
index b59202c9..0e8a0443 100644
--- a/b_asic/scheduler_gui/scheduler_item.py
+++ b/b_asic/scheduler_gui/scheduler_item.py
@@ -1,10 +1,10 @@
 #!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 """
-B-ASIC Scheduler-gui Graphics Graph Item Module.
+B-ASIC Scheduler-GUI Scheduler Item Module.
 
-Contains the scheduler-gui SchedulerItem class for drawing and
-maintain a component in a graph.
+Contains the scheduler_gui SchedulerItem class for drawing and
+maintaining a schedule.
 """
 from collections import defaultdict
 from math import floor
@@ -31,7 +31,9 @@ from b_asic.scheduler_gui.signal_item import SignalItem
 
 class SchedulerItem(SchedulerEvent, QGraphicsItemGroup):  # PySide2 / PyQt5
     """
-    A class to represent a graph in a QGraphicsScene. This class is a
+    A class to represent a schedule in a QGraphicsScene.
+
+    This class is a
     subclass of QGraphicsItemGroup and contains the objects, axes from
     AxesItem, as well as components from OperationItem. It
     also inherits from SchedulerEvent, which acts as a filter for events
@@ -53,9 +55,7 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup):  # PySide2 / PyQt5
     _event_items: List[QGraphicsItem]
     _signal_dict: Dict[OperationItem, Set[SignalItem]]
 
-    def __init__(
-        self, schedule: Schedule, parent: Optional[QGraphicsItem] = None
-    ):
+    def __init__(self, schedule: Schedule, parent: Optional[QGraphicsItem] = None):
         """
         Construct a SchedulerItem. *parent* is passed to QGraphicsItemGroup's
         constructor.
@@ -176,27 +176,23 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup):  # PySide2 / PyQt5
 
     def is_valid_delta_time(self, delta_time: int) -> bool:
         """
-        Takes in a delta time and returns True if the schedule time can be changed by
-        *delta_time*. False otherwise.
+        Return True if the schedule time can be changed by *delta_time*.
         """
         # TODO: implement
         # item = self.scene().mouseGrabberItem()
         if self.schedule is None:
             raise ValueError("No schedule installed.")
         return (
-            self.schedule.schedule_time + delta_time
-            >= self.schedule.get_max_end_time()
+            self.schedule.schedule_time + delta_time >= self.schedule.get_max_end_time()
         )
 
-    def set_schedule_time(self, delta_time: int) -> None:
+    def change_schedule_time(self, delta_time: int) -> None:
         """Change the schedule time by *delta_time* and redraw the graph."""
         if self._axes is None:
             raise RuntimeError("No AxesItem!")
         if self.schedule is None:
             raise ValueError("No schedule installed.")
-        self.schedule.set_schedule_time(
-            self.schedule.schedule_time + delta_time
-        )
+        self.schedule.set_schedule_time(self.schedule.schedule_time + delta_time)
         self._axes.set_width(self._axes.width + delta_time)
         # Redraw all lines
         self._redraw_all_lines()
@@ -223,9 +219,7 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup):  # PySide2 / PyQt5
         op_item = self._operation_items[graph_id]
         op_item.setPos(
             self._x_axis_indent + self.schedule.start_times[graph_id],
-            self.schedule._get_y_position(
-                graph_id, OPERATION_HEIGHT, OPERATION_GAP
-            ),
+            self.schedule._get_y_position(graph_id, OPERATION_HEIGHT, OPERATION_GAP),
         )
 
     def _redraw_from_start(self) -> None:
@@ -261,9 +255,7 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup):  # PySide2 / PyQt5
         # build components
         for graph_id in self.schedule.start_times.keys():
             operation = cast(Operation, self.schedule.sfg.find_by_id(graph_id))
-            component = OperationItem(
-                operation, height=OPERATION_HEIGHT, parent=self
-            )
+            component = OperationItem(operation, height=OPERATION_HEIGHT, parent=self)
             self._operation_items[graph_id] = component
             self._set_position(graph_id)
             self._event_items += component.event_items
diff --git a/b_asic/scheduler_gui/signal_item.py b/b_asic/scheduler_gui/signal_item.py
index 8a00a331..d1d1d27a 100644
--- a/b_asic/scheduler_gui/signal_item.py
+++ b/b_asic/scheduler_gui/signal_item.py
@@ -1,3 +1,11 @@
+"""
+B-ASIC Scheduler-GUI Signal Item Module.
+
+Contains the scheduler_gui SignalItem class for drawing and maintaining a signal
+in the schedule.
+"""
+
+
 from typing import TYPE_CHECKING, Optional, cast
 
 from qtpy.QtCore import QPointF
@@ -24,14 +32,14 @@ class SignalItem(QGraphicsPathItem):
 
     Parameters
     ----------
-    src_operation : OperationItem
+    src_operation : `~b_asic.scheduler_gui.operation_item.OperationItem`
         The operation that the signal is drawn from.
-    dest_operation : OperationItem
+    dest_operation : `~b_asic.scheduler_gui.operation_item.OperationItem`
         The operation that the signal is drawn to.
-    signal : Signal
+    signal : `~b_asic.signal.Signal`
         The signal on the SFG level.
     parent : QGraphicsItem, optional
-        The parent QGraphicsItem.
+        The parent QGraphicsItem passed to QGraphicsPathItem.
     """
 
     _path: Optional[QPainterPath] = None
@@ -75,7 +83,6 @@ class SignalItem(QGraphicsPathItem):
         schedule = cast("SchedulerItem", self.parentItem()).schedule
         if dest_x - source_x <= -0.1 or schedule._laps[self._signal.graph_id]:
             offset = SCHEDULE_INDENT  # TODO: Get from parent/axes...
-            laps = schedule._laps[self._signal.graph_id]
             path.lineTo(schedule.schedule_time + offset, source_y)
             path.moveTo(0 + offset, dest_y)
             path.lineTo(dest_x, dest_y)
diff --git a/b_asic/scheduler_gui/timeline_item.py b/b_asic/scheduler_gui/timeline_item.py
index 97908ac5..96509c25 100644
--- a/b_asic/scheduler_gui/timeline_item.py
+++ b/b_asic/scheduler_gui/timeline_item.py
@@ -1,10 +1,10 @@
 #!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 """
-B-ASIC Scheduler-gui Graphics Timeline Item Module.
+B-ASIC Scheduler-GUI Timeline Item Module.
 
-Contains the scheduler-gui TimelineItem class for drawing and
-maintain the timeline in a graph.
+Contains the scheduler_gui TimelineItem class for drawing and
+maintain the timeline in a schedule.
 """
 from typing import List, Optional, overload
 
@@ -21,9 +21,7 @@ class TimelineItem(QGraphicsLineItem):
     _delta_time_label: QGraphicsTextItem
 
     @overload
-    def __init__(
-        self, line: QLineF, parent: Optional[QGraphicsItem] = None
-    ) -> None:
+    def __init__(self, line: QLineF, parent: Optional[QGraphicsItem] = None) -> None:
         """
         Constructs a TimelineItem out of 'line'. 'parent' is passed to
         QGraphicsLineItem's constructor.
-- 
GitLab