File: connection_painter.py

package info (click to toggle)
python-qtpynodeeditor 0.2.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 604 kB
  • sloc: python: 5,038; makefile: 14; sh: 1
file content (219 lines) | stat: -rw-r--r-- 5,707 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
from qtpy.QtCore import QLineF, QPoint, QSize, Qt
from qtpy.QtGui import QIcon, QPainter, QPainterPath, QPainterPathStroker, QPen

from .base import ConnectionBase
from .connection_geometry import ConnectionGeometry
from .enums import PortType
from .style import ConnectionStyle

use_debug_drawing = False


def cubic_path(geom):
    source, sink = geom.source, geom.sink
    c1, c2 = geom.points_c1_c2()

    # cubic spline
    cubic = QPainterPath(source)

    cubic.cubicTo(c1, c2, sink)
    return cubic


def debug_drawing(painter, connection):
    geom = connection.geometry
    source, sink = geom.source, geom.sink
    c1, c2 = geom.points_c1_c2()

    painter.setPen(Qt.red)
    painter.setBrush(Qt.red)

    painter.drawLine(QLineF(source, c1))
    painter.drawLine(QLineF(c1, c2))
    painter.drawLine(QLineF(c2, sink))
    painter.drawEllipse(c1, 3, 3)
    painter.drawEllipse(c2, 3, 3)

    painter.setBrush(Qt.NoBrush)

    painter.drawPath(cubic_path(geom))
    painter.setPen(Qt.yellow)

    painter.drawRect(geom.bounding_rect)


def draw_sketch_line(painter, connection, style):
    if not connection.requires_port:
        return

    p = QPen()
    p.setWidth(style.construction_line_width)
    p.setColor(style.construction_color)
    p.setStyle(Qt.DashLine)

    painter.setPen(p)
    painter.setBrush(Qt.NoBrush)

    geom = connection.geometry

    cubic = cubic_path(geom)
    # cubic spline
    painter.drawPath(cubic)


def draw_hovered_or_selected(painter, connection, style):
    geom = connection.geometry
    hovered = geom.hovered

    graphics_object = connection.graphics_object
    selected = graphics_object.isSelected()

    # drawn as a fat background
    if hovered or selected:
        p = QPen()

        line_width = style.line_width

        p.setWidth(2 * line_width)
        p.setColor((style.selected_halo_color
                    if selected
                    else style.hovered_color))

        painter.setPen(p)
        painter.setBrush(Qt.NoBrush)

        # cubic spline
        cubic = cubic_path(geom)
        painter.drawPath(cubic)


def draw_normal_line(painter, connection, style):
    if connection.requires_port:
        return

    # colors
    normal_color_out = style.get_normal_color()
    normal_color_in = normal_color_out

    selected_color = style.selected_color

    gradient_color = False
    if style.use_data_defined_colors:
        data_type_out = connection.data_type(PortType.output)
        data_type_in = connection.data_type(PortType.input)

        gradient_color = data_type_out.id != data_type_in.id

        normal_color_out = style.get_normal_color(data_type_out.id)
        normal_color_in = style.get_normal_color(data_type_in.id)
        selected_color = normal_color_out.darker(200)

    # geometry
    geom = connection.geometry
    line_width = style.line_width

    # draw normal line
    p = QPen()
    p.setWidth(line_width)

    graphics_object = connection.graphics_object
    selected = graphics_object.isSelected()

    cubic = cubic_path(geom)
    if gradient_color:
        painter.setBrush(Qt.NoBrush)

        c = normal_color_out
        if selected:
            c = c.darker(200)

        p.setColor(c)
        painter.setPen(p)

        segments = 60

        for i in range(segments):
            ratio_prev = float(i) / segments
            ratio = float(i + 1) / segments

            if i == segments / 2:
                c = normal_color_in
                if selected:
                    c = c.darker(200)

                p.setColor(c)
                painter.setPen(p)

            painter.drawLine(cubic.pointAtPercent(ratio_prev), cubic.pointAtPercent(ratio))

        icon = QIcon(":convert.png")

        pixmap = icon.pixmap(QSize(22, 22))
        painter.drawPixmap(cubic.pointAtPercent(0.50) - QPoint(pixmap.width() / 2, pixmap.height() / 2), pixmap)
    else:
        p.setColor(normal_color_out)

        if selected:
            p.setColor(selected_color)

        painter.setPen(p)
        painter.setBrush(Qt.NoBrush)

        painter.drawPath(cubic)


class ConnectionPainter:
    @staticmethod
    def paint(painter: QPainter, connection: ConnectionBase,
              style: ConnectionStyle):
        """
        Paint

        Parameters
        ----------
        painter : QPainter
        connection : Connection
        style : ConnectionStyle
        """
        draw_hovered_or_selected(painter, connection, style)
        draw_sketch_line(painter, connection, style)
        draw_normal_line(painter, connection, style)
        if use_debug_drawing:
            debug_drawing(painter, connection)

        # draw end points
        geom = connection.geometry
        source, sink = geom.source, geom.sink

        point_diameter = style.point_diameter
        painter.setPen(style.construction_color)
        painter.setBrush(style.construction_color)
        point_radius = point_diameter / 2.0
        painter.drawEllipse(source, point_radius, point_radius)
        painter.drawEllipse(sink, point_radius, point_radius)

    @staticmethod
    def get_painter_stroke(geom: ConnectionGeometry) -> QPainterPath:
        """
        Get painter stroke

        Parameters
        ----------
        geom : ConnectionGeometry

        Returns
        -------
        value : QPainterPath
        """
        cubic = cubic_path(geom)
        source = geom.source
        result = QPainterPath(source)
        segments = 20

        for i in range(segments):
            ratio = float(i + 1) / segments
            result.lineTo(cubic.pointAtPercent(ratio))

        stroker = QPainterPathStroker()
        stroker.setWidth(10.0)
        return stroker.createStroke(result)