Exemple #1
0
    def plot_vert_line_graph(self, qp, x_line, color, c, arrow_up=False,
                             arrow_down=False):
        if x_line < self._start_date or x_line > self._end_date:
            return

        x_line -= self._start_date

        qp.save()
        qp.setPen(color)
        qp.setBrush(color)
        qp.setRenderHint(QPainter.Antialiasing)
        arrowSize = 2.0
        x, y = self.origGraph(c)
        line = QLineF(x + self.convX(x_line), y + 10, x + self.convX(x_line),
                      y + 50)
        qp.drawLine(line)
        if arrow_up:
            arrowP1 = line.p1() + QPointF(arrowSize, arrowSize * 3)
            arrowP2 = line.p1() + QPointF(-arrowSize, arrowSize * 3)
            qp.drawLine(line.p1(), arrowP1)
            qp.drawLine(line.p1(), arrowP2)
        if arrow_down:
            arrowP1 = line.p2() + QPointF(arrowSize, - arrowSize * 3)
            arrowP2 = line.p2() + QPointF(-arrowSize, - arrowSize * 3)
            qp.drawLine(line.p2(), arrowP1)
            qp.drawLine(line.p2(), arrowP2)
        qp.restore()
Exemple #2
0
    def setLine(self, line):
        """
        Set the arrow base line (a `QLineF` in object coordinates).
        """
        if self.__line != line:
            self.__line = line

            # local item coordinate system
            geom = self.geometry().translated(-self.pos())

            if geom.isNull() and not line.isNull():
                geom = QRectF(0, 0, 1, 1)

            arrow_shape = arrow_path_concave(line, self.lineWidth())
            arrow_rect = arrow_shape.boundingRect()

            if not (geom.contains(arrow_rect)):
                geom = geom.united(arrow_rect)

            if self.__autoAdjustGeometry:
                # Shrink the geometry if required.
                geom = geom.intersected(arrow_rect)

            # topLeft can move changing the local coordinates.
            diff = geom.topLeft()
            line = QLineF(line.p1() - diff, line.p2() - diff)
            self.__arrowItem.setLine(line)
            self.__line = line

            # parent item coordinate system
            geom.translate(self.pos())
            self.setGeometry(geom)
Exemple #3
0
    def setLine(self, line):
        """
        Set the arrow base line (a `QLineF` in object coordinates).
        """
        if self.__line != line:
            self.__line = line

            # local item coordinate system
            geom = self.geometry().translated(-self.pos())

            if geom.isNull() and not line.isNull():
                geom = QRectF(0, 0, 1, 1)

            arrow_shape = arrow_path_concave(line, self.lineWidth())
            arrow_rect = arrow_shape.boundingRect()

            if not (geom.contains(arrow_rect)):
                geom = geom.united(arrow_rect)

            if self.__autoAdjustGeometry:
                # Shrink the geometry if required.
                geom = geom.intersected(arrow_rect)

            # topLeft can move changing the local coordinates.
            diff = geom.topLeft()
            line = QLineF(line.p1() - diff, line.p2() - diff)
            self.__arrowItem.setLine(line)
            self.__line = line

            # parent item coordinate system
            geom.translate(self.pos())
            self.setGeometry(geom)
    def _updateTextAnchors(self):
        n = len(self._items)

        items = self._items
        dist = 15

        shape = reduce(QPainterPath.united, [item.path() for item in items])
        brect = shape.boundingRect()
        bradius = max(brect.width() / 2, brect.height() / 2)

        center = self.boundingRect().center()

        anchors = _category_anchors(items)
        self._textanchors = []
        for angle, anchor_h, anchor_v in anchors:
            line = QLineF.fromPolar(bradius, angle)
            ext = QLineF.fromPolar(dist, angle)
            line = QLineF(line.p1(), line.p2() + ext.p2())
            line = line.translated(center)

            anchor_pos = line.p2()
            self._textanchors.append((anchor_pos, anchor_h, anchor_v))

        for i in range(n):
            self._updateTextItemPos(i)
Exemple #5
0
    def _updateTextAnchors(self):
        n = len(self._items)

        items = self._items
        dist = 15

        shape = reduce(QPainterPath.united, [item.path() for item in items])
        brect = shape.boundingRect()
        bradius = max(brect.width() / 2, brect.height() / 2)

        center = self.boundingRect().center()

        anchors = _category_anchors(items)
        self._textanchors = []
        for angle, anchor_h, anchor_v in anchors:
            line = QLineF.fromPolar(bradius, angle)
            ext = QLineF.fromPolar(dist, angle)
            line = QLineF(line.p1(), line.p2() + ext.p2())
            line = line.translated(center)

            anchor_pos = line.p2()
            self._textanchors.append((anchor_pos, anchor_h, anchor_v))

        for i in range(n):
            self._updateTextItemPos(i)
    def adjust(self):
        if not self.source or not self.dest:
            return

        line = QLineF(self.mapFromItem(self.source, 0, 0),
                      self.mapFromItem(self.dest, 0, 0))
        length = line.length()

        self.prepareGeometryChange()

        if length > 20.0:
            edgeOffset = QPointF((line.dx() * 10) / length,
                                 (line.dy() * 10) / length)

            self.sourcePoint = line.p1() + edgeOffset
            self.destPoint = line.p2() - edgeOffset
        else:
            self.sourcePoint = line.p1()
            self.destPoint = line.p1()
Exemple #7
0
    def drawPath(self, startPoint, endPoint):
        path = QPainterPath()

        one = (QPointF(endPoint.x(), startPoint.y()) + startPoint) / 2
        two = (QPointF(startPoint.x(), endPoint.y()) + endPoint) / 2

        path.moveTo(startPoint)

        angle = math.pi / 2
        bLine1 = QLineF()
        bLine1.setP1(startPoint)

        if startPoint.x() > endPoint.x():
            dist = startPoint.x() - endPoint.x()
            one = (bLine1.p1() + QPointF(math.sin(angle) * dist,  math.cos(angle) * dist))
            bLine1.setP1(endPoint)
            two = (bLine1.p1() + QPointF(math.sin(angle) * dist,  math.cos(angle) * dist))

        path.cubicTo(one, two,  endPoint)
        return path, QLineF(one, two)
Exemple #8
0
    def drawToolButtonMenuIndicator(self, option, painter, widget=None):
        arrow_rect = self.proxy().subControlRect(QStyle.CC_ToolButton, option, QStyle.SC_ToolButtonMenu, widget)

        text_color = option.palette.color(QPalette.WindowText if option.state & QStyle.State_AutoRaise else QPalette.ButtonText)
        button_color = option.palette.color(QPalette.Button)
        background_color = self.background_color(button_color, 0.5)

        painter.save()

        # draw separating vertical line
        if option.state & (QStyle.State_On|QStyle.State_Sunken):
            top_offset, bottom_offset = 4, 3
        else:
            top_offset, bottom_offset = 2, 2

        if option.direction == Qt.LeftToRight:
            separator_line = QLineF(arrow_rect.x()-3, arrow_rect.top()+top_offset, arrow_rect.x()-3, arrow_rect.bottom()-bottom_offset)
        else:
            separator_line = QLineF(arrow_rect.right()+3, arrow_rect.top()+top_offset, arrow_rect.right()+3, arrow_rect.bottom()-bottom_offset)

        light_gradient = QLinearGradient(separator_line.p1(), separator_line.p2())
        light_gradient.setColorAt(0.0, ColorScheme.shade(self.background_top_color(button_color), ColorScheme.LightShade, 0.0))
        light_gradient.setColorAt(1.0, ColorScheme.shade(self.background_bottom_color(button_color), ColorScheme.MidlightShade, 0.5))
        separator_color = ColorScheme.shade(self.background_bottom_color(button_color), ColorScheme.MidShade, 0.0)

        painter.setRenderHint(QPainter.Antialiasing, False)
        painter.setPen(QPen(light_gradient, 1))
        painter.drawLine(separator_line.translated(-1, 0))
        painter.drawLine(separator_line.translated(+1, 0))
        painter.setPen(QPen(separator_color, 1))
        painter.drawLine(separator_line)

        # draw arrow
        arrow = QPolygonF([QPointF(-3, -1.5), QPointF(0.5, 2.5), QPointF(4, -1.5)])
        if option.direction == Qt.LeftToRight:
            arrow.translate(-2, 1)
        else:
            arrow.translate(+2, 1)
        pen_thickness = 1.6

        painter.setRenderHint(QPainter.Antialiasing, True)
        painter.translate(arrow_rect.center())

        painter.translate(0, +1)
        painter.setPen(QPen(self.calc_light_color(background_color), pen_thickness, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        painter.drawPolyline(arrow)
        painter.translate(0, -1)
        painter.setPen(QPen(self.deco_color(background_color, text_color), pen_thickness, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        painter.drawPolyline(arrow)

        painter.restore()
Exemple #9
0
    def drawPath(self, startPoint, endPoint):
        path = QPainterPath()

        one = (QPointF(endPoint.x(), startPoint.y()) + startPoint) / 2
        two = (QPointF(startPoint.x(), endPoint.y()) + endPoint) / 2

        path.moveTo(startPoint)

        angle = math.pi / 2
        bLine1 = QLineF()
        bLine1.setP1(startPoint)

        if startPoint.x() > endPoint.x():
            dist = startPoint.x() - endPoint.x()
            one = (bLine1.p1() +
                   QPointF(math.sin(angle) * dist,
                           math.cos(angle) * dist))
            bLine1.setP1(endPoint)
            two = (bLine1.p1() +
                   QPointF(math.sin(angle) * dist,
                           math.cos(angle) * dist))

        path.cubicTo(one, two, endPoint)
        return path, QLineF(one, two)
Exemple #10
0
def arrow_path_concave(line, width):
    """
    Return a :class:`QPainterPath` of a pretty looking arrow.
    """
    path = QPainterPath()
    p1, p2 = line.p1(), line.p2()

    if p1 == p2:
        return path

    baseline = QLineF(line)
    # Require some minimum length.
    baseline.setLength(max(line.length() - width * 3, width * 3))

    start, end = baseline.p1(), baseline.p2()
    mid = (start + end) / 2.0
    normal = QLineF.fromPolar(1.0, baseline.angle() + 90).p2()

    path.moveTo(start)
    path.lineTo(start + (normal * width / 4.0))

    path.quadTo(mid + (normal * width / 4.0),
                end + (normal * width / 1.5))

    path.lineTo(end - (normal * width / 1.5))
    path.quadTo(mid - (normal * width / 4.0),
                start - (normal * width / 4.0))
    path.closeSubpath()

    arrow_head_len = width * 4
    arrow_head_angle = 50
    line_angle = line.angle() - 180

    angle_1 = line_angle - arrow_head_angle / 2.0
    angle_2 = line_angle + arrow_head_angle / 2.0

    points = [p2,
              p2 + QLineF.fromPolar(arrow_head_len, angle_1).p2(),
              baseline.p2(),
              p2 + QLineF.fromPolar(arrow_head_len, angle_2).p2(),
              p2]

    poly = QPolygonF(points)
    path_head = QPainterPath()
    path_head.addPolygon(poly)
    path = path.united(path_head)
    return path
Exemple #11
0
def arrow_path_concave(line, width):
    """
    Return a :class:`QPainterPath` of a pretty looking arrow.
    """
    path = QPainterPath()
    p1, p2 = line.p1(), line.p2()

    if p1 == p2:
        return path

    baseline = QLineF(line)
    # Require some minimum length.
    baseline.setLength(max(line.length() - width * 3, width * 3))

    start, end = baseline.p1(), baseline.p2()
    mid = (start + end) / 2.0
    normal = QLineF.fromPolar(1.0, baseline.angle() + 90).p2()

    path.moveTo(start)
    path.lineTo(start + (normal * width / 4.0))

    path.quadTo(mid + (normal * width / 4.0), end + (normal * width / 1.5))

    path.lineTo(end - (normal * width / 1.5))
    path.quadTo(mid - (normal * width / 4.0), start - (normal * width / 4.0))
    path.closeSubpath()

    arrow_head_len = width * 4
    arrow_head_angle = 50
    line_angle = line.angle() - 180

    angle_1 = line_angle - arrow_head_angle / 2.0
    angle_2 = line_angle + arrow_head_angle / 2.0

    points = [
        p2, p2 + QLineF.fromPolar(arrow_head_len, angle_1).p2(),
        baseline.p2(), p2 + QLineF.fromPolar(arrow_head_len, angle_2).p2(), p2
    ]

    poly = QPolygonF(points)
    path_head = QPainterPath()
    path_head.addPolygon(poly)
    path = path.united(path_head)
    return path
Exemple #12
0
    def drawPath(self, startPoint, endPoint):
        path = QPainterPath()

        one = (QPointF(endPoint.x(), startPoint.y()) + startPoint) / 2
        two = (QPointF(startPoint.x(), endPoint.y()) + endPoint) / 2

        path.moveTo(startPoint)

        if startPoint.x() > endPoint.x():
            dist = (startPoint.x() - endPoint.x()) * 2

            tLine = QLineF((dist / 2), 0.0, -(dist / 2), 0.0).translated(QLineF(startPoint, endPoint).pointAt(0.5))

            one = tLine.p1()
            two = tLine.p2()

        path.cubicTo(one, two, endPoint)

        self.__path = path
        return path, QLineF(one, two)
Exemple #13
0
def arrow_path_plain(line, width):
    """
    Return an :class:`QPainterPath` of a plain looking arrow.
    """
    path = QPainterPath()
    p1, p2 = line.p1(), line.p2()

    if p1 == p2:
        return path

    baseline = QLineF(line)
    # Require some minimum length.
    baseline.setLength(max(line.length() - width * 3, width * 3))
    path.moveTo(baseline.p1())
    path.lineTo(baseline.p2())

    stroker = QPainterPathStroker()
    stroker.setWidth(width)
    path = stroker.createStroke(path)

    arrow_head_len = width * 4
    arrow_head_angle = 50
    line_angle = line.angle() - 180

    angle_1 = line_angle - arrow_head_angle / 2.0
    angle_2 = line_angle + arrow_head_angle / 2.0

    points = [
        p2,
        p2 + QLineF.fromPolar(arrow_head_len, angle_1).p2(),
        p2 + QLineF.fromPolar(arrow_head_len, angle_2).p2(),
        p2,
    ]

    poly = QPolygonF(points)
    path_head = QPainterPath()
    path_head.addPolygon(poly)
    path = path.united(path_head)
    return path
Exemple #14
0
def arrow_path_plain(line, width):
    """
    Return an :class:`QPainterPath` of a plain looking arrow.
    """
    path = QPainterPath()
    p1, p2 = line.p1(), line.p2()

    if p1 == p2:
        return path

    baseline = QLineF(line)
    # Require some minimum length.
    baseline.setLength(max(line.length() - width * 3, width * 3))
    path.moveTo(baseline.p1())
    path.lineTo(baseline.p2())

    stroker = QPainterPathStroker()
    stroker.setWidth(width)
    path = stroker.createStroke(path)

    arrow_head_len = width * 4
    arrow_head_angle = 50
    line_angle = line.angle() - 180

    angle_1 = line_angle - arrow_head_angle / 2.0
    angle_2 = line_angle + arrow_head_angle / 2.0

    points = [
        p2, p2 + QLineF.fromPolar(arrow_head_len, angle_1).p2(),
        p2 + QLineF.fromPolar(arrow_head_len, angle_2).p2(), p2
    ]

    poly = QPolygonF(points)
    path_head = QPainterPath()
    path_head.addPolygon(poly)
    path = path.united(path_head)
    return path
Exemple #15
0
    def adjustGeometry(self):
        """
        Adjust the widget geometry to exactly fit the arrow inside
        while preserving the arrow path scene geometry.

        """
        # local system coordinate
        geom = self.geometry().translated(-self.pos())
        line = self.__line

        arrow_rect = self.__arrowItem.shape().boundingRect()

        if geom.isNull() and not line.isNull():
            geom = QRectF(0, 0, 1, 1)

        if not (geom.contains(arrow_rect)):
            geom = geom.united(arrow_rect)

        geom = geom.intersected(arrow_rect)
        diff = geom.topLeft()
        line = QLineF(line.p1() - diff, line.p2() - diff)
        geom.translate(self.pos())
        self.setGeometry(geom)
        self.setLine(line)
Exemple #16
0
    def adjustGeometry(self):
        """
        Adjust the widget geometry to exactly fit the arrow inside
        while preserving the arrow path scene geometry.

        """
        # local system coordinate
        geom = self.geometry().translated(-self.pos())
        line = self.__line

        arrow_rect = self.__arrowItem.shape().boundingRect()

        if geom.isNull() and not line.isNull():
            geom = QRectF(0, 0, 1, 1)

        if not (geom.contains(arrow_rect)):
            geom = geom.united(arrow_rect)

        geom = geom.intersected(arrow_rect)
        diff = geom.topLeft()
        line = QLineF(line.p1() - diff, line.p2() - diff)
        geom.translate(self.pos())
        self.setGeometry(geom)
        self.setLine(line)
Exemple #17
0
class EEdge(QGraphicsObject):
    def __init__(self, head, tail, uuid):
        QGraphicsObject.__init__(self)

        if not issubclass(head.__class__, dict) and not isinstance(tail.__class__, dict):
            raise AttributeError

        self.setZValue(0.0)

        self.__kId = uuid
        self.__head = head
        self.__tail = tail

        if  head[ENode.kGuiAttributeType].match(EAttribute.kTypeInput):
            self.__head = tail
            self.__tail = head

        self.__head[ENode.kGuiAttributeParent].onMove.connect(self.update)
        self.__tail[ENode.kGuiAttributeParent].onMove.connect(self.update)

        self.__headPoint = QPointF(0.0, 0.0)
        self.__tailPoint = QPointF(0.0, 0.0)

        self.__pen = QPen(QColor(43, 43, 43), 2, Qt.SolidLine)

        self.update()

    @property
    def Id(self):
        return self.__kId

    @property
    def Head(self):
        return self.__head

    @property
    def Tail(self):
        return self.__tail

    def pen(self):
        return self.__pen

    def setPen(self, pen):
        if not isinstance(pen, QPen):
            raise AttributeError

        self.__pen = pen

    def update(self):

        QGraphicsObject.prepareGeometryChange(self)

        self.__headPoint = self.mapFromItem(self.__head[ENode.kGuiAttributeParent],
                                            self.__head[ENode.kGuiAttributePlug])

        self.__tailPoint = self.mapFromItem(self.__tail[ENode.kGuiAttributeParent],
                                            self.__tail[ENode.kGuiAttributePlug])

        self.__headOffsetLine = QLineF(self.__headPoint, QPointF(self.__headPoint.x() + 15, self.__headPoint.y()))
        self.__tailOffsetLine = QLineF(self.__tailPoint, QPointF(self.__tailPoint.x() - 15, self.__tailPoint.y()))

        line = QLineF(self.__headPoint, self.__tailPoint)
        self.__line = line

    def boundingRect(self):
        extra = (self.pen().width() * 64) / 2
        return QRectF(self.__line.p1(),
                      QSizeF(self.__line.p2().x() - self.__line.p1().x(),
                             self.__line.p2().y() - self.__line.p1().y())).normalized().adjusted(-extra,
                                                                                                 -extra,
                                                                                                 extra,
                                                                                                 extra)

    def shape(self):
        return QGraphicsObject.shape(self)

    def drawPath(self, startPoint, endPoint):
        path = QPainterPath()

        one = (QPointF(endPoint.x(), startPoint.y()) + startPoint) / 2
        two = (QPointF(startPoint.x(), endPoint.y()) + endPoint) / 2

        path.moveTo(startPoint)

        angle = math.pi / 2
        bLine1 = QLineF()
        bLine1.setP1(startPoint)

        if startPoint.x() > endPoint.x():
            dist = startPoint.x() - endPoint.x()
            one = (bLine1.p1() + QPointF(math.sin(angle) * dist,  math.cos(angle) * dist))
            bLine1.setP1(endPoint)
            two = (bLine1.p1() + QPointF(math.sin(angle) * dist,  math.cos(angle) * dist))

        path.cubicTo(one, two,  endPoint)
        return path, QLineF(one, two)

    def paint(self, painter, option, widget=None):

        painter.setPen(self.pen())

        headCenter = self.mapFromItem(self.__head[ENode.kGuiAttributeParent],
                                      self.__head[ENode.kGuiAttributeParent].boundingRect().center())

        tailCenter = self.mapFromItem(self.__tail[ENode.kGuiAttributeParent],
                                      self.__tail[ENode.kGuiAttributeParent].boundingRect().center())

        centerPoint = QLineF(headCenter, tailCenter).pointAt(0.5)

        centerPoint.setX(self.__headOffsetLine.p2().x())
        lineFromHead = QLineF(self.__headOffsetLine.p2(), centerPoint)
        centerPoint.setX(self.__tailOffsetLine.p2().x())
        lineFromTail = QLineF(self.__tailOffsetLine.p2(), centerPoint)

        painter.drawPath(self.drawPath(self.__headOffsetLine.p1(), self.__tailOffsetLine.p1())[0])
    def paint(self, painter, option, widget):
        if not self.source or not self.dest:
            return

        # Draw the line itself.
        line = QLineF(self.sourcePoint, self.destPoint)

        if line.length() == 0.0:
            return

        palette = QPalette()

        self.setZValue(self.state)

        if self.state == 3:
            pen = QPen(Qt.red, 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
        if self.state == 2:
            pen = QPen(Qt.red, 2, Qt.DashLine, Qt.RoundCap, Qt.RoundJoin)
        elif self.state == 1:
            pen = QPen(palette.color(QPalette.Disabled, QPalette.WindowText),
                       0, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
        elif self.state == 0:
            pen = QPen()
            pen.setBrush(QBrush(Qt.NoBrush))

        painter.setPen(pen)

        painter.drawLine(line)

        angle = math.acos(line.dx() / line.length())
        if line.dy() >= 0:
            angle = Edge.TwoPi - angle

        # draw arrowheads
        if self.state == 2 or self.state == 3:

            # Draw the arrows if there's enough room.
            sourceArrowP1 = self.sourcePoint + QPointF(
                math.sin(angle + Edge.Pi / 3) * self.arrowSize,
                math.cos(angle + Edge.Pi / 3) * self.arrowSize)
            sourceArrowP2 = self.sourcePoint + QPointF(
                math.sin(angle + Edge.Pi - Edge.Pi / 3) * self.arrowSize,
                math.cos(angle + Edge.Pi - Edge.Pi / 3) * self.arrowSize)
            destArrowP1 = self.destPoint + QPointF(
                math.sin(angle - Edge.Pi / 3) * self.arrowSize,
                math.cos(angle - Edge.Pi / 3) * self.arrowSize)
            destArrowP2 = self.destPoint + QPointF(
                math.sin(angle - Edge.Pi + Edge.Pi / 3) * self.arrowSize,
                math.cos(angle - Edge.Pi + Edge.Pi / 3) * self.arrowSize)

            painter.setPen(
                QPen(Qt.red, 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
            painter.setBrush(QBrush(Qt.red, Qt.SolidPattern))
            painter.drawPolygon(
                QPolygonF([line.p1(), sourceArrowP1, sourceArrowP2]))
            #painter.drawPolygon(QPolygonF([line.p2(), destArrowP1, destArrowP2]))

        if self.state > 0 and self.source > self.dest:
            point = QPointF((self.sourcePoint.x() + self.destPoint.x()) / 2,
                            (self.sourcePoint.y() + self.destPoint.y()) / 2)
            point = QPointF(point.x() + math.sin(angle) * 16,
                            point.y() + math.cos(angle) * 16)
            painter.drawText(point, self.text)
Exemple #19
0
class ControlPointLine(QGraphicsObject):

    lineChanged = Signal(QLineF)
    lineEdited = Signal(QLineF)

    def __init__(self, parent=None, **kwargs):
        QGraphicsObject.__init__(self, parent, **kwargs)
        self.setFlag(QGraphicsItem.ItemHasNoContents)
        self.setFlag(QGraphicsItem.ItemIsFocusable)

        self.__line = QLineF()
        self.__points = \
            [ControlPoint(self, ControlPoint.TopLeft),  # TopLeft is line start
             ControlPoint(self, ControlPoint.BottomRight)  # line end
             ]

        self.__activeControl = None

        if self.scene():
            self.__installFilter()

        for p in self.__points:
            p.setFlag(QGraphicsItem.ItemIsFocusable)
            p.setFocusProxy(self)

    def setLine(self, line):
        if not isinstance(line, QLineF):
            raise TypeError()

        if line != self.__line:
            self.__line = line
            self.__pointsLayout()
            self.lineChanged.emit(line)

    def line(self):
        return self.__line

    def isControlActive(self):
        """Return the state of the control. True if the control is
        active (user is dragging one of the points) False otherwise.

        """
        return self.__activeControl is not None

    def __installFilter(self):
        for p in self.__points:
            p.installSceneEventFilter(self)

    def itemChange(self, change, value):
        if change == QGraphicsItem.ItemSceneHasChanged:
            if self.scene():
                self.__installFilter()
        return QGraphicsObject.itemChange(self, change, value)

    def sceneEventFilter(self, obj, event):
        try:
            obj = toGraphicsObjectIfPossible(obj)
            if isinstance(obj, ControlPoint):
                etype = event.type()
                if etype == QEvent.GraphicsSceneMousePress:
                    self.__setActiveControl(obj)
                elif etype == QEvent.GraphicsSceneMouseRelease:
                    self.__setActiveControl(None)

            return QGraphicsObject.sceneEventFilter(self, obj, event)
        except Exception:
            log.error("", exc_info=True)

    def __pointsLayout(self):
        self.__points[0].setPos(self.__line.p1())
        self.__points[1].setPos(self.__line.p2())

    def __setActiveControl(self, control):
        if self.__activeControl != control:
            if self.__activeControl is not None:
                self.__activeControl.positionChanged[QPointF].disconnect(
                    self.__activeControlMoved
                )

            self.__activeControl = control

            if control is not None:
                control.positionChanged[QPointF].connect(
                    self.__activeControlMoved
                )

    def __activeControlMoved(self, pos):
        line = QLineF(self.__line)
        control = self.__activeControl
        if control.anchor() == ControlPoint.TopLeft:
            line.setP1(pos)
        elif control.anchor() == ControlPoint.BottomRight:
            line.setP2(pos)

        if self.__line != line:
            self.blockSignals(True)
            self.setLine(line)
            self.blockSignals(False)
            self.lineEdited.emit(line)

    def boundingRect(self):
        return QRectF()
Exemple #20
0
    def render(o):
        path = QPainterPath()

        # unit_x gives offset and direction of the x base vector. Start and end should be the grid points.

        # move the endpoints inwards an unnoticable bit, so that the intersection detector
        # won't trip on the common endpoint.
        u_x = QLineF(o.unit_x.pointAt(0.0001), o.unit_x.pointAt(0.9999))

        path.moveTo(u_x.p1())

        if o.is_straight:
            path.lineTo(u_x.p2())
            return path

        if o.flipped:
            u_x = QLineF(u_x.p2(), u_x.p1())

        u_y = u_x.normalVector()
        # move y unit to start at (0,0).
        u_y.translate(-u_y.p1())

        scaling = o.length_base / u_x.length() * o.size_correction
        if o.basewidth * scaling > 0.8:
            # Plug is too large for the edge length. Make it smaller.
            scaling = 0.8 / o.basewidth

        # some magic numbers here... carefully fine-tuned, better leave them as they are.
        ends_ctldist = 0.4
        #base_lcdist = 0.1 * scaling
        base_ucdist = 0.05 * scaling
        knob_lcdist = 0.6 * o.knobsize * scaling
        knob_ucdist = 0.8 * o.knobsize * scaling

        # set up piece -- here is where the really interesting stuff happens.
        # We will work from the ends inwards, so that symmetry counterparts are adjacent.
        # The QLine.pointAt function is used to transform everything into the coordinate
        # space defined by the us.
        # -- end points

        r1y = ends_ctldist * o.basepos * dsin(o.startangle)
        q6y = ends_ctldist * (1. - o.basepos) * dsin(o.endangle)
        p1 = u_x.p1()
        p6 = u_x.p2()
        r1 = u_x.pointAt(
            ends_ctldist * o.basepos * dcos(o.startangle)) + u_y.pointAt(r1y)
        q6 = u_x.pointAt(1. - ends_ctldist * (1. - o.basepos) *
                         dcos(o.endangle)) + u_y.pointAt(q6y)

        # -- base points
        p2x = o.basepos - 0.5 * o.basewidth * scaling
        p5x = o.basepos + 0.5 * o.basewidth * scaling

        if p2x < 0.1 or p5x > 0.9:
            # knob to large. center knob on the edge. (o.basewidth * scaling < 0.8 -- see above)
            p2x = 0.5 - 0.5 * o.basewidth * scaling
            p5x = 0.5 + 0.5 * o.basewidth * scaling

        #base_y = r1y > q6y ? r1y : q6y
        #base_y = 0.5*(r1y + q6y)
        base_y = -o.baseroundness * ends_ctldist * min(p2x, 1. - p5x)
        if base_y > 0:
            base_y = 0

        base_lcy = base_y * 2.0

        base_y += base_ucdist / 2
        base_lcy -= base_ucdist / 2
        #base_lcy = r1y
        #if (q6y < r1y): base_lcy = q6y

        # at least -base_ucdist from base_y
        #if (base_lcy > base_y - base_ucdist): base_lcy = base_y-base_ucdist

        q2 = u_x.pointAt(p2x) + u_y.pointAt(base_lcy)
        r5 = u_x.pointAt(p5x) + u_y.pointAt(base_lcy)
        p2 = u_x.pointAt(p2x) + u_y.pointAt(base_y)
        p5 = u_x.pointAt(p5x) + u_y.pointAt(base_y)
        r2 = u_x.pointAt(p2x) + u_y.pointAt(base_y + base_ucdist)
        q5 = u_x.pointAt(p5x) + u_y.pointAt(base_y + base_ucdist)

        if o._is_plugless:
            if not o.flipped:
                path.cubicTo(r1, q2, p2)
                path.cubicTo(r2, q5, p5)
                path.cubicTo(r5, q6, p6)
            else:
                path.cubicTo(q6, r5, p5)
                path.cubicTo(q5, r2, p2)
                path.cubicTo(q2, r1, p1)
            return path

        # -- knob points
        p3x = p2x - o.knobsize * scaling * dsin(o.knobangle - o.knobtilt)
        p4x = p5x + o.knobsize * scaling * dsin(o.knobangle + o.knobtilt)
        # for the y coordinate, knobtilt sign was swapped. Knobs look better this way...
        # like x offset from base points y, but that is 0.
        p3y = o.knobsize * scaling * dcos(o.knobangle + o.knobtilt) + base_y
        p4y = o.knobsize * scaling * dcos(o.knobangle - o.knobtilt) + base_y

        q3 = u_x.pointAt(p3x) + u_y.pointAt(p3y - knob_lcdist)
        r4 = u_x.pointAt(p4x) + u_y.pointAt(p4y - knob_lcdist)
        p3 = u_x.pointAt(p3x) + u_y.pointAt(p3y)
        p4 = u_x.pointAt(p4x) + u_y.pointAt(p4y)
        r3 = u_x.pointAt(p3x) + u_y.pointAt(p3y + knob_ucdist)
        q4 = u_x.pointAt(p4x) + u_y.pointAt(p4y + knob_ucdist)

        # done setting up. construct path.
        # if flipped, add points in reverse.
        if not o.flipped:
            path.cubicTo(r1, q2, p2)
            path.cubicTo(r2, q3, p3)
            path.cubicTo(r3, q4, p4)
            path.cubicTo(r4, q5, p5)
            path.cubicTo(r5, q6, p6)
        else:
            path.cubicTo(q6, r5, p5)
            path.cubicTo(q5, r4, p4)
            path.cubicTo(q4, r3, p3)
            path.cubicTo(q3, r2, p2)
            path.cubicTo(q2, r1, p1)
        return path
Exemple #21
0
class EEdge(QGraphicsObject):
    def __init__(self, head, tail, uuid):
        QGraphicsObject.__init__(self)

        if not issubclass(head.__class__, dict) and not isinstance(
                tail.__class__, dict):
            raise AttributeError

        self.setZValue(0.0)

        self.__kId = uuid
        self.__head = head
        self.__tail = tail

        if head[ENode.kGuiAttributeType].match(EAttribute.kTypeInput):
            self.__head = tail
            self.__tail = head

        self.__head[ENode.kGuiAttributeParent].onMove.connect(self.update)
        self.__tail[ENode.kGuiAttributeParent].onMove.connect(self.update)

        self.__headPoint = QPointF(0.0, 0.0)
        self.__tailPoint = QPointF(0.0, 0.0)

        self.__pen = QPen(QColor(43, 43, 43), 2, Qt.SolidLine)

        self.update()

    @property
    def Id(self):
        return self.__kId

    @property
    def Head(self):
        return self.__head

    @property
    def Tail(self):
        return self.__tail

    def pen(self):
        return self.__pen

    def setPen(self, pen):
        if not isinstance(pen, QPen):
            raise AttributeError

        self.__pen = pen

    def update(self):

        QGraphicsObject.prepareGeometryChange(self)

        self.__headPoint = self.mapFromItem(
            self.__head[ENode.kGuiAttributeParent],
            self.__head[ENode.kGuiAttributePlug])

        self.__tailPoint = self.mapFromItem(
            self.__tail[ENode.kGuiAttributeParent],
            self.__tail[ENode.kGuiAttributePlug])

        self.__headOffsetLine = QLineF(
            self.__headPoint,
            QPointF(self.__headPoint.x() + 15, self.__headPoint.y()))
        self.__tailOffsetLine = QLineF(
            self.__tailPoint,
            QPointF(self.__tailPoint.x() - 15, self.__tailPoint.y()))

        line = QLineF(self.__headPoint, self.__tailPoint)
        self.__line = line

    def boundingRect(self):
        extra = (self.pen().width() * 64) / 2
        return QRectF(
            self.__line.p1(),
            QSizeF(self.__line.p2().x() - self.__line.p1().x(),
                   self.__line.p2().y() -
                   self.__line.p1().y())).normalized().adjusted(
                       -extra, -extra, extra, extra)

    def shape(self):
        return QGraphicsObject.shape(self)

    def drawPath(self, startPoint, endPoint):
        path = QPainterPath()

        one = (QPointF(endPoint.x(), startPoint.y()) + startPoint) / 2
        two = (QPointF(startPoint.x(), endPoint.y()) + endPoint) / 2

        path.moveTo(startPoint)

        angle = math.pi / 2
        bLine1 = QLineF()
        bLine1.setP1(startPoint)

        if startPoint.x() > endPoint.x():
            dist = startPoint.x() - endPoint.x()
            one = (bLine1.p1() +
                   QPointF(math.sin(angle) * dist,
                           math.cos(angle) * dist))
            bLine1.setP1(endPoint)
            two = (bLine1.p1() +
                   QPointF(math.sin(angle) * dist,
                           math.cos(angle) * dist))

        path.cubicTo(one, two, endPoint)
        return path, QLineF(one, two)

    def paint(self, painter, option, widget=None):

        painter.setPen(self.pen())

        headCenter = self.mapFromItem(
            self.__head[ENode.kGuiAttributeParent],
            self.__head[ENode.kGuiAttributeParent].boundingRect().center())

        tailCenter = self.mapFromItem(
            self.__tail[ENode.kGuiAttributeParent],
            self.__tail[ENode.kGuiAttributeParent].boundingRect().center())

        centerPoint = QLineF(headCenter, tailCenter).pointAt(0.5)

        centerPoint.setX(self.__headOffsetLine.p2().x())
        lineFromHead = QLineF(self.__headOffsetLine.p2(), centerPoint)
        centerPoint.setX(self.__tailOffsetLine.p2().x())
        lineFromTail = QLineF(self.__tailOffsetLine.p2(), centerPoint)

        painter.drawPath(
            self.drawPath(self.__headOffsetLine.p1(),
                          self.__tailOffsetLine.p1())[0])
Exemple #22
0
    def update(self, zoom_only = False):
        self.update_ticks()
        line_color = self.plot.color(OWPalette.Axis)
        text_color = self.plot.color(OWPalette.Text)
        if not self.graph_line or not self.scene():
            return
        self.line_item.setLine(self.graph_line)
        self.line_item.setPen(line_color)
        if self.title:
            self.title_item.setHtml('<b>' + self.title + '</b>')
            self.title_item.setDefaultTextColor(text_color)
        if self.title_location == AxisMiddle:
            title_p = 0.5
        elif self.title_location == AxisEnd:
            title_p = 0.95
        else:
            title_p = 0.05
        title_pos = self.graph_line.pointAt(title_p)
        v = self.graph_line.normalVector().unitVector()

        dense_text = False
        if hasattr(self, 'title_margin'):
            offset = self.title_margin
        elif self._ticks:
            if self.should_be_expanded():
                offset = 55
                dense_text = True
            else:
                offset = 35
        else:
            offset = 10

        if self.title_above:
            title_pos = title_pos + (v.p2() - v.p1())*(offset + QFontMetrics(self.title_item.font()).height())
        else:
            title_pos = title_pos - (v.p2() - v.p1())*offset
        ## TODO: Move it according to self.label_pos
        self.title_item.setVisible(self.show_title)
        self.title_item.setRotation(-self.graph_line.angle())
        c = self.title_item.mapToParent(self.title_item.boundingRect().center())
        tl = self.title_item.mapToParent(self.title_item.boundingRect().topLeft())
        self.title_item.setPos(title_pos - c + tl)

        ## Arrows
        if not zoom_only:
            if self.start_arrow_item:
                self.scene().removeItem(self.start_arrow_item)
                self.start_arrow_item = None
            if self.end_arrow_item:
                self.scene().removeItem(self.end_arrow_item)
                self.end_arrow_item = None

        if self.arrows & AxisStart:
            if not zoom_only or not self.start_arrow_item:
                self.start_arrow_item = QGraphicsPathItem(self.arrow_path, self)
            self.start_arrow_item.setPos(self.graph_line.p1())
            self.start_arrow_item.setRotation(-self.graph_line.angle() + 180)
            self.start_arrow_item.setBrush(line_color)
            self.start_arrow_item.setPen(line_color)
        if self.arrows & AxisEnd:
            if not zoom_only or not self.end_arrow_item:
                self.end_arrow_item = QGraphicsPathItem(self.arrow_path, self)
            self.end_arrow_item.setPos(self.graph_line.p2())
            self.end_arrow_item.setRotation(-self.graph_line.angle())
            self.end_arrow_item.setBrush(line_color)
            self.end_arrow_item.setPen(line_color)

        ## Labels

        n = len(self._ticks)
        resize_plot_item_list(self.label_items, n, QGraphicsTextItem, self)
        resize_plot_item_list(self.label_bg_items, n, QGraphicsRectItem, self)
        resize_plot_item_list(self.tick_items, n, QGraphicsLineItem, self)

        test_rect = QRectF(self.graph_line.p1(),  self.graph_line.p2()).normalized()
        test_rect.adjust(-1, -1, 1, 1)

        n_v = self.graph_line.normalVector().unitVector()
        if self.title_above:
            n_p = n_v.p2() - n_v.p1()
        else:
            n_p = n_v.p1() - n_v.p2()
        l_v = self.graph_line.unitVector()
        l_p = l_v.p2() - l_v.p1()
        for i in range(n):
            pos, text, size, step = self._ticks[i]
            hs = 0.5 * step
            tick_pos = self.map_to_graph( pos )
            if not test_rect.contains(tick_pos):
                self.tick_items[i].setVisible(False)
                self.label_items[i].setVisible(False)
                continue
            item = self.label_items[i]
            item.setVisible(True)
            if not zoom_only:
                if self.id in XAxes or getattr(self, 'is_horizontal', False):
                    item.setHtml( '<center>' + Qt.escape(text.strip()) + '</center>')
                else:
                    item.setHtml(Qt.escape(text.strip()))

            item.setTextWidth(-1)
            text_angle = 0
            if dense_text:
                w = min(item.boundingRect().width(), self.max_text_width)
                item.setTextWidth(w)
                if self.title_above:
                    label_pos = tick_pos + n_p * (w + self.text_margin) + l_p * item.boundingRect().height()/2
                else:
                    label_pos = tick_pos + n_p * self.text_margin + l_p * item.boundingRect().height()/2
                text_angle = -90 if self.title_above else 90
            else:
                w = min(item.boundingRect().width(), QLineF(self.map_to_graph(pos - hs), self.map_to_graph(pos + hs) ).length())
                label_pos = tick_pos + n_p * self.text_margin - l_p * w/2
                item.setTextWidth(w)

            if not self.always_horizontal_text:
                if self.title_above:
                    item.setRotation(-self.graph_line.angle() - text_angle)
                else:
                    item.setRotation(self.graph_line.angle() - text_angle)

            item.setPos(label_pos)
            item.setDefaultTextColor(text_color)

            self.label_bg_items[i].setRect(item.boundingRect())
            self.label_bg_items[i].setPen(QPen(Qt.NoPen))
            self.label_bg_items[i].setBrush(self.plot.color(OWPalette.Canvas))

            item = self.tick_items[i]
            item.setVisible(True)
            tick_line = QLineF(v)
            tick_line.translate(-tick_line.p1())
            tick_line.setLength(size)
            if self.title_above:
                tick_line.setAngle(tick_line.angle() + 180)
            item.setLine( tick_line )
            item.setPen(line_color)
            item.setPos(self.map_to_graph(pos))
Exemple #23
0
 def crop_line(self, line, line_point):
     global_rect = self.globalBoundingRect()
     
     # Go to local coordinate system - ellipse equations assume ellipse is centered on (0,0)        
     local_trans = global_rect.center()
     local_line = QLineF(line.p1() - local_trans, line.p2() - local_trans)
     
     if(local_line.dx() == 0):
         return line
     
     # Solve line equation        
     e_a = ((local_line.p2().y() - local_line.p1().y()) / 
               (local_line.p2().x() - local_line.p1().x()))
     
     e_b = local_line.p1().y() - e_a * local_line.p1().x()
     
     # ellipse params 
     e_c = global_rect.width()/2
     e_d = global_rect.height()/2
     
     # check condition
     if(e_c * e_d == 0):
         return line
     
     # precalculate things that are used more than once
     # a^2, b^2 ...
     ak = math.pow(e_a, 2)
     bk = math.pow(e_b, 2)
     ck = math.pow(e_c, 2)
     dk = math.pow(e_d, 2)
     
     # check another condition
     if((ak * ck + dk) == 0):
         return line
     
     # a^2*c^2, c^2*d^2
     akck = ak * ck
     ckdk = ck * dk
     
     # a*b*c^2
     abck = e_a*e_b*ck
     
     # parts of denomiator and numerator of x
     denom = (akck + dk)
     numer =  math.sqrt(ck*dk*(akck-bk+dk))
     
     # Decide which points to take
     xrel = (line.p1().x() > line.p2().x())
     yrel = (line.p1().y() > line.p2().y())
     
     if(line_point != 0):
         xrel = not xrel
         yrel = not yrel
     
     if((xrel and yrel) or (xrel and not yrel)):
         x1 = (-numer - abck) / denom
         y1 = (e_b*dk - e_a*math.sqrt(-ckdk*(-akck+bk-dk))) / denom
         
         intersectionPoint = QPointF(x1, y1)
     elif((not xrel and yrel) or (not xrel and not yrel)):
         x2 = (numer - abck) / denom         
         y2 = -(e_b*dk - e_a*math.sqrt(-ckdk*(-akck+bk-dk))) / denom  
     
         intersectionPoint = QPointF(x2, y2)
 
     # Go back to global coordinate system
     intersectionPoint = intersectionPoint + local_trans
 
     if(line_point == 0):
         return QLineF(intersectionPoint, line.p2())
     else:
         return QLineF(line.p1(), intersectionPoint)  
     
     return line
Exemple #24
0
class EEdge(QGraphicsObject):
    def __init__(self, head, tail, uuid, arrowed=False):
        QGraphicsObject.__init__(self)

        self.__arrowed = arrowed

        if not issubclass(head.__class__, dict) and not isinstance(tail.__class__, dict):
            raise AttributeError

        self.setZValue(0.0)

        self.__kId = uuid
        self.__head = head
        self.__tail = tail

        self.__path = QPainterPath()
        self.__headPoint = QPointF(0.0, 0.0)
        self.__tailPoint = QPointF(0.0, 0.0)

        self.__head[ENode.kGuiAttributeParent].onMove.connect(self.update)
        self.__tail[ENode.kGuiAttributeParent].onMove.connect(self.update)

        self.__pen = QPen(QColor(43, 43, 43), 2, Qt.SolidLine)

        self.update()

    @property
    def Id(self):
        return self.__kId

    @property
    def Line(self):
        return QLineF(self.__headPoint, self.__tailPoint)

    @property
    def Head(self):
        return self.__head

    @Head.setter
    def Head(self, newHead):
        self.__head = newHead

    @property
    def Tail(self):
        return self.__tail

    @Tail.setter
    def Tail(self, newTail):
        self.__tail = newTail

    def pen(self):
        return self.__pen

    def setPen(self, pen):
        if not isinstance(pen, QPen):
            raise AttributeError

        self.__pen = pen

    def update(self):

        QGraphicsObject.prepareGeometryChange(self)

        self.__headPoint = self.mapFromItem(self.__head[ENode.kGuiAttributeParent],
                                            self.__head[ENode.kGuiAttributePlug])

        self.__tailPoint = self.mapFromItem(self.__tail[ENode.kGuiAttributeParent],
                                            self.__tail[ENode.kGuiAttributePlug])

        self.__headOffsetLine = QLineF(self.__headPoint, QPointF(self.__headPoint.x() + 15, self.__headPoint.y()))
        self.__tailOffsetLine = QLineF(self.__tailPoint, QPointF(self.__tailPoint.x() - 15, self.__tailPoint.y()))

        line = QLineF(self.__headPoint, self.__tailPoint)
        self.__line = line

    def boundingRect(self):
        extra = (self.pen().width() * 64) / 2
        return QRectF(self.__line.p1(),
                      QSizeF(self.__line.p2().x() - self.__line.p1().x(),
                             self.__line.p2().y() - self.__line.p1().y())).normalized().adjusted(-extra,
                                                                                                 -extra,
                                                                                                 extra,
                                                                                                 extra)

    def shape(self):
        if self.__arrowed:
            return QGraphicsObject.shape(self)

        return QPainterPath(self.__path)

    def getIntersectPoint(self, polygon, point1, point2):

        p1 = polygon[0] + point1
        intersectPoint = QPointF()

        for i in polygon:
            p2 = i + point2
            polyLine = QLineF(p1, p2)

            intersectType = polyLine.intersect(QLineF(point1, point2), intersectPoint)

            if intersectType == QLineF.BoundedIntersection:
                break

            p1 = p2

        return intersectPoint

    def getArrow(self, line):

        Pi = math.pi
        TwoPi = 2.0 * Pi

        arrowSize = 14

        if line.length() > 0:

            angle = math.acos(line.dx() / line.length())
            if line.dy() >= 0:
                angle = TwoPi - angle

            sourceArrowP1 = line.p1() + QPointF(math.sin(angle + Pi / 3) * arrowSize,
                                                math.cos(angle + Pi / 3) * arrowSize)
            sourceArrowP2 = line.p1() + QPointF(math.sin(angle + Pi - Pi / 3) * arrowSize,
                                                math.cos(angle + Pi - Pi / 3) * arrowSize)
            destinationArrowP1 = line.p2() + QPointF(math.sin(angle - Pi / 3) * arrowSize,
                                                     math.cos(angle - Pi / 3) * arrowSize)
            destinationArrowP2 = line.p2() + QPointF(math.sin(angle - Pi + Pi / 3) * arrowSize,
                                                     math.cos(angle - Pi + Pi / 3) * arrowSize)

            arrows = [QPolygonF([line.p1(), sourceArrowP1, sourceArrowP2]),
                      QPolygonF([line.p2(), destinationArrowP1, destinationArrowP2])]

            return arrows[0]

        return QPolygonF()

    def drawPath(self, startPoint, endPoint):
        path = QPainterPath()

        one = (QPointF(endPoint.x(), startPoint.y()) + startPoint) / 2
        two = (QPointF(startPoint.x(), endPoint.y()) + endPoint) / 2

        path.moveTo(startPoint)

        if startPoint.x() > endPoint.x():
            dist = (startPoint.x() - endPoint.x()) * 2

            tLine = QLineF((dist / 2), 0.0, -(dist / 2), 0.0).translated(QLineF(startPoint, endPoint).pointAt(0.5))

            one = tLine.p1()
            two = tLine.p2()

        path.cubicTo(one, two, endPoint)

        self.__path = path
        return path, QLineF(one, two)

    def paint(self, painter, option, widget=None):

        painter.setPen(self.pen())

        if not self.__arrowed:
            headCenter = self.mapFromItem(self.__head[ENode.kGuiAttributeParent],
                                          self.__head[ENode.kGuiAttributeParent].boundingRect().center())

            tailCenter = self.mapFromItem(self.__tail[ENode.kGuiAttributeParent],
                                          self.__tail[ENode.kGuiAttributeParent].boundingRect().center())

            centerPoint = QLineF(headCenter, tailCenter).pointAt(0.5)

            centerPoint.setX(self.__headOffsetLine.p2().x())
            centerPoint.setX(self.__tailOffsetLine.p2().x())

            painter.drawPath(self.drawPath(self.__headOffsetLine.p1(), self.__tailOffsetLine.p1())[0])

        else:

            painter.drawLine(self.__line)
            painter.setPen(Qt.NoPen)
            painter.setBrush(QColor(43, 43, 43))

            headCutPoint = self.getIntersectPoint(self.__head[ENode.kGuiAttributeParent].Polygon,
                                                  self.__line.p1(), self.__line.p2())

            tailCutPoint = self.getIntersectPoint(self.__tail[ENode.kGuiAttributeParent].Polygon,
                                                  self.__line.p2(), self.__line.p1())

            painter.drawPolygon(self.getArrow(QLineF(headCutPoint, tailCutPoint)))
Exemple #25
0
class SliderLine(QGraphicsObject):
    """A movable slider line."""
    valueChanged = Signal(float)

    linePressed = Signal()
    lineMoved = Signal()
    lineReleased = Signal()
    rangeChanged = Signal(float, float)

    def __init__(self,
                 parent=None,
                 orientation=Qt.Vertical,
                 value=0.0,
                 length=10.0,
                 **kwargs):
        self._orientation = orientation
        self._value = value
        self._length = length
        self._min = 0.0
        self._max = 1.0
        self._line = QLineF()
        self._pen = QPen()
        super().__init__(parent, **kwargs)

        self.setAcceptedMouseButtons(Qt.LeftButton)
        self.setPen(make_pen(brush=QColor(50, 50, 50), width=1, cosmetic=True))

        if self._orientation == Qt.Vertical:
            self.setCursor(Qt.SizeVerCursor)
        else:
            self.setCursor(Qt.SizeHorCursor)

    def setPen(self, pen):
        pen = QPen(pen)
        if self._pen != pen:
            self.prepareGeometryChange()
            self._pen = pen
            self._line = None
            self.update()

    def pen(self):
        return QPen(self._pen)

    def setValue(self, value):
        value = min(max(value, self._min), self._max)

        if self._value != value:
            self.prepareGeometryChange()
            self._value = value
            self._line = None
            self.valueChanged.emit(value)

    def value(self):
        return self._value

    def setRange(self, minval, maxval):
        maxval = max(minval, maxval)
        if minval != self._min or maxval != self._max:
            self._min = minval
            self._max = maxval
            self.rangeChanged.emit(minval, maxval)
            self.setValue(self._value)

    def setLength(self, length):
        if self._length != length:
            self.prepareGeometryChange()
            self._length = length
            self._line = None

    def length(self):
        return self._length

    def setOrientation(self, orientation):
        if self._orientation != orientation:
            self.prepareGeometryChange()
            self._orientation = orientation
            self._line = None
            if self._orientation == Qt.Vertical:
                self.setCursor(Qt.SizeVerCursor)
            else:
                self.setCursor(Qt.SizeHorCursor)

    def mousePressEvent(self, event):
        event.accept()
        self.linePressed.emit()

    def mouseMoveEvent(self, event):
        pos = event.pos()
        if self._orientation == Qt.Vertical:
            self.setValue(pos.y())
        else:
            self.setValue(pos.x())
        self.lineMoved.emit()
        event.accept()

    def mouseReleaseEvent(self, event):
        if self._orientation == Qt.Vertical:
            self.setValue(event.pos().y())
        else:
            self.setValue(event.pos().x())
        self.lineReleased.emit()
        event.accept()

    def boundingRect(self):
        if self._line is None:
            if self._orientation == Qt.Vertical:
                self._line = QLineF(0, self._value, self._length, self._value)
            else:
                self._line = QLineF(self._value, 0, self._value, self._length)
        r = QRectF(self._line.p1(), self._line.p2())
        penw = self.pen().width()
        return r.adjusted(-penw, -penw, penw, penw)

    def paint(self, painter, *args):
        if self._line is None:
            self.boundingRect()

        painter.save()
        painter.setPen(self.pen())
        painter.drawLine(self._line)
        painter.restore()
Exemple #26
0
    def update(self, zoom_only=False):
        self.update_ticks()
        line_color = self.plot.color(OWPalette.Axis)
        text_color = self.plot.color(OWPalette.Text)
        if not self.graph_line or not self.scene():
            return
        self.line_item.setLine(self.graph_line)
        self.line_item.setPen(line_color)
        if self.title:
            self.title_item.setHtml('<b>' + self.title + '</b>')
            self.title_item.setDefaultTextColor(text_color)
        if self.title_location == AxisMiddle:
            title_p = 0.5
        elif self.title_location == AxisEnd:
            title_p = 0.95
        else:
            title_p = 0.05
        title_pos = self.graph_line.pointAt(title_p)
        v = self.graph_line.normalVector().unitVector()

        dense_text = False
        if hasattr(self, 'title_margin'):
            offset = self.title_margin
        elif self._ticks:
            if self.should_be_expanded():
                offset = 55
                dense_text = True
            else:
                offset = 35
        else:
            offset = 10

        if self.title_above:
            title_pos = title_pos + (v.p2() - v.p1()) * (
                offset + QFontMetrics(self.title_item.font()).height())
        else:
            title_pos = title_pos - (v.p2() - v.p1()) * offset
        ## TODO: Move it according to self.label_pos
        self.title_item.setVisible(self.show_title)
        self.title_item.setRotation(-self.graph_line.angle())
        c = self.title_item.mapToParent(
            self.title_item.boundingRect().center())
        tl = self.title_item.mapToParent(
            self.title_item.boundingRect().topLeft())
        self.title_item.setPos(title_pos - c + tl)

        ## Arrows
        if not zoom_only:
            if self.start_arrow_item:
                self.scene().removeItem(self.start_arrow_item)
                self.start_arrow_item = None
            if self.end_arrow_item:
                self.scene().removeItem(self.end_arrow_item)
                self.end_arrow_item = None

        if self.arrows & AxisStart:
            if not zoom_only or not self.start_arrow_item:
                self.start_arrow_item = QGraphicsPathItem(
                    self.arrow_path, self)
            self.start_arrow_item.setPos(self.graph_line.p1())
            self.start_arrow_item.setRotation(-self.graph_line.angle() + 180)
            self.start_arrow_item.setBrush(line_color)
            self.start_arrow_item.setPen(line_color)
        if self.arrows & AxisEnd:
            if not zoom_only or not self.end_arrow_item:
                self.end_arrow_item = QGraphicsPathItem(self.arrow_path, self)
            self.end_arrow_item.setPos(self.graph_line.p2())
            self.end_arrow_item.setRotation(-self.graph_line.angle())
            self.end_arrow_item.setBrush(line_color)
            self.end_arrow_item.setPen(line_color)

        ## Labels

        n = len(self._ticks)
        resize_plot_item_list(self.label_items, n, QGraphicsTextItem, self)
        resize_plot_item_list(self.label_bg_items, n, QGraphicsRectItem, self)
        resize_plot_item_list(self.tick_items, n, QGraphicsLineItem, self)

        test_rect = QRectF(self.graph_line.p1(),
                           self.graph_line.p2()).normalized()
        test_rect.adjust(-1, -1, 1, 1)

        n_v = self.graph_line.normalVector().unitVector()
        if self.title_above:
            n_p = n_v.p2() - n_v.p1()
        else:
            n_p = n_v.p1() - n_v.p2()
        l_v = self.graph_line.unitVector()
        l_p = l_v.p2() - l_v.p1()
        for i in range(n):
            pos, text, size, step = self._ticks[i]
            hs = 0.5 * step
            tick_pos = self.map_to_graph(pos)
            if not test_rect.contains(tick_pos):
                self.tick_items[i].setVisible(False)
                self.label_items[i].setVisible(False)
                continue
            item = self.label_items[i]
            item.setVisible(True)
            if not zoom_only:
                if self.id in XAxes or getattr(self, 'is_horizontal', False):
                    item.setHtml('<center>' + Qt.escape(text.strip()) +
                                 '</center>')
                else:
                    item.setHtml(Qt.escape(text.strip()))

            item.setTextWidth(-1)
            text_angle = 0
            if dense_text:
                w = min(item.boundingRect().width(), self.max_text_width)
                item.setTextWidth(w)
                if self.title_above:
                    label_pos = tick_pos + n_p * (
                        w + self.text_margin
                    ) + l_p * item.boundingRect().height() / 2
                else:
                    label_pos = tick_pos + n_p * self.text_margin + l_p * item.boundingRect(
                    ).height() / 2
                text_angle = -90 if self.title_above else 90
            else:
                w = min(
                    item.boundingRect().width(),
                    QLineF(self.map_to_graph(pos - hs),
                           self.map_to_graph(pos + hs)).length())
                label_pos = tick_pos + n_p * self.text_margin - l_p * w / 2
                item.setTextWidth(w)

            if not self.always_horizontal_text:
                if self.title_above:
                    item.setRotation(-self.graph_line.angle() - text_angle)
                else:
                    item.setRotation(self.graph_line.angle() - text_angle)

            item.setPos(label_pos)
            item.setDefaultTextColor(text_color)

            self.label_bg_items[i].setRect(item.boundingRect())
            self.label_bg_items[i].setPen(QPen(Qt.NoPen))
            self.label_bg_items[i].setBrush(self.plot.color(OWPalette.Canvas))

            item = self.tick_items[i]
            item.setVisible(True)
            tick_line = QLineF(v)
            tick_line.translate(-tick_line.p1())
            tick_line.setLength(size)
            if self.title_above:
                tick_line.setAngle(tick_line.angle() + 180)
            item.setLine(tick_line)
            item.setPen(line_color)
            item.setPos(self.map_to_graph(pos))
class SliderLine(QGraphicsObject):
    """A movable slider line."""
    valueChanged = Signal(float)

    linePressed = Signal()
    lineMoved = Signal()
    lineReleased = Signal()
    rangeChanged = Signal(float, float)

    def __init__(self, parent=None, orientation=Qt.Vertical, value=0.0,
                 length=10.0, **kwargs):
        self._orientation = orientation
        self._value = value
        self._length = length
        self._min = 0.0
        self._max = 1.0
        self._line = QLineF()
        self._pen = QPen()
        super().__init__(parent, **kwargs)

        self.setAcceptedMouseButtons(Qt.LeftButton)
        self.setPen(make_pen(brush=QColor(50, 50, 50), width=1, cosmetic=True))

        if self._orientation == Qt.Vertical:
            self.setCursor(Qt.SizeVerCursor)
        else:
            self.setCursor(Qt.SizeHorCursor)

    def setPen(self, pen):
        pen = QPen(pen)
        if self._pen != pen:
            self.prepareGeometryChange()
            self._pen = pen
            self._line = None
            self.update()

    def pen(self):
        return QPen(self._pen)

    def setValue(self, value):
        value = min(max(value, self._min), self._max)

        if self._value != value:
            self.prepareGeometryChange()
            self._value = value
            self._line = None
            self.valueChanged.emit(value)

    def value(self):
        return self._value

    def setRange(self, minval, maxval):
        maxval = max(minval, maxval)
        if minval != self._min or maxval != self._max:
            self._min = minval
            self._max = maxval
            self.rangeChanged.emit(minval, maxval)
            self.setValue(self._value)

    def setLength(self, length):
        if self._length != length:
            self.prepareGeometryChange()
            self._length = length
            self._line = None

    def length(self):
        return self._length

    def setOrientation(self, orientation):
        if self._orientation != orientation:
            self.prepareGeometryChange()
            self._orientation = orientation
            self._line = None
            if self._orientation == Qt.Vertical:
                self.setCursor(Qt.SizeVerCursor)
            else:
                self.setCursor(Qt.SizeHorCursor)

    def mousePressEvent(self, event):
        event.accept()
        self.linePressed.emit()

    def mouseMoveEvent(self, event):
        pos = event.pos()
        if self._orientation == Qt.Vertical:
            self.setValue(pos.y())
        else:
            self.setValue(pos.x())
        self.lineMoved.emit()
        event.accept()

    def mouseReleaseEvent(self, event):
        if self._orientation == Qt.Vertical:
            self.setValue(event.pos().y())
        else:
            self.setValue(event.pos().x())
        self.lineReleased.emit()
        event.accept()

    def boundingRect(self):
        if self._line is None:
            if self._orientation == Qt.Vertical:
                self._line = QLineF(0, self._value, self._length, self._value)
            else:
                self._line = QLineF(self._value, 0, self._value, self._length)
        r = QRectF(self._line.p1(), self._line.p2())
        penw = self.pen().width()
        return r.adjusted(-penw, -penw, penw, penw)

    def paint(self, painter, *args):
        if self._line is None:
            self.boundingRect()

        painter.save()
        painter.setPen(self.pen())
        painter.drawLine(self._line)
        painter.restore()