Пример #1
0
    def initUI(self):
        self.setGeometry(200, 200, 800, 800)
        self.layout = QVBoxLayout()
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(self.layout)

        self.scene = Scene()
        self.grScene = self.scene.grScene

        self.view = QDMGraphicsView(self.grScene, self)
        self.layout.addWidget(self.view)

        node1 = Node(self.scene, "First Node", inputs=[1, 1, 1],
                     outputs=[1])  # 数字代表 socket 类型, socket index 按数组顺序
        node2 = Node(self.scene, "Second Node", inputs=[1, 1, 1], outputs=[1])
        node3 = Node(self.scene, "Third Node", inputs=[1, 1, 1], outputs=[1])
        node1.setPos(-350, 100)
        node2.setPos(-75, 0)
        node3.setPos(200, -100)

        edge1 = Edge(self.scene, node1.outputs[0], node2.inputs[0],
                     EDGE_TYPE_BEZIER)
        edge2 = Edge(self.scene, node2.outputs[0], node3.inputs[1],
                     EDGE_TYPE_BEZIER)

        self.setWindowTitle("Node Editor")
        self.show()
Пример #2
0
    def addNodes(self):
        node1 = Node(self.scene,
                     "My Awesome Node 1",
                     inputs=[0, 0, 0],
                     outputs=[1])
        node2 = Node(self.scene,
                     "My Awesome Node 2",
                     inputs=[3, 3, 3],
                     outputs=[1])
        node3 = Node(self.scene,
                     "My Awesome Node 3",
                     inputs=[2, 2, 2],
                     outputs=[1])
        node1.setPos(-350, -250)
        node2.setPos(-75, 0)
        node3.setPos(200, -150)

        edge1 = Edge(self.scene,
                     node1.outputs[0],
                     node2.inputs[0],
                     edge_type=EDGE_TYPE_BEZIER)
        edge2 = Edge(self.scene,
                     node2.outputs[0],
                     node3.inputs[0],
                     edge_type=EDGE_TYPE_BEZIER)
Пример #3
0
 def edgeDragStart(self, item):
     print("Start drag edge")
     # self.dragEdge 是临时边
     self.previousEdge = item.socket.edge
     self.last_start_socket = item.socket
     self.dragEdge = Edge(self.grScene.scene, item.socket, None,
                          EDGE_TYPE_BEZIER)
Пример #4
0
 def edgeDragStart(self, item:'QGraphicsItem'):
     try:
         if DEBUG: print('View::edgeDragStart ~ Start dragging edge')
         if DEBUG: print('View::edgeDragStart ~   assign Start Socket to:', item.socket)
         self.drag_start_socket = item.socket
         self.drag_edge = Edge(self.grScene.scene, item.socket, None, EDGE_TYPE_BEZIER)
         if DEBUG: print('View::edgeDragStart ~   dragEdge:', self.drag_edge)
     except Exception as e: dumpException(e)
 def edgeDragStart(self, item):
     if DEBUG: print('View::edgeDragStart - Start Dragging edge')
     if DEBUG:
         print('View::edgeDragStart - assign Start Socket to:', item.socket)
     self.previousEdge = item.socket.edge
     self.last_start_socket = item.socket
     self.dragEdge = Edge(self.graphics_scene.scene, item.socket, None,
                          EDGE_TYPE_BEZIER)
     if DEBUG: print('View::edgeDragStart - dragEdge:', self.dragEdge)
    def addNodes(self):
        node1 = Node(self.scene, "Skeleton", inputs=[0], outputs=[1])
        node2 = Node(self.scene, "Muscle", inputs=[0], outputs=[1])
        node3 = Node(self.scene, "Fascia/Fat", inputs=[0], outputs=[1])
        node1.setPos(-350, -250)
        node2.setPos(-75, -0)
        node3.setPos(200, -150)

        edge1 = Edge(self.scene,
                     node1.outputs[0],
                     node2.inputs[0],
                     edgeType=EDGE_TYPE_BEZIER)
        edge2 = Edge(self.scene,
                     node2.outputs[0],
                     node3.inputs[0],
                     edgeType=EDGE_TYPE_BEZIER)
Пример #7
0
    def edgeDragEnd(self, item):
        """ return True if skip the rest of the code """
        self.mode = MODE_NOOP
        self.drag_edge.remove()
        self.drag_edge = None

        if type(item) is QDMGraphicsSocket:
            if item.socket != self.drag_start_socket:
                # if we released dragging on a socket (other then the beginning socket)

                # we wanna keep all the edges comming from target socket
                if not item.socket.is_multi_edges:
                    item.socket.removeAllEdges()

                # we wanna keep all the edges comming from start socket
                if not self.drag_start_socket.is_multi_edges:
                    self.drag_start_socket.removeAllEdges()

                new_edge = Edge(self.grScene.scene,
                                self.drag_start_socket,
                                item.socket,
                                edge_type=EDGE_TYPE_BEZIER)

            self.grScene.scene.history.storeHistory(
                "Created new edge by dragging", setModified=True)

            return True

        return False
Пример #8
0
 def addNodes(self):
     node1 = Node(self.scene, "Dataset Path", inputs=[0], outputs=[1])
     node2 = Node(self.scene, "Image Settings", inputs=[1], outputs=[1])
     node3 = Node(self.scene, "Train", inputs=[0], outputs=[1])
     node4 = Node(self.scene, "GPU", inputs=[0], outputs=[1])
     node5 = Node(self.scene, "Batch", inputs=[0], outputs=[1])
     node6 = Node(self.scene, "Dimensions", inputs=[0], outputs=[1])
     node7 = Node(self.scene,
                  "GAN",
                  inputs=[0, 1, 2, 3, 4, 5, 5, 5, 5, 7],
                  outputs=[2])
     node8 = Node(self.scene, "Start", inputs=[0], outputs=[0])
     node9 = Node(self.scene, "Output", inputs=[0], outputs=[1])
     node1.setPos(-450, -150)
     node2.setPos(-200, -150)
     node3.setPos(-450, 200)
     node4.setPos(-450, 350)
     node5.setPos(-450, 500)
     node6.setPos(-200, 200)
     node7.setPos(150, -150)
     node8.setPos(400, -150)
     node9.setPos(400, 250)
     edge1 = Edge(self.scene,
                  node1.outputs[0],
                  node2.inputs[0],
                  edge_type=EDGE_TYPE_BEZIER)
     edge2 = Edge(self.scene,
                  node2.outputs[0],
                  node7.inputs[0],
                  edge_type=EDGE_TYPE_BEZIER)
     edge3 = Edge(self.scene,
                  node3.outputs[0],
                  node7.inputs[1],
                  edge_type=EDGE_TYPE_BEZIER)
     edge4 = Edge(self.scene,
                  node4.outputs[0],
                  node7.inputs[2],
                  edge_type=EDGE_TYPE_BEZIER)
     edge5 = Edge(self.scene,
                  node5.outputs[0],
                  node7.inputs[3],
                  edge_type=EDGE_TYPE_BEZIER)
     edge6 = Edge(self.scene,
                  node6.outputs[0],
                  node7.inputs[4],
                  edge_type=EDGE_TYPE_BEZIER)
     edge7 = Edge(self.scene,
                  node7.outputs[0],
                  node8.inputs[0],
                  edge_type=EDGE_TYPE_BEZIER)
     edge8 = Edge(self.scene,
                  node7.outputs[0],
                  node9.inputs[0],
                  edge_type=EDGE_TYPE_BEZIER)
     self.scene.history.storeInitialHistoryStamp()
Пример #9
0
 def deserializeFromClipboard(self, data:dict):
     hashmap = {}
     view = self.scene.getView()
     mouse_scene_pos = view.last_scene_mouse_position
     minx, maxx, miny, maxy = 10000000,-10000000, 10000000,-10000000
     for node_data in data['nodes']:
         x, y = node_data['pos_x'], node_data['pos_y']
         if x < minx: minx = x
         if x > maxx: maxx = x
         if y < miny: miny = y
         if y > maxy: maxy = y
     maxx -= 180
     maxy += 100
     relbboxcenterx = (minx + maxx) / 2 - minx
     relbboxcentery = (miny + maxy) / 2 - miny
     if DEBUG_PASTING:
         print (" *** PASTA:")
         print("Copied boudaries:\n\tX:", minx, maxx, "   Y:", miny, maxy)
         print("\tbbox_center:", relbboxcenterx, relbboxcentery)
     mousex, mousey = mouse_scene_pos.x(), mouse_scene_pos.y()
     created_nodes = []
     self.scene.setSilentSelectionEvents()
     self.scene.doDeselectItems()
     for node_data in data['nodes']:
         new_node = self.scene.getNodeClassFromData(node_data)(self.scene)
         new_node.deserialize(node_data, hashmap, restore_id=False)
         created_nodes.append(new_node)
         posx, posy = new_node.pos.x(), new_node.pos.y()
         newx, newy = mousex + posx - minx, mousey + posy - miny
         new_node.setPos(newx, newy)
         new_node.doSelect()
         if DEBUG_PASTING:
             print("** PASTA SUM:")
             print("\tMouse pos:", mousex, mousey)
             print("\tnew node pos:", posx, posy)
             print("\tFINAL:", newx, newy)
     if 'edges' in data:
         for edge_data in data['edges']:
             new_edge = Edge(self.scene)
             new_edge.deserialize(edge_data, hashmap, restore_id=False)
     self.scene.setSilentSelectionEvents(False)
     self.scene.history.storeHistory("Pasted elements in scene", setModified=True)
     return created_nodes
    def deserializeFromClipboard(self, data):

        hashmap = {}

        # calculate mouse pointer - scene position
        view = self.scene.getView()
        mouse_scene_pos = view.last_scene_mouse_position

        # calculate selected objects bbox and center
        minx, maxx, miny, maxy = 0,0,0,0
        for node_data in data['nodes']:
            x, y = node_data['pos_x'], node_data['pos_y']
            if x < minx: minx = x
            if x > maxx: maxx = x
            if y < miny: miny = y
            if y > maxy: maxy = y
        bbox_center_x = (minx + maxx) / 2
        bbox_center_y = (miny + maxy) / 2

        # center = view.mapToScene(view.rect().center())

        # calculate tehe offset of the newly creating nodes
        offset_x = mouse_scene_pos.x() - bbox_center_x
        offset_y = mouse_scene_pos.y() - bbox_center_y

        # create each node
        for node_data in data['nodes']:
            new_node = self.scene.getNodeClassFromData(node_data)(self.scene)
            new_node.deserialize(node_data, hashmap, restore_id=False)

            # readjust the new node's position
            pos = new_node.pos
            new_node.setPos(pos.x() + offset_x, pos.y() + offset_y)

        # create each edge
        if 'edges' in data:
            for edge_data in data['edges']:
                new_edge = Edge(self.scene)
                new_edge.deserialize(edge_data, hashmap, restore_id=False)

        # store history
        self.scene.history.storeHistory("Pasted elements in scene", setModified = True)
Пример #11
0
    def addNodes(self):
        node1 = Node(self.scene,
                     "Monte Carlo Driver",
                     inputs=[1, 2, 3],
                     outputs=[4])
        node2 = Node(self.scene, "Dihedral Mutator", inputs=[3], outputs=[1])
        node3 = Node(self.scene, "Energy Function", inputs=[], outputs=[2])
        node1.setPos(200, -150)
        node2.setPos(-350, 0)
        node3.setPos(-75, -250)

        edge1 = Edge(self.scene,
                     node3.outputs[0],
                     node1.inputs[1],
                     edge_type=EDGE_TYPE_BEZIER)
        edge2 = Edge(self.scene,
                     node2.outputs[0],
                     node1.inputs[0],
                     edge_type=EDGE_TYPE_BEZIER)

        self.scene.history.storeInitialHistoryStamp()
Пример #12
0
    def deserialize(self, data, hashmap={}, restore_id=True):
        self.clear()
        hashmap = {}

        if restore_id: self.id = data['id']

        # create nodes
        for node_data in data['nodes']:
            self.getNodeClassFromData(node_data)(self).deserialize(
                node_data, hashmap, restore_id)

        # create edges
        for edge_data in data['edges']:
            Edge(self).deserialize(edge_data, hashmap, restore_id)

        return True
Пример #13
0
 def deserialize(self,
                 data: dict,
                 hashmap: dict = {},
                 restore_id: bool = True) -> bool:
     hashmap = {}
     if restore_id: self.id = data['id']
     all_nodes = self.nodes.copy()
     for node_data in data['nodes']:
         found = False
         for node in all_nodes:
             if node.id == node_data['id']:
                 found = node
                 break
         if not found:
             new_node = self.getNodeClassFromData(node_data)(self)
             new_node.deserialize(node_data, hashmap, restore_id)
             new_node.onDeserialized(node_data)
         else:
             found.deserialize(node_data, hashmap, restore_id)
             found.onDeserialized(node_data)
             all_nodes.remove(found)
     while all_nodes != []:
         node = all_nodes.pop()
         node.remove()
     all_edges = self.edges.copy()
     for edge_data in data['edges']:
         found = False
         for edge in all_edges:
             if edge.id == edge_data['id']:
                 found = edge
                 break
         if not found:
             new_edge = Edge(self).deserialize(edge_data, hashmap,
                                               restore_id)
         else:
             found.deserialize(edge_data, hashmap, restore_id)
             all_edges.remove(found)
     while all_edges != []:
         edge = all_edges.pop()
         edge.remove()
     return True
Пример #14
0
 def edgeDragEnd(self, item:'QGraphicsItem'):
     self.mode = MODE_NOOP
     if DEBUG: print('View::edgeDragEnd ~ End dragging edge')
     self.drag_edge.remove(silent=True)      
     self.drag_edge = None
     try:
         if isinstance(item, QDMGraphicsSocket):
             if item.socket != self.drag_start_socket:
                 for socket in (item.socket, self.drag_start_socket):
                     if not socket.is_multi_edges:
                         if socket.is_input:
                             socket.removeAllEdges(silent=True)
                         else:
                             socket.removeAllEdges(silent=False)
                 new_edge = Edge(self.grScene.scene, self.drag_start_socket, item.socket, edge_type=EDGE_TYPE_BEZIER)
                 if DEBUG: print("View::edgeDragEnd ~  created new edge:", new_edge, "connecting", new_edge.start_socket, "<-->", new_edge.end_socket)
                 for socket in [self.drag_start_socket, item.socket]:
                     socket.node.onEdgeConnectionChanged(new_edge)
                     if socket.is_input: socket.node.onInputChanged(socket)
                 self.grScene.scene.history.storeHistory("Created new edge by dragging", setModified=True)
                 return True
     except Exception as e: dumpException(e)
     if DEBUG: print('View::edgeDragEnd ~ everything done.')
     return False
Пример #15
0
class QDMGraphicsView(QGraphicsView):
    scenePosChanged = pyqtSignal(int, int)
    def __init__(self, grScene:'QDMGraphicsScene', parent:'QWidget'=None):
        super().__init__(parent)
        self.grScene = grScene
        self.initUI()
        self.setScene(self.grScene)
        self.mode = MODE_NOOP
        self.editingFlag = False
        self.rubberBandDraggingRectangle = False
        self.last_scene_mouse_position = QPoint(0,0)
        self.zoomInFactor = 1.25
        self.zoomClamp = True
        self.zoom = 10
        self.zoomStep = 1
        self.zoomRange = [0, 10]
        self.cutline = QDMCutLine()
        self.grScene.addItem(self.cutline)
        self._drag_enter_listeners = []
        self._drop_listeners = []
    def initUI(self):
        self.setRenderHints(QPainter.Antialiasing | QPainter.HighQualityAntialiasing | QPainter.TextAntialiasing | QPainter.SmoothPixmapTransform)
        self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        self.setDragMode(QGraphicsView.RubberBandDrag)
        self.setAcceptDrops(True)
    def dragEnterEvent(self, event:QDragEnterEvent):
        for callback in self._drag_enter_listeners: callback(event)
    def dropEvent(self, event:QDropEvent):
        for callback in self._drop_listeners: callback(event)
    def addDragEnterListener(self, callback:'function'):
        self._drag_enter_listeners.append(callback)
    def addDropListener(self, callback:'function'):
        self._drop_listeners.append(callback)
    def mousePressEvent(self, event:QMouseEvent):
        if event.button() == Qt.MiddleButton:
            self.middleMouseButtonPress(event)
        elif event.button() == Qt.LeftButton:
            self.leftMouseButtonPress(event)
        elif event.button() == Qt.RightButton:
            self.rightMouseButtonPress(event)
        else:
            super().mousePressEvent(event)
    def mouseReleaseEvent(self, event:QMouseEvent):
        if event.button() == Qt.MiddleButton:
            self.middleMouseButtonRelease(event)
        elif event.button() == Qt.LeftButton:
            self.leftMouseButtonRelease(event)
        elif event.button() == Qt.RightButton:
            self.rightMouseButtonRelease(event)
        else:
            super().mouseReleaseEvent(event)
    def middleMouseButtonPress(self, event:QMouseEvent):
        item = self.getItemAtClick(event)
        if DEBUG_MMB_SCENE_ITEMS:
            if isinstance(item, QDMGraphicsEdge):
                print("MMB DEBUG:", item.edge,"\n\t", item.edge.grEdge if item.edge.grEdge is not None else None)
            if isinstance(item, QDMGraphicsSocket):
                print("MMB DEBUG:", item.socket, "socket_type:", item.socket.socket_type,
                      "has edges:", "no" if item.socket.edges == [] else "")
                if item.socket.edges:
                    for edge in item.socket.edges: print("\t", edge)
        if DEBUG_MMB_SCENE_ITEMS and (item is None):
            print("SCENE:")
            print("  Nodes:")
            for node in self.grScene.scene.nodes: print("\t", node)
            print("  Edges:")
            for edge in self.grScene.scene.edges: print("\t", edge, "\n\t\tgrEdge:", edge.grEdge if edge.grEdge is not None else None)
            if event.modifiers() & Qt.CTRL:
                print("  Graphic Items in GraphicScene:")
                for item in self.grScene.items():
                    print('    ', item)
        releaseEvent = QMouseEvent(QEvent.MouseButtonRelease, event.localPos(), event.screenPos(),
                                   Qt.LeftButton, Qt.NoButton, event.modifiers())
        super().mouseReleaseEvent(releaseEvent)
        self.setDragMode(QGraphicsView.ScrollHandDrag)
        fakeEvent = QMouseEvent(event.type(), event.localPos(), event.screenPos(),
                                Qt.LeftButton, event.buttons() | Qt.LeftButton, event.modifiers())
        super().mousePressEvent(fakeEvent)
    def middleMouseButtonRelease(self, event:QMouseEvent):
        fakeEvent = QMouseEvent(event.type(), event.localPos(), event.screenPos(),
                                Qt.LeftButton, event.buttons() & ~Qt.LeftButton, event.modifiers())
        super().mouseReleaseEvent(fakeEvent)
        self.setDragMode(QGraphicsView.RubberBandDrag)
    def leftMouseButtonPress(self, event:QMouseEvent):
        item = self.getItemAtClick(event)
        self.last_lmb_click_scene_pos = self.mapToScene(event.pos())
        if hasattr(item, "node") or isinstance(item, QDMGraphicsEdge) or item is None:
            if event.modifiers() & Qt.ShiftModifier:
                event.ignore()
                fakeEvent = QMouseEvent(QEvent.MouseButtonPress, event.localPos(), event.screenPos(),
                                        Qt.LeftButton, event.buttons() | Qt.LeftButton,
                                        event.modifiers() | Qt.ControlModifier)
                super().mousePressEvent(fakeEvent)
                return
        if isinstance(item, QDMGraphicsSocket):
            if self.mode == MODE_NOOP:
                self.mode = MODE_EDGE_DRAG
                self.edgeDragStart(item)
                return
        if self.mode == MODE_EDGE_DRAG:
            res = self.edgeDragEnd(item)
            if res: return
        if item is None:
            if event.modifiers() & Qt.ControlModifier:
                self.mode = MODE_EDGE_CUT
                fakeEvent = QMouseEvent(QEvent.MouseButtonRelease, event.localPos(), event.screenPos(),
                                        Qt.LeftButton, Qt.NoButton, event.modifiers())
                super().mouseReleaseEvent(fakeEvent)
                QApplication.setOverrideCursor(Qt.CrossCursor)
                return
            else:
                self.rubberBandDraggingRectangle = True
        super().mousePressEvent(event)
    def leftMouseButtonRelease(self, event:QMouseEvent):
        item = self.getItemAtClick(event)
        try:
            if hasattr(item, "node") or isinstance(item, QDMGraphicsEdge) or item is None:
                if event.modifiers() & Qt.ShiftModifier:
                    event.ignore()
                    fakeEvent = QMouseEvent(event.type(), event.localPos(), event.screenPos(),
                                            Qt.LeftButton, Qt.NoButton,
                                            event.modifiers() | Qt.ControlModifier)
                    super().mouseReleaseEvent(fakeEvent)
                    return
            if self.mode == MODE_EDGE_DRAG:
                if self.distanceBetweenClickAndReleaseIsOff(event):
                    res = self.edgeDragEnd(item)
                    if res: return
            if self.mode == MODE_EDGE_CUT:
                self.cutIntersectingEdges()
                self.cutline.line_points = []
                self.cutline.update()
                QApplication.setOverrideCursor(Qt.ArrowCursor)
                self.mode = MODE_NOOP
                return
            if self.rubberBandDraggingRectangle:
                self.rubberBandDraggingRectangle = False
                current_selected_items = self.grScene.selectedItems()
                if current_selected_items != self.grScene.scene._last_selected_items:
                    if current_selected_items == []:
                        self.grScene.itemsDeselected.emit()
                    else:
                        self.grScene.itemSelected.emit()
                    self.grScene.scene._last_selected_items = current_selected_items
                return
            if item is None:
                self.grScene.itemsDeselected.emit()
        except: dumpException()
        super().mouseReleaseEvent(event)
    def rightMouseButtonPress(self, event:QMouseEvent):
        super().mousePressEvent(event)
    def rightMouseButtonRelease(self, event:QMouseEvent):
        super().mouseReleaseEvent(event)
    def mouseMoveEvent(self, event:QMouseEvent):
        scenepos = self.mapToScene(event.pos())
        if self.mode == MODE_EDGE_DRAG:
            if self.drag_edge is not None and self.drag_edge.grEdge is not None:
                self.drag_edge.grEdge.setDestination(scenepos.x(), scenepos.y())
                self.drag_edge.grEdge.update()
            else:
                print(">>> Want to update self.drag_edge grEdge, but it's None!!!")
        if self.mode == MODE_EDGE_CUT and self.cutline is not None:
            self.cutline.line_points.append(scenepos)
            self.cutline.update()
        self.last_scene_mouse_position = scenepos
        self.scenePosChanged.emit( int(scenepos.x()), int(scenepos.y()) )
        super().mouseMoveEvent(event)
    def keyPressEvent(self, event:QKeyEvent):
        super().keyPressEvent(event)
    def cutIntersectingEdges(self):
        for ix in range(len(self.cutline.line_points) - 1):
            p1 = self.cutline.line_points[ix]
            p2 = self.cutline.line_points[ix + 1]
            for edge in self.grScene.scene.edges:
                if edge.grEdge.intersectsWith(p1, p2):
                    edge.remove()
        self.grScene.scene.history.storeHistory("Delete cutted edges", setModified=True)
    def deleteSelected(self):
        for item in self.grScene.selectedItems():
            if isinstance(item, QDMGraphicsEdge):
                item.edge.remove()
            elif hasattr(item, 'node'):
                item.node.remove()
        self.grScene.scene.history.storeHistory("Delete selected", setModified=True)
    def debug_modifiers(self, event):
        out = "MODS: "
        if event.modifiers() & Qt.ShiftModifier: out += "SHIFT "
        if event.modifiers() & Qt.ControlModifier: out += "CTRL "
        if event.modifiers() & Qt.AltModifier: out += "ALT "
        return out
    def getItemAtClick(self, event:QEvent) -> 'QGraphicsItem':
        pos = event.pos()
        obj = self.itemAt(pos)
        return obj
    def edgeDragStart(self, item:'QGraphicsItem'):
        try:
            if DEBUG: print('View::edgeDragStart ~ Start dragging edge')
            if DEBUG: print('View::edgeDragStart ~   assign Start Socket to:', item.socket)
            self.drag_start_socket = item.socket
            self.drag_edge = Edge(self.grScene.scene, item.socket, None, EDGE_TYPE_BEZIER)
            if DEBUG: print('View::edgeDragStart ~   dragEdge:', self.drag_edge)
        except Exception as e: dumpException(e)
    def edgeDragEnd(self, item:'QGraphicsItem'):
        self.mode = MODE_NOOP
        if DEBUG: print('View::edgeDragEnd ~ End dragging edge')
        self.drag_edge.remove(silent=True)      
        self.drag_edge = None
        try:
            if isinstance(item, QDMGraphicsSocket):
                if item.socket != self.drag_start_socket:
                    for socket in (item.socket, self.drag_start_socket):
                        if not socket.is_multi_edges:
                            if socket.is_input:
                                socket.removeAllEdges(silent=True)
                            else:
                                socket.removeAllEdges(silent=False)
                    new_edge = Edge(self.grScene.scene, self.drag_start_socket, item.socket, edge_type=EDGE_TYPE_BEZIER)
                    if DEBUG: print("View::edgeDragEnd ~  created new edge:", new_edge, "connecting", new_edge.start_socket, "<-->", new_edge.end_socket)
                    for socket in [self.drag_start_socket, item.socket]:
                        socket.node.onEdgeConnectionChanged(new_edge)
                        if socket.is_input: socket.node.onInputChanged(socket)
                    self.grScene.scene.history.storeHistory("Created new edge by dragging", setModified=True)
                    return True
        except Exception as e: dumpException(e)
        if DEBUG: print('View::edgeDragEnd ~ everything done.')
        return False
    def distanceBetweenClickAndReleaseIsOff(self, event:QMouseEvent) -> bool:
        new_lmb_release_scene_pos = self.mapToScene(event.pos())
        dist_scene = new_lmb_release_scene_pos - self.last_lmb_click_scene_pos
        edge_drag_threshold_sq = EDGE_DRAG_START_THRESHOLD*EDGE_DRAG_START_THRESHOLD
        return (dist_scene.x()*dist_scene.x() + dist_scene.y()*dist_scene.y()) > edge_drag_threshold_sq
    def wheelEvent(self, event:QWheelEvent):
        zoomOutFactor = 1 / self.zoomInFactor
        if event.angleDelta().y() > 0:
            zoomFactor = self.zoomInFactor
            self.zoom += self.zoomStep
        else:
            zoomFactor = zoomOutFactor
            self.zoom -= self.zoomStep
        clamped = False
        if self.zoom < self.zoomRange[0]: self.zoom, clamped = self.zoomRange[0], True
        if self.zoom > self.zoomRange[1]: self.zoom, clamped = self.zoomRange[1], True
        if not clamped or self.zoomClamp is False:
            self.scale(zoomFactor, zoomFactor)
class ShotGraphicsView(QGraphicsView):
    def __init__(self, graphics_scene, parent=None):
        super().__init__(parent)

        self.graphics_scene = graphics_scene
        self.__init_ui__()
        self.setScene(self.graphics_scene)

        self.mode = MODE_NOOPERATION

        self.zoomInFactor = 1.25
        self.zoomClamp = True
        self.zoom = 10
        self.zoomStep = 1
        self.zoomRange = [0, 15]

    def __init_ui__(self):
        self.setRenderHints(QPainter.Antialiasing
                            | QPainter.HighQualityAntialiasing
                            | QPainter.TextAntialiasing
                            | QPainter.SmoothPixmapTransform)

        self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)

        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        self.setDragMode(QGraphicsView.RubberBandDrag)

    def mousePressEvent(self, event):
        if event.button() == Qt.MiddleButton:
            self.middleMouseButtonPress(event)
        elif event.button() == Qt.LeftButton:
            self.leftMouseButtonPress(event)
        elif event.button() == Qt.RightButton:
            self.rightMouseButtonPress(event)
        else:
            super().mousePressEvent(event)

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.MiddleButton:
            self.middleMouseButtonRelease(event)
        elif event.button() == Qt.LeftButton:
            self.leftMouseButtonRelease(event)
        elif event.button() == Qt.RightButton:
            self.rightMouseButtonRelease(event)
        else:
            super().mouseReleaseEvent(event)

    def middleMouseButtonPress(self, event):
        releaseEvent = QMouseEvent(QEvent.MouseButtonRelease, event.localPos(),
                                   event.screenPos(), Qt.LeftButton,
                                   Qt.NoButton, event.modifiers())
        super().mouseReleaseEvent(releaseEvent)
        self.setDragMode(QGraphicsView.ScrollHandDrag)
        fakeEvent = QMouseEvent(event.type(), event.localPos(),
                                event.screenPos(), Qt.LeftButton,
                                event.buttons() | Qt.LeftButton,
                                event.modifiers())
        super().mousePressEvent(fakeEvent)

    def middleMouseButtonRelease(self, event):
        fakeEvent = QMouseEvent(event.type(), event.localPos(),
                                event.screenPos(), Qt.LeftButton,
                                event.buttons() & Qt.LeftButton,
                                event.modifiers())
        super().mouseReleaseEvent(fakeEvent)
        self.setDragMode(QGraphicsView.NoDrag)

    def leftMouseButtonPress(self, event):
        item = self.getItemAtClick(event)

        self.last_lmb_click_scene_pos = self.mapToScene(event.pos())

        if DEBUG: print("LMB Click on", item, self.debug_modifiers(event))

        if hasattr(item, "node") or isinstance(
                item, NodeGraphicsEdge) or item is None:
            if event.modifiers() & Qt.ShiftModifier:
                event.ignore()
                fakeEvent = QMouseEvent(QEvent.MouseButtonPress,
                                        event.localPos(), event.screenPos(),
                                        Qt.LeftButton,
                                        event.buttons() | Qt.LeftButton,
                                        event.modifiers() | Qt.ControlModifier)
                super().mousePressEvent(fakeEvent)
                return

        if type(item) is NodeGraphicsSocket:
            if self.mode == MODE_NOOPERATION:
                self.mode = MODE_EDGE_DRAG
                self.edgeDragStart(item)
                return

        if self.mode == MODE_EDGE_DRAG:
            res = self.edgeDragEnd(item)
            if res: return

        super().mousePressEvent(event)

    def leftMouseButtonRelease(self, event):

        item = self.getItemAtClick(event)

        if hasattr(item, "node") or isinstance(
                item, NodeGraphicsEdge) or item is None:
            if event.modifiers() & Qt.ShiftModifier:
                if DEBUG: print("LMB Release + Shift on", item)
                event.ignore()
                fakeEvent = QMouseEvent(event.type(), event.localPos(),
                                        event.screenPos(), Qt.LeftButton,
                                        Qt.NoButton,
                                        event.modifiers() | Qt.ControlModifier)
                super().mouseReleaseEvent(fakeEvent)
                return

        if self.mode == MODE_EDGE_DRAG:
            self.distanceBetweenClickAndReleaseIsOff(event)
            if self.distanceBetweenClickAndReleaseIsOff:
                res = self.edgeDragEnd(item)
                if res: return

        super().mouseReleaseEvent(event)

    def rightMouseButtonPress(self, event):
        super().mousePressEvent(event)

        item = self.getItemAtClick(event)

    def rightMouseButtonRelease(self, event):
        super().mouseReleaseEvent(event)

    def mouseMoveEvent(self, event):
        if self.mode == MODE_EDGE_DRAG:
            pos = self.mapToScene(event.pos())
            self.dragEdge.graphic_edge.setDestination(pos.x(), pos.y())
            self.dragEdge.graphic_edge.update()

        super().mouseMoveEvent(event)

    def keyPressEvent(self, event):

        if event.key() == Qt.Key_Delete:
            self.deleteSelected()
        else:
            super().keyPressEvent(event)

    def deleteSelected(self):
        for item in self.graphics_scene.selectedItems():
            if isinstance(item, NodeGraphicsEdge):
                item.edge.remove()
            elif hasattr(item, 'node'):
                item.node.remove()

    def debug_modifiers(self, event):
        out = "MODS: "
        if event.modifiers() & Qt.ShiftModifier: out += "SHIFT "
        if event.modifiers() & Qt.ControlModifier: out += "CTRL "
        if event.modifiers() & Qt.AltModifier: out += "ATL "
        return out

    def getItemAtClick(self, event):
        pos = event.pos()
        obj = self.itemAt(pos)
        return obj

    def edgeDragStart(self, item):
        if DEBUG: print('View::edgeDragStart - Start Dragging edge')
        if DEBUG:
            print('View::edgeDragStart - assign Start Socket to:', item.socket)
        self.previousEdge = item.socket.edge
        self.last_start_socket = item.socket
        self.dragEdge = Edge(self.graphics_scene.scene, item.socket, None,
                             EDGE_TYPE_BEZIER)
        if DEBUG: print('View::edgeDragStart - dragEdge:', self.dragEdge)

    def edgeDragEnd(self, item):
        self.mode = MODE_NOOPERATION

        if type(item) is NodeGraphicsSocket:
            if item.socket != self.last_start_socket:
                if DEBUG:
                    print('View::edgeDragEnd - previous edge',
                          self.previousEdge)
                if item.socket.hasEdge():
                    item.socket.edge.remove()

                if DEBUG:
                    print('View::edgeDragEnd - End Dragging edge', item.socket)
                if self.previousEdge is not None: self.previousEdge.remove()
                if DEBUG: print('View::edgeDragEnd - previous edge removed')
                self.dragEdge.start_socket = self.last_start_socket
                self.dragEdge.end_socket = item.socket
                self.dragEdge.start_socket.setConnectedEdge(self.dragEdge)
                self.dragEdge.end_socket.setConnectedEdge(self.dragEdge)
                if DEBUG:
                    print(
                        'View::edgeDragEnd - reassigned start & end sockets to drag edge'
                    )
                self.dragEdge.updatePositions()
                return True

        if DEBUG: print('View::edgeDragEnd - End dragging edge')
        self.dragEdge.remove()
        self.dragEdge = None
        if DEBUG:
            print('View::edgeDragEnd - about to set socket to previous edge:',
                  self.previousEdge)
        if self.previousEdge is not None:
            self.previousEdge.start_socket.edge = self.previousEdge
        if DEBUG: print('View::edgeDragEnd - everything done')

    def distanceBetweenClickAndReleaseIsOff(self, event):
        new_lmb_release_scene_pos = self.mapToScene(event.pos())
        dist_scene = new_lmb_release_scene_pos - self.last_lmb_click_scene_pos
        edge_drag_threshold_sq = EDGE_DRAG_START_THRESHOLD * EDGE_DRAG_START_THRESHOLD
        return (dist_scene.x() * dist_scene.x() +
                dist_scene.y() * dist_scene.y()) > edge_drag_threshold_sq

    def wheelEvent(self, event):
        # calculate our zoom Factor
        zoomOutFactor = 1 / self.zoomInFactor

        # calculate zoom
        if event.angleDelta().y() > 0:
            zoomFactor = self.zoomInFactor
            self.zoom += self.zoomStep
        else:
            zoomFactor = zoomOutFactor
            self.zoom -= self.zoomStep

        clamped = False
        if self.zoom < self.zoomRange[0]:
            self.zoom, clamped = self.zoomRange[0], True
        if self.zoom > self.zoomRange[1]:
            self.zoom, clamped = self.zoomRange[1], True

        # set scene scale
        if not clamped or self.zoomClamp is False:
            self.scale(zoomFactor, zoomFactor)
Пример #17
0
 def edgeDragStart(self, item):
     self.drag_start_socket = item.socket
     self.drag_edge = Edge(self.grScene.scene, item.socket, None,
                           EDGE_TYPE_BEZIER)
Пример #18
0
class QDMGraphicsView(QGraphicsView):
    def __init__(self, grScene, parent=None):
        super().__init__(parent)
        self.grScene = grScene

        self.initUI()
        self.setScene(grScene)

        self.mode = MODE_NOOP

        self.zoonInFactor = 1.25
        self.zoomClamp = False  # Useless
        self.zoom = 10
        self.zoomStep = 1
        self.zoomRange = [0, 10]

    def initUI(self):
        self.setRenderHints(QPainter.Antialiasing
                            | QPainter.HighQualityAntialiasing
                            | QPainter.TextAntialiasing
                            | QPainter.SmoothPixmapTransform)

        self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)

        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)

    def mousePressEvent(self, event):
        if event.button() == Qt.MiddleButton:
            self.middleMouseButtonPress(event)
        elif event.button() == Qt.LeftButton:
            self.leftMouseButtonPress(event)
        elif event.button() == Qt.RightButton:
            self.rightMouseButtonPress(event)
        else:
            super().mousePressEvent(event)

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.MiddleButton:
            self.middleMouseButtonRelease(event)
        elif event.button() == Qt.LeftButton:
            self.leftMouseButtonRelease(event)
        elif event.button() == Qt.RightButton:
            self.rightMouseButtonRelease(event)
        else:
            super().mouseReleaseEvent(event)

    def middleMouseButtonPress(self, event):
        # 中键拖动面板
        # 先释放左键
        releaseEvent = QMouseEvent(QEvent.MouseButtonRelease, event.localPos(),
                                   event.screenPos(), Qt.LeftButton,
                                   Qt.NoButton, event.modifiers())
        super().mouseReleaseEvent(releaseEvent)
        self.setDragMode(QGraphicsView.ScrollHandDrag)
        fakeEvent = QMouseEvent(event.type(), event.localPos(),
                                event.screenPos(), Qt.LeftButton,
                                event.buttons() | Qt.LeftButton,
                                event.modifiers())
        super().mousePressEvent(fakeEvent)

    def middleMouseButtonRelease(self, event):
        fakeEvent = QMouseEvent(event.type(), event.localPos(),
                                event.screenPos(), Qt.LeftButton,
                                event.buttons() & -Qt.LeftButton,
                                event.modifiers())
        super().mouseReleaseEvent(fakeEvent)
        self.setDragMode(QGraphicsView.NoDrag)

    def edgeDragStart(self, item):
        print("Start drag edge")
        # self.dragEdge 是临时边
        self.previousEdge = item.socket.edge
        self.last_start_socket = item.socket
        self.dragEdge = Edge(self.grScene.scene, item.socket, None,
                             EDGE_TYPE_BEZIER)

    def edgeDragEnd(self, item):
        self.mode = MODE_NOOP
        print("End drag edge")
        if type(item) is QDMGraphicsSocket:
            print("Assign End socket")
            if item.socket.hasEdge():
                self.tempEdge = item.socket.edge
                item.socket.edge.remove()
                print(self.tempEdge != self.previousEdge)
            if self.previousEdge is not None and self.tempEdge != self.previousEdge:
                # 可能重复连接,是同一条边,那就不要remove两次
                self.previousEdge.remove()
            self.tempEdge = None
            self.dragEdge.end_socket = item.socket
            self.dragEdge.start_socket.setConnectedEdge(self.dragEdge)
            self.dragEdge.end_socket.setConnectedEdge(self.dragEdge)
            self.dragEdge.updatePositions()
            return True

        self.dragEdge.remove()  # 清理 grEdge 和当前 edge
        self.dragEdge = None
        if self.previousEdge is not None:
            self.previousEdge.start_socket.edge = self.previousEdge
            # 在 edgeDragStart 生成新的 Edge 时修改了 start_socket.edge,需要恢复
        return False

    def distanceBetweenClickAndReleaseIsOff(self, event):
        new_lmb_release_scene_pos = self.mapToScene(
            event.pos())  # 用来和 MousePress 时对比判断鼠标移动距离
        dist_scene_pos = new_lmb_release_scene_pos - self.last_lmb_click_scene_pos
        dist_scene_pos_len = dist_scene_pos.x() * dist_scene_pos.x(
        ) + dist_scene_pos.y() * dist_scene_pos.y()
        return dist_scene_pos_len > EDGE_DRAG_START_THRESHOLD * EDGE_DRAG_START_THRESHOLD

    def leftMouseButtonPress(self, event):

        item = self.getItemAtClick(event)

        self.last_lmb_click_scene_pos = self.mapToScene(event.pos())

        # 单击 socket 开始生成一条新的边
        # 进入 EDGE_DRAG 模式
        if type(item) is QDMGraphicsSocket:
            if self.mode == MODE_NOOP:
                self.mode = MODE_EDGE_DRAG
                self.edgeDragStart(item)
                return

        # 在 EDGE_DRAG 模式下单击左键退出模式,如果终点是socket,就把边放上去
        if self.mode == MODE_EDGE_DRAG:
            if self.edgeDragEnd(item):
                return

        super().mousePressEvent(event)

    def leftMouseButtonRelease(self, event):
        item = self.getItemAtClick(event)

        # 如果在 EDGE_DRAG 模式下,抬起左键时,如果在 socket 上就生成新的连接
        if self.mode == MODE_EDGE_DRAG:
            if self.distanceBetweenClickAndReleaseIsOff(event):
                # 只有鼠标移出一段距离才会assign socket,防止连到自己
                print("ReleaseOff")
                if self.edgeDragEnd(item):
                    return
            print("No ReleaseOff")

        super().mouseReleaseEvent(event)

    def rightMouseButtonPress(self, event):
        super().mousePressEvent(event)

    def rightMouseButtonRelease(self, event):
        super().mouseReleaseEvent(event)

    def mouseMoveEvent(self, event):
        if self.mode == MODE_EDGE_DRAG:
            pos = self.mapToScene(event.pos())
            self.dragEdge.grEdge.setDestination(pos.x(), pos.y())
            self.dragEdge.grEdge.update()  # redraw

        super().mouseMoveEvent(event)

    def wheelEvent(self, event):
        # 滚轮缩放整体面板
        zoomOutFactor = 1. / self.zoonInFactor
        oldPos = self.mapToScene(event.pos())
        if event.angleDelta().y() > 0:
            zoomFactor = self.zoonInFactor
            self.zoom += self.zoomStep
        else:
            zoomFactor = zoomOutFactor
            self.zoom -= self.zoomStep

        if self.zoom < self.zoomRange[0]:
            self.zoom = self.zoomRange[0]
            zoomFactor = 1.0
        elif self.zoom > self.zoomRange[1]:
            self.zoom = self.zoomRange[1]
            zoomFactor = 1.0

        self.scale(zoomFactor, zoomFactor)

    def getItemAtClick(self, event):
        pos = event.pos()
        obj = self.itemAt(pos)
        return obj
Пример #19
0
class QDMGraphicsView(QGraphicsView):
    def __init__(self, grScene, parent=None):
        super().__init__(parent)
        self.grScene = grScene

        self.initUI()

        self.setScene(self.grScene)

        self.mode = MODE_NOOP
        self.editingFlag = False

        self.zoomInFactor = 1.25
        self.zoomClamp = True
        self.zoom = 10
        self.zoomStep = 1
        self.zoomRange = [0, 10]
        # cutline
        self.cutline = QDMCutLine()
        self.grScene.addItem(self.cutline)

    def initUI(self):
        """ smooth out the Pixels in the Lines, Text etc. """
        self.setRenderHints(QPainter.Antialiasing
                            | QPainter.HighQualityAntialiasing
                            | QPainter.TextAntialiasing
                            | QPainter.SmoothPixmapTransform)

        self.setViewportUpdateMode(
            QGraphicsView.FullViewportUpdate
        )  # Fix the problem that the Lines under the Rect getting smaller
        # hide scrollbar
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        # set the Center under the Mouse for scrolling in/out
        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        self.setDragMode(QGraphicsView.RubberBandDrag)

    def mousePressEvent(self, event):
        if event.button() == Qt.MiddleButton:
            self.middleMouseButtonPress(event)
        elif event.button() == Qt.LeftButton:
            self.leftMouseButtonPress(event)
        elif event.button() == Qt.RightButton:
            self.rightMouseButtonPress(event)
        else:
            super().mousePressEvent(event)

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.MiddleButton:
            self.middleMouseButtonRelease(event)
        elif event.button() == Qt.LeftButton:
            self.leftMouseButtonRelease(event)
        elif event.button() == Qt.RightButton:
            self.rightMouseButtonRelease(event)
        else:
            super().mouseReleaseEvent(event)

    """ Drag around """

    def middleMouseButtonPress(self, event):
        releaseEvent = QMouseEvent(QEvent.MouseButtonRelease, event.localPos(),
                                   event.screenPos(), Qt.LeftButton,
                                   Qt.NoButton, event.modifiers())
        super().mouseReleaseEvent(releaseEvent)
        self.setDragMode(QGraphicsView.ScrollHandDrag)
        fakeEvent = QMouseEvent(event.type(), event.localPos(),
                                event.screenPos(), Qt.LeftButton,
                                event.buttons() | Qt.LeftButton,
                                event.modifiers())
        super().mousePressEvent(fakeEvent)

    def middleMouseButtonRelease(self, event):
        fakeEvent = QMouseEvent(event.type(), event.localPos(),
                                event.screenPos(), Qt.LeftButton,
                                event.buttons() & ~Qt.LeftButton,
                                event.modifiers())
        super().mouseReleaseEvent(fakeEvent)
        self.setDragMode(QGraphicsView.NoDrag)

    def leftMouseButtonPress(self, event):
        # get item which we clicked on
        item = self.getItemAtClick(event)

        # we store the position of last LMB click
        self.last_lmb_click_scene_pos = self.mapToScene(event.pos())

        if DEBUG: print("LMB Click on", item, self.debug_modifiers(event))

        # logic
        if hasattr(item, "node") or isinstance(
                item, QDMGraphicsEdge) or item is None:
            if event.modifiers() & Qt.ShiftModifier:
                if DEBUG: print("LMB + Shift on", item)
                event.ignore()
                fakeEvent = QMouseEvent(QEvent.MouseButtonPress,
                                        event.localPos(), event.screenPos(),
                                        Qt.LeftButton,
                                        event.buttons() | Qt.LeftButton,
                                        event.modifiers() | Qt.ControlModifier)
                super().mousePressEvent(fakeEvent)
                return

        if type(item) is QDMGraphicsSocket:
            if self.mode == MODE_NOOP:
                self.mode = MODE_EDGE_DRAG
                self.edgeDragStart(item)
                return

        if self.mode == MODE_EDGE_DRAG:
            res = self.edgeDragEnd(item)
            if res: return

        if item is None:
            if event.modifiers() & Qt.ControlModifier:
                self.mode = MODE_EDGE_CUT
                fakeEvent = QMouseEvent(QEvent.MouseButtonRelease,
                                        event.localPos(), event.screenPos(),
                                        Qt.LeftButton, Qt.NoButton,
                                        event.modifiers())
                super().mouseReleaseEvent(fakeEvent)
                QApplication.setOverrideCursor(Qt.CrossCursor)
                return

        super().mousePressEvent(event)

    def leftMouseButtonRelease(self, event):
        # get item which we release mouse button on
        item = self.getItemAtClick(event)

        # logic
        if hasattr(item, "node") or isinstance(
                item, QDMGraphicsEdge) or item is None:
            if event.modifiers() & Qt.ShiftModifier:
                event.ignore()
                fakeEvent = QMouseEvent(event.type(), event.localPos(),
                                        event.screenPos(), Qt.LeftButton,
                                        Qt.NoButton,
                                        event.modifiers() | Qt.ControlModifier)
                super().mouseReleaseEvent(fakeEvent)
                return

        if self.mode == MODE_EDGE_DRAG:
            if self.distanceBetweenClickAndReleaseIsOff(event):
                res = self.edgeDragEnd(item)
                if res: return

        if self.mode == MODE_EDGE_CUT:
            self.cutIntersectingEdges()
            self.cutline.line_points = []
            self.cutline.update()
            QApplication.setOverrideCursor(Qt.ArrowCursor)
            self.mode = MODE_NOOP
            return

        super().mouseReleaseEvent(event)

    def rightMouseButtonPress(self, event):
        super().mousePressEvent(event)

        item = self.getItemAtClick(event)

        if DEBUG:
            if isinstance(item, QDMGraphicsEdge):
                print('RMB DEBUG:', item.edge, ' connecting sockets:',
                      item.edge.start_socket, '<-->', item.edge.end_socket)
            if type(item) is QDMGraphicsSocket:
                print('RMB DEBUG:', item.socket, 'has edge:', item.socket.edge)

            if item is None:
                print('SCENE:')
                print('  Nodes:')
                for node in self.grScene.scene.nodes:
                    print('    ', node)
                print('  Edges:')
                for edge in self.grScene.scene.edges:
                    print('    ', edge)

    def rightMouseButtonRelease(self, event):
        super().mouseReleaseEvent(event)

    def mouseMoveEvent(self, event):
        if self.mode == MODE_EDGE_DRAG:
            pos = self.mapToScene(event.pos())
            self.dragEdge.grEdge.setDestination(pos.x(), pos.y())
            self.dragEdge.grEdge.update()

        if self.mode == MODE_EDGE_CUT:
            pos = self.mapToScene(event.pos())
            self.cutline.line_points.append(pos)
            self.cutline.update()

        super().mouseMoveEvent(event)

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Delete:
            self.deleteSelected()
            if not self.editingFlag:
                self.deleteSelected()
            else:
                super().keyPressEvent(event)
        else:
            super().keyPressEvent(event)  # that not everthing is overwritten

    def cutIntersectingEdges(self):
        for ix in range(len(self.cutline.line_points) - 1):
            p1 = self.cutline.line_points[ix]
            p2 = self.cutline.line_points[ix + 1]

            for edge in self.grScene.scene.edges:
                if edge.grEdge.intersectsWith(p1, p2):
                    edge.remove()

    def deleteSelected(self):
        for item in self.grScene.selectedItems():
            if isinstance(item, QDMGraphicsEdge):
                item.edge.remove()
            elif hasattr(item, 'node'):
                item.node.remove()

    def debug_modifiers(self, event):
        out = "MODS: "
        if event.modifiers() & Qt.ShiftModifier: out += "SHIFT "
        if event.modifiers() & Qt.ControlModifier: out += "CTRL "
        if event.modifiers() & Qt.AltModifier: out += "ALT "
        return out

    def getItemAtClick(self, event):
        """ return the object on which we've clicked/release mouse button """
        pos = event.pos()
        obj = self.itemAt(pos)
        return obj

    def edgeDragStart(self, item):
        if DEBUG: print('View::edgeDragStart ~ Start dragging edge')
        if DEBUG:
            print('View::edgeDragStart ~   assign Start Socket to:',
                  item.socket)
        self.previousEdge = item.socket.edge
        self.last_start_socket = item.socket
        self.dragEdge = Edge(self.grScene.scene, item.socket, None,
                             EDGE_TYPE_BEZIER)
        if DEBUG: print('View::edgeDragStart ~   dragEdge:', self.dragEdge)

    def edgeDragEnd(self, item):
        """ return True if skip the rest of the code """
        self.mode = MODE_NOOP

        if type(item) is QDMGraphicsSocket:
            if item.socket != self.last_start_socket:
                if DEBUG:
                    print('View::edgeDragEnd ~   previous edge:',
                          self.previousEdge)
                if item.socket.hasEdge():
                    item.socket.edge.remove()
                if DEBUG:
                    print('View::edgeDragEnd ~   assign End Socket',
                          item.socket)
                if self.previousEdge is not None: self.previousEdge.remove()
                if DEBUG: print('View::edgeDragEnd ~  previous edge removed')
                self.dragEdge.start_socket = self.last_start_socket
                self.dragEdge.end_socket = item.socket
                self.dragEdge.start_socket.setConnectedEdge(self.dragEdge)
                self.dragEdge.end_socket.setConnectedEdge(self.dragEdge)
                if DEBUG:
                    print(
                        'View::edgeDragEnd ~  reassigned start & end sockets to drag edge'
                    )
                self.dragEdge.updatePositions()
                return True

        if DEBUG: print('View::edgeDragEnd ~ End dragging edge')
        self.dragEdge.remove()
        self.dragEdge = None
        if DEBUG:
            print('View::edgeDragEnd ~ about to set socket to previous edge:',
                  self.previousEdge)
        if self.previousEdge is not None:
            self.previousEdge.start_socket.edge = self.previousEdge
        if DEBUG: print('View::edgeDragEnd ~ everything done.')

        return False

    def distanceBetweenClickAndReleaseIsOff(self, event):
        """ measures if we are too far from the last LMB click scene position """
        new_lmb_release_scene_pos = self.mapToScene(event.pos())
        dist_scene = new_lmb_release_scene_pos - self.last_lmb_click_scene_pos
        edge_drag_threshold_sq = EDGE_DRAG_START_THRESHOLD * EDGE_DRAG_START_THRESHOLD
        return (dist_scene.x() * dist_scene.x() +
                dist_scene.y() * dist_scene.y()) > edge_drag_threshold_sq

    def wheelEvent(self, event):
        # calculate our zoom Factor
        zoomOutFactor = 1 / self.zoomInFactor

        # calculate zoom
        if event.angleDelta().y() > 0:
            zoomFactor = self.zoomInFactor
            self.zoom += self.zoomStep
        else:
            zoomFactor = zoomOutFactor
            self.zoom -= self.zoomStep

        clamped = False
        if self.zoom < self.zoomRange[0]:
            self.zoom, clamped = self.zoomRange[0], True
        if self.zoom > self.zoomRange[1]:
            self.zoom, clamped = self.zoomRange[1], True

        # set scene scale
        if not clamped or self.zoomClamp is False:
            self.scale(zoomFactor, zoomFactor)
Пример #20
0
class QDMGraphicsView(QGraphicsView):
    scenePosChanged = pyqtSignal(int, int)

    def __init__(self, grScene, parent=None):
        super().__init__(parent)
        self.grScene = grScene

        self.initUI()

        self.setScene(self.grScene)

        self.mode = MODE_NOOP
        self.editingFlag = False
        self.rubberBandDraggingRectangle = False

        self.zoomInFactor = 1.25
        self.zoomClamp = True
        self.zoom = 10
        self.zoomStep = 1
        self.zoomRange = [0, 10]

        # cutline
        self.cutline = QDMCutLine()
        self.grScene.addItem(self.cutline)

        # listeners
        self._drag_enter_listeners = []
        self._drop_listeners = []

    def initUI(self):
        self.setRenderHints(QPainter.Antialiasing
                            | QPainter.HighQualityAntialiasing
                            | QPainter.TextAntialiasing
                            | QPainter.SmoothPixmapTransform)

        self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)

        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        self.setDragMode(QGraphicsView.RubberBandDrag)

        # enable dropping
        self.setAcceptDrops(True)

    def dragEnterEvent(self, event):
        for callback in self._drag_enter_listeners:
            callback(event)

    def dropEvent(self, event):
        for callback in self._drop_listeners:
            callback(event)

    def addDragEnterListener(self, callback):
        self._drag_enter_listeners.append(callback)

    def addDropListener(self, callback):
        self._drop_listeners.append(callback)

    def mousePressEvent(self, event):
        if event.button() == Qt.MiddleButton:
            self.middleMouseButtonPress(event)
        elif event.button() == Qt.LeftButton:
            self.leftMouseButtonPress(event)
        elif event.button() == Qt.RightButton:
            self.rightMouseButtonPress(event)
        else:
            super().mousePressEvent(event)

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.MiddleButton:
            self.middleMouseButtonRelease(event)
        elif event.button() == Qt.LeftButton:
            self.leftMouseButtonRelease(event)
        elif event.button() == Qt.RightButton:
            self.rightMouseButtonRelease(event)
        else:
            super().mouseReleaseEvent(event)

    def middleMouseButtonPress(self, event):
        item = self.getItemAtClick(event)

        # faking events for enable MMB dragging the scene
        releaseEvent = QMouseEvent(QEvent.MouseButtonRelease, event.localPos(),
                                   event.screenPos(), Qt.LeftButton,
                                   Qt.NoButton, event.modifiers())
        super().mouseReleaseEvent(releaseEvent)
        QApplication.setOverrideCursor(Qt.ClosedHandCursor)
        self.setDragMode(QGraphicsView.ScrollHandDrag)
        fakeEvent = QMouseEvent(event.type(), event.localPos(),
                                event.screenPos(), Qt.LeftButton,
                                event.buttons() | Qt.LeftButton,
                                event.modifiers())
        super().mousePressEvent(fakeEvent)

    def middleMouseButtonRelease(self, event):
        fakeEvent = QMouseEvent(event.type(), event.localPos(),
                                event.screenPos(), Qt.LeftButton,
                                event.buttons() & ~Qt.LeftButton,
                                event.modifiers())
        super().mouseReleaseEvent(fakeEvent)
        self.setDragMode(QGraphicsView.RubberBandDrag)
        QApplication.restoreOverrideCursor()

    def leftMouseButtonPress(self, event):
        # get item which we clicked on
        item = self.getItemAtClick(event)

        # we store the position of last LMB click
        self.last_lmb_click_scene_pos = self.mapToScene(event.pos())

        # logic
        if hasattr(item, "node") or isinstance(
                item, QDMGraphicsEdge) or item is None:
            if event.modifiers() & Qt.ShiftModifier:
                event.ignore()
                fakeEvent = QMouseEvent(QEvent.MouseButtonPress,
                                        event.localPos(), event.screenPos(),
                                        Qt.LeftButton,
                                        event.buttons() | Qt.LeftButton,
                                        event.modifiers() | Qt.ControlModifier)
                super().mousePressEvent(fakeEvent)
                return

        if type(item) is QDMGraphicsSocket:
            if self.mode == MODE_NOOP:
                self.mode = MODE_EDGE_DRAG
                self.edgeDragStart(item)
                return

        if self.mode == MODE_EDGE_DRAG:
            res = self.edgeDragEnd(item)
            if res: return

        if item is None:
            if event.modifiers() & Qt.ControlModifier:
                self.mode = MODE_EDGE_CUT
                fakeEvent = QMouseEvent(QEvent.MouseButtonRelease,
                                        event.localPos(), event.screenPos(),
                                        Qt.LeftButton, Qt.NoButton,
                                        event.modifiers())
                super().mouseReleaseEvent(fakeEvent)
                QApplication.setOverrideCursor(Qt.CrossCursor)
                return
            else:
                self.rubberBandDraggingRectangle = True

        super().mousePressEvent(event)

    def leftMouseButtonRelease(self, event):
        # get item which we release mouse button on
        item = self.getItemAtClick(event)

        # logic
        if hasattr(item, "node") or isinstance(
                item, QDMGraphicsEdge) or item is None:
            if event.modifiers() & Qt.ShiftModifier:
                event.ignore()
                fakeEvent = QMouseEvent(event.type(), event.localPos(),
                                        event.screenPos(), Qt.LeftButton,
                                        Qt.NoButton,
                                        event.modifiers() | Qt.ControlModifier)
                super().mouseReleaseEvent(fakeEvent)
                return

        if self.mode == MODE_EDGE_DRAG:
            if self.distanceBetweenClickAndReleaseIsOff(event):
                res = self.edgeDragEnd(item)
                if res: return

        if self.mode == MODE_EDGE_CUT:
            self.cutIntersectingEdges()
            self.cutline.line_points = []
            self.cutline.update()
            QApplication.setOverrideCursor(Qt.ArrowCursor)
            self.mode = MODE_NOOP
            return

        if self.rubberBandDraggingRectangle:
            self.rubberBandDraggingRectangle = False
            current_selected_items = self.grScene.selectedItems()

            if current_selected_items != self.grScene.scene._last_selected_items:
                if current_selected_items == []:
                    self.grScene.itemsDeselected.emit()
                else:
                    self.grScene.itemSelected.emit()
                self.grScene.scene._last_selected_items = current_selected_items

            return

        # otherwise deselect everything
        if item is None:
            self.grScene.itemsDeselected.emit()

        super().mouseReleaseEvent(event)

    def rightMouseButtonPress(self, event):
        super().mousePressEvent(event)

    def rightMouseButtonRelease(self, event):
        super().mouseReleaseEvent(event)

    def mouseMoveEvent(self, event):
        if self.mode == MODE_EDGE_DRAG:
            pos = self.mapToScene(event.pos())
            self.drag_edge.grEdge.setDestination(pos.x(), pos.y())
            self.drag_edge.grEdge.update()

        if self.mode == MODE_EDGE_CUT:
            pos = self.mapToScene(event.pos())
            self.cutline.line_points.append(pos)
            self.cutline.update()

        self.last_scene_mouse_position = self.mapToScene(event.pos())

        self.scenePosChanged.emit(int(self.last_scene_mouse_position.x()),
                                  int(self.last_scene_mouse_position.y()))

        super().mouseMoveEvent(event)

    def keyPressEvent(self, event):
        # if event.key() == Qt.Key_Delete:
        #     if not self.editingFlag:
        #         self.deleteSelected()
        #     else:
        #         super().keyPressEvent(event)
        # elif event.key() == Qt.Key_S and event.modifiers() & Qt.ControlModifier:
        #     self.grScene.scene.saveToFile("graph.json.txt")
        # elif event.key() == Qt.Key_L and event.modifiers() & Qt.ControlModifier:
        #     self.grScene.scene.loadFromFile("graph.json.txt")
        # elif event.key() == Qt.Key_Z and event.modifiers() & Qt.ControlModifier and not event.modifiers() & Qt.ShiftModifier:
        #     self.grScene.scene.history.undo()
        # elif event.key() == Qt.Key_Z and event.modifiers() & Qt.ControlModifier and event.modifiers() & Qt.ShiftModifier:
        #     self.grScene.scene.history.redo()

        # else:
        super().keyPressEvent(event)

    def cutIntersectingEdges(self):
        for ix in range(len(self.cutline.line_points) - 1):
            p1 = self.cutline.line_points[ix]
            p2 = self.cutline.line_points[ix + 1]

            for edge in self.grScene.scene.edges:
                if edge.grEdge.intersectsWith(p1, p2):
                    edge.remove()
        self.grScene.scene.history.storeHistory("Delete cutted edges",
                                                setModified=True)

    def deleteSelected(self):
        for item in self.grScene.selectedItems():
            if isinstance(item, QDMGraphicsEdge):
                item.edge.remove()
            elif hasattr(item, 'node'):
                item.node.remove()
        self.grScene.scene.history.storeHistory("Delete selected",
                                                setModified=True)

    def debug_modifiers(self, event):  # ?
        out = "MODS: "
        if event.modifiers() & Qt.ShiftModifier: out += "SHIFT "
        if event.modifiers() & Qt.ControlModifier: out += "CTRL "
        if event.modifiers() & Qt.AltModifier: out += "ALT "
        return out

    def getItemAtClick(self, event):
        """ return the object on which we've clicked/release mouse button """
        pos = event.pos()
        obj = self.itemAt(pos)
        return obj

    def edgeDragStart(self, item):
        self.drag_start_socket = item.socket
        self.drag_edge = Edge(self.grScene.scene, item.socket, None,
                              EDGE_TYPE_BEZIER)

    def edgeDragEnd(self, item):
        """ return True if skip the rest of the code """
        self.mode = MODE_NOOP
        self.drag_edge.remove()
        self.drag_edge = None

        if type(item) is QDMGraphicsSocket:
            if item.socket != self.drag_start_socket:
                # if we released dragging on a socket (other then the beginning socket)

                # we wanna keep all the edges comming from target socket
                if not item.socket.is_multi_edges:
                    item.socket.removeAllEdges()

                # we wanna keep all the edges comming from start socket
                if not self.drag_start_socket.is_multi_edges:
                    self.drag_start_socket.removeAllEdges()

                new_edge = Edge(self.grScene.scene,
                                self.drag_start_socket,
                                item.socket,
                                edge_type=EDGE_TYPE_BEZIER)

            self.grScene.scene.history.storeHistory(
                "Created new edge by dragging", setModified=True)

            return True

        return False

    def distanceBetweenClickAndReleaseIsOff(self, event):
        """ measures if we are too far from the last LMB click scene position """
        new_lmb_release_scene_pos = self.mapToScene(event.pos())
        dist_scene = new_lmb_release_scene_pos - self.last_lmb_click_scene_pos
        edge_drag_threshold_sq = EDGE_DRAG_START_THRESHOLD * EDGE_DRAG_START_THRESHOLD
        return (dist_scene.x() * dist_scene.x() +
                dist_scene.y() * dist_scene.y()) > edge_drag_threshold_sq

    def wheelEvent(self, event):
        # calculate our zoom Factor
        zoomOutFactor = 1 / self.zoomInFactor

        # calculate zoom
        if event.angleDelta().y() > 0:
            zoomFactor = self.zoomInFactor
            self.zoom += self.zoomStep
        else:
            zoomFactor = zoomOutFactor
            self.zoom -= self.zoomStep

        clamped = False
        if self.zoom < self.zoomRange[0]:
            self.zoom, clamped = self.zoomRange[0], True
        if self.zoom > self.zoomRange[1]:
            self.zoom, clamped = self.zoomRange[1], True

        # set scene scale
        if not clamped or self.zoomClamp is False:
            self.scale(zoomFactor, zoomFactor)