qpuiq 0.10__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of qpuiq might be problematic. Click here for more details.
- PUI/PySide6/__init__.py +49 -0
- PUI/PySide6/application.py +58 -0
- PUI/PySide6/base.py +222 -0
- PUI/PySide6/button.py +21 -0
- PUI/PySide6/canvas.py +288 -0
- PUI/PySide6/checkbox.py +32 -0
- PUI/PySide6/combobox.py +75 -0
- PUI/PySide6/dialog.py +72 -0
- PUI/PySide6/divider.py +23 -0
- PUI/PySide6/image.py +30 -0
- PUI/PySide6/label.py +33 -0
- PUI/PySide6/layout.py +72 -0
- PUI/PySide6/matplotlib.py +23 -0
- PUI/PySide6/mdi.py +33 -0
- PUI/PySide6/menu.py +85 -0
- PUI/PySide6/modal.py +132 -0
- PUI/PySide6/progressbar.py +17 -0
- PUI/PySide6/radiobutton.py +29 -0
- PUI/PySide6/scroll.py +153 -0
- PUI/PySide6/splitter.py +25 -0
- PUI/PySide6/tab.py +39 -0
- PUI/PySide6/table.py +89 -0
- PUI/PySide6/text.py +35 -0
- PUI/PySide6/textfield.py +62 -0
- PUI/PySide6/toolbar.py +57 -0
- PUI/PySide6/tree.py +120 -0
- PUI/PySide6/window.py +81 -0
- PUI/__init__.py +46 -0
- PUI/common.py +20 -0
- PUI/decorator.py +20 -0
- PUI/dom.py +238 -0
- PUI/flet/__init__.py +21 -0
- PUI/flet/application.py +42 -0
- PUI/flet/base.py +37 -0
- PUI/flet/button.py +20 -0
- PUI/flet/canvas.py +86 -0
- PUI/flet/checkbox.py +23 -0
- PUI/flet/label.py +27 -0
- PUI/flet/layout.py +50 -0
- PUI/flet/progressbar.py +21 -0
- PUI/flet/radiobutton.py +27 -0
- PUI/flet/scroll.py +83 -0
- PUI/flet/tab.py +42 -0
- PUI/flet/text.py +55 -0
- PUI/flet/textfield.py +58 -0
- PUI/flet/window.py +25 -0
- PUI/interfaces.py +97 -0
- PUI/node.py +407 -0
- PUI/state.py +698 -0
- PUI/textual/__init__.py +34 -0
- PUI/textual/application.py +82 -0
- PUI/textual/base.py +113 -0
- PUI/textual/button.py +17 -0
- PUI/textual/checkbox.py +21 -0
- PUI/textual/label.py +36 -0
- PUI/textual/layout.py +48 -0
- PUI/textual/progressbar.py +17 -0
- PUI/textual/radiobutton.py +24 -0
- PUI/textual/scroll.py +72 -0
- PUI/textual/tab.py +75 -0
- PUI/textual/text.py +32 -0
- PUI/textual/textfield.py +49 -0
- PUI/textual/window.py +7 -0
- PUI/timeline.py +36 -0
- PUI/tkinter/__init__.py +43 -0
- PUI/tkinter/application.py +49 -0
- PUI/tkinter/base.py +68 -0
- PUI/tkinter/button.py +15 -0
- PUI/tkinter/canvas.py +49 -0
- PUI/tkinter/checkbox.py +27 -0
- PUI/tkinter/label.py +17 -0
- PUI/tkinter/layout.py +114 -0
- PUI/tkinter/progressbar.py +17 -0
- PUI/tkinter/radiobutton.py +26 -0
- PUI/tkinter/scroll.py +201 -0
- PUI/tkinter/tab.py +52 -0
- PUI/tkinter/text.py +20 -0
- PUI/tkinter/textfield.py +53 -0
- PUI/tkinter/window.py +51 -0
- PUI/utils.py +15 -0
- PUI/view.py +161 -0
- PUI/wx/__init__.py +19 -0
- PUI/wx/application.py +44 -0
- PUI/wx/base.py +202 -0
- PUI/wx/button.py +16 -0
- PUI/wx/canvas.py +255 -0
- PUI/wx/checkbox.py +25 -0
- PUI/wx/combobox.py +72 -0
- PUI/wx/dialog.py +66 -0
- PUI/wx/divider.py +19 -0
- PUI/wx/label.py +18 -0
- PUI/wx/layout.py +46 -0
- PUI/wx/progressbar.py +17 -0
- PUI/wx/radiobutton.py +27 -0
- PUI/wx/scroll.py +44 -0
- PUI/wx/text.py +23 -0
- PUI/wx/textfield.py +56 -0
- PUI/wx/window.py +58 -0
- qpuiq-0.10.dist-info/LICENSE.txt +21 -0
- qpuiq-0.10.dist-info/METADATA +227 -0
- qpuiq-0.10.dist-info/RECORD +103 -0
- qpuiq-0.10.dist-info/WHEEL +5 -0
- qpuiq-0.10.dist-info/top_level.txt +1 -0
PUI/PySide6/__init__.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from PySide6.QtWidgets import QSizePolicy, QLayout
|
|
2
|
+
|
|
3
|
+
from .application import *
|
|
4
|
+
from .button import *
|
|
5
|
+
from .canvas import *
|
|
6
|
+
from .checkbox import *
|
|
7
|
+
from .combobox import *
|
|
8
|
+
from .dialog import *
|
|
9
|
+
from .divider import *
|
|
10
|
+
from .image import *
|
|
11
|
+
from .label import *
|
|
12
|
+
from .layout import *
|
|
13
|
+
from .modal import *
|
|
14
|
+
from .matplotlib import *
|
|
15
|
+
from .progressbar import *
|
|
16
|
+
from .radiobutton import *
|
|
17
|
+
from .scroll import *
|
|
18
|
+
from .splitter import *
|
|
19
|
+
from .table import *
|
|
20
|
+
from .tab import *
|
|
21
|
+
from .text import *
|
|
22
|
+
from .textfield import *
|
|
23
|
+
from .tree import *
|
|
24
|
+
from .window import *
|
|
25
|
+
from .mdi import *
|
|
26
|
+
from .toolbar import *
|
|
27
|
+
|
|
28
|
+
PUIView = QtPUIView
|
|
29
|
+
|
|
30
|
+
def PUI(func):
|
|
31
|
+
"""
|
|
32
|
+
PUI.PySide6.PUI triggers update() by signal/slot
|
|
33
|
+
"""
|
|
34
|
+
def func_wrapper(*args, **kwargs):
|
|
35
|
+
class PUIViewWrapper(QtPUIView):
|
|
36
|
+
pui_virtual = True
|
|
37
|
+
def __init__(self, name):
|
|
38
|
+
self.name = name
|
|
39
|
+
super().__init__()
|
|
40
|
+
|
|
41
|
+
def content(self):
|
|
42
|
+
return func(*args, **kwargs)
|
|
43
|
+
|
|
44
|
+
ret = PUIViewWrapper(func.__name__)
|
|
45
|
+
return ret
|
|
46
|
+
|
|
47
|
+
return func_wrapper
|
|
48
|
+
|
|
49
|
+
PUI_BACKEND = "PySide6"
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
|
|
4
|
+
class QtApplicationSignal(QtCore.QObject):
|
|
5
|
+
quit = QtCore.Signal()
|
|
6
|
+
|
|
7
|
+
class Application(QtPUIView):
|
|
8
|
+
def __init__(self, icon=None):
|
|
9
|
+
super().__init__()
|
|
10
|
+
self.ui = None
|
|
11
|
+
self.icon = icon
|
|
12
|
+
self._qtappsignal = QtApplicationSignal()
|
|
13
|
+
self._qtappsignal.quit.connect(self._quit, QtCore.Qt.ConnectionType.QueuedConnection) # Use QueuedConnection to prevent nested trigger
|
|
14
|
+
|
|
15
|
+
def redraw(self):
|
|
16
|
+
if self.ui:
|
|
17
|
+
super().redraw()
|
|
18
|
+
else:
|
|
19
|
+
self.sync()
|
|
20
|
+
|
|
21
|
+
def update(self, prev=None):
|
|
22
|
+
if not self.ui:
|
|
23
|
+
from PySide6 import QtWidgets
|
|
24
|
+
self.ui = QtWidgets.QApplication([])
|
|
25
|
+
if self.icon:
|
|
26
|
+
self.ui.setWindowIcon(QtGui.QIcon(self.icon))
|
|
27
|
+
|
|
28
|
+
super().update(prev)
|
|
29
|
+
|
|
30
|
+
def addChild(self, idx, child):
|
|
31
|
+
child.outer.show()
|
|
32
|
+
|
|
33
|
+
def removeChild(self, idx, child):
|
|
34
|
+
child.outer.close()
|
|
35
|
+
|
|
36
|
+
def start(self):
|
|
37
|
+
self.ui.exec()
|
|
38
|
+
|
|
39
|
+
def quit(self):
|
|
40
|
+
self._qtappsignal.quit.emit()
|
|
41
|
+
|
|
42
|
+
def _quit(self):
|
|
43
|
+
self.ui.quit()
|
|
44
|
+
|
|
45
|
+
def PUIApp(func):
|
|
46
|
+
def func_wrapper(*args, **kwargs):
|
|
47
|
+
class PUIAppWrapper(Application):
|
|
48
|
+
def __init__(self, name):
|
|
49
|
+
self.name = name
|
|
50
|
+
super().__init__()
|
|
51
|
+
|
|
52
|
+
def content(self):
|
|
53
|
+
return func(*args, **kwargs)
|
|
54
|
+
|
|
55
|
+
ret = PUIAppWrapper(func.__name__)
|
|
56
|
+
return ret
|
|
57
|
+
|
|
58
|
+
return func_wrapper
|
PUI/PySide6/base.py
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from PySide6 import QtCore, QtWidgets, QtGui
|
|
3
|
+
|
|
4
|
+
class QtViewSignal(QtCore.QObject):
|
|
5
|
+
redraw = QtCore.Signal()
|
|
6
|
+
|
|
7
|
+
def _apply_params(ui, node):
|
|
8
|
+
styles = {}
|
|
9
|
+
if node.style_fontsize:
|
|
10
|
+
styles["font"] = f"{node.style_fontsize}pt"
|
|
11
|
+
if node.style_fontfamily:
|
|
12
|
+
styles["font-family"] = node.style_fontfamily
|
|
13
|
+
if node.style_color:
|
|
14
|
+
styles["color"] = f"#{node.style_color:06X}"
|
|
15
|
+
if node.style_bgcolor:
|
|
16
|
+
styles["background-color"] = f"#{node.style_bgcolor:06X}"
|
|
17
|
+
|
|
18
|
+
style = node.qt_params.get("Style")
|
|
19
|
+
if not style is None:
|
|
20
|
+
ui.setStyle(style)
|
|
21
|
+
|
|
22
|
+
HorizontalPolicy = node.qt_params.get("HorizontalPolicy")
|
|
23
|
+
if not HorizontalPolicy is None:
|
|
24
|
+
ui.sizePolicy().setHorizontalPolicy(HorizontalPolicy)
|
|
25
|
+
|
|
26
|
+
VerticalPolicy = node.qt_params.get("VerticalPolicy")
|
|
27
|
+
if not VerticalPolicy is None:
|
|
28
|
+
ui.sizePolicy().setVerticalPolicy(VerticalPolicy)
|
|
29
|
+
|
|
30
|
+
SizeConstraint = node.qt_params.get("SizeConstraint")
|
|
31
|
+
if not SizeConstraint is None:
|
|
32
|
+
ui.setSizeConstraint(SizeConstraint)
|
|
33
|
+
|
|
34
|
+
StyleSheet = node.qt_params.get("StyleSheet", {})
|
|
35
|
+
for k,v in StyleSheet.items():
|
|
36
|
+
styles[k] = v
|
|
37
|
+
|
|
38
|
+
if hasattr(ui, "setStyleSheet"):
|
|
39
|
+
ui.setStyleSheet("".join([f"{k}:{v};" for k,v in styles.items()]))
|
|
40
|
+
|
|
41
|
+
if node.layout_padding:
|
|
42
|
+
ui.setContentsMargins(*trbl2ltrb(node.layout_padding))
|
|
43
|
+
|
|
44
|
+
class QtPUIView(PUIView):
|
|
45
|
+
pui_virtual = True
|
|
46
|
+
def __init__(self):
|
|
47
|
+
super().__init__()
|
|
48
|
+
self.qt_params = {}
|
|
49
|
+
self._qtsignal = QtViewSignal()
|
|
50
|
+
self._qtsignal.redraw.connect(self.sync, QtCore.Qt.ConnectionType.QueuedConnection) # Use QueuedConnection to prevent nested trigger
|
|
51
|
+
|
|
52
|
+
def destroy(self, direct):
|
|
53
|
+
if direct:
|
|
54
|
+
if self.ui: # PUIView doesn't have ui
|
|
55
|
+
self.ui.deleteLater()
|
|
56
|
+
self.ui = None
|
|
57
|
+
super().destroy(direct)
|
|
58
|
+
|
|
59
|
+
def redraw(self):
|
|
60
|
+
self.dirty = True
|
|
61
|
+
if self.updating:
|
|
62
|
+
return
|
|
63
|
+
self.updating = True
|
|
64
|
+
self._qtsignal.redraw.emit()
|
|
65
|
+
|
|
66
|
+
def update(self, prev=None):
|
|
67
|
+
super().update(prev)
|
|
68
|
+
_apply_params(self.ui, self)
|
|
69
|
+
|
|
70
|
+
def qt(self, **kwargs):
|
|
71
|
+
for k,v in kwargs.items():
|
|
72
|
+
self.qt_params[k] = v
|
|
73
|
+
return self
|
|
74
|
+
|
|
75
|
+
class QtBaseWidget(PUINode):
|
|
76
|
+
pui_terminal = True
|
|
77
|
+
|
|
78
|
+
def __init__(self):
|
|
79
|
+
super().__init__()
|
|
80
|
+
self.qt_params = {}
|
|
81
|
+
|
|
82
|
+
def destroy(self, direct):
|
|
83
|
+
if direct:
|
|
84
|
+
if self.ui:
|
|
85
|
+
self.ui.deleteLater()
|
|
86
|
+
self.ui = None
|
|
87
|
+
super().destroy(direct)
|
|
88
|
+
|
|
89
|
+
def update(self, prev=None):
|
|
90
|
+
super().update(prev)
|
|
91
|
+
|
|
92
|
+
sizePolicy = self.ui.sizePolicy()
|
|
93
|
+
if self.layout_width is not None:
|
|
94
|
+
sizePolicy.setHorizontalPolicy(QtWidgets.QSizePolicy.Preferred)
|
|
95
|
+
if self.layout_height is not None:
|
|
96
|
+
sizePolicy.setVerticalPolicy(QtWidgets.QSizePolicy.Preferred)
|
|
97
|
+
self.ui.setSizePolicy(sizePolicy)
|
|
98
|
+
|
|
99
|
+
if not hasattr(self.ui, "origSizeHint"):
|
|
100
|
+
self.ui.origSizeHint = self.ui.sizeHint
|
|
101
|
+
self.ui.sizeHint = self.qtSizeHint
|
|
102
|
+
|
|
103
|
+
_apply_params(self.ui, self)
|
|
104
|
+
|
|
105
|
+
def qtSizeHint(self):
|
|
106
|
+
node = self.get_node()
|
|
107
|
+
if not node.ui:
|
|
108
|
+
return QtCore.QSize(0, 0)
|
|
109
|
+
sh = node.ui.origSizeHint()
|
|
110
|
+
w = sh.width()
|
|
111
|
+
h = sh.height()
|
|
112
|
+
if not node.layout_width is None:
|
|
113
|
+
w = node.layout_width
|
|
114
|
+
if not node.layout_height is None:
|
|
115
|
+
h = node.layout_height
|
|
116
|
+
return QtCore.QSize(w, h)
|
|
117
|
+
|
|
118
|
+
def qt(self, **kwargs):
|
|
119
|
+
for k,v in kwargs.items():
|
|
120
|
+
self.qt_params[k] = v
|
|
121
|
+
return self
|
|
122
|
+
|
|
123
|
+
class QtBaseLayout(PUINode):
|
|
124
|
+
def __init__(self):
|
|
125
|
+
super().__init__()
|
|
126
|
+
self.qt_params = {}
|
|
127
|
+
if not isinstance(self.non_virtual_parent, QtBaseLayout):
|
|
128
|
+
self.layout_padding = (11,11,11,11)
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def outer(self):
|
|
132
|
+
return self.ui
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def inner(self):
|
|
136
|
+
return self.layout
|
|
137
|
+
|
|
138
|
+
def destroy(self, direct):
|
|
139
|
+
if direct:
|
|
140
|
+
if self.ui:
|
|
141
|
+
self.ui.deleteLater()
|
|
142
|
+
self.layout = None
|
|
143
|
+
self.ui = None
|
|
144
|
+
super().destroy(direct)
|
|
145
|
+
|
|
146
|
+
def update(self, prev=None):
|
|
147
|
+
super().update(prev)
|
|
148
|
+
_apply_params(self.ui, self)
|
|
149
|
+
|
|
150
|
+
def addChild(self, idx, child):
|
|
151
|
+
from .modal import Modal
|
|
152
|
+
from .layout import Spacer
|
|
153
|
+
if isinstance(child, Spacer):
|
|
154
|
+
self.layout.insertItem(idx, child.outer)
|
|
155
|
+
elif isinstance(child, Modal):
|
|
156
|
+
pass
|
|
157
|
+
elif isinstance(child, QtBaseWidget) or isinstance(child, QtBaseLayout):
|
|
158
|
+
params = {}
|
|
159
|
+
if not child.layout_weight is None:
|
|
160
|
+
params["stretch"] = child.layout_weight
|
|
161
|
+
self.layout.insertWidget(idx, child.outer, **params)
|
|
162
|
+
|
|
163
|
+
def removeChild(self, idx, child):
|
|
164
|
+
from .modal import Modal
|
|
165
|
+
from .layout import Spacer
|
|
166
|
+
if isinstance(child, Spacer):
|
|
167
|
+
self.layout.removeItem(child.outer)
|
|
168
|
+
elif isinstance(child, Modal):
|
|
169
|
+
pass
|
|
170
|
+
elif isinstance(child, QtBaseWidget) or isinstance(child, QtBaseLayout):
|
|
171
|
+
child.outer.setParent(None)
|
|
172
|
+
|
|
173
|
+
def qt(self, **kwargs):
|
|
174
|
+
for k,v in kwargs.items():
|
|
175
|
+
self.qt_params[k] = v
|
|
176
|
+
return self
|
|
177
|
+
|
|
178
|
+
class QtBaseFrame(QtBaseWidget):
|
|
179
|
+
pui_terminal = False
|
|
180
|
+
|
|
181
|
+
def destroy(self, direct):
|
|
182
|
+
if direct:
|
|
183
|
+
if self.ui:
|
|
184
|
+
self.ui.deleteLater()
|
|
185
|
+
self.ui = None
|
|
186
|
+
|
|
187
|
+
def addChild(self, idx, child):
|
|
188
|
+
if idx != 0:
|
|
189
|
+
return
|
|
190
|
+
if isinstance(child, QtBaseWidget) or isinstance(child, QtBaseLayout):
|
|
191
|
+
self.ui.setWidget(child.outer)
|
|
192
|
+
elif child.children:
|
|
193
|
+
self.addChild(idx, child.children[0])
|
|
194
|
+
|
|
195
|
+
def removeChild(self, idx, child):
|
|
196
|
+
if idx != 0:
|
|
197
|
+
return
|
|
198
|
+
if isinstance(child, QtBaseWidget) or isinstance(child, QtBaseLayout):
|
|
199
|
+
child.outer.setParent(None)
|
|
200
|
+
elif child.children:
|
|
201
|
+
self.removeChild(idx, child.children[0])
|
|
202
|
+
|
|
203
|
+
class QtInPui(QtBaseWidget):
|
|
204
|
+
def __init__(self, widget, *args):
|
|
205
|
+
self._internal_tag = str(id(widget))
|
|
206
|
+
super().__init__(*args)
|
|
207
|
+
self.ui = widget
|
|
208
|
+
|
|
209
|
+
def destroy(self, direct):
|
|
210
|
+
pass
|
|
211
|
+
|
|
212
|
+
class PuiInQt(QtPUIView):
|
|
213
|
+
def __init__(self, ui):
|
|
214
|
+
super().__init__()
|
|
215
|
+
self.ui = ui
|
|
216
|
+
self.ui.update()
|
|
217
|
+
|
|
218
|
+
def addChild(self, idx, child):
|
|
219
|
+
self.ui.addChild(idx, child)
|
|
220
|
+
|
|
221
|
+
def removeChild(self, idx, child):
|
|
222
|
+
self.ui.removeChild(idx, child)
|
PUI/PySide6/button.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
|
|
4
|
+
class Button(QtBaseWidget):
|
|
5
|
+
def __init__(self, text):
|
|
6
|
+
super().__init__()
|
|
7
|
+
self.text = text
|
|
8
|
+
|
|
9
|
+
def update(self, prev):
|
|
10
|
+
if prev and prev.ui:
|
|
11
|
+
self.ui = prev.ui
|
|
12
|
+
self.ui.setText(self.text)
|
|
13
|
+
try:
|
|
14
|
+
self.ui.clicked.disconnect()
|
|
15
|
+
except:
|
|
16
|
+
pass
|
|
17
|
+
prev.callback = None
|
|
18
|
+
else:
|
|
19
|
+
self.ui = QtWidgets.QPushButton(text=self.text)
|
|
20
|
+
self.ui.clicked.connect(self._clicked)
|
|
21
|
+
super().update(prev)
|
PUI/PySide6/canvas.py
ADDED
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
|
|
4
|
+
from PySide6 import QtWidgets, QtGui
|
|
5
|
+
from PySide6.QtGui import QPainter, QColor, QPainterPath
|
|
6
|
+
from PySide6.QtCore import QPoint
|
|
7
|
+
|
|
8
|
+
class PUIQtCanvas(QtWidgets.QWidget):
|
|
9
|
+
def __init__(self, node, width=None, height=None):
|
|
10
|
+
self.node = node
|
|
11
|
+
self.width = width
|
|
12
|
+
self.height = height
|
|
13
|
+
super().__init__()
|
|
14
|
+
|
|
15
|
+
def minimumSizeHint(self):
|
|
16
|
+
return QtCore.QSize(self.width, self.height)
|
|
17
|
+
|
|
18
|
+
def mouseDoubleClickEvent(self, event):
|
|
19
|
+
e = PUIEvent()
|
|
20
|
+
e.button = event.button().value
|
|
21
|
+
e.x, e.y = event.position().toPoint().toTuple()
|
|
22
|
+
self.node._dblclicked(e)
|
|
23
|
+
|
|
24
|
+
def mousePressEvent(self, event):
|
|
25
|
+
e = PUIEvent()
|
|
26
|
+
e.button = event.button().value
|
|
27
|
+
e.x, e.y = event.position().toPoint().toTuple()
|
|
28
|
+
self.node._mousedown(e)
|
|
29
|
+
|
|
30
|
+
def mouseReleaseEvent(self, event):
|
|
31
|
+
e = PUIEvent()
|
|
32
|
+
e.button = event.button().value
|
|
33
|
+
e.x, e.y = event.position().toPoint().toTuple()
|
|
34
|
+
self.node._mouseup(e)
|
|
35
|
+
|
|
36
|
+
def mouseMoveEvent(self, event):
|
|
37
|
+
e = PUIEvent()
|
|
38
|
+
e.button = event.button().value
|
|
39
|
+
e.x, e.y = event.position().toPoint().toTuple()
|
|
40
|
+
self.node._mousemove(e)
|
|
41
|
+
|
|
42
|
+
def wheelEvent(self, event):
|
|
43
|
+
e = PUIEvent()
|
|
44
|
+
e.x, e.y = event.position().toPoint().toTuple()
|
|
45
|
+
e.y_delta = event.pixelDelta().y()
|
|
46
|
+
e.x_delta = event.pixelDelta().x()
|
|
47
|
+
e.v_delta = event.angleDelta().y()
|
|
48
|
+
e.h_delta = event.angleDelta().x()
|
|
49
|
+
self.node._wheel(e)
|
|
50
|
+
|
|
51
|
+
def paintEvent(self, event):
|
|
52
|
+
node = self.node.get_node()
|
|
53
|
+
node.qpainter = QPainter()
|
|
54
|
+
node.qpainter.begin(self)
|
|
55
|
+
node.qpainter.setRenderHints(QtGui.QPainter.Antialiasing, True)
|
|
56
|
+
|
|
57
|
+
if not node.style_bgcolor is None:
|
|
58
|
+
bgBrush = QtGui.QBrush()
|
|
59
|
+
bgBrush.setColor(QtGui.QColor(node.style_bgcolor))
|
|
60
|
+
bgBrush.setStyle(QtCore.Qt.SolidPattern)
|
|
61
|
+
rect = QtCore.QRect(0, 0, self.width or self.geometry().width(), self.height or self.geometry().height())
|
|
62
|
+
node.qpainter.fillRect(rect, bgBrush)
|
|
63
|
+
|
|
64
|
+
node.painter(node, *node.args)
|
|
65
|
+
|
|
66
|
+
node.qpainter.end()
|
|
67
|
+
node.qpainter = None
|
|
68
|
+
|
|
69
|
+
class Canvas(QtBaseWidget):
|
|
70
|
+
def __init__(self, painter, *args):
|
|
71
|
+
super().__init__()
|
|
72
|
+
self.ui = None
|
|
73
|
+
self.painter = painter
|
|
74
|
+
self.args = args
|
|
75
|
+
|
|
76
|
+
def update(self, prev):
|
|
77
|
+
if prev and prev.ui:
|
|
78
|
+
self.ui = prev.ui
|
|
79
|
+
self.ui.puinode = self
|
|
80
|
+
self.ui.width = self.layout_width or 0
|
|
81
|
+
self.ui.height = self.layout_height or 0
|
|
82
|
+
else:
|
|
83
|
+
self.ui = PUIQtCanvas(self, self.layout_width or 0, self.layout_height or 0)
|
|
84
|
+
self.ui.setMouseTracking(bool(self._onMouseMove))
|
|
85
|
+
self.ui.update()
|
|
86
|
+
super().update(prev)
|
|
87
|
+
|
|
88
|
+
def drawText(self, x, y, text, w=None, h=None, size=12, color=None, rotate=0, anchor=Anchor.LEFT_TOP):
|
|
89
|
+
if w is None:
|
|
90
|
+
w = self.ui.geometry().width()
|
|
91
|
+
if h is None:
|
|
92
|
+
h = self.ui.geometry().height()
|
|
93
|
+
self.qpainter.save()
|
|
94
|
+
br = self.qpainter.boundingRect(0, 0, w, h, 0, text)
|
|
95
|
+
self.qpainter.restore()
|
|
96
|
+
|
|
97
|
+
dx = 0
|
|
98
|
+
dy = 0
|
|
99
|
+
if anchor.value[0]=="center":
|
|
100
|
+
dx = br.width()/2
|
|
101
|
+
elif anchor.value[0]=="right":
|
|
102
|
+
dx = br.width()
|
|
103
|
+
|
|
104
|
+
if anchor.value[1]=="center":
|
|
105
|
+
dy = br.height()/2
|
|
106
|
+
elif anchor.value[1]=="bottom":
|
|
107
|
+
dy = br.height()
|
|
108
|
+
|
|
109
|
+
self.qpainter.save()
|
|
110
|
+
self.qpainter.translate(int(x+dx), int(y+dy))
|
|
111
|
+
self.qpainter.rotate(rotate)
|
|
112
|
+
self.qpainter.translate(int(-dx), int(-dy))
|
|
113
|
+
|
|
114
|
+
if size is not None:
|
|
115
|
+
font = self.qpainter.font()
|
|
116
|
+
font.setPointSize(size)
|
|
117
|
+
self.qpainter.setFont(font)
|
|
118
|
+
|
|
119
|
+
if color is not None:
|
|
120
|
+
self.qpainter.setPen(QColor(color))
|
|
121
|
+
|
|
122
|
+
self.qpainter.drawText(0, 0, w, h, 0, text)
|
|
123
|
+
self.qpainter.restore()
|
|
124
|
+
|
|
125
|
+
def drawLine(self, x1, y1, x2, y2, color=None, width=1):
|
|
126
|
+
self.qpainter.save()
|
|
127
|
+
|
|
128
|
+
pen = self.qpainter.pen()
|
|
129
|
+
if color is None:
|
|
130
|
+
pen.setStyle(QtCore.Qt.NoPen)
|
|
131
|
+
else:
|
|
132
|
+
pen.setStyle(QtCore.Qt.SolidLine)
|
|
133
|
+
pen.setColor(QColor(color))
|
|
134
|
+
pen.setWidth(width)
|
|
135
|
+
self.qpainter.setPen(pen)
|
|
136
|
+
|
|
137
|
+
self.qpainter.drawLine(x1, y1, x2, y2)
|
|
138
|
+
|
|
139
|
+
self.qpainter.restore()
|
|
140
|
+
|
|
141
|
+
def drawPolyline(self, coords, color=None, width=1):
|
|
142
|
+
self.qpainter.save()
|
|
143
|
+
|
|
144
|
+
pen = self.qpainter.pen()
|
|
145
|
+
if color is None:
|
|
146
|
+
pen.setStyle(QtCore.Qt.NoPen)
|
|
147
|
+
else:
|
|
148
|
+
pen.setStyle(QtCore.Qt.SolidLine)
|
|
149
|
+
pen.setColor(QColor(color))
|
|
150
|
+
pen.setWidth(width)
|
|
151
|
+
self.qpainter.setPen(pen)
|
|
152
|
+
|
|
153
|
+
self.qpainter.drawPolyline([QtCore.QPointF(x,y) for x,y in coords])
|
|
154
|
+
|
|
155
|
+
self.qpainter.restore()
|
|
156
|
+
|
|
157
|
+
def drawPolygon(self, coords, fill=None, stroke=None, width=1):
|
|
158
|
+
self.qpainter.save()
|
|
159
|
+
|
|
160
|
+
brush = self.qpainter.brush()
|
|
161
|
+
if fill is None:
|
|
162
|
+
brush.setStyle(QtCore.Qt.NoBrush)
|
|
163
|
+
else:
|
|
164
|
+
brush.setStyle(QtCore.Qt.SolidPattern)
|
|
165
|
+
brush.setColor(QColor(fill))
|
|
166
|
+
self.qpainter.setBrush(brush)
|
|
167
|
+
|
|
168
|
+
pen = self.qpainter.pen()
|
|
169
|
+
if stroke is None:
|
|
170
|
+
pen.setStyle(QtCore.Qt.NoPen)
|
|
171
|
+
else:
|
|
172
|
+
pen.setStyle(QtCore.Qt.SolidLine)
|
|
173
|
+
pen.setColor(QColor(stroke))
|
|
174
|
+
pen.setWidth(width)
|
|
175
|
+
self.qpainter.setPen(pen)
|
|
176
|
+
|
|
177
|
+
polygon = QtGui.QPolygonF()
|
|
178
|
+
for p in coords:
|
|
179
|
+
polygon.append(QtCore.QPointF(*p))
|
|
180
|
+
self.qpainter.drawPolygon(polygon)
|
|
181
|
+
|
|
182
|
+
self.qpainter.restore()
|
|
183
|
+
|
|
184
|
+
def drawRect(self, x1, y1, x2, y2, fill=None, stroke=None, width=1):
|
|
185
|
+
self.qpainter.save()
|
|
186
|
+
|
|
187
|
+
x = min(x1, x2)
|
|
188
|
+
y = min(y1, y2)
|
|
189
|
+
w = abs(x2-x1)
|
|
190
|
+
h = abs(y2-y1)
|
|
191
|
+
|
|
192
|
+
brush = self.qpainter.brush()
|
|
193
|
+
if fill is None:
|
|
194
|
+
brush.setStyle(QtCore.Qt.NoBrush)
|
|
195
|
+
else:
|
|
196
|
+
brush.setStyle(QtCore.Qt.SolidPattern)
|
|
197
|
+
brush.setColor(QColor(fill))
|
|
198
|
+
self.qpainter.setBrush(brush)
|
|
199
|
+
|
|
200
|
+
pen = self.qpainter.pen()
|
|
201
|
+
if stroke is None:
|
|
202
|
+
pen.setStyle(QtCore.Qt.NoPen)
|
|
203
|
+
else:
|
|
204
|
+
pen.setStyle(QtCore.Qt.SolidLine)
|
|
205
|
+
pen.setColor(QColor(stroke))
|
|
206
|
+
pen.setWidth(width)
|
|
207
|
+
self.qpainter.setPen(pen)
|
|
208
|
+
|
|
209
|
+
self.qpainter.drawRect(x, y, w, h)
|
|
210
|
+
|
|
211
|
+
self.qpainter.restore()
|
|
212
|
+
|
|
213
|
+
def drawEllipse(self, x, y, rx, ry, fill=None, stroke=None, width=1):
|
|
214
|
+
self.qpainter.save()
|
|
215
|
+
|
|
216
|
+
brush = self.qpainter.brush()
|
|
217
|
+
if fill is None:
|
|
218
|
+
brush.setStyle(QtCore.Qt.NoBrush)
|
|
219
|
+
else:
|
|
220
|
+
brush.setStyle(QtCore.Qt.SolidPattern)
|
|
221
|
+
brush.setColor(QColor(fill))
|
|
222
|
+
self.qpainter.setBrush(brush)
|
|
223
|
+
|
|
224
|
+
pen = self.qpainter.pen()
|
|
225
|
+
if stroke is None:
|
|
226
|
+
pen.setStyle(QtCore.Qt.NoPen)
|
|
227
|
+
else:
|
|
228
|
+
pen.setStyle(QtCore.Qt.SolidLine)
|
|
229
|
+
pen.setColor(QColor(stroke))
|
|
230
|
+
pen.setWidth(width)
|
|
231
|
+
self.qpainter.setPen(pen)
|
|
232
|
+
|
|
233
|
+
self.qpainter.drawEllipse(QtCore.QPointF(x,y), rx, ry)
|
|
234
|
+
|
|
235
|
+
self.qpainter.restore()
|
|
236
|
+
|
|
237
|
+
def drawShapely(self, shape, fill=None, stroke=None, width=1):
|
|
238
|
+
self.qpainter.save()
|
|
239
|
+
|
|
240
|
+
brush = self.qpainter.brush()
|
|
241
|
+
if fill is None:
|
|
242
|
+
brush.setStyle(QtCore.Qt.NoBrush)
|
|
243
|
+
else:
|
|
244
|
+
brush.setStyle(QtCore.Qt.SolidPattern)
|
|
245
|
+
brush.setColor(QColor(fill))
|
|
246
|
+
self.qpainter.setBrush(brush)
|
|
247
|
+
|
|
248
|
+
pen = self.qpainter.pen()
|
|
249
|
+
if stroke is None:
|
|
250
|
+
pen.setStyle(QtCore.Qt.NoPen)
|
|
251
|
+
else:
|
|
252
|
+
pen.setStyle(QtCore.Qt.SolidLine)
|
|
253
|
+
pen.setColor(QColor(stroke))
|
|
254
|
+
pen.setWidth(width)
|
|
255
|
+
self.qpainter.setPen(pen)
|
|
256
|
+
|
|
257
|
+
self._drawShapely(shape, fill, stroke, width)
|
|
258
|
+
|
|
259
|
+
self.qpainter.restore()
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def _drawShapely(self, shape, fill=None, stroke=None, width=1):
|
|
263
|
+
if hasattr(shape, "geoms"):
|
|
264
|
+
for g in shape.geoms:
|
|
265
|
+
self.drawShapely(g, fill, stroke, width)
|
|
266
|
+
elif hasattr(shape, "exterior"): # polygon
|
|
267
|
+
path = QPainterPath()
|
|
268
|
+
|
|
269
|
+
exterior = QtGui.QPolygonF()
|
|
270
|
+
for p in shape.exterior.coords:
|
|
271
|
+
exterior.append(QtCore.QPointF(*p))
|
|
272
|
+
path.addPolygon(exterior)
|
|
273
|
+
|
|
274
|
+
for h in shape.interiors:
|
|
275
|
+
hole = QtGui.QPolygonF()
|
|
276
|
+
for p in h.coords:
|
|
277
|
+
hole.append(QtCore.QPointF(*p))
|
|
278
|
+
hpoly = QPainterPath()
|
|
279
|
+
hpoly.addPolygon(hole)
|
|
280
|
+
path = path.subtracted(hpoly)
|
|
281
|
+
|
|
282
|
+
self.qpainter.drawPath(path)
|
|
283
|
+
elif hasattr(shape, "x") and hasattr(shape, "y"): # point
|
|
284
|
+
self.drawEllipse(shape.x, shape.y, width/2, width/2, fill=stroke)
|
|
285
|
+
elif hasattr(shape, "coords"): # linestring, linearring
|
|
286
|
+
self.drawPolyline(shape.coords, color=stroke, width=width)
|
|
287
|
+
else:
|
|
288
|
+
raise RuntimeError(f"Not implemented: drawShapely({type(shape).__name__}) {dir(shape)}")
|
PUI/PySide6/checkbox.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
from ..utils import *
|
|
4
|
+
from PySide6.QtWidgets import QSizePolicy
|
|
5
|
+
|
|
6
|
+
class Checkbox(QtBaseWidget):
|
|
7
|
+
def __init__(self, text, model):
|
|
8
|
+
super().__init__()
|
|
9
|
+
self.text = text
|
|
10
|
+
self.model = model
|
|
11
|
+
|
|
12
|
+
def update(self, prev):
|
|
13
|
+
if prev and prev.ui:
|
|
14
|
+
self.ui = prev.ui
|
|
15
|
+
try:
|
|
16
|
+
self.ui.stateChanged.disconnect()
|
|
17
|
+
except:
|
|
18
|
+
pass
|
|
19
|
+
try:
|
|
20
|
+
self.ui.clicked.disconnect()
|
|
21
|
+
except:
|
|
22
|
+
pass
|
|
23
|
+
else:
|
|
24
|
+
self.ui = QtWidgets.QCheckBox()
|
|
25
|
+
self.ui.setText(self.text)
|
|
26
|
+
self.ui.setChecked(bool(self.model.value))
|
|
27
|
+
self.ui.stateChanged.connect(self._stateChanged)
|
|
28
|
+
self.ui.clicked.connect(self._clicked)
|
|
29
|
+
super().update(prev)
|
|
30
|
+
|
|
31
|
+
def _stateChanged(self, value):
|
|
32
|
+
self.model.value = bool(value)
|