123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- from enum import Enum
- from PyQt5.QtWidgets import QGraphicsScene, QGraphicsItem, QGraphicsLineItem, QGraphicsRectItem, \
- QGraphicsEllipseItem, QInputDialog
- from PyQt5.Qt import Qt, QPointF, QPen, QTransform
- from PyQt5.QtCore import pyqtSignal
- from sketchUI.graphics_edge_item import GraphicsEdgeItem
- from sketchUI.graphics_node_item import GraphicsNodeItem
- from sketchUI import mvops
- class Mode(Enum):
- SELECT = 0
- CONNECT = 1
- LINE = 2
- RECT = 3
- CIRCLE = 4
- FREE = 5
- class SketchScene(QGraphicsScene):
- def __init__(self, model, parent):
- 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._cur_model = model
- self._orig_point = QPointF()
- self._free_draw_lines = []
- self._parent = parent
- def set_mode(self, mode):
- self._mode = mode
- def _in_draw_mode(self):
- # are we in one of the draw modes? (rect, line, free, ...)
- if self._mode == Mode.CONNECT or self._mode == Mode.SELECT:
- return False
- return True
- def draw_edge(self, from_item, to_item, is_new):
- line = GraphicsEdgeItem(from_item, to_item)
- line.setFlag(QGraphicsItem.ItemIsMovable, False)
- line.setFlag(QGraphicsItem.ItemIsSelectable, False)
- self.addItem(line)
- line.redraw()
- if is_new:
- mvops.add_edge(self._cur_model, from_item.node_id, to_item.node_id)
- def mousePressEvent(self, event):
- if event.button() == Qt.LeftButton and self._in_draw_mode():
- # start drawing, save click point
- self._orig_point = event.scenePos()
- self._cur_drawing = True
- elif event.button() == Qt.LeftButton and self._mode == Mode.CONNECT:
- item = self.itemAt(event.scenePos(), QTransform())
- if not item:
- return
- self._from_item = item
- else:
- pass
- QGraphicsScene.mousePressEvent(self, event)
- def mouseMoveEvent(self, event):
- # if in freehand mode, draw lines from move movement
- if self._mode == Mode.FREE and self._cur_drawing:
- pt = event.scenePos()
- line = QGraphicsLineItem(self._orig_point.x(), self._orig_point.y(), pt.x(), pt.y())
- line.setPen(QPen(Qt.black, 2, Qt.SolidLine))
- self.addItem(line)
- self._orig_point = pt
- self._free_draw_lines.append(line)
- QGraphicsScene.mouseMoveEvent(self, event)
- def mouseReleaseEvent(self, event):
- if self._cur_drawing:
- end_point = event.scenePos()
- if self._mode == Mode.LINE:
- line = QGraphicsLineItem(self._orig_point.x(), self._orig_point.y(),
- end_point.x(), end_point.y())
- line.setPen(QPen(Qt.black, 2, Qt.SolidLine))
- self.addItem(line)
- elif self._mode == Mode.RECT:
- width = abs(end_point.x() - self._orig_point.x())
- height = abs(end_point.y() - self._orig_point.y())
- rect = QGraphicsRectItem(self._orig_point.x(), self._orig_point.y(),
- width, height)
- rect.setPen(QPen(Qt.black, 2, Qt.SolidLine))
- self.addItem(rect)
- elif self._mode == Mode.CIRCLE:
- width = abs(end_point.x() - self._orig_point.x())
- height = abs(end_point.y() - self._orig_point.y())
- ellipse = QGraphicsEllipseItem(self._orig_point.x(), self._orig_point.y(),
- width, height)
- ellipse.setPen(QPen(Qt.black, 2, Qt.SolidLine))
- self.addItem(ellipse)
- elif self._mode == Mode.FREE:
- line = QGraphicsLineItem(self._orig_point.x(), self._orig_point.y(),
- end_point.x(), end_point.y())
- line.setPen(QPen(Qt.black, 2, Qt.SolidLine))
- self.addItem(line)
- # group lines together
- self._free_draw_lines.append(line)
- group = self.createItemGroup(self._free_draw_lines)
- group.setFlag(QGraphicsItem.ItemIsSelectable, False)
- group.setFlag(QGraphicsItem.ItemIsMovable, False)
- del self._free_draw_lines[:]
- else:
- pass
- self._cur_drawing = False
- else:
- if self._mode == Mode.SELECT:
- item = self.itemAt(event.scenePos(), QTransform())
- if not item:
- return
- for item in self.items():
- try:
- item.__hack__() # hack to check if item is of edge type
- item.redraw()
- except AttributeError:
- continue
- elif self._mode == Mode.CONNECT:
- item = self.itemAt(event.scenePos(), QTransform())
- if not item:
- return
- self.draw_edge(self._from_item, item, is_new=True)
- else:
- pass
- QGraphicsScene.mouseReleaseEvent(self, event)
- def keyPressEvent(self, event):
- if not self._mode == Mode.SELECT:
- return
- # "del" deletes all selected items
- if event.key() == Qt.Key_Delete:
- for item in self.selectedItems():
- self.removeItem(item)
- # "G" groups selected items
- elif event.key() == Qt.Key_G:
- selected = self.selectedItems()
- self.clearSelection()
- group = self.createItemGroup(selected)
- bb_rect = QGraphicsRectItem(group.boundingRect())
- bb_rect.setPen(QPen(Qt.gray, 1, Qt.DashLine))
- group.addToGroup(bb_rect)
- group.setFlag(QGraphicsItem.ItemIsSelectable, True)
- group.setFlag(QGraphicsItem.ItemIsMovable, True)
- elif event.key() == Qt.Key_T:
- selected = self.selectedItems()
- if len(selected) != 1:
- return
- item = selected[0]
- # "T" lets the user type the selected item
- text, ok = QInputDialog.getText(self._parent, "Text input", "Enter type")
- if ok and text:
- print("Typing item {} to type {}".format(item, text))
- if text in mvops.get_available_types():
- print("Already such a type: {}".format(text))
- return
- self._type_item(item, text)
- else:
- QGraphicsScene.keyPressEvent(self, event)
- def _type_item(self, item, typ):
- # typing means elevating it to a real node
- nid = mvops.add_node(self._cur_model, typ)
- nodeitem = GraphicsNodeItem(nid)
- nodeitem.setText(typ)
- nodeitem.setPos(item.x(), item.y())
- nodeitem.setFlag(QGraphicsItem.ItemIsSelectable, True)
- nodeitem.setFlag(QGraphicsItem.ItemIsMovable, True)
- self.removeItem(item)
- self.addItem(nodeitem)
- self._parent.populate_types()
|