def __init__(self,
                 action: 'ActionWrapper',
                 parent=None) -> 'ActionGraphics':
        """
		Constructs an Action Wrapper Graphics object for the given action wrapper.

		:param action: The action wrapper for which this graphics item represents.
		:type action: ActionWrapper
		:param parent: None
		:type parent: NoneType
		:return: The graphics of an action.
		:rtype: ActionGraphics
		"""
        ActionGraphics.__init__(self, action, parent)
        self.setAcceptHoverEvents(True)
        self.color = ActionWrapperGraphics.COLOR

        def delete():
            action.getParent().removeAction(action)
            sm.StateMachine.instance.view.ui.apiModelView.refresh()

        self.menu = ActionWrapperMenu()
        self.menu.onDelete(delete)

        # create buttons for moving action in sequence
        self.upButton = MoveButton(MoveButton.Direction.Up, self)
        self.downButton = MoveButton(MoveButton.Direction.Down, self)
        self.upButton.clicked.connect(self.promote)
        self.downButton.clicked.connect(self.demote)
        self.upButton.hide()
        self.downButton.hide()

        self.updateGraphics()
    def __init__(self,
                 actionPipeline: 'ActionPipeline',
                 parent=None) -> 'ActionPipelineGraphics':
        """
		Constructs a Action Graphics object for the given action.

		:param actionPipeline: The action pipeline for which this graphics item represents.
		:type actionPipeline: ActionPipeline
		:param parent: The parent graphics item
		:type parent: QGraphicsItem
		:return: The graphics of the action pipeline.
		:rtype: ActionPipelineGraphics
		"""
        ActionGraphics.__init__(self, actionPipeline, parent)

        self._actionGraphics = []
        self._wireGraphics = []

        self._actionMapping = {}
        self._wireMapping = {}

        # item used to draw lines between ports being connected.
        self.connectionIndicator = ConnectionIndicator(self)
        self.connectionIndicator.hide()
        self.stagingConnection = None

        ActionPipelineGraphics.updateGraphics(self)
    def __init__(self,
                 action: 'Action',
                 parent: QGraphicsItem = None) -> 'ActionGraphics':
        """
		Creates an ActionIconGraphics object.
		
		:param action: The action to create icon graphics for.
		:type action: Action
		:param parent: The parent graphics item.
		:type parent: QGraphicsItem
		"""
        ActionGraphics.__init__(self, action, parent)
        self._interactivePorts = False
    def updateGraphics(self) -> None:
        """
		Updates the graphics and all sub-graphics for the action pipeline.
		
		starts by updating the sub-actions, then sub-wires, then calls teh same method but in the
		ActionGraphics class to update the ports.
		
		:return: None
		:rtype: NoneType
		"""
        self.prepareGeometryChange()
        self.updateActionGraphics()
        ActionGraphics.updateGraphics(self)
        self.updateWireGraphics()
    def paint(self, painter: QPainter, option: QStyleOptionGraphicsItem,
              index: QWidget) -> None:
        """
		Paint the graphics of the action wrapper including action name, number, and ports.

		:param painter: This draws the widget.
		:type painter: QPainter
		:param option: Option for the style of graphic.
		:type option: QStyleOptionGraphicsItem
		:param index: Index for the painted graphic.
		:type index: QWidget
		:return: None
		:rtype: NoneType
		"""
        ActionGraphics.paint(self, painter, option, index)

        # Get dimensions of the action
        x, y, width, height = self.getActionRect(self._action.getInputPorts(),
                                                 self._action.getOutputPorts())

        # Draw the number tag.
        number = str(
            self._action.getParent().getActions().index(self._action) + 1)
        offset = 5
        radius = 15
        size = ActionGraphics.H_SPACE / 2 - offset * 2
        painter.setBrush(QColor(29, 110, 37))
        painter.drawRoundedRect(QRectF(x + offset, y + offset, size, size),
                                radius, radius)
        painter.setPen(ActionWrapperGraphics.TAG_TEXT_COLOR)
        painter.setBrush(ActionWrapperGraphics.TAG_TEXT_COLOR)
        painter.setFont(ActionWrapperGraphics.TAG_FONT)
        fm = QFontMetricsF(ActionWrapperGraphics.TAG_FONT)
        pixelsWide = fm.width(number)
        pixelsHigh = fm.height()
        # TODO: fix text positioning - font metrics aren't working well
        painter.drawText(x + offset + size / 2 - pixelsWide,
                         y + offset + size / 2 + pixelsHigh / 2, number)

        # Draw the name of the action
        painter.setPen(ActionWrapperGraphics.NAME_TEXT_COLOR)
        painter.setBrush(ActionWrapperGraphics.NAME_TEXT_COLOR)
        painter.setFont(ActionWrapperGraphics.NAME_FONT)
        fm = QFontMetricsF(ActionWrapperGraphics.NAME_FONT)
        br = fm.boundingRect(self._action.getName())
        # TODO: fix text positioning - font metrics aren't working well
        t = fm.elidedText(self._action.getName(), Qt.ElideRight,
                          self._width - offset * 2)
        painter.drawText(x + offset, br.height(), t)
    def getActionRect(self, inputPorts: QGraphicsItem,
                      outputPorts: QGraphicsItem) -> list:
        """
		Gets the bounding rect of the action.

		:param inputPorts: Input ports added for the action.
		:type: QGraphicsItem
		:param outputPorts: Output ports added for the action.
		:type: QGraphicsItem
		:return: List of coordinates and dimensions for the bounding rect of the action.
		:rtype: list
		"""
        x, y, width, height = ActionGraphics.getActionRect(
            self, inputPorts, outputPorts)

        # resize the action to fit all actions and wires inside.
        maxChildWidth = 0
        numActions = len(self._actionGraphics)

        for actionGraphics in self._actionGraphics:
            br = actionGraphics.boundingRect()
            curChildWidth = br.width() + ActionPipelineGraphics.SIDE_MARGIN * 2
            maxChildWidth = max(maxChildWidth, curChildWidth)

        height = ActionGraphics.MAX_HEIGHT * numActions + \
           ActionPipelineGraphics.V_SPACE * (numActions + 1) + \
           PortGraphics.TOTAL_HEIGHT

        self._width = max(self._width, maxChildWidth)
        self._height = height

        x = -self._width / 2
        y = -self._height / 2

        return x, y, self._width, self._height
    def getPortGraphics(self, port: 'Port') -> PortGraphics:
        """
		Gets the port graphics for any port that is owned by either this action pipeline or any
		actions inside of the this action pipeline.
		
		.. note:: This function returns None if the port was not found.
		
		:param port: The port to get the PortGraphics for.
		:type port: Port
		:return: The PortGraphics for the port
		:rtype: PortGraphics
		"""

        pm = {}
        pm.update(self._inputPortMapping)
        pm.update(self._outputPortMapping)
        for a in self._actionGraphics:
            pm.update(a._inputPortMapping)
            pm.update(a._outputPortMapping)

        return pm[port]

        pg = ActionGraphics.getPortGraphics(self, port)
        if pg is not None:
            return pg

        else:
            for action in self._actionGraphics:
                pg = action.getPortGraphics(port)
                if pg:
                    return pg

        raise Exception("Port Graphics not found!")
    def createPortGraphics(self) -> None:
        """
		Override the ActionGraphics createPortGraphics method to not allow context-menu summoning.
		
		:return: None
		:rtype: NoneType
		"""
        self._interactivePorts = False
        return ActionGraphics.createPortGraphics(self)
    def updateGraphics(self) -> None:
        """
		Update the graphics for the action wrapper and all children graphics.
		
		:return: None
		:rtype: NoneType
		"""
        ActionGraphics.updateGraphics(self)

        self.updateActionRect()

        # update position of move buttons
        hOffset = ActionGraphics.H_SPACE / 4
        vOffset = MoveButton.HEIGHT + 20
        self.upButton.setPos(self._width / 2 - hOffset,
                             -self._height / 2 + vOffset)
        self.downButton.setPos(self._width / 2 - hOffset,
                               self._height / 2 - vOffset)
    def paint(self, painter: QPainter, option: QStyleOptionGraphicsItem,
              index: QWidget) -> None:
        """
		Paint the graphics of the action pipeline with ports, wires, and internal graphics.

		:param painter: This draws the widget.
		:type painter: QPainter
		:param option: Option for the style of graphic.
		:type option: QStyleOptionGraphicsItem
		:param index: Index for the painted graphic.
		:type index: QWidget
		:return: None
		:rtype: NoneType
		"""

        self.getActionRect(self._action.getInputPorts(),
                           self._action.getOutputPorts())
        ActionGraphics.paint(self, painter, option, index)
        self.placeActions()