im_scene.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. from enum import Enum
  2. from PyQt5.QtWidgets import QGraphicsScene, QGraphicsItem
  3. from PyQt5.Qt import Qt, QTransform
  4. from sketchUI.graphics_edge_item import GraphicsEdgeItem
  5. from sketchUI.graphics_node_item import GraphicsNodeItem
  6. from sketchUI import mvops
  7. class Mode(Enum):
  8. SELECT = 0
  9. CONNECT = 1
  10. class CustomScene(QGraphicsScene):
  11. def __init__(self, model, parent):
  12. QGraphicsScene.__init__(self)
  13. self._mode = None # set by mainwindow at start
  14. self.connect_from_item = None # store the item to draw the connecting line from
  15. self._cur_model = model # the mv model we operate on
  16. self._parent = parent # mainwindow parent
  17. def set_mode(self, mode):
  18. self._mode = mode
  19. def mousePressEvent(self, event):
  20. if event.button() == Qt.LeftButton and self._mode == Mode.CONNECT:
  21. item = self.itemAt(event.scenePos(), QTransform())
  22. if not item:
  23. return
  24. self.connect_from_item = item
  25. QGraphicsScene.mousePressEvent(self, event)
  26. def mouseReleaseEvent(self, event):
  27. if event.button() == Qt.LeftButton and self._mode == Mode.CONNECT:
  28. item = self.itemAt(event.scenePos(), QTransform())
  29. if not item:
  30. return
  31. if item == self.connect_from_item:
  32. self._parent.plainTextEdit.appendPlainText("Error: Cannot connect same elements")
  33. return
  34. self.draw_edge(self.connect_from_item, item, is_new=True)
  35. if event.button() == Qt.LeftButton and self._mode == Mode.SELECT:
  36. item = self.itemAt(event.scenePos(), QTransform())
  37. if not item:
  38. return
  39. for item in self.items():
  40. try:
  41. item.__hack__() # hack to check if item is of edge type
  42. item.redraw()
  43. except AttributeError:
  44. continue
  45. QGraphicsScene.mouseReleaseEvent(self, event)
  46. def keyPressEvent(self, event):
  47. if not self._mode == Mode.SELECT:
  48. return
  49. # del deletes elements
  50. if event.key() == Qt.Key_Delete:
  51. self._handle_keypress_delete(self.selectedItems())
  52. def draw_edge(self, from_item, to_item, is_new):
  53. # type: (GraphicsNodeItem, GraphicsNodeItem, bool) -> None
  54. """
  55. Draw edge on screen between the node items "from_item" and "to_item".
  56. If is_new, additionally instantiate the edge in the model (if supported).
  57. """
  58. from_type = from_item.get_type()
  59. to_type = to_item.get_type()
  60. if is_new:
  61. if not mvops.is_edge_supported(from_type, to_type):
  62. self._parent.plainTextEdit.appendPlainText("Error: Edge not supported between types {} and {}".format(from_type, to_type))
  63. return
  64. line = GraphicsEdgeItem(from_item, to_item)
  65. line.setFlag(QGraphicsItem.ItemIsMovable, False)
  66. line.setFlag(QGraphicsItem.ItemIsSelectable, False)
  67. self.addItem(line)
  68. line.redraw()
  69. if is_new:
  70. mvops.add_edge(self._cur_model, from_item.node_id, to_item.node_id)
  71. self._parent.plainTextEdit.appendPlainText("Added edge between {} and {} to model".format(from_type, to_type))
  72. def _handle_keypress_delete(self, selected):
  73. for item in selected:
  74. # delete node in model (also deletes edges in model)
  75. if isinstance(item, GraphicsNodeItem):
  76. self._parent.plainTextEdit.appendPlainText("Deleting node of type {}".format(item.get_type()))
  77. mvops.delete_node(self._cur_model, item.node_id)
  78. # in view, delete edges that were connected to this node as well
  79. # modelverse does this on its own so do not delete edges explicitly here
  80. for edge in self.items():
  81. if not isinstance(edge, GraphicsEdgeItem):
  82. continue
  83. if edge.from_item.node_id == item.node_id or edge.to_item.node_id == item.node_id:
  84. self.removeItem(edge)
  85. self.removeItem(item)