|
@@ -8,6 +8,7 @@ from sketchUI import mvops
|
|
|
from evolution.node_ops import NodeAdd, NodeDelete, NodeRetype
|
|
|
from commons import all_nodes_with_type
|
|
|
|
|
|
+
|
|
|
class Mode(Enum):
|
|
|
SELECT = 0
|
|
|
CONNECT = 1
|
|
@@ -22,7 +23,7 @@ class SketchScene(QGraphicsScene):
|
|
|
QGraphicsScene.__init__(self)
|
|
|
self._cur_drawing = False
|
|
|
self._mode = None # set from mainwindow on start
|
|
|
- self._from_item = None # mouse pressed on this item if in connect mode
|
|
|
+ self._connect_from_item = None # mouse pressed on this item if in connect mode
|
|
|
self._cur_model = model
|
|
|
|
|
|
self._orig_point = QPointF()
|
|
@@ -40,6 +41,8 @@ class SketchScene(QGraphicsScene):
|
|
|
return True
|
|
|
|
|
|
def draw_edge(self, from_item, to_item, is_new):
|
|
|
+ # type: (GraphicsNodeItem, GraphicsNodeItem, bool) -> None
|
|
|
+ # draw an edge between two items. If is_new, also add it to the model
|
|
|
line = GraphicsEdgeItem(from_item, to_item)
|
|
|
line.setFlag(QGraphicsItem.ItemIsMovable, False)
|
|
|
line.setFlag(QGraphicsItem.ItemIsSelectable, False)
|
|
@@ -56,9 +59,10 @@ class SketchScene(QGraphicsScene):
|
|
|
self._cur_drawing = True
|
|
|
elif event.button() == Qt.LeftButton and self._mode == Mode.CONNECT:
|
|
|
item = self.itemAt(event.scenePos(), QTransform())
|
|
|
- if not item:
|
|
|
+ if not item or not isinstance(item, GraphicsNodeItem):
|
|
|
return
|
|
|
- self._from_item = item
|
|
|
+ else:
|
|
|
+ self._connect_from_item = item
|
|
|
else:
|
|
|
pass
|
|
|
|
|
@@ -135,9 +139,9 @@ class SketchScene(QGraphicsScene):
|
|
|
|
|
|
elif self._mode == Mode.CONNECT:
|
|
|
item = self.itemAt(event.scenePos(), QTransform())
|
|
|
- if not item:
|
|
|
+ if not item or not isinstance(item, GraphicsNodeItem):
|
|
|
return
|
|
|
- self.draw_edge(self._from_item, item, is_new=True)
|
|
|
+ self.draw_edge(self._connect_from_item, item, is_new=True)
|
|
|
|
|
|
else:
|
|
|
pass
|
|
@@ -179,10 +183,12 @@ class SketchScene(QGraphicsScene):
|
|
|
|
|
|
else:
|
|
|
QGraphicsScene.keyPressEvent(self, event)
|
|
|
+ self.clearSelection()
|
|
|
|
|
|
def _handle_keypress_type_on_node(self, item):
|
|
|
- # type a node = retype it
|
|
|
- node_type, ok = QInputDialog.getText(self._parent, "Retype node", "New type", text=item.text())
|
|
|
+ # type: (GraphicsNodeItem) -> None
|
|
|
+ # type an already typed node = retype it
|
|
|
+ node_type, ok = QInputDialog.getText(self._parent, "Retype node", "New type", text=item.get_type())
|
|
|
if not ok:
|
|
|
# user canceled
|
|
|
return
|
|
@@ -207,14 +213,15 @@ class SketchScene(QGraphicsScene):
|
|
|
for node_item in self.items():
|
|
|
if not isinstance(node_item, GraphicsNodeItem):
|
|
|
continue
|
|
|
- if item.text() == node_item.text():
|
|
|
- node_item.setText(node_type)
|
|
|
+ if item.get_type() == node_item.get_type():
|
|
|
+ node_item.set_type(node_type)
|
|
|
|
|
|
# update list widget
|
|
|
self._parent.populate_types()
|
|
|
|
|
|
def _handle_keypress_type_on_group(self, group):
|
|
|
- # type the selected group
|
|
|
+ # type: (QGraphicsItemGroup) -> None
|
|
|
+ # type the selected group = make a real node out of it and store it in the actual model
|
|
|
# get the type from the user
|
|
|
node_type, ok = QInputDialog.getText(self._parent, "Type node", "Enter type")
|
|
|
if not ok:
|
|
@@ -235,15 +242,13 @@ class SketchScene(QGraphicsScene):
|
|
|
add_handler = NodeAdd()
|
|
|
if scope == "Global":
|
|
|
add_handler.execute(self._cur_model, node_type, local=False)
|
|
|
- # Hack: Get node id of newly added node in current model
|
|
|
- nodeid = all_nodes_with_type(self._cur_model, node_type)[0]
|
|
|
else:
|
|
|
add_handler.execute(self._cur_model, node_type, local=True)
|
|
|
- nodeid = add_handler.get_node_id()
|
|
|
+ # Get node id of newly added node in current model
|
|
|
+ nodeid = all_nodes_with_type(self._cur_model, node_type)[0]
|
|
|
|
|
|
# update view
|
|
|
- nodeitem = GraphicsNodeItem(nodeid)
|
|
|
- nodeitem.setText(node_type)
|
|
|
+ nodeitem = GraphicsNodeItem(nodeid, node_type)
|
|
|
nodeitem.setPos(group.x(), group.y())
|
|
|
nodeitem.setFlag(QGraphicsItem.ItemIsSelectable, True)
|
|
|
nodeitem.setFlag(QGraphicsItem.ItemIsMovable, True)
|
|
@@ -254,27 +259,32 @@ class SketchScene(QGraphicsScene):
|
|
|
def _handle_keypress_delete(self, selected):
|
|
|
del_hander = NodeDelete()
|
|
|
for item in selected:
|
|
|
- # only delete nodes, edges are taken care of
|
|
|
- if not isinstance(item, GraphicsNodeItem):
|
|
|
- continue
|
|
|
- # when deleting a node, local or global?
|
|
|
- scope, ok = QInputDialog.getItem(self._parent, "Select scope", "Scope", ["Local", "Global"])
|
|
|
- if not ok:
|
|
|
- return
|
|
|
- if scope == "Global":
|
|
|
- # global language evolution, so delete node with same type everywhere
|
|
|
- del_hander.execute(self._cur_model, item.node_id, local=False, check_if_last=False)
|
|
|
+ # only delete nodes, edges are taken care of later
|
|
|
+ if isinstance(item, GraphicsNodeItem):
|
|
|
+ # when deleting a node, local or global?
|
|
|
+ scope, ok = QInputDialog.getItem(self._parent, "Select scope", "Scope", ["Local", "Global"])
|
|
|
+ if not ok:
|
|
|
+ return
|
|
|
+ if scope == "Global":
|
|
|
+ # global language evolution, so delete node with same type everywhere
|
|
|
+ del_hander.execute(self._cur_model, item.node_id, local=False, check_if_last=False)
|
|
|
+ else:
|
|
|
+ # just local, delete from this model only
|
|
|
+ del_hander.execute(self._cur_model, item.node_id, local=True, check_if_last=True)
|
|
|
+
|
|
|
+ # in view, delete edges that were connected to this node as well
|
|
|
+ for edge in self.items():
|
|
|
+ if not isinstance(edge, GraphicsEdgeItem):
|
|
|
+ continue
|
|
|
+ if edge.from_item.node_id == item.node_id or edge.to_item.node_id == item.node_id:
|
|
|
+ self.removeItem(edge)
|
|
|
+
|
|
|
+ self.removeItem(item)
|
|
|
+ # repopulate available types in view since they might have changed
|
|
|
else:
|
|
|
- # just local, delete from this model only
|
|
|
- del_hander.execute(self._cur_model, item.node_id, local=True, check_if_last=True)
|
|
|
-
|
|
|
- # in view, delete edges that were connected to this node as well
|
|
|
- for edge in self.items():
|
|
|
- if not isinstance(edge, GraphicsEdgeItem):
|
|
|
- continue
|
|
|
- if edge.from_item.node_id == item.node_id or edge.to_item.node_id == item.node_id:
|
|
|
- self.removeItem(edge)
|
|
|
-
|
|
|
- self.removeItem(item)
|
|
|
- # repopulate available types in view since they might have changed
|
|
|
+ for item in selected:
|
|
|
+ self.removeItem(item)
|
|
|
+
|
|
|
+ # if any node was deleted, repopulate list if available items
|
|
|
+ if any(isinstance(item, GraphicsNodeItem) for item in selected):
|
|
|
self._parent.populate_types()
|