File: line_widget.py

package info (click to toggle)
raysession 0.17.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 19,168 kB
  • sloc: python: 44,371; sh: 1,538; makefile: 208; xml: 86
file content (199 lines) | stat: -rw-r--r-- 7,206 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
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# PatchBay Canvas engine using QGraphicsView/Scene
# Copyright (C) 2010-2019 Filipe Coelho <falktx@falktx.com>
# Copyright (C) 2019-2024 Mathieu Picot <picotmathieu@gmail.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# For a full copy of the GNU General Public License see the doc/GPL.txt file.

from enum import Enum
from typing import TYPE_CHECKING

from qtpy.QtCore import Qt
from qtpy.QtGui import (QColor, QLinearGradient,
                        QPainterPath, QPen, QBrush)
from qtpy.QtWidgets import QGraphicsPathItem

from patshared import PortType
from .init_values import (
    canvas,
    options,
    CanvasItemType)

if TYPE_CHECKING:
    from .port_widget import PortWidget


class _ThemeState(Enum):
    NORMAL = 0
    SELECTED = 1
    DISCONNECTING = 2


class _ThemeAttributes:
    base_pen: QPen
    color_main: QColor
    color_alter: QColor | None
    base_width: float


class LineWidget(QGraphicsPathItem):
    def __init__(self, connection_id: int,
                 item1: 'PortWidget', item2: 'PortWidget'):
        ''' Class for connection line widget '''
        QGraphicsPathItem.__init__(self)

        # is true when the connection will be undo by user if (s)he
        # leaves the mouse button
        self.ready_to_disc = False        

        self._item1 = item1
        self._item2 = item2
        self._connection_id = connection_id

        self._semi_hidden = False
        
        self._th_attribs = dict[_ThemeState, _ThemeAttributes]()
        self.update_theme()

        self.setBrush(QColor(0, 0, 0, 0))
        self.setGraphicsEffect(None) # type:ignore
        self.update_line_pos()

    def check_select_state(self):
        self.update_line_gradient()

    def trigger_disconnect(self):
        canvas.cb.ports_disconnect(self._connection_id)

    def semi_hide(self, yesno: bool):
        self._semi_hidden = yesno
        self.update_line_gradient()

    def update_line_pos(self, fast_move=False):
        item1_con_pos = self._item1.connect_pos()
        item1_x = item1_con_pos.x()
        item1_y = item1_con_pos.y()
        
        item2_con_pos = self._item2.connect_pos()
        item2_x = item2_con_pos.x()
        item2_y = item2_con_pos.y()

        x_diff = item2_x - item1_x
        mid_x = abs(x_diff) / 2

        diffxy = abs(item1_y - item2_y) - abs(x_diff)
        if diffxy > 0:
            mid_x += diffxy

        mid_x = min(mid_x, max(200.0, x_diff / 2))

    def type(self) -> CanvasItemType:
        return CanvasItemType.BEZIER_LINE

    def update_theme(self):
        port_type1 = self._item1.get_port_type()
        
        for theme_state in _ThemeState:
            if theme_state is _ThemeState.DISCONNECTING:
                theme = canvas.theme.line.disconnecting
            else:
                theme = canvas.theme.line
                if port_type1 == PortType.AUDIO_JACK:
                    theme = theme.audio
                elif port_type1 == PortType.MIDI_JACK:
                    theme = theme.midi
                elif port_type1 == PortType.MIDI_ALSA:
                    theme = theme.alsa
                elif port_type1 == PortType.VIDEO:
                    theme = theme.video

                if theme_state is _ThemeState.SELECTED:
                    theme = theme.selected

            tha = _ThemeAttributes()
            tha.base_pen = theme.fill_pen
            tha.color_main = theme.background_color
            tha.color_alter = theme.background2_color
            if tha.color_alter is None:
                tha.color_alter = tha.color_main
            tha.base_width = tha.base_pen.widthF() + 0.000001
            self._th_attribs[theme_state] = tha            

    def update_line_gradient(self):
        pos_top = self.boundingRect().top()
        pos_bot = self.boundingRect().bottom()

        if self.ready_to_disc:
            tha = self._th_attribs[_ThemeState.DISCONNECTING]
        elif self._item1.isSelected() or self._item2.isSelected():
            tha = self._th_attribs[_ThemeState.SELECTED]
        else:
            tha = self._th_attribs[_ThemeState.NORMAL]
        
        has_gradient = bool(tha.color_main != tha.color_alter)
        
        if has_gradient:
            port_gradient = QLinearGradient(0, pos_top, 0, pos_bot)

            if self.ready_to_disc:
                port_gradient.setColorAt(0.0, tha.color_main)
                port_gradient.setColorAt(1.0, tha.color_main)
            else:
                if tha.color_alter is None:
                    raise Exception
                
                if self._semi_hidden:
                    shd = options.semi_hide_opacity
                    bgcolor = canvas.theme.scene_background_color
                    
                    color_main = QColor(
                        int(tha.color_main.red() * shd + bgcolor.red() * (1.0 - shd) + 0.5),
                        int(tha.color_main.green() * shd + bgcolor.green() * (1.0 - shd)+ 0.5),
                        int(tha.color_main.blue() * shd + bgcolor.blue() * (1.0 - shd) + 0.5),
                        tha.color_main.alpha())
                    
                    color_alter = QColor(
                        int(tha.color_alter.red() * shd + bgcolor.red() * (1.0 - shd) + 0.5),
                        int(tha.color_alter.green() * shd + bgcolor.green() * (1.0 - shd)+ 0.5),
                        int(tha.color_alter.blue() * shd + bgcolor.blue() * (1.0 - shd) + 0.5),
                        tha.color_alter.alpha())
                
                else:
                    color_main, color_alter = tha.color_main, tha.color_alter

                port_gradient.setColorAt(0.0, color_main)
                port_gradient.setColorAt(0.5, color_alter)
                port_gradient.setColorAt(1.0, color_main)
            
            self.setPen(QPen(port_gradient, tha.base_width, Qt.PenStyle.SolidLine, Qt.PenCapStyle.FlatCap))
        else:
            if self._semi_hidden:
                shd = options.semi_hide_opacity
                bgcolor = canvas.theme.scene_background_color

                color_main = QColor(
                    int(tha.color_main.red() * shd + bgcolor.red() * (1.0 - shd) + 0.5),
                    int(tha.color_main.green() * shd + bgcolor.green() * (1.0 - shd)+ 0.5),
                    int(tha.color_main.blue() * shd + bgcolor.blue() * (1.0 - shd) + 0.5),
                    tha.color_main.alpha())
            else:
                color_main = tha.color_main
        
            pen = QPen(QBrush(color_main), tha.base_width, Qt.PenStyle.SolidLine, Qt.PenCapStyle.FlatCap)
            pen.setCosmetic(True)
            self.setPen(pen)

    def paint(self, painter, option, widget):
        return