Ejemplo n.º 1
0
class DataNode:
    def __init__(self, data, radius=15):

        self.data = data

        # Add circular node
        self.node = QGraphicsEllipseItem(0, 0, 1, 1)

        # Set radius
        self.radius = radius

        # Add text label
        self.label = QGraphicsTextItem(data.label)
        font = self.label.font()
        font.setPointSize(10)
        self.label.setFont(font)

        # Add line between label and node
        self.line1 = QGraphicsLineItem(0, 0, 1, 1)
        self.line2 = QGraphicsLineItem(0, 0, 1, 1)

        self.node.setZValue(20)
        self.label.setZValue(10)
        self.line1.setZValue(10)
        self.line2.setZValue(10)

        self.line1.setPen(get_pen('0.5'))
        self.line2.setPen(get_pen('0.5'))

        self.color = '0.8'

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):
        self._radius = value
        self.node.setRect(-value, -value, 2 * value, 2 * value)

    def contains(self, point):

        # Check label
        if self.label.contains(self.label.mapFromScene(point)):
            return True

        # Check node
        if self.node.contains(self.node.mapFromScene(point)):
            return True

        return False

    def update(self):
        self.node.update()

    def add_to_scene(self, scene):
        scene.addItem(self.node)
        scene.addItem(self.label)
        scene.addItem(self.line1)
        scene.addItem(self.line2)

    def remove_from_scene(self, scene):
        scene.removeItem(self.node)
        scene.removeItem(self.label)
        scene.removeItem(self.line1)
        scene.removeItem(self.line2)

    @property
    def node_position(self):
        pos = self.node.pos()
        return pos.x(), pos.y()

    @node_position.setter
    def node_position(self, value):
        self.node.setPos(value[0], value[1])
        self.update_lines()

    @property
    def label_position(self):
        pos = self.label.pos()
        return pos.x(), pos.y()

    @label_position.setter
    def label_position(self, value):
        self.label.setPos(value[0], value[1])
        self.update_lines()

    def update_lines(self):
        x0, y0 = self.label_position
        x2, y2 = self.node_position
        x1 = 0.5 * (x0 + x2)
        y1 = y0
        self.line1.setLine(x0, y0, x1, y1)
        self.line2.setLine(x1, y1, x2, y2)

    @property
    def color(self):
        return qt_to_mpl_color(self.node.brush().color())

    @color.setter
    def color(self, value):
        self.node.setBrush(mpl_to_qt_color(value))
Ejemplo n.º 2
0
 def addLine(self, text, color, width=1.):
     shape = QGraphicsLineItem(10., 10., 20., 20.)
     pen = makePen(color, width=width)
     shape.setPen(pen)
     self.addEntry(MapLegendEntryItem(shape, text))
Ejemplo n.º 3
0
class Diagram_Item(QGraphicsItem):
    def __init__(self, entity):
        super().__init__()
        self.entity = entity
        self.modified_callback = None
        self.connection_in_progress_from = None
        self.connection_in_progress_line = None
        self.connect_on_double_click = True
        self.avoid_router = avoid.Router(
            #avoid.PolyLineRouting)
            avoid.OrthogonalRouting)
        self.avoid_router.setRoutingParameter(avoid.shapeBufferDistance, 10.0)
        self.avoid_router.setRoutingParameter(avoid.idealNudgingDistance, 10.0)
        self.avoid_router.setRoutingParameter(avoid.crossingPenalty, 50000000)
        self.route_radius = 6.0
        self.pin_length = 10.0
        self._connection_items = []
        self._block_items = []
        for i, s in enumerate(self.entity.symbols):
            w = s.width
            h = s.height
            s_ui = self.add_block(s, debug=False)
            s_ui.moveBy(s.x, s.y)
            r = s_ui.rect()
            r.setWidth(w)
            r.setHeight(h)
            s_ui.setRect(r)
            s_ui._ensure_minimum_size()
        for c in self.entity.connections:
            self.add_connection(c)
        self.process_avoid_updates()

    def double_clicked_in_background(self, scene_pos):
        # Note that this block should really be associated with
        # some component, but that is not required at this time.
        b = diagram.Block(name="Untitled", width=100, height=100)
        b_item = self.add_block(b, debug=False)
        b_item.setPos(b_item.mapFromScene(scene_pos))
        b_item.set_editing_mode(True, edit_title=True)
        return True  # Do not call mouseDoubleClickEvent, will stop editing

    def mouse_moved_in_scene(self, scene_pos):
        diagram = self
        if diagram.connection_in_progress_from:
            diagram_pos = diagram.mapFromScene(scene_pos)
            x1 = diagram.connection_in_progress_line.line().x1()
            y1 = diagram.connection_in_progress_line.line().y1()
            diagram.connection_in_progress_line.setLine(
                x1, y1, diagram_pos.x(), diagram_pos.y())
            self.connection_in_progress_from.setPen(QPen(highlight_color, 4))

    def start_connecting(self, c, event):
        self.connection_in_progress_from = c
        x, y = c.get_connection_point()
        p1 = self.mapToParent(
            self.mapFromScene(c.parentItem().mapToScene(x, y)))
        x1 = p1.x()
        y1 = p1.y()
        p2 = self.mapFromScene(event.scenePos())
        self.connection_in_progress_line = QGraphicsLineItem(
            x1, y1, p2.x(), p2.y())
        self.connection_in_progress_line.setParentItem(self)
        self.connection_in_progress_line.setPen(QPen(highlight_color, 4))
        c.setPen(QPen(highlight_color, 4))
        self.set_hover_highlight_connectors(True)

    def finish_connecting(self, c):
        start_c = self.connection_in_progress_from
        if c != start_c:
            source_ep = diagram.Endpoint(connector=start_c._connector)
            sink_ep = diagram.Endpoint(connector=c._connector)
            conn = diagram.Connection(
                source=source_ep,
                sink=sink_ep,
            )
            self._stop_connecting()
            self.add_connection(conn)
            self.process_avoid_updates()
        else:
            self.abort_connecting(c)

    def abort_connecting(self, source_item=None):
        if source_item:
            if self.connection_in_progress_from:
                source_item.clearFocus()
        self._stop_connecting()

    def _stop_connecting(self):
        start_c = self.connection_in_progress_from
        if start_c:
            self.set_hover_highlight_connectors(False)
            start_c._set_default_appearance()
            self.connection_in_progress_from = None
            self.connection_in_progress_line.setParentItem(None)
            self.connection_in_progress_line = None

    def add_connection(self, connection):
        c_ui = Connection_Item(connection, self)
        c_ui.setParentItem(self)
        c_ui.arrow.setParentItem(self)
        self._connection_items.append(c_ui)
        self._hide_duplicate_connections()
        if not connection in self.entity.connections:
            self.entity.connections.append(connection)
        return c_ui

    def remove_connection(self, c_ui):
        self.avoid_router.deleteConnector(c_ui.avoid_conn)
        self._connection_items.remove(c_ui)
        c_ui.setParentItem(None)
        c_ui.arrow.setParentItem(None)
        self._hide_duplicate_connections()
        self.entity.connections.remove(c_ui._connection)

    def add_block(self, block, debug=False):
        s_ui = Block_Item(block, debug=debug)
        s_ui.modified_callback = self.set_modified
        s_ui.setParentItem(self)
        self._block_items.append(s_ui)
        if not block in self.entity.symbols:
            self.entity.symbols.append(block)
        return s_ui

    def remove_block(self, block):
        self._block_items.remove(block)
        block.remove_all_connectors()
        block.setParentItem(None)
        self.entity.symbols.remove(block._block)

    def mouse_pressed_in(self, source_item):
        # Allow diagram elements to know that the mouse was pressed
        # outside of the element.
        for item in self._block_items:
            if source_item != item:
                item.mouse_pressed_in(source_item)
        self.abort_connecting(source_item)

    def paint(self, *args, **kw):
        # Implement pure virtual method
        pass

    def boundingRect(self, *args, **kw):
        # Implement pure virtual method
        return QRectF(0, 0, 0, 0)

    def set_hover_highlight_connectors(self, highlight):
        for b in self._block_items:
            b.set_hover_highlight_connectors(highlight)

    def set_show_connection_ports_on_hover(self, show):
        for c_ui in list(self._connection_items):
            c_ui.set_show_connection_ports_on_hover(show)

    def set_modified(self, subitem=None):
        if self.modified_callback:
            self.modified_callback(self)

    def process_avoid_updates(self):
        for c_ui in list(self._connection_items):
            success = c_ui.update_endpoints()
            if not success:
                self.remove_connection(c_ui)
        self.avoid_router.processTransaction()
        for c_ui in self._connection_items:
            c_ui.update_from_avoid_router()
        self.set_modified()

    def _hide_duplicate_connections(self):
        processed_connections = []
        for c in self._connection_items:
            c._duplicate_is = None
            c._duplicate_of = None
            c.show()
            for p in processed_connections:
                if (c._sink_ui == p._source_ui and c._source_ui == p._sink_ui):
                    c.hide()
                    p._duplicate_is = c
                    c._duplicate_of = p
            processed_connections.append(c)
        self.process_avoid_updates()
Ejemplo n.º 4
0
class DataNode:

    def __init__(self, data, radius=15):

        self.data = data

        # Add circular node
        self.node = QGraphicsEllipseItem(0, 0, 1, 1)

        # Set radius
        self.radius = radius

        # Add text label
        self.label = QGraphicsTextItem(data.label)
        font = self.label.font()
        font.setPointSize(10)
        self.label.setFont(font)

        # Add line between label and node
        self.line1 = QGraphicsLineItem(0, 0, 1, 1)
        self.line2 = QGraphicsLineItem(0, 0, 1, 1)

        self.node.setZValue(20)
        self.label.setZValue(10)
        self.line1.setZValue(10)
        self.line2.setZValue(10)

        self.line1.setPen(get_pen('0.5'))
        self.line2.setPen(get_pen('0.5'))

        self.color = '0.8'

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):
        self._radius = value
        self.node.setRect(-value, -value, 2 * value, 2 * value)

    def contains(self, point):

        # Check label
        if self.label.contains(self.label.mapFromScene(point)):
            return True

        # Check node
        if self.node.contains(self.node.mapFromScene(point)):
            return True

        return False

    def update(self):
        self.node.update()

    def add_to_scene(self, scene):
        scene.addItem(self.node)
        scene.addItem(self.label)
        scene.addItem(self.line1)
        scene.addItem(self.line2)

    def remove_from_scene(self, scene):
        scene.removeItem(self.node)
        scene.removeItem(self.label)
        scene.removeItem(self.line1)
        scene.removeItem(self.line2)

    @property
    def node_position(self):
        pos = self.node.pos()
        return pos.x(), pos.y()

    @node_position.setter
    def node_position(self, value):
        self.node.setPos(value[0], value[1])
        self.update_lines()

    @property
    def label_position(self):
        pos = self.label.pos()
        return pos.x(), pos.y()

    @label_position.setter
    def label_position(self, value):
        self.label.setPos(value[0], value[1])
        self.update_lines()

    def update_lines(self):
        x0, y0 = self.label_position
        x2, y2 = self.node_position
        x1 = 0.5 * (x0 + x2)
        y1 = y0
        self.line1.setLine(x0, y0, x1, y1)
        self.line2.setLine(x1, y1, x2, y2)

    @property
    def color(self):
        return qt_to_mpl_color(self.node.brush().color())

    @color.setter
    def color(self, value):
        self.node.setBrush(mpl_to_qt_color(value))
Ejemplo n.º 5
0
class DualColoredLineSegment(QGraphicsItemGroup):
    """
    One individual line segment.  This is a group because it needs to create two
    lines in order to create a multi colored dashed pattern.

    Attributes:
        spacing (int): how much space in pixels are between each line segment
    """
    def __init__(self,
                 parent=None,
                 width=1,
                 color1=QColor(0, 0, 0),
                 color2=QColor(255, 255, 255)):
        super(DualColoredLineSegment, self).__init__(parent)

        # create lines
        self.line_1 = QGraphicsLineItem()
        self.line_2 = QGraphicsLineItem()

        self.width = width
        self._length = 2
        self._spacing = 5

        # set pen
        self.setColor1(color1)
        self.setColor2(color2)

        # add lines to group
        self.addToGroup(self.line_1)
        self.addToGroup(self.line_2)

    """ DISPLAY"""

    def setColor1(self, color):
        """
        Sets the first line to the specified color

        Args:
            color (QColor): color for the line to be set to
        """
        pen = self.createPen(color)
        self.line_1.setPen(pen)

    def setColor2(self, color):
        """
        Sets the first line to the specified color

        Args:
            color (QColor): color for the line to be set to
        """
        pen = self.createPen(color, offset=True)
        self.line_2.setPen(pen)

    def updatePen(self):
        for line in [self.line_1, self.line_2]:
            pen = line.pen()
            total_line_space = self.length() + (2 * self.spacing())
            pen.setDashPattern([self.length(), total_line_space])
            pen.setWidth(self.width)
            line.setPen(pen)

    def createPen(self, color, offset=None):
        """
        Creates a pen of the color specified

        Args:
            color (QColor): color for the line to be set to
            offset (bool): if color should be offset or not.
                Since this is only two colors, this can be a boolean, rather
                than an index.
        """
        pen = QPen()
        pen.setColor(color)
        total_line_space = self.length() + (2 * self.spacing())
        if offset:
            pen.setDashOffset(self.length() + self.spacing())
        pen.setDashPattern([self.length(), total_line_space])
        pen.setWidth(self.width)

        return pen

    def setLine(self, x, y, width, height):
        self.line_1.setLine(x, y, width, height)
        self.line_2.setLine(x, y, width, height)

    """ PROPERTIES """

    def width(self):
        return self._width

    def setWidth(self, width):
        self._width = width

    def length(self):
        return self._length

    def setLength(self, length):
        self._length = length

    def spacing(self):
        return self._spacing

    def setSpacing(self, spacing):
        self._spacing = spacing
Ejemplo n.º 6
0
 def addLine(self, text, color, width=1.):
     shape = QGraphicsLineItem(10., 10., 20., 20.)
     pen = makePen(color, width=width)
     shape.setPen(pen)
     self.addEntry(MapLegendEntryItem(shape, text))