コード例 #1
0
class DefaultGraphicalVertex(Vertex, QtGui.QGraphicsEllipseItem):
    circleSize = 10.0 * 2
    def __init__(self, vertex, graph):
        QtGui.QGraphicsEllipseItem .__init__(self, 0, 0, self.circleSize, self.circleSize, None)
        Vertex.__init__(self, vertex, graph, defaultCenterConnector=True)

    mousePressEvent = qtutils.mixin_method(Vertex, QtGui.QGraphicsEllipseItem,
                                   "mousePressEvent")
    itemChange = qtutils.mixin_method(Vertex, QtGui.QGraphicsEllipseItem,
                                      "itemChange")
    paint = qtutils.mixin_method(QtGui.QGraphicsEllipseItem, None,
                         "paint")
コード例 #2
0
    class InvisibleConnector(QtGui.QGraphicsEllipseItem, Connector):
        size = 10
        def __init__(self, parent, *args, **kwargs):
            QtGui.QGraphicsEllipseItem.__init__(self, 0, 0 , self.size, self.size, None)
            Connector.__init__(self, *args, **kwargs)
            self.setBrush(QtGui.QBrush(QtCore.Qt.darkGreen))
            # Needs to be visible or else won't receive events
            # we override paint in order to hide the item
            self.setVisible(True)
            self.fakeParent = parent



        def position_changed(self, *args):
            """reimplemented to do nothing. otherwise caught
            position changes from the model and ignored
            the position it was forced to"""
            pass

        def paint(self, painter, options, widget):
            pass

        itemChange = qtutils.mixin_method(Connector, QtGui.QGraphicsEllipseItem,
                                  "itemChange")
コード例 #3
0
class GraphicalPort(qt.QtGui.QGraphicsEllipseItem, qtgraphview.Connector):
    """ A vertex port """
    MAX_TIPLEN = 400
    WIDTH = 7.0
    HEIGHT = 7.0

    def __init__(self, parent, port):
        """
"""
        qt.QtGui.QGraphicsEllipseItem.__init__(self, 0, 0, self.WIDTH,
                                               self.HEIGHT, parent)
        qtgraphview.Connector.__init__(self, observed=port)
        self.__interfaceColor = None
        self.set_connection_modifiers(qt.QtCore.Qt.NoModifier)
        self.initialise_from_model()

    port = baselisteners.GraphElementListenerBase.get_observed

    def initialise_from_model(self):
        port = self.port()
        mdict = port.get_ad_hoc_dict()
        # graphical data init.
        mdict.simulate_full_data_change(self, port)
        interface = port.get_interface()
        if interface and interface.__color__ is not None:
            self.__interfaceColor = qt.QtGui.QColor(*interface.__color__)
        # update tooltip
        self.notify(port, ("tooltip_modified", port.get_tip()))

    def change_observed(self, old, new):
        if isinstance(new, AbstractPort):
            qtgraphview.Element.clear_observed(self)
            self.set_observed(new)

    def close_and_delete(self, obj):
        self.clear_observed()
        del self

    def notify(self, sender, event):
        try:
            self.port()
        except:
            self.clear_observed()
            del self
            return

        if (event[0] in ["tooltip_modified", "stop_eval"]):
            self.__update_tooltip()
        elif (event[0] == "metadata_changed"):
            if (sender == self.port()):
                if (event[1] == "hide"):
                    if event[2]:  # if hide
                        self.hide()
                    else:
                        self.show()
                    self.parentItem().refresh_geometry()
        qtgraphview.Connector.notify(self, sender, event)

    def clear_observed(self, *args):
        qtgraphview.Element.clear_observed(self)
        return

    def __update_tooltip(self):
        node = self.port().vertex()
        if isinstance(self.port(), OutputPort):
            data = node.get_output(self.port().get_id())
        elif isinstance(self.port(), InputPort):
            data = node.get_input(self.port().get_id())
        try:
            s = str(data)
        except:
            s = ''
        if (len(s) > self.MAX_TIPLEN):
            s = "String too long..."
            self.setToolTip(s)
        else:
            #self.setToolTip("Value: " + s)
            self.setToolTip(self.port().get_tip(data))

    def get_id(self):
        return self.port().get_id()

    ##################
    # QtWorld-Events #
    #################
    def contextMenuEvent(self, event):
        if isinstance(self.port(), OutputPort):
            operator = GraphOperator(graph=self.graph, graphScene=self.scene())
            operator.set_port_item(self)
            menu = qtutils.AleaQMenu(operator.get_sensible_parent())
            menu.addAction(operator("Send to pool", menu, "port_send_to_pool"))
            menu.addAction(
                operator("Send to console", menu, "port_send_to_console"))
            menu.addAction(operator("Print", menu, "port_print_value"))
            menu.show()
            menu.move(event.screenPos())
            event.accept()

    def paint(self, painter, option, widget):
        if (not self.isVisible()):
            return
        pos = self.pos()
        painter.setBackgroundMode(qt.QtCore.Qt.TransparentMode)
        gradient = qt.QtGui.QLinearGradient(0, 0, 10, 0)
        if self.highlighted:
            gradient.setColorAt(1,
                                qt.QtGui.QColor(qt.QtCore.Qt.red).lighter(120))
            gradient.setColorAt(
                0,
                qt.QtGui.QColor(qt.QtCore.Qt.darkRed).lighter(120))
        else:
            if self.__interfaceColor is None:
                gradient.setColorAt(
                    0.8,
                    qt.QtGui.QColor(qt.QtCore.Qt.yellow).lighter(120))
                gradient.setColorAt(
                    0.2,
                    qt.QtGui.QColor(qt.QtCore.Qt.darkYellow).lighter(120))
            else:
                gradient.setColorAt(0.8, self.__interfaceColor.lighter(120))
                gradient.setColorAt(0.2, self.__interfaceColor.lighter(120))

        painter.setBrush(qt.QtGui.QBrush(gradient))
        painter.setPen(qt.QtGui.QPen(qt.QtCore.Qt.black, 0))
        painter.drawEllipse(qt.QtCore.QRectF(0, 0, self.WIDTH, self.HEIGHT))

    itemChange = mixin_method(qtgraphview.Connector, qt.QtGui.QGraphicsItem,
                              "itemChange")
コード例 #4
0
class ObserverOnlyGraphicalVertex(
        qtgraphview.Vertex,
        qtutils.AleaQGraphicsRoundedRectItem,
):
    # --- PAINTING STUFF ---
    # Color Definition
    default_pen_color = qt.QtGui.QColor(qt.QtCore.Qt.darkGray)
    default_pen_selected_color = qt.QtGui.QColor(qt.QtCore.Qt.lightGray)
    default_pen_error_color = qt.QtGui.QColor(qt.QtCore.Qt.red)

    default_top_color = qt.QtGui.QColor(200, 200, 200, 255)
    default_bottom_color = qt.QtGui.QColor(140, 140, 255, 255)
    default_error_color = qt.QtGui.QColor(255, 0, 0, 255)
    default_user_application_color = qt.QtGui.QColor(255, 144, 0, 200)
    default_unlazy_color = qt.QtGui.QColor(200, 255, 160, 255)

    # gradient stops
    startPos = 0.0
    endPos = 1.0

    # Shape definition
    portSpacing = 5.0
    outMargins = 5.0
    delayMargins = 7.0
    evalColor = qt.QtGui.QColor(255, 0, 0, 200)

    default_corner_radius = 1.2
    default_margin = 3.0
    pen_width = 1.0

    maxTipLength = 400

    def __init__(self, vertex, graph, parent=None):
        qtutils.AleaQGraphicsRoundedRectItem.__init__(
            self, self.default_corner_radius, True, 0, 0, 1, 1, parent)
        qtgraphview.Vertex.__init__(self, vertex, graph)

        # ----- The colors -----
        self.__topColor = self.default_top_color
        self.__bottomColor = self.default_bottom_color
        self.__penColor = self.default_pen_color

        # ----- Layout of the item -----
        ph = GraphicalPort.HEIGHT
        self.vLayout = qtutils.VerticalLayout(margins=(self.outMargins,
                                                       self.outMargins, 0.,
                                                       0.),
                                              center=True)
        # in ports
        self.inPortLayout = qtutils.HorizontalLayout(
            parent=self.vLayout,
            innerMargins=(self.portSpacing, 0.),
            center=True,
            mins=(ph, ph))
        # Caption
        self._caption = qt.QtGui.QGraphicsSimpleTextItem(self)
        self.vLayout.addItem(self._caption)
        # out ports
        self.outPortLayout = qtutils.HorizontalLayout(
            parent=self.vLayout,
            innerMargins=(self.portSpacing, 0.),
            center=True,
            mins=(ph, ph))

        # Editor
        self.__editor = None

        # Small dots when the vertex has hidden ports
        hiddenPortItem = HiddenPort(self)
        hiddenPortItem.setVisible(False)
        self.hiddenPortItem = hiddenPortItem
        self.inPortLayout.addFinalItem(hiddenPortItem)

        # Small box when the vertex is busy, beping evaluated
        self._busyItem = qt.QtGui.QGraphicsRectItem(0, 0, 7, 7, self)
        self._busyItem.setBrush(self.evalColor)
        self._busyItem.setAcceptedMouseButtons(qt.QtCore.Qt.NoButton)
        self._busyItem.setVisible(False)

        # Clock image when the vertex has a delay
        self._delayItem = qt.QtSvg.QGraphicsSvgItem(":icons/clock.svg", self)
        self._delayItem.setAcceptedMouseButtons(qt.QtCore.Qt.NoButton)
        self._delayItem.setVisible(False)

        self._delayText = qt.QtGui.QGraphicsSimpleTextItem(
            "0", self._delayItem)
        self._delayText.setFont(qt.QtGui.QFont("ariana", 6))
        self._delayText.setBrush(
            qt.QtGui.QBrush(qt.QtGui.QColor(255, 0, 0, 200)))
        self._delayText.setZValue(self._delayItem.zValue() + 1)
        self._delayText.setVisible(False)

        # ----- drawing nicities -----
        self.setPen(qt.QtGui.QPen(qt.QtCore.Qt.black, self.pen_width))
        if safeEffects:
            fx = qt.QtGui.QGraphicsDropShadowEffect()
            fx.setOffset(2, 2)
            fx.setBlurRadius(5)
            self.setGraphicsEffect(fx)

    def initialise_from_model(self):
        vertex = self.vertex()
        mdict = vertex.get_ad_hoc_dict()

        # position/color...
        mdict.simulate_full_data_change(self, vertex)
        userColor = self.get_view_data("userColor")
        if (userColor is None):
            self.store_view_data(useUserColor=False)

        # add connectors and configure their visibility
        for i in vertex.input_desc + vertex.output_desc:
            self.add_port(i)
        # once connectors are added we also initialise them
        for c in self.iter_connectors():
            c.initialise_from_model()

        # configure other items to be visible or not
        self.update_delay_item()
        self.update_hidden_port_item()
        self.set_graphical_tooltip(vertex.get_tip())
        self.set_graphical_caption(vertex.caption)
        # self.refresh_geometry() already done by set_graphical_caption
        self.update_colors()  # last because gradient depends on geometry

    def terminate_from_model(self):
        vertex = self.vertex()
        self.remove_ports(lambda x: isinstance(x, InputPort))
        self.remove_ports(lambda x: isinstance(x, OutputPort))

    def set_editor_instance(self, editor):
        self.__editor = editor

    def get_editor_instance(self):
        return self.__editor

    ###########
    # Queries #
    ###########
    def all_inputs_visible(self):
        for i in self.inPortLayout:
            if not i.isVisible():
                return False
        return True

    #############
    # Modifiers #
    #############
    def update_hidden_port_item(self):
        visible = not self.all_inputs_visible() and self.isVisible()
        self.hiddenPortItem.setVisible(visible)

    def update_delay_item(self):
        visible = self.vertex().delay > 0
        self._delayItem.setVisible(visible and self.isVisible())
        self._delayText.setVisible(visible and self.isVisible())
        if visible:
            self._delayText.setText(str(self.vertex().delay))

    def update_colors(self):
        self.__topColor = self.default_top_color
        self.__bottomColor = self.default_bottom_color
        self.__penColor = self.default_pen_color

        if not self.get_view_data("useUserColor"):
            if self.vertex().raise_exception:
                self.__topColor = self.default_error_color
                self.__bottomColor = self.__topColor.darker()
                self.__penColor = self.default_pen_error_color
            elif self.vertex().user_application:
                self.__topColor = self.default_user_application_color
                self.__bottomColor = self.__topColor.darker()
            elif not self.vertex().lazy:
                self.__topColor = self.default_unlazy_color
                self.__bottomColor = self.__topColor.darker()
        else:
            userColor = self.get_view_data("userColor")
            if userColor:
                self.__topColor = qt.QtGui.QColor(*userColor)
                self.__bottomColor = qt.QtGui.QColor(*userColor)

        pen = self.pen()
        pen.setColor(self.__penColor)

        gradient = qt.QtGui.QLinearGradient(self.rect().topLeft(),
                                            self.rect().bottomLeft())
        gradient.setColorAt(self.startPos, self.__topColor)
        gradient.setColorAt(self.endPos, self.__bottomColor)
        brush = qt.QtGui.QBrush(gradient)

        self.setPen(pen)
        self.setBrush(brush)

    def set_graphical_caption(self, caption):
        """Sets the name displayed in the vertex widget, doesn't change
the vertex data"""
        if caption == "" or caption == None:
            caption = " "
        if len(caption) > 20:
            caption = caption[:20] + "..."
        self._caption.setText(caption)
        self.refresh_geometry()

    def set_graphical_tooltip(self, rawtooltip):
        if rawtooltip is None:
            rawtooltip = ""
        if len(rawtooltip) > self.maxTipLength:
            rawtooltip = rawtooltip[:self.maxTipLength]
            rawtooltip += "...\nSee Help tab for complete documentation"
        self.setToolTip(rawtooltip)

    ####################
    # Observer methods #
    ####################
    def store_view_data(self, **kwargs):
        for k, v in kwargs.iteritems():
            self.vertex().get_ad_hoc_dict().set_metadata(k, v)

    def get_view_data(self, key):
        return self.vertex().get_ad_hoc_dict().get_metadata(key)

    def notify(self, sender, event):
        """ Notification sent by the vertex associated to the item """
        if event is None:
            return

        try:
            refresh = eval(Settings().get("UI", "EvalCue"))
        except:
            refresh = True

        eventTopKey = event[0]
        if eventTopKey == "close":
            if self.__editor:
                self.__editor.close()
        elif eventTopKey == "data_modified":
            key = event[1]
            if key == "caption":
                self.set_graphical_caption(event[2])
        elif eventTopKey == "internal_state_changed":
            key = event[1]
            if key == "delay":
                self.update_delay_item()
            elif key == "lazy" or key == "blocked" or key == "user_application":
                self.update_colors()
        elif eventTopKey == "metadata_changed":
            if event[1] == "userColor":
                if event[2] is None:
                    self.store_view_data(useUserColor=False)
                else:
                    self.update_colors()
            elif event[1] == "useUserColor":
                self.update_colors()
        elif eventTopKey == "exception_state_changed":
            self.update_colors()
        elif eventTopKey == "hiddenPortChange":
            self.update_hidden_port_item()
        elif (eventTopKey == "tooltip_modified"):
            self.set_graphical_tooltip(event[1])
        if refresh:
            if (eventTopKey == "start_eval"):
                self._busyItem.setVisible(self.isVisible())
                qt.QtGui.QApplication.processEvents()
            elif (eventTopKey == "stop_eval"):
                self._busyItem.setVisible(False)
                qt.QtGui.QApplication.processEvents()
        elif (eventTopKey == "input_port_added"):
            self.add_port(event[1])
        elif (eventTopKey == "output_port_added"):
            self.add_port(event[1])
        elif (eventTopKey == "cleared_input_ports"):
            self.remove_ports(lambda x: isinstance(x.port(), InputPort))
        elif (eventTopKey == "cleared_output_ports"):
            self.remove_ports(lambda x: isinstance(x.port(), OutputPort))
        self.update()
        qtgraphview.Vertex.notify(self, sender, event)

    #######################################
    # Methods to add/remove model ports #
    # They automatically do the according #
    # operation in the GUI. #
    #######################################
    def add_port(self, modelPort):
        if isinstance(modelPort, InputPort):
            l = self.inPortLayout
        elif isinstance(modelPort, OutputPort):
            l = self.outPortLayout
        if modelPort not in l:
            gp = GraphicalPort(self, modelPort)
            if gp:
                l.addItem(gp)
                self.add_connector(gp)
                self.refresh_geometry()

    def remove_port(self, modelPort):
        if isinstance(modelPort, InputPort):
            l = self.inPortLayout
        elif isinstance(modelPort, OutputPort):
            l = self.outPortLayout
        for gp in l._items[:]:
            if gp.port() == modelPort:
                l.removeItem(gp)
                gp.remove_from_view(self.scene())
                self.remove_connector(gp)
                del gp
                self.refresh_geometry()

    def remove_ports(self, filter=lambda x: True):
        for con in list(self.iter_connectors(filter)):
            l = self.inPortLayout if isinstance(
                con.port(), InputPort) else self.outPortLayout
            l.removeItem(con)
            con.remove_from_view(self.scene())
            self.remove_connector(con)

    #####################################################################
    # Code related to the layout of subitems and geometry of the vertex #
    #####################################################################
    def layout_items(self):
        geom = self.vLayout.boundingRect(force=True)
        self.vLayout.setPos(qt.QtCore.QPointF(0., 0.))
        self._busyItem.setPos(0, 0)

        diBr = self._delayItem.boundingRect()
        dtBr = self._delayText.boundingRect()
        self._delayItem.setPos(-diBr.width() / 2 - self.delayMargins,
                               (geom.height() - diBr.height()) / 2)
        self._delayText.setPos((diBr.width() - dtBr.width()) / 2,
                               (diBr.height() - dtBr.height()) / 2)
        return geom

    def refresh_geometry(self):
        halfPortH = GraphicalPort.HEIGHT / 2
        geom = self.layout_items().adjusted(-self.pen_width,
                                            halfPortH - self.pen_width,
                                            self.pen_width,
                                            -(halfPortH - self.pen_width))
        self.setRect(geom)
        self.refresh_cached_shape()

    ################
    # Drawing Code #
    ################
    def paint(self, painter, options, widget):
        path = self.shape()
        pen = self.pen()
        brush = self.brush()
        painter.setPen(pen)
        painter.setBrush(brush)
        painter.drawPath(path)

        if (self.vertex().block):
            brush.setStyle(qt.QtCore.Qt.BDiagPattern)
            painter.setBrush(brush)
            painter.drawPath(path)

    ################
    # Qt Overloads #
    ################
    def itemChange(self, change, value):
        if change == qt.QtGui.QGraphicsItem.ItemSelectedChange:
            selected = bool(value)
            pen = self.pen()
            brush = self.brush()
            gradient = brush.gradient()
            if selected:
                pen.setColor(self.default_pen_selected_color)
                if gradient:  # invert the gradient
                    gradient.setColorAt(self.endPos, self.__topColor)
                    gradient.setColorAt(self.startPos, self.__bottomColor)
                scene = self.scene()
                scene.focusedItemChanged.emit(scene, self)
            else:
                pen.setColor(self.default_pen_color)
                if gradient:  # invert the gradient
                    gradient.setColorAt(self.startPos, self.__topColor)
                    gradient.setColorAt(self.endPos, self.__bottomColor)
            self.setPen(pen)
            self.setBrush(brush)

        qtgraphview.Vertex.itemChange(self, change, value)
        return qt.QtGui.QGraphicsRectItem.itemChange(self, change, value)

    mousePressEvent = mixin_method(qtgraphview.Vertex,
                                   qt.QtGui.QGraphicsRectItem,
                                   "mousePressEvent")
コード例 #5
0
class SimpleVertex(QtGui.QGraphicsEllipseItem, Vertex):
    __vertex_size__ = QtCore.QSizeF(30.0, 30.0)
    __border_size__ = 5

    def __init__(self, vertex, graph, parent=None):
        QtGui.QGraphicsEllipseItem.__init__(self, 0.0, 0.0,
                                            self.__vertex_size__.width(),
                                            self.__vertex_size__.height(),
                                            parent)
        Vertex.__init__(self, vertex, graph)
        self.setZValue(1.0)

        #we choose the avocado colors
        self.setBrush(QtGui.QBrush(QtCore.Qt.yellow))
        pen = QtGui.QPen(QtCore.Qt.darkGreen)
        pen.setWidth(self.__border_size__ - 2)
        self.setPen(pen)

        self.initialise_from_model()

    ##################
    # QtWorld-Layout #
    ##################
    def size(self):
        return self.__vertex_size__

    def sizeHint(self, blop, blip):
        return self.__vertex_size__

    ##################
    # QtWorld-Events #
    ##################
    mousePressEvent = mixin_method(Vertex, QtGui.QGraphicsEllipseItem,
                                   "mousePressEvent")
    itemChange = mixin_method(Vertex, QtGui.QGraphicsEllipseItem, "itemChange")

    def contextMenuEvent(self, event):  #called on right click on the vertex.
        menu = QtGui.QMenu(event.widget())
        action = menu.addAction("Delete vertex")
        action.connect(action, QtCore.SIGNAL("triggered()"), self.remove)
        menu.popup(event.screenPos())
        event.accept()

    def remove(self):
        self.graph().remove_vertex(self.vertex())

    def paint(self, painter, painterOptions, widget):
        QtGui.QGraphicsEllipseItem.paint(self, painter, painterOptions, widget)

    def store_view_data(self, key, value, notify=True):
        self.vertex().get_ad_hoc_dict().set_metadata(key, value, notify)

    def get_view_data(self, key):
        return self.vertex().get_ad_hoc_dict().get_metadata(key)

    def announce_view_data(self, exclusive=False):
        if not exclusive:
            self.vertex().get_ad_hoc_dict().simulate_full_data_change()
        else:
            self.vertex().exclusive_command(
                exclusive,
                self.vertex().get_ad_hoc_dict().simulate_full_data_change)