exm_scene.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. from enum import Enum
  2. from PyQt5.QtWidgets import QGraphicsScene, QGraphicsItem, QGraphicsLineItem, QGraphicsRectItem, \
  3. QGraphicsEllipseItem, QInputDialog
  4. from PyQt5.Qt import Qt, QPointF, QPen, QTransform
  5. from PyQt5.QtCore import pyqtSignal
  6. from sketchUI.graphics_edge_item import GraphicsEdgeItem
  7. from sketchUI.graphics_node_item import GraphicsNodeItem
  8. from sketchUI import mvops
  9. class Mode(Enum):
  10. SELECT = 0
  11. CONNECT = 1
  12. LINE = 2
  13. RECT = 3
  14. CIRCLE = 4
  15. FREE = 5
  16. class SketchScene(QGraphicsScene):
  17. def __init__(self, model, parent):
  18. QGraphicsScene.__init__(self)
  19. self._cur_drawing = False
  20. self._mode = None # set from mainwindow on start
  21. self._from_item = None # mouse pressed on this item if in connect mode
  22. self._cur_model = model
  23. self._orig_point = QPointF()
  24. self._free_draw_lines = []
  25. self._parent = parent
  26. def set_mode(self, mode):
  27. self._mode = mode
  28. def _in_draw_mode(self):
  29. # are we in one of the draw modes? (rect, line, free, ...)
  30. if self._mode == Mode.CONNECT or self._mode == Mode.SELECT:
  31. return False
  32. return True
  33. def draw_edge(self, from_item, to_item, is_new):
  34. line = GraphicsEdgeItem(from_item, to_item)
  35. line.setFlag(QGraphicsItem.ItemIsMovable, False)
  36. line.setFlag(QGraphicsItem.ItemIsSelectable, False)
  37. self.addItem(line)
  38. line.redraw()
  39. if is_new:
  40. mvops.add_edge(self._cur_model, from_item.node_id, to_item.node_id)
  41. def mousePressEvent(self, event):
  42. if event.button() == Qt.LeftButton and self._in_draw_mode():
  43. # start drawing, save click point
  44. self._orig_point = event.scenePos()
  45. self._cur_drawing = True
  46. elif event.button() == Qt.LeftButton and self._mode == Mode.CONNECT:
  47. item = self.itemAt(event.scenePos(), QTransform())
  48. if not item:
  49. return
  50. self._from_item = item
  51. else:
  52. pass
  53. QGraphicsScene.mousePressEvent(self, event)
  54. def mouseMoveEvent(self, event):
  55. # if in freehand mode, draw lines from move movement
  56. if self._mode == Mode.FREE and self._cur_drawing:
  57. pt = event.scenePos()
  58. line = QGraphicsLineItem(self._orig_point.x(), self._orig_point.y(), pt.x(), pt.y())
  59. line.setPen(QPen(Qt.black, 2, Qt.SolidLine))
  60. self.addItem(line)
  61. self._orig_point = pt
  62. self._free_draw_lines.append(line)
  63. QGraphicsScene.mouseMoveEvent(self, event)
  64. def mouseReleaseEvent(self, event):
  65. if self._cur_drawing:
  66. end_point = event.scenePos()
  67. if self._mode == Mode.LINE:
  68. line = QGraphicsLineItem(self._orig_point.x(), self._orig_point.y(),
  69. end_point.x(), end_point.y())
  70. line.setPen(QPen(Qt.black, 2, Qt.SolidLine))
  71. self.addItem(line)
  72. elif self._mode == Mode.RECT:
  73. width = abs(end_point.x() - self._orig_point.x())
  74. height = abs(end_point.y() - self._orig_point.y())
  75. rect = QGraphicsRectItem(self._orig_point.x(), self._orig_point.y(),
  76. width, height)
  77. rect.setPen(QPen(Qt.black, 2, Qt.SolidLine))
  78. self.addItem(rect)
  79. elif self._mode == Mode.CIRCLE:
  80. width = abs(end_point.x() - self._orig_point.x())
  81. height = abs(end_point.y() - self._orig_point.y())
  82. ellipse = QGraphicsEllipseItem(self._orig_point.x(), self._orig_point.y(),
  83. width, height)
  84. ellipse.setPen(QPen(Qt.black, 2, Qt.SolidLine))
  85. self.addItem(ellipse)
  86. elif self._mode == Mode.FREE:
  87. line = QGraphicsLineItem(self._orig_point.x(), self._orig_point.y(),
  88. end_point.x(), end_point.y())
  89. line.setPen(QPen(Qt.black, 2, Qt.SolidLine))
  90. self.addItem(line)
  91. # group lines together
  92. self._free_draw_lines.append(line)
  93. group = self.createItemGroup(self._free_draw_lines)
  94. group.setFlag(QGraphicsItem.ItemIsSelectable, False)
  95. group.setFlag(QGraphicsItem.ItemIsMovable, False)
  96. del self._free_draw_lines[:]
  97. else:
  98. pass
  99. self._cur_drawing = False
  100. else:
  101. if self._mode == Mode.SELECT:
  102. item = self.itemAt(event.scenePos(), QTransform())
  103. if not item:
  104. return
  105. for item in self.items():
  106. try:
  107. item.__hack__() # hack to check if item is of edge type
  108. item.redraw()
  109. except AttributeError:
  110. continue
  111. elif self._mode == Mode.CONNECT:
  112. item = self.itemAt(event.scenePos(), QTransform())
  113. if not item:
  114. return
  115. self.draw_edge(self._from_item, item, is_new=True)
  116. else:
  117. pass
  118. QGraphicsScene.mouseReleaseEvent(self, event)
  119. def keyPressEvent(self, event):
  120. if not self._mode == Mode.SELECT:
  121. return
  122. # "del" deletes all selected items
  123. if event.key() == Qt.Key_Delete:
  124. for item in self.selectedItems():
  125. self.removeItem(item)
  126. # "G" groups selected items
  127. elif event.key() == Qt.Key_G:
  128. selected = self.selectedItems()
  129. self.clearSelection()
  130. group = self.createItemGroup(selected)
  131. bb_rect = QGraphicsRectItem(group.boundingRect())
  132. bb_rect.setPen(QPen(Qt.gray, 1, Qt.DashLine))
  133. group.addToGroup(bb_rect)
  134. group.setFlag(QGraphicsItem.ItemIsSelectable, True)
  135. group.setFlag(QGraphicsItem.ItemIsMovable, True)
  136. elif event.key() == Qt.Key_T:
  137. selected = self.selectedItems()
  138. if len(selected) != 1:
  139. return
  140. item = selected[0]
  141. # "T" lets the user type the selected item
  142. text, ok = QInputDialog.getText(self._parent, "Text input", "Enter type")
  143. if ok and text:
  144. print("Typing item {} to type {}".format(item, text))
  145. if text in mvops.get_available_types():
  146. print("Already such a type: {}".format(text))
  147. return
  148. self._type_item(item, text)
  149. else:
  150. QGraphicsScene.keyPressEvent(self, event)
  151. def _type_item(self, item, typ):
  152. # typing means elevating it to a real node
  153. nid = mvops.add_node(self._cur_model, typ)
  154. nodeitem = GraphicsNodeItem(nid)
  155. nodeitem.setText(typ)
  156. nodeitem.setPos(item.x(), item.y())
  157. nodeitem.setFlag(QGraphicsItem.ItemIsSelectable, True)
  158. nodeitem.setFlag(QGraphicsItem.ItemIsMovable, True)
  159. self.removeItem(item)
  160. self.addItem(nodeitem)
  161. self._parent.populate_types()