class FacetNode(AbstractNode): """ This class implements the 'Facet' node. """ IndexTL = 0 IndexTR = 1 IndexBR = 2 IndexBL = 3 IndexEE = 4 DefaultBrushA = QtGui.QBrush(QtGui.QColor(222, 222, 222, 255)) DefaultBrushB = QtGui.QBrush(QtGui.QColor(252, 252, 252, 255)) DefaultPenA = QtGui.QPen( QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.0, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin ) DefaultPenB = QtGui.QPen( QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.0, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin ) Identities = {Identity.Facet} Type = Item.FacetNode def __init__(self, width=80, height=40, brush=None, **kwargs): """ Initialize the node. :type width: int :type height: int :type brush: QBrush """ super().__init__(**kwargs) self.background = Polygon(self.createPolygon(88, 48)) self.selection = Polygon(self.createPolygon(88, 48)) self.polygon = Polygon(self.createPolygon(80, 40)) self.polygonA = Polygon(self.createPolygonA(80, 40), FacetNode.DefaultBrushA, FacetNode.DefaultPenA) self.polygonB = Polygon(self.createPolygonA(80, 40), FacetNode.DefaultBrushB, FacetNode.DefaultPenB) self.labelA = NodeLabel(Facet.length.value, pos=self.centerA, editable=False, movable=False, parent=self) self.labelB = FacetQuotedLabel(template='"32"', movable=False, pos=self.centerB, parent=self) self.updateNode() self.updateTextPos() ############################################# # PROPERTIES ################################# @property def datatype(self): """ Returns the datatype this facet is restricting, or None if the node is isolated. :rtype: Datatype """ f1 = lambda x: x.type() is Item.InputEdge f2 = lambda x: x.type() is Item.DatatypeRestrictionNode f3 = lambda x: x.type() is Item.ValueDomainNode outgoing = first(self.outgoingNodes(filter_on_edges=f1, filter_on_nodes=f2)) if outgoing: incoming = first(outgoing.incomingNodes(filter_on_edges=f1, filter_on_nodes=f3)) if incoming: return incoming.datatype return None @property def facet(self): """ Returns the facet associated with this node. :rtype: Facet """ return Facet.forValue(self.labelA.text()) @property def value(self): """ Returns the value of this facet node. :rtype: str """ return self.labelB.text().strip('"') ############################################# # INTERFACE ################################# def boundingRect(self): """ Returns the shape bounding rectangle. :rtype: QtCore.QRectF """ path = QtGui.QPainterPath() path.addPolygon(self.selection.geometry()) return path.boundingRect() def brushA(self): """ Returns the brush used to paint the shape A of this node. :rtype: QtGui.QBrush """ return self.polygonA.brush() def brushB(self): """ Returns the brush used to paint the shape B of this node. :rtype: QtGui.QBrush """ return self.polygonB.brush() def centerA(self): """ Returns the center point of polygon A. :rtype: QPointF """ return self.boundingRect().center() - QtCore.QPointF(0, 40 / 4) def centerB(self): """ Returns the center point of polygon A. :rtype: QPointF """ return self.boundingRect().center() + QtCore.QPointF(0, 40 / 4) @staticmethod def compose(facet, value): """ Compose the restriction string. :type facet: Facet :type value: str :return: str """ return '{0}^^"{1}"'.format(facet.value, value.strip().strip('"')) def copy(self, diagram): """ Create a copy of the current item. :type diagram: Diagram """ node = diagram.factory.create(self.type(), **{"id": self.id, "height": self.height(), "width": self.width()}) node.setPos(self.pos()) node.setText(self.text()) node.updateNode() 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 """ return set(self.incomingNodes(filter_on_edges=lambda x: x.type() is Item.InputEdge)) @staticmethod def createPolygon(w, h): """ Returns the initialized polygon according to the given width/height. :type w: int :type h: int :rtype: QtGui.QPolygonF """ return QtGui.QPolygonF( [ QtCore.QPointF(-w / 2 + 10, -h / 2), QtCore.QPointF(+w / 2, -h / 2), QtCore.QPointF(+w / 2 - 10, +h / 2), QtCore.QPointF(-w / 2, +h / 2), QtCore.QPointF(-w / 2 + 10, -h / 2), ] ) @staticmethod def createPolygonA(w, h): """ Returns the initialized top-half polygon according to the given width/height. :type w: int :type h: int :rtype: QtGui.QPolygonF """ return QtGui.QPolygonF( [ QtCore.QPointF(-w / 2 + 10, -h / 2), QtCore.QPointF(+w / 2, -h / 2), QtCore.QPointF(+w / 2 - 10 / 2, 0), QtCore.QPointF(-w / 2 + 10 / 2, 0), QtCore.QPointF(-w / 2 + 10, -h / 2), ] ) @staticmethod def createPolygonB(w, h): """ Returns the initialized bottom-half polygon according to the given width/height. :type w: int :type h: int :rtype: QtGui.QPolygonF """ return QtGui.QPolygonF( [ QtCore.QPointF(-w / 2 + 10 / 2, 0), QtCore.QPointF(+w / 2 - 10 / 2, 0), QtCore.QPointF(+w / 2 - 10, +h / 2), QtCore.QPointF(-w / 2, +h / 2), QtCore.QPointF(-w / 2 + 10 / 2, 0), ] ) def geometryA(self): """ Returns the geometry of the shape A of this node. :rtype: QtGui.QPolygonF """ return self.polygonA.geometry() def geometryB(self): """ Returns the geometry of the shape B of this node. :rtype: QtGui.QPolygonF """ return self.polygonB.geometry() def height(self): """ Returns the height of the shape. :rtype: int """ polygonA = self.polygonA.geometry() polygonB = self.polygonB.geometry() return polygonA[self.IndexBL].y() - polygonB[self.IndexTL].y() def identity(self): """ Returns the identity of the current node. :rtype: Identity """ return Identity.Facet 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()) # SHAPE painter.setPen(self.polygonA.pen()) painter.setBrush(self.polygonA.brush()) painter.drawPolygon(self.polygonA.geometry()) painter.setPen(self.polygonB.pen()) painter.setBrush(self.polygonB.brush()) painter.drawPolygon(self.polygonB.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 penA(self): """ Returns the pen used to paint the shape A of this node. :rtype: QtGui.QPen """ return self.polygonA.pen() def penB(self): """ Returns the pen used to paint the shape B of this node. :rtype: QtGui.QPen """ return self.polygonB.pen() 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 """ match = RE_FACET.match(text) if match: self.labelA.setText((Facet.forValue(match.group("facet")) or Facet.length).value) self.labelB.setText('"{0}"'.format(match.group("value"))) self.updateNode() else: # USE THE OLD VALUE-RESTRICTION PATTERN match = RE_VALUE_RESTRICTION.match(text) if match: self.labelA.setText((Facet.forValue(match.group("facet")) or Facet.length).value) self.labelB.setText('"{0}"'.format(match.group("value"))) self.updateNode() def setTextPos(self, pos): """ Set the label position. :type pos: QPointF """ pass 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()) return path def text(self): """ Returns the label text. :rtype: str """ return self.compose(self.facet, self.value) def textPos(self): """ Returns the current label position in item coordinates. :rtype: QPointF """ return self.boundingRect().center() def updateNode(self, *args, **kwargs): """ Update the current node. """ # POLYGONS + BACKGROUND + SELECTION (GEOMETRY) width = max(self.labelA.width() + 16, self.labelB.width() + 16, 80) self.background.setGeometry(self.createPolygon(width + 8, 48)) self.selection.setGeometry(self.createPolygon(width + 8, 48)) self.polygon.setGeometry(self.createPolygon(width, 40)) self.polygonA.setGeometry(self.createPolygonA(width, 40)) self.polygonB.setGeometry(self.createPolygonB(width, 40)) self.updateTextPos() self.updateEdges() # SELECTION + BACKGROUND + CACHE REFRESH super().updateNode(**kwargs) def updateTextPos(self, *args, **kwargs): """ Update the label position. """ self.labelA.updatePos() self.labelB.updatePos() def width(self): """ Returns the width of the shape. :rtype: int """ polygonA = self.polygonA.geometry() polygonB = self.polygonB.geometry() return polygonA[self.IndexTR].x() - polygonB[self.IndexBL].x()
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)
class IndividualNode(OntologyEntityResizableNode): """ 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} Type = Item.IndividualIRINode def __init__(self, iri=None, width=60, height=60, brush=None, **kwargs): """ Initialize the node. :type iri: IRI :type width: int :type height: int :type brush: QBrush """ super().__init__(iri=iri, **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.updateNode() ############################################# # INTERFACE ################################# def initialLabelPosition(self): return self.center() 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(), 'iri': None, }) node.setPos(self.pos()) node.iri = self.iri 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.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. :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)
class ValueDomainNode(AbstractNode): """ This class implements the 'Value-Domain' 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.ValueDomain} Type = Item.ValueDomainNode def __init__(self, width=90, height=40, brush=None, **kwargs): """ Initialize the ValueDomain node. :type width: int :type height: int :type brush: QBrush """ super().__init__(**kwargs) brush = brush or ValueDomainNode.DefaultBrush pen = ValueDomainNode.DefaultPen self.background = Polygon(QtCore.QRectF(-49, -24, 98, 48)) self.selection = Polygon(QtCore.QRectF(-49, -24, 98, 48)) self.polygon = Polygon(QtCore.QRectF(-45, -20, 90, 40), brush, pen) self.label = NodeLabel(Datatype.string.value, pos=self.center, editable=False, movable=False, parent=self) self.updateNode() self.updateTextPos() ############################################# # PROPERTIES ################################# @property def datatype(self): """ Returns the datatype associated with this node. :rtype: Datatype """ return Datatype.valueOf(self.text()) ############################################# # 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.ValueDomain 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.drawRoundedRect(self.selection.geometry(), 8, 8) # SYNTAX VALIDATION painter.setRenderHint(QtGui.QPainter.Antialiasing) painter.setPen(self.background.pen()) painter.setBrush(self.background.brush()) painter.drawRoundedRect(self.background.geometry(), 8, 8) # SHAPE painter.setPen(self.polygon.pen()) painter.setBrush(self.polygon.brush()) painter.drawRoundedRect(self.polygon.geometry(), 8, 8) def painterPath(self): """ Returns the current shape as QtGui.QPainterPath (used for collision detection). :rtype: QPainterPath """ path = QtGui.QPainterPath() path.addRoundedRect(self.polygon.geometry(), 8, 8) return path 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 """ datatype = Datatype.valueOf(text) or Datatype.string self.label.setText(datatype.value) self.updateNode() 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.addRoundedRect(self.polygon.geometry(), 8, 8) 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 updateNode(self, *args, **kwargs): """ Update the current node. """ # POLYGON + BACKGROUND + SELECTION (GEOMETRY) width = max(self.label.width() + 16, 90) self.polygon.setGeometry(QtCore.QRectF(-width / 2, -20, width, 40)) self.background.setGeometry( QtCore.QRectF(-(width + 8) / 2, -24, width + 8, 48)) self.selection.setGeometry( QtCore.QRectF(-(width + 8) / 2, -24, width + 8, 48)) self.updateTextPos() self.updateEdges() # SELECTION + BACKGROUND + CACHE REFRESH super().updateNode(**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)
class FacetNode(AbstractNode): """ This class implements the 'Facet' node. """ IndexTL = 0 IndexTR = 1 IndexBR = 2 IndexBL = 3 IndexEE = 4 DefaultBrushA = QtGui.QBrush(QtGui.QColor(222, 222, 222, 255)) DefaultBrushB = QtGui.QBrush(QtGui.QColor(252, 252, 252, 255)) DefaultPenA = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.0, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin) DefaultPenB = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.0, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin) Identities = {Identity.Facet} Type = Item.FacetIRINode def __init__(self, facet=None, width=80, height=40, brush=None, **kwargs): """ Initialize the node. :type width: int :type height: int :type brush: QBrush :type facet: Facet """ super().__init__(**kwargs) self.background = Polygon(self.createPolygon(88, 48)) self.selection = Polygon(self.createPolygon(88, 48)) self.polygon = Polygon(self.createPolygon(80, 40)) self.polygonA = Polygon(self.createPolygonA(80, 40), FacetNode.DefaultBrushA, FacetNode.DefaultPenA) self.polygonB = Polygon(self.createPolygonA(80, 40), FacetNode.DefaultBrushB, FacetNode.DefaultPenB) self._facet = facet self.labelA = NodeLabel('Empty', pos=self.centerA, editable=False, movable=False, parent=self) self.labelB = FacetQuotedLabel(template='"Empty"', movable=False, pos=self.centerB, parent=self) self.updateNode() self.updateTextPos() ############################################# # PROPERTIES ################################# @property def datatype(self): """ Returns the datatype this facet is restricting, or None if the node is isolated. :rtype: Datatype """ f1 = lambda x: x.type() is Item.InputEdge f2 = lambda x: x.type() is Item.DatatypeRestrictionNode f3 = lambda x: x.type() is Item.ValueDomainNode outgoing = first( self.outgoingNodes(filter_on_edges=f1, filter_on_nodes=f2)) if outgoing: incoming = first( outgoing.incomingNodes(filter_on_edges=f1, filter_on_nodes=f3)) if incoming: return incoming.datatype return None @property def facet(self): ''' :rtype: Facet ''' return self._facet @facet.setter def facet(self, facet): ''' :type facet:Facet ''' self._facet = facet if self.diagram: self.doUpdateNodeLabel() self.sgnNodeModified.emit() ############################################# # SLOTS ################################# @QtCore.pyqtSlot() def doUpdateNodeLabel(self): iri = self.facet.constrainingFacet prefixed = iri.manager.getShortestPrefixedForm(iri) if prefixed: self.labelA.setText(str(prefixed)) else: self.labelA.setText('<{}>', str(iri)) literal = self.facet.literal self.labelB.setText(str(literal)) #self.updateNode() ############################################# # INTERFACE ################################# def mouseDoubleClickEvent(self, mouseEvent): """ Executed when the mouse is double clicked on the text item. :type mouseEvent: QGraphicsSceneMouseEvent """ print() self.session.doOpenConstrainingFacetBuilder(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() def brushA(self): """ Returns the brush used to paint the shape A of this node. :rtype: QtGui.QBrush """ return self.polygonA.brush() def brushB(self): """ Returns the brush used to paint the shape B of this node. :rtype: QtGui.QBrush """ return self.polygonB.brush() def centerA(self): """ Returns the center point of polygon A. :rtype: QPointF """ return self.boundingRect().center() - QtCore.QPointF(0, 40 / 4) def centerB(self): """ Returns the center point of polygon A. :rtype: QPointF """ return self.boundingRect().center() + QtCore.QPointF(0, 40 / 4) @staticmethod def compose(facet, value): """ Compose the restriction string. :type facet: Facet :type value: str :return: str """ return '{0}^^"{1}"'.format(facet.value, value.strip().strip('"')) def copy(self, diagram): """ Create a copy of the current item. :type diagram: Diagram """ node = diagram.factory.create( self.type(), **{ 'id': self.id, 'height': self.height(), 'width': self.width(), 'facet': self.facet }) node.setPos(self.pos()) node.setText(self.text()) node.updateNode() 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 """ return set( self.incomingNodes( filter_on_edges=lambda x: x.type() is Item.InputEdge)) @staticmethod def createPolygon(w, h): """ Returns the initialized polygon according to the given width/height. :type w: int :type h: int :rtype: QtGui.QPolygonF """ return QtGui.QPolygonF([ QtCore.QPointF(-w / 2 + 10, -h / 2), QtCore.QPointF(+w / 2, -h / 2), QtCore.QPointF(+w / 2 - 10, +h / 2), QtCore.QPointF(-w / 2, +h / 2), QtCore.QPointF(-w / 2 + 10, -h / 2), ]) @staticmethod def createPolygonA(w, h): """ Returns the initialized top-half polygon according to the given width/height. :type w: int :type h: int :rtype: QtGui.QPolygonF """ return QtGui.QPolygonF([ QtCore.QPointF(-w / 2 + 10, -h / 2), QtCore.QPointF(+w / 2, -h / 2), QtCore.QPointF(+w / 2 - 10 / 2, 0), QtCore.QPointF(-w / 2 + 10 / 2, 0), QtCore.QPointF(-w / 2 + 10, -h / 2), ]) @staticmethod def createPolygonB(w, h): """ Returns the initialized bottom-half polygon according to the given width/height. :type w: int :type h: int :rtype: QtGui.QPolygonF """ return QtGui.QPolygonF([ QtCore.QPointF(-w / 2 + 10 / 2, 0), QtCore.QPointF(+w / 2 - 10 / 2, 0), QtCore.QPointF(+w / 2 - 10, +h / 2), QtCore.QPointF(-w / 2, +h / 2), QtCore.QPointF(-w / 2 + 10 / 2, 0), ]) def geometryA(self): """ Returns the geometry of the shape A of this node. :rtype: QtGui.QPolygonF """ return self.polygonA.geometry() def geometryB(self): """ Returns the geometry of the shape B of this node. :rtype: QtGui.QPolygonF """ return self.polygonB.geometry() def height(self): """ Returns the height of the shape. :rtype: int """ polygonA = self.polygonA.geometry() polygonB = self.polygonB.geometry() return polygonA[self.IndexBL].y() - polygonB[self.IndexTL].y() def identity(self): """ Returns the identity of the current node. :rtype: Identity """ return Identity.Facet 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()) # SHAPE painter.setPen(self.polygonA.pen()) painter.setBrush(self.polygonA.brush()) painter.drawPolygon(self.polygonA.geometry()) painter.setPen(self.polygonB.pen()) painter.setBrush(self.polygonB.brush()) painter.drawPolygon(self.polygonB.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 penA(self): """ Returns the pen used to paint the shape A of this node. :rtype: QtGui.QPen """ return self.polygonA.pen() def penB(self): """ Returns the pen used to paint the shape B of this node. :rtype: QtGui.QPen """ return self.polygonB.pen() 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 """ pass def setTextPos(self, pos): """ Set the label position. :type pos: QPointF """ pass 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()) return path def text(self): """ Returns the label text. :rtype: str """ if self.facet: return str(self.facet) return 'Facet' def textPos(self): """ Returns the current label position in item coordinates. :rtype: QPointF """ return self.boundingRect().center() def updateNode(self, *args, **kwargs): """ Update the current node. """ # POLYGONS + BACKGROUND + SELECTION (GEOMETRY) width = max(self.labelA.width() + 16, self.labelB.width() + 16, 80) self.background.setGeometry(self.createPolygon(width + 8, 48)) self.selection.setGeometry(self.createPolygon(width + 8, 48)) self.polygon.setGeometry(self.createPolygon(width, 40)) self.polygonA.setGeometry(self.createPolygonA(width, 40)) self.polygonB.setGeometry(self.createPolygonB(width, 40)) self.updateTextPos() self.updateEdges() # SELECTION + BACKGROUND + CACHE REFRESH super().updateNode(**kwargs) def updateTextPos(self, *args, **kwargs): """ Update the label position. """ self.labelA.updatePos() self.labelB.updatePos() def width(self): """ Returns the width of the shape. :rtype: int """ polygonA = self.polygonA.geometry() polygonB = self.polygonB.geometry() return polygonA[self.IndexTR].x() - polygonB[self.IndexBL].x()
class AttributeNode(OntologyEntityNode): """ 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, Identity.Individual} Type = Item.AttributeIRINode def __init__(self, iri=None, width=20, height=20, brush=None, **kwargs): """ Initialize the node. :type width: int :type height: int :type brush: QBrush """ super().__init__(iri=iri, **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) def connectIRIMetaSignals(self): connect(self.iri.sgnFunctionalModified, self.onFunctionalModified) def disconnectIRIMetaSignals(self): disconnect(self.iri.sgnFunctionalModified, self.onFunctionalModified) @QtCore.pyqtSlot() def onFunctionalModified(self): self.updateNode() ############################################# # INTERFACE ################################# def initialLabelPosition(self): return self.center() - QtCore.QPointF(0, 22) def occursAsIndividual(self): #Class Assertion for instEdge in [ x for x in self.edges if x.type() is Item.MembershipEdge ]: if instEdge.source is self: return True #Object[Data] Property Assertion for inputEdge in [x for x in self.edges if x.type() is Item.InputEdge]: if inputEdge.source is self and inputEdge.target.type( ) is Item.PropertyAssertionNode: return True #SameAs and Different for inputEdge in [ x for x in self.edges if (x.type() is Item.SameEdge or x.type() is Item.DifferentEdge ) ]: if inputEdge.source is self or inputEdge.target is self: return True return False 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(), 'iri': None, }) node.setPos(self.pos()) node.iri = self.iri 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 """ return self.iri.functional 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 """ self.iri.functional = functional 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 """ # TODO implementa nuova versione passando da metodo IRI.isTopBottomEntity (isOWlThing? etc etc...) 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: if self.iri: functional = self.isFunctional() # TODO CANCELLA if functional is None: functional = False # TODO END CANCELLA # 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)
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)
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)
class EquivalenceEdge(AbstractEdge): """ This class implements the 'Equivalence' edge. """ Type = Item.EquivalenceEdge def __init__(self, **kwargs): """ Initialize the edge. """ super().__init__(**kwargs) self.tail = Polygon(QtGui.QPolygonF()) ############################################# # INTERFACE ################################# def boundingRect(self): """ Returns the shape bounding rect. :rtype: QRectF """ path = QtGui.QPainterPath() path.addPath(self.selection.geometry()) path.addPolygon(self.head.geometry()) path.addPolygon(self.tail.geometry()) for polygon in self.handles: path.addEllipse(polygon.geometry()) for polygon in self.anchors.values(): path.addEllipse(polygon.geometry()) return path.controlPointRect() def copy(self, diagram): """ Create a copy of the current item. :type diagram: Diagram """ return diagram.factory.create(self.type(), **{ 'id': self.id, 'source': self.source, 'target': self.target, 'breakpoints': self.breakpoints[:], }) @staticmethod def createHead(p1, angle, size): """ Create the head polygon. :type p1: QPointF :type angle: float :type size: int :rtype: QPolygonF """ rad = radians(angle) p2 = p1 - QtCore.QPointF(sin(rad + M_PI / 3.0) * size, cos(rad + M_PI / 3.0) * size) p3 = p1 - QtCore.QPointF(sin(rad + M_PI - M_PI / 3.0) * size, cos(rad + M_PI - M_PI / 3.0) * size) return QtGui.QPolygonF([p1, p2, p3]) @staticmethod def createTail(p1, angle, size): """ Create the tail polygon. :type p1: QPointF :type angle: float :type size: int :rtype: QPolygonF """ rad = radians(angle) p2 = p1 + QtCore.QPointF(sin(rad + M_PI / 3.0) * size, cos(rad + M_PI / 3.0) * size) p3 = p1 + QtCore.QPointF(sin(rad + M_PI - M_PI / 3.0) * size, cos(rad + M_PI - M_PI / 3.0) * size) return QtGui.QPolygonF([p1, p2, p3]) def paint(self, painter, option, widget=None): """ Paint the edge in the diagram scene. :type painter: QPainter :type option: QStyleOptionGraphicsItem :type widget: QWidget """ # SET THE RECT THAT NEEDS TO BE REPAINTED painter.setClipRect(option.exposedRect) # SELECTION AREA painter.setRenderHint(QtGui.QPainter.Antialiasing) painter.fillPath(self.selection.geometry(), self.selection.brush()) # EDGE LINE painter.setPen(self.path.pen()) painter.drawPath(self.path.geometry()) # HEAD POLYGON painter.setPen(self.head.pen()) painter.setBrush(self.head.brush()) painter.drawPolygon(self.head.geometry()) # TAIL POLYGON painter.setPen(self.tail.pen()) painter.setBrush(self.tail.brush()) painter.drawPolygon(self.tail.geometry()) # BREAKPOINTS for polygon in self.handles: painter.setPen(polygon.pen()) painter.setBrush(polygon.brush()) painter.drawEllipse(polygon.geometry()) # ANCHOR POINTS for polygon in self.anchors.values(): 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.addPath(self.path.geometry()) path.addPolygon(self.head.geometry()) path.addPolygon(self.tail.geometry()) return path def setText(self, text): """ Set the label text. :type text: str """ pass def setTextPos(self, pos): """ Set the label position. :type pos: QPointF """ pass def shape(self): """ Returns the shape of this item as a QPainterPath in local coordinates. :rtype: QPainterPath """ path = QtGui.QPainterPath() path.addPath(self.selection.geometry()) path.addPolygon(self.head.geometry()) path.addPolygon(self.tail.geometry()) if self.isSelected(): for polygon in self.handles: path.addEllipse(polygon.geometry()) for polygon in self.anchors.values(): path.addEllipse(polygon.geometry()) return path def text(self): """ Returns the label text. :rtype: str """ pass def textPos(self): """ Returns the current label position. :rtype: QPointF """ pass def updateEdge(self, selected=None, visible=None, breakpoint=None, anchor=None, target=None, **kwargs): """ Update the current edge. :type selected: bool :type visible: bool :type breakpoint: int :type anchor: AbstractNode :type target: QtCore.QPointF """ if visible is None: visible = self.canDraw() sourceNode = self.source targetNode = self.target sourcePos = sourceNode.anchor(self) targetPos = target if targetPos is None: targetPos = targetNode.anchor(self) self.prepareGeometryChange() ########################################## # PATH, SELECTION, HEAD, TAIL (GEOMETRY) ################################# collection = self.createPath(sourceNode, targetNode, [sourcePos] + self.breakpoints + [targetPos]) selection = QtGui.QPainterPath() path = QtGui.QPainterPath() head = QtGui.QPolygonF() tail = QtGui.QPolygonF() if len(collection) == 1: subpath = collection[0] p1 = sourceNode.intersection(subpath) p2 = targetNode.intersection(subpath) if targetNode else subpath.p2() if p1 is not None and p2 is not None: path.moveTo(p1) path.lineTo(p2) selection.addPolygon(createArea(p1, p2, subpath.angle(), 8)) head = self.createHead(p2, subpath.angle(), 12) tail = self.createTail(p1, subpath.angle(), 12) elif len(collection) > 1: subpath1 = collection[0] subpathN = collection[-1] p11 = sourceNode.intersection(subpath1) p22 = targetNode.intersection(subpathN) if p11 and p22: p12 = subpath1.p2() p21 = subpathN.p1() path.moveTo(p11) path.lineTo(p12) selection.addPolygon(createArea(p11, p12, subpath1.angle(), 8)) for subpath in collection[1:-1]: p1 = subpath.p1() p2 = subpath.p2() path.moveTo(p1) path.lineTo(p2) selection.addPolygon(createArea(p1, p2, subpath.angle(), 8)) path.moveTo(p21) path.lineTo(p22) selection.addPolygon(createArea(p21, p22, subpathN.angle(), 8)) head = self.createHead(p22, subpathN.angle(), 12) tail = self.createTail(p11, subpath1.angle(), 12) self.selection.setGeometry(selection) self.path.setGeometry(path) self.head.setGeometry(head) self.tail.setGeometry(tail) ########################################## # PATH, HEAD, TAIL (BRUSH) ################################# headBrush = QtGui.QBrush(QtCore.Qt.NoBrush) headPen = QtGui.QPen(QtCore.Qt.NoPen) pathPen = QtGui.QPen(QtCore.Qt.NoPen) tailBrush = QtGui.QBrush(QtCore.Qt.NoBrush) tailPen = QtGui.QPen(QtCore.Qt.NoPen) if visible: headBrush = QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)) headPen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.1, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin) pathPen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.1, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin) tailBrush = QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)) tailPen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.1, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin) self.head.setBrush(headBrush) self.head.setPen(headPen) self.path.setPen(pathPen) self.tail.setBrush(tailBrush) self.tail.setPen(tailPen) super().updateEdge(selected, visible, breakpoint, anchor, **kwargs)
class RoleNode(OntologyEntityResizableNode): """ 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,Identity.Individual} Type = Item.RoleIRINode def __init__(self, iri = None, width=70, height=50, brush=None, **kwargs): """ Initialize the node. :type width: int :type height: int :type brush: QBrush """ super().__init__(iri=iri,**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.updateNode() def connectIRIMetaSignals(self): connect(self.iri.sgnFunctionalModified,self.onFunctionalModified) connect(self.iri.sgnInverseFunctionalModified, self.onFunctionalModified) def disconnectIRIMetaSignals(self): disconnect(self.iri.sgnFunctionalModified,self.onFunctionalModified) disconnect(self.iri.sgnInverseFunctionalModified, self.onFunctionalModified) @QtCore.pyqtSlot() def onFunctionalModified(self): self.updateNode() ############################################# # INTERFACE ################################# def initialLabelPosition(self): return self.center() - QtCore.QPointF(0, 30) def occursAsIndividual(self): #Class Assertion for instEdge in [x for x in self.edges if x.type() is Item.MembershipEdge]: if instEdge.source is self: return True #Object[Data] Property Assertion for inputEdge in [x for x in self.edges if x.type() is Item.InputEdge]: if inputEdge.source is self and inputEdge.target.type() is Item.PropertyAssertionNode: return True #SameAs and Different for inputEdge in [x for x in self.edges if (x.type() is Item.SameEdge or x.type() is Item.DifferentEdge)]: if inputEdge.source is self or inputEdge.target is self: return True return False 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(), 'iri': None, }) node.setPos(self.pos()) node.iri = self.iri 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 """ return self.iri.asymmetric def isFunctional(self): """ Returns True if the predicate represented by this node is functional, else False. :rtype: bool """ return self.iri.functional def isInverseFunctional(self): """ Returns True if the predicate represented by this node is inverse functional, else False. :rtype: bool """ return self.iri.inverseFunctional def isIrreflexive(self): """ Returns True if the predicate represented by this node is irreflexive, False otherwise. :rtype: bool """ return self.iri.irreflexive def isReflexive(self): """ Returns True if the predicate represented by this node is reflexive, False otherwise. :rtype: bool """ return self.iri.reflexive def isSymmetric(self): """ Returns True if the predicate represented by this node is symmetric, False otherwise. :rtype: bool """ return self.iri.symmetric def isTransitive(self): """ Returns True if the transitive represented by this node is symmetric, False otherwise. :rtype: bool """ return self.iri.transitive 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 """ self.iri.asymmetric = asymmetric def setFunctional(self, functional): """ Set the functional property of the predicate represented by this node. :type functional: bool """ self.iri.functional = functional 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 """ self.iri.inverseFunctional = inverseFunctional def setIrreflexive(self, irreflexive): """ Set the irreflexive property for the predicate represented by this node. :type irreflexive: bool """ self.iri.irreflexive = irreflexive def setReflexive(self, reflexive): """ Set the reflexive property for the predicate represented by this node. :type reflexive: bool """ self.iri.reflexive = reflexive def setSymmetric(self, symmetric): """ Set the symmetric property for the predicate represented by this node. :type symmetric: bool """ self.iri.symmetric = symmetric def setTransitive(self, transitive): """ Set the transitive property for the predicate represented by this node. :type transitive: bool """ self.iri.transitive = transitive 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 """ # TODO implementa nuova versione passando da metodo IRI.isTopBottomEntity (isOWlThing? etc etc...) 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: if self.iri: functional = self.isFunctional() #TODO CANCELLA if functional is None: functional = False # TODO END CANCELLA if inverseFunctional is None: if self.iri: inverseFunctional = self.isInverseFunctional() # TODO CANCELLA if inverseFunctional is None: inverseFunctional = False # TODO END CANCELLA 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)# -*- coding: utf-8 -*-
class ValueDomainNode(AbstractNode): """ This class implements the 'Value-Domain' 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.ValueDomain} Type = Item.ValueDomainNode def __init__(self, width=90, height=40, brush=None, **kwargs): """ Initialize the ValueDomain node. :type width: int :type height: int :type brush: QBrush """ super().__init__(**kwargs) brush = brush or ValueDomainNode.DefaultBrush pen = ValueDomainNode.DefaultPen self.background = Polygon(QtCore.QRectF(-49, -24, 98, 48)) self.selection = Polygon(QtCore.QRectF(-49, -24, 98, 48)) self.polygon = Polygon(QtCore.QRectF(-45, -20, 90, 40), brush, pen) self.label = NodeLabel(Datatype.string.value, pos=self.center, editable=False, movable=False, parent=self) self.updateNode() self.updateTextPos() ############################################# # PROPERTIES ################################# @property def datatype(self): """ Returns the datatype associated with this node. :rtype: Datatype """ return Datatype.forValue(self.text()) ############################################# # 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.ValueDomain 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.drawRoundedRect(self.selection.geometry(), 8, 8) # SYNTAX VALIDATION painter.setRenderHint(QtGui.QPainter.Antialiasing) painter.setPen(self.background.pen()) painter.setBrush(self.background.brush()) painter.drawRoundedRect(self.background.geometry(), 8, 8) # SHAPE painter.setPen(self.polygon.pen()) painter.setBrush(self.polygon.brush()) painter.drawRoundedRect(self.polygon.geometry(), 8, 8) def painterPath(self): """ Returns the current shape as QtGui.QPainterPath (used for collision detection). :rtype: QPainterPath """ path = QtGui.QPainterPath() path.addRoundedRect(self.polygon.geometry(), 8, 8) return path 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 """ datatype = Datatype.forValue(text) or Datatype.string self.label.setText(datatype.value) self.updateNode() 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.addRoundedRect(self.polygon.geometry(), 8, 8) 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 updateNode(self, *args, **kwargs): """ Update the current node. """ # POLYGON + BACKGROUND + SELECTION (GEOMETRY) width = max(self.label.width() + 16, 90) self.polygon.setGeometry(QtCore.QRectF(-width / 2, -20, width, 40)) self.background.setGeometry(QtCore.QRectF(-(width + 8) / 2, -24, width + 8, 48)) self.selection.setGeometry(QtCore.QRectF(-(width + 8) / 2, -24, width + 8, 48)) self.updateTextPos() self.updateEdges() # SELECTION + BACKGROUND + CACHE REFRESH super().updateNode(**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)
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)
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)
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)
class EquivalenceEdge(AxiomEdge): """ This class implements the 'Equivalence' edge. """ Type = Item.EquivalenceEdge def __init__(self, **kwargs): """ Initialize the edge. """ super().__init__(**kwargs) self.tail = Polygon(QtGui.QPolygonF()) ############################################# # INTERFACE ################################# def boundingRect(self): """ Returns the shape bounding rect. :rtype: QRectF """ path = QtGui.QPainterPath() path.addPath(self.selection.geometry()) path.addPolygon(self.head.geometry()) path.addPolygon(self.tail.geometry()) for polygon in self.handles: path.addEllipse(polygon.geometry()) for polygon in self.anchors.values(): path.addEllipse(polygon.geometry()) return path.controlPointRect() def copy(self, diagram): """ Create a copy of the current item. :type diagram: Diagram """ return diagram.factory.create( self.type(), **{ 'id': self.id, 'source': self.source, 'target': self.target, 'breakpoints': self.breakpoints[:], }) @staticmethod def createHead(p1, angle, size): """ Create the head polygon. :type p1: QPointF :type angle: float :type size: int :rtype: QPolygonF """ rad = radians(angle) p2 = p1 - QtCore.QPointF( sin(rad + M_PI / 3.0) * size, cos(rad + M_PI / 3.0) * size) p3 = p1 - QtCore.QPointF( sin(rad + M_PI - M_PI / 3.0) * size, cos(rad + M_PI - M_PI / 3.0) * size) return QtGui.QPolygonF([p1, p2, p3]) @staticmethod def createTail(p1, angle, size): """ Create the tail polygon. :type p1: QPointF :type angle: float :type size: int :rtype: QPolygonF """ rad = radians(angle) p2 = p1 + QtCore.QPointF( sin(rad + M_PI / 3.0) * size, cos(rad + M_PI / 3.0) * size) p3 = p1 + QtCore.QPointF( sin(rad + M_PI - M_PI / 3.0) * size, cos(rad + M_PI - M_PI / 3.0) * size) return QtGui.QPolygonF([p1, p2, p3]) def paint(self, painter, option, widget=None): """ Paint the edge in the diagram scene. :type painter: QPainter :type option: QStyleOptionGraphicsItem :type widget: QWidget """ # SET THE RECT THAT NEEDS TO BE REPAINTED painter.setClipRect(option.exposedRect) # SELECTION AREA painter.setRenderHint(QtGui.QPainter.Antialiasing) painter.fillPath(self.selection.geometry(), self.selection.brush()) # EDGE LINE painter.setPen(self.path.pen()) painter.drawPath(self.path.geometry()) # HEAD POLYGON painter.setPen(self.head.pen()) painter.setBrush(self.head.brush()) painter.drawPolygon(self.head.geometry()) # TAIL POLYGON painter.setPen(self.tail.pen()) painter.setBrush(self.tail.brush()) painter.drawPolygon(self.tail.geometry()) # BREAKPOINTS for polygon in self.handles: painter.setPen(polygon.pen()) painter.setBrush(polygon.brush()) painter.drawEllipse(polygon.geometry()) # ANCHOR POINTS for polygon in self.anchors.values(): 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.addPath(self.path.geometry()) path.addPolygon(self.head.geometry()) path.addPolygon(self.tail.geometry()) return path def setText(self, text): """ Set the label text. :type text: str """ pass def setTextPos(self, pos): """ Set the label position. :type pos: QPointF """ pass def shape(self): """ Returns the shape of this item as a QPainterPath in local coordinates. :rtype: QPainterPath """ path = QtGui.QPainterPath() path.addPath(self.selection.geometry()) path.addPolygon(self.head.geometry()) path.addPolygon(self.tail.geometry()) if self.isSelected(): for polygon in self.handles: path.addEllipse(polygon.geometry()) for polygon in self.anchors.values(): path.addEllipse(polygon.geometry()) return path def text(self): """ Returns the label text. :rtype: str """ pass def textPos(self): """ Returns the current label position. :rtype: QPointF """ pass def updateEdge(self, selected=None, visible=None, breakpoint=None, anchor=None, target=None, **kwargs): """ Update the current edge. :type selected: bool :type visible: bool :type breakpoint: int :type anchor: AbstractNode :type target: QtCore.QPointF """ if visible is None: visible = self.canDraw() sourceNode = self.source targetNode = self.target sourcePos = sourceNode.anchor(self) targetPos = target if targetPos is None: targetPos = targetNode.anchor(self) self.prepareGeometryChange() ########################################## # PATH, SELECTION, HEAD, TAIL (GEOMETRY) ################################# collection = self.createPath(sourceNode, targetNode, [sourcePos] + self.breakpoints + [targetPos]) selection = QtGui.QPainterPath() path = QtGui.QPainterPath() head = QtGui.QPolygonF() tail = QtGui.QPolygonF() if len(collection) == 1: subpath = collection[0] p1 = sourceNode.intersection(subpath) p2 = targetNode.intersection( subpath) if targetNode else subpath.p2() if p1 is not None and p2 is not None: path.moveTo(p1) path.lineTo(p2) selection.addPolygon(createArea(p1, p2, subpath.angle(), 8)) head = self.createHead(p2, subpath.angle(), 12) tail = self.createTail(p1, subpath.angle(), 12) elif len(collection) > 1: subpath1 = collection[0] subpathN = collection[-1] p11 = sourceNode.intersection(subpath1) p22 = targetNode.intersection(subpathN) if p11 and p22: p12 = subpath1.p2() p21 = subpathN.p1() path.moveTo(p11) path.lineTo(p12) selection.addPolygon(createArea(p11, p12, subpath1.angle(), 8)) for subpath in collection[1:-1]: p1 = subpath.p1() p2 = subpath.p2() path.moveTo(p1) path.lineTo(p2) selection.addPolygon(createArea(p1, p2, subpath.angle(), 8)) path.moveTo(p21) path.lineTo(p22) selection.addPolygon(createArea(p21, p22, subpathN.angle(), 8)) head = self.createHead(p22, subpathN.angle(), 12) tail = self.createTail(p11, subpath1.angle(), 12) self.selection.setGeometry(selection) self.path.setGeometry(path) self.head.setGeometry(head) self.tail.setGeometry(tail) ########################################## # PATH, HEAD, TAIL (BRUSH) ################################# headBrush = QtGui.QBrush(QtCore.Qt.NoBrush) headPen = QtGui.QPen(QtCore.Qt.NoPen) pathPen = QtGui.QPen(QtCore.Qt.NoPen) tailBrush = QtGui.QBrush(QtCore.Qt.NoBrush) tailPen = QtGui.QPen(QtCore.Qt.NoPen) if visible: headBrush = QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)) headPen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.1, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin) pathPen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.1, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin) tailBrush = QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)) tailPen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0, 0, 0, 255)), 1.1, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin) self.head.setBrush(headBrush) self.head.setPen(headPen) self.path.setPen(pathPen) self.tail.setBrush(tailBrush) self.tail.setPen(tailPen) super().updateEdge(selected, visible, breakpoint, anchor, **kwargs)
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)
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)