From 1183e1d4ac768b69736faf43684f62714ee0815c Mon Sep 17 00:00:00 2001
From: Oscar Gustafsson <oscar.gustafsson@gmail.com>
Date: Thu, 26 Jan 2023 17:10:54 +0100
Subject: [PATCH] Add test for properties dialog plus black style fixes

---
 b_asic/GUI/drag_button.py       |  8 ++--
 b_asic/GUI/main_window.py       |  4 +-
 b_asic/GUI/properties_window.py |  4 +-
 b_asic/operation.py             |  1 -
 b_asic/schedule.py              | 11 +++--
 b_asic/signal_flow_graph.py     | 74 ++++++++++++++++++++++-----------
 test/test_gui.py                | 41 ++++++++++++++++++
 test/test_gui/twotapfir.py      |  4 +-
 8 files changed, 108 insertions(+), 39 deletions(-)

diff --git a/b_asic/GUI/drag_button.py b/b_asic/GUI/drag_button.py
index 241e00e3..495291a3 100644
--- a/b_asic/GUI/drag_button.py
+++ b/b_asic/GUI/drag_button.py
@@ -38,7 +38,6 @@ class DragButton(QPushButton):
         self,
         name,
         operation,
-        operation_path_name,
         is_show_name,
         window,
         parent=None,
@@ -48,7 +47,6 @@ class DragButton(QPushButton):
         self.is_show_name = is_show_name
         self._window = window
         self.operation = operation
-        self.operation_path_name = operation_path_name
         self.clicked = 0
         self.pressed = False
         self._m_press = False
@@ -75,7 +73,7 @@ class DragButton(QPushButton):
         flip.triggered.connect(self._flip)
         menu.exec_(self.cursor().pos())
 
-    def show_properties_window(self, event):
+    def show_properties_window(self, event=None):
         self._properties_window = PropertiesWindow(self, self._window)
         self._properties_window.show()
 
@@ -155,7 +153,9 @@ class DragButton(QPushButton):
         path_to_image = os.path.join(
             os.path.dirname(__file__),
             "operation_icons",
-            f"{self.operation_path_name}{'_grey.png' if self.pressed else '.png'}",
+            (
+                f"{self.operation.type_name().lower()}{'_grey.png' if self.pressed else '.png'}"
+            ),
         )
         self.setIcon(QIcon(path_to_image))
         self.setIconSize(QSize(MINBUTTONSIZE, MINBUTTONSIZE))
diff --git a/b_asic/GUI/main_window.py b/b_asic/GUI/main_window.py
index 5ea25e56..c0e1adad 100644
--- a/b_asic/GUI/main_window.py
+++ b/b_asic/GUI/main_window.py
@@ -489,9 +489,7 @@ class MainWindow(QMainWindow):
 
     def create_operation(self, op, position=None):
         try:
-            attr_button = DragButton(
-                op.graph_id, op, op.type_name().lower(), True, window=self
-            )
+            attr_button = DragButton(op.graph_id, op, True, window=self)
             if position is None:
                 attr_button.move(GRID * 3, GRID * 2)
             else:
diff --git a/b_asic/GUI/properties_window.py b/b_asic/GUI/properties_window.py
index 84576d8b..3ff586fc 100644
--- a/b_asic/GUI/properties_window.py
+++ b/b_asic/GUI/properties_window.py
@@ -23,7 +23,9 @@ class PropertiesWindow(QDialog):
         self.name_layout = QHBoxLayout()
         self.name_layout.setSpacing(50)
         self.name_label = QLabel("Name:")
-        self.edit_name = QLineEdit(self.operation.operation_path_name)
+        self.edit_name = QLineEdit(
+            self.operation.name or self.operation.type_name
+        )
         self.name_layout.addWidget(self.name_label)
         self.name_layout.addWidget(self.edit_name)
         self.latency_fields = {}
diff --git a/b_asic/operation.py b/b_asic/operation.py
index 7a01d8d8..ecedacef 100644
--- a/b_asic/operation.py
+++ b/b_asic/operation.py
@@ -389,7 +389,6 @@ class Operation(GraphComponent, SignalSourceProvider):
         """
         raise NotImplementedError
 
-
     @abstractmethod
     def _increase_time_resolution(self, factor: int) -> None:
         raise NotImplementedError
diff --git a/b_asic/schedule.py b/b_asic/schedule.py
index a0ac495e..3a4f0f7b 100644
--- a/b_asic/schedule.py
+++ b/b_asic/schedule.py
@@ -90,7 +90,8 @@ class Schedule:
             op = cast(Operation, self._sfg.find_by_id(op_id))
             for outport in op.outputs:
                 max_end_time = max(
-                    max_end_time, op_start_time + cast(int, outport.latency_offset)
+                    max_end_time,
+                    op_start_time + cast(int, outport.latency_offset),
                 )
         return max_end_time
 
@@ -209,7 +210,9 @@ class Schedule:
             k: factor * v for k, v in self._start_times.items()
         }
         for op_id in self._start_times:
-            cast(Operation, self._sfg.find_by_id(op_id))._increase_time_resolution(factor)
+            cast(
+                Operation, self._sfg.find_by_id(op_id)
+            )._increase_time_resolution(factor)
         self._schedule_time *= factor
         return self
 
@@ -260,7 +263,9 @@ class Schedule:
             k: v // factor for k, v in self._start_times.items()
         }
         for op_id in self._start_times:
-            cast(Operation, self._sfg.find_by_id(op_id))._decrease_time_resolution(factor)
+            cast(
+                Operation, self._sfg.find_by_id(op_id)
+            )._decrease_time_resolution(factor)
         self._schedule_time = self._schedule_time // factor
         return self
 
diff --git a/b_asic/signal_flow_graph.py b/b_asic/signal_flow_graph.py
index 0c98df62..c52d7dba 100644
--- a/b_asic/signal_flow_graph.py
+++ b/b_asic/signal_flow_graph.py
@@ -160,8 +160,12 @@ class SFG(AbstractOperation):
                     raise ValueError(
                         f"Duplicate input signal {signal!r} in SFG"
                     )
-                new_input_op = cast(Input, self._add_component_unconnected_copy(Input()))
-                new_signal = cast(Signal, self._add_component_unconnected_copy(signal))
+                new_input_op = cast(
+                    Input, self._add_component_unconnected_copy(Input())
+                )
+                new_signal = cast(
+                    Signal, self._add_component_unconnected_copy(signal)
+                )
                 new_signal.set_source(new_input_op.output(0))
                 self._input_operations.append(new_input_op)
                 self._original_input_signals_to_indices[signal] = input_index
@@ -190,14 +194,20 @@ class SFG(AbstractOperation):
         # Setup output signals.
         if output_signals is not None:
             for output_index, signal in enumerate(output_signals):
-                new_output_op = cast(Output, self._add_component_unconnected_copy(Output()))
+                new_output_op = cast(
+                    Output, self._add_component_unconnected_copy(Output())
+                )
                 if signal in self._original_components_to_new:
                     # Signal was already added when setting up inputs.
-                    new_signal = cast(Signal, self._original_components_to_new[signal])
+                    new_signal = cast(
+                        Signal, self._original_components_to_new[signal]
+                    )
                     new_signal.set_destination(new_output_op.input(0))
                 else:
                     # New signal has to be created.
-                    new_signal = cast(Signal, self._add_component_unconnected_copy(signal))
+                    new_signal = cast(
+                        Signal, self._add_component_unconnected_copy(signal)
+                    )
                     new_signal.set_destination(new_output_op.input(0))
 
                 self._output_operations.append(new_output_op)
@@ -213,7 +223,9 @@ class SFG(AbstractOperation):
                         f"Duplicate output operation {output_op!r} in SFG"
                     )
 
-                new_output_op = cast(Output, self._add_component_unconnected_copy(output_op))
+                new_output_op = cast(
+                    Output, self._add_component_unconnected_copy(output_op)
+                )
                 for signal in output_op.input(0).signals:
                     if signal in self._original_components_to_new:
                         # Signal was already added when setting up inputs.
@@ -993,11 +1005,16 @@ class SFG(AbstractOperation):
             original_op = op_stack.pop()
             # Add or get the new copy of the operation.
             if original_op not in self._original_components_to_new:
-                new_op = cast(Operation, self._add_component_unconnected_copy(original_op))
+                new_op = cast(
+                    Operation,
+                    self._add_component_unconnected_copy(original_op),
+                )
                 self._components_dfs_order.append(new_op)
                 self._operations_dfs_order.append(new_op)
             else:
-                new_op = cast(Operation, self._original_components_to_new[original_op])
+                new_op = cast(
+                    Operation, self._original_components_to_new[original_op]
+                )
 
             # Connect input ports to new signals.
             for original_input_port in original_op.inputs:
@@ -1011,9 +1028,10 @@ class SFG(AbstractOperation):
                         in self._original_input_signals_to_indices
                     ):
                         # New signal already created during first step of constructor.
-                        new_signal = cast(Signal, self._original_components_to_new[
-                            original_signal
-                        ])
+                        new_signal = cast(
+                            Signal,
+                            self._original_components_to_new[original_signal],
+                        )
 
                         new_signal.set_destination(
                             new_op.input(original_input_port.index)
@@ -1023,9 +1041,7 @@ class SFG(AbstractOperation):
                         self._components_dfs_order.extend(
                             [new_signal, source.operation]
                         )
-                        self._operations_dfs_order.append(
-                            source.operation
-                        )
+                        self._operations_dfs_order.append(source.operation)
 
                     # Check if the signal has not been added before.
                     elif (
@@ -1036,9 +1052,12 @@ class SFG(AbstractOperation):
                                 "Dangling signal without source in SFG"
                             )
 
-                        new_signal = cast(Signal, self._add_component_unconnected_copy(
-                            original_signal
-                        ))
+                        new_signal = cast(
+                            Signal,
+                            self._add_component_unconnected_copy(
+                                original_signal
+                            ),
+                        )
 
                         new_signal.set_destination(
                             new_op.input(original_input_port.index)
@@ -1054,19 +1073,23 @@ class SFG(AbstractOperation):
                             original_connected_op
                             in self._original_components_to_new
                         ):
-                            component = cast(Operation, self._original_components_to_new[
-                                original_connected_op
-                            ])
+                            component = cast(
+                                Operation,
+                                self._original_components_to_new[
+                                    original_connected_op
+                                ],
+                            )
                             # Set source to the already added operations port.
                             new_signal.set_source(
                                 component.output(original_signal.source.index)
                             )
                         else:
                             # Create new operation, set signal source to it.
-                            new_connected_op = cast(Operation,
+                            new_connected_op = cast(
+                                Operation,
                                 self._add_component_unconnected_copy(
                                     original_connected_op
-                                )
+                                ),
                             )
                             new_signal.set_source(
                                 new_connected_op.output(
@@ -1089,9 +1112,10 @@ class SFG(AbstractOperation):
                         in self._original_output_signals_to_indices
                     ):
                         # New signal already created during first step of constructor.
-                        new_signal = cast(Signal, self._original_components_to_new[
-                            original_signal
-                        ])
+                        new_signal = cast(
+                            Signal,
+                            self._original_components_to_new[original_signal],
+                        )
 
                         new_signal.set_source(
                             new_op.output(original_output_port.index)
diff --git a/test/test_gui.py b/test/test_gui.py
index 7dab9d38..7bf9a424 100644
--- a/test/test_gui.py
+++ b/test/test_gui.py
@@ -138,5 +138,46 @@ def test_help_dialogs(qtbot):
     widget.display_faq_page()
     widget.display_about_page()
     widget.display_keybinds_page()
+    qtbot.wait(100)
+    widget.faq_page.close()
+    widget.about_page.close()
+    widget.keybinds_page.close()
+
+    widget.exit_app()
+
+
+def test_properties_window_smoke_test(qtbot, datadir):
+    # Smoke test to open up the properties window
+    # Should really check that the contents are correct and changes works etc
+    widget = GUI.MainWindow()
+    qtbot.addWidget(widget)
+    widget._load_from_file(datadir.join('twotapfir.py'))
+    sfg = widget.sfg_dict['twotapfir']
+    op = sfg.find_by_name("cmul2")[0]
+    dragbutton = widget.operationDragDict[op]
+    dragbutton.show_properties_window()
+    assert dragbutton._properties_window.operation == dragbutton
+    qtbot.mouseClick(dragbutton._properties_window.ok, QtCore.Qt.MouseButton.LeftButton)
+    widget.exit_app()
+
+
+def test_properties_window_change_name(qtbot, datadir):
+    # Smoke test to open up the properties window
+    # Should really check that the contents are correct and changes works etc
+    widget = GUI.MainWindow()
+    qtbot.addWidget(widget)
+    widget._load_from_file(datadir.join('twotapfir.py'))
+    sfg = widget.sfg_dict['twotapfir']
+    op = sfg.find_by_name("cmul2")[0]
+    dragbutton = widget.operationDragDict[op]
+    assert dragbutton.name == "cmul2"
+    assert dragbutton.operation.name == "cmul2"
+    dragbutton.show_properties_window()
+    assert dragbutton._properties_window.edit_name.text() == "cmul2"
+    dragbutton._properties_window.edit_name.setText("cmul73")
+    qtbot.mouseClick(dragbutton._properties_window.ok, QtCore.Qt.MouseButton.LeftButton)
+    dragbutton._properties_window.save_properties()
+    assert dragbutton.name == "cmul73"
+    assert dragbutton.operation.name == "cmul73"
 
     widget.exit_app()
diff --git a/test/test_gui/twotapfir.py b/test/test_gui/twotapfir.py
index 15660359..c0ab4c54 100644
--- a/test/test_gui/twotapfir.py
+++ b/test/test_gui/twotapfir.py
@@ -13,9 +13,9 @@ out1 = Output(name="")
 
 # Operations:
 t1 = Delay(initial_value=0, name="")
-cmul1 = ConstantMultiplication(value=0.5, name="cmul2", latency_offsets={'in0': None, 'out0': None})
+cmul1 = ConstantMultiplication(value=-0.5, name="cmul1", latency_offsets={'in0': None, 'out0': None})
 add1 = Addition(name="add1", latency_offsets={'in0': None, 'in1': None, 'out0': None})
-cmul2 = ConstantMultiplication(value=0.5, name="cmul", latency_offsets={'in0': None, 'out0': None})
+cmul2 = ConstantMultiplication(value=0.5, name="cmul2", latency_offsets={'in0': None, 'out0': None})
 
 # Signals:
 
-- 
GitLab