class NodeBodyItem(GraphicsPathObject): """ The central part (body) of the `NodeItem`. """ def __init__(self, parent=None): GraphicsPathObject.__init__(self, parent) assert (isinstance(parent, NodeItem)) self.__processingState = 0 self.__progress = -1 self.__animationEnabled = False self.__isSelected = False self.__hasFocus = False self.__hover = False self.__shapeRect = QRectF(-10, -10, 20, 20) self.setAcceptHoverEvents(True) self.setFlag(QGraphicsItem.ItemSendsScenePositionChanges, True) self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True) self.setPen(QPen(Qt.NoPen)) self.setPalette(default_palette()) self.shadow = QGraphicsDropShadowEffect( blurRadius=3, color=QColor(SHADOW_COLOR), offset=QPointF(0, 0), ) self.setGraphicsEffect(self.shadow) self.shadow.setEnabled(True) self.__blurAnimation = QPropertyAnimation(self.shadow, "blurRadius", self) self.__blurAnimation.setDuration(100) self.__blurAnimation.finished.connect(self.__on_finished) self.__pingAnimation = QPropertyAnimation(self, "scale", self) self.__pingAnimation.setDuration(250) self.__pingAnimation.setKeyValues([(0.0, 1.0), (0.5, 1.1), (1.0, 1.0)]) # TODO: The body item should allow the setting of arbitrary painter # paths (for instance rounded rect, ...) def setShapeRect(self, rect): """ Set the item's shape `rect`. The item should be confined within this rect. """ path = QPainterPath() path.addEllipse(rect) self.setPath(path) self.__shapeRect = rect def setPalette(self, palette): """ Set the body color palette (:class:`QPalette`). """ self.palette = palette self.__updateBrush() def setAnimationEnabled(self, enabled): """ Set the node animation enabled. """ if self.__animationEnabled != enabled: self.__animationEnabled = enabled def setProcessingState(self, state): """ Set the processing state of the node. """ if self.__processingState != state: self.__processingState = state if not state and self.__animationEnabled: self.ping() def setProgress(self, progress): """ Set the progress indicator state of the node. `progress` should be a number between 0 and 100. """ self.__progress = progress self.update() def ping(self): """ Trigger a 'ping' animation. """ animation_restart(self.__pingAnimation) def hoverEnterEvent(self, event): self.__hover = True self.__updateShadowState() return GraphicsPathObject.hoverEnterEvent(self, event) def hoverLeaveEvent(self, event): self.__hover = False self.__updateShadowState() return GraphicsPathObject.hoverLeaveEvent(self, event) def paint(self, painter, option, widget): """ Paint the shape and a progress meter. """ # Let the default implementation draw the shape if option.state & QStyle.State_Selected: # Prevent the default bounding rect selection indicator. option.state = option.state ^ QStyle.State_Selected GraphicsPathObject.paint(self, painter, option, widget) if self.__progress >= 0: # Draw the progress meter over the shape. # Set the clip to shape so the meter does not overflow the shape. painter.setClipPath(self.shape(), Qt.ReplaceClip) color = self.palette.color(QPalette.ButtonText) pen = QPen(color, 5) painter.save() painter.setPen(pen) painter.setRenderHints(QPainter.Antialiasing) span = max(1, int(self.__progress * 57.60)) painter.drawArc(self.__shapeRect, 90 * 16, -span) painter.restore() def __updateShadowState(self): if self.__hasFocus: color = QColor(FOCUS_OUTLINE_COLOR) self.setPen(QPen(color, 1.5)) else: self.setPen(QPen(Qt.NoPen)) radius = 3 enabled = False if self.__isSelected: enabled = True radius = 7 if self.__hover: radius = 17 enabled = True if enabled and not self.shadow.isEnabled(): self.shadow.setEnabled(enabled) if self.__animationEnabled: if self.__blurAnimation.state() == QPropertyAnimation.Running: self.__blurAnimation.pause() self.__blurAnimation.setStartValue(self.shadow.blurRadius()) self.__blurAnimation.setEndValue(radius) self.__blurAnimation.start() else: self.shadow.setBlurRadius(radius) def __updateBrush(self): palette = self.palette if self.__isSelected: cg = QPalette.Active else: cg = QPalette.Inactive palette.setCurrentColorGroup(cg) c1 = palette.color(QPalette.Light) c2 = palette.color(QPalette.Button) grad = radial_gradient(c2, c1) self.setBrush(QBrush(grad)) # TODO: The selected and focus states should be set using the # QStyle flags (State_Selected. State_HasFocus) def setSelected(self, selected): """ Set the `selected` state. .. note:: The item does not have `QGraphicsItem.ItemIsSelectable` flag. This property is instead controlled by the parent NodeItem. """ self.__isSelected = selected self.__updateBrush() def setHasFocus(self, focus): """ Set the `has focus` state. .. note:: The item does not have `QGraphicsItem.ItemIsFocusable` flag. This property is instead controlled by the parent NodeItem. """ self.__hasFocus = focus self.__updateShadowState() def __on_finished(self): if self.shadow.blurRadius() == 0: self.shadow.setEnabled(False)
class NodeBodyItem(GraphicsPathObject): """ The central part (body) of the `NodeItem`. """ def __init__(self, parent=None): GraphicsPathObject.__init__(self, parent) assert(isinstance(parent, NodeItem)) self.__processingState = 0 self.__progress = -1 self.__animationEnabled = False self.__isSelected = False self.__hasFocus = False self.__hover = False self.__shapeRect = QRectF(-10, -10, 20, 20) self.setAcceptHoverEvents(True) self.setFlag(QGraphicsItem.ItemSendsScenePositionChanges, True) self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True) self.setPen(QPen(Qt.NoPen)) self.setPalette(default_palette()) self.shadow = QGraphicsDropShadowEffect( blurRadius=3, color=QColor(SHADOW_COLOR), offset=QPointF(0, 0), ) self.setGraphicsEffect(self.shadow) self.shadow.setEnabled(True) self.__blurAnimation = QPropertyAnimation(self.shadow, "blurRadius", self) self.__blurAnimation.setDuration(100) self.__blurAnimation.finished.connect(self.__on_finished) self.__pingAnimation = QPropertyAnimation(self, "scale", self) self.__pingAnimation.setDuration(250) self.__pingAnimation.setKeyValues([(0.0, 1.0), (0.5, 1.1), (1.0, 1.0)]) # TODO: The body item should allow the setting of arbitrary painter # paths (for instance rounded rect, ...) def setShapeRect(self, rect): """ Set the item's shape `rect`. The item should be confined within this rect. """ path = QPainterPath() path.addEllipse(rect) self.setPath(path) self.__shapeRect = rect def setPalette(self, palette): """ Set the body color palette (:class:`QPalette`). """ self.palette = palette self.__updateBrush() def setAnimationEnabled(self, enabled): """ Set the node animation enabled. """ if self.__animationEnabled != enabled: self.__animationEnabled = enabled def setProcessingState(self, state): """ Set the processing state of the node. """ if self.__processingState != state: self.__processingState = state if not state and self.__animationEnabled: self.ping() def setProgress(self, progress): """ Set the progress indicator state of the node. `progress` should be a number between 0 and 100. """ self.__progress = progress self.update() def ping(self): """ Trigger a 'ping' animation. """ animation_restart(self.__pingAnimation) def hoverEnterEvent(self, event): self.__hover = True self.__updateShadowState() return GraphicsPathObject.hoverEnterEvent(self, event) def hoverLeaveEvent(self, event): self.__hover = False self.__updateShadowState() return GraphicsPathObject.hoverLeaveEvent(self, event) def paint(self, painter, option, widget): """ Paint the shape and a progress meter. """ # Let the default implementation draw the shape if option.state & QStyle.State_Selected: # Prevent the default bounding rect selection indicator. option.state = option.state ^ QStyle.State_Selected GraphicsPathObject.paint(self, painter, option, widget) if self.__progress >= 0: # Draw the progress meter over the shape. # Set the clip to shape so the meter does not overflow the shape. painter.setClipPath(self.shape(), Qt.ReplaceClip) color = self.palette.color(QPalette.ButtonText) pen = QPen(color, 5) painter.save() painter.setPen(pen) painter.setRenderHints(QPainter.Antialiasing) span = int(self.__progress * 57.60) painter.drawArc(self.__shapeRect, 90 * 16, -span) painter.restore() def __updateShadowState(self): if self.__hasFocus: color = QColor(FOCUS_OUTLINE_COLOR) self.setPen(QPen(color, 1.5)) else: self.setPen(QPen(Qt.NoPen)) radius = 3 enabled = False if self.__isSelected: enabled = True radius = 7 if self.__hover: radius = 17 enabled = True if enabled and not self.shadow.isEnabled(): self.shadow.setEnabled(enabled) if self.__animationEnabled: if self.__blurAnimation.state() == QPropertyAnimation.Running: self.__blurAnimation.pause() self.__blurAnimation.setStartValue(self.shadow.blurRadius()) self.__blurAnimation.setEndValue(radius) self.__blurAnimation.start() else: self.shadow.setBlurRadius(radius) def __updateBrush(self): palette = self.palette if self.__isSelected: cg = QPalette.Active else: cg = QPalette.Inactive palette.setCurrentColorGroup(cg) c1 = palette.color(QPalette.Light) c2 = palette.color(QPalette.Button) grad = radial_gradient(c2, c1) self.setBrush(QBrush(grad)) # TODO: The selected and focus states should be set using the # QStyle flags (State_Selected. State_HasFocus) def setSelected(self, selected): """ Set the `selected` state. .. note:: The item does not have `QGraphicsItem.ItemIsSelectable` flag. This property is instead controlled by the parent NodeItem. """ self.__isSelected = selected self.__updateBrush() def setHasFocus(self, focus): """ Set the `has focus` state. .. note:: The item does not have `QGraphicsItem.ItemIsFocusable` flag. This property is instead controlled by the parent NodeItem. """ self.__hasFocus = focus self.__updateShadowState() def __on_finished(self): if self.shadow.blurRadius() == 0: self.shadow.setEnabled(False)
class LinkCurveItem(QGraphicsPathItem): """ Link curve item. The main component of a :class:`LinkItem`. """ def __init__(self, parent): QGraphicsPathItem.__init__(self, parent) if not isinstance(parent, LinkItem): raise TypeError("'LinkItem' expected") self.setAcceptedMouseButtons(Qt.NoButton) self.__canvasLink = parent self.setAcceptHoverEvents(True) self.shadow = QGraphicsDropShadowEffect( blurRadius=5, color=QColor(SHADOW_COLOR), offset=QPointF(0, 0) ) self.normalPen = QPen(QBrush(QColor("#9CACB4")), 2.0) self.hoverPen = QPen(QBrush(QColor("#7D7D7D")), 2.1) self.setPen(self.normalPen) self.setGraphicsEffect(self.shadow) self.shadow.setEnabled(False) self.__hover = False self.__enabled = True self.__shape = None def linkItem(self): """ Return the :class:`LinkItem` instance this curve belongs to. """ return self.__canvasLink def setHoverState(self, state): self.prepareGeometryChange() self.__shape = None self.__hover = state self.__update() def setLinkEnabled(self, state): self.prepareGeometryChange() self.__shape = None self.__enabled = state self.__update() def isLinkEnabled(self): return self.__enabled def setCurvePenSet(self, pen, hoverPen): self.prepareGeometryChange() if pen is not None: self.normalPen = pen if hoverPen is not None: self.hoverPen = hoverPen self.__shape = None self.__update() def shape(self): if self.__shape is None: path = self.path() pen = QPen(self.pen()) pen.setWidthF(max(pen.widthF(), 7.0)) pen.setStyle(Qt.SolidLine) self.__shape = stroke_path(path, pen) return self.__shape def setPath(self, path): self.__shape = None QGraphicsPathItem.setPath(self, path) def __update(self): shadow_enabled = self.__hover if self.shadow.isEnabled() != shadow_enabled: self.shadow.setEnabled(shadow_enabled) link_enabled = self.__enabled if link_enabled: pen_style = Qt.SolidLine else: pen_style = Qt.DashLine if self.__hover: pen = self.hoverPen else: pen = self.normalPen pen.setStyle(pen_style) self.setPen(pen)
class LinkCurveItem(QGraphicsPathItem): """ Link curve item. The main component of a :class:`LinkItem`. """ def __init__(self, parent): QGraphicsPathItem.__init__(self, parent) if not isinstance(parent, LinkItem): raise TypeError("'LinkItem' expected") self.setAcceptedMouseButtons(Qt.NoButton) self.__canvasLink = parent self.setAcceptHoverEvents(True) self.shadow = QGraphicsDropShadowEffect(blurRadius=5, color=QColor(SHADOW_COLOR), offset=QPointF(0, 0)) self.normalPen = QPen(QBrush(QColor("#9CACB4")), 2.0) self.hoverPen = QPen(QBrush(QColor("#7D7D7D")), 2.1) self.setPen(self.normalPen) self.setGraphicsEffect(self.shadow) self.shadow.setEnabled(False) self.__hover = False self.__enabled = True self.__shape = None def linkItem(self): """ Return the :class:`LinkItem` instance this curve belongs to. """ return self.__canvasLink def setHoverState(self, state): self.prepareGeometryChange() self.__shape = None self.__hover = state self.__update() def setLinkEnabled(self, state): self.prepareGeometryChange() self.__shape = None self.__enabled = state self.__update() def isLinkEnabled(self): return self.__enabled def setCurvePenSet(self, pen, hoverPen): self.prepareGeometryChange() if pen is not None: self.normalPen = pen if hoverPen is not None: self.hoverPen = hoverPen self.__shape = None self.__update() def shape(self): if self.__shape is None: path = self.path() pen = QPen(self.pen()) pen.setWidthF(max(pen.widthF(), 7.0)) pen.setStyle(Qt.SolidLine) self.__shape = stroke_path(path, pen) return self.__shape def setPath(self, path): self.__shape = None QGraphicsPathItem.setPath(self, path) def __update(self): shadow_enabled = self.__hover if self.shadow.isEnabled() != shadow_enabled: self.shadow.setEnabled(shadow_enabled) link_enabled = self.__enabled if link_enabled: pen_style = Qt.SolidLine else: pen_style = Qt.DashLine if self.__hover: pen = self.hoverPen else: pen = self.normalPen pen.setStyle(pen_style) self.setPen(pen)
class LinkCurveItem(QGraphicsPathItem): """ Link curve item. The main component of a :class:`LinkItem`. """ def __init__(self, parent): super().__init__(parent) self.setAcceptedMouseButtons(Qt.NoButton) self.setAcceptHoverEvents(True) self.shadow = QGraphicsDropShadowEffect(blurRadius=10, color=QColor(SHADOW_COLOR), offset=QPointF(0, 0)) self.setGraphicsEffect(self.shadow) self.shadow.setEnabled(False) self.__hover = False self.__enabled = True self.__shape = None self.__curvepath = QPainterPath() self.__curvepath_disabled = None self.__pen = self.pen() self.setPen(QPen(QBrush(QColor("#9CACB4")), 2.0)) def setCurvePath(self, path): if path != self.__curvepath: self.prepareGeometryChange() self.__curvepath = QPainterPath(path) self.__curvepath_disabled = None self.__shape = None self.__update() def curvePath(self): return QPainterPath(self.__curvepath) def setHoverState(self, state): self.prepareGeometryChange() self.__hover = state self.__update() def setLinkEnabled(self, state): self.prepareGeometryChange() self.__enabled = state self.__update() def isLinkEnabled(self): return self.__enabled def setPen(self, pen): if self.__pen != pen: self.prepareGeometryChange() self.__pen = QPen(pen) self.__shape = None super().setPen(self.__pen) def shape(self): if self.__shape is None: path = self.curvePath() pen = QPen(QBrush(Qt.black), max(self.pen().widthF(), 20), Qt.SolidLine) self.__shape = stroke_path(path, pen) return self.__shape def setPath(self, path): self.__shape = None super().setPath(path) def __update(self): shadow_enabled = self.__hover if self.shadow.isEnabled() != shadow_enabled: self.shadow.setEnabled(shadow_enabled) basecurve = self.__curvepath link_enabled = self.__enabled if link_enabled: path = basecurve else: if self.__curvepath_disabled is None: self.__curvepath_disabled = path_link_disabled(basecurve) path = self.__curvepath_disabled self.setPath(path)
class LinkCurveItem(QGraphicsPathItem): """ Link curve item. The main component of a :class:`LinkItem`. """ def __init__(self, parent): QGraphicsPathItem.__init__(self, parent) if not isinstance(parent, LinkItem): raise TypeError("'LinkItem' expected") self.setAcceptedMouseButtons(Qt.NoButton) self.__canvasLink = parent self.setAcceptHoverEvents(True) self.shadow = QGraphicsDropShadowEffect( blurRadius=5, color=QColor(SHADOW_COLOR), offset=QPointF(0, 0) ) self.normalPen = QPen(QBrush(QColor("#9CACB4")), 2.0) self.hoverPen = QPen(QBrush(QColor("#7D7D7D")), 2.1) self.setPen(self.normalPen) self.setGraphicsEffect(self.shadow) self.shadow.setEnabled(False) self.__hover = False def linkItem(self): """ Return the :class:`LinkItem` instance this curve belongs to. """ return self.__canvasLink def setHoverState(self, state): self.__hover = state self.__update() def setCurvePenSet(self, pen, hoverPen): if pen is not None: self.normalPen = pen if hoverPen is not None: self.hoverPen = hoverPen self.__update() def itemChange(self, change, value): if change == QGraphicsItem.ItemEnabledHasChanged: # Update the pen style self.__update() return QGraphicsPathItem.itemChange(self, change, value) def __update(self): shadow_enabled = self.__hover if self.shadow.isEnabled() != shadow_enabled: self.shadow.setEnabled(shadow_enabled) link_enabled = self.isEnabled() if link_enabled: pen_style = Qt.SolidLine else: pen_style = Qt.DashLine if self.__hover: pen = self.hoverPen else: pen = self.normalPen pen.setStyle(pen_style) self.setPen(pen)
class LinkCurveItem(QGraphicsPathItem): """ Link curve item. The main component of a :class:`LinkItem`. """ def __init__(self, parent): super().__init__(parent) self.setAcceptedMouseButtons(Qt.NoButton) self.setAcceptHoverEvents(True) self.shadow = QGraphicsDropShadowEffect( blurRadius=10, color=QColor(SHADOW_COLOR), offset=QPointF(0, 0) ) self.setGraphicsEffect(self.shadow) self.shadow.setEnabled(False) self.__hover = False self.__enabled = True self.__shape = None self.__curvepath = QPainterPath() self.__curvepath_disabled = None self.__pen = self.pen() self.setPen(QPen(QBrush(QColor("#9CACB4")), 2.0)) def setCurvePath(self, path): if path != self.__curvepath: self.prepareGeometryChange() self.__curvepath = QPainterPath(path) self.__curvepath_disabled = None self.__shape = None self.__update() def curvePath(self): return QPainterPath(self.__curvepath) def setHoverState(self, state): self.prepareGeometryChange() self.__hover = state self.__update() def setLinkEnabled(self, state): self.prepareGeometryChange() self.__enabled = state self.__update() def isLinkEnabled(self): return self.__enabled def setPen(self, pen): if self.__pen != pen: self.prepareGeometryChange() self.__pen = QPen(pen) self.__shape = None super().setPen(self.__pen) def shape(self): if self.__shape is None: path = self.curvePath() pen = QPen(QBrush(Qt.black), max(self.pen().widthF(), 20), Qt.SolidLine) self.__shape = stroke_path(path, pen) return self.__shape def setPath(self, path): self.__shape = None super().setPath(path) def __update(self): shadow_enabled = self.__hover if self.shadow.isEnabled() != shadow_enabled: self.shadow.setEnabled(shadow_enabled) basecurve = self.__curvepath link_enabled = self.__enabled if link_enabled: path = basecurve else: if self.__curvepath_disabled is None: self.__curvepath_disabled = path_link_disabled(basecurve) path = self.__curvepath_disabled self.setPath(path)