im_mainwindow.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. from PyQt5.QtWidgets import QMainWindow, QGraphicsItem, QAction, QActionGroup, QGraphicsView
  2. from PyQt5.QtGui import QIcon
  3. from PyQt5.QtCore import QStateMachine, QState
  4. from sketchUI.ui import Ui_MainWindow
  5. from sketchUI.im_scene import CustomScene, Mode
  6. from sketchUI import mvops
  7. from sketchUI.graphics_node_item import GraphicsNodeItem
  8. from wrappers.modelverse import element_list_nice
  9. class IMMainWindow(QMainWindow, Ui_MainWindow):
  10. def __init__(self, model):
  11. QMainWindow.__init__(self)
  12. self.setupUi(self)
  13. self.setWindowTitle(model)
  14. self._cur_model = model
  15. self._scene = CustomScene(model)
  16. self._scene.set_mode(Mode.SELECT)
  17. self._scene.setSceneRect(0, 0, 200, 200)
  18. self.graphicsView.setScene(self._scene)
  19. self.listWidget.addItems(mvops.get_available_types())
  20. self.listWidget.itemDoubleClicked.connect(self._on_list_item_clicked)
  21. self.setup_toolbar()
  22. self.setup_state_machine()
  23. # load the model
  24. self._load_model()
  25. #lastly, start the state machine
  26. self._statemachine.start()
  27. def setup_toolbar(self):
  28. self.select_action = QAction("Select", self)
  29. self.select_action.setIcon(QIcon("sketchUI/icons/select.png"))
  30. self.select_action.setCheckable(True)
  31. self.select_action.setChecked(True)
  32. self.connect_action = QAction("Connect", self)
  33. self.connect_action.setIcon(QIcon("sketchUI/icons/connect.png"))
  34. self.connect_action.setCheckable(True)
  35. action_group = QActionGroup(self)
  36. action_group.setExclusive(True)
  37. action_group.addAction(self.select_action)
  38. action_group.addAction(self.connect_action)
  39. for item in action_group.actions():
  40. self.toolBar.addAction(item)
  41. def setup_state_machine(self):
  42. self._statemachine = QStateMachine()
  43. state_select = QState()
  44. state_connect = QState()
  45. state_select.addTransition(self.connect_action.triggered, state_connect)
  46. state_connect.addTransition(self.select_action.triggered, state_select)
  47. state_connect.entered.connect(self._state_connect_entered)
  48. state_select.entered.connect(self._state_select_entered)
  49. self._statemachine.addState(state_select)
  50. self._statemachine.addState(state_connect)
  51. self._statemachine.setInitialState(state_select)
  52. def _load_model(self):
  53. """
  54. Load the model from the mv and render to screen
  55. Likely to be replaced later since rendering ideally already happens in the mv
  56. """
  57. model = element_list_nice(self._cur_model)
  58. if not model:
  59. # emtpy model
  60. return
  61. for item in model:
  62. typ = item["type"]
  63. if typ == "Node":
  64. # first, draw all nodes
  65. node_type = item["typeID"]
  66. self._add_node_to_scene(item["id"], node_type)
  67. for item in model:
  68. typ = item["type"]
  69. if typ == "Edge":
  70. target = item["__target"]
  71. src = item["__source"]
  72. self._add_edge_to_scene(src, target)
  73. def _state_connect_entered(self):
  74. self._scene.set_mode(Mode.CONNECT)
  75. self._make_items_movable(False)
  76. self._enable_list_widget(False)
  77. def _state_select_entered(self):
  78. self._scene.set_mode(Mode.SELECT)
  79. self._make_items_movable(True)
  80. self._enable_box_select(True)
  81. self._enable_list_widget(True)
  82. def _enable_list_widget(self, enabled):
  83. self.listWidget.setEnabled(enabled)
  84. def _make_items_movable(self, movable):
  85. for item in self._scene.items():
  86. try:
  87. # hacky hack because of pythons isinstance fails due to import chaos
  88. # edges are not selectable or movable
  89. item.__hack__()
  90. item.setFlag(QGraphicsItem.ItemIsMovable, False)
  91. item.setFlag(QGraphicsItem.ItemIsSelectable, False)
  92. continue
  93. except AttributeError:
  94. pass
  95. item.setFlag(QGraphicsItem.ItemIsMovable, movable)
  96. item.setFlag(QGraphicsItem.ItemIsSelectable, movable)
  97. def _enable_box_select(self, enable):
  98. if enable:
  99. self.graphicsView.setDragMode(QGraphicsView.RubberBandDrag)
  100. else:
  101. self.graphicsView.setDragMode(QGraphicsView.NoDrag)
  102. def _add_node_to_scene(self, node_id, node_type, x=0, y=0):
  103. item = GraphicsNodeItem(node_id)
  104. item.setText(node_type)
  105. item.setPos(x, y)
  106. item.setFlag(QGraphicsItem.ItemIsMovable, True)
  107. item.setFlag(QGraphicsItem.ItemIsSelectable, True)
  108. self._scene.addItem(item)
  109. def _add_edge_to_scene(self, from_id, to_id):
  110. from_item = None
  111. to_item = None
  112. for item in self._scene.items():
  113. try:
  114. node_id = item.node_id
  115. except AttributeError:
  116. # no node item, continue
  117. continue
  118. if node_id == from_id:
  119. from_item = item
  120. continue
  121. if node_id == to_id:
  122. to_item = item
  123. self._scene.draw_edge(from_item, to_item, is_new=False)
  124. def _on_list_item_clicked(self, event):
  125. # add new node to model in mv
  126. node_id = mvops.add_node(self._cur_model, event.text())
  127. # render to scene
  128. self._add_node_to_scene(node_id, event.text())