From 56e81186398897171021f47ca9b2989c0af8db8a Mon Sep 17 00:00:00 2001
From: Jacob Wahlman <jacwa448@student.liu.se>
Date: Tue, 19 May 2020 17:21:16 +0200
Subject: [PATCH] lots of bug fixes in gui

---
 b_asic/GUI/arrow.py                           |  11 ++-
 b_asic/GUI/drag_button.py                     |   3 +-
 b_asic/GUI/main_window.py                     |  69 +++++++++++++++---
 b_asic/GUI/operation_icons/{reg.png => t.png} | Bin
 .../{reg_grey.png => t_grey.png}              | Bin
 b_asic/GUI/properties_window.py               |   5 +-
 b_asic/save_load_structure.py                 |   5 +-
 7 files changed, 78 insertions(+), 15 deletions(-)
 rename b_asic/GUI/operation_icons/{reg.png => t.png} (100%)
 rename b_asic/GUI/operation_icons/{reg_grey.png => t_grey.png} (100%)

diff --git a/b_asic/GUI/arrow.py b/b_asic/GUI/arrow.py
index aea8fec3..eb4e279d 100644
--- a/b_asic/GUI/arrow.py
+++ b/b_asic/GUI/arrow.py
@@ -30,7 +30,16 @@ class Arrow(QGraphicsLineItem):
         self.signal.remove_destination()
         self.signal.remove_source()
         self._window.scene.removeItem(self)
-        self._window.signalList.remove(self)
+        if self in self._window.signalList:
+            self._window.signalList.remove(self)
+
+        if self in self._window.signalPortDict:
+            for port1, port2 in self._window.signalPortDict[self]:
+                for operation, operation_ports in self._window.portDict.items():
+                    if (port1 in operation_ports or port2 in operation_ports) and operation in self._window.opToSFG:
+                        self._window.logger.info(f"Operation detected in existing sfg, removing sfg with name: {self._window.opToSFG[operation].name}.")
+                        del self._window.sfg_dict[self._window.opToSFG[operation].name]
+                        self._window.opToSFG = {op: self._window.opToSFG[op] for op in self._window.opToSFG if self._window.opToSFG[op] is not self._window.opToSFG[operation]}
 
     def moveLine(self):
         self.setPen(QPen(Qt.black, 3))
diff --git a/b_asic/GUI/drag_button.py b/b_asic/GUI/drag_button.py
index fe78f463..a67027d8 100644
--- a/b_asic/GUI/drag_button.py
+++ b/b_asic/GUI/drag_button.py
@@ -128,11 +128,12 @@ class DragButton(QPushButton):
 
         if self in self._window.opToSFG:
             self._window.logger.info(f"Operation detected in existing sfg, removing sfg with name: {self._window.opToSFG[self].name}.")
-            self._window.opToSFG = {op: self._window.opToSFG[op] for op in self._window.opToSFG if self._window.opToSFG[op] is self._window.opToSFG[self]}
             del self._window.sfg_dict[self._window.opToSFG[self].name]
+            self._window.opToSFG = {op: self._window.opToSFG[op] for op in self._window.opToSFG if self._window.opToSFG[op] is not self._window.opToSFG[self]}
 
         for signal in _signals:
             del self._window.signalPortDict[signal]
+            signal.remove()
 
         for port in self._window.portDict[self]:
             if port in self._window.pressed_ports:
diff --git a/b_asic/GUI/main_window.py b/b_asic/GUI/main_window.py
index 0607100a..9f232ad8 100644
--- a/b_asic/GUI/main_window.py
+++ b/b_asic/GUI/main_window.py
@@ -101,6 +101,8 @@ class MainWindow(QMainWindow):
         self.shortcut_save.activated.connect(self.save_work)
         self.shortcut_help = QShortcut(QKeySequence("Ctrl+?"), self)
         self.shortcut_help.activated.connect(self.display_faq_page)
+        self.shortcut_signal = QShortcut(QKeySequence(Qt.Key_Space), self)
+        self.shortcut_signal.activated.connect(self._connect_button)
 
         self.logger.info("Finished setting up GUI")
         self.logger.info("For questions please refer to 'Ctrl+?', or visit the 'Help' section on the toolbar.")
@@ -257,11 +259,56 @@ class MainWindow(QMainWindow):
         sfg = SFG(inputs=inputs, outputs=outputs, name=name)
         self.logger.info(f"Created SFG with name: {name} from selected operations.")
 
-        sfg_operations = sfg.operations.copy()
-        for op in self.pressed_operations:
-            operation = [op_ for op_ in sfg_operations if op_.type_name() == op.operation.type_name()][0]
-            op.operation = operation
-            sfg_operations.remove(operation)
+        def check_equality(signal, signal_2):
+            # check operation types
+            if not (signal.source.operation.type_name() == signal_2.source.operation.type_name() \
+                and signal.destination.operation.type_name() == signal_2.destination.operation.type_name()):
+                return False
+
+            if hasattr(signal.source.operation, "value") and hasattr(signal_2.source.operation, "value") \
+                and hasattr(signal.destination.operation, "value") and hasattr(signal_2.destination.operation, "value"):
+                if not (signal.source.operation.value == signal_2.source.operation.value \
+                    and signal.destination.operation.value == signal_2.destination.operation.value):
+                    return False
+
+            if hasattr(signal.source.operation, "name") and hasattr(signal_2.source.operation, "name") \
+                and hasattr(signal.destination.operation, "name") and hasattr(signal_2.destination.operation, "name"):
+                if not (signal.source.operation.name == signal_2.source.operation.name \
+                    and signal.destination.operation.name == signal_2.destination.operation.name):
+                    return False
+
+            try:
+                _signal_source_index = [signal.source.operation.outputs.index(port) for port in signal.source.operation.outputs if signal in port.signals]
+                _signal_2_source_index = [signal_2.source.operation.outputs.index(port) for port in signal_2.source.operation.outputs if signal_2 in port.signals]
+            except ValueError:
+                return False  # Signal output connections not matching
+
+            try:
+                _signal_destination_index = [signal.destination.operation.inputs.index(port) for port in signal.destination.operation.inputs if signal in port.signals]
+                _signal_2_destination_index = [signal_2.destination.operation.inputs.index(port) for port in signal_2.destination.operation.inputs if signal_2 in port.signals]
+            except ValueError:
+                return False  # Signal input connections not matching
+
+            if not (_signal_source_index == _signal_2_source_index and _signal_destination_index == _signal_2_destination_index):
+                return False
+
+            return True
+
+        for pressed_op in self.pressed_operations:
+            for operation in sfg.operations:
+                for input_ in operation.inputs:
+                    for signal in input_.signals:
+                        for line in self.signalPortDict:
+                            if check_equality(line.signal, signal):
+                                line.source.operation.operation = signal.source.operation
+                                line.destination.operation.operation = signal.destination.operation
+
+                for output_ in operation.outputs:
+                    for signal in output_.signals:
+                        for line in self.signalPortDict:
+                            if check_equality(line.signal, signal):
+                                line.source.operation.operation = signal.source.operation
+                                line.destination.operation.operation = signal.destination.operation
 
         for op in self.pressed_operations:
             op.setToolTip(sfg.name)
@@ -352,10 +399,9 @@ class MainWindow(QMainWindow):
             attr_button.setParent(None)
             attr_button_scene = self.scene.addWidget(attr_button)
             if position is None:
-                attr_button_scene.moveBy(self.move_button_index * 100, 0)
+                attr_button_scene.moveBy(int(self.scene.width() / 2), int(self.scene.height() / 2))
             attr_button_scene.setFlag(attr_button_scene.ItemIsSelectable, True)
-            self.move_button_index += 1
-            operation_label = QGraphicsTextItem(op.type_name(), attr_button_scene)
+            operation_label = QGraphicsTextItem(op.name, attr_button_scene)
             if not self.is_show_names:
                 operation_label.setOpacity(0)
             operation_label.setTransformOriginPoint(operation_label.boundingRect().center())
@@ -394,7 +440,7 @@ class MainWindow(QMainWindow):
             self.pressed_operations.clear()
         super().keyPressEvent(event)
 
-    def _connect_button(self, event):
+    def _connect_button(self, *event):
         if len(self.pressed_ports) < 2:
             self.logger.warning("Can't connect less than two ports. Please select more.")
             return
@@ -403,6 +449,11 @@ class MainWindow(QMainWindow):
             source = self.pressed_ports[i] if isinstance(self.pressed_ports[i].port, OutputPort) else self.pressed_ports[i + 1]
             destination = self.pressed_ports[i + 1] if source is not self.pressed_ports[i + 1] else self.pressed_ports[i]
             if source.port.operation is destination.port.operation:
+                self.logger.warning("Can't connect to the same port")
+                continue
+
+            if type(source.port) == type(destination.port):
+                self.logger.warning(f"Can't connect port of type: {type(source.port).__name__} to port of type: {type(destination.port).__name__}.")
                 continue
 
             self.connect_button(source, destination)
diff --git a/b_asic/GUI/operation_icons/reg.png b/b_asic/GUI/operation_icons/t.png
similarity index 100%
rename from b_asic/GUI/operation_icons/reg.png
rename to b_asic/GUI/operation_icons/t.png
diff --git a/b_asic/GUI/operation_icons/reg_grey.png b/b_asic/GUI/operation_icons/t_grey.png
similarity index 100%
rename from b_asic/GUI/operation_icons/reg_grey.png
rename to b_asic/GUI/operation_icons/t_grey.png
diff --git a/b_asic/GUI/properties_window.py b/b_asic/GUI/properties_window.py
index 04d899fd..af6cf762 100644
--- a/b_asic/GUI/properties_window.py
+++ b/b_asic/GUI/properties_window.py
@@ -22,7 +22,7 @@ class PropertiesWindow(QDialog):
         self.vertical_layout = QVBoxLayout()
         self.vertical_layout.addLayout(self.name_layout)
 
-        if self.operation.operation_path_name == "c":
+        if hasattr(self.operation.operation, "value"):
             self.constant_layout = QHBoxLayout()
             self.constant_layout.setSpacing(50)
             self.constant_value = QLabel("Constant:")
@@ -122,8 +122,9 @@ class PropertiesWindow(QDialog):
     def save_properties(self):
         self._window.logger.info(f"Saving properties of operation: {self.operation.name}.")
         self.operation.name = self.edit_name.text()
+        self.operation.operation.name = self.edit_name.text()
         self.operation.label.setPlainText(self.operation.name)
-        if self.operation.operation_path_name == "c":
+        if hasattr(self.operation.operation, "value"):
             self.operation.operation.value = int(self.edit_constant.text())
         if self.check_show_name.isChecked():
             self.operation.label.setOpacity(1)
diff --git a/b_asic/save_load_structure.py b/b_asic/save_load_structure.py
index 5311d3fe..88e1d4fb 100644
--- a/b_asic/save_load_structure.py
+++ b/b_asic/save_load_structure.py
@@ -62,8 +62,9 @@ def sfg_to_python(sfg: SFG, counter: int = 0, suffix: str = None) -> str:
     inputs = "[" + ", ".join(op.graph_id for op in sfg.input_operations) + "]"
     outputs = "[" + ", ".join(op.graph_id for op in sfg.output_operations) + "]"
     sfg_name = sfg.name if sfg.name else "sfg" + str(counter) if counter > 0 else 'sfg'
-    result += f"\n{sfg_name} = SFG(inputs={inputs}, outputs={outputs}, name='{sfg_name}')\n"
-    result += "\n# SFG Properties:\n" + "prop = {'name':" + f"{sfg_name}" + "}"
+    sfg_name_var = sfg_name.replace(" ", "_")
+    result += f"\n{sfg_name_var} = SFG(inputs={inputs}, outputs={outputs}, name='{sfg_name}')\n"
+    result += "\n# SFG Properties:\n" + "prop = {'name':" + f"{sfg_name_var}" + "}"
 
     if suffix is not None:
         result += "\n" + suffix + "\n"
-- 
GitLab