im_mainwindow.py 5.3 KB

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