Browse Source

implemented same attributing functions for example modeling, but without constraints

Lucas Heer 7 years ago
parent
commit
0b4eddeab4
5 changed files with 123 additions and 24 deletions
  1. 2 2
      main.py
  2. 47 2
      sketchUI/exm_mainwindow.py
  3. 50 4
      sketchUI/exm_scene.py
  4. 23 15
      sketchUI/im_scene.py
  5. 1 1
      wrappers/modelverse_SCCD.py

+ 2 - 2
main.py

@@ -69,10 +69,10 @@ def upload_instance_model():
 
 if __name__ == "__main__":
     parser = argparse.ArgumentParser()
-    parser.add_argument("-u", action="store_true", default=False, help="Upload models")
+    parser.add_argument("-u", action="store_true", default=False, help="Upload metamodels to Modelverse at startup")
     parser.add_argument("-im", action="store_true", default=False, help="Instance modeling")
     parser.add_argument("-exm", action="store_true", default=False, help="Example modeling")
-    parser.add_argument("-m", help="Model to open")
+    parser.add_argument("-m", help="Model to open. Not using this argument will create a new, empty model.")
     args = parser.parse_args()
 
     mv.init()

+ 47 - 2
sketchUI/exm_mainwindow.py

@@ -1,6 +1,6 @@
-from PyQt5.QtWidgets import QMainWindow, QAction, QActionGroup, QGraphicsItem, QGraphicsView
+from PyQt5.QtWidgets import QMainWindow, QAction, QActionGroup, QGraphicsItem, QGraphicsView, QTableWidgetItem
 from PyQt5.QtGui import QIcon
-from PyQt5.QtCore import QStateMachine, QState
+from PyQt5.QtCore import QStateMachine, QState, Qt
 from sketchUI.ui import Ui_MainWindow
 from sketchUI.exm_scene import SketchScene, Mode
 from sketchUI import mvops
@@ -34,6 +34,12 @@ class EXMMainWindow(QMainWindow, Ui_MainWindow):
         # setup log viewer
         self.plainTextEdit.setReadOnly(True)
 
+        # setup table view for attributes
+        self.tableWidget.setColumnCount(2)
+        self.tableWidget.setHorizontalHeaderLabels(["Key", "Value"])
+        self.tableWidget.horizontalHeader().setStretchLastSection(True)
+        self.tableWidget.itemChanged.connect(self._on_attribute_edited)
+
         # lastly, run state machine
         self._statemachine.start()
 
@@ -247,3 +253,42 @@ class EXMMainWindow(QMainWindow, Ui_MainWindow):
         # render node
         self._add_node_to_scene(node_id, event.text())
         self.plainTextEdit.appendPlainText("Added node of type {} to model".format(event.text()))
+
+    def _on_attribute_edited(self, item):
+        # type: (QTableWidgetItem) -> None
+        """ An attribute was edited, change it in the model but do not check (too expensive so
+        checking is done by verify method on demand).
+        If the new entered value is empty, delete the attribute.
+        """
+        row = self.tableWidget.row(item)
+        attr_key = self.tableWidget.item(row, 0).text()
+        attr_val = self.tableWidget.item(row, 1).text()
+        node = self._scene.selectedItems()[0]
+
+        if not attr_val:
+            self.plainTextEdit.appendPlainText("Deleting attribute {}".format(attr_key))
+            mvops.delete_attribute_from_node(self._cur_model, node.node_id, attr_key)
+            self.tableWidget.removeRow(row)
+        else:
+            self.plainTextEdit.appendPlainText("Updating value of attribute {} to {}".format(attr_key, attr_val))
+            mvops.update_attribute_val(self._cur_model, node.node_id, attr_key, attr_val)
+
+    def add_new_attribute(self, key, val="unknown"):
+        """
+        Adds a new attribute to the view with key "key" and optional val. Also adds this attribute to the modelverse
+        model.
+        """
+        selected_node = self._scene.selectedItems()[0]
+        self.plainTextEdit.appendPlainText("Adding new attribute with key {} to node {}".format(key, selected_node.get_type()))
+        self.tableWidget.blockSignals(True)
+        table_item_key = QTableWidgetItem(key)
+        table_item_key.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
+        table_item_val = QTableWidgetItem(val)
+        cur_row_cnt = self.tableWidget.rowCount()
+        self.tableWidget.insertRow(cur_row_cnt)
+        self.tableWidget.setItem(cur_row_cnt, 0, table_item_key)
+        self.tableWidget.setItem(cur_row_cnt, 1, table_item_val)
+        self.tableWidget.blockSignals(False)
+
+        # add to modelverse
+        mvops.add_attribute(self._cur_model, selected_node.node_id, key, val)

+ 50 - 4
sketchUI/exm_scene.py

@@ -1,12 +1,12 @@
 from enum import Enum
 from PyQt5.QtWidgets import QGraphicsScene, QGraphicsItem, QGraphicsLineItem, QGraphicsRectItem, \
-    QGraphicsEllipseItem, QInputDialog, QGraphicsItemGroup
+    QGraphicsEllipseItem, QInputDialog, QGraphicsItemGroup, QTableWidgetItem
 from PyQt5.Qt import Qt, QPointF, QPen, QTransform, QApplication
 from sketchUI.graphics_edge_item import GraphicsEdgeItem
 from sketchUI.graphics_node_item import GraphicsNodeItem, IconType
 from sketchUI import mvops
 from evolution.node_ops import NodeAdd, NodeDelete, NodeRetype
-from commons import all_nodes_with_type
+import commons
 
 
 class Mode(Enum):
@@ -57,12 +57,35 @@ class SketchScene(QGraphicsScene):
             # start drawing, save click point
             self._orig_point = event.scenePos()
             self._cur_drawing = True
+
         elif event.button() == Qt.LeftButton and self._mode == Mode.CONNECT:
+            # store clicked item to connect it later
             item = self.itemAt(event.scenePos(), QTransform())
             if not item or not isinstance(item, GraphicsNodeItem):
                 return
             else:
                 self._connect_from_item = item
+
+        elif event.button() == Qt.LeftButton and self._mode == Mode.SELECT:
+            # load attributes for selected item (if it is a typed node)
+            item = self.itemAt(event.scenePos(), QTransform())
+            if not item or not isinstance(item, GraphicsNodeItem):
+                return
+
+            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)
+                table_item_key.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
+                table_item_val = QTableWidgetItem(attr.val)
+                cur_row_cnt = self._parent.tableWidget.rowCount()
+                self._parent.tableWidget.insertRow(cur_row_cnt)
+                self._parent.tableWidget.setItem(cur_row_cnt, 0, table_item_key)
+                self._parent.tableWidget.setItem(cur_row_cnt, 1, table_item_val)
+            self._parent.tableWidget.blockSignals(False)
+
         else:
             pass
 
@@ -182,9 +205,11 @@ class SketchScene(QGraphicsScene):
             else:
                 self._parent.plainTextEdit.appendPlainText("Error: Cannot type element {}".format(item))
 
+        # "A" attributes a node
+        elif event.key() == Qt.Key_A:
+            self._handle_keypress_attribute(self.selectedItems())
         else:
             QGraphicsScene.keyPressEvent(self, event)
-        self.clearSelection()
 
     def _handle_keypress_type_on_node(self, item):
         # type: (GraphicsNodeItem) -> None
@@ -258,7 +283,7 @@ class SketchScene(QGraphicsScene):
         else:
             add_handler.execute(self._cur_model, node_type, local=True)
         # Get node id of newly added node in current model
-        nodeid = all_nodes_with_type(self._cur_model, node_type)[0]
+        nodeid = commons.all_nodes_with_type(self._cur_model, node_type)[0]
 
         self._parent.plainTextEdit.appendPlainText("Capturing concrete syntax of group ...")
         # create concrete syntax model for the sketched elements
@@ -323,3 +348,24 @@ class SketchScene(QGraphicsScene):
             self._parent.populate_types()
 
         QApplication.restoreOverrideCursor()
+
+    def _handle_keypress_attribute(self, selected):
+        if not len(selected) == 1:
+            return
+        item = selected[0]
+        if not isinstance(item, GraphicsNodeItem):
+            return
+
+        # ask user for key value
+        key, ok = QInputDialog.getText(self._parent, "New attribute", "Key value")
+        if not ok or not key:
+            return
+
+        # check if key value already used for this node
+        attrs = commons.get_attributes_of_node(self._cur_model, item.node_id)
+        for attr in attrs:
+            if attr.key == key:
+                self._parent.plainTextEdit.appendPlainText("Error: Already such a key for the node: {}".format(key))
+                return
+
+        self._parent.add_new_attribute(key)

+ 23 - 15
sketchUI/im_scene.py

@@ -32,23 +32,23 @@ class CustomScene(QGraphicsScene):
 
         if event.button() == Qt.LeftButton and self._mode == Mode.SELECT:
             # load attributes for selected node
-            self._parent.tableWidget.setRowCount(0)
             item = self.itemAt(event.scenePos(), QTransform())
-            if not item:
+            if not item or not isinstance(item, GraphicsNodeItem):
                 return
-            if isinstance(item, GraphicsNodeItem):
-                self._parent.tableWidget.blockSignals(True)
-                self._parent.plainTextEdit.appendPlainText("Selected item 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)
-                    table_item_key.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
-                    table_item_val = QTableWidgetItem(attr.val)
-                    cur_row_cnt = self._parent.tableWidget.rowCount()
-                    self._parent.tableWidget.insertRow(cur_row_cnt)
-                    self._parent.tableWidget.setItem(cur_row_cnt, 0, table_item_key)
-                    self._parent.tableWidget.setItem(cur_row_cnt, 1, table_item_val)
-                self._parent.tableWidget.blockSignals(False)
+
+            self._parent.tableWidget.setRowCount(0)
+            self._parent.tableWidget.blockSignals(True)
+            self._parent.plainTextEdit.appendPlainText("Selected item 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)
+                table_item_key.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
+                table_item_val = QTableWidgetItem(attr.val)
+                cur_row_cnt = self._parent.tableWidget.rowCount()
+                self._parent.tableWidget.insertRow(cur_row_cnt)
+                self._parent.tableWidget.setItem(cur_row_cnt, 0, table_item_key)
+                self._parent.tableWidget.setItem(cur_row_cnt, 1, table_item_val)
+            self._parent.tableWidget.blockSignals(False)
 
         QGraphicsScene.mousePressEvent(self, event)
 
@@ -150,4 +150,12 @@ class CustomScene(QGraphicsScene):
         key, ok = QInputDialog.getText(self._parent, "New attribute", "Key value")
         if not ok or not key:
             return
+
+        # check if key value already used for this node
+        attrs = commons.get_attributes_of_node(self._cur_model, item.node_id)
+        for attr in attrs:
+            if attr.key == key:
+                self._parent.plainTextEdit.appendPlainText("Error: Already such a key for the node: {}".format(key))
+                return
+
         self._parent.add_new_attribute(key)

+ 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:   Wed Apr 25 11:43:23 2018
+Date:   Wed Apr 25 15:33:59 2018
 
 Model author: Yentl Van Tendeloo
 Model name:   MvK Server