Ver código fonte

added node highlighting for verify and select

Lucas Heer 7 anos atrás
pai
commit
6fb919a04e

+ 6 - 2
sketchUI/exm_mainwindow.py

@@ -1,6 +1,7 @@
 from PyQt5.QtWidgets import QMainWindow, QAction, QActionGroup, QGraphicsItem, QGraphicsView, QTableWidgetItem
 from PyQt5.QtGui import QIcon
 from PyQt5.QtCore import QStateMachine, QState, Qt
+from PyQt5.Qt import QApplication
 from sketchUI.ui import Ui_MainWindow
 from sketchUI.exm_scene import SketchScene, Mode
 from sketchUI import mvops
@@ -300,15 +301,17 @@ class EXMMainWindow(QMainWindow, Ui_MainWindow):
         mvops.add_attribute(self._cur_model, selected_node.node_id, key, val)
 
     def _on_delete_model_clicked(self, event):
-        # delete the open example model
+        # delete the open example model by iteratively deleting all nodes
         self.plainTextEdit.appendPlainText("Deleting model ...")
         self.plainTextEdit.repaint()
 
+        QApplication.setOverrideCursor(Qt.WaitCursor)
         delhander = NodeDelete()
         for item in self._scene.items():
             if not isinstance(item, GraphicsNodeItem):
                 continue
-            print("Deleting node {}".format(item.node_id))
+            self.plainTextEdit.appendPlainText("Deleting node {}".format(item.node_id))
+            self.plainTextEdit.repaint()
             delhander.execute(self._cur_model, item.node_id, local=True, check_if_last=True)
 
         # delete the empty model from the Modelverse
@@ -316,3 +319,4 @@ class EXMMainWindow(QMainWindow, Ui_MainWindow):
             self.close()
         else:
             self.plainTextEdit.appendPlainText("Error: Delete failed")
+            QApplication.restoreOverrideCursor()

+ 12 - 1
sketchUI/exm_scene.py

@@ -76,10 +76,11 @@ class SketchScene(QGraphicsScene):
                 return
 
             elif isinstance(item, GraphicsNodeItem):
+                self._parent.plainTextEdit.appendPlainText("Selected node of type {}".format(item.get_type()))
+                self.highlight_node(item.node_id, Qt.blue)
                 # load attributes for selected node
                 self._parent.tableWidget.setRowCount(0)
                 self._parent.tableWidget.blockSignals(True)
-                self._parent.plainTextEdit.appendPlainText("Selected node of type {}".format(item.get_type()))
                 attrs = commons.get_attributes_of_node(self._cur_model, item.node_id)
                 for attr in attrs:
                     table_item_key = QTableWidgetItem(attr.key)
@@ -431,3 +432,13 @@ class SketchScene(QGraphicsScene):
                 return
 
         self._parent.add_new_attribute(key)
+
+    def highlight_node(self, node_id, color):
+        for item in self.items():
+            if not isinstance(item, GraphicsNodeItem):
+                continue
+            if item.node_id == node_id:
+                item.set_highlighted(True, color)
+            else:
+                item.set_highlighted(False, color)
+            item.update(item.boundingRect())

+ 11 - 0
sketchUI/graphics_node_item.py

@@ -21,6 +21,8 @@ class GraphicsNodeItem(QGraphicsItem):
         self.node_id = node_id
         self._type = node_type
         self._consyn = consyn
+        self._is_highlighted = False
+        self._highlight_color = None
 
         self._icon_type = None
         self._font = QFont()
@@ -43,19 +45,28 @@ class GraphicsNodeItem(QGraphicsItem):
         bbox = QRectF(0, 0, 120, 120)
         return bbox
 
+    def set_highlighted(self, highlight, color):
+        self._is_highlighted = highlight
+        self._highlight_color = color
+
     def paint(self, painter, option, widget=None):
         # type: (QPainter, QStyleOptionGraphicsItem, QWidget) -> None
         # draw type text and bounding rectangle
         painter.setFont(self._font)
 
+        # draw bounding rectangle
         painter.setBrush(QBrush(Qt.white))
+        if self._is_highlighted:
+            painter.setPen(self._highlight_color)
         painter.drawRect(self.boundingRect())
 
         text_box = QRectF(0, 100, 120, 20)
         painter.drawRect(text_box)
+        painter.setPen(Qt.black)
         painter.setBrush(QBrush(QColor(0, 0, 0, 0)))
         painter.drawText(text_box, Qt.AlignCenter | Qt.TextDontClip, self._type)
 
+
         # draw concrete syntax
         if not self._consyn:
             # nothing to draw, so leave empty

+ 1 - 0
sketchUI/im_mainwindow.py

@@ -208,6 +208,7 @@ class IMMainWindow(QMainWindow, Ui_MainWindow):
         ret = verify.verify_attributes()
         if not ret["OK"]:
             self.plainTextEdit.appendPlainText("Error: {}".format(str(ret["error"])))
+            self._scene.highlight_node(ret["affected"][0], Qt.red)
             QApplication.restoreOverrideCursor()
             return
         else:

+ 13 - 1
sketchUI/im_scene.py

@@ -36,9 +36,11 @@ class CustomScene(QGraphicsScene):
             if not item:
                 return
             elif isinstance(item, GraphicsNodeItem):
+                self._parent.plainTextEdit.appendPlainText("Selected node of type {}".format(item.get_type()))
+                self.highlight_node(item.node_id, Qt.blue)
+                # load node attributes and display them in table
                 self._parent.tableWidget.setRowCount(0)
                 self._parent.tableWidget.blockSignals(True)
-                self._parent.plainTextEdit.appendPlainText("Selected node of type {}".format(item.get_type()))
                 attrs = commons.get_attributes_of_node(self._cur_model, item.node_id)
                 for attr in attrs:
                     table_item_key = QTableWidgetItem(attr.key)
@@ -176,3 +178,13 @@ class CustomScene(QGraphicsScene):
                 return
 
         self._parent.add_new_attribute(key)
+
+    def highlight_node(self, node_id, color):
+        for item in self.items():
+            if not isinstance(item, GraphicsNodeItem):
+                continue
+            if item.node_id == node_id:
+                item.set_highlighted(True, color)
+            else:
+                item.set_highlighted(False, color)
+            item.update(item.boundingRect())

+ 12 - 8
verifier.py

@@ -59,7 +59,7 @@ class Verifier(object):
             if node_typ not in self._available_types:
                 return {"OK": False, "error": "Type {} from instance model not in example models".format(node_typ)}
 
-        return {"OK":True, "error":None}
+        return {"OK":True, "error":None, "affected":[]}
 
     def verify_node_multiplicity(self):
         """
@@ -78,7 +78,7 @@ class Verifier(object):
             if not commons.count_occurences(el, self._instance_model) >= min_occ:
                 return {"OK": False, "error": "Node with type {} needs to occur at least {} times".format(el, min_occ)}
 
-        return {"OK": True, "error": None}
+        return {"OK": True, "error": None, "affected":[]}
 
     def _get_attributes_of_all_types(self):
         """
@@ -140,7 +140,8 @@ class Verifier(object):
                         break
                 else:
                     # loop completed without break, so we did not find any key in example models
-                    return {"OK": False, "error": "No key {} for type {} in example models".format(attr.key, node_typ)}
+                    return {"OK": False, "error": "No key {} for type {} in example models".format(attr.key, node_typ),
+                            "affected":[node]}
 
         # Check if mandatory attributes are present in instance model
         attr_mandatory = {node_type:{} for node_type in self._available_types}
@@ -165,9 +166,10 @@ class Verifier(object):
             for attr, mand in attr_mand.iteritems():
                 if mand:
                     if not attr in [x.key for x in node_attrs]:
-                        return {"OK": False, "error":"Attribute {} for type {} mandatory".format(attr, node_type)}
+                        return {"OK": False, "error":"Attribute {} for type {} mandatory".format(attr, node_type),
+                                "affected":[node]}
 
-        return {"OK": True, "error": None}
+        return {"OK": True, "error": None, "affected":[]}
 
     def verify_associations(self):
         """
@@ -200,7 +202,8 @@ class Verifier(object):
             # instance model contains both types
             for node in commons.all_nodes_with_type(self._instance_model, edge.n1):
                 if not commons.has_edge_to_type(self._instance_model, node, edge.n2):
-                    return {"OK":False, "error": "Edge between {} and {} mandatory".format(edge.n1, edge.n2)}
+                    return {"OK":False, "error": "Edge between {} and {} mandatory".format(edge.n1, edge.n2),
+                            "affected":[]}
 
         # lastly, check if all edges in the instance model are actually supported
         all_edges = mv.all_instances(self._instance_model, "Edge")
@@ -210,6 +213,7 @@ class Verifier(object):
             src_type = commons.get_node_type(self._instance_model, src_id)
             dest_type = commons.get_node_type(self._instance_model, dest_id)
             if not commons.is_edge_supported(src_type, dest_type):
-                return {"OK":False, "error": "Edge between {} and {} not supported".format(edge.n1, edge.n2)}
+                return {"OK":False, "error": "Edge between {} and {} not supported".format(edge.n1, edge.n2),
+                        "affected":[src_id, dest_id]}
 
-        return {"OK": True, "error": None}
+        return {"OK": True, "error": None, "affected":[]}

+ 1 - 1
wrappers/modelverse_SCCD.py

@@ -1,7 +1,7 @@
 """
 Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
 
-Date:   Sat Apr 28 11:35:47 2018
+Date:   Sat Apr 28 14:38:25 2018
 
 Model author: Yentl Van Tendeloo
 Model name:   MvK Server