コード例 #1
0
    def __init__(self, graph, srcPortCircle, dstPortCircle):
        super(Connection, self).__init__()

        self.__graph = graph
        self.__srcPortCircle = srcPortCircle
        self.__dstPortCircle = dstPortCircle
        penStyle = QtCore.Qt.DashLine

        self.__connectionColor = QtGui.QColor(0, 0, 0)
        self.__connectionColor.setRgbF(
            *self.__srcPortCircle.getColor().getRgbF())
        self.__connectionColor.setAlpha(125)

        self.__defaultPen = QtGui.QPen(self.__connectionColor, 1.5, s=penStyle)
        self.__defaultPen.setDashPattern([1, 2, 2, 1])

        self.__connectionHoverColor = QtGui.QColor(0, 0, 0)
        self.__connectionHoverColor.setRgbF(
            *self.__srcPortCircle.getColor().getRgbF())
        self.__connectionHoverColor.setAlpha(255)

        self.__hoverPen = QtGui.QPen(self.__connectionHoverColor,
                                     1.5,
                                     s=penStyle)
        self.__hoverPen.setDashPattern([1, 2, 2, 1])

        self.setPen(self.__defaultPen)
        self.setZValue(-1)

        self.setAcceptHoverEvents(True)
        self.connect()
コード例 #2
0
    def paint(self, painter, option, widget):
        rect = self.windowFrameRect()
        painter.setBrush(self.__color)

        painter.setPen(QtGui.QPen(QtGui.QColor(0, 0, 0, 0), 0))

        roundingY = 10
        roundingX = rect.height() / rect.width() * roundingY

        painter.drawRoundRect(rect, roundingX, roundingY)

        # Title BG
        titleHeight = self.__headerItem.size().height() - 3

        painter.setBrush(self.__color.darker(125))
        roundingY = rect.width() * roundingX / titleHeight
        painter.drawRoundRect(0, 0, rect.width(), titleHeight, roundingX, roundingY)
        painter.drawRect(0, titleHeight * 0.5 + 2, rect.width(), titleHeight * 0.5)

        # painter.setPen(self.__linePen)
        # painter.drawLine(QtCore.QPoint(0, titleHeight), QtCore.QPoint(rect.width(), titleHeight))

        painter.setBrush(QtGui.QColor(0, 0, 0, 0))
        if self.__selected:
            painter.setPen(self.__selectedPen)
        else:
            painter.setPen(self.__unselectedPen)

        roundingY = 10
        roundingX = rect.height() / rect.width() * roundingY

        painter.drawRoundRect(rect, roundingX, roundingY)
コード例 #3
0
def generateNodes(count, offset, depth):
    for i in range(count):
        node1 = Node(graph, 'node' + str(depth) + str(i))
        node1.addPort(
            InputPort(node1, graph, 'InPort', QtGui.QColor(128, 170, 170, 255),
                      'MyDataX'))
        node1.addPort(
            OutputPort(node1, graph, 'OutPort', QtGui.QColor(32, 255, 32, 255),
                       'MyDataX'))
        node1.setGraphPos(QtCore.QPointF(offset, i * 80))

        graph.addNode(node1)

        global totalCount
        totalCount += 1

    if depth < 6:
        generateNodes(count * 2, offset + 160, depth + 1)

        for i in range(count):
            graph.connectPorts('node' + str(depth) + str(i), 'OutPort',
                               'node' + str(depth + 1) + str(i * 2), 'InPort')
            graph.connectPorts('node' + str(depth) + str(i), 'OutPort',
                               'node' + str(depth + 1) + str(i * 2 + 1),
                               'InPort')
    elif depth < 12:
        generateNodes(int(count / 2), offset + 160, depth + 1)

        for i in range(count / 2):
            graph.connectPorts('node' + str(depth) + str(i), 'OutPort',
                               'node' + str(depth + 1) + str(int(i)), 'InPort')
コード例 #4
0
ファイル: knode.py プロジェクト: mjcg91/Kraken
    def __init__(self, port, graph, hOffset, color, connectionPointType):
        super(KNodePortCircle, self).__init__(port, graph, hOffset, color,
                                              connectionPointType)

        if self.getPort().getDataType().endswith('[]'):
            self.setDefaultPen(QtGui.QPen(QtGui.QColor(204, 0, 0), 1.5))
            self.setHoverPen(QtGui.QPen(QtGui.QColor(255, 155, 100), 2.0))
コード例 #5
0
class SelectionRect(QtWidgets.QGraphicsWidget):
    __backgroundColor = QtGui.QColor(100, 100, 100, 50)
    __pen = QtGui.QPen(QtGui.QColor(25, 25, 25), 1.0, QtCore.Qt.DashLine)

    def __init__(self, graph, mouseDownPos):
        super(SelectionRect, self).__init__()
        self.setZValue(-1)

        self.__graph = graph
        self.__graph.scene().addItem(self)
        self.__mouseDownPos = mouseDownPos
        self.setPos(self.__mouseDownPos)
        self.resize(0, 0)

    def setDragPoint(self, dragPoint):
        topLeft = QtCore.QPointF(self.__mouseDownPos)
        bottomRight = QtCore.QPointF(dragPoint)
        if dragPoint.x() < self.__mouseDownPos.x():
            topLeft.setX(dragPoint.x())
            bottomRight.setX(self.__mouseDownPos.x())
        if dragPoint.y() < self.__mouseDownPos.y():
            topLeft.setY(dragPoint.y())
            bottomRight.setY(self.__mouseDownPos.y())
        self.setPos(topLeft)
        self.resize(bottomRight.x() - topLeft.x(),
                    bottomRight.y() - topLeft.y())

    def paint(self, painter, option, widget):
        rect = self.windowFrameRect()
        painter.setBrush(self.__backgroundColor)
        painter.setPen(self.__pen)
        painter.drawRect(rect)

    def destroy(self):
        self.__graph.scene().removeItem(self)
コード例 #6
0
ファイル: knode.py プロジェクト: mjcg91/Kraken
def getPortColor(dataType):

    if dataType.startswith('Xfo'):
        return QtGui.QColor(128, 170, 170, 255)
    elif dataType.startswith('Float'):
        return QtGui.QColor(32, 255, 32, 255)
    elif dataType.startswith('Integer'):
        return QtGui.QColor(0, 128, 0, 255)
    elif dataType.startswith('Boolean'):
        return QtGui.QColor(255, 102, 0, 255)
    else:
        return QtGui.QColor(50, 205, 254, 255)
コード例 #7
0
class NodeTitle(QtWidgets.QGraphicsWidget):

    __color = QtGui.QColor(25, 25, 25)
    __font = QtGui.QFont('Decorative', 14)
    __font.setLetterSpacing(QtGui.QFont.PercentageSpacing, 115)
    __labelBottomSpacing = 12

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

        self.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed))

        self.__textItem = QtWidgets.QGraphicsTextItem(text, self)
        self.__textItem.setDefaultTextColor(self.__color)
        self.__textItem.setFont(self.__font)
        self.__textItem.setPos(0, -2)
        option = self.__textItem.document().defaultTextOption()
        option.setWrapMode(QtGui.QTextOption.NoWrap)
        self.__textItem.document().setDefaultTextOption(option)
        self.__textItem.adjustSize()

        self.setPreferredSize(self.textSize())

    def setText(self, text):
        self.__textItem.setPlainText(text)
        self.__textItem.adjustSize()
        self.setPreferredSize(self.textSize())

    def textSize(self):
        return QtCore.QSizeF(
            self.__textItem.textWidth(),
            self.__font.pointSizeF() + self.__labelBottomSpacing
            )
コード例 #8
0
    def setData(self, data):
        """Sets the data on a backdrop after loading.

        Args:
            data (dict): Name, comment, graph pos, size, and color.

        Returns:
            bool: True if successful.

        """

        self.setComment(data.get('comment', ''))

        size = data.get('size', (self.minimumWidth(), self.minimumHeight()))
        self.resize(size[0], size[1])

        position = data.get('graphPos', (0, 0))
        self.setGraphPos(QtCore.QPointF(position[0], position[1]))

        color = data.get('color', self.__defaultColor.toTuple())
        self.setColor(
            color=QtGui.QColor(color[0], color[1], color[2], color[3]))
        self.setUnselectedColor(self.getColor().darker(125))
        self.setSelectedColor(self.getColor().lighter(175))
        self.setHoveredColor(self.getColor().lighter(110))

        return True
コード例 #9
0
    def dragObject(self):

        if not self.selectedIndexes():
            return

        item = self.selectedItems()[0]
        role = item.data(0, QtCore.Qt.UserRole)

        if role == 'Folder':
            return

        text = 'KrakenComponent:' + role

        mimeData = QtCore.QMimeData()
        mimeData.setText(text)

        drag = QtGui.QDrag(self)
        drag.setMimeData(mimeData)
        drag.setHotSpot(QtCore.QPoint(90, 23))

        ghostComponent = QtGui.QPixmap(180, 46)
        ghostComponent.fill(QtGui.QColor(67, 143, 153, 80))

        drag.setPixmap(ghostComponent)
        drag.start(QtCore.Qt.IgnoreAction)
コード例 #10
0
    def write(self, msg, level):

        if level == 'DEBUG':
            messageColor = QtGui.QColor("#EEE97B")
        elif level == 'INFO':
            messageColor = QtGui.QColor(QtCore.Qt.white)
        elif level == 'INFORM':
            messageColor = QtGui.QColor("#009900")
        elif level == 'WARNING':
            messageColor = QtGui.QColor("#D89614")
        elif level == 'ERROR':
            messageColor = QtGui.QColor("#CC0000")
        elif level == 'CRITICAL':
            messageColor = QtGui.QColor("#CC0000")
        else:
            messageColor = QtGui.QColor(QtCore.Qt.white)

        self.textWidget.setTextColor(messageColor)
        charFormat = self.textWidget.currentCharFormat()
        textCursor = self.textWidget.textCursor()
        textCursor.movePosition(QtGui.QTextCursor.End)
        textCursor.insertText('[ ' + level + ' ] ' + msg, charFormat)

        self.textWidget.setTextCursor(textCursor)
        self.textWidget.ensureCursorVisible()
コード例 #11
0
    def paint(self, painter, option, widget):
        rect = self.windowFrameRect()
        painter.setBrush(self.__color)

        painter.setPen(QtGui.QPen(QtGui.QColor(0, 0, 0, 0), 0))

        roundingY = 20.0 / (rect.height() / 80.0)
        roundingX = rect.height() / rect.width() * roundingY

        painter.drawRoundRect(rect,
                              roundingX,
                              roundingY,
                              mode=QtCore.Qt.AbsoluteSize)

        # Title BG
        titleHeight = self.__headerItem.size().height() - 3

        darkerColor = self.__color.darker(125)
        darkerColor.setAlpha(255)
        painter.setBrush(darkerColor)
        roundingYHeader = rect.width() * roundingX / titleHeight
        painter.drawRoundRect(0, 0, rect.width(), titleHeight, roundingX,
                              roundingYHeader)
        painter.drawRect(0, titleHeight * 0.5 + 2, rect.width(),
                         titleHeight * 0.5)

        painter.setBrush(QtGui.QColor(0, 0, 0, 0))
        if self.__selected:
            painter.setPen(self.__selectedPen)
        elif self.__hoveredOver:
            painter.setPen(self.__hoveredPen)
        else:
            painter.setPen(self.__unselectedPen)

        painter.drawRoundRect(rect,
                              roundingX,
                              roundingY,
                              mode=QtCore.Qt.AbsoluteSize)

        super(KBackdrop, self).paint(painter, option, widget)
コード例 #12
0
class KBackdropTitle(QtWidgets.QGraphicsWidget):

    __color = QtGui.QColor(255, 255, 255)
    __font = QtGui.QFont('Helvetica', 11)
    __font.setLetterSpacing(QtGui.QFont.PercentageSpacing, 120)
    __fontMetrics = QtGui.QFontMetrics(__font)
    __labelBottomSpacing = 4

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

        self.parentWidget = parent

        self.__textItem = QtWidgets.QGraphicsTextItem(text, self)
        self.__textItem.setDefaultTextColor(self.__color)
        self.__textItem.setFont(self.__font)
        self.__textItem.setPos(0, 1)
        option = self.__textItem.document().defaultTextOption()
        self.__textItem.document().setDefaultTextOption(option)
        self.__textItem.adjustSize()
        self.__textItem.setTextWidth(120)

        self.setPreferredSize(self.textSize())

    def setText(self, text):
        self.__textItem.setPlainText(text)
        # self.__textItem.adjustSize()
        self.nodeResized(self.parentWidget.parentWidget.size().width())

    def setTextColor(self, color):
        self.__color = color
        self.update()

    def textSize(self):
        return QtCore.QSizeF(self.__textItem.textWidth(), self.textHeight())

    def textHeight(self):
        return self.__textItem.document().documentLayout().documentSize(
        ).height() + self.__labelBottomSpacing

    def nodeResized(self, width=None):

        fmWidth = self.__fontMetrics.width(self.__textItem.toPlainText())
        newWidth = min(fmWidth, width)
        if width > fmWidth:
            newWidth = width

        self.__textItem.setTextWidth(newWidth)
        self.setPreferredSize(newWidth, self.textHeight())

    def getBackdropWidget(self):
        return self.parent().parent()
コード例 #13
0
ファイル: color_widget.py プロジェクト: yes7rose/Kraken
    def __init__(self, parent, color):
        super(KColorWidget, self).__init__(parent)
        self.installEventFilter(self)
        self._color = QtGui.QColor(color)

        self.pixmap = QtGui.QPixmap(12, 12)
        self.pixmap.fill(self._color)

        self.setProperty('colorLabel', True)
        self.setFixedSize(24, 24)
        self.setScaledContents(True)
        self.setPixmap(self.pixmap)

        self.createConnections()
コード例 #14
0
ファイル: port.py プロジェクト: mjcg91/Kraken
    def __init__(self, port, graph, hOffset, color, connectionPointType):
        super(PortCircle, self).__init__(port)

        self.__port = port
        self._graph = graph
        self._connectionPointType = connectionPointType
        self.__connections = set()
        self._supportsOnlySingleConnections = connectionPointType == 'In'

        self.setSizePolicy(
            QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed,
                                  QtWidgets.QSizePolicy.Fixed))
        size = QtCore.QSizeF(self.__diameter, self.__diameter)
        self.setPreferredSize(size)
        self.setWindowFrameMargins(0, 0, 0, 0)

        self.transform().translate(self.__radius * hOffset, 0)

        self.__defaultPen = QtGui.QPen(QtGui.QColor(25, 25, 25), 1.0)
        self.__hoverPen = QtGui.QPen(QtGui.QColor(255, 255, 100), 1.5)

        self._ellipseItem = QtWidgets.QGraphicsEllipseItem(self)
        self._ellipseItem.setPen(self.__defaultPen)
        self._ellipseItem.setPos(size.width() / 2, size.height() / 2)
        self._ellipseItem.setRect(
            -self.__radius,
            -self.__radius,
            self.__diameter,
            self.__diameter,
        )
        if connectionPointType == 'In':
            self._ellipseItem.setStartAngle(270 * 16)
            self._ellipseItem.setSpanAngle(180 * 16)

        self.setColor(color)
        self.setAcceptHoverEvents(True)
コード例 #15
0
ファイル: knode.py プロジェクト: mjcg91/Kraken
    def __init__(self, graph, component):
        super(KNode, self).__init__(graph, component.getDecoratedName())

        self.__component = component
        self.__inspectorWidget = None

        for i in range(self.__component.getNumInputs()):
            componentInput = component.getInputByIndex(i)
            self.addPort(KNodeInputPort(self, graph, componentInput))

        for i in range(self.__component.getNumOutputs()):
            componentOutput = component.getOutputByIndex(i)
            self.addPort(KNodeOutputPort(self, graph, componentOutput))

        self.setGraphPos(
            QtCore.QPointF(self.__component.getGraphPos().x,
                           self.__component.getGraphPos().y))

        nodeColor = component.getComponentColor()
        self.setColor(
            QtGui.QColor(nodeColor[0], nodeColor[1], nodeColor[2],
                         nodeColor[3]))
        self.setUnselectedColor(self.getColor().darker(125))
        self.setSelectedColor(self.getColor().lighter(175))
コード例 #16
0
ファイル: color_editor.py プロジェクト: yes7rose/Kraken
 def __onColorChanged(self, qcolor):
     self.__color = QtGui.QColor(qcolor.redF() * 255,
                                 qcolor.greenF() * 255,
                                 qcolor.blueF() * 255)
     self._qgraphcsView.setBackgroundBrush(self.__color)
     self._setValueToController()
コード例 #17
0
ファイル: graph_view_widget.py プロジェクト: yes7rose/Kraken
    def getGraphView(self):
        return self.graphView


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)

    widget = GraphViewWidget()
    graph = GraphView(parent=widget)

    from node import Node
    from port import InputPort, OutputPort, IOPort

    node1 = Node(graph, 'Short')
    node1.addPort(
        InputPort(node1, graph, 'InPort1', QtGui.QColor(128, 170, 170, 255),
                  'MyDataX'))
    node1.addPort(
        InputPort(node1, graph, 'InPort2', QtGui.QColor(128, 170, 170, 255),
                  'MyDataX'))
    node1.addPort(
        OutputPort(node1, graph, 'OutPort', QtGui.QColor(32, 255, 32, 255),
                   'MyDataY'))
    node1.addPort(
        IOPort(node1, graph, 'IOPort1', QtGui.QColor(32, 255, 32, 255),
               'MyDataY'))
    node1.addPort(
        IOPort(node1, graph, 'IOPort2', QtGui.QColor(32, 255, 32, 255),
               'MyDataY'))
    node1.setGraphPos(QtCore.QPointF(-100, 0))
コード例 #18
0
class KBackdrop(QtWidgets.QGraphicsWidget):

    nameChanged = QtCore.Signal(str, str)
    sizeChanged = QtCore.Signal(float)

    __defaultColor = QtGui.QColor(65, 120, 122, 255)
    __defaultUnselectedColor = QtGui.QColor(__defaultColor.darker(125))
    __defaultSelectedColor = QtGui.QColor(__defaultColor.lighter(175))
    __defaultHoverColor = QtGui.QColor(__defaultColor.lighter(110))

    __defaultUnselectedPen = QtGui.QPen(__defaultUnselectedColor, 1.6)
    __defaultSelectedPen = QtGui.QPen(__defaultSelectedColor, 1.6)
    __defaultHoveredPen = QtGui.QPen(__defaultHoverColor, 1.6)
    __defaultLinePen = QtGui.QPen(QtGui.QColor(25, 25, 25, 255), 1.25)

    __resizeDistance = 16.0
    __setCustomCursor = False
    __hoveredOver = False

    def __init__(self, graph, name):
        super(KBackdrop, self).__init__()
        self.setAcceptHoverEvents(True)

        self.__name = name
        self.__comment = None

        self.__graph = graph
        self.__color = self.__defaultColor
        self.__color.setAlpha(25)
        self.__unselectedColor = self.__defaultUnselectedColor
        self.__selectedColor = self.__defaultSelectedColor
        self.__hoverColor = self.__defaultHoverColor

        self.__unselectedPen = QtGui.QPen(self.__defaultUnselectedPen)
        self.__selectedPen = QtGui.QPen(self.__defaultSelectedPen)
        self.__hoveredPen = QtGui.QPen(self.__defaultHoveredPen)
        self.__linePen = QtGui.QPen(self.__defaultLinePen)

        self.__inspectorWidget = None

        self.setMinimumWidth(120)
        self.setMinimumHeight(80)
        self.setZValue(-100)

        # Set defaults for interactions
        self.__selected = False
        self.__dragging = False
        self.__resizing = False
        self.__resizeCorner = -1
        self.__resizeEdge = -1

        self.createLayout()
        self.createConnections()

        # Initialize the comment with the name
        self.setComment(name)

    def createLayout(self):

        layout = QtWidgets.QGraphicsLinearLayout()
        layout.setContentsMargins(5, 0, 5, 7)
        layout.setSpacing(7)
        layout.setOrientation(QtCore.Qt.Vertical)
        self.setLayout(layout)

        self.__headerItem = KBackdropHeader(self.__name, self)
        self.__titleWidget = self.__headerItem.getTitleWidget()
        layout.addItem(self.__headerItem)
        layout.setAlignment(self.__headerItem,
                            QtCore.Qt.AlignCenter | QtCore.Qt.AlignTop)
        layout.addStretch(1)

    def createConnections(self):

        self.sizeChanged.connect(self.__titleWidget.nodeResized)

    def getName(self):
        return self.__name

    def setName(self, name):
        if name != self.__name:
            origName = self.__name
            self.__name = name
            # self.__headerItem.setText(self.__name)

            # Emit an event, so that the graph can update itsself.
            self.nameChanged.emit(origName, name)

            # Update the node so that the size is computed.
            self.adjustSize()

    def getComment(self):
        return self.__comment

    def setComment(self, comment):
        self.__comment = comment
        self.__headerItem.setText(comment)

        # Resize the width of the backdrop based on title width
        titleWidget = self.__headerItem.getTitleWidget()
        titleWidth = titleWidget.textSize().width()
        self.resize(titleWidth, self.size().height())

        # Update the node so that the size is computed.
        self.adjustSize()

    def getColor(self):
        color = QtGui.QColor(self.__color)
        color.setAlpha(255)
        return color

    def setColor(self, color):
        self.__color = color
        self.__color.setAlpha(25)
        self.update()

    def getUnselectedColor(self):
        return self.__unselectedColor

    def setUnselectedColor(self, color):
        self.__unselectedColor = color
        self.__unselectedPen.setColor(self.__unselectedColor)
        self.update()

    def getSelectedColor(self):
        return self.__selectedColor

    def setSelectedColor(self, color):
        self.__selectedColor = color
        self.__selectedPen.setColor(self.__selectedColor)
        self.update()

    def getHoveredColor(self):
        return self.__hoverColor

    def setHoveredColor(self, color):
        self.__hoverColor = color
        self.__hoveredPen.setColor(self.__hoverColor)
        self.update()

    def getGraph(self):
        return self.__graph

    def getHeader(self):
        return self.__headerItem

    # ==========
    # Selection
    # ==========
    def isSelected(self):
        return self.__selected

    def setSelected(self, selected=True):
        self.__selected = selected
        self.update()

    # ==========
    # Graph Pos
    # ==========
    def getGraphPos(self):
        transform = self.transform()
        size = self.size()
        return QtCore.QPointF(transform.dx() + (size.width() * 0.5),
                              transform.dy() + (size.height() * 0.5))

    def setGraphPos(self, graphPos):
        size = self.size()
        self.setTransform(
            QtGui.QTransform.fromTranslate(
                graphPos.x() - (size.width() * 0.5),
                graphPos.y() - (size.height() * 0.5)), False)

    def translate(self, x, y):
        super(KBackdrop, self).translate(x, y)

    def paint(self, painter, option, widget):
        rect = self.windowFrameRect()
        painter.setBrush(self.__color)

        painter.setPen(QtGui.QPen(QtGui.QColor(0, 0, 0, 0), 0))

        roundingY = 20.0 / (rect.height() / 80.0)
        roundingX = rect.height() / rect.width() * roundingY

        painter.drawRoundRect(rect,
                              roundingX,
                              roundingY,
                              mode=QtCore.Qt.AbsoluteSize)

        # Title BG
        titleHeight = self.__headerItem.size().height() - 3

        darkerColor = self.__color.darker(125)
        darkerColor.setAlpha(255)
        painter.setBrush(darkerColor)
        roundingYHeader = rect.width() * roundingX / titleHeight
        painter.drawRoundRect(0, 0, rect.width(), titleHeight, roundingX,
                              roundingYHeader)
        painter.drawRect(0, titleHeight * 0.5 + 2, rect.width(),
                         titleHeight * 0.5)

        painter.setBrush(QtGui.QColor(0, 0, 0, 0))
        if self.__selected:
            painter.setPen(self.__selectedPen)
        elif self.__hoveredOver:
            painter.setPen(self.__hoveredPen)
        else:
            painter.setPen(self.__unselectedPen)

        painter.drawRoundRect(rect,
                              roundingX,
                              roundingY,
                              mode=QtCore.Qt.AbsoluteSize)

        super(KBackdrop, self).paint(painter, option, widget)

    # =======
    # Events
    # =======
    def mousePressEvent(self, event):
        if event.button() is QtCore.Qt.MouseButton.LeftButton:

            resizeCorner = self.getCorner(event.pos())
            resizeEdge = self.getEdge(event.pos())
            if resizeCorner != -1 and self.isSelected():
                self.__resizing = True
                self.__resizeCorner = resizeCorner
                self._resizedBackdrop = False
            elif resizeEdge != -1 and self.isSelected():
                self.__resizing = True
                self.__resizeEdge = resizeEdge
                self._resizedBackdrop = False
            else:
                modifiers = event.modifiers()
                if modifiers == QtCore.Qt.ControlModifier:
                    if not self.isSelected():
                        self.__graph.selectNode(self, clearSelection=False)
                    else:
                        self.__graph.deselectNode(self)

                elif modifiers == QtCore.Qt.ShiftModifier:
                    if not self.isSelected():
                        self.__graph.selectNode(self, clearSelection=False)
                else:
                    if not self.isSelected():
                        self.__graph.selectNode(self, clearSelection=True)

                    if self.__headerItem.contains(event.pos()):
                        self.setCursor(QtCore.Qt.ClosedHandCursor)
                        self.__dragging = True
                        self._nodesMoved = False

            self._mouseDownPoint = self.mapToScene(event.pos())
            self._mouseDelta = self._mouseDownPoint - self.getGraphPos()
            self._lastDragPoint = self._mouseDownPoint

            self._initPos = self.pos()
            self._initScenePos = self.mapToScene(self.pos())
            self._initBoundingRect = self.boundingRect()
            self._initSceneBoundingRect = self.sceneBoundingRect()

        else:
            super(KBackdrop, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if self.__dragging:
            newPos = self.mapToScene(event.pos())

            graph = self.getGraph()
            if graph.getSnapToGrid() is True:
                gridSize = graph.getGridSize()

                newNodePos = newPos - self._mouseDelta

                snapPosX = math.floor(newNodePos.x() / gridSize) * gridSize
                snapPosY = math.floor(newNodePos.y() / gridSize) * gridSize
                snapPos = QtCore.QPointF(snapPosX, snapPosY)

                newPosOffset = snapPos - newNodePos

                newPos = newPos + newPosOffset

            delta = newPos - self._lastDragPoint
            self.__graph.moveSelectedNodes(delta)
            self._lastDragPoint = newPos
            self._nodesMoved = True

        elif self.__resizing:

            newPos = self.mapToScene(event.pos())
            delta = newPos - self._mouseDownPoint
            self._resizedBackdrop = True

            newPosX = 0
            newPosY = 0
            newWidth = self._initBoundingRect.width()
            newHeight = self._initBoundingRect.height()

            if self.__resizeCorner == 0:

                newWidth = self._initBoundingRect.width() + (delta.x() * -1.0)
                newHeight = self._initBoundingRect.height() + (delta.y() *
                                                               -1.0)

                if newWidth <= self.minimumWidth():
                    newWidth = self.minimumWidth()
                else:
                    newPosX = self._initPos.x() + delta.x()

                if newHeight <= self.minimumHeight():
                    newHeight = self.minimumHeight()
                else:
                    newPosY = self._initPos.y() + delta.y()

            elif self.__resizeCorner == 1:

                newWidth = self._initBoundingRect.width() + delta.x()
                newHeight = self._initBoundingRect.height() + (delta.y() *
                                                               -1.0)

                if newWidth <= self.minimumWidth():
                    newWidth = self.minimumWidth()
                else:
                    newPosX = self._initPos.x()

                if newHeight <= self.minimumHeight():
                    newHeight = self.minimumHeight()
                else:
                    newPosY = self._initPos.y() + delta.y()

            elif self.__resizeCorner == 2:

                newWidth = self._initBoundingRect.width() + (delta.x() * -1.0)
                newHeight = self._initBoundingRect.height() + delta.y()

                if newWidth <= self.minimumWidth():
                    newWidth = self.minimumWidth()
                else:
                    newPosX = self._initPos.x() + delta.x()

                if newHeight <= self.minimumHeight():
                    newHeight = self.minimumHeight()
                else:
                    newPosY = self._initPos.y()

            elif self.__resizeCorner == 3:
                newPosX = self._initPos.x()
                newPosY = self._initPos.y()
                newWidth = self._initBoundingRect.width() + delta.x()
                newHeight = self._initBoundingRect.height() + delta.y()

                if newWidth <= self.minimumWidth():
                    newWidth = self.minimumWidth()

                if newHeight <= self.minimumHeight():
                    newHeight = self.minimumHeight()

            elif self.__resizeEdge == 0:
                pass

            elif self.__resizeEdge == 1:
                newWidth = self._initBoundingRect.width() + delta.x()
                newHeight = self._initBoundingRect.height()

                newPosY = self._initPos.y()

                if newWidth <= self.minimumWidth():
                    newWidth = self.minimumWidth()
                else:
                    newPosX = self._initPos.x()

            elif self.__resizeEdge == 2:
                newWidth = self._initBoundingRect.width()
                newHeight = self._initBoundingRect.height() + delta.y()

                newPosX = self._initPos.x()

                if newHeight <= self.minimumHeight():
                    newHeight = self.minimumHeight()
                else:
                    newPosY = self._initPos.y()

            elif self.__resizeEdge == 3:
                newWidth = self._initBoundingRect.width() + (delta.x() * -1.0)
                newHeight = self._initBoundingRect.height()

                newPosY = self._initPos.y()

                if newWidth <= self.minimumWidth():
                    newWidth = self.minimumWidth()
                else:
                    newPosX = self._initPos.x() + delta.x()

            self.setPos(newPosX, newPosY)
            self.resize(newWidth, newHeight)

            self.sizeChanged.emit(newWidth)

            self.prepareGeometryChange()

        else:
            super(KBackdrop, self).mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        if self.__dragging:
            if self._nodesMoved:

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

                delta = newPos - self._mouseDownPoint
                self.__graph.endMoveSelectedNodes(delta)

            self.setCursor(QtCore.Qt.ArrowCursor)
            self.__dragging = False

        elif self.__resizing:

            self.setCursor(QtCore.Qt.ArrowCursor)
            self.__resizing = False
            self.__resizeCorner = -1

        else:
            super(KBackdrop, self).mouseReleaseEvent(event)

    def mouseDoubleClickEvent(self, event):
        if self.__inspectorWidget is None:
            parentWidget = self.getGraph().getGraphViewWidget()
            self.__inspectorWidget = BackdropInspector(parent=parentWidget,
                                                       nodeItem=self)
            result = self.__inspectorWidget.exec_()
        else:
            self.__inspectorWidget.setFocus()

        super(KBackdrop, self).mouseDoubleClickEvent(event)

    def hoverEnterEvent(self, event):
        self.__hoveredOver = True
        self.update()

    def hoverMoveEvent(self, event):

        resizeCorner = self.getCorner(event.pos())
        resizeEdge = self.getEdge(event.pos())
        if resizeCorner == 0:
            self.__setCustomCursor = True
            self.setCursor(QtCore.Qt.SizeFDiagCursor)
        elif resizeCorner == 1:
            self.__setCustomCursor = True
            self.setCursor(QtCore.Qt.SizeBDiagCursor)
        elif resizeCorner == 2:
            self.__setCustomCursor = True
            self.setCursor(QtCore.Qt.SizeBDiagCursor)
        elif resizeCorner == 3:
            self.__setCustomCursor = True
            self.setCursor(QtCore.Qt.SizeFDiagCursor)
        elif resizeEdge == 0:
            self.__setCustomCursor = True
            self.setCursor(QtCore.Qt.SizeVerCursor)
        elif resizeEdge == 1:
            self.__setCustomCursor = True
            self.setCursor(QtCore.Qt.SizeHorCursor)
        elif resizeEdge == 2:
            self.__setCustomCursor = True
            self.setCursor(QtCore.Qt.SizeVerCursor)
        elif resizeEdge == 3:
            self.__setCustomCursor = True
            self.setCursor(QtCore.Qt.SizeHorCursor)
        elif self.__headerItem.contains(event.pos()) is True:
            self.__setCustomCursor = True
            self.setCursor(QtCore.Qt.OpenHandCursor)
        else:
            if self.__setCustomCursor is True:
                self.setCursor(QtCore.Qt.ArrowCursor)

    def hoverLeaveEvent(self, event):
        self.setCursor(QtCore.Qt.ArrowCursor)
        self.__hoveredOver = False
        self.update()

    # =============
    # Misc Methods
    # =============
    def getCorner(self, pos):
        topLeft = self.mapFromItem(self, self.boundingRect().topLeft())
        bottomRight = self.mapFromItem(self, self.boundingRect().bottomRight())
        rect = QtCore.QRectF(topLeft, bottomRight)

        if (rect.topLeft() - pos).manhattanLength() < self.__resizeDistance:
            return 0
        elif (rect.topRight() - pos).manhattanLength() < self.__resizeDistance:
            return 1
        elif (rect.bottomLeft() -
              pos).manhattanLength() < self.__resizeDistance:
            return 2
        elif (rect.bottomRight() -
              pos).manhattanLength() < self.__resizeDistance:
            return 3

        return -1

    def getEdge(self, pos):
        topRectUpperLeft = self.mapFromItem(self,
                                            self.boundingRect().topLeft())
        topRectLowerRight = self.mapFromItem(self,
                                             self.boundingRect().right(),
                                             self.__resizeDistance * 0.25)
        topRect = QtCore.QRectF(topRectUpperLeft, topRectLowerRight)

        rightRectUpperLeft = self.mapFromItem(
            self,
            self.boundingRect().right() - self.__resizeDistance * 0.25, 0)
        rightRectLowerRight = self.mapFromItem(
            self,
            self.boundingRect().bottomRight())
        rightRect = QtCore.QRectF(rightRectUpperLeft, rightRectLowerRight)

        bottomRectUpperLeft = self.mapFromItem(
            self, 0,
            self.boundingRect().bottom() - self.__resizeDistance * 0.25)
        bottomRectLowerRight = self.mapFromItem(
            self,
            self.boundingRect().bottomRight())
        bottomRect = QtCore.QRectF(bottomRectUpperLeft, bottomRectLowerRight)

        leftRectUpperLeft = self.mapFromItem(self,
                                             self.boundingRect().topLeft())
        leftRectLowerRight = self.mapFromItem(
            self,
            self.boundingRect().left() + self.__resizeDistance * 0.25,
            self.boundingRect().bottom())
        leftRect = QtCore.QRectF(leftRectUpperLeft, leftRectLowerRight)

        if topRect.contains(pos):
            return -1  # Disabling the top resize by default.
        elif rightRect.contains(pos):
            return 1
        elif bottomRect.contains(pos):
            return 2
        elif leftRect.contains(pos):
            return 3

        return -1

    def inspectorClosed(self):
        self.__inspectorWidget = None

    # ==========
    # Shut Down
    # ==========
    def disconnectAllPorts(self):
        pass

    # =============
    # Data Methods
    # =============
    def getData(self):
        """Gets the essential data of the backdrop for saving.

        Returns:
            dict: Data for saving.

        """

        data = {
            'name': self.getName(),
            'comment': self.getComment(),
            'graphPos': self.getGraphPos().toTuple(),
            'size': self.size().toTuple(),
            'color': self.getColor().toTuple()
        }

        return data

    def setData(self, data):
        """Sets the data on a backdrop after loading.

        Args:
            data (dict): Name, comment, graph pos, size, and color.

        Returns:
            bool: True if successful.

        """

        self.setComment(data.get('comment', ''))

        size = data.get('size', (self.minimumWidth(), self.minimumHeight()))
        self.resize(size[0], size[1])

        position = data.get('graphPos', (0, 0))
        self.setGraphPos(QtCore.QPointF(position[0], position[1]))

        color = data.get('color', self.__defaultColor.toTuple())
        self.setColor(
            color=QtGui.QColor(color[0], color[1], color[2], color[3]))
        self.setUnselectedColor(self.getColor().darker(125))
        self.setSelectedColor(self.getColor().lighter(175))
        self.setHoveredColor(self.getColor().lighter(110))

        return True
コード例 #19
0
 def setNodeColor(self, color):
     self.nodeItem.setColor(QtGui.QColor(color))
     self.nodeItem.setUnselectedColor(self.nodeItem.getColor().darker(125))
     self.nodeItem.setSelectedColor(self.nodeItem.getColor().lighter(175))
     self.nodeItem.setHoveredColor(self.nodeItem.getColor().lighter(110))
コード例 #20
0
class Node(QtWidgets.QGraphicsWidget):

    nameChanged = QtCore.Signal(str, str)

    __defaultColor = QtGui.QColor(154, 205, 50, 255)
    __defaultUnselectedColor = QtGui.QColor(25, 25, 25)
    __defaultSelectedColor = QtGui.QColor(255, 255, 255, 255)

    __defaultUnselectedPen = QtGui.QPen(__defaultUnselectedColor, 1.6)
    __defaultSelectedPen = QtGui.QPen(__defaultSelectedColor, 1.6)
    __defaultLinePen = QtGui.QPen(QtGui.QColor(25, 25, 25, 255), 1.25)

    def __init__(self, graph, name):
        super(Node, self).__init__()

        self.__name = name
        self.__graph = graph
        self.__color = self.__defaultColor
        self.__unselectedColor = self.__defaultUnselectedColor
        self.__selectedColor = self.__defaultSelectedColor

        self.__unselectedPen = QtGui.QPen(self.__defaultUnselectedPen)
        self.__selectedPen = QtGui.QPen(self.__defaultSelectedPen)
        self.__linePen = QtGui.QPen(self.__defaultLinePen)

        self.setMinimumWidth(60)
        self.setMinimumHeight(20)
        self.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding))

        layout = QtWidgets.QGraphicsLinearLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        layout.setOrientation(QtCore.Qt.Vertical)
        self.setLayout(layout)

        self.__headerItem = NodeHeader(self.__name, self)
        layout.addItem(self.__headerItem)
        layout.setAlignment(self.__headerItem, QtCore.Qt.AlignCenter | QtCore.Qt.AlignTop)

        self.__ports = []
        self.__inputPortsHolder = PortList(self)
        self.__ioPortsHolder = PortList(self)
        self.__outputPortsHolder = PortList(self)

        layout.addItem(self.__inputPortsHolder)
        layout.addItem(self.__ioPortsHolder)
        layout.addItem(self.__outputPortsHolder)

        self.__selected = False
        self.__dragging = False

    # =====
    # Name
    # =====
    def getName(self):
        return self.__name

    def setName(self, name):
        if name != self.__name:
            origName = self.__name
            self.__name = name
            self.__headerItem.setText(self.__name)

            # Emit an event, so that the graph can update itsself.
            self.nameChanged.emit(origName, name)

            # Update the node so that the size is computed.
            self.adjustSize()

    # =======
    # Colors
    # =======
    def getColor(self):
        return self.__color

    def setColor(self, color):
        self.__color = color
        self.update()


    def getUnselectedColor(self):
        return self.__unselectedColor

    def setUnselectedColor(self, color):
        self.__unselectedColor = color
        self.__unselectedPen.setColor(self.__unselectedColor)
        self.update()


    def getSelectedColor(self):
        return self.__selectedColor

    def setSelectedColor(self, color):
        self.__selectedColor = color
        self.__selectedPen.setColor(self.__selectedColor)
        self.update()

    # =============
    # Misc Methods
    # =============
    def getGraph(self):
        return self.__graph


    def getHeader(self):
        return self.__headerItem


    # ==========
    # Selection
    # ==========
    def isSelected(self):
        return self.__selected

    def setSelected(self, selected=True):
        self.__selected = selected
        self.setZValue(20.0)
        self.update()


    #########################
    ## Graph Pos

    def getGraphPos(self):
        transform = self.transform()
        size = self.size()
        return QtCore.QPointF(transform.dx()+(size.width()*0.5), transform.dy()+(size.height()*0.5))


    def setGraphPos(self, graphPos):
        self.prepareConnectionGeometryChange()
        size = self.size()
        self.setTransform(QtGui.QTransform.fromTranslate(graphPos.x()-(size.width()*0.5), graphPos.y()-(size.height()*0.5)), False)


    def translate(self, x, y):
        self.prepareConnectionGeometryChange()
        currPos = self.pos()
        super(Node, self).setPos(currPos.x() + x, currPos.y() + y)


    # Prior to moving the node, we need to tell the connections to prepare for a geometry change.
    # This method must be called preior to moving a node.
    def prepareConnectionGeometryChange(self):
        for port in self.__ports:
            if port.inCircle():
                for connection in port.inCircle().getConnections():
                    connection.prepareGeometryChange()
            if port.outCircle():
                for connection in port.outCircle().getConnections():
                    connection.prepareGeometryChange()

    #########################
    ## Ports

    def addPort(self, port):
        if isinstance(port, InputPort):
            self.__inputPortsHolder.addPort(port, QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
        elif isinstance(port, OutputPort):
            self.__outputPortsHolder.addPort(port, QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
        else:
            self.__ioPortsHolder.addPort(port, QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
        self.__ports.append(port)

        self.adjustSize()
        return port


    def getPort(self, name):
        for port in self.__ports:
            if port.getName() == name:
                return port
        return None

    def getInputPort(self, name):
        for port in self.__ports:
            if port.getName() == name and isinstance(port, (InputPort, IOPort)):
                return port
        return None

    def getOutputPort(self, name):
        for port in self.__ports:
            if port.getName() == name and isinstance(port, (OutputPort, IOPort)):
                return port
        return None


    def paint(self, painter, option, widget):
        rect = self.windowFrameRect()
        painter.setBrush(self.__color)

        painter.setPen(QtGui.QPen(QtGui.QColor(0, 0, 0, 0), 0))

        roundingY = 10
        roundingX = rect.height() / rect.width() * roundingY

        painter.drawRoundRect(rect, roundingX, roundingY)

        # Title BG
        titleHeight = self.__headerItem.size().height() - 3

        painter.setBrush(self.__color.darker(125))
        roundingY = rect.width() * roundingX / titleHeight
        painter.drawRoundRect(0, 0, rect.width(), titleHeight, roundingX, roundingY)
        painter.drawRect(0, titleHeight * 0.5 + 2, rect.width(), titleHeight * 0.5)

        # painter.setPen(self.__linePen)
        # painter.drawLine(QtCore.QPoint(0, titleHeight), QtCore.QPoint(rect.width(), titleHeight))

        painter.setBrush(QtGui.QColor(0, 0, 0, 0))
        if self.__selected:
            painter.setPen(self.__selectedPen)
        else:
            painter.setPen(self.__unselectedPen)

        roundingY = 10
        roundingX = rect.height() / rect.width() * roundingY

        painter.drawRoundRect(rect, roundingX, roundingY)


    #########################
    ## Events

    def mousePressEvent(self, event):
        if event.button() is QtCore.Qt.MouseButton.LeftButton:

            modifiers = event.modifiers()
            if modifiers == QtCore.Qt.ControlModifier:
                if not self.isSelected():
                    self.__graph.selectNode(self, clearSelection=False)
                else:
                    self.__graph.deselectNode(self)

            elif modifiers == QtCore.Qt.ShiftModifier:
                if not self.isSelected():
                    self.__graph.selectNode(self, clearSelection=False)
            else:
                if not self.isSelected():
                    self.__graph.selectNode(self, clearSelection=True)

                    # Push all nodes back 1 level in z depth to bring selected
                    # node to front
                    for node in [x for x in self.__graph.getNodes().values()]:
                        if node == self:
                            continue

                        if node.zValue() != 0.0:
                            node.setZValue(node.zValue() - 1)

                self.__dragging = True
                self._mouseDownPoint = self.mapToScene(event.pos())
                self._mouseDelta = self._mouseDownPoint - self.getGraphPos()
                self._lastDragPoint = self._mouseDownPoint
                self._nodesMoved = False

        else:
            super(Node, self).mousePressEvent(event)


    def mouseMoveEvent(self, event):
        if self.__dragging:
            newPos = self.mapToScene(event.pos())

            graph = self.getGraph()
            if graph.getSnapToGrid() is True:
                gridSize = graph.getGridSize()

                newNodePos = newPos - self._mouseDelta

                snapPosX = math.floor(newNodePos.x() / gridSize) * gridSize
                snapPosY = math.floor(newNodePos.y() / gridSize) * gridSize
                snapPos = QtCore.QPointF(snapPosX, snapPosY)

                newPosOffset = snapPos - newNodePos

                newPos = newPos + newPosOffset

            delta = newPos - self._lastDragPoint
            self.__graph.moveSelectedNodes(delta)
            self._lastDragPoint = newPos
            self._nodesMoved = True
        else:
            super(Node, self).mouseMoveEvent(event)


    def mouseReleaseEvent(self, event):
        if self.__dragging:
            if self._nodesMoved:

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

                delta = newPos - self._mouseDownPoint
                self.__graph.endMoveSelectedNodes(delta)

            self.setCursor(QtCore.Qt.ArrowCursor)
            self.__dragging = False
        else:
            super(Node, self).mouseReleaseEvent(event)


    #########################
    ## shut down

    def disconnectAllPorts(self):
        # gather all the connections into a list, and then remove them from the graph.
        # This is because we can't remove connections from ports while
        # iterating over the set.
        connections = []

        for port in self.__ports:
            if port.inCircle():
                for connection in port.inCircle().getConnections():
                    connections.append(connection)
            if port.outCircle():
                for connection in port.outCircle().getConnections():
                    connections.append(connection)

        for connection in connections:
            self.__graph.removeConnection(connection)
コード例 #21
0
ファイル: color_editor.py プロジェクト: yes7rose/Kraken
 def setEditorValue(self, value):
     self.__color = QtGui.QColor(value.r * 255, value.g * 255,
                                 value.b * 255)
     self._qgraphcsView.setBackgroundBrush(self.__color)
     self._qgraphcsView.update()
コード例 #22
0
 def getColor(self):
     color = QtGui.QColor(self.__color)
     color.setAlpha(255)
     return color
コード例 #23
0
ファイル: port.py プロジェクト: mjcg91/Kraken
class BasePort(QtWidgets.QGraphicsWidget):

    _labelColor = QtGui.QColor(25, 25, 25)
    _labelHighlightColor = QtGui.QColor(225, 225, 225, 255)

    def __init__(self, parent, graph, name, color, dataType,
                 connectionPointType):
        super(BasePort, self).__init__(parent)

        self._node = parent
        self._graph = graph
        self._name = name
        self._dataType = dataType
        self._connectionPointType = connectionPointType

        self.setSizePolicy(
            QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                  QtWidgets.QSizePolicy.Fixed))

        layout = QtWidgets.QGraphicsLinearLayout()
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)

        self._color = color

        self._inCircle = None
        self._outCircle = None
        self._labelItem = None

        self._inCircleHolder = ItemHolder(self)
        self._outCircleHolder = ItemHolder(self)
        self._labelItemHolder = ItemHolder(self)

        self.layout().addItem(self._inCircleHolder)
        self.layout().setAlignment(
            self._inCircleHolder, QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)

        self.layout().addItem(self._labelItemHolder)
        self.layout().setAlignment(
            self._labelItemHolder,
            QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)

        self.layout().addItem(self._outCircleHolder)
        self.layout().setAlignment(
            self._outCircleHolder,
            QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)

    def getName(self):
        return self._name

    def getDataType(self):
        return self._dataType

    def getNode(self):
        return self._node

    def getGraph(self):
        return self._graph

    def getColor(self):
        return self._color

    def setColor(self, color):
        if self._inCircle is not None:
            self._inCircle.setColor(color)
        if self._outCircle is not None:
            self._outCircle.setColor(color)
        self._color = color

    def inCircle(self):
        return self._inCircle

    def setInCircle(self, inCircle):
        self._inCircleHolder.setItem(inCircle)
        self._inCircle = inCircle
        self.layout().insertStretch(2, 2)
        self.updatecontentMargins()

    def outCircle(self):
        return self._outCircle

    def setOutCircle(self, outCircle):
        self._outCircleHolder.setItem(outCircle)
        self._outCircle = outCircle
        self.layout().insertStretch(1, 2)
        self.updatecontentMargins()

    def updatecontentMargins(self):
        left = 0
        right = 0
        if self._inCircle is None:
            left = 30
        if self._outCircle is None:
            right = 30
        self.layout().setContentsMargins(left, 0, right, 0)

    def labelItem(self):
        return self._labelItem

    def setLabelItem(self, labelItem):
        self._labelItemHolder.setItem(labelItem)
        self._labelItem = labelItem

    # ===================
    # Connection Methods
    # ===================
    def connectionPointType(self):
        return self._connectionPointType
コード例 #24
0
class Connection(QtWidgets.QGraphicsPathItem):
    __defaultPen = QtGui.QPen(QtGui.QColor(168, 134, 3), 1.5)

    def __init__(self, graph, srcPortCircle, dstPortCircle):
        super(Connection, self).__init__()

        self.__graph = graph
        self.__srcPortCircle = srcPortCircle
        self.__dstPortCircle = dstPortCircle
        penStyle = QtCore.Qt.DashLine

        self.__connectionColor = QtGui.QColor(0, 0, 0)
        self.__connectionColor.setRgbF(
            *self.__srcPortCircle.getColor().getRgbF())
        self.__connectionColor.setAlpha(125)

        self.__defaultPen = QtGui.QPen(self.__connectionColor, 1.5, s=penStyle)
        self.__defaultPen.setDashPattern([1, 2, 2, 1])

        self.__connectionHoverColor = QtGui.QColor(0, 0, 0)
        self.__connectionHoverColor.setRgbF(
            *self.__srcPortCircle.getColor().getRgbF())
        self.__connectionHoverColor.setAlpha(255)

        self.__hoverPen = QtGui.QPen(self.__connectionHoverColor,
                                     1.5,
                                     s=penStyle)
        self.__hoverPen.setDashPattern([1, 2, 2, 1])

        self.setPen(self.__defaultPen)
        self.setZValue(-1)

        self.setAcceptHoverEvents(True)
        self.connect()

    def setPenStyle(self, penStyle):
        self.__defaultPen.setStyle(penStyle)
        self.__hoverPen.setStyle(penStyle)
        self.setPen(self.__defaultPen)  # Force a redraw

    def setPenWidth(self, width):
        self.__defaultPen.setWidthF(width)
        self.__hoverPen.setWidthF(width)
        self.setPen(self.__defaultPen)  # Force a redraw

    def getSrcPortCircle(self):
        return self.__srcPortCircle

    def getDstPortCircle(self):
        return self.__dstPortCircle

    def getSrcPort(self):
        return self.__srcPortCircle.getPort()

    def getDstPort(self):
        return self.__dstPortCircle.getPort()

    def boundingRect(self):
        srcPoint = self.mapFromScene(
            self.__srcPortCircle.centerInSceneCoords())
        dstPoint = self.mapFromScene(
            self.__dstPortCircle.centerInSceneCoords())
        penWidth = self.__defaultPen.width()

        return QtCore.QRectF(
            min(srcPoint.x(), dstPoint.x()),
            min(srcPoint.y(), dstPoint.y()),
            abs(dstPoint.x() - srcPoint.x()),
            abs(dstPoint.y() - srcPoint.y()),
        ).adjusted(-penWidth / 2, -penWidth / 2, +penWidth / 2, +penWidth / 2)

    def paint(self, painter, option, widget):
        srcPoint = self.mapFromScene(
            self.__srcPortCircle.centerInSceneCoords())
        dstPoint = self.mapFromScene(
            self.__dstPortCircle.centerInSceneCoords())

        dist_between = dstPoint - srcPoint

        self.__path = QtGui.QPainterPath()
        self.__path.moveTo(srcPoint)
        self.__path.cubicTo(
            srcPoint + QtCore.QPointF(dist_between.x() * 0.4, 0),
            dstPoint - QtCore.QPointF(dist_between.x() * 0.4, 0), dstPoint)
        self.setPath(self.__path)
        super(Connection, self).paint(painter, option, widget)

    def hoverEnterEvent(self, event):
        self.setPen(self.__hoverPen)
        super(Connection, self).hoverEnterEvent(event)

    def hoverLeaveEvent(self, event):
        self.setPen(self.__defaultPen)
        super(Connection, self).hoverLeaveEvent(event)

    def mousePressEvent(self, event):
        if event.button() is QtCore.Qt.MouseButton.LeftButton:
            self.__dragging = True
            self._lastDragPoint = self.mapToScene(event.pos())
            event.accept()
        else:
            super(Connection, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if self.__dragging:
            pos = self.mapToScene(event.pos())
            delta = pos - self._lastDragPoint
            if delta.x() != 0:

                self.__graph.removeConnection(self)

                import mouse_grabber
                if delta.x() < 0:
                    mouse_grabber.MouseGrabber(self.__graph, pos,
                                               self.__srcPortCircle, 'In')
                else:
                    mouse_grabber.MouseGrabber(self.__graph, pos,
                                               self.__dstPortCircle, 'Out')

        else:
            super(Connection, self).mouseMoveEvent(event)

    def disconnect(self):
        self.__srcPortCircle.removeConnection(self)
        self.__dstPortCircle.removeConnection(self)

    def connect(self):
        self.__srcPortCircle.addConnection(self)
        self.__dstPortCircle.addConnection(self)
コード例 #25
0
class GraphView(QtWidgets.QGraphicsView):

    nodeAdded = QtCore.Signal(Node)
    nodeRemoved = QtCore.Signal(Node)
    nodeNameChanged = QtCore.Signal(str, str)
    beginDeleteSelection = QtCore.Signal()
    endDeleteSelection = QtCore.Signal()

    beginConnectionManipulation = QtCore.Signal()
    endConnectionManipulation = QtCore.Signal()
    connectionAdded = QtCore.Signal(Connection)
    connectionRemoved = QtCore.Signal(Connection)

    beginNodeSelection = QtCore.Signal()
    endNodeSelection = QtCore.Signal()
    selectionChanged = QtCore.Signal(list, list)

    # During the movement of the nodes, this signal is emitted with the incremental delta.
    selectionMoved = QtCore.Signal(set, QtCore.QPointF)

    # After moving the nodes interactively, this signal is emitted with the final delta.
    endSelectionMoved = QtCore.Signal(set, QtCore.QPointF)

    _clipboardData = None

    _backgroundColor = QtGui.QColor(50, 50, 50)
    _gridPenS = QtGui.QPen(QtGui.QColor(44, 44, 44, 255), 0.5)
    _gridPenL = QtGui.QPen(QtGui.QColor(40, 40, 40, 255), 1.0)
    _gridSizeFine = 30
    _gridSizeCourse = 300

    _mouseWheelZoomRate = 0.0005

    _snapToGrid = False

    def __init__(self, parent=None):
        super(GraphView, self).__init__(parent)
        self.setObjectName('graphView')

        self.__graphViewWidget = parent

        self.setRenderHint(QtGui.QPainter.Antialiasing)
        self.setRenderHint(QtGui.QPainter.TextAntialiasing)

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

        # Explicitly set the scene rect. This ensures all view parameters will be explicitly controlled
        # in the event handlers of this class.
        size = QtCore.QSize(600, 400)
        self.resize(size)
        self.setSceneRect(-size.width() * 0.5, -size.height() * 0.5,
                          size.width(), size.height())

        self.setAcceptDrops(True)
        self.reset()

    def getGraphViewWidget(self):
        return self.__graphViewWidget

    ################################################
    ## Graph
    def reset(self):
        self.setScene(QtWidgets.QGraphicsScene())

        self.__connections = set()
        self.__nodes = {}
        self.__selection = set()

        self._manipulationMode = MANIP_MODE_NONE
        self._selectionRect = None

    def getGridSize(self):
        """Gets the size of the grid of the graph.

        Returns:
            int: Size of the grid.

        """

        return self._gridSizeFine

    def getSnapToGrid(self):
        """Gets the snap to grid value.

        Returns:
            Boolean: Whether snap to grid is active or not.

        """

        return self._snapToGrid

    def setSnapToGrid(self, snap):
        """Sets the snap to grid value.

        Args:
            snap (Boolean): True to snap to grid, false not to.

        """

        self._snapToGrid = snap

    ################################################
    ## Nodes

    def addNode(self, node, emitSignal=True):
        self.scene().addItem(node)
        self.__nodes[node.getName()] = node
        node.nameChanged.connect(self._onNodeNameChanged)

        if emitSignal:
            self.nodeAdded.emit(node)

        return node

    def removeNode(self, node, emitSignal=True):

        del self.__nodes[node.getName()]
        self.scene().removeItem(node)
        node.nameChanged.disconnect(self._onNodeNameChanged)

        if emitSignal:
            self.nodeRemoved.emit(node)

    def hasNode(self, name):
        return name in self.__nodes

    def getNode(self, name):
        if name in self.__nodes:
            return self.__nodes[name]
        return None

    def getNodes(self):
        return self.__nodes

    def _onNodeNameChanged(self, origName, newName):
        if newName in self.__nodes and self.__nodes[origName] != self.__nodes[
                newName]:
            raise Exception("New name collides with existing node.")
        node = self.__nodes[origName]
        self.__nodes[newName] = node
        del self.__nodes[origName]
        self.nodeNameChanged.emit(origName, newName)

    def clearSelection(self, emitSignal=True):

        prevSelection = []
        if emitSignal:
            for node in self.__selection:
                prevSelection.append(node)

        for node in self.__selection:
            node.setSelected(False)
        self.__selection.clear()

        if emitSignal and len(prevSelection) != 0:
            self.selectionChanged.emit(prevSelection, [])

    def selectNode(self, node, clearSelection=False, emitSignal=True):
        prevSelection = []
        if emitSignal:
            for n in self.__selection:
                prevSelection.append(n)

        if clearSelection is True:
            self.clearSelection(emitSignal=False)

        if node in self.__selection:
            raise IndexError("Node is already in selection!")

        node.setSelected(True)
        self.__selection.add(node)

        if emitSignal:

            newSelection = []
            for n in self.__selection:
                newSelection.append(n)

            self.selectionChanged.emit(prevSelection, newSelection)

    def deselectNode(self, node, emitSignal=True):

        if node not in self.__selection:
            raise IndexError("Node is not in selection!")

        prevSelection = []
        if emitSignal:
            for n in self.__selection:
                prevSelection.append(n)

        node.setSelected(False)
        self.__selection.remove(node)

        if emitSignal:
            newSelection = []
            for n in self.__selection:
                newSelection.append(n)

            self.selectionChanged.emit(prevSelection, newSelection)

    def getSelectedNodes(self):
        return self.__selection

    def deleteSelectedNodes(self):
        self.beginDeleteSelection.emit()

        selectedNodes = self.getSelectedNodes()
        names = ""
        for node in selectedNodes:
            node.disconnectAllPorts()
            self.removeNode(node)

        self.endDeleteSelection.emit()

    def frameNodes(self, nodes):
        if len(nodes) == 0:
            return

        def computeWindowFrame():
            windowRect = self.rect()
            windowRect.setLeft(windowRect.left() + 16)
            windowRect.setRight(windowRect.right() - 16)
            windowRect.setTop(windowRect.top() + 16)
            windowRect.setBottom(windowRect.bottom() - 16)
            return windowRect

        nodesRect = None
        for node in nodes:
            nodeRectF = node.transform().mapRect(node.rect())
            nodeRect = QtCore.QRect(nodeRectF.x(), nodeRectF.y(),
                                    nodeRectF.width(), nodeRectF.height())
            if nodesRect is None:
                nodesRect = nodeRect
            else:
                nodesRect = nodesRect.united(nodeRect)

        windowRect = computeWindowFrame()

        scaleX = float(windowRect.width()) / float(nodesRect.width())
        scaleY = float(windowRect.height()) / float(nodesRect.height())
        if scaleY > scaleX:
            scale = scaleX
        else:
            scale = scaleY

        if scale < 1.0:
            self.setTransform(QtGui.QTransform.fromScale(scale, scale))
        else:
            self.setTransform(QtGui.QTransform())

        sceneRect = self.sceneRect()
        pan = sceneRect.center() - nodesRect.center()
        sceneRect.translate(-pan.x(), -pan.y())
        self.setSceneRect(sceneRect)

        # Update the main panel when reframing.
        self.update()

    def frameSelectedNodes(self):
        self.frameNodes(self.getSelectedNodes())

    def frameAllNodes(self):
        allnodes = []
        for name, node in self.__nodes.iteritems():
            allnodes.append(node)
        self.frameNodes(allnodes)

    def getSelectedNodesCentroid(self):
        selectedNodes = self.getSelectedNodes()

        leftMostNode = None
        topMostNode = None
        for node in selectedNodes:
            nodePos = node.getGraphPos()

            if leftMostNode is None:
                leftMostNode = node
            else:
                if nodePos.x() < leftMostNode.getGraphPos().x():
                    leftMostNode = node

            if topMostNode is None:
                topMostNode = node
            else:
                if nodePos.y() < topMostNode.getGraphPos().y():
                    topMostNode = node

        xPos = leftMostNode.getGraphPos().x()
        yPos = topMostNode.getGraphPos().y()
        pos = QtCore.QPoint(xPos, yPos)

        return pos

    def moveSelectedNodes(self, delta, emitSignal=True):
        for node in self.__selection:
            node.translate(delta.x(), delta.y())

        if emitSignal:
            self.selectionMoved.emit(self.__selection, delta)

    # After moving the nodes interactively, this signal is emitted with the final delta.
    def endMoveSelectedNodes(self, delta):
        self.endSelectionMoved.emit(self.__selection, delta)

    ################################################
    ## Connections

    def emitBeginConnectionManipulationSignal(self):
        self.beginConnectionManipulation.emit()

    def emitEndConnectionManipulationSignal(self):
        self.endConnectionManipulation.emit()

    def addConnection(self, connection, emitSignal=True):

        self.__connections.add(connection)
        self.scene().addItem(connection)
        if emitSignal:
            self.connectionAdded.emit(connection)
        return connection

    def removeConnection(self, connection, emitSignal=True):

        connection.disconnect()
        self.__connections.remove(connection)
        self.scene().removeItem(connection)
        if emitSignal:
            self.connectionRemoved.emit(connection)

    def connectPorts(self, srcNode, outputName, tgtNode, inputName):

        if isinstance(srcNode, Node):
            sourceNode = srcNode
        elif isinstance(srcNode, basestring):
            sourceNode = self.getNode(srcNode)
            if not sourceNode:
                raise Exception("Node not found:" + str(srcNode))
        else:
            raise Exception("Invalid srcNode:" + str(srcNode))

        sourcePort = sourceNode.getOutputPort(outputName)
        if not sourcePort:
            raise Exception("Node '" + sourceNode.getName() +
                            "' does not have output:" + outputName)

        if isinstance(tgtNode, Node):
            targetNode = tgtNode
        elif isinstance(tgtNode, basestring):
            targetNode = self.getNode(tgtNode)
            if not targetNode:
                raise Exception("Node not found:" + str(tgtNode))
        else:
            raise Exception("Invalid tgtNode:" + str(tgtNode))

        targetPort = targetNode.getInputPort(inputName)
        if not targetPort:
            raise Exception("Node '" + targetNode.getName() +
                            "' does not have input:" + inputName)

        connection = Connection(self, sourcePort.outCircle(),
                                targetPort.inCircle())
        self.addConnection(connection, emitSignal=False)

        return connection

    ################################################
    ## Events

    def mousePressEvent(self, event):

        if event.button() is QtCore.Qt.MouseButton.LeftButton and self.itemAt(
                event.pos()) is None:
            self.beginNodeSelection.emit()
            self._manipulationMode = MANIP_MODE_SELECT
            self._mouseDownSelection = copy.copy(self.getSelectedNodes())
            self._selectionRect = SelectionRect(graph=self,
                                                mouseDownPos=self.mapToScene(
                                                    event.pos()))

        elif event.button() is QtCore.Qt.MouseButton.MiddleButton:
            self.setCursor(QtCore.Qt.OpenHandCursor)
            self._manipulationMode = MANIP_MODE_PAN
            self._lastPanPoint = self.mapToScene(event.pos())

        elif event.button() is QtCore.Qt.MouseButton.RightButton:
            self.setCursor(QtCore.Qt.SizeHorCursor)
            self._manipulationMode = MANIP_MODE_ZOOM
            self._lastZoomPoint = self.mapToScene(event.pos())
            self._lastTransform = QtGui.QTransform(self.transform())

        else:
            super(GraphView, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        modifiers = QtWidgets.QApplication.keyboardModifiers()

        if self._manipulationMode == MANIP_MODE_SELECT:
            dragPoint = self.mapToScene(event.pos())
            self._selectionRect.setDragPoint(dragPoint)

            # This logic allows users to use ctrl and shift with rectangle
            # select to add / remove nodes.
            if modifiers == QtCore.Qt.ControlModifier:
                for name, node in self.__nodes.iteritems():

                    if node in self._mouseDownSelection:
                        if node.isSelected(
                        ) and self._selectionRect.collidesWithItem(node):
                            self.deselectNode(node, emitSignal=False)
                        elif not node.isSelected(
                        ) and not self._selectionRect.collidesWithItem(node):
                            self.selectNode(node, emitSignal=False)
                    else:
                        if not node.isSelected(
                        ) and self._selectionRect.collidesWithItem(node):
                            self.selectNode(node, emitSignal=False)
                        elif node.isSelected(
                        ) and not self._selectionRect.collidesWithItem(node):
                            if node not in self._mouseDownSelection:
                                self.deselectNode(node, emitSignal=False)

            elif modifiers == QtCore.Qt.ShiftModifier:
                for name, node in self.__nodes.iteritems():
                    if not node.isSelected(
                    ) and self._selectionRect.collidesWithItem(node):
                        self.selectNode(node, emitSignal=False)
                    elif node.isSelected(
                    ) and not self._selectionRect.collidesWithItem(node):
                        if node not in self._mouseDownSelection:
                            self.deselectNode(node, emitSignal=False)

            else:
                self.clearSelection(emitSignal=False)

                for name, node in self.__nodes.iteritems():
                    if not node.isSelected(
                    ) and self._selectionRect.collidesWithItem(node):
                        self.selectNode(node, emitSignal=False)
                    elif node.isSelected(
                    ) and not self._selectionRect.collidesWithItem(node):
                        self.deselectNode(node, emitSignal=False)

        elif self._manipulationMode == MANIP_MODE_PAN:
            delta = self.mapToScene(event.pos()) - self._lastPanPoint

            rect = self.sceneRect()
            rect.translate(-delta.x(), -delta.y())
            self.setSceneRect(rect)

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

        elif self._manipulationMode == MANIP_MODE_MOVE:

            newPos = self.mapToScene(event.pos())
            delta = newPos - self._lastDragPoint
            self._lastDragPoint = newPos

            selectedNodes = self.getSelectedNodes()

            # Apply the delta to each selected node
            for node in selectedNodes:
                node.translate(delta.x(), delta.y())

        elif self._manipulationMode == MANIP_MODE_ZOOM:

            # How much
            delta = event.pos() - self._lastMousePos
            zoomFactor = 1.0
            if delta.x() > 0:
                zoomFactor = 1.0 + delta.x() / 100.0
            else:
                zoomFactor = 1.0 / (1.0 + abs(delta.x()) / 100.0)

            # Limit zoom to 3x
            if self._lastTransform.m22() * zoomFactor >= 2.0:
                return

            # Reset to when we mouse pressed
            self.setSceneRect(self._lastSceneRect)
            self.setTransform(self._lastTransform)

            # Center scene around mouse down
            rect = self.sceneRect()
            rect.translate(self._lastOffsetFromSceneCenter)
            self.setSceneRect(rect)

            # Zoom in (QGraphicsView auto-centers!)
            self.scale(zoomFactor, zoomFactor)

            newSceneCenter = self.sceneRect().center()
            newScenePos = self.mapToScene(self._lastMousePos)
            newOffsetFromSceneCenter = newScenePos - newSceneCenter

            # Put mouse down back where is was on screen
            rect = self.sceneRect()
            rect.translate(-1 * newOffsetFromSceneCenter)
            self.setSceneRect(rect)

            # Call udpate to redraw background
            self.update()

        else:
            super(GraphView, self).mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        if self._manipulationMode == MANIP_MODE_SELECT:

            # If users simply clicks in the empty space, clear selection.
            if self.mapToScene(event.pos()) == self._selectionRect.pos():
                self.clearSelection(emitSignal=False)

            self._selectionRect.destroy()
            self._selectionRect = None
            self._manipulationMode = MANIP_MODE_NONE

            selection = self.getSelectedNodes()

            deselectedNodes = []
            selectedNodes = []

            for node in self._mouseDownSelection:
                if node not in selection:
                    deselectedNodes.append(node)

            for node in selection:
                if node not in self._mouseDownSelection:
                    selectedNodes.append(node)

            if selectedNodes != deselectedNodes:
                self.selectionChanged.emit(deselectedNodes, selectedNodes)

            self.endNodeSelection.emit()

        elif self._manipulationMode == MANIP_MODE_PAN:
            self.setCursor(QtCore.Qt.ArrowCursor)
            self._manipulationMode = MANIP_MODE_NONE

        elif self._manipulationMode == MANIP_MODE_ZOOM:
            self.setCursor(QtCore.Qt.ArrowCursor)
            self._manipulationMode = MANIP_MODE_NONE
            #self.setTransformationAnchor(self._lastAnchor)

        else:
            super(GraphView, self).mouseReleaseEvent(event)

    def wheelEvent(self, event):

        zoomFactor = 1.0 + event.delta() * self._mouseWheelZoomRate

        transform = self.transform()
        # Limit zoom to 3x
        if transform.m22() * zoomFactor >= 2.0:
            return

        sceneCenter = self.sceneRect().center()
        scenePoint = self.mapToScene(event.pos())
        posFromSceneCenter = scenePoint - sceneCenter

        rect = self.sceneRect()
        rect.translate(posFromSceneCenter)
        self.setSceneRect(rect)

        # Zoom in (QGraphicsView auto-centers!)
        self.scale(zoomFactor, zoomFactor)

        # Translate scene back to align original mouse press
        sceneCenter = self.sceneRect().center()
        scenePoint = self.mapToScene(event.pos())
        posFromSceneCenter = scenePoint - sceneCenter

        rect = self.sceneRect()
        posFromSceneCenter *= -1.0
        rect.translate(posFromSceneCenter)
        self.setSceneRect(rect)

        # Call udpate to redraw background
        self.update()

    ################################################
    ## Painting

    def drawBackground(self, painter, rect):

        oldTransform = painter.transform()
        painter.fillRect(rect, self._backgroundColor)

        left = int(rect.left()) - (int(rect.left()) % self._gridSizeFine)
        top = int(rect.top()) - (int(rect.top()) % self._gridSizeFine)

        # Draw horizontal fine lines
        gridLines = []
        painter.setPen(self._gridPenS)
        y = float(top)
        while y < float(rect.bottom()):
            gridLines.append(QtCore.QLineF(rect.left(), y, rect.right(), y))
            y += self._gridSizeFine
        painter.drawLines(gridLines)

        # Draw vertical fine lines
        gridLines = []
        painter.setPen(self._gridPenS)
        x = float(left)
        while x < float(rect.right()):
            gridLines.append(QtCore.QLineF(x, rect.top(), x, rect.bottom()))
            x += self._gridSizeFine
        painter.drawLines(gridLines)

        # Draw thick grid
        left = int(rect.left()) - (int(rect.left()) % self._gridSizeCourse)
        top = int(rect.top()) - (int(rect.top()) % self._gridSizeCourse)

        # Draw vertical thick lines
        gridLines = []
        painter.setPen(self._gridPenL)
        x = left
        while x < rect.right():
            gridLines.append(QtCore.QLineF(x, rect.top(), x, rect.bottom()))
            x += self._gridSizeCourse
        painter.drawLines(gridLines)

        # Draw horizontal thick lines
        gridLines = []
        painter.setPen(self._gridPenL)
        y = top
        while y < rect.bottom():
            gridLines.append(QtCore.QLineF(rect.left(), y, rect.right(), y))
            y += self._gridSizeCourse
        painter.drawLines(gridLines)

        return super(GraphView, self).drawBackground(painter, rect)