Exemplo n.º 1
0
class LiteralNode(AbstractResizableNode):
    """
    This class implements the 'Individual' node.
    """
    IndexLT = 0
    IndexLB = 1
    IndexBL = 2
    IndexBR = 3
    IndexRB = 4
    IndexRT = 5
    IndexTR = 6
    IndexTL = 7
    IndexEE = 8

    DefaultBrush = QtGui.QBrush(QtGui.QColor(252, 252, 252, 255))
    DefaultPen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.0,
                            QtCore.Qt.SolidLine, QtCore.Qt.RoundCap,
                            QtCore.Qt.RoundJoin)
    Identities = {Identity.Value}
    Type = Item.LiteralNode

    def __init__(self,
                 literal=None,
                 width=60,
                 height=60,
                 brush=None,
                 **kwargs):
        """
        Initialize the node.
        :type width: int
        :type height: int
        :type brush: QBrush
        """
        super().__init__(**kwargs)

        w = max(width, 60)
        h = max(height, 60)
        brush = brush or LiteralNode.DefaultBrush
        pen = LiteralNode.DefaultPen

        createPolygon = lambda x, y: QtGui.QPolygonF([
            QtCore.QPointF(-(x / 2), -((y / (1 + math.sqrt(2))) / 2)),
            QtCore.QPointF(-(x / 2), +((y / (1 + math.sqrt(2))) / 2)),
            QtCore.QPointF(-((x / (1 + math.sqrt(2))) / 2), +(y / 2)),
            QtCore.QPointF(+((x / (1 + math.sqrt(2))) / 2), +(y / 2)),
            QtCore.QPointF(+(x / 2), +((y / (1 + math.sqrt(2))) / 2)),
            QtCore.QPointF(+(x / 2), -((y / (1 + math.sqrt(2))) / 2)),
            QtCore.QPointF(+((x / (1 + math.sqrt(2))) / 2), -(y / 2)),
            QtCore.QPointF(-((x / (1 + math.sqrt(2))) / 2), -(y / 2)),
            QtCore.QPointF(-(x / 2), -((y / (1 + math.sqrt(2))) / 2)),
        ])

        self.background = Polygon(createPolygon(w + 8, h + 8))
        self.selection = Polygon(createPolygon(w + 8, h + 8))
        self.polygon = Polygon(createPolygon(w, h), brush, pen)

        self._literal = literal

        #self.label = NodeLabel(template='Empty', pos=self.center, parent=self, editable=True)
        #self.label.setAlignment(QtCore.Qt.AlignCenter)
        self.updateNode()
        #self.updateTextPos()

    @property
    def datatype(self):
        """
        Returns the datatype associated with this node.
        :rtype: IRI
        """
        if self._literal and self._literal.datatype:
            return self._literal.datatype
        else:
            return OWL2Datatype.PlainLiteral.value

    @property
    def lexicalForm(self):
        """
        Returns the lexical form of the literal associated with this node.
        :rtype: str
        """
        if self._literal:
            return self._literal.lexicalForm
        return None

    @property
    def language(self):
        if self._literal:
            return self._literal.language
        return None

    @property
    def literal(self):
        '''
        :rtype: Literal
        '''
        return self._literal

    @literal.setter
    def literal(self, literal):
        '''
        :type literal:Literal
        '''
        self._literal = literal
        if self.diagram:
            self.doUpdateNodeLabel()
        self.sgnNodeModified.emit()

    def initialLabelPosition(self):
        return self.center()

    #############################################
    #   SLOTS
    #################################
    @QtCore.pyqtSlot()
    def doUpdateNodeLabel(self):
        if self.label and not self.labelString == str(self.literal):
            self.labelString = str(self.literal)
            labelPos = lambda: self.label.pos()
            self.label.diagram.removeItem(self.label)
            self.label = NodeLabel(template=self.labelString,
                                   pos=labelPos,
                                   parent=self,
                                   editable=True)
            self.diagram.sgnUpdated.emit()
        else:
            self.labelString = str(self.literal)
            self.label = NodeLabel(template=self.labelString,
                                   pos=lambda: self.initialLabelPosition(),
                                   parent=self,
                                   editable=True)
            self.diagram.sgnUpdated.emit()

    #############################################
    #   INTERFACE
    #################################
    def mouseDoubleClickEvent(self, mouseEvent):
        """
        Executed when the mouse is double clicked on the text item.
        :type mouseEvent: QGraphicsSceneMouseEvent
        """
        self.session.doOpenLiteralDialog(self)
        mouseEvent.accept()

    def boundingRect(self):
        """
        Returns the shape bounding rectangle.
        :rtype: QtCore.QRectF
        """
        path = QtGui.QPainterPath()
        path.addPolygon(self.selection.geometry())
        return path.boundingRect()

    @staticmethod
    def compose(value, datatype):
        """
        Compose the value string.
        :type value: str
        :type datatype: Datatype
        :return: str
        """
        return '"{0}"^^{1}'.format(value.strip('"'), datatype.value)

    def copy(self, diagram):
        """
        Create a copy of the current item.
        :type diagram: Diagram
        """
        node = diagram.factory.create(
            self.type(), **{
                'id': self.id,
                'brush': self.brush(),
                'height': self.height(),
                'width': self.width(),
                'literal': self._literal,
            })
        node.setPos(self.pos())
        node.literal = self._literal
        node.setTextPos(node.mapFromScene(self.mapToScene(self.textPos())))
        return node

    def height(self):
        """
        Returns the height of the shape.
        :rtype: int
        """
        polygon = self.polygon.geometry()

        # return polygon[self.IndexTR].y() - polygon[self.IndexBR].y()
        return polygon[self.IndexBR].y() - polygon[self.IndexTR].y()

    def identity(self):
        """
        Returns the identity of the current node.
        :rtype: Identity
        """
        return Identity.Value

    def paint(self, painter, option, widget=None):
        """
        Paint the node in the diagram.
        :type painter: QPainter
        :type option: QStyleOptionGraphicsItem
        :type widget: QWidget
        """
        # SET THE RECT THAT NEEDS TO BE REPAINTED
        painter.setClipRect(option.exposedRect)
        # SELECTION AREA
        painter.setPen(self.selection.pen())
        painter.setBrush(self.selection.brush())
        painter.drawPolygon(self.selection.geometry())
        # SYNTAX VALIDATION
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        painter.setPen(self.background.pen())
        painter.setBrush(self.background.brush())
        painter.drawPolygon(self.background.geometry())
        # ITEM SHAPE
        painter.setPen(self.polygon.pen())
        painter.setBrush(self.polygon.brush())
        painter.drawPolygon(self.polygon.geometry())
        # RESIZE HANDLES
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        for polygon in self.handles:
            painter.setPen(polygon.pen())
            painter.setBrush(polygon.brush())
            painter.drawEllipse(polygon.geometry())

    def painterPath(self):
        """
        Returns the current shape as QtGui.QPainterPath (used for collision detection).
        :rtype: QPainterPath
        """
        path = QtGui.QPainterPath()
        path.addPolygon(self.polygon.geometry())
        return path

    def resize(self, mousePos):
        """
        Handle the interactive resize of the shape.
        :type mousePos: QtCore.QPointF
        """
        snap = self.session.action('toggle_grid').isChecked()
        size = self.diagram.GridSize
        moved = self.label.isMoved()

        background = self.background.geometry()
        selection = self.selection.geometry()
        polygon = self.polygon.geometry()

        R = QtCore.QRectF(self.boundingRect())
        D = QtCore.QPointF(0, 0)

        mbrh = 68
        mbrw = 68

        self.prepareGeometryChange()

        if self.mp_Handle == self.HandleTL:

            fromX = self.mp_Bound.left()
            fromY = self.mp_Bound.top()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, -4, snap)
            toY = snapF(toY, size, -4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setLeft(toX)
            R.setTop(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() - mbrw + R.width())
                R.setLeft(R.left() - mbrw + R.width())
            if R.height() < mbrh:
                D.setY(D.y() - mbrh + R.height())
                R.setTop(R.top() - mbrh + R.height())

            newSideY = (R.height() - 4 * 2) / (1 + math.sqrt(2))
            newSideX = (R.width() - 4 * 2) / (1 + math.sqrt(2))
            newLeftRightBottomY = (R.y() + R.height() / 2) + newSideY / 2
            newLeftRightTopY = (R.y() + R.height() / 2) - newSideY / 2
            newTopBottomLeftX = (R.x() + R.width() / 2) - newSideX / 2
            newTopBottomRightX = (R.x() + R.width() / 2) + newSideX / 2

            selection[self.IndexLT] = QtCore.QPointF(R.left(),
                                                     newLeftRightTopY)
            selection[self.IndexLB] = QtCore.QPointF(R.left(),
                                                     newLeftRightBottomY)
            selection[self.IndexRT] = QtCore.QPointF(R.right(),
                                                     newLeftRightTopY)
            selection[self.IndexRB] = QtCore.QPointF(R.right(),
                                                     newLeftRightBottomY)
            selection[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX,
                                                     R.top())
            selection[self.IndexTR] = QtCore.QPointF(newTopBottomRightX,
                                                     R.top())
            selection[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX,
                                                     R.bottom())
            selection[self.IndexBR] = QtCore.QPointF(newTopBottomRightX,
                                                     R.bottom())
            selection[self.IndexEE] = QtCore.QPointF(R.left(),
                                                     newLeftRightTopY)

            background[self.IndexLT] = QtCore.QPointF(R.left(),
                                                      newLeftRightTopY)
            background[self.IndexLB] = QtCore.QPointF(R.left(),
                                                      newLeftRightBottomY)
            background[self.IndexRT] = QtCore.QPointF(R.right(),
                                                      newLeftRightTopY)
            background[self.IndexRB] = QtCore.QPointF(R.right(),
                                                      newLeftRightBottomY)
            background[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX,
                                                      R.top())
            background[self.IndexTR] = QtCore.QPointF(newTopBottomRightX,
                                                      R.top())
            background[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX,
                                                      R.bottom())
            background[self.IndexBR] = QtCore.QPointF(newTopBottomRightX,
                                                      R.bottom())
            background[self.IndexEE] = QtCore.QPointF(R.left(),
                                                      newLeftRightTopY)

            polygon[self.IndexLT] = QtCore.QPointF(R.left() + 4,
                                                   newLeftRightTopY)
            polygon[self.IndexLB] = QtCore.QPointF(R.left() + 4,
                                                   newLeftRightBottomY)
            polygon[self.IndexRT] = QtCore.QPointF(R.right() - 4,
                                                   newLeftRightTopY)
            polygon[self.IndexRB] = QtCore.QPointF(R.right() - 4,
                                                   newLeftRightBottomY)
            polygon[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX,
                                                   R.top() + 4)
            polygon[self.IndexTR] = QtCore.QPointF(newTopBottomRightX,
                                                   R.top() + 4)
            polygon[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX,
                                                   R.bottom() - 4)
            polygon[self.IndexBR] = QtCore.QPointF(newTopBottomRightX,
                                                   R.bottom() - 4)
            polygon[self.IndexEE] = QtCore.QPointF(R.left() + 4,
                                                   newLeftRightTopY)

        elif self.mp_Handle == self.HandleTM:

            fromY = self.mp_Bound.top()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toY = snapF(toY, size, -4, snap)
            D.setY(toY - fromY)
            R.setTop(toY)

            ## CLAMP SIZE
            if R.height() < mbrh:
                D.setY(D.y() - mbrh + R.height())
                R.setTop(R.top() - mbrh + R.height())

            newSide = (R.height() - 4 * 2) / (1 + math.sqrt(2))
            newLeftRightBottomY = (R.y() + R.height() / 2) + newSide / 2
            newLeftRightTopY = (R.y() + R.height() / 2) - newSide / 2

            selection[self.IndexTL] = QtCore.QPointF(
                background[self.IndexTL].x(), R.top())
            selection[self.IndexTR] = QtCore.QPointF(
                background[self.IndexTR].x(), R.top())
            selection[self.IndexLB] = QtCore.QPointF(
                background[self.IndexLB].x(), newLeftRightBottomY)
            selection[self.IndexRB] = QtCore.QPointF(
                background[self.IndexRB].x(), newLeftRightBottomY)
            selection[self.IndexLT] = QtCore.QPointF(
                background[self.IndexLT].x(), newLeftRightTopY)
            selection[self.IndexRT] = QtCore.QPointF(
                background[self.IndexRT].x(), newLeftRightTopY)
            selection[self.IndexEE] = QtCore.QPointF(
                background[self.IndexEE].x(), newLeftRightTopY)

            background[self.IndexTL] = QtCore.QPointF(
                background[self.IndexTL].x(), R.top())
            background[self.IndexTR] = QtCore.QPointF(
                background[self.IndexTR].x(), R.top())
            background[self.IndexLB] = QtCore.QPointF(
                background[self.IndexLB].x(), newLeftRightBottomY)
            background[self.IndexRB] = QtCore.QPointF(
                background[self.IndexRB].x(), newLeftRightBottomY)
            background[self.IndexLT] = QtCore.QPointF(
                background[self.IndexLT].x(), newLeftRightTopY)
            background[self.IndexRT] = QtCore.QPointF(
                background[self.IndexRT].x(), newLeftRightTopY)
            background[self.IndexEE] = QtCore.QPointF(
                background[self.IndexEE].x(), newLeftRightTopY)

            polygon[self.IndexTL] = QtCore.QPointF(polygon[self.IndexTL].x(),
                                                   R.top() + 4)
            polygon[self.IndexTR] = QtCore.QPointF(polygon[self.IndexTR].x(),
                                                   R.top() + 4)
            polygon[self.IndexLB] = QtCore.QPointF(polygon[self.IndexLB].x(),
                                                   newLeftRightBottomY)
            polygon[self.IndexRB] = QtCore.QPointF(polygon[self.IndexRB].x(),
                                                   newLeftRightBottomY)
            polygon[self.IndexLT] = QtCore.QPointF(polygon[self.IndexLT].x(),
                                                   newLeftRightTopY)
            polygon[self.IndexRT] = QtCore.QPointF(polygon[self.IndexRT].x(),
                                                   newLeftRightTopY)
            polygon[self.IndexEE] = QtCore.QPointF(polygon[self.IndexEE].x(),
                                                   newLeftRightTopY)

        elif self.mp_Handle == self.HandleTR:

            fromX = self.mp_Bound.right()
            fromY = self.mp_Bound.top()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, +4, snap)
            toY = snapF(toY, size, -4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setRight(toX)
            R.setTop(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() + mbrw - R.width())
                R.setRight(R.right() + mbrw - R.width())
            if R.height() < mbrh:
                D.setY(D.y() - mbrh + R.height())
                R.setTop(R.top() - mbrh + R.height())

            newSideY = (R.height() - 4 * 2) / (1 + math.sqrt(2))
            newSideX = (R.width() - 4 * 2) / (1 + math.sqrt(2))
            newLeftRightBottomY = (R.y() + R.height() / 2) + newSideY / 2
            newLeftRightTopY = (R.y() + R.height() / 2) - newSideY / 2
            newTopBottomLeftX = (R.x() + R.width() / 2) - newSideX / 2
            newTopBottomRightX = (R.x() + R.width() / 2) + newSideX / 2

            selection[self.IndexLT] = QtCore.QPointF(R.left(),
                                                     newLeftRightTopY)
            selection[self.IndexLB] = QtCore.QPointF(R.left(),
                                                     newLeftRightBottomY)
            selection[self.IndexRT] = QtCore.QPointF(R.right(),
                                                     newLeftRightTopY)
            selection[self.IndexRB] = QtCore.QPointF(R.right(),
                                                     newLeftRightBottomY)
            selection[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX,
                                                     R.top())
            selection[self.IndexTR] = QtCore.QPointF(newTopBottomRightX,
                                                     R.top())
            selection[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX,
                                                     R.bottom())
            selection[self.IndexBR] = QtCore.QPointF(newTopBottomRightX,
                                                     R.bottom())
            selection[self.IndexEE] = QtCore.QPointF(R.left(),
                                                     newLeftRightTopY)

            background[self.IndexLT] = QtCore.QPointF(R.left(),
                                                      newLeftRightTopY)
            background[self.IndexLB] = QtCore.QPointF(R.left(),
                                                      newLeftRightBottomY)
            background[self.IndexRT] = QtCore.QPointF(R.right(),
                                                      newLeftRightTopY)
            background[self.IndexRB] = QtCore.QPointF(R.right(),
                                                      newLeftRightBottomY)
            background[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX,
                                                      R.top())
            background[self.IndexTR] = QtCore.QPointF(newTopBottomRightX,
                                                      R.top())
            background[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX,
                                                      R.bottom())
            background[self.IndexBR] = QtCore.QPointF(newTopBottomRightX,
                                                      R.bottom())
            background[self.IndexEE] = QtCore.QPointF(R.left(),
                                                      newLeftRightTopY)

            polygon[self.IndexLT] = QtCore.QPointF(R.left() + 4,
                                                   newLeftRightTopY)
            polygon[self.IndexLB] = QtCore.QPointF(R.left() + 4,
                                                   newLeftRightBottomY)
            polygon[self.IndexRT] = QtCore.QPointF(R.right() - 4,
                                                   newLeftRightTopY)
            polygon[self.IndexRB] = QtCore.QPointF(R.right() - 4,
                                                   newLeftRightBottomY)
            polygon[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX,
                                                   R.top() + 4)
            polygon[self.IndexTR] = QtCore.QPointF(newTopBottomRightX,
                                                   R.top() + 4)
            polygon[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX,
                                                   R.bottom() - 4)
            polygon[self.IndexBR] = QtCore.QPointF(newTopBottomRightX,
                                                   R.bottom() - 4)
            polygon[self.IndexEE] = QtCore.QPointF(R.left() + 4,
                                                   newLeftRightTopY)

        elif self.mp_Handle == self.HandleML:

            fromX = self.mp_Bound.left()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toX = snapF(toX, size, -4, snap)
            D.setX(toX - fromX)
            R.setLeft(toX)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() - mbrw + R.width())
                R.setLeft(R.left() - mbrw + R.width())

            newSide = (R.width() - 4 * 2) / (1 + math.sqrt(2))
            newTopBottomLeftX = (R.x() + R.width() / 2) - newSide / 2
            newTopBottomRightX = (R.x() + R.width() / 2) + newSide / 2

            selection[self.IndexLT] = QtCore.QPointF(
                R.left(), selection[self.IndexLT].y())
            selection[self.IndexLB] = QtCore.QPointF(
                R.left(), selection[self.IndexLB].y())
            selection[self.IndexEE] = QtCore.QPointF(
                R.left(), selection[self.IndexEE].y())
            selection[self.IndexTL] = QtCore.QPointF(
                newTopBottomLeftX, selection[self.IndexTL].y())
            selection[self.IndexTR] = QtCore.QPointF(
                newTopBottomRightX, selection[self.IndexTR].y())
            selection[self.IndexBL] = QtCore.QPointF(
                newTopBottomLeftX, selection[self.IndexBL].y())
            selection[self.IndexBR] = QtCore.QPointF(
                newTopBottomRightX, selection[self.IndexBR].y())

            background[self.IndexLT] = QtCore.QPointF(
                R.left(), background[self.IndexLT].y())
            background[self.IndexLB] = QtCore.QPointF(
                R.left(), background[self.IndexLB].y())
            background[self.IndexEE] = QtCore.QPointF(
                R.left(), background[self.IndexEE].y())
            background[self.IndexTL] = QtCore.QPointF(
                newTopBottomLeftX, background[self.IndexTL].y())
            background[self.IndexTR] = QtCore.QPointF(
                newTopBottomRightX, background[self.IndexTR].y())
            background[self.IndexBL] = QtCore.QPointF(
                newTopBottomLeftX, background[self.IndexBL].y())
            background[self.IndexBR] = QtCore.QPointF(
                newTopBottomRightX, background[self.IndexBR].y())

            polygon[self.IndexLT] = QtCore.QPointF(R.left() + 4,
                                                   polygon[self.IndexLT].y())
            polygon[self.IndexLB] = QtCore.QPointF(R.left() + 4,
                                                   polygon[self.IndexLB].y())
            polygon[self.IndexEE] = QtCore.QPointF(R.left() + 4,
                                                   polygon[self.IndexEE].y())
            polygon[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX,
                                                   polygon[self.IndexTL].y())
            polygon[self.IndexTR] = QtCore.QPointF(newTopBottomRightX,
                                                   polygon[self.IndexTR].y())
            polygon[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX,
                                                   polygon[self.IndexBL].y())
            polygon[self.IndexBR] = QtCore.QPointF(newTopBottomRightX,
                                                   polygon[self.IndexBR].y())

        elif self.mp_Handle == self.HandleMR:

            fromX = self.mp_Bound.right()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toX = snapF(toX, size, +4, snap)
            D.setX(toX - fromX)
            R.setRight(toX)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() + mbrw - R.width())
                R.setRight(R.right() + mbrw - R.width())

            newSide = (R.width() - 4 * 2) / (1 + math.sqrt(2))
            newTopBottomRightX = (R.x() + R.width() / 2) + newSide / 2
            newTopBottomLeftX = (R.x() + R.width() / 2) - newSide / 2

            selection[self.IndexRT] = QtCore.QPointF(
                R.right(), selection[self.IndexRT].y())
            selection[self.IndexRB] = QtCore.QPointF(
                R.right(), selection[self.IndexRB].y())
            selection[self.IndexTL] = QtCore.QPointF(
                newTopBottomLeftX, selection[self.IndexTL].y())
            selection[self.IndexTR] = QtCore.QPointF(
                newTopBottomRightX, selection[self.IndexTR].y())
            selection[self.IndexBL] = QtCore.QPointF(
                newTopBottomLeftX, selection[self.IndexBL].y())
            selection[self.IndexBR] = QtCore.QPointF(
                newTopBottomRightX, selection[self.IndexBR].y())

            background[self.IndexRT] = QtCore.QPointF(
                R.right(), background[self.IndexRT].y())
            background[self.IndexRB] = QtCore.QPointF(
                R.right(), background[self.IndexRB].y())
            background[self.IndexTL] = QtCore.QPointF(
                newTopBottomLeftX, background[self.IndexTL].y())
            background[self.IndexTR] = QtCore.QPointF(
                newTopBottomRightX, background[self.IndexTR].y())
            background[self.IndexBL] = QtCore.QPointF(
                newTopBottomLeftX, background[self.IndexBL].y())
            background[self.IndexBR] = QtCore.QPointF(
                newTopBottomRightX, background[self.IndexBR].y())

            polygon[self.IndexRT] = QtCore.QPointF(R.right() - 4,
                                                   polygon[self.IndexRT].y())
            polygon[self.IndexRB] = QtCore.QPointF(R.right() - 4,
                                                   polygon[self.IndexRB].y())
            polygon[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX,
                                                   polygon[self.IndexTL].y())
            polygon[self.IndexTR] = QtCore.QPointF(newTopBottomRightX,
                                                   polygon[self.IndexTR].y())
            polygon[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX,
                                                   polygon[self.IndexBL].y())
            polygon[self.IndexBR] = QtCore.QPointF(newTopBottomRightX,
                                                   polygon[self.IndexBR].y())

        elif self.mp_Handle == self.HandleBL:

            fromX = self.mp_Bound.left()
            fromY = self.mp_Bound.bottom()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, -4, snap)
            toY = snapF(toY, size, +4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setLeft(toX)
            R.setBottom(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() - mbrw + R.width())
                R.setLeft(R.left() - mbrw + R.width())
            if R.height() < mbrh:
                D.setY(D.y() + mbrh - R.height())
                R.setBottom(R.bottom() + mbrh - R.height())

            newSideY = (R.height() - 4 * 2) / (1 + math.sqrt(2))
            newSideX = (R.width() - 4 * 2) / (1 + math.sqrt(2))
            newLeftRightBottomY = (R.y() + R.height() / 2) + newSideY / 2
            newLeftRightTopY = (R.y() + R.height() / 2) - newSideY / 2
            newTopBottomLeftX = (R.x() + R.width() / 2) - newSideX / 2
            newTopBottomRightX = (R.x() + R.width() / 2) + newSideX / 2

            selection[self.IndexLT] = QtCore.QPointF(R.left(),
                                                     newLeftRightTopY)
            selection[self.IndexLB] = QtCore.QPointF(R.left(),
                                                     newLeftRightBottomY)
            selection[self.IndexRT] = QtCore.QPointF(R.right(),
                                                     newLeftRightTopY)
            selection[self.IndexRB] = QtCore.QPointF(R.right(),
                                                     newLeftRightBottomY)
            selection[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX,
                                                     R.top())
            selection[self.IndexTR] = QtCore.QPointF(newTopBottomRightX,
                                                     R.top())
            selection[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX,
                                                     R.bottom())
            selection[self.IndexBR] = QtCore.QPointF(newTopBottomRightX,
                                                     R.bottom())
            selection[self.IndexEE] = QtCore.QPointF(R.left(),
                                                     newLeftRightTopY)

            background[self.IndexLT] = QtCore.QPointF(R.left(),
                                                      newLeftRightTopY)
            background[self.IndexLB] = QtCore.QPointF(R.left(),
                                                      newLeftRightBottomY)
            background[self.IndexRT] = QtCore.QPointF(R.right(),
                                                      newLeftRightTopY)
            background[self.IndexRB] = QtCore.QPointF(R.right(),
                                                      newLeftRightBottomY)
            background[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX,
                                                      R.top())
            background[self.IndexTR] = QtCore.QPointF(newTopBottomRightX,
                                                      R.top())
            background[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX,
                                                      R.bottom())
            background[self.IndexBR] = QtCore.QPointF(newTopBottomRightX,
                                                      R.bottom())
            background[self.IndexEE] = QtCore.QPointF(R.left(),
                                                      newLeftRightTopY)

            polygon[self.IndexLT] = QtCore.QPointF(R.left() + 4,
                                                   newLeftRightTopY)
            polygon[self.IndexLB] = QtCore.QPointF(R.left() + 4,
                                                   newLeftRightBottomY)
            polygon[self.IndexRT] = QtCore.QPointF(R.right() - 4,
                                                   newLeftRightTopY)
            polygon[self.IndexRB] = QtCore.QPointF(R.right() - 4,
                                                   newLeftRightBottomY)
            polygon[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX,
                                                   R.top() + 4)
            polygon[self.IndexTR] = QtCore.QPointF(newTopBottomRightX,
                                                   R.top() + 4)
            polygon[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX,
                                                   R.bottom() - 4)
            polygon[self.IndexBR] = QtCore.QPointF(newTopBottomRightX,
                                                   R.bottom() - 4)
            polygon[self.IndexEE] = QtCore.QPointF(R.left() + 4,
                                                   newLeftRightTopY)

        elif self.mp_Handle == self.HandleBM:

            fromY = self.mp_Bound.bottom()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toY = snapF(toY, size, +4, snap)
            D.setY(toY - fromY)
            R.setBottom(toY)

            ## CLAMP SIZE
            if R.height() < mbrh:
                D.setY(D.y() + mbrh - R.height())
                R.setBottom(R.bottom() + mbrh - R.height())

            newSide = (R.height() - 4 * 2) / (1 + math.sqrt(2))
            newLeftRightTopY = (R.y() + R.height() / 2) - newSide / 2
            newLeftRightBottomY = (R.y() + R.height() / 2) + newSide / 2

            selection[self.IndexBL] = QtCore.QPointF(
                selection[self.IndexBL].x(), R.bottom())
            selection[self.IndexBR] = QtCore.QPointF(
                selection[self.IndexBR].x(), R.bottom())
            selection[self.IndexLB] = QtCore.QPointF(
                selection[self.IndexLB].x(), newLeftRightBottomY)
            selection[self.IndexRB] = QtCore.QPointF(
                selection[self.IndexRB].x(), newLeftRightBottomY)
            selection[self.IndexLT] = QtCore.QPointF(
                selection[self.IndexLT].x(), newLeftRightTopY)
            selection[self.IndexRT] = QtCore.QPointF(
                selection[self.IndexRT].x(), newLeftRightTopY)
            selection[self.IndexEE] = QtCore.QPointF(
                selection[self.IndexEE].x(), newLeftRightTopY)

            background[self.IndexBL] = QtCore.QPointF(
                background[self.IndexBL].x(), R.bottom())
            background[self.IndexBR] = QtCore.QPointF(
                background[self.IndexBR].x(), R.bottom())
            background[self.IndexLB] = QtCore.QPointF(
                background[self.IndexLB].x(), newLeftRightBottomY)
            background[self.IndexRB] = QtCore.QPointF(
                background[self.IndexRB].x(), newLeftRightBottomY)
            background[self.IndexLT] = QtCore.QPointF(
                background[self.IndexLT].x(), newLeftRightTopY)
            background[self.IndexRT] = QtCore.QPointF(
                background[self.IndexRT].x(), newLeftRightTopY)
            background[self.IndexEE] = QtCore.QPointF(
                background[self.IndexEE].x(), newLeftRightTopY)

            polygon[self.IndexBL] = QtCore.QPointF(polygon[self.IndexBL].x(),
                                                   R.bottom() - 4)
            polygon[self.IndexBR] = QtCore.QPointF(polygon[self.IndexBR].x(),
                                                   R.bottom() - 4)
            polygon[self.IndexLB] = QtCore.QPointF(polygon[self.IndexLB].x(),
                                                   newLeftRightBottomY)
            polygon[self.IndexRB] = QtCore.QPointF(polygon[self.IndexRB].x(),
                                                   newLeftRightBottomY)
            polygon[self.IndexLT] = QtCore.QPointF(polygon[self.IndexLT].x(),
                                                   newLeftRightTopY)
            polygon[self.IndexRT] = QtCore.QPointF(polygon[self.IndexRT].x(),
                                                   newLeftRightTopY)
            polygon[self.IndexEE] = QtCore.QPointF(polygon[self.IndexEE].x(),
                                                   newLeftRightTopY)

        elif self.mp_Handle == self.HandleBR:

            fromX = self.mp_Bound.right()
            fromY = self.mp_Bound.bottom()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, +4, snap)
            toY = snapF(toY, size, +4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setRight(toX)
            R.setBottom(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() + mbrw - R.width())
                R.setRight(R.right() + mbrw - R.width())
            if R.height() < mbrh:
                D.setY(D.y() + mbrh - R.height())
                R.setBottom(R.bottom() + mbrh - R.height())

            newSideY = (R.height() - 4 * 2) / (1 + math.sqrt(2))
            newSideX = (R.width() - 4 * 2) / (1 + math.sqrt(2))
            newLeftRightBottomY = (R.y() + R.height() / 2) + newSideY / 2
            newLeftRightTopY = (R.y() + R.height() / 2) - newSideY / 2
            newTopBottomLeftX = (R.x() + R.width() / 2) - newSideX / 2
            newTopBottomRightX = (R.x() + R.width() / 2) + newSideX / 2

            selection[self.IndexLT] = QtCore.QPointF(R.left(),
                                                     newLeftRightTopY)
            selection[self.IndexLB] = QtCore.QPointF(R.left(),
                                                     newLeftRightBottomY)
            selection[self.IndexRT] = QtCore.QPointF(R.right(),
                                                     newLeftRightTopY)
            selection[self.IndexRB] = QtCore.QPointF(R.right(),
                                                     newLeftRightBottomY)
            selection[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX,
                                                     R.top())
            selection[self.IndexTR] = QtCore.QPointF(newTopBottomRightX,
                                                     R.top())
            selection[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX,
                                                     R.bottom())
            selection[self.IndexBR] = QtCore.QPointF(newTopBottomRightX,
                                                     R.bottom())
            selection[self.IndexEE] = QtCore.QPointF(R.left(),
                                                     newLeftRightTopY)

            background[self.IndexLT] = QtCore.QPointF(R.left(),
                                                      newLeftRightTopY)
            background[self.IndexLB] = QtCore.QPointF(R.left(),
                                                      newLeftRightBottomY)
            background[self.IndexRT] = QtCore.QPointF(R.right(),
                                                      newLeftRightTopY)
            background[self.IndexRB] = QtCore.QPointF(R.right(),
                                                      newLeftRightBottomY)
            background[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX,
                                                      R.top())
            background[self.IndexTR] = QtCore.QPointF(newTopBottomRightX,
                                                      R.top())
            background[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX,
                                                      R.bottom())
            background[self.IndexBR] = QtCore.QPointF(newTopBottomRightX,
                                                      R.bottom())
            background[self.IndexEE] = QtCore.QPointF(R.left(),
                                                      newLeftRightTopY)

            polygon[self.IndexLT] = QtCore.QPointF(R.left() + 4,
                                                   newLeftRightTopY)
            polygon[self.IndexLB] = QtCore.QPointF(R.left() + 4,
                                                   newLeftRightBottomY)
            polygon[self.IndexRT] = QtCore.QPointF(R.right() - 4,
                                                   newLeftRightTopY)
            polygon[self.IndexRB] = QtCore.QPointF(R.right() - 4,
                                                   newLeftRightBottomY)
            polygon[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX,
                                                   R.top() + 4)
            polygon[self.IndexTR] = QtCore.QPointF(newTopBottomRightX,
                                                   R.top() + 4)
            polygon[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX,
                                                   R.bottom() - 4)
            polygon[self.IndexBR] = QtCore.QPointF(newTopBottomRightX,
                                                   R.bottom() - 4)
            polygon[self.IndexEE] = QtCore.QPointF(R.left() + 4,
                                                   newLeftRightTopY)

        self.background.setGeometry(background)
        self.selection.setGeometry(selection)
        self.polygon.setGeometry(polygon)

        self.updateNode(selected=True,
                        handle=self.mp_Handle,
                        anchors=(self.mp_Data, D))
        self.updateTextPos(moved=moved)

    def setIdentity(self, identity):
        """
        Set the identity of the current node.
        :type identity: Identity
        """
        pass

    def setText(self, text):
        """
        Set the label text: will additionally block label editing if a literal is being.
        :type text: str
        """
        self.label.setText(text)
        self.label.setAlignment(QtCore.Qt.AlignCenter)

    def setTextPos(self, pos):
        """
        Set the label position.
        :type pos: QPointF
        """
        self.label.setPos(pos)

    def shape(self):
        """
        Returns the shape of this item as a QPainterPath in local coordinates.
        :rtype: QPainterPath
        """
        path = QtGui.QPainterPath()
        path.addPolygon(self.polygon.geometry())
        for polygon in self.handles:
            path.addEllipse(polygon.geometry())
        return path

    def text(self):
        """
        Returns the label text.
        :rtype: str
        """
        return self.label.text()

    def textPos(self):
        """
        Returns the current label position in item coordinates.
        :rtype: QPointF
        """
        return self.label.pos()

    def updateTextPos(self, *args, **kwargs):
        """
        Update the label position.
        """
        self.label.updatePos(*args, **kwargs)

    def width(self):
        """
        Returns the width of the shape.
        :rtype: int
        """
        polygon = self.polygon.geometry()
        return polygon[self.IndexRT].x() - polygon[self.IndexLT].x()

    def __repr__(self):
        """
        Returns repr(self).
        """
        return '{0}:{1}:{2}'.format(self.__class__.__name__, self.text(),
                                    self.id)
Exemplo n.º 2
0
class ConceptNode(AbstractResizableNode):
    """
    This class implements the 'Concept' node.
    """
    DefaultBrush = QtGui.QBrush(QtGui.QColor(252, 252, 252, 255))
    DefaultPen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.0, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
    Identities = {Identity.Concept}
    Type = Item.ConceptNode

    def __init__(self, width=110, height=50, brush=None, **kwargs):
        """
        Initialize the node.
        :type width: int
        :type height: int
        :type brush: QBrush
        """
        super().__init__(**kwargs)
        w = max(width, 110)
        h = max(height, 50)
        brush = brush or ConceptNode.DefaultBrush
        pen = ConceptNode.DefaultPen
        self.background = Polygon(QtCore.QRectF(-(w + 8) / 2, -(h + 8) / 2, w + 8, h + 8))
        self.selection = Polygon(QtCore.QRectF(-(w + 8) / 2, -(h + 8) / 2, w + 8, h + 8))
        self.polygon = Polygon(QtCore.QRectF(-w / 2, -h / 2, w, h), brush, pen)
        self.label = NodeLabel(template='concept', pos=self.center, parent=self)
        self.label.setAlignment(QtCore.Qt.AlignCenter)
        self.updateNode()
        self.updateTextPos()

    #############################################
    #   INTERFACE
    #################################

    def boundingRect(self):
        """
        Returns the shape bounding rectangle.
        :rtype: QtCore.QRectF
        """
        return self.selection.geometry()

    def copy(self, diagram):
        """
        Create a copy of the current item.
        :type diagram: Diagram
        """
        node = diagram.factory.create(self.type(), **{
            'id': self.id,
            'brush': self.brush(),
            'height': self.height(),
            'width': self.width()
        })
        node.setPos(self.pos())
        node.setText(self.text())
        node.setTextPos(node.mapFromScene(self.mapToScene(self.textPos())))
        return node

    def height(self):
        """
        Returns the height of the shape.
        :rtype: int
        """
        return self.polygon.geometry().height()

    def identity(self):
        """
        Returns the identity of the current node.
        :rtype: Identity
        """
        return Identity.Concept

    def paint(self, painter, option, widget=None):
        """
        Paint the node in the diagram.
        :type painter: QPainter
        :type option: QStyleOptionGraphicsItem
        :type widget: QWidget
        """
        # SET THE RECT THAT NEEDS TO BE REPAINTED
        painter.setClipRect(option.exposedRect)
        # SELECTION AREA
        painter.setPen(self.selection.pen())
        painter.setBrush(self.selection.brush())
        painter.drawRect(self.selection.geometry())
        # SYNTAX VALIDATION
        painter.setPen(self.background.pen())
        painter.setBrush(self.background.brush())
        painter.drawRect(self.background.geometry())
        # ITEM SHAPE
        painter.setPen(self.polygon.pen())
        painter.setBrush(self.polygon.brush())
        painter.drawRect(self.polygon.geometry())
        # RESIZE HANDLES
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        for polygon in self.handles:
            painter.setPen(polygon.pen())
            painter.setBrush(polygon.brush())
            painter.drawEllipse(polygon.geometry())

    def painterPath(self):
        """
        Returns the current shape as QtGui.QPainterPath (used for collision detection).
        :rtype: QPainterPath
        """
        path = QtGui.QPainterPath()
        path.addRect(self.polygon.geometry())
        return path

    def resize(self, mousePos):
        """
        Handle the interactive resize of the shape.
        :type mousePos: QtCore.QPointF
        """
        snap = self.session.action('toggle_grid').isChecked()
        size = self.diagram.GridSize
        moved = self.label.isMoved()
        background = self.background.geometry()
        selection = self.selection.geometry()
        polygon = self.polygon.geometry()

        R = QtCore.QRectF(self.boundingRect())
        D = QtCore.QPointF(0, 0)

        mbrh = 58
        mbrw = 118

        self.prepareGeometryChange()

        if self.mp_Handle == self.HandleTL:

            fromX = self.mp_Bound.left()
            fromY = self.mp_Bound.top()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, -4, snap)
            toY = snapF(toY, size, -4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setLeft(toX)
            R.setTop(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() - mbrw + R.width())
                R.setLeft(R.left() - mbrw + R.width())
            if R.height() < mbrh:
                D.setY(D.y() - mbrh + R.height())
                R.setTop(R.top() - mbrh + R.height())

            background.setLeft(R.left())
            background.setTop(R.top())
            selection.setLeft(R.left())
            selection.setTop(R.top())
            polygon.setLeft(R.left() + 4)
            polygon.setTop(R.top() + 4)

        elif self.mp_Handle == self.HandleTM:

            fromY = self.mp_Bound.top()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toY = snapF(toY, size, -4, snap)
            D.setY(toY - fromY)
            R.setTop(toY)

            ## CLAMP SIZE
            if R.height() < mbrh:
                D.setY(D.y() - mbrh + R.height())
                R.setTop(R.top() - mbrh + R.height())

            background.setTop(R.top())
            selection.setTop(R.top())
            polygon.setTop(R.top() + 4)

        elif self.mp_Handle == self.HandleTR:

            fromX = self.mp_Bound.right()
            fromY = self.mp_Bound.top()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, +4, snap)
            toY = snapF(toY, size, -4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setRight(toX)
            R.setTop(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() + mbrw - R.width())
                R.setRight(R.right() + mbrw - R.width())
            if R.height() < mbrh:
                D.setY(D.y() - mbrh + R.height())
                R.setTop(R.top() - mbrh + R.height())

            background.setRight(R.right())
            background.setTop(R.top())
            selection.setRight(R.right())
            selection.setTop(R.top())
            polygon.setRight(R.right() - 4)
            polygon.setTop(R.top() + 4)

        elif self.mp_Handle == self.HandleML:

            fromX = self.mp_Bound.left()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toX = snapF(toX, size, -4, snap)
            D.setX(toX - fromX)
            R.setLeft(toX)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() - mbrw + R.width())
                R.setLeft(R.left() - mbrw + R.width())

            background.setLeft(R.left())
            selection.setLeft(R.left())
            polygon.setLeft(R.left() + 4)

        elif self.mp_Handle == self.HandleMR:

            fromX = self.mp_Bound.right()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toX = snapF(toX, size, +4, snap)
            D.setX(toX - fromX)
            R.setRight(toX)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() + mbrw - R.width())
                R.setRight(R.right() + mbrw - R.width())

            background.setRight(R.right())
            selection.setRight(R.right())
            polygon.setRight(R.right() - 4)

        elif self.mp_Handle == self.HandleBL:

            fromX = self.mp_Bound.left()
            fromY = self.mp_Bound.bottom()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, -4, snap)
            toY = snapF(toY, size, +4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setLeft(toX)
            R.setBottom(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() - mbrw + R.width())
                R.setLeft(R.left() - mbrw + R.width())
            if R.height() < mbrh:
                D.setY(D.y() + mbrh - R.height())
                R.setBottom(R.bottom() + mbrh - R.height())

            background.setLeft(R.left())
            background.setBottom(R.bottom())
            selection.setLeft(R.left())
            selection.setBottom(R.bottom())
            polygon.setLeft(R.left() + 4)
            polygon.setBottom(R.bottom() - 4)

        elif self.mp_Handle == self.HandleBM:

            fromY = self.mp_Bound.bottom()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toY = snapF(toY, size, +4, snap)
            D.setY(toY - fromY)
            R.setBottom(toY)

            ## CLAMP SIZE
            if R.height() < mbrh:
                D.setY(D.y() + mbrh - R.height())
                R.setBottom(R.bottom() + mbrh - R.height())

            background.setBottom(R.bottom())
            selection.setBottom(R.bottom())
            polygon.setBottom(R.bottom() - 4)

        elif self.mp_Handle == self.HandleBR:

            fromX = self.mp_Bound.right()
            fromY = self.mp_Bound.bottom()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, +4, snap)
            toY = snapF(toY, size, +4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setRight(toX)
            R.setBottom(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() + mbrw - R.width())
                R.setRight(R.right() + mbrw - R.width())
            if R.height() < mbrh:
                D.setY(D.y() + mbrh - R.height())
                R.setBottom(R.bottom() + mbrh - R.height())

            background.setRight(R.right())
            background.setBottom(R.bottom())
            selection.setRight(R.right())
            selection.setBottom(R.bottom())
            polygon.setRight(R.right() - 4)
            polygon.setBottom(R.bottom() - 4)

        self.background.setGeometry(background)
        self.selection.setGeometry(selection)
        self.polygon.setGeometry(polygon)

        self.updateNode(selected=True, handle=self.mp_Handle, anchors=(self.mp_Data, D))
        self.updateTextPos(moved=moved)

    def setIdentity(self, identity):
        """
        Set the identity of the current node.
        :type identity: Identity
        """
        pass

    def setText(self, text):
        """
        Set the label text.
        :type text: str
        """
        self.label.setText(text)
        self.label.setAlignment(QtCore.Qt.AlignCenter)

    def setTextPos(self, pos):
        """
        Set the label position.
        :type pos: QPointF
        """
        self.label.setPos(pos)

    def shape(self):
        """
        Returns the shape of this item as a QPainterPath in local coordinates.
        :rtype: QPainterPath
        """
        path = QtGui.QPainterPath()
        path.addRect(self.polygon.geometry())
        for polygon in self.handles:
            path.addEllipse(polygon.geometry())
        return path

    def special(self):
        """
        Returns the special type of this node.
        :rtype: Special
        """
        return Special.valueOf(self.text())

    def text(self):
        """
        Returns the label text.
        :rtype: str
        """
        return self.label.text()

    def textPos(self):
        """
        Returns the current label position in item coordinates.
        :rtype: QPointF
        """
        return self.label.pos()

    def updateTextPos(self, *args, **kwargs):
        """
        Update the label position.
        """
        self.label.updatePos(*args, **kwargs)

    def width(self):
        """
        Returns the width of the shape.
        :rtype: int
        """
        return self.polygon.geometry().width()

    def __repr__(self):
        """
        Returns repr(self).
        """
        return '{0}:{1}:{2}'.format(self.__class__.__name__, self.text(), self.id)
Exemplo n.º 3
0
class AttributeNode(AbstractNode):
    """
    This class implements the 'Attribute' node.
    """
    DefaultBrush = QtGui.QBrush(QtGui.QColor(252, 252, 252, 255))
    DefaultPen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.1,
                            QtCore.Qt.SolidLine, QtCore.Qt.RoundCap,
                            QtCore.Qt.RoundJoin)
    Identities = {Identity.Attribute}
    Type = Item.AttributeNode

    def __init__(self,
                 width=20,
                 height=20,
                 brush=None,
                 remaining_characters='attribute',
                 **kwargs):
        """
        Initialize the node.
        :type width: int
        :type height: int
        :type brush: QBrush
        """
        super().__init__(**kwargs)
        brush = brush or AttributeNode.DefaultBrush
        pen = AttributeNode.DefaultPen
        self.fpolygon = Polygon(QtGui.QPainterPath())
        self.background = Polygon(QtCore.QRectF(-14, -14, 28, 28))
        self.selection = Polygon(QtCore.QRectF(-14, -14, 28, 28))
        self.polygon = Polygon(QtCore.QRectF(-10, -10, 20, 20), brush, pen)

        self.remaining_characters = remaining_characters

        self.label = NodeLabel(
            template='attribute',
            pos=lambda: self.center() - QtCore.QPointF(0, 22),
            parent=self,
            editable=True)
        self.label.setAlignment(QtCore.Qt.AlignCenter)

    #############################################
    #   INTERFACE
    #################################

    def boundingRect(self):
        """
        Returns the shape bounding rectangle.
        :rtype: QRectF
        """
        return self.selection.geometry()

    def copy(self, diagram):
        """
        Create a copy of the current item.
        :type diagram: Diagram
        """
        node = diagram.factory.create(
            self.type(), **{
                'id': self.id,
                'brush': self.brush(),
                'height': self.height(),
                'width': self.width(),
                'remaining_characters': self.remaining_characters,
            })
        node.setPos(self.pos())
        node.setText(self.text())
        node.setTextPos(node.mapFromScene(self.mapToScene(self.textPos())))
        return node

    def definition(self):
        """
        Returns the list of nodes which contribute to the definition of this very node.
        :rtype: set
        """
        f1 = lambda x: x.type() is Item.InputEdge
        f2 = lambda x: x.type(
        ) in {Item.DomainRestrictionNode, Item.RangeRestrictionNode}
        return set(self.outgoingNodes(filter_on_edges=f1, filter_on_nodes=f2))

    def height(self):
        """
        Returns the height of the shape.
        :rtype: int
        """
        return self.polygon.geometry().height()

    def identity(self):
        """
        Returns the identity of the current node.
        :rtype: Identity
        """
        return Identity.Attribute

    def isFunctional(self):
        """
        Returns True if the predicate represented by this node is functional, else False.
        :rtype: bool
        """
        try:
            return self.project.meta(self.type(),
                                     self.text())[K_FUNCTIONAL]  #\
            #and \
            #self.project.profile.type() is not OWLProfile.OWL2QL

        except (AttributeError, KeyError):
            return False

    def paint(self, painter, option, widget=None):
        """
        Paint the node in the diagram.
        :type painter: QPainter
        :type option: QStyleOptionGraphicsItem
        :type widget: QWidget
        """
        # SET THE RECT THAT NEEDS TO BE REPAINTED
        painter.setClipRect(option.exposedRect)
        # SELECTION AREA
        painter.setPen(self.selection.pen())
        painter.setBrush(self.selection.brush())
        painter.drawEllipse(self.selection.geometry())
        # SYNTAX VALIDATION
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        painter.setPen(self.background.pen())
        painter.setBrush(self.background.brush())
        painter.drawEllipse(self.background.geometry())
        # ITEM SHAPE
        painter.setPen(self.polygon.pen())
        painter.setBrush(self.polygon.brush())
        painter.drawEllipse(self.polygon.geometry())
        # FUNCTIONALITY
        painter.setPen(self.fpolygon.pen())
        painter.setBrush(self.fpolygon.brush())
        painter.drawPath(self.fpolygon.geometry())

    def painterPath(self):
        """
        Returns the current shape as QPainterPath (used for collision detection).
        :rtype: QPainterPath
        """
        path = QtGui.QPainterPath()
        path.addEllipse(self.polygon.geometry())
        return path

    def setFunctional(self, functional):
        """
        Set the functional property of the predicate represented by this node.
        :type functional: bool
        """
        meta = self.project.meta(self.type(), self.text())
        meta[K_FUNCTIONAL] = bool(functional)
        self.project.setMeta(self.type(), self.text(), meta)
        for node in self.project.predicates(self.type(), self.text()):
            node.updateNode(functional=functional, selected=node.isSelected())

    def setIdentity(self, identity):
        """
        Set the identity of the current node.
        :type identity: Identity
        """
        pass

    def setText(self, text):
        """
        Set the label text.
        :type text: str
        """
        self.label.setText(text)
        self.label.setAlignment(QtCore.Qt.AlignCenter)

    def setTextPos(self, pos):
        """
        Set the label position.
        :type pos: QPointF
        """
        self.label.setPos(pos)

    def shape(self):
        """
        Returns the shape of this item as a QPainterPath in local coordinates.
        :rtype: QPainterPath
        """
        path = QtGui.QPainterPath()
        path.addEllipse(self.polygon.geometry())
        return path

    def special(self):
        """
        Returns the special type of this node.
        :rtype: Special
        """
        return Special.valueOf(self.text())

    def text(self):
        """
        Returns the label text.
        :rtype: str
        """
        return self.label.text()

    def textPos(self):
        """
        Returns the current label position in item coordinates.
        :rtype: QPointF
        """
        return self.label.pos()

    def updateNode(self, functional=None, **kwargs):
        """
        Update the current node.
        :type functional: bool
        """
        if functional is None:
            functional = self.isFunctional()

        # FUNCTIONAL POLYGON (SHAPE)
        path1 = QtGui.QPainterPath()
        path1.addEllipse(self.polygon.geometry())
        path2 = QtGui.QPainterPath()
        path2.addEllipse(QtCore.QRectF(-7, -7, 14, 14))
        self.fpolygon.setGeometry(path1.subtracted(path2))

        # FUNCTIONAL POLYGON (PEN & BRUSH)
        pen = QtGui.QPen(QtCore.Qt.NoPen)
        brush = QtGui.QBrush(QtCore.Qt.NoBrush)
        if functional:
            pen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.1,
                             QtCore.Qt.SolidLine, QtCore.Qt.RoundCap,
                             QtCore.Qt.RoundJoin)
            brush = QtGui.QBrush(QtGui.QColor(252, 252, 252, 255))
        self.fpolygon.setPen(pen)
        self.fpolygon.setBrush(brush)

        # SELECTION + BACKGROUND + CACHE REFRESH
        super().updateNode(**kwargs)

    def updateTextPos(self, *args, **kwargs):
        """
        Update the label position.
        """
        self.label.updatePos(*args, **kwargs)

    def width(self):
        """
        Returns the width of the shape.
        :rtype: int
        """
        return self.polygon.geometry().width()

    def __repr__(self):
        """
        Returns repr(self).
        """
        return '{0}:{1}:{2}'.format(self.__class__.__name__, self.text(),
                                    self.id)
Exemplo n.º 4
0
class RoleNode(AbstractResizableNode):
    """
    This class implements the 'Role' node.
    """
    IndexL = 0
    IndexB = 1
    IndexR = 2
    IndexT = 3
    IndexE = 4

    DefaultBrush = QtGui.QBrush(QtGui.QColor(252, 252, 252, 255))
    DefaultPen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.1,
                            QtCore.Qt.SolidLine, QtCore.Qt.RoundCap,
                            QtCore.Qt.RoundJoin)
    Identities = {Identity.Role}
    Type = Item.RoleNode

    def __init__(self,
                 width=70,
                 height=50,
                 brush=None,
                 remaining_characters='role',
                 **kwargs):
        """
        Initialize the node.
        :type width: int
        :type height: int
        :type brush: QBrush
        """
        super().__init__(**kwargs)

        w = max(width, 70)
        h = max(height, 50)
        brush = brush or RoleNode.DefaultBrush
        pen = RoleNode.DefaultPen

        createPolygon = lambda x, y: QtGui.QPolygonF([
            QtCore.QPointF(-x / 2, 0),
            QtCore.QPointF(0, +y / 2),
            QtCore.QPointF(+x / 2, 0),
            QtCore.QPointF(0, -y / 2),
            QtCore.QPointF(-x / 2, 0)
        ])

        self.fpolygon = Polygon(QtGui.QPainterPath())
        self.ipolygon = Polygon(QtGui.QPainterPath())
        self.background = Polygon(createPolygon(w + 8, h + 8))
        self.selection = Polygon(createPolygon(w + 8, h + 8))
        self.polygon = Polygon(createPolygon(w, h), brush, pen)

        self.remaining_characters = remaining_characters

        self.label = NodeLabel(template='role',
                               pos=self.center,
                               parent=self,
                               editable=True)
        self.label.setAlignment(QtCore.Qt.AlignCenter)
        self.updateNode()
        self.updateTextPos()

    #############################################
    #   INTERFACE
    #################################

    def boundingRect(self):
        """
        Returns the shape bounding rectangle.
        :rtype: QtCore.QRectF
        """
        path = QtGui.QPainterPath()
        path.addPolygon(self.selection.geometry())
        return path.boundingRect()

    def copy(self, diagram):
        """
        Create a copy of the current item.
        :type diagram: Diagram
        """
        node = diagram.factory.create(
            self.type(), **{
                'id': self.id,
                'brush': self.brush(),
                'height': self.height(),
                'width': self.width(),
                'remaining_characters': self.remaining_characters,
            })
        node.setPos(self.pos())
        node.setText(self.text())
        node.setTextPos(node.mapFromScene(self.mapToScene(self.textPos())))
        return node

    def definition(self):
        """
        Returns the list of nodes which contribute to the definition of this very node.
        :rtype: set
        """
        f1 = lambda x: x.type() is Item.InputEdge
        f2 = lambda x: x.type(
        ) in {Item.DomainRestrictionNode, Item.RangeRestrictionNode}
        return self.outgoingNodes(filter_on_edges=f1, filter_on_nodes=f2)

    def height(self):
        """
        Returns the height of the shape.
        :rtype: int
        """
        polygon = self.polygon.geometry()
        return polygon[self.IndexB].y() - polygon[self.IndexT].y()

    def identity(self):
        """
        Returns the identity of the current node.
        :rtype: Identity
        """
        return Identity.Role

    def isAsymmetric(self):
        """
        Returns True if the predicate represented by this node is asymmetric, False otherwise.
        :rtype: bool
        """
        try:
            return self.project.meta(self.type(), self.text())[K_ASYMMETRIC]
        except (AttributeError, KeyError):
            return False

    def isFunctional(self):
        """
        Returns True if the predicate represented by this node is functional, else False.
        :rtype: bool
        """
        try:
            return self.project.meta(self.type(),
                                     self.text())[K_FUNCTIONAL]  #and \
            #self.project.profile.type() is not OWLProfile.OWL2QL
        except (AttributeError, KeyError):
            return False

    def isInverseFunctional(self):
        """
        Returns True if the predicate represented by this node is inverse functional, else False.
        :rtype: bool
        """
        try:
            return self.project.meta(self.type(),
                                     self.text())[K_INVERSE_FUNCTIONAL]  #and \
            #self.project.profile.type() is not OWLProfile.OWL2QL
        except (AttributeError, KeyError):
            return False

    def isIrreflexive(self):
        """
        Returns True if the predicate represented by this node is irreflexive, False otherwise.
        :rtype: bool
        """
        try:
            return self.project.meta(self.type(), self.text())[K_IRREFLEXIVE]
        except (AttributeError, KeyError):
            return False

    def isReflexive(self):
        """
        Returns True if the predicate represented by this node is reflexive, False otherwise.
        :rtype: bool
        """
        try:
            return self.project.meta(self.type(),
                                     self.text())[K_REFLEXIVE]  #and \
            #self.project.profile.type() is not OWLProfile.OWL2RL
        except (AttributeError, KeyError):
            return False

    def isSymmetric(self):
        """
        Returns True if the predicate represented by this node is symmetric, False otherwise.
        :rtype: bool
        """
        try:
            return self.project.meta(self.type(), self.text())[K_SYMMETRIC]
        except (AttributeError, KeyError):
            return False

    def isTransitive(self):
        """
        Returns True if the transitive represented by this node is symmetric, False otherwise.
        :rtype: bool
        """
        try:
            return self.project.meta(self.type(),
                                     self.text())[K_TRANSITIVE]  #and \
            #self.project.profile.type() is not OWLProfile.OWL2QL
        except (AttributeError, KeyError):
            return False

    def paint(self, painter, option, widget=None):
        """
        Paint the node in the diagram.
        :type painter: QPainter
        :type option: QStyleOptionGraphicsItem
        :type widget: QWidget
        """
        # SET THE RECT THAT NEEDS TO BE REPAINTED
        painter.setClipRect(option.exposedRect)
        # SELECTION AREA
        painter.setPen(self.selection.pen())
        painter.setBrush(self.selection.brush())
        painter.drawPolygon(self.selection.geometry())
        # SYNTAX VALIDATION
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        painter.setPen(self.background.pen())
        painter.setBrush(self.background.brush())
        painter.drawPolygon(self.background.geometry())
        # ITEM SHAPE
        painter.setPen(self.polygon.pen())
        painter.setBrush(self.polygon.brush())
        painter.drawPolygon(self.polygon.geometry())
        # FUNCTIONALITY
        painter.setPen(self.fpolygon.pen())
        painter.setBrush(self.fpolygon.brush())
        painter.drawPath(self.fpolygon.geometry())
        # INVERSE FUNCTIONALITY
        painter.setPen(self.ipolygon.pen())
        painter.setBrush(self.ipolygon.brush())
        painter.drawPath(self.ipolygon.geometry())
        # RESIZE HANDLES
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        for polygon in self.handles:
            painter.setPen(polygon.pen())
            painter.setBrush(polygon.brush())
            painter.drawEllipse(polygon.geometry())

    def painterPath(self):
        """
        Returns the current shape as QtGui.QPainterPath (used for collision detection).
        :rtype: QPainterPath
        """
        path = QtGui.QPainterPath()
        path.addPolygon(self.polygon.geometry())
        return path

    def resize(self, mousePos):
        """
        Handle the interactive resize of the shape.
        :type mousePos: QtCore.QPointF
        """
        snap = self.session.action('toggle_grid').isChecked()
        size = self.diagram.GridSize
        moved = self.label.isMoved()

        background = self.background.geometry()
        selection = self.selection.geometry()
        polygon = self.polygon.geometry()

        R = QtCore.QRectF(self.boundingRect())
        D = QtCore.QPointF(0, 0)

        mbrh = 58
        mbrw = 78

        self.prepareGeometryChange()

        if self.mp_Handle == self.HandleTL:

            fromX = self.mp_Bound.left()
            fromY = self.mp_Bound.top()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, -4, snap)
            toY = snapF(toY, size, -4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setLeft(toX)
            R.setTop(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() - mbrw + R.width())
                R.setLeft(R.left() - mbrw + R.width())
            if R.height() < mbrh:
                D.setY(D.y() - mbrh + R.height())
                R.setTop(R.top() - mbrh + R.height())

            selection[self.IndexT] = QtCore.QPointF(R.left() + R.width() / 2,
                                                    R.top())
            selection[self.IndexB] = QtCore.QPointF(R.left() + R.width() / 2,
                                                    selection[self.IndexB].y())
            selection[self.IndexL] = QtCore.QPointF(R.left(),
                                                    R.top() + R.height() / 2)
            selection[self.IndexE] = QtCore.QPointF(R.left(),
                                                    R.top() + R.height() / 2)
            selection[self.IndexR] = QtCore.QPointF(selection[self.IndexR].x(),
                                                    R.top() + R.height() / 2)

            background[self.IndexT] = QtCore.QPointF(R.left() + R.width() / 2,
                                                     R.top())
            background[self.IndexB] = QtCore.QPointF(
                R.left() + R.width() / 2, background[self.IndexB].y())
            background[self.IndexL] = QtCore.QPointF(R.left(),
                                                     R.top() + R.height() / 2)
            background[self.IndexE] = QtCore.QPointF(R.left(),
                                                     R.top() + R.height() / 2)
            background[self.IndexR] = QtCore.QPointF(
                background[self.IndexR].x(),
                R.top() + R.height() / 2)

            polygon[self.IndexT] = QtCore.QPointF(R.left() + R.width() / 2,
                                                  R.top() + 4)
            polygon[self.IndexB] = QtCore.QPointF(R.left() + R.width() / 2,
                                                  polygon[self.IndexB].y())
            polygon[self.IndexL] = QtCore.QPointF(R.left() + 4,
                                                  R.top() + R.height() / 2)
            polygon[self.IndexE] = QtCore.QPointF(R.left() + 4,
                                                  R.top() + R.height() / 2)
            polygon[self.IndexR] = QtCore.QPointF(polygon[self.IndexR].x(),
                                                  R.top() + R.height() / 2)

        elif self.mp_Handle == self.HandleTM:

            fromY = self.mp_Bound.top()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toY = snapF(toY, size, -4, snap)
            D.setY(toY - fromY)
            R.setTop(toY)

            ## CLAMP SIZE
            if R.height() < mbrh:
                D.setY(D.y() - mbrh + R.height())
                R.setTop(R.top() - mbrh + R.height())

            selection[self.IndexT] = QtCore.QPointF(selection[self.IndexT].x(),
                                                    R.top())
            selection[self.IndexL] = QtCore.QPointF(selection[self.IndexL].x(),
                                                    R.top() + R.height() / 2)
            selection[self.IndexE] = QtCore.QPointF(selection[self.IndexE].x(),
                                                    R.top() + R.height() / 2)
            selection[self.IndexR] = QtCore.QPointF(selection[self.IndexR].x(),
                                                    R.top() + R.height() / 2)

            background[self.IndexT] = QtCore.QPointF(
                background[self.IndexT].x(), R.top())
            background[self.IndexL] = QtCore.QPointF(
                background[self.IndexL].x(),
                R.top() + R.height() / 2)
            background[self.IndexE] = QtCore.QPointF(
                background[self.IndexE].x(),
                R.top() + R.height() / 2)
            background[self.IndexR] = QtCore.QPointF(
                background[self.IndexR].x(),
                R.top() + R.height() / 2)

            polygon[self.IndexT] = QtCore.QPointF(polygon[self.IndexT].x(),
                                                  R.top() + 4)
            polygon[self.IndexL] = QtCore.QPointF(polygon[self.IndexL].x(),
                                                  R.top() + R.height() / 2)
            polygon[self.IndexE] = QtCore.QPointF(polygon[self.IndexE].x(),
                                                  R.top() + R.height() / 2)
            polygon[self.IndexR] = QtCore.QPointF(polygon[self.IndexR].x(),
                                                  R.top() + R.height() / 2)

        elif self.mp_Handle == self.HandleTR:

            fromX = self.mp_Bound.right()
            fromY = self.mp_Bound.top()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, +4, snap)
            toY = snapF(toY, size, -4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setRight(toX)
            R.setTop(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() + mbrw - R.width())
                R.setRight(R.right() + mbrw - R.width())
            if R.height() < mbrh:
                D.setY(D.y() - mbrh + R.height())
                R.setTop(R.top() - mbrh + R.height())

            selection[self.IndexT] = QtCore.QPointF(R.right() - R.width() / 2,
                                                    R.top())
            selection[self.IndexB] = QtCore.QPointF(R.right() - R.width() / 2,
                                                    selection[self.IndexB].y())
            selection[self.IndexL] = QtCore.QPointF(selection[self.IndexL].x(),
                                                    R.top() + R.height() / 2)
            selection[self.IndexE] = QtCore.QPointF(selection[self.IndexE].x(),
                                                    R.top() + R.height() / 2)
            selection[self.IndexR] = QtCore.QPointF(R.right(),
                                                    R.top() + R.height() / 2)

            background[self.IndexT] = QtCore.QPointF(R.right() - R.width() / 2,
                                                     R.top())
            background[self.IndexB] = QtCore.QPointF(
                R.right() - R.width() / 2, background[self.IndexB].y())
            background[self.IndexL] = QtCore.QPointF(
                background[self.IndexL].x(),
                R.top() + R.height() / 2)
            background[self.IndexE] = QtCore.QPointF(
                background[self.IndexE].x(),
                R.top() + R.height() / 2)
            background[self.IndexR] = QtCore.QPointF(R.right(),
                                                     R.top() + R.height() / 2)

            polygon[self.IndexT] = QtCore.QPointF(R.right() - R.width() / 2,
                                                  R.top() + 4)
            polygon[self.IndexB] = QtCore.QPointF(R.right() - R.width() / 2,
                                                  polygon[self.IndexB].y())
            polygon[self.IndexL] = QtCore.QPointF(polygon[self.IndexL].x(),
                                                  R.top() + R.height() / 2)
            polygon[self.IndexE] = QtCore.QPointF(polygon[self.IndexE].x(),
                                                  R.top() + R.height() / 2)
            polygon[self.IndexR] = QtCore.QPointF(R.right() - 4,
                                                  R.top() + R.height() / 2)

        elif self.mp_Handle == self.HandleML:

            fromX = self.mp_Bound.left()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toX = snapF(toX, size, -4, snap)
            D.setX(toX - fromX)
            R.setLeft(toX)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() - mbrw + R.width())
                R.setLeft(R.left() - mbrw + R.width())

            selection[self.IndexL] = QtCore.QPointF(
                R.left(),
                self.mp_Bound.top() + self.mp_Bound.height() / 2)
            selection[self.IndexE] = QtCore.QPointF(
                R.left(),
                self.mp_Bound.top() + self.mp_Bound.height() / 2)
            selection[self.IndexT] = QtCore.QPointF(R.left() + R.width() / 2,
                                                    selection[self.IndexT].y())
            selection[self.IndexB] = QtCore.QPointF(R.left() + R.width() / 2,
                                                    selection[self.IndexB].y())

            background[self.IndexL] = QtCore.QPointF(
                R.left(),
                self.mp_Bound.top() + self.mp_Bound.height() / 2)
            background[self.IndexE] = QtCore.QPointF(
                R.left(),
                self.mp_Bound.top() + self.mp_Bound.height() / 2)
            background[self.IndexT] = QtCore.QPointF(
                R.left() + R.width() / 2, background[self.IndexT].y())
            background[self.IndexB] = QtCore.QPointF(
                R.left() + R.width() / 2, background[self.IndexB].y())

            polygon[self.IndexL] = QtCore.QPointF(
                R.left() + 4,
                self.mp_Bound.top() + self.mp_Bound.height() / 2)
            polygon[self.IndexE] = QtCore.QPointF(
                R.left() + 4,
                self.mp_Bound.top() + self.mp_Bound.height() / 2)
            polygon[self.IndexT] = QtCore.QPointF(R.left() + R.width() / 2,
                                                  polygon[self.IndexT].y())
            polygon[self.IndexB] = QtCore.QPointF(R.left() + R.width() / 2,
                                                  polygon[self.IndexB].y())

        elif self.mp_Handle == self.HandleMR:

            fromX = self.mp_Bound.right()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toX = snapF(toX, size, +4, snap)
            D.setX(toX - fromX)
            R.setRight(toX)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() + mbrw - R.width())
                R.setRight(R.right() + mbrw - R.width())

            selection[self.IndexR] = QtCore.QPointF(
                R.right(),
                self.mp_Bound.top() + self.mp_Bound.height() / 2)
            selection[self.IndexT] = QtCore.QPointF(R.right() - R.width() / 2,
                                                    selection[self.IndexT].y())
            selection[self.IndexB] = QtCore.QPointF(R.right() - R.width() / 2,
                                                    selection[self.IndexB].y())

            background[self.IndexR] = QtCore.QPointF(
                R.right(),
                self.mp_Bound.top() + self.mp_Bound.height() / 2)
            background[self.IndexT] = QtCore.QPointF(
                R.right() - R.width() / 2, background[self.IndexT].y())
            background[self.IndexB] = QtCore.QPointF(
                R.right() - R.width() / 2, background[self.IndexB].y())

            polygon[self.IndexR] = QtCore.QPointF(
                R.right() - 4,
                self.mp_Bound.top() + self.mp_Bound.height() / 2)
            polygon[self.IndexT] = QtCore.QPointF(R.right() - R.width() / 2,
                                                  polygon[self.IndexT].y())
            polygon[self.IndexB] = QtCore.QPointF(R.right() - R.width() / 2,
                                                  polygon[self.IndexB].y())

        elif self.mp_Handle == self.HandleBL:

            fromX = self.mp_Bound.left()
            fromY = self.mp_Bound.bottom()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, -4, snap)
            toY = snapF(toY, size, +4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setLeft(toX)
            R.setBottom(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() - mbrw + R.width())
                R.setLeft(R.left() - mbrw + R.width())
            if R.height() < mbrh:
                D.setY(D.y() + mbrh - R.height())
                R.setBottom(R.bottom() + mbrh - R.height())

            selection[self.IndexT] = QtCore.QPointF(R.left() + R.width() / 2,
                                                    selection[self.IndexT].y())
            selection[self.IndexB] = QtCore.QPointF(R.left() + R.width() / 2,
                                                    R.bottom())
            selection[self.IndexL] = QtCore.QPointF(
                R.left(),
                R.bottom() - R.height() / 2)
            selection[self.IndexE] = QtCore.QPointF(
                R.left(),
                R.bottom() - R.height() / 2)
            selection[self.IndexR] = QtCore.QPointF(
                selection[self.IndexR].x(),
                R.bottom() - R.height() / 2)

            background[self.IndexT] = QtCore.QPointF(
                R.left() + R.width() / 2, background[self.IndexT].y())
            background[self.IndexB] = QtCore.QPointF(R.left() + R.width() / 2,
                                                     R.bottom())
            background[self.IndexL] = QtCore.QPointF(
                R.left(),
                R.bottom() - R.height() / 2)
            background[self.IndexE] = QtCore.QPointF(
                R.left(),
                R.bottom() - R.height() / 2)
            background[self.IndexR] = QtCore.QPointF(
                background[self.IndexR].x(),
                R.bottom() - R.height() / 2)

            polygon[self.IndexT] = QtCore.QPointF(R.left() + R.width() / 2,
                                                  polygon[self.IndexT].y())
            polygon[self.IndexB] = QtCore.QPointF(R.left() + R.width() / 2,
                                                  R.bottom() - 4)
            polygon[self.IndexL] = QtCore.QPointF(R.left() + 4,
                                                  R.bottom() - R.height() / 2)
            polygon[self.IndexE] = QtCore.QPointF(R.left() + 4,
                                                  R.bottom() - R.height() / 2)
            polygon[self.IndexR] = QtCore.QPointF(polygon[self.IndexR].x(),
                                                  R.bottom() - R.height() / 2)

        elif self.mp_Handle == self.HandleBM:

            fromY = self.mp_Bound.bottom()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toY = snapF(toY, size, +4, snap)
            D.setY(toY - fromY)
            R.setBottom(toY)

            ## CLAMP SIZE
            if R.height() < mbrh:
                D.setY(D.y() + mbrh - R.height())
                R.setBottom(R.bottom() + mbrh - R.height())

            selection[self.IndexB] = QtCore.QPointF(selection[self.IndexB].x(),
                                                    R.bottom())
            selection[self.IndexL] = QtCore.QPointF(selection[self.IndexL].x(),
                                                    R.top() + R.height() / 2)
            selection[self.IndexE] = QtCore.QPointF(selection[self.IndexE].x(),
                                                    R.top() + R.height() / 2)
            selection[self.IndexR] = QtCore.QPointF(selection[self.IndexR].x(),
                                                    R.top() + R.height() / 2)

            background[self.IndexB] = QtCore.QPointF(
                background[self.IndexB].x(), R.bottom())
            background[self.IndexL] = QtCore.QPointF(
                background[self.IndexL].x(),
                R.top() + R.height() / 2)
            background[self.IndexE] = QtCore.QPointF(
                background[self.IndexE].x(),
                R.top() + R.height() / 2)
            background[self.IndexR] = QtCore.QPointF(
                background[self.IndexR].x(),
                R.top() + R.height() / 2)

            polygon[self.IndexB] = QtCore.QPointF(polygon[self.IndexB].x(),
                                                  R.bottom() - 4)
            polygon[self.IndexL] = QtCore.QPointF(polygon[self.IndexL].x(),
                                                  R.top() + R.height() / 2)
            polygon[self.IndexE] = QtCore.QPointF(polygon[self.IndexE].x(),
                                                  R.top() + R.height() / 2)
            polygon[self.IndexR] = QtCore.QPointF(polygon[self.IndexR].x(),
                                                  R.top() + R.height() / 2)

        elif self.mp_Handle == self.HandleBR:

            fromX = self.mp_Bound.right()
            fromY = self.mp_Bound.bottom()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, +4, snap)
            toY = snapF(toY, size, +4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setRight(toX)
            R.setBottom(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() + mbrw - R.width())
                R.setRight(R.right() + mbrw - R.width())
            if R.height() < mbrh:
                D.setY(D.y() + mbrh - R.height())
                R.setBottom(R.bottom() + mbrh - R.height())

            selection[self.IndexT] = QtCore.QPointF(R.right() - R.width() / 2,
                                                    selection[self.IndexT].y())
            selection[self.IndexB] = QtCore.QPointF(R.right() - R.width() / 2,
                                                    R.bottom())
            selection[self.IndexL] = QtCore.QPointF(
                selection[self.IndexL].x(),
                R.bottom() - R.height() / 2)
            selection[self.IndexE] = QtCore.QPointF(
                selection[self.IndexE].x(),
                R.bottom() - R.height() / 2)
            selection[self.IndexR] = QtCore.QPointF(
                R.right(),
                R.bottom() - R.height() / 2)

            background[self.IndexT] = QtCore.QPointF(
                R.right() - R.width() / 2, background[self.IndexT].y())
            background[self.IndexB] = QtCore.QPointF(R.right() - R.width() / 2,
                                                     R.bottom())
            background[self.IndexL] = QtCore.QPointF(
                background[self.IndexL].x(),
                R.bottom() - R.height() / 2)
            background[self.IndexE] = QtCore.QPointF(
                background[self.IndexE].x(),
                R.bottom() - R.height() / 2)
            background[self.IndexR] = QtCore.QPointF(
                R.right(),
                R.bottom() - R.height() / 2)

            polygon[self.IndexT] = QtCore.QPointF(R.right() - R.width() / 2,
                                                  polygon[self.IndexT].y())
            polygon[self.IndexB] = QtCore.QPointF(R.right() - R.width() / 2,
                                                  R.bottom() - 4)
            polygon[self.IndexL] = QtCore.QPointF(polygon[self.IndexL].x(),
                                                  R.bottom() - R.height() / 2)
            polygon[self.IndexE] = QtCore.QPointF(polygon[self.IndexE].x(),
                                                  R.bottom() - R.height() / 2)
            polygon[self.IndexR] = QtCore.QPointF(R.right() - 4,
                                                  R.bottom() - R.height() / 2)

        self.background.setGeometry(background)
        self.selection.setGeometry(selection)
        self.polygon.setGeometry(polygon)

        self.updateNode(selected=True,
                        handle=self.mp_Handle,
                        anchors=(self.mp_Data, D))
        self.updateTextPos(moved=moved)

    def setAsymmetric(self, asymmetric):
        """
        Set the asymmetric property for the predicate represented by this node.
        :type asymmetric: bool
        """
        meta = self.project.meta(self.type(), self.text())
        meta[K_ASYMMETRIC] = bool(asymmetric)
        self.project.setMeta(self.type(), self.text(), meta)

    def setFunctional(self, functional):
        """
        Set the functional property of the predicate represented by this node.
        :type functional: bool
        """
        meta = self.project.meta(self.type(), self.text())
        meta[K_FUNCTIONAL] = bool(functional)
        self.project.setMeta(self.type(), self.text(), meta)
        for node in self.project.predicates(self.type(), self.text()):
            node.updateNode(functional=functional, selected=node.isSelected())

    def setIdentity(self, identity):
        """
        Set the identity of the current node.
        :type identity: Identity
        """
        pass

    def setInverseFunctional(self, inverseFunctional):
        """
        Set the inverse functional property of the predicate represented by this node.
        :type inverseFunctional: bool
        """
        meta = self.project.meta(self.type(), self.text())
        meta[K_INVERSE_FUNCTIONAL] = bool(inverseFunctional)
        self.project.setMeta(self.type(), self.text(), meta)
        for node in self.project.predicates(self.type(), self.text()):
            node.updateNode(inverseFunctional=inverseFunctional,
                            selected=node.isSelected())

    def setIrreflexive(self, irreflexive):
        """
        Set the irreflexive property for the predicate represented by this node.
        :type irreflexive: bool
        """
        meta = self.project.meta(self.type(), self.text())
        meta[K_IRREFLEXIVE] = bool(irreflexive)
        self.project.setMeta(self.type(), self.text(), meta)

    def setReflexive(self, reflexive):
        """
        Set the reflexive property for the predicate represented by this node.
        :type reflexive: bool
        """
        meta = self.project.meta(self.type(), self.text())
        meta[K_REFLEXIVE] = bool(reflexive)
        self.project.setMeta(self.type(), self.text(), meta)

    def setSymmetric(self, symmetric):
        """
        Set the symmetric property for the predicate represented by this node.
        :type symmetric: bool
        """
        meta = self.project.meta(self.type(), self.text())
        meta[K_SYMMETRIC] = bool(symmetric)
        self.project.setMeta(self.type(), self.text(), meta)

    def setTransitive(self, transitive):
        """
        Set the transitive property for the predicate represented by this node.
        :type transitive: bool
        """
        meta = self.project.meta(self.type(), self.text())
        meta[K_TRANSITIVE] = bool(transitive)
        self.project.setMeta(self.type(), self.text(), meta)

    def setText(self, text):
        """
        Set the label text.
        :type text: str
        """
        self.label.setText(text)

    def setTextPos(self, pos):
        """
        Set the label position.
        :type pos: QPointF
        """
        self.label.setPos(pos)
        self.label.setAlignment(QtCore.Qt.AlignCenter)

    def shape(self):
        """
        Returns the shape of this item as a QPainterPath in local coordinates.
        :rtype: QPainterPath
        """
        path = QtGui.QPainterPath()
        path.addPolygon(self.polygon.geometry())
        for polygon in self.handles:
            path.addEllipse(polygon.geometry())
        return path

    def special(self):
        """
        Returns the special type of this node.
        :rtype: Special
        """
        return Special.valueOf(self.text())

    def text(self):
        """
        Returns the label text.
        :rtype: str
        """
        return self.label.text()

    def textPos(self):
        """
        Returns the current label position in item coordinates.
        :rtype: QPointF
        """
        return self.label.pos()

    def updateNode(self, functional=None, inverseFunctional=None, **kwargs):
        """
        Update the current node.
        :type functional: bool
        :type inverseFunctional: bool
        """
        if functional is None:
            functional = self.isFunctional()
        if inverseFunctional is None:
            inverseFunctional = self.isInverseFunctional()

        polygon = self.polygon.geometry()

        # FUNCTIONAL POLYGON (SHAPE)
        fpolygon = QtGui.QPainterPath()
        if functional and not inverseFunctional:
            path = QtGui.QPainterPath()
            path.addPolygon(
                QtGui.QPolygonF([
                    polygon[self.IndexL] + QtCore.QPointF(+5, 0),
                    polygon[self.IndexB] + QtCore.QPointF(0, -4),
                    polygon[self.IndexR] + QtCore.QPointF(-5, 0),
                    polygon[self.IndexT] + QtCore.QPointF(0, +4),
                    polygon[self.IndexL] + QtCore.QPointF(+5, 0),
                ]))
            fpolygon.addPolygon(polygon)
            fpolygon = fpolygon.subtracted(path)

        # INVERSE FUNCTIONAL POLYGON (SHAPE)
        ipolygon = QtGui.QPainterPath()
        if not functional and inverseFunctional:
            path = QtGui.QPainterPath()
            path.addPolygon(
                QtGui.QPolygonF([
                    polygon[self.IndexL] + QtCore.QPointF(+5, 0),
                    polygon[self.IndexB] + QtCore.QPointF(0, -4),
                    polygon[self.IndexR] + QtCore.QPointF(-5, 0),
                    polygon[self.IndexT] + QtCore.QPointF(0, +4),
                    polygon[self.IndexL] + QtCore.QPointF(+5, 0),
                ]))
            ipolygon.addPolygon(polygon)
            ipolygon = ipolygon.subtracted(path)

        # FUNCTIONAL + INVERSE FUNCTIONAL POLYGONS (SHAPE)
        if functional and inverseFunctional:
            path = QtGui.QPainterPath()
            path.addPolygon(
                QtGui.QPolygonF([
                    polygon[self.IndexL] + QtCore.QPointF(+5, 0),
                    polygon[self.IndexB] + QtCore.QPointF(0, -4),
                    polygon[self.IndexB],
                    polygon[self.IndexR],
                    polygon[self.IndexT],
                    polygon[self.IndexT] + QtCore.QPointF(0, +4),
                    polygon[self.IndexL] + QtCore.QPointF(+5, 0),
                ]))
            fpolygon.addPolygon(polygon)
            fpolygon = fpolygon.subtracted(path)
            path = QtGui.QPainterPath()
            path.addPolygon(
                QtGui.QPolygonF([
                    polygon[self.IndexL],
                    polygon[self.IndexB],
                    polygon[self.IndexB] + QtCore.QPointF(0, -4),
                    polygon[self.IndexR] + QtCore.QPointF(-5, 0),
                    polygon[self.IndexT] + QtCore.QPointF(0, +4),
                    polygon[self.IndexT],
                    polygon[self.IndexL],
                ]))
            ipolygon.addPolygon(polygon)
            ipolygon = ipolygon.subtracted(path)

        # FUNCTIONAL POLYGON (PEN + BRUSH)
        fpen = QtGui.QPen(QtCore.Qt.NoPen)
        fbrush = QtGui.QBrush(QtCore.Qt.NoBrush)
        if functional:
            fpen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.1,
                              QtCore.Qt.SolidLine, QtCore.Qt.RoundCap,
                              QtCore.Qt.RoundJoin)
            fbrush = QtGui.QBrush(QtGui.QColor(252, 252, 252, 255))

        # INVERSE FUNCTIONAL POLYGON (PEN + BRUSH)
        ipen = QtGui.QPen(QtCore.Qt.NoPen)
        ibrush = QtGui.QBrush(QtCore.Qt.NoBrush)
        if inverseFunctional:
            ipen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.1,
                              QtCore.Qt.SolidLine, QtCore.Qt.RoundCap,
                              QtCore.Qt.RoundJoin)
            ibrush = QtGui.QBrush(QtGui.QColor(0, 0, 0, 255))

        self.fpolygon.setPen(fpen)
        self.fpolygon.setBrush(fbrush)
        self.fpolygon.setGeometry(fpolygon)
        self.ipolygon.setPen(ipen)
        self.ipolygon.setBrush(ibrush)
        self.ipolygon.setGeometry(ipolygon)

        # SELECTION + BACKGROUND + HANDLES + ANCHORS + CACHE REFRESH
        super().updateNode(**kwargs)

    def updateTextPos(self, *args, **kwargs):
        """
        Update the label position.
        """
        self.label.updatePos(*args, **kwargs)

    def width(self):
        """
        Returns the width of the shape.
        :rtype: int
        """
        polygon = self.polygon.geometry()
        return polygon[self.IndexR].x() - polygon[self.IndexL].x()

    def __repr__(self):
        """
        Returns repr(self).
        """
        return '{0}:{1}:{2}'.format(self.__class__.__name__, self.text(),
                                    self.id)
Exemplo n.º 5
0
class AttributeNode(AbstractNode):
    """
    This class implements the 'Attribute' node.
    """
    DefaultBrush = QtGui.QBrush(QtGui.QColor(252, 252, 252, 255))
    DefaultPen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.1, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
    Identities = {Identity.Attribute}
    Type = Item.AttributeNode

    def __init__(self, width=20, height=20, brush=None, **kwargs):
        """
        Initialize the node.
        :type width: int
        :type height: int
        :type brush: QBrush
        """
        super().__init__(**kwargs)
        brush = brush or AttributeNode.DefaultBrush
        pen = AttributeNode.DefaultPen
        self.fpolygon = Polygon(QtGui.QPainterPath())
        self.background = Polygon(QtCore.QRectF(-14, -14, 28, 28))
        self.selection = Polygon(QtCore.QRectF(-14, -14, 28, 28))
        self.polygon = Polygon(QtCore.QRectF(-10, -10, 20, 20), brush, pen)
        self.label = NodeLabel(template='attribute', pos=lambda: self.center() - QtCore.QPointF(0, 22), parent=self)
        self.label.setAlignment(QtCore.Qt.AlignCenter)

    #############################################
    #   INTERFACE
    #################################

    def boundingRect(self):
        """
        Returns the shape bounding rectangle.
        :rtype: QRectF
        """
        return self.selection.geometry()

    def copy(self, diagram):
        """
        Create a copy of the current item.
        :type diagram: Diagram
        """
        node = diagram.factory.create(self.type(), **{
            'id': self.id,
            'brush': self.brush(),
            'height': self.height(),
            'width': self.width()
        })
        node.setPos(self.pos())
        node.setText(self.text())
        node.setTextPos(node.mapFromScene(self.mapToScene(self.textPos())))
        return node

    def definition(self):
        """
        Returns the list of nodes which contribute to the definition of this very node.
        :rtype: set
        """
        f1 = lambda x: x.type() is Item.InputEdge
        f2 = lambda x: x.type() in {Item.DomainRestrictionNode, Item.RangeRestrictionNode}
        return set(self.outgoingNodes(filter_on_edges=f1, filter_on_nodes=f2))

    def height(self):
        """
        Returns the height of the shape.
        :rtype: int
        """
        return self.polygon.geometry().height()

    def identity(self):
        """
        Returns the identity of the current node.
        :rtype: Identity
        """
        return Identity.Attribute

    def isFunctional(self):
        """
        Returns True if the predicate represented by this node is functional, else False.
        :rtype: bool
        """
        try:
            return self.project.meta(self.type(), self.text())['functional'] and \
                   self.project.profile.type() is not OWLProfile.OWL2QL
        except (AttributeError, KeyError):
            return False

    def paint(self, painter, option, widget=None):
        """
        Paint the node in the diagram.
        :type painter: QPainter
        :type option: QStyleOptionGraphicsItem
        :type widget: QWidget
        """
        # SET THE RECT THAT NEEDS TO BE REPAINTED
        painter.setClipRect(option.exposedRect)
        # SELECTION AREA
        painter.setPen(self.selection.pen())
        painter.setBrush(self.selection.brush())
        painter.drawEllipse(self.selection.geometry())
        # SYNTAX VALIDATION
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        painter.setPen(self.background.pen())
        painter.setBrush(self.background.brush())
        painter.drawEllipse(self.background.geometry())
        # ITEM SHAPE
        painter.setPen(self.polygon.pen())
        painter.setBrush(self.polygon.brush())
        painter.drawEllipse(self.polygon.geometry())
        # FUNCTIONALITY
        painter.setPen(self.fpolygon.pen())
        painter.setBrush(self.fpolygon.brush())
        painter.drawPath(self.fpolygon.geometry())

    def painterPath(self):
        """
        Returns the current shape as QPainterPath (used for collision detection).
        :rtype: QPainterPath
        """
        path = QtGui.QPainterPath()
        path.addEllipse(self.polygon.geometry())
        return path

    def setFunctional(self, functional):
        """
        Set the functional property of the predicate represented by this node.
        :type functional: bool
        """
        meta = self.project.meta(self.type(), self.text())
        meta['functional'] = bool(functional)
        self.project.setMeta(self.type(), self.text(), meta)
        for node in self.project.predicates(self.type(), self.text()):
            node.updateNode(functional=functional, selected=node.isSelected())

    def setIdentity(self, identity):
        """
        Set the identity of the current node.
        :type identity: Identity
        """
        pass

    def setText(self, text):
        """
        Set the label text.
        :type text: str
        """
        self.label.setText(text)
        self.label.setAlignment(QtCore.Qt.AlignCenter)

    def setTextPos(self, pos):
        """
        Set the label position.
        :type pos: QPointF
        """
        self.label.setPos(pos)

    def shape(self):
        """
        Returns the shape of this item as a QPainterPath in local coordinates.
        :rtype: QPainterPath
        """
        path = QtGui.QPainterPath()
        path.addEllipse(self.polygon.geometry())
        return path

    def special(self):
        """
        Returns the special type of this node.
        :rtype: Special
        """
        return Special.forValue(self.text())

    def text(self):
        """
        Returns the label text.
        :rtype: str
        """
        return self.label.text()

    def textPos(self):
        """
        Returns the current label position in item coordinates.
        :rtype: QPointF
        """
        return self.label.pos()

    def updateNode(self, functional=None, **kwargs):
        """
        Update the current node.
        :type functional: bool
        """
        if functional is None:
            functional = self.isFunctional()

        # FUNCTIONAL POLYGON (SHAPE)
        path1 = QtGui.QPainterPath()
        path1.addEllipse(self.polygon.geometry())
        path2 = QtGui.QPainterPath()
        path2.addEllipse(QtCore.QRectF(-7, -7, 14, 14))
        self.fpolygon.setGeometry(path1.subtracted(path2))

        # FUNCTIONAL POLYGON (PEN & BRUSH)
        pen = QtGui.QPen(QtCore.Qt.NoPen)
        brush = QtGui.QBrush(QtCore.Qt.NoBrush)
        if functional:
            pen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.1, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
            brush = QtGui.QBrush(QtGui.QColor(252, 252, 252, 255))
        self.fpolygon.setPen(pen)
        self.fpolygon.setBrush(brush)

        # SELECTION + BACKGROUND + CACHE REFRESH
        super().updateNode(**kwargs)

    def updateTextPos(self, *args, **kwargs):
        """
        Update the label position.
        """
        self.label.updatePos(*args, **kwargs)

    def width(self):
        """
        Returns the width of the shape.
        :rtype: int
        """
        return self.polygon.geometry().width()

    def __repr__(self):
        """
        Returns repr(self).
        """
        return '{0}:{1}:{2}'.format(self.__class__.__name__, self.text(), self.id)
Exemplo n.º 6
0
class RoleNode(AbstractResizableNode):
    """
    This class implements the 'Role' node.
    """
    IndexL = 0
    IndexB = 1
    IndexR = 2
    IndexT = 3
    IndexE = 4

    DefaultBrush = QtGui.QBrush(QtGui.QColor(252, 252, 252, 255))
    DefaultPen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.1, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
    Identities = {Identity.Role}
    Type = Item.RoleNode

    def __init__(self, width=70, height=50, brush=None, **kwargs):
        """
        Initialize the node.
        :type width: int
        :type height: int
        :type brush: QBrush
        """
        super().__init__(**kwargs)
        
        w = max(width, 70)
        h = max(height, 50)
        brush = brush or RoleNode.DefaultBrush
        pen = RoleNode.DefaultPen

        createPolygon = lambda x, y: QtGui.QPolygonF([
            QtCore.QPointF(-x / 2, 0),
            QtCore.QPointF(0, +y / 2),
            QtCore.QPointF(+x / 2, 0),
            QtCore.QPointF(0, -y / 2),
            QtCore.QPointF(-x / 2, 0)
        ])

        self.fpolygon = Polygon(QtGui.QPainterPath())
        self.ipolygon = Polygon(QtGui.QPainterPath())
        self.background = Polygon(createPolygon(w + 8, h + 8))
        self.selection = Polygon(createPolygon(w + 8, h + 8))
        self.polygon = Polygon(createPolygon(w, h), brush, pen)
        self.label = NodeLabel(template='role', pos=self.center, parent=self)
        self.label.setAlignment(QtCore.Qt.AlignCenter)
        self.updateNode()
        self.updateTextPos()

    #############################################
    #   INTERFACE
    #################################

    def boundingRect(self):
        """
        Returns the shape bounding rectangle.
        :rtype: QtCore.QRectF
        """
        path = QtGui.QPainterPath()
        path.addPolygon(self.selection.geometry())
        return path.boundingRect()

    def copy(self, diagram):
        """
        Create a copy of the current item.
        :type diagram: Diagram
        """
        node = diagram.factory.create(self.type(), **{
            'id': self.id,
            'brush': self.brush(),
            'height': self.height(),
            'width': self.width()
        })
        node.setPos(self.pos())
        node.setText(self.text())
        node.setTextPos(node.mapFromScene(self.mapToScene(self.textPos())))
        return node

    def definition(self):
        """
        Returns the list of nodes which contribute to the definition of this very node.
        :rtype: set
        """
        f1 = lambda x: x.type() is Item.InputEdge
        f2 = lambda x: x.type() in {Item.DomainRestrictionNode, Item.RangeRestrictionNode}
        return self.outgoingNodes(filter_on_edges=f1, filter_on_nodes=f2)

    def height(self):
        """
        Returns the height of the shape.
        :rtype: int
        """
        polygon = self.polygon.geometry()
        return polygon[self.IndexB].y() - polygon[self.IndexT].y()

    def identity(self):
        """
        Returns the identity of the current node.
        :rtype: Identity
        """
        return Identity.Role

    def isAsymmetric(self):
        """
        Returns True if the predicate represented by this node is asymmetric, False otherwise.
        :rtype: bool
        """
        try:
            return self.project.meta(self.type(), self.text())['asymmetric']
        except (AttributeError, KeyError):
            return False

    def isFunctional(self):
        """
        Returns True if the predicate represented by this node is functional, else False.
        :rtype: bool
        """
        try:
            return self.project.meta(self.type(), self.text())['functional'] and \
                   self.project.profile.type() is not OWLProfile.OWL2QL
        except (AttributeError, KeyError):
            return False

    def isInverseFunctional(self):
        """
        Returns True if the predicate represented by this node is inverse functional, else False.
        :rtype: bool
        """
        try:
            return self.project.meta(self.type(), self.text())['inverseFunctional'] and \
                   self.project.profile.type() is not OWLProfile.OWL2QL
        except (AttributeError, KeyError):
            return False

    def isIrreflexive(self):
        """
        Returns True if the predicate represented by this node is irreflexive, False otherwise.
        :rtype: bool
        """
        try:
            return self.project.meta(self.type(), self.text())['irreflexive']
        except (AttributeError, KeyError):
            return False

    def isReflexive(self):
        """
        Returns True if the predicate represented by this node is reflexive, False otherwise.
        :rtype: bool
        """
        try:
            return self.project.meta(self.type(), self.text())['reflexive'] and \
                   self.project.profile.type() is not OWLProfile.OWL2RL
        except (AttributeError, KeyError):
            return False

    def isSymmetric(self):
        """
        Returns True if the predicate represented by this node is symmetric, False otherwise.
        :rtype: bool
        """
        try:
            return self.project.meta(self.type(), self.text())['symmetric']
        except (AttributeError, KeyError):
            return False

    def isTransitive(self):
        """
        Returns True if the transitive represented by this node is symmetric, False otherwise.
        :rtype: bool
        """
        try:
            return self.project.meta(self.type(), self.text())['transitive'] and \
                   self.project.profile.type() is not OWLProfile.OWL2QL
        except (AttributeError, KeyError):
            return False

    def paint(self, painter, option, widget=None):
        """
        Paint the node in the diagram.
        :type painter: QPainter
        :type option: QStyleOptionGraphicsItem
        :type widget: QWidget
        """
        # SET THE RECT THAT NEEDS TO BE REPAINTED
        painter.setClipRect(option.exposedRect)
        # SELECTION AREA
        painter.setPen(self.selection.pen())
        painter.setBrush(self.selection.brush())
        painter.drawPolygon(self.selection.geometry())
        # SYNTAX VALIDATION
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        painter.setPen(self.background.pen())
        painter.setBrush(self.background.brush())
        painter.drawPolygon(self.background.geometry())
        # ITEM SHAPE
        painter.setPen(self.polygon.pen())
        painter.setBrush(self.polygon.brush())
        painter.drawPolygon(self.polygon.geometry())
        # FUNCTIONALITY
        painter.setPen(self.fpolygon.pen())
        painter.setBrush(self.fpolygon.brush())
        painter.drawPath(self.fpolygon.geometry())
        # INVERSE FUNCTIONALITY
        painter.setPen(self.ipolygon.pen())
        painter.setBrush(self.ipolygon.brush())
        painter.drawPath(self.ipolygon.geometry())
        # RESIZE HANDLES
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        for polygon in self.handles:
            painter.setPen(polygon.pen())
            painter.setBrush(polygon.brush())
            painter.drawEllipse(polygon.geometry())

    def painterPath(self):
        """
        Returns the current shape as QtGui.QPainterPath (used for collision detection).
        :rtype: QPainterPath
        """
        path = QtGui.QPainterPath()
        path.addPolygon(self.polygon.geometry())
        return path

    def resize(self, mousePos):
        """
        Handle the interactive resize of the shape.
        :type mousePos: QtCore.QPointF
        """
        snap = self.session.action('toggle_grid').isChecked()
        size = self.diagram.GridSize
        moved = self.label.isMoved()

        background = self.background.geometry()
        selection = self.selection.geometry()
        polygon = self.polygon.geometry()
        
        R = QtCore.QRectF(self.boundingRect())
        D = QtCore.QPointF(0, 0)

        mbrh = 58
        mbrw = 78

        self.prepareGeometryChange()

        if self.mp_Handle == self.HandleTL:

            fromX = self.mp_Bound.left()
            fromY = self.mp_Bound.top()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, -4, snap)
            toY = snapF(toY, size, -4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setLeft(toX)
            R.setTop(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() - mbrw + R.width())
                R.setLeft(R.left() - mbrw + R.width())
            if R.height() < mbrh:
                D.setY(D.y() - mbrh + R.height())
                R.setTop(R.top() - mbrh + R.height())

            selection[self.IndexT] = QtCore.QPointF(R.left() + R.width() / 2, R.top())
            selection[self.IndexB] = QtCore.QPointF(R.left() + R.width() / 2, selection[self.IndexB].y())
            selection[self.IndexL] = QtCore.QPointF(R.left(), R.top() + R.height() / 2)
            selection[self.IndexE] = QtCore.QPointF(R.left(), R.top() + R.height() / 2)
            selection[self.IndexR] = QtCore.QPointF(selection[self.IndexR].x(), R.top() + R.height() / 2)

            background[self.IndexT] = QtCore.QPointF(R.left() + R.width() / 2, R.top())
            background[self.IndexB] = QtCore.QPointF(R.left() + R.width() / 2, background[self.IndexB].y())
            background[self.IndexL] = QtCore.QPointF(R.left(), R.top() + R.height() / 2)
            background[self.IndexE] = QtCore.QPointF(R.left(), R.top() + R.height() / 2)
            background[self.IndexR] = QtCore.QPointF(background[self.IndexR].x(), R.top() + R.height() / 2)
            
            polygon[self.IndexT] = QtCore.QPointF(R.left() + R.width() / 2, R.top() + 4)
            polygon[self.IndexB] = QtCore.QPointF(R.left() + R.width() / 2, polygon[self.IndexB].y())
            polygon[self.IndexL] = QtCore.QPointF(R.left() + 4, R.top() + R.height() / 2)
            polygon[self.IndexE] = QtCore.QPointF(R.left() + 4, R.top() + R.height() / 2)
            polygon[self.IndexR] = QtCore.QPointF(polygon[self.IndexR].x(), R.top() + R.height() / 2)

        elif self.mp_Handle == self.HandleTM:

            fromY = self.mp_Bound.top()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toY = snapF(toY, size, -4, snap)
            D.setY(toY - fromY)
            R.setTop(toY)

            ## CLAMP SIZE
            if R.height() < mbrh:
                D.setY(D.y() - mbrh + R.height())
                R.setTop(R.top() - mbrh + R.height())

            selection[self.IndexT] = QtCore.QPointF(selection[self.IndexT].x(), R.top())
            selection[self.IndexL] = QtCore.QPointF(selection[self.IndexL].x(), R.top() + R.height() / 2)
            selection[self.IndexE] = QtCore.QPointF(selection[self.IndexE].x(), R.top() + R.height() / 2)
            selection[self.IndexR] = QtCore.QPointF(selection[self.IndexR].x(), R.top() + R.height() / 2)

            background[self.IndexT] = QtCore.QPointF(background[self.IndexT].x(), R.top())
            background[self.IndexL] = QtCore.QPointF(background[self.IndexL].x(), R.top() + R.height() / 2)
            background[self.IndexE] = QtCore.QPointF(background[self.IndexE].x(), R.top() + R.height() / 2)
            background[self.IndexR] = QtCore.QPointF(background[self.IndexR].x(), R.top() + R.height() / 2)
            
            polygon[self.IndexT] = QtCore.QPointF(polygon[self.IndexT].x(), R.top() + 4)
            polygon[self.IndexL] = QtCore.QPointF(polygon[self.IndexL].x(), R.top() + R.height() / 2)
            polygon[self.IndexE] = QtCore.QPointF(polygon[self.IndexE].x(), R.top() + R.height() / 2)
            polygon[self.IndexR] = QtCore.QPointF(polygon[self.IndexR].x(), R.top() + R.height() / 2)

        elif self.mp_Handle == self.HandleTR:

            fromX = self.mp_Bound.right()
            fromY = self.mp_Bound.top()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, +4, snap)
            toY = snapF(toY, size, -4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setRight(toX)
            R.setTop(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() + mbrw - R.width())
                R.setRight(R.right() + mbrw - R.width())
            if R.height() < mbrh:
                D.setY(D.y() - mbrh + R.height())
                R.setTop(R.top() - mbrh + R.height())

            selection[self.IndexT] = QtCore.QPointF(R.right() - R.width() / 2, R.top())
            selection[self.IndexB] = QtCore.QPointF(R.right() - R.width() / 2, selection[self.IndexB].y())
            selection[self.IndexL] = QtCore.QPointF(selection[self.IndexL].x(), R.top() + R.height() / 2)
            selection[self.IndexE] = QtCore.QPointF(selection[self.IndexE].x(), R.top() + R.height() / 2)
            selection[self.IndexR] = QtCore.QPointF(R.right(), R.top() + R.height() / 2)

            background[self.IndexT] = QtCore.QPointF(R.right() - R.width() / 2, R.top())
            background[self.IndexB] = QtCore.QPointF(R.right() - R.width() / 2, background[self.IndexB].y())
            background[self.IndexL] = QtCore.QPointF(background[self.IndexL].x(), R.top() + R.height() / 2)
            background[self.IndexE] = QtCore.QPointF(background[self.IndexE].x(), R.top() + R.height() / 2)
            background[self.IndexR] = QtCore.QPointF(R.right(), R.top() + R.height() / 2)
            
            polygon[self.IndexT] = QtCore.QPointF(R.right() - R.width() / 2, R.top() + 4)
            polygon[self.IndexB] = QtCore.QPointF(R.right() - R.width() / 2, polygon[self.IndexB].y())
            polygon[self.IndexL] = QtCore.QPointF(polygon[self.IndexL].x(), R.top() + R.height() / 2)
            polygon[self.IndexE] = QtCore.QPointF(polygon[self.IndexE].x(), R.top() + R.height() / 2)
            polygon[self.IndexR] = QtCore.QPointF(R.right() - 4, R.top() + R.height() / 2)

        elif self.mp_Handle == self.HandleML:

            fromX = self.mp_Bound.left()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toX = snapF(toX, size, -4, snap)
            D.setX(toX - fromX)
            R.setLeft(toX)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() - mbrw + R.width())
                R.setLeft(R.left() - mbrw + R.width())

            selection[self.IndexL] = QtCore.QPointF(R.left(), self.mp_Bound.top() + self.mp_Bound.height() / 2)
            selection[self.IndexE] = QtCore.QPointF(R.left(), self.mp_Bound.top() + self.mp_Bound.height() / 2)
            selection[self.IndexT] = QtCore.QPointF(R.left() + R.width() / 2, selection[self.IndexT].y())
            selection[self.IndexB] = QtCore.QPointF(R.left() + R.width() / 2, selection[self.IndexB].y())
            
            background[self.IndexL] = QtCore.QPointF(R.left(), self.mp_Bound.top() + self.mp_Bound.height() / 2)
            background[self.IndexE] = QtCore.QPointF(R.left(), self.mp_Bound.top() + self.mp_Bound.height() / 2)
            background[self.IndexT] = QtCore.QPointF(R.left() + R.width() / 2, background[self.IndexT].y())
            background[self.IndexB] = QtCore.QPointF(R.left() + R.width() / 2, background[self.IndexB].y())
            
            polygon[self.IndexL] = QtCore.QPointF(R.left() + 4, self.mp_Bound.top() + self.mp_Bound.height() / 2)
            polygon[self.IndexE] = QtCore.QPointF(R.left() + 4, self.mp_Bound.top() + self.mp_Bound.height() / 2)
            polygon[self.IndexT] = QtCore.QPointF(R.left() + R.width() / 2, polygon[self.IndexT].y())
            polygon[self.IndexB] = QtCore.QPointF(R.left() + R.width() / 2, polygon[self.IndexB].y())

        elif self.mp_Handle == self.HandleMR:

            fromX = self.mp_Bound.right()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toX = snapF(toX, size, +4, snap)
            D.setX(toX - fromX)
            R.setRight(toX)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() + mbrw - R.width())
                R.setRight(R.right() + mbrw - R.width())

            selection[self.IndexR] = QtCore.QPointF(R.right(), self.mp_Bound.top() + self.mp_Bound.height() / 2)
            selection[self.IndexT] = QtCore.QPointF(R.right() - R.width() / 2, selection[self.IndexT].y())
            selection[self.IndexB] = QtCore.QPointF(R.right() - R.width() / 2, selection[self.IndexB].y())
            
            background[self.IndexR] = QtCore.QPointF(R.right(), self.mp_Bound.top() + self.mp_Bound.height() / 2)
            background[self.IndexT] = QtCore.QPointF(R.right() - R.width() / 2, background[self.IndexT].y())
            background[self.IndexB] = QtCore.QPointF(R.right() - R.width() / 2, background[self.IndexB].y())
            
            polygon[self.IndexR] = QtCore.QPointF(R.right() - 4, self.mp_Bound.top() + self.mp_Bound.height() / 2)
            polygon[self.IndexT] = QtCore.QPointF(R.right() - R.width() / 2, polygon[self.IndexT].y())
            polygon[self.IndexB] = QtCore.QPointF(R.right() - R.width() / 2, polygon[self.IndexB].y())

        elif self.mp_Handle == self.HandleBL:

            fromX = self.mp_Bound.left()
            fromY = self.mp_Bound.bottom()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, -4, snap)
            toY = snapF(toY, size, +4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setLeft(toX)
            R.setBottom(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() - mbrw + R.width())
                R.setLeft(R.left() - mbrw + R.width())
            if R.height() < mbrh:
                D.setY(D.y() + mbrh - R.height())
                R.setBottom(R.bottom() + mbrh - R.height())

            selection[self.IndexT] = QtCore.QPointF(R.left() + R.width() / 2, selection[self.IndexT].y())
            selection[self.IndexB] = QtCore.QPointF(R.left() + R.width() / 2, R.bottom())
            selection[self.IndexL] = QtCore.QPointF(R.left(), R.bottom() - R.height() / 2)
            selection[self.IndexE] = QtCore.QPointF(R.left(), R.bottom() - R.height() / 2)
            selection[self.IndexR] = QtCore.QPointF(selection[self.IndexR].x(), R.bottom() - R.height() / 2)
            
            background[self.IndexT] = QtCore.QPointF(R.left() + R.width() / 2, background[self.IndexT].y())
            background[self.IndexB] = QtCore.QPointF(R.left() + R.width() / 2, R.bottom())
            background[self.IndexL] = QtCore.QPointF(R.left(), R.bottom() - R.height() / 2)
            background[self.IndexE] = QtCore.QPointF(R.left(), R.bottom() - R.height() / 2)
            background[self.IndexR] = QtCore.QPointF(background[self.IndexR].x(), R.bottom() - R.height() / 2)
            
            polygon[self.IndexT] = QtCore.QPointF(R.left() + R.width() / 2, polygon[self.IndexT].y())
            polygon[self.IndexB] = QtCore.QPointF(R.left() + R.width() / 2, R.bottom() - 4)
            polygon[self.IndexL] = QtCore.QPointF(R.left() + 4, R.bottom() - R.height() / 2)
            polygon[self.IndexE] = QtCore.QPointF(R.left() + 4, R.bottom() - R.height() / 2)
            polygon[self.IndexR] = QtCore.QPointF(polygon[self.IndexR].x(), R.bottom() - R.height() / 2)

        elif self.mp_Handle == self.HandleBM:

            fromY = self.mp_Bound.bottom()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toY = snapF(toY, size, +4, snap)
            D.setY(toY - fromY)
            R.setBottom(toY)

            ## CLAMP SIZE
            if R.height() < mbrh:
                D.setY(D.y() + mbrh - R.height())
                R.setBottom(R.bottom() + mbrh - R.height())

            selection[self.IndexB] = QtCore.QPointF(selection[self.IndexB].x(), R.bottom())
            selection[self.IndexL] = QtCore.QPointF(selection[self.IndexL].x(), R.top() + R.height() / 2)
            selection[self.IndexE] = QtCore.QPointF(selection[self.IndexE].x(), R.top() + R.height() / 2)
            selection[self.IndexR] = QtCore.QPointF(selection[self.IndexR].x(), R.top() + R.height() / 2)

            background[self.IndexB] = QtCore.QPointF(background[self.IndexB].x(), R.bottom())
            background[self.IndexL] = QtCore.QPointF(background[self.IndexL].x(), R.top() + R.height() / 2)
            background[self.IndexE] = QtCore.QPointF(background[self.IndexE].x(), R.top() + R.height() / 2)
            background[self.IndexR] = QtCore.QPointF(background[self.IndexR].x(), R.top() + R.height() / 2)
            
            polygon[self.IndexB] = QtCore.QPointF(polygon[self.IndexB].x(), R.bottom() - 4)
            polygon[self.IndexL] = QtCore.QPointF(polygon[self.IndexL].x(), R.top() + R.height() / 2)
            polygon[self.IndexE] = QtCore.QPointF(polygon[self.IndexE].x(), R.top() + R.height() / 2)
            polygon[self.IndexR] = QtCore.QPointF(polygon[self.IndexR].x(), R.top() + R.height() / 2)

        elif self.mp_Handle == self.HandleBR:

            fromX = self.mp_Bound.right()
            fromY = self.mp_Bound.bottom()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, +4, snap)
            toY = snapF(toY, size, +4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setRight(toX)
            R.setBottom(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() + mbrw - R.width())
                R.setRight(R.right() + mbrw - R.width())
            if R.height() < mbrh:
                D.setY(D.y() + mbrh - R.height())
                R.setBottom(R.bottom() + mbrh - R.height())

            selection[self.IndexT] = QtCore.QPointF(R.right() - R.width() / 2, selection[self.IndexT].y())
            selection[self.IndexB] = QtCore.QPointF(R.right() - R.width() / 2, R.bottom())
            selection[self.IndexL] = QtCore.QPointF(selection[self.IndexL].x(), R.bottom() - R.height() / 2)
            selection[self.IndexE] = QtCore.QPointF(selection[self.IndexE].x(), R.bottom() - R.height() / 2)
            selection[self.IndexR] = QtCore.QPointF(R.right(), R.bottom() - R.height() / 2)

            background[self.IndexT] = QtCore.QPointF(R.right() - R.width() / 2, background[self.IndexT].y())
            background[self.IndexB] = QtCore.QPointF(R.right() - R.width() / 2, R.bottom())
            background[self.IndexL] = QtCore.QPointF(background[self.IndexL].x(), R.bottom() - R.height() / 2)
            background[self.IndexE] = QtCore.QPointF(background[self.IndexE].x(), R.bottom() - R.height() / 2)
            background[self.IndexR] = QtCore.QPointF(R.right(), R.bottom() - R.height() / 2)
            
            polygon[self.IndexT] = QtCore.QPointF(R.right() - R.width() / 2, polygon[self.IndexT].y())
            polygon[self.IndexB] = QtCore.QPointF(R.right() - R.width() / 2, R.bottom() - 4)
            polygon[self.IndexL] = QtCore.QPointF(polygon[self.IndexL].x(), R.bottom() - R.height() / 2)
            polygon[self.IndexE] = QtCore.QPointF(polygon[self.IndexE].x(), R.bottom() - R.height() / 2)
            polygon[self.IndexR] = QtCore.QPointF(R.right() - 4, R.bottom() - R.height() / 2)

        self.background.setGeometry(background)
        self.selection.setGeometry(selection)
        self.polygon.setGeometry(polygon)

        self.updateNode(selected=True, handle=self.mp_Handle, anchors=(self.mp_Data, D))
        self.updateTextPos(moved=moved)

    def setAsymmetric(self, asymmetric):
        """
        Set the asymmetric property for the predicate represented by this node.
        :type asymmetric: bool
        """
        meta = self.project.meta(self.type(), self.text())
        meta['asymmetric'] = bool(asymmetric)
        self.project.setMeta(self.type(), self.text(), meta)

    def setFunctional(self, functional):
        """
        Set the functional property of the predicate represented by this node.
        :type functional: bool
        """
        meta = self.project.meta(self.type(), self.text())
        meta['functional'] = bool(functional)
        self.project.setMeta(self.type(), self.text(), meta)
        for node in self.project.predicates(self.type(), self.text()):
            node.updateNode(functional=functional, selected=node.isSelected())

    def setIdentity(self, identity):
        """
        Set the identity of the current node.
        :type identity: Identity
        """
        pass

    def setInverseFunctional(self, inverseFunctional):
        """
        Set the inverse functional property of the predicate represented by this node.
        :type inverseFunctional: bool
        """
        meta = self.project.meta(self.type(), self.text())
        meta['inverseFunctional'] = bool(inverseFunctional)
        self.project.setMeta(self.type(), self.text(), meta)
        for node in self.project.predicates(self.type(), self.text()):
            node.updateNode(inverseFunctional=inverseFunctional, selected=node.isSelected())

    def setIrreflexive(self, irreflexive):
        """
        Set the irreflexive property for the predicate represented by this node.
        :type irreflexive: bool
        """
        meta = self.project.meta(self.type(), self.text())
        meta['irreflexive'] = bool(irreflexive)
        self.project.setMeta(self.type(), self.text(), meta)

    def setReflexive(self, reflexive):
        """
        Set the reflexive property for the predicate represented by this node.
        :type reflexive: bool
        """
        meta = self.project.meta(self.type(), self.text())
        meta['reflexive'] = bool(reflexive)
        self.project.setMeta(self.type(), self.text(), meta)

    def setSymmetric(self, symmetric):
        """
        Set the symmetric property for the predicate represented by this node.
        :type symmetric: bool
        """
        meta = self.project.meta(self.type(), self.text())
        meta['symmetric'] = bool(symmetric)
        self.project.setMeta(self.type(), self.text(), meta)

    def setTransitive(self, transitive):
        """
        Set the transitive property for the predicate represented by this node.
        :type transitive: bool
        """
        meta = self.project.meta(self.type(), self.text())
        meta['transitive'] = bool(transitive)
        self.project.setMeta(self.type(), self.text(), meta)

    def setText(self, text):
        """
        Set the label text.
        :type text: str
        """
        self.label.setText(text)

    def setTextPos(self, pos):
        """
        Set the label position.
        :type pos: QPointF
        """
        self.label.setPos(pos)
        self.label.setAlignment(QtCore.Qt.AlignCenter)

    def shape(self):
        """
        Returns the shape of this item as a QPainterPath in local coordinates.
        :rtype: QPainterPath
        """
        path = QtGui.QPainterPath()
        path.addPolygon(self.polygon.geometry())
        for polygon in self.handles:
            path.addEllipse(polygon.geometry())
        return path

    def special(self):
        """
        Returns the special type of this node.
        :rtype: Special
        """
        return Special.forValue(self.text())

    def text(self):
        """
        Returns the label text.
        :rtype: str
        """
        return self.label.text()

    def textPos(self):
        """
        Returns the current label position in item coordinates.
        :rtype: QPointF
        """
        return self.label.pos()

    def updateNode(self, functional=None, inverseFunctional=None, **kwargs):
        """
        Update the current node.
        :type functional: bool
        :type inverseFunctional: bool
        """
        if functional is None:
            functional = self.isFunctional()
        if inverseFunctional is None:
            inverseFunctional = self.isInverseFunctional()

        polygon = self.polygon.geometry()

        # FUNCTIONAL POLYGON (SHAPE)
        fpolygon = QtGui.QPainterPath()
        if functional and not inverseFunctional:
            path = QtGui.QPainterPath()
            path.addPolygon(QtGui.QPolygonF([
                polygon[self.IndexL] + QtCore.QPointF(+5, 0),
                polygon[self.IndexB] + QtCore.QPointF(0, -4),
                polygon[self.IndexR] + QtCore.QPointF(-5, 0),
                polygon[self.IndexT] + QtCore.QPointF(0, +4),
                polygon[self.IndexL] + QtCore.QPointF(+5, 0),
            ]))
            fpolygon.addPolygon(polygon)
            fpolygon = fpolygon.subtracted(path)

        # INVERSE FUNCTIONAL POLYGON (SHAPE)
        ipolygon = QtGui.QPainterPath()
        if not functional and inverseFunctional:
            path = QtGui.QPainterPath()
            path.addPolygon(QtGui.QPolygonF([
                polygon[self.IndexL] + QtCore.QPointF(+5, 0),
                polygon[self.IndexB] + QtCore.QPointF(0, -4),
                polygon[self.IndexR] + QtCore.QPointF(-5, 0),
                polygon[self.IndexT] + QtCore.QPointF(0, +4),
                polygon[self.IndexL] + QtCore.QPointF(+5, 0),
            ]))
            ipolygon.addPolygon(polygon)
            ipolygon = ipolygon.subtracted(path)

        # FUNCTIONAL + INVERSE FUNCTIONAL POLYGONS (SHAPE)
        if functional and inverseFunctional:
            path = QtGui.QPainterPath()
            path.addPolygon(QtGui.QPolygonF([
                polygon[self.IndexL] + QtCore.QPointF(+5, 0),
                polygon[self.IndexB] + QtCore.QPointF(0, -4),
                polygon[self.IndexB],
                polygon[self.IndexR],
                polygon[self.IndexT],
                polygon[self.IndexT] + QtCore.QPointF(0, +4),
                polygon[self.IndexL] + QtCore.QPointF(+5, 0),
            ]))
            fpolygon.addPolygon(polygon)
            fpolygon = fpolygon.subtracted(path)
            path = QtGui.QPainterPath()
            path.addPolygon(QtGui.QPolygonF([
                polygon[self.IndexL],
                polygon[self.IndexB],
                polygon[self.IndexB] + QtCore.QPointF(0, -4),
                polygon[self.IndexR] + QtCore.QPointF(-5, 0),
                polygon[self.IndexT] + QtCore.QPointF(0, +4),
                polygon[self.IndexT],
                polygon[self.IndexL],
            ]))
            ipolygon.addPolygon(polygon)
            ipolygon = ipolygon.subtracted(path)

        # FUNCTIONAL POLYGON (PEN + BRUSH)
        fpen = QtGui.QPen(QtCore.Qt.NoPen)
        fbrush = QtGui.QBrush(QtCore.Qt.NoBrush)
        if functional:
            fpen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.1, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
            fbrush = QtGui.QBrush(QtGui.QColor(252, 252, 252, 255))

        # INVERSE FUNCTIONAL POLYGON (PEN + BRUSH)
        ipen = QtGui.QPen(QtCore.Qt.NoPen)
        ibrush = QtGui.QBrush(QtCore.Qt.NoBrush)
        if inverseFunctional:
            ipen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.1, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
            ibrush = QtGui.QBrush(QtGui.QColor(0, 0, 0, 255))

        self.fpolygon.setPen(fpen)
        self.fpolygon.setBrush(fbrush)
        self.fpolygon.setGeometry(fpolygon)
        self.ipolygon.setPen(ipen)
        self.ipolygon.setBrush(ibrush)
        self.ipolygon.setGeometry(ipolygon)

        # SELECTION + BACKGROUND + HANDLES + ANCHORS + CACHE REFRESH
        super().updateNode(**kwargs)

    def updateTextPos(self, *args, **kwargs):
        """
        Update the label position.
        """
        self.label.updatePos(*args, **kwargs)

    def width(self):
        """
        Returns the width of the shape.
        :rtype: int
        """
        polygon = self.polygon.geometry()
        return polygon[self.IndexR].x() - polygon[self.IndexL].x()

    def __repr__(self):
        """
        Returns repr(self).
        """
        return '{0}:{1}:{2}'.format(self.__class__.__name__, self.text(), self.id)
Exemplo n.º 7
0
class ConceptNode(AbstractResizableNode):
    """
    This class implements the 'Concept' node.
    """
    DefaultBrush = QtGui.QBrush(QtGui.QColor(252, 252, 252, 255))
    DefaultPen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.0, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
    Identities = {Identity.Concept}
    Type = Item.ConceptNode

    def __init__(self, width=110, height=50, brush=None, **kwargs):
        """
        Initialize the node.
        :type width: int
        :type height: int
        :type brush: QBrush
        """
        super().__init__(**kwargs)
        w = max(width, 110)
        h = max(height, 50)
        brush = brush or ConceptNode.DefaultBrush
        pen = ConceptNode.DefaultPen
        self.background = Polygon(QtCore.QRectF(-(w + 8) / 2, -(h + 8) / 2, w + 8, h + 8))
        self.selection = Polygon(QtCore.QRectF(-(w + 8) / 2, -(h + 8) / 2, w + 8, h + 8))
        self.polygon = Polygon(QtCore.QRectF(-w / 2, -h / 2, w, h), brush, pen)
        self.label = NodeLabel(template='concept', pos=self.center, parent=self)
        self.label.setAlignment(QtCore.Qt.AlignCenter)
        self.updateNode()
        self.updateTextPos()

    #############################################
    #   INTERFACE
    #################################

    def boundingRect(self):
        """
        Returns the shape bounding rectangle.
        :rtype: QtCore.QRectF
        """
        return self.selection.geometry()

    def copy(self, diagram):
        """
        Create a copy of the current item.
        :type diagram: Diagram
        """
        node = diagram.factory.create(self.type(), **{
            'id': self.id,
            'brush': self.brush(),
            'height': self.height(),
            'width': self.width()
        })
        node.setPos(self.pos())
        node.setText(self.text())
        node.setTextPos(node.mapFromScene(self.mapToScene(self.textPos())))
        return node

    def height(self):
        """
        Returns the height of the shape.
        :rtype: int
        """
        return self.polygon.geometry().height()

    def identity(self):
        """
        Returns the identity of the current node.
        :rtype: Identity
        """
        return Identity.Concept

    def paint(self, painter, option, widget=None):
        """
        Paint the node in the diagram.
        :type painter: QPainter
        :type option: QStyleOptionGraphicsItem
        :type widget: QWidget
        """
        # SET THE RECT THAT NEEDS TO BE REPAINTED
        painter.setClipRect(option.exposedRect)
        # SELECTION AREA
        painter.setPen(self.selection.pen())
        painter.setBrush(self.selection.brush())
        painter.drawRect(self.selection.geometry())
        # SYNTAX VALIDATION
        painter.setPen(self.background.pen())
        painter.setBrush(self.background.brush())
        painter.drawRect(self.background.geometry())
        # ITEM SHAPE
        painter.setPen(self.polygon.pen())
        painter.setBrush(self.polygon.brush())
        painter.drawRect(self.polygon.geometry())
        # RESIZE HANDLES
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        for polygon in self.handles:
            painter.setPen(polygon.pen())
            painter.setBrush(polygon.brush())
            painter.drawEllipse(polygon.geometry())

    def painterPath(self):
        """
        Returns the current shape as QtGui.QPainterPath (used for collision detection).
        :rtype: QPainterPath
        """
        path = QtGui.QPainterPath()
        path.addRect(self.polygon.geometry())
        return path

    def resize(self, mousePos):
        """
        Handle the interactive resize of the shape.
        :type mousePos: QtCore.QPointF
        """
        snap = self.session.action('toggle_grid').isChecked()
        size = self.diagram.GridSize
        moved = self.label.isMoved()
        background = self.background.geometry()
        selection = self.selection.geometry()
        polygon = self.polygon.geometry()

        R = QtCore.QRectF(self.boundingRect())
        D = QtCore.QPointF(0, 0)

        mbrh = 58
        mbrw = 118

        self.prepareGeometryChange()

        if self.mp_Handle == self.HandleTL:

            fromX = self.mp_Bound.left()
            fromY = self.mp_Bound.top()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, -4, snap)
            toY = snapF(toY, size, -4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setLeft(toX)
            R.setTop(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() - mbrw + R.width())
                R.setLeft(R.left() - mbrw + R.width())
            if R.height() < mbrh:
                D.setY(D.y() - mbrh + R.height())
                R.setTop(R.top() - mbrh + R.height())

            background.setLeft(R.left())
            background.setTop(R.top())
            selection.setLeft(R.left())
            selection.setTop(R.top())
            polygon.setLeft(R.left() + 4)
            polygon.setTop(R.top() + 4)

        elif self.mp_Handle == self.HandleTM:

            fromY = self.mp_Bound.top()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toY = snapF(toY, size, -4, snap)
            D.setY(toY - fromY)
            R.setTop(toY)

            ## CLAMP SIZE
            if R.height() < mbrh:
                D.setY(D.y() - mbrh + R.height())
                R.setTop(R.top() - mbrh + R.height())

            background.setTop(R.top())
            selection.setTop(R.top())
            polygon.setTop(R.top() + 4)

        elif self.mp_Handle == self.HandleTR:

            fromX = self.mp_Bound.right()
            fromY = self.mp_Bound.top()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, +4, snap)
            toY = snapF(toY, size, -4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setRight(toX)
            R.setTop(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() + mbrw - R.width())
                R.setRight(R.right() + mbrw - R.width())
            if R.height() < mbrh:
                D.setY(D.y() - mbrh + R.height())
                R.setTop(R.top() - mbrh + R.height())

            background.setRight(R.right())
            background.setTop(R.top())
            selection.setRight(R.right())
            selection.setTop(R.top())
            polygon.setRight(R.right() - 4)
            polygon.setTop(R.top() + 4)

        elif self.mp_Handle == self.HandleML:

            fromX = self.mp_Bound.left()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toX = snapF(toX, size, -4, snap)
            D.setX(toX - fromX)
            R.setLeft(toX)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() - mbrw + R.width())
                R.setLeft(R.left() - mbrw + R.width())

            background.setLeft(R.left())
            selection.setLeft(R.left())
            polygon.setLeft(R.left() + 4)

        elif self.mp_Handle == self.HandleMR:

            fromX = self.mp_Bound.right()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toX = snapF(toX, size, +4, snap)
            D.setX(toX - fromX)
            R.setRight(toX)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() + mbrw - R.width())
                R.setRight(R.right() + mbrw - R.width())

            background.setRight(R.right())
            selection.setRight(R.right())
            polygon.setRight(R.right() - 4)

        elif self.mp_Handle == self.HandleBL:

            fromX = self.mp_Bound.left()
            fromY = self.mp_Bound.bottom()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, -4, snap)
            toY = snapF(toY, size, +4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setLeft(toX)
            R.setBottom(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() - mbrw + R.width())
                R.setLeft(R.left() - mbrw + R.width())
            if R.height() < mbrh:
                D.setY(D.y() + mbrh - R.height())
                R.setBottom(R.bottom() + mbrh - R.height())

            background.setLeft(R.left())
            background.setBottom(R.bottom())
            selection.setLeft(R.left())
            selection.setBottom(R.bottom())
            polygon.setLeft(R.left() + 4)
            polygon.setBottom(R.bottom() - 4)

        elif self.mp_Handle == self.HandleBM:

            fromY = self.mp_Bound.bottom()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toY = snapF(toY, size, +4, snap)
            D.setY(toY - fromY)
            R.setBottom(toY)

            ## CLAMP SIZE
            if R.height() < mbrh:
                D.setY(D.y() + mbrh - R.height())
                R.setBottom(R.bottom() + mbrh - R.height())

            background.setBottom(R.bottom())
            selection.setBottom(R.bottom())
            polygon.setBottom(R.bottom() - 4)

        elif self.mp_Handle == self.HandleBR:

            fromX = self.mp_Bound.right()
            fromY = self.mp_Bound.bottom()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, +4, snap)
            toY = snapF(toY, size, +4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setRight(toX)
            R.setBottom(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() + mbrw - R.width())
                R.setRight(R.right() + mbrw - R.width())
            if R.height() < mbrh:
                D.setY(D.y() + mbrh - R.height())
                R.setBottom(R.bottom() + mbrh - R.height())

            background.setRight(R.right())
            background.setBottom(R.bottom())
            selection.setRight(R.right())
            selection.setBottom(R.bottom())
            polygon.setRight(R.right() - 4)
            polygon.setBottom(R.bottom() - 4)

        self.background.setGeometry(background)
        self.selection.setGeometry(selection)
        self.polygon.setGeometry(polygon)

        self.updateNode(selected=True, handle=self.mp_Handle, anchors=(self.mp_Data, D))
        self.updateTextPos(moved=moved)

    def setIdentity(self, identity):
        """
        Set the identity of the current node.
        :type identity: Identity
        """
        pass

    def setText(self, text):
        """
        Set the label text.
        :type text: str
        """
        self.label.setText(text)
        self.label.setAlignment(QtCore.Qt.AlignCenter)

    def setTextPos(self, pos):
        """
        Set the label position.
        :type pos: QPointF
        """
        self.label.setPos(pos)

    def shape(self):
        """
        Returns the shape of this item as a QPainterPath in local coordinates.
        :rtype: QPainterPath
        """
        path = QtGui.QPainterPath()
        path.addRect(self.polygon.geometry())
        for polygon in self.handles:
            path.addEllipse(polygon.geometry())
        return path

    def special(self):
        """
        Returns the special type of this node.
        :rtype: Special
        """
        return Special.forValue(self.text())

    def text(self):
        """
        Returns the label text.
        :rtype: str
        """
        return self.label.text()

    def textPos(self):
        """
        Returns the current label position in item coordinates.
        :rtype: QPointF
        """
        return self.label.pos()

    def updateTextPos(self, *args, **kwargs):
        """
        Update the label position.
        """
        self.label.updatePos(*args, **kwargs)

    def width(self):
        """
        Returns the width of the shape.
        :rtype: int
        """
        return self.polygon.geometry().width()

    def __repr__(self):
        """
        Returns repr(self).
        """
        return '{0}:{1}:{2}'.format(self.__class__.__name__, self.text(), self.id)
Exemplo n.º 8
0
class IndividualNode(AbstractResizableNode):
    """
    This class implements the 'Individual' node.
    """

    IndexLT = 0
    IndexLB = 1
    IndexBL = 2
    IndexBR = 3
    IndexRB = 4
    IndexRT = 5
    IndexTR = 6
    IndexTL = 7
    IndexEE = 8

    DefaultBrush = QtGui.QBrush(QtGui.QColor(252, 252, 252, 255))
    DefaultPen = QtGui.QPen(
        QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.0, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin
    )
    Identities = {Identity.Individual, Identity.Value}
    Type = Item.IndividualNode

    def __init__(self, width=60, height=60, brush=None, **kwargs):
        """
        Initialize the node.
        :type width: int
        :type height: int
        :type brush: QBrush
        """
        super().__init__(**kwargs)

        w = max(width, 60)
        h = max(height, 60)
        brush = brush or IndividualNode.DefaultBrush
        pen = IndividualNode.DefaultPen

        createPolygon = lambda x, y: QtGui.QPolygonF(
            [
                QtCore.QPointF(-(x / 2), -((y / (1 + math.sqrt(2))) / 2)),
                QtCore.QPointF(-(x / 2), +((y / (1 + math.sqrt(2))) / 2)),
                QtCore.QPointF(-((x / (1 + math.sqrt(2))) / 2), +(y / 2)),
                QtCore.QPointF(+((x / (1 + math.sqrt(2))) / 2), +(y / 2)),
                QtCore.QPointF(+(x / 2), +((y / (1 + math.sqrt(2))) / 2)),
                QtCore.QPointF(+(x / 2), -((y / (1 + math.sqrt(2))) / 2)),
                QtCore.QPointF(+((x / (1 + math.sqrt(2))) / 2), -(y / 2)),
                QtCore.QPointF(-((x / (1 + math.sqrt(2))) / 2), -(y / 2)),
                QtCore.QPointF(-(x / 2), -((y / (1 + math.sqrt(2))) / 2)),
            ]
        )

        self.background = Polygon(createPolygon(w + 8, h + 8))
        self.selection = Polygon(createPolygon(w + 8, h + 8))
        self.polygon = Polygon(createPolygon(w, h), brush, pen)
        self.label = NodeLabel(template="individual", pos=self.center, parent=self)
        self.label.setAlignment(QtCore.Qt.AlignCenter)
        self.updateNode()
        self.updateTextPos()

    #############################################
    #   PROPERTIES
    #################################

    @property
    def datatype(self):
        """
        Returns the datatype associated with this node.
        :rtype: Datatype
        """
        match = RE_VALUE.match(self.text())
        if match:
            return Datatype.forValue(match.group("datatype"))
        return None

    @property
    def value(self):
        """
        Returns the value value associated with this node.
        :rtype: str
        """
        match = RE_VALUE.match(self.text())
        if match:
            return match.group("value")
        return None

    #############################################
    #   INTERFACE
    #################################

    def boundingRect(self):
        """
        Returns the shape bounding rectangle.
        :rtype: QtCore.QRectF
        """
        path = QtGui.QPainterPath()
        path.addPolygon(self.selection.geometry())
        return path.boundingRect()

    @staticmethod
    def compose(value, datatype):
        """
        Compose the value string.
        :type value: str
        :type datatype: Datatype
        :return: str
        """
        return '"{0}"^^{1}'.format(value.strip('"'), datatype.value)

    def copy(self, diagram):
        """
        Create a copy of the current item.
        :type diagram: Diagram
        """
        node = diagram.factory.create(
            self.type(), **{"id": self.id, "brush": self.brush(), "height": self.height(), "width": self.width()}
        )
        node.setPos(self.pos())
        node.setText(self.text())
        node.setTextPos(node.mapFromScene(self.mapToScene(self.textPos())))
        return node

    def height(self):
        """
        Returns the height of the shape.
        :rtype: int
        """
        polygon = self.polygon.geometry()
        return polygon[self.IndexTR].y() - polygon[self.IndexBR].y()

    def identity(self):
        """
        Returns the identity of the current node.
        :rtype: Identity
        """
        match = RE_VALUE.match(self.text())
        if match:
            return Identity.Value
        return Identity.Individual

    def paint(self, painter, option, widget=None):
        """
        Paint the node in the diagram.
        :type painter: QPainter
        :type option: QStyleOptionGraphicsItem
        :type widget: QWidget
        """
        # SET THE RECT THAT NEEDS TO BE REPAINTED
        painter.setClipRect(option.exposedRect)
        # SELECTION AREA
        painter.setPen(self.selection.pen())
        painter.setBrush(self.selection.brush())
        painter.drawPolygon(self.selection.geometry())
        # SYNTAX VALIDATION
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        painter.setPen(self.background.pen())
        painter.setBrush(self.background.brush())
        painter.drawPolygon(self.background.geometry())
        # ITEM SHAPE
        painter.setPen(self.polygon.pen())
        painter.setBrush(self.polygon.brush())
        painter.drawPolygon(self.polygon.geometry())
        # RESIZE HANDLES
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        for polygon in self.handles:
            painter.setPen(polygon.pen())
            painter.setBrush(polygon.brush())
            painter.drawEllipse(polygon.geometry())

    def painterPath(self):
        """
        Returns the current shape as QtGui.QPainterPath (used for collision detection).
        :rtype: QPainterPath
        """
        path = QtGui.QPainterPath()
        path.addPolygon(self.polygon.geometry())
        return path

    def resize(self, mousePos):
        """
        Handle the interactive resize of the shape.
        :type mousePos: QtCore.QPointF
        """
        snap = self.session.action("toggle_grid").isChecked()
        size = self.diagram.GridSize
        moved = self.label.isMoved()

        background = self.background.geometry()
        selection = self.selection.geometry()
        polygon = self.polygon.geometry()

        R = QtCore.QRectF(self.boundingRect())
        D = QtCore.QPointF(0, 0)

        mbrh = 68
        mbrw = 68

        self.prepareGeometryChange()

        if self.mp_Handle == self.HandleTL:

            fromX = self.mp_Bound.left()
            fromY = self.mp_Bound.top()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, -4, snap)
            toY = snapF(toY, size, -4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setLeft(toX)
            R.setTop(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() - mbrw + R.width())
                R.setLeft(R.left() - mbrw + R.width())
            if R.height() < mbrh:
                D.setY(D.y() - mbrh + R.height())
                R.setTop(R.top() - mbrh + R.height())

            newSideY = (R.height() - 4 * 2) / (1 + math.sqrt(2))
            newSideX = (R.width() - 4 * 2) / (1 + math.sqrt(2))
            newLeftRightBottomY = (R.y() + R.height() / 2) + newSideY / 2
            newLeftRightTopY = (R.y() + R.height() / 2) - newSideY / 2
            newTopBottomLeftX = (R.x() + R.width() / 2) - newSideX / 2
            newTopBottomRightX = (R.x() + R.width() / 2) + newSideX / 2

            selection[self.IndexLT] = QtCore.QPointF(R.left(), newLeftRightTopY)
            selection[self.IndexLB] = QtCore.QPointF(R.left(), newLeftRightBottomY)
            selection[self.IndexRT] = QtCore.QPointF(R.right(), newLeftRightTopY)
            selection[self.IndexRB] = QtCore.QPointF(R.right(), newLeftRightBottomY)
            selection[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX, R.top())
            selection[self.IndexTR] = QtCore.QPointF(newTopBottomRightX, R.top())
            selection[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX, R.bottom())
            selection[self.IndexBR] = QtCore.QPointF(newTopBottomRightX, R.bottom())
            selection[self.IndexEE] = QtCore.QPointF(R.left(), newLeftRightTopY)

            background[self.IndexLT] = QtCore.QPointF(R.left(), newLeftRightTopY)
            background[self.IndexLB] = QtCore.QPointF(R.left(), newLeftRightBottomY)
            background[self.IndexRT] = QtCore.QPointF(R.right(), newLeftRightTopY)
            background[self.IndexRB] = QtCore.QPointF(R.right(), newLeftRightBottomY)
            background[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX, R.top())
            background[self.IndexTR] = QtCore.QPointF(newTopBottomRightX, R.top())
            background[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX, R.bottom())
            background[self.IndexBR] = QtCore.QPointF(newTopBottomRightX, R.bottom())
            background[self.IndexEE] = QtCore.QPointF(R.left(), newLeftRightTopY)

            polygon[self.IndexLT] = QtCore.QPointF(R.left() + 4, newLeftRightTopY)
            polygon[self.IndexLB] = QtCore.QPointF(R.left() + 4, newLeftRightBottomY)
            polygon[self.IndexRT] = QtCore.QPointF(R.right() - 4, newLeftRightTopY)
            polygon[self.IndexRB] = QtCore.QPointF(R.right() - 4, newLeftRightBottomY)
            polygon[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX, R.top() + 4)
            polygon[self.IndexTR] = QtCore.QPointF(newTopBottomRightX, R.top() + 4)
            polygon[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX, R.bottom() - 4)
            polygon[self.IndexBR] = QtCore.QPointF(newTopBottomRightX, R.bottom() - 4)
            polygon[self.IndexEE] = QtCore.QPointF(R.left() + 4, newLeftRightTopY)

        elif self.mp_Handle == self.HandleTM:

            fromY = self.mp_Bound.top()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toY = snapF(toY, size, -4, snap)
            D.setY(toY - fromY)
            R.setTop(toY)

            ## CLAMP SIZE
            if R.height() < mbrh:
                D.setY(D.y() - mbrh + R.height())
                R.setTop(R.top() - mbrh + R.height())

            newSide = (R.height() - 4 * 2) / (1 + math.sqrt(2))
            newLeftRightBottomY = (R.y() + R.height() / 2) + newSide / 2
            newLeftRightTopY = (R.y() + R.height() / 2) - newSide / 2

            selection[self.IndexTL] = QtCore.QPointF(background[self.IndexTL].x(), R.top())
            selection[self.IndexTR] = QtCore.QPointF(background[self.IndexTR].x(), R.top())
            selection[self.IndexLB] = QtCore.QPointF(background[self.IndexLB].x(), newLeftRightBottomY)
            selection[self.IndexRB] = QtCore.QPointF(background[self.IndexRB].x(), newLeftRightBottomY)
            selection[self.IndexLT] = QtCore.QPointF(background[self.IndexLT].x(), newLeftRightTopY)
            selection[self.IndexRT] = QtCore.QPointF(background[self.IndexRT].x(), newLeftRightTopY)
            selection[self.IndexEE] = QtCore.QPointF(background[self.IndexEE].x(), newLeftRightTopY)

            background[self.IndexTL] = QtCore.QPointF(background[self.IndexTL].x(), R.top())
            background[self.IndexTR] = QtCore.QPointF(background[self.IndexTR].x(), R.top())
            background[self.IndexLB] = QtCore.QPointF(background[self.IndexLB].x(), newLeftRightBottomY)
            background[self.IndexRB] = QtCore.QPointF(background[self.IndexRB].x(), newLeftRightBottomY)
            background[self.IndexLT] = QtCore.QPointF(background[self.IndexLT].x(), newLeftRightTopY)
            background[self.IndexRT] = QtCore.QPointF(background[self.IndexRT].x(), newLeftRightTopY)
            background[self.IndexEE] = QtCore.QPointF(background[self.IndexEE].x(), newLeftRightTopY)

            polygon[self.IndexTL] = QtCore.QPointF(polygon[self.IndexTL].x(), R.top() + 4)
            polygon[self.IndexTR] = QtCore.QPointF(polygon[self.IndexTR].x(), R.top() + 4)
            polygon[self.IndexLB] = QtCore.QPointF(polygon[self.IndexLB].x(), newLeftRightBottomY)
            polygon[self.IndexRB] = QtCore.QPointF(polygon[self.IndexRB].x(), newLeftRightBottomY)
            polygon[self.IndexLT] = QtCore.QPointF(polygon[self.IndexLT].x(), newLeftRightTopY)
            polygon[self.IndexRT] = QtCore.QPointF(polygon[self.IndexRT].x(), newLeftRightTopY)
            polygon[self.IndexEE] = QtCore.QPointF(polygon[self.IndexEE].x(), newLeftRightTopY)

        elif self.mp_Handle == self.HandleTR:

            fromX = self.mp_Bound.right()
            fromY = self.mp_Bound.top()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, +4, snap)
            toY = snapF(toY, size, -4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setRight(toX)
            R.setTop(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() + mbrw - R.width())
                R.setRight(R.right() + mbrw - R.width())
            if R.height() < mbrh:
                D.setY(D.y() - mbrh + R.height())
                R.setTop(R.top() - mbrh + R.height())

            newSideY = (R.height() - 4 * 2) / (1 + math.sqrt(2))
            newSideX = (R.width() - 4 * 2) / (1 + math.sqrt(2))
            newLeftRightBottomY = (R.y() + R.height() / 2) + newSideY / 2
            newLeftRightTopY = (R.y() + R.height() / 2) - newSideY / 2
            newTopBottomLeftX = (R.x() + R.width() / 2) - newSideX / 2
            newTopBottomRightX = (R.x() + R.width() / 2) + newSideX / 2

            selection[self.IndexLT] = QtCore.QPointF(R.left(), newLeftRightTopY)
            selection[self.IndexLB] = QtCore.QPointF(R.left(), newLeftRightBottomY)
            selection[self.IndexRT] = QtCore.QPointF(R.right(), newLeftRightTopY)
            selection[self.IndexRB] = QtCore.QPointF(R.right(), newLeftRightBottomY)
            selection[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX, R.top())
            selection[self.IndexTR] = QtCore.QPointF(newTopBottomRightX, R.top())
            selection[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX, R.bottom())
            selection[self.IndexBR] = QtCore.QPointF(newTopBottomRightX, R.bottom())
            selection[self.IndexEE] = QtCore.QPointF(R.left(), newLeftRightTopY)

            background[self.IndexLT] = QtCore.QPointF(R.left(), newLeftRightTopY)
            background[self.IndexLB] = QtCore.QPointF(R.left(), newLeftRightBottomY)
            background[self.IndexRT] = QtCore.QPointF(R.right(), newLeftRightTopY)
            background[self.IndexRB] = QtCore.QPointF(R.right(), newLeftRightBottomY)
            background[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX, R.top())
            background[self.IndexTR] = QtCore.QPointF(newTopBottomRightX, R.top())
            background[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX, R.bottom())
            background[self.IndexBR] = QtCore.QPointF(newTopBottomRightX, R.bottom())
            background[self.IndexEE] = QtCore.QPointF(R.left(), newLeftRightTopY)

            polygon[self.IndexLT] = QtCore.QPointF(R.left() + 4, newLeftRightTopY)
            polygon[self.IndexLB] = QtCore.QPointF(R.left() + 4, newLeftRightBottomY)
            polygon[self.IndexRT] = QtCore.QPointF(R.right() - 4, newLeftRightTopY)
            polygon[self.IndexRB] = QtCore.QPointF(R.right() - 4, newLeftRightBottomY)
            polygon[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX, R.top() + 4)
            polygon[self.IndexTR] = QtCore.QPointF(newTopBottomRightX, R.top() + 4)
            polygon[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX, R.bottom() - 4)
            polygon[self.IndexBR] = QtCore.QPointF(newTopBottomRightX, R.bottom() - 4)
            polygon[self.IndexEE] = QtCore.QPointF(R.left() + 4, newLeftRightTopY)

        elif self.mp_Handle == self.HandleML:

            fromX = self.mp_Bound.left()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toX = snapF(toX, size, -4, snap)
            D.setX(toX - fromX)
            R.setLeft(toX)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() - mbrw + R.width())
                R.setLeft(R.left() - mbrw + R.width())

            newSide = (R.width() - 4 * 2) / (1 + math.sqrt(2))
            newTopBottomLeftX = (R.x() + R.width() / 2) - newSide / 2
            newTopBottomRightX = (R.x() + R.width() / 2) + newSide / 2

            selection[self.IndexLT] = QtCore.QPointF(R.left(), selection[self.IndexLT].y())
            selection[self.IndexLB] = QtCore.QPointF(R.left(), selection[self.IndexLB].y())
            selection[self.IndexEE] = QtCore.QPointF(R.left(), selection[self.IndexEE].y())
            selection[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX, selection[self.IndexTL].y())
            selection[self.IndexTR] = QtCore.QPointF(newTopBottomRightX, selection[self.IndexTR].y())
            selection[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX, selection[self.IndexBL].y())
            selection[self.IndexBR] = QtCore.QPointF(newTopBottomRightX, selection[self.IndexBR].y())

            background[self.IndexLT] = QtCore.QPointF(R.left(), background[self.IndexLT].y())
            background[self.IndexLB] = QtCore.QPointF(R.left(), background[self.IndexLB].y())
            background[self.IndexEE] = QtCore.QPointF(R.left(), background[self.IndexEE].y())
            background[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX, background[self.IndexTL].y())
            background[self.IndexTR] = QtCore.QPointF(newTopBottomRightX, background[self.IndexTR].y())
            background[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX, background[self.IndexBL].y())
            background[self.IndexBR] = QtCore.QPointF(newTopBottomRightX, background[self.IndexBR].y())

            polygon[self.IndexLT] = QtCore.QPointF(R.left() + 4, polygon[self.IndexLT].y())
            polygon[self.IndexLB] = QtCore.QPointF(R.left() + 4, polygon[self.IndexLB].y())
            polygon[self.IndexEE] = QtCore.QPointF(R.left() + 4, polygon[self.IndexEE].y())
            polygon[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX, polygon[self.IndexTL].y())
            polygon[self.IndexTR] = QtCore.QPointF(newTopBottomRightX, polygon[self.IndexTR].y())
            polygon[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX, polygon[self.IndexBL].y())
            polygon[self.IndexBR] = QtCore.QPointF(newTopBottomRightX, polygon[self.IndexBR].y())

        elif self.mp_Handle == self.HandleMR:

            fromX = self.mp_Bound.right()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toX = snapF(toX, size, +4, snap)
            D.setX(toX - fromX)
            R.setRight(toX)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() + mbrw - R.width())
                R.setRight(R.right() + mbrw - R.width())

            newSide = (R.width() - 4 * 2) / (1 + math.sqrt(2))
            newTopBottomRightX = (R.x() + R.width() / 2) + newSide / 2
            newTopBottomLeftX = (R.x() + R.width() / 2) - newSide / 2

            selection[self.IndexRT] = QtCore.QPointF(R.right(), selection[self.IndexRT].y())
            selection[self.IndexRB] = QtCore.QPointF(R.right(), selection[self.IndexRB].y())
            selection[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX, selection[self.IndexTL].y())
            selection[self.IndexTR] = QtCore.QPointF(newTopBottomRightX, selection[self.IndexTR].y())
            selection[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX, selection[self.IndexBL].y())
            selection[self.IndexBR] = QtCore.QPointF(newTopBottomRightX, selection[self.IndexBR].y())

            background[self.IndexRT] = QtCore.QPointF(R.right(), background[self.IndexRT].y())
            background[self.IndexRB] = QtCore.QPointF(R.right(), background[self.IndexRB].y())
            background[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX, background[self.IndexTL].y())
            background[self.IndexTR] = QtCore.QPointF(newTopBottomRightX, background[self.IndexTR].y())
            background[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX, background[self.IndexBL].y())
            background[self.IndexBR] = QtCore.QPointF(newTopBottomRightX, background[self.IndexBR].y())

            polygon[self.IndexRT] = QtCore.QPointF(R.right() - 4, polygon[self.IndexRT].y())
            polygon[self.IndexRB] = QtCore.QPointF(R.right() - 4, polygon[self.IndexRB].y())
            polygon[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX, polygon[self.IndexTL].y())
            polygon[self.IndexTR] = QtCore.QPointF(newTopBottomRightX, polygon[self.IndexTR].y())
            polygon[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX, polygon[self.IndexBL].y())
            polygon[self.IndexBR] = QtCore.QPointF(newTopBottomRightX, polygon[self.IndexBR].y())

        elif self.mp_Handle == self.HandleBL:

            fromX = self.mp_Bound.left()
            fromY = self.mp_Bound.bottom()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, -4, snap)
            toY = snapF(toY, size, +4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setLeft(toX)
            R.setBottom(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() - mbrw + R.width())
                R.setLeft(R.left() - mbrw + R.width())
            if R.height() < mbrh:
                D.setY(D.y() + mbrh - R.height())
                R.setBottom(R.bottom() + mbrh - R.height())

            newSideY = (R.height() - 4 * 2) / (1 + math.sqrt(2))
            newSideX = (R.width() - 4 * 2) / (1 + math.sqrt(2))
            newLeftRightBottomY = (R.y() + R.height() / 2) + newSideY / 2
            newLeftRightTopY = (R.y() + R.height() / 2) - newSideY / 2
            newTopBottomLeftX = (R.x() + R.width() / 2) - newSideX / 2
            newTopBottomRightX = (R.x() + R.width() / 2) + newSideX / 2

            selection[self.IndexLT] = QtCore.QPointF(R.left(), newLeftRightTopY)
            selection[self.IndexLB] = QtCore.QPointF(R.left(), newLeftRightBottomY)
            selection[self.IndexRT] = QtCore.QPointF(R.right(), newLeftRightTopY)
            selection[self.IndexRB] = QtCore.QPointF(R.right(), newLeftRightBottomY)
            selection[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX, R.top())
            selection[self.IndexTR] = QtCore.QPointF(newTopBottomRightX, R.top())
            selection[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX, R.bottom())
            selection[self.IndexBR] = QtCore.QPointF(newTopBottomRightX, R.bottom())
            selection[self.IndexEE] = QtCore.QPointF(R.left(), newLeftRightTopY)

            background[self.IndexLT] = QtCore.QPointF(R.left(), newLeftRightTopY)
            background[self.IndexLB] = QtCore.QPointF(R.left(), newLeftRightBottomY)
            background[self.IndexRT] = QtCore.QPointF(R.right(), newLeftRightTopY)
            background[self.IndexRB] = QtCore.QPointF(R.right(), newLeftRightBottomY)
            background[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX, R.top())
            background[self.IndexTR] = QtCore.QPointF(newTopBottomRightX, R.top())
            background[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX, R.bottom())
            background[self.IndexBR] = QtCore.QPointF(newTopBottomRightX, R.bottom())
            background[self.IndexEE] = QtCore.QPointF(R.left(), newLeftRightTopY)

            polygon[self.IndexLT] = QtCore.QPointF(R.left() + 4, newLeftRightTopY)
            polygon[self.IndexLB] = QtCore.QPointF(R.left() + 4, newLeftRightBottomY)
            polygon[self.IndexRT] = QtCore.QPointF(R.right() - 4, newLeftRightTopY)
            polygon[self.IndexRB] = QtCore.QPointF(R.right() - 4, newLeftRightBottomY)
            polygon[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX, R.top() + 4)
            polygon[self.IndexTR] = QtCore.QPointF(newTopBottomRightX, R.top() + 4)
            polygon[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX, R.bottom() - 4)
            polygon[self.IndexBR] = QtCore.QPointF(newTopBottomRightX, R.bottom() - 4)
            polygon[self.IndexEE] = QtCore.QPointF(R.left() + 4, newLeftRightTopY)

        elif self.mp_Handle == self.HandleBM:

            fromY = self.mp_Bound.bottom()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toY = snapF(toY, size, +4, snap)
            D.setY(toY - fromY)
            R.setBottom(toY)

            ## CLAMP SIZE
            if R.height() < mbrh:
                D.setY(D.y() + mbrh - R.height())
                R.setBottom(R.bottom() + mbrh - R.height())

            newSide = (R.height() - 4 * 2) / (1 + math.sqrt(2))
            newLeftRightTopY = (R.y() + R.height() / 2) - newSide / 2
            newLeftRightBottomY = (R.y() + R.height() / 2) + newSide / 2

            selection[self.IndexBL] = QtCore.QPointF(selection[self.IndexBL].x(), R.bottom())
            selection[self.IndexBR] = QtCore.QPointF(selection[self.IndexBR].x(), R.bottom())
            selection[self.IndexLB] = QtCore.QPointF(selection[self.IndexLB].x(), newLeftRightBottomY)
            selection[self.IndexRB] = QtCore.QPointF(selection[self.IndexRB].x(), newLeftRightBottomY)
            selection[self.IndexLT] = QtCore.QPointF(selection[self.IndexLT].x(), newLeftRightTopY)
            selection[self.IndexRT] = QtCore.QPointF(selection[self.IndexRT].x(), newLeftRightTopY)
            selection[self.IndexEE] = QtCore.QPointF(selection[self.IndexEE].x(), newLeftRightTopY)

            background[self.IndexBL] = QtCore.QPointF(background[self.IndexBL].x(), R.bottom())
            background[self.IndexBR] = QtCore.QPointF(background[self.IndexBR].x(), R.bottom())
            background[self.IndexLB] = QtCore.QPointF(background[self.IndexLB].x(), newLeftRightBottomY)
            background[self.IndexRB] = QtCore.QPointF(background[self.IndexRB].x(), newLeftRightBottomY)
            background[self.IndexLT] = QtCore.QPointF(background[self.IndexLT].x(), newLeftRightTopY)
            background[self.IndexRT] = QtCore.QPointF(background[self.IndexRT].x(), newLeftRightTopY)
            background[self.IndexEE] = QtCore.QPointF(background[self.IndexEE].x(), newLeftRightTopY)

            polygon[self.IndexBL] = QtCore.QPointF(polygon[self.IndexBL].x(), R.bottom() - 4)
            polygon[self.IndexBR] = QtCore.QPointF(polygon[self.IndexBR].x(), R.bottom() - 4)
            polygon[self.IndexLB] = QtCore.QPointF(polygon[self.IndexLB].x(), newLeftRightBottomY)
            polygon[self.IndexRB] = QtCore.QPointF(polygon[self.IndexRB].x(), newLeftRightBottomY)
            polygon[self.IndexLT] = QtCore.QPointF(polygon[self.IndexLT].x(), newLeftRightTopY)
            polygon[self.IndexRT] = QtCore.QPointF(polygon[self.IndexRT].x(), newLeftRightTopY)
            polygon[self.IndexEE] = QtCore.QPointF(polygon[self.IndexEE].x(), newLeftRightTopY)

        elif self.mp_Handle == self.HandleBR:

            fromX = self.mp_Bound.right()
            fromY = self.mp_Bound.bottom()
            toX = fromX + mousePos.x() - self.mp_Pos.x()
            toY = fromY + mousePos.y() - self.mp_Pos.y()
            toX = snapF(toX, size, +4, snap)
            toY = snapF(toY, size, +4, snap)
            D.setX(toX - fromX)
            D.setY(toY - fromY)
            R.setRight(toX)
            R.setBottom(toY)

            ## CLAMP SIZE
            if R.width() < mbrw:
                D.setX(D.x() + mbrw - R.width())
                R.setRight(R.right() + mbrw - R.width())
            if R.height() < mbrh:
                D.setY(D.y() + mbrh - R.height())
                R.setBottom(R.bottom() + mbrh - R.height())

            newSideY = (R.height() - 4 * 2) / (1 + math.sqrt(2))
            newSideX = (R.width() - 4 * 2) / (1 + math.sqrt(2))
            newLeftRightBottomY = (R.y() + R.height() / 2) + newSideY / 2
            newLeftRightTopY = (R.y() + R.height() / 2) - newSideY / 2
            newTopBottomLeftX = (R.x() + R.width() / 2) - newSideX / 2
            newTopBottomRightX = (R.x() + R.width() / 2) + newSideX / 2

            selection[self.IndexLT] = QtCore.QPointF(R.left(), newLeftRightTopY)
            selection[self.IndexLB] = QtCore.QPointF(R.left(), newLeftRightBottomY)
            selection[self.IndexRT] = QtCore.QPointF(R.right(), newLeftRightTopY)
            selection[self.IndexRB] = QtCore.QPointF(R.right(), newLeftRightBottomY)
            selection[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX, R.top())
            selection[self.IndexTR] = QtCore.QPointF(newTopBottomRightX, R.top())
            selection[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX, R.bottom())
            selection[self.IndexBR] = QtCore.QPointF(newTopBottomRightX, R.bottom())
            selection[self.IndexEE] = QtCore.QPointF(R.left(), newLeftRightTopY)

            background[self.IndexLT] = QtCore.QPointF(R.left(), newLeftRightTopY)
            background[self.IndexLB] = QtCore.QPointF(R.left(), newLeftRightBottomY)
            background[self.IndexRT] = QtCore.QPointF(R.right(), newLeftRightTopY)
            background[self.IndexRB] = QtCore.QPointF(R.right(), newLeftRightBottomY)
            background[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX, R.top())
            background[self.IndexTR] = QtCore.QPointF(newTopBottomRightX, R.top())
            background[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX, R.bottom())
            background[self.IndexBR] = QtCore.QPointF(newTopBottomRightX, R.bottom())
            background[self.IndexEE] = QtCore.QPointF(R.left(), newLeftRightTopY)

            polygon[self.IndexLT] = QtCore.QPointF(R.left() + 4, newLeftRightTopY)
            polygon[self.IndexLB] = QtCore.QPointF(R.left() + 4, newLeftRightBottomY)
            polygon[self.IndexRT] = QtCore.QPointF(R.right() - 4, newLeftRightTopY)
            polygon[self.IndexRB] = QtCore.QPointF(R.right() - 4, newLeftRightBottomY)
            polygon[self.IndexTL] = QtCore.QPointF(newTopBottomLeftX, R.top() + 4)
            polygon[self.IndexTR] = QtCore.QPointF(newTopBottomRightX, R.top() + 4)
            polygon[self.IndexBL] = QtCore.QPointF(newTopBottomLeftX, R.bottom() - 4)
            polygon[self.IndexBR] = QtCore.QPointF(newTopBottomRightX, R.bottom() - 4)
            polygon[self.IndexEE] = QtCore.QPointF(R.left() + 4, newLeftRightTopY)

        self.background.setGeometry(background)
        self.selection.setGeometry(selection)
        self.polygon.setGeometry(polygon)

        self.updateNode(selected=True, handle=self.mp_Handle, anchors=(self.mp_Data, D))
        self.updateTextPos(moved=moved)

    def setIdentity(self, identity):
        """
        Set the identity of the current node.
        :type identity: Identity
        """
        pass

    def setText(self, text):
        """
        Set the label text: will additionally block label editing if a literal is being.
        :type text: str
        """
        self.label.setEditable(RE_VALUE.match(text) is None)
        self.label.setText(text)
        self.label.setAlignment(QtCore.Qt.AlignCenter)

    def setTextPos(self, pos):
        """
        Set the label position.
        :type pos: QPointF
        """
        self.label.setPos(pos)

    def shape(self):
        """
        Returns the shape of this item as a QPainterPath in local coordinates.
        :rtype: QPainterPath
        """
        path = QtGui.QPainterPath()
        path.addPolygon(self.polygon.geometry())
        for polygon in self.handles:
            path.addEllipse(polygon.geometry())
        return path

    def text(self):
        """
        Returns the label text.
        :rtype: str
        """
        return self.label.text()

    def textPos(self):
        """
        Returns the current label position in item coordinates.
        :rtype: QPointF
        """
        return self.label.pos()

    def updateTextPos(self, *args, **kwargs):
        """
        Update the label position.
        """
        self.label.updatePos(*args, **kwargs)

    def width(self):
        """
        Returns the width of the shape.
        :rtype: int
        """
        polygon = self.polygon.geometry()
        return polygon[self.IndexRT].x() - polygon[self.IndexLT].x()

    def __repr__(self):
        """
        Returns repr(self).
        """
        return "{0}:{1}:{2}".format(self.__class__.__name__, self.text(), self.id)