qpuiq 0.23__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.
- PUI/PySide6/__init__.py +49 -0
- PUI/PySide6/application.py +58 -0
- PUI/PySide6/base.py +285 -0
- PUI/PySide6/button.py +21 -0
- PUI/PySide6/canvas.py +345 -0
- PUI/PySide6/checkbox.py +32 -0
- PUI/PySide6/combobox.py +85 -0
- PUI/PySide6/dialog.py +72 -0
- PUI/PySide6/divider.py +23 -0
- PUI/PySide6/image.py +48 -0
- PUI/PySide6/label.py +33 -0
- PUI/PySide6/layout.py +141 -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 +155 -0
- PUI/PySide6/splitter.py +25 -0
- PUI/PySide6/tab.py +39 -0
- PUI/PySide6/table.py +147 -0
- PUI/PySide6/text.py +35 -0
- PUI/PySide6/textfield.py +62 -0
- PUI/PySide6/toolbar.py +57 -0
- PUI/PySide6/tree.py +290 -0
- PUI/PySide6/window.py +82 -0
- PUI/__init__.py +46 -0
- PUI/common.py +26 -0
- PUI/decorator.py +20 -0
- PUI/dom.py +263 -0
- PUI/flet/__init__.py +22 -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/divider.py +14 -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 +432 -0
- PUI/state.py +711 -0
- PUI/textual/__init__.py +35 -0
- PUI/textual/application.py +82 -0
- PUI/textual/base.py +148 -0
- PUI/textual/button.py +17 -0
- PUI/textual/checkbox.py +21 -0
- PUI/textual/label.py +36 -0
- PUI/textual/layout.py +52 -0
- PUI/textual/progressbar.py +17 -0
- PUI/textual/radiobutton.py +24 -0
- PUI/textual/scroll.py +74 -0
- PUI/textual/tab.py +75 -0
- PUI/textual/text.py +32 -0
- PUI/textual/textfield.py +55 -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 +52 -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 +246 -0
- PUI/wx/button.py +16 -0
- PUI/wx/canvas.py +255 -0
- PUI/wx/checkbox.py +25 -0
- PUI/wx/combobox.py +81 -0
- PUI/wx/dialog.py +66 -0
- PUI/wx/divider.py +19 -0
- PUI/wx/label.py +18 -0
- PUI/wx/layout.py +52 -0
- PUI/wx/progressbar.py +19 -0
- PUI/wx/radiobutton.py +27 -0
- PUI/wx/scroll.py +55 -0
- PUI/wx/text.py +23 -0
- PUI/wx/textfield.py +66 -0
- PUI/wx/window.py +64 -0
- qpuiq-0.23.dist-info/LICENSE.txt +21 -0
- qpuiq-0.23.dist-info/METADATA +234 -0
- qpuiq-0.23.dist-info/RECORD +104 -0
- qpuiq-0.23.dist-info/WHEEL +5 -0
- qpuiq-0.23.dist-info/top_level.txt +1 -0
PUI/PySide6/canvas.py
ADDED
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
|
|
4
|
+
from PySide6 import QtWidgets, QtGui
|
|
5
|
+
from PySide6.QtGui import QPainter, QColor, QPainterPath, QImage
|
|
6
|
+
|
|
7
|
+
class PUIQtCanvas(QtWidgets.QWidget):
|
|
8
|
+
def __init__(self, node, width=None, height=None):
|
|
9
|
+
self.puinode = node
|
|
10
|
+
self.width = width
|
|
11
|
+
self.height = height
|
|
12
|
+
super().__init__()
|
|
13
|
+
|
|
14
|
+
def minimumSizeHint(self):
|
|
15
|
+
return QtCore.QSize(self.width, self.height)
|
|
16
|
+
|
|
17
|
+
def mouseDoubleClickEvent(self, event):
|
|
18
|
+
e = PUIEvent()
|
|
19
|
+
e.button = event.button().value
|
|
20
|
+
e.x, e.y = event.position().toPoint().toTuple()
|
|
21
|
+
self.puinode._dblclicked(e)
|
|
22
|
+
|
|
23
|
+
def mousePressEvent(self, event):
|
|
24
|
+
e = PUIEvent()
|
|
25
|
+
e.button = event.button().value
|
|
26
|
+
e.x, e.y = event.position().toPoint().toTuple()
|
|
27
|
+
self.puinode._mousedown(e)
|
|
28
|
+
|
|
29
|
+
def mouseReleaseEvent(self, event):
|
|
30
|
+
e = PUIEvent()
|
|
31
|
+
e.button = event.button().value
|
|
32
|
+
e.x, e.y = event.position().toPoint().toTuple()
|
|
33
|
+
self.puinode._mouseup(e)
|
|
34
|
+
|
|
35
|
+
def mouseMoveEvent(self, event):
|
|
36
|
+
e = PUIEvent()
|
|
37
|
+
e.button = event.button().value
|
|
38
|
+
e.x, e.y = event.position().toPoint().toTuple()
|
|
39
|
+
self.puinode._mousemove(e)
|
|
40
|
+
|
|
41
|
+
def wheelEvent(self, event):
|
|
42
|
+
e = PUIEvent()
|
|
43
|
+
e.x, e.y = event.position().toPoint().toTuple()
|
|
44
|
+
e.y_delta = event.pixelDelta().y()
|
|
45
|
+
e.x_delta = event.pixelDelta().x()
|
|
46
|
+
e.v_delta = event.angleDelta().y()
|
|
47
|
+
e.h_delta = event.angleDelta().x()
|
|
48
|
+
modifier = 0
|
|
49
|
+
emodifiers = event.modifiers()
|
|
50
|
+
if emodifiers & QtCore.Qt.ShiftModifier:
|
|
51
|
+
modifier |= KeyModifier.SHIFT
|
|
52
|
+
if emodifiers & QtCore.Qt.ControlModifier:
|
|
53
|
+
modifier |= KeyModifier.CTRL
|
|
54
|
+
if emodifiers & QtCore.Qt.AltModifier:
|
|
55
|
+
modifier |= KeyModifier.ALT
|
|
56
|
+
if emodifiers & QtCore.Qt.MetaModifier:
|
|
57
|
+
modifier |= KeyModifier.META
|
|
58
|
+
e.modifiers = modifier
|
|
59
|
+
self.puinode._wheel(e)
|
|
60
|
+
|
|
61
|
+
def paintEvent(self, event):
|
|
62
|
+
puinode = self.puinode.get_node()
|
|
63
|
+
puinode.qpainter = QPainter()
|
|
64
|
+
puinode.qpainter.begin(self)
|
|
65
|
+
puinode.qpainter.setRenderHints(QtGui.QPainter.Antialiasing, True)
|
|
66
|
+
|
|
67
|
+
if not puinode.style_bgcolor is None:
|
|
68
|
+
bgBrush = QtGui.QBrush()
|
|
69
|
+
bgBrush.setColor(QtGui.QColor(puinode.style_bgcolor))
|
|
70
|
+
bgBrush.setStyle(QtCore.Qt.SolidPattern)
|
|
71
|
+
rect = QtCore.QRect(0, 0, self.width or self.geometry().width(), self.height or self.geometry().height())
|
|
72
|
+
puinode.qpainter.fillRect(rect, bgBrush)
|
|
73
|
+
|
|
74
|
+
puinode.width = self.geometry().width()
|
|
75
|
+
puinode.height = self.geometry().height()
|
|
76
|
+
immediate = puinode.painter(puinode, *puinode.args)
|
|
77
|
+
puinode.qpainter.end()
|
|
78
|
+
puinode.qpainter = None
|
|
79
|
+
if immediate:
|
|
80
|
+
self.update()
|
|
81
|
+
|
|
82
|
+
class ImageResource():
|
|
83
|
+
@staticmethod
|
|
84
|
+
def load(path):
|
|
85
|
+
ir = ImageResource()
|
|
86
|
+
ir.qimage = QImage(path)
|
|
87
|
+
return ir
|
|
88
|
+
|
|
89
|
+
def crop(self, x, y, width, height):
|
|
90
|
+
ir = ImageResource()
|
|
91
|
+
ir.qimage = self.qimage.copy(x, y, width, height)
|
|
92
|
+
return ir
|
|
93
|
+
|
|
94
|
+
def scale(self, width, height, keepAspectRatio=True, quality=0):
|
|
95
|
+
ir = ImageResource()
|
|
96
|
+
method = {
|
|
97
|
+
0: QtCore.Qt.TransformationMode.FastTransformation
|
|
98
|
+
}.get(quality, QtCore.Qt.TransformationMode.SmoothTransformation)
|
|
99
|
+
ir.qimage = self.qimage.scaled(width, height, QtCore.Qt.AspectRatioMode.KeepAspectRatio if keepAspectRatio else QtCore.Qt.IgnoreAspectRatio, method)
|
|
100
|
+
return ir
|
|
101
|
+
|
|
102
|
+
class Canvas(QtBaseWidget):
|
|
103
|
+
def __init__(self, painter, *args):
|
|
104
|
+
super().__init__()
|
|
105
|
+
self.ui = None
|
|
106
|
+
self.painter = painter
|
|
107
|
+
self.args = args
|
|
108
|
+
|
|
109
|
+
def update(self, prev):
|
|
110
|
+
if prev and prev.ui:
|
|
111
|
+
self.ui = prev.ui
|
|
112
|
+
self.ui.puinode = self
|
|
113
|
+
self.ui.width = self.layout_width or 0
|
|
114
|
+
self.ui.height = self.layout_height or 0
|
|
115
|
+
else:
|
|
116
|
+
self.ui = PUIQtCanvas(self, self.layout_width or 0, self.layout_height or 0)
|
|
117
|
+
self.ui.setMouseTracking(bool(self._onMouseMove))
|
|
118
|
+
self.ui.update()
|
|
119
|
+
super().update(prev)
|
|
120
|
+
|
|
121
|
+
def drawText(self, x, y, text, w=None, h=None, size=12, color=None, rotate=0, anchor=Anchor.LEFT_TOP):
|
|
122
|
+
if w is None:
|
|
123
|
+
w = self.ui.geometry().width()
|
|
124
|
+
if h is None:
|
|
125
|
+
h = self.ui.geometry().height()
|
|
126
|
+
self.qpainter.save()
|
|
127
|
+
br = self.qpainter.boundingRect(0, 0, w, h, 0, text)
|
|
128
|
+
self.qpainter.restore()
|
|
129
|
+
|
|
130
|
+
dx = 0
|
|
131
|
+
dy = 0
|
|
132
|
+
if anchor.value[0]=="center":
|
|
133
|
+
dx = br.width()/2
|
|
134
|
+
elif anchor.value[0]=="right":
|
|
135
|
+
dx = br.width()
|
|
136
|
+
|
|
137
|
+
if anchor.value[1]=="center":
|
|
138
|
+
dy = br.height()/2
|
|
139
|
+
elif anchor.value[1]=="bottom":
|
|
140
|
+
dy = br.height()
|
|
141
|
+
|
|
142
|
+
self.qpainter.save()
|
|
143
|
+
self.qpainter.translate(int(x+dx), int(y+dy))
|
|
144
|
+
self.qpainter.rotate(rotate)
|
|
145
|
+
self.qpainter.translate(int(-dx), int(-dy))
|
|
146
|
+
|
|
147
|
+
if size is not None:
|
|
148
|
+
font = self.qpainter.font()
|
|
149
|
+
font.setPointSize(size)
|
|
150
|
+
self.qpainter.setFont(font)
|
|
151
|
+
|
|
152
|
+
if color is not None:
|
|
153
|
+
self.qpainter.setPen(QColor(color))
|
|
154
|
+
|
|
155
|
+
self.qpainter.drawText(0, 0, w, h, 0, text)
|
|
156
|
+
self.qpainter.restore()
|
|
157
|
+
|
|
158
|
+
def drawLine(self, x1, y1, x2, y2, color=None, width=1):
|
|
159
|
+
self.qpainter.save()
|
|
160
|
+
|
|
161
|
+
pen = self.qpainter.pen()
|
|
162
|
+
if color is None:
|
|
163
|
+
pen.setStyle(QtCore.Qt.NoPen)
|
|
164
|
+
else:
|
|
165
|
+
pen.setStyle(QtCore.Qt.SolidLine)
|
|
166
|
+
pen.setColor(QColor(color))
|
|
167
|
+
pen.setWidth(width)
|
|
168
|
+
self.qpainter.setPen(pen)
|
|
169
|
+
|
|
170
|
+
self.qpainter.drawLine(x1, y1, x2, y2)
|
|
171
|
+
|
|
172
|
+
self.qpainter.restore()
|
|
173
|
+
|
|
174
|
+
def drawPolyline(self, coords, color=None, width=1):
|
|
175
|
+
self.qpainter.save()
|
|
176
|
+
|
|
177
|
+
pen = self.qpainter.pen()
|
|
178
|
+
if color is None:
|
|
179
|
+
pen.setStyle(QtCore.Qt.NoPen)
|
|
180
|
+
else:
|
|
181
|
+
pen.setStyle(QtCore.Qt.SolidLine)
|
|
182
|
+
pen.setColor(QColor(color))
|
|
183
|
+
pen.setWidth(width)
|
|
184
|
+
self.qpainter.setPen(pen)
|
|
185
|
+
|
|
186
|
+
self.qpainter.drawPolyline([QtCore.QPointF(x,y) for x,y in coords])
|
|
187
|
+
|
|
188
|
+
self.qpainter.restore()
|
|
189
|
+
|
|
190
|
+
def drawPolygon(self, coords, fill=None, stroke=None, width=1):
|
|
191
|
+
self.qpainter.save()
|
|
192
|
+
|
|
193
|
+
brush = self.qpainter.brush()
|
|
194
|
+
if fill is None:
|
|
195
|
+
brush.setStyle(QtCore.Qt.NoBrush)
|
|
196
|
+
else:
|
|
197
|
+
brush.setStyle(QtCore.Qt.SolidPattern)
|
|
198
|
+
brush.setColor(QColor(fill))
|
|
199
|
+
self.qpainter.setBrush(brush)
|
|
200
|
+
|
|
201
|
+
pen = self.qpainter.pen()
|
|
202
|
+
if stroke is None:
|
|
203
|
+
pen.setStyle(QtCore.Qt.NoPen)
|
|
204
|
+
else:
|
|
205
|
+
pen.setStyle(QtCore.Qt.SolidLine)
|
|
206
|
+
pen.setColor(QColor(stroke))
|
|
207
|
+
pen.setWidth(width)
|
|
208
|
+
self.qpainter.setPen(pen)
|
|
209
|
+
|
|
210
|
+
polygon = QtGui.QPolygonF()
|
|
211
|
+
for p in coords:
|
|
212
|
+
polygon.append(QtCore.QPointF(*p))
|
|
213
|
+
self.qpainter.drawPolygon(polygon)
|
|
214
|
+
|
|
215
|
+
self.qpainter.restore()
|
|
216
|
+
|
|
217
|
+
def drawRect(self, x1, y1, x2, y2, fill=None, stroke=None, width=1):
|
|
218
|
+
self.qpainter.save()
|
|
219
|
+
|
|
220
|
+
x = min(x1, x2)
|
|
221
|
+
y = min(y1, y2)
|
|
222
|
+
w = abs(x2-x1)
|
|
223
|
+
h = abs(y2-y1)
|
|
224
|
+
|
|
225
|
+
brush = self.qpainter.brush()
|
|
226
|
+
if fill is None:
|
|
227
|
+
brush.setStyle(QtCore.Qt.NoBrush)
|
|
228
|
+
else:
|
|
229
|
+
brush.setStyle(QtCore.Qt.SolidPattern)
|
|
230
|
+
brush.setColor(QColor(fill))
|
|
231
|
+
self.qpainter.setBrush(brush)
|
|
232
|
+
|
|
233
|
+
pen = self.qpainter.pen()
|
|
234
|
+
if stroke is None:
|
|
235
|
+
pen.setStyle(QtCore.Qt.NoPen)
|
|
236
|
+
else:
|
|
237
|
+
pen.setStyle(QtCore.Qt.SolidLine)
|
|
238
|
+
pen.setColor(QColor(stroke))
|
|
239
|
+
pen.setWidth(width)
|
|
240
|
+
self.qpainter.setPen(pen)
|
|
241
|
+
|
|
242
|
+
self.qpainter.drawRect(x, y, w, h)
|
|
243
|
+
|
|
244
|
+
self.qpainter.restore()
|
|
245
|
+
|
|
246
|
+
def drawEllipse(self, x, y, rx, ry, fill=None, stroke=None, width=1):
|
|
247
|
+
self.qpainter.save()
|
|
248
|
+
|
|
249
|
+
brush = self.qpainter.brush()
|
|
250
|
+
if fill is None:
|
|
251
|
+
brush.setStyle(QtCore.Qt.NoBrush)
|
|
252
|
+
else:
|
|
253
|
+
brush.setStyle(QtCore.Qt.SolidPattern)
|
|
254
|
+
brush.setColor(QColor(fill))
|
|
255
|
+
self.qpainter.setBrush(brush)
|
|
256
|
+
|
|
257
|
+
pen = self.qpainter.pen()
|
|
258
|
+
if stroke is None:
|
|
259
|
+
pen.setStyle(QtCore.Qt.NoPen)
|
|
260
|
+
else:
|
|
261
|
+
pen.setStyle(QtCore.Qt.SolidLine)
|
|
262
|
+
pen.setColor(QColor(stroke))
|
|
263
|
+
pen.setWidth(width)
|
|
264
|
+
self.qpainter.setPen(pen)
|
|
265
|
+
|
|
266
|
+
self.qpainter.drawEllipse(QtCore.QPointF(x,y), rx, ry)
|
|
267
|
+
|
|
268
|
+
self.qpainter.restore()
|
|
269
|
+
|
|
270
|
+
def drawShapely(self, shape, fill=None, stroke=None, width=1):
|
|
271
|
+
self.qpainter.save()
|
|
272
|
+
|
|
273
|
+
brush = self.qpainter.brush()
|
|
274
|
+
if fill is None:
|
|
275
|
+
brush.setStyle(QtCore.Qt.NoBrush)
|
|
276
|
+
else:
|
|
277
|
+
brush.setStyle(QtCore.Qt.SolidPattern)
|
|
278
|
+
brush.setColor(QColor(fill))
|
|
279
|
+
self.qpainter.setBrush(brush)
|
|
280
|
+
|
|
281
|
+
pen = self.qpainter.pen()
|
|
282
|
+
if stroke is None:
|
|
283
|
+
pen.setStyle(QtCore.Qt.NoPen)
|
|
284
|
+
else:
|
|
285
|
+
pen.setStyle(QtCore.Qt.SolidLine)
|
|
286
|
+
pen.setColor(QColor(stroke))
|
|
287
|
+
pen.setWidth(width)
|
|
288
|
+
self.qpainter.setPen(pen)
|
|
289
|
+
|
|
290
|
+
self._drawShapely(shape, fill, stroke, width)
|
|
291
|
+
|
|
292
|
+
self.qpainter.restore()
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def _drawShapely(self, shape, fill=None, stroke=None, width=1):
|
|
296
|
+
if hasattr(shape, "geoms"):
|
|
297
|
+
for g in shape.geoms:
|
|
298
|
+
self.drawShapely(g, fill, stroke, width)
|
|
299
|
+
elif hasattr(shape, "exterior"): # polygon
|
|
300
|
+
path = QPainterPath()
|
|
301
|
+
|
|
302
|
+
exterior = QtGui.QPolygonF()
|
|
303
|
+
for p in shape.exterior.coords:
|
|
304
|
+
exterior.append(QtCore.QPointF(*p))
|
|
305
|
+
path.addPolygon(exterior)
|
|
306
|
+
|
|
307
|
+
for h in shape.interiors:
|
|
308
|
+
hole = QtGui.QPolygonF()
|
|
309
|
+
for p in h.coords:
|
|
310
|
+
hole.append(QtCore.QPointF(*p))
|
|
311
|
+
hpoly = QPainterPath()
|
|
312
|
+
hpoly.addPolygon(hole)
|
|
313
|
+
path = path.subtracted(hpoly)
|
|
314
|
+
|
|
315
|
+
self.qpainter.drawPath(path)
|
|
316
|
+
elif hasattr(shape, "x") and hasattr(shape, "y"): # point
|
|
317
|
+
self.drawEllipse(shape.x, shape.y, width/2, width/2, fill=stroke)
|
|
318
|
+
elif hasattr(shape, "coords"): # linestring, linearring
|
|
319
|
+
self.drawPolyline(shape.coords, color=stroke, width=width)
|
|
320
|
+
else:
|
|
321
|
+
raise RuntimeError(f"Not implemented: drawShapely({type(shape).__name__}) {dir(shape)}")
|
|
322
|
+
|
|
323
|
+
def loadImage(self, image_path):
|
|
324
|
+
return ImageResource.load(image_path)
|
|
325
|
+
|
|
326
|
+
def drawImage(self, image, x=0, y=0, width=None, height=None, src_x=0, src_y=0, src_width=None, src_height=None, opacity=1.0):
|
|
327
|
+
if image.qimage.isNull():
|
|
328
|
+
return
|
|
329
|
+
|
|
330
|
+
if src_width is None:
|
|
331
|
+
src_width = image.qimage.width() - src_x
|
|
332
|
+
if src_height is None:
|
|
333
|
+
src_height = image.qimage.height() - src_y
|
|
334
|
+
|
|
335
|
+
source_rect = QtCore.QRect(src_x, src_y, src_width, src_height)
|
|
336
|
+
|
|
337
|
+
if width is None:
|
|
338
|
+
width = src_width
|
|
339
|
+
if height is None:
|
|
340
|
+
height = src_height
|
|
341
|
+
|
|
342
|
+
dest_rect = QtCore.QRect(x, y, width, height)
|
|
343
|
+
self.qpainter.setOpacity(opacity)
|
|
344
|
+
self.qpainter.drawImage(dest_rect, image.qimage, source_rect)
|
|
345
|
+
self.qpainter.setOpacity(1.0)
|
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)
|
PUI/PySide6/combobox.py
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
|
|
4
|
+
class ComboBox(QtBaseWidget):
|
|
5
|
+
pui_terminal = False
|
|
6
|
+
def __init__(self, editable=False, index_model=None, text_model=None):
|
|
7
|
+
super().__init__()
|
|
8
|
+
self.editable = editable
|
|
9
|
+
self.index_model = index_model
|
|
10
|
+
self.text_model = text_model
|
|
11
|
+
|
|
12
|
+
def update(self, prev):
|
|
13
|
+
if prev and prev.ui:
|
|
14
|
+
self.curr_index = prev.curr_index
|
|
15
|
+
self.curr_text = prev.curr_text
|
|
16
|
+
self.signal_connected = prev.signal_connected
|
|
17
|
+
self.ui = prev.ui
|
|
18
|
+
else:
|
|
19
|
+
self.curr_index = Prop()
|
|
20
|
+
self.curr_text = Prop()
|
|
21
|
+
self.signal_connected = False
|
|
22
|
+
self.ui = QtWidgets.QComboBox()
|
|
23
|
+
self.ui.setEditable(self.editable)
|
|
24
|
+
super().update(prev)
|
|
25
|
+
|
|
26
|
+
def postSync(self):
|
|
27
|
+
index = -1
|
|
28
|
+
text = ""
|
|
29
|
+
|
|
30
|
+
if self.index_model:
|
|
31
|
+
index = self.index_model.value
|
|
32
|
+
text = self.children[index].text
|
|
33
|
+
elif self.text_model:
|
|
34
|
+
text = str(self.text_model.value)
|
|
35
|
+
try:
|
|
36
|
+
index = [c.value for c in self.children].index(text)
|
|
37
|
+
except:
|
|
38
|
+
index = -1
|
|
39
|
+
|
|
40
|
+
if self.signal_connected:
|
|
41
|
+
self.ui.currentIndexChanged.disconnect()
|
|
42
|
+
self.ui.currentTextChanged.disconnect()
|
|
43
|
+
|
|
44
|
+
if self.curr_index.set(index):
|
|
45
|
+
self.ui.setCurrentIndex(index)
|
|
46
|
+
|
|
47
|
+
if self.curr_text.set(text):
|
|
48
|
+
self.ui.setCurrentText(text)
|
|
49
|
+
|
|
50
|
+
self.ui.currentIndexChanged.connect(self.on_currentIndexChanged)
|
|
51
|
+
self.ui.currentTextChanged.connect(self.on_currentTextChanged)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def on_currentIndexChanged(self, idx):
|
|
55
|
+
if self.index_model:
|
|
56
|
+
self.index_model.value = idx
|
|
57
|
+
if self.text_model:
|
|
58
|
+
self.text_model.value = self.children[idx].value
|
|
59
|
+
e = PUIEvent()
|
|
60
|
+
e.value = idx
|
|
61
|
+
self._change(e)
|
|
62
|
+
|
|
63
|
+
def on_currentTextChanged(self, text):
|
|
64
|
+
if not self.editable:
|
|
65
|
+
return
|
|
66
|
+
if self.text_model:
|
|
67
|
+
self.text_model.value = text
|
|
68
|
+
e = PUIEvent()
|
|
69
|
+
e.value = text
|
|
70
|
+
self._change(e)
|
|
71
|
+
|
|
72
|
+
def addChild(self, idx, child):
|
|
73
|
+
self.ui.insertItem(idx, child.text)
|
|
74
|
+
|
|
75
|
+
def removeChild(self, idx, child):
|
|
76
|
+
self.ui.removeItem(idx)
|
|
77
|
+
|
|
78
|
+
class ComboBoxItem(PUINode):
|
|
79
|
+
def __init__(self, text, value=None):
|
|
80
|
+
super().__init__()
|
|
81
|
+
self.id(text)
|
|
82
|
+
self.text = text
|
|
83
|
+
if value is None:
|
|
84
|
+
value = text
|
|
85
|
+
self.value = value
|
PUI/PySide6/dialog.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
|
|
4
|
+
def OpenDirectory(title="Open Directory", dir=None):
|
|
5
|
+
res = QtWidgets.QFileDialog.getExistingDirectory(None, title, dir)
|
|
6
|
+
return res
|
|
7
|
+
|
|
8
|
+
def OpenFile(title="Open File", dir=None, types=None):
|
|
9
|
+
if types:
|
|
10
|
+
types = types.replace("|", ";;")
|
|
11
|
+
res = QtWidgets.QFileDialog.getOpenFileName(None, title, dir, types)
|
|
12
|
+
return res[0] or None
|
|
13
|
+
|
|
14
|
+
def OpenFiles(title="Open Files", dir=None, types=None):
|
|
15
|
+
if types:
|
|
16
|
+
types = types.replace("|", ";;")
|
|
17
|
+
res = QtWidgets.QFileDialog.getOpenFileNames(None, title, dir, types)
|
|
18
|
+
return res[0] or None
|
|
19
|
+
|
|
20
|
+
def SaveFile(default, title="Save File", dir=None, types=None):
|
|
21
|
+
if types:
|
|
22
|
+
types = types.replace("|", ";;")
|
|
23
|
+
if not dir:
|
|
24
|
+
value = default
|
|
25
|
+
if isinstance(value, str):
|
|
26
|
+
dir = value
|
|
27
|
+
res = QtWidgets.QFileDialog.getSaveFileName(None, title, dir, types)
|
|
28
|
+
return res[0] or None
|
|
29
|
+
|
|
30
|
+
def Information(message="Information", title="Information Dialog"):
|
|
31
|
+
dlg = QtWidgets.QMessageBox(None)
|
|
32
|
+
dlg.setWindowTitle(title)
|
|
33
|
+
dlg.setText(message)
|
|
34
|
+
dlg.setStandardButtons(QtWidgets.QMessageBox.Ok)
|
|
35
|
+
dlg.setIcon(QtWidgets.QMessageBox.Information)
|
|
36
|
+
dlg.exec_()
|
|
37
|
+
|
|
38
|
+
def Warning(message="Warning", title="Warning Dialog"):
|
|
39
|
+
dlg = QtWidgets.QMessageBox(None)
|
|
40
|
+
dlg.setWindowTitle(title)
|
|
41
|
+
dlg.setText(message)
|
|
42
|
+
dlg.setStandardButtons(QtWidgets.QMessageBox.Ok)
|
|
43
|
+
dlg.setIcon(QtWidgets.QMessageBox.Warning)
|
|
44
|
+
dlg.exec_()
|
|
45
|
+
|
|
46
|
+
def Critical(message="Critical", title="Critical Dialog"):
|
|
47
|
+
dlg = QtWidgets.QMessageBox(None)
|
|
48
|
+
dlg.setWindowTitle(title)
|
|
49
|
+
dlg.setText(message)
|
|
50
|
+
dlg.setStandardButtons(QtWidgets.QMessageBox.Ok)
|
|
51
|
+
dlg.setIcon(QtWidgets.QMessageBox.Critical)
|
|
52
|
+
dlg.exec_()
|
|
53
|
+
|
|
54
|
+
def Confirm(message="Confirm", title="Confirm Dialog"):
|
|
55
|
+
dlg = QtWidgets.QMessageBox(None)
|
|
56
|
+
dlg.setWindowTitle(title)
|
|
57
|
+
dlg.setText(message)
|
|
58
|
+
dlg.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
|
|
59
|
+
dlg.setIcon(QtWidgets.QMessageBox.Question)
|
|
60
|
+
button = dlg.exec_()
|
|
61
|
+
|
|
62
|
+
if button == QtWidgets.QMessageBox.Yes:
|
|
63
|
+
return True
|
|
64
|
+
else:
|
|
65
|
+
return False
|
|
66
|
+
|
|
67
|
+
def Prompt(prompt="Input", title="Input Dialog", default=""):
|
|
68
|
+
text, ok = QtWidgets.QInputDialog.getText(None, title, prompt, QtWidgets.QLineEdit.Normal, default)
|
|
69
|
+
if ok:
|
|
70
|
+
return text
|
|
71
|
+
else:
|
|
72
|
+
return None
|
PUI/PySide6/divider.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
from .layout import *
|
|
4
|
+
|
|
5
|
+
class Divider(QtBaseWidget):
|
|
6
|
+
def __init__(self):
|
|
7
|
+
super().__init__()
|
|
8
|
+
|
|
9
|
+
def update(self, prev):
|
|
10
|
+
if prev and prev.ui:
|
|
11
|
+
self.ui = prev.ui
|
|
12
|
+
else:
|
|
13
|
+
self.ui = QtWidgets.QFrame()
|
|
14
|
+
parent = self.non_virtual_parent
|
|
15
|
+
if isinstance(parent, VBox):
|
|
16
|
+
self.ui.setFrameShape(QtWidgets.QFrame.Shape.HLine)
|
|
17
|
+
elif isinstance(parent, HBox):
|
|
18
|
+
self.ui.setFrameShape(QtWidgets.QFrame.Shape.VLine)
|
|
19
|
+
else:
|
|
20
|
+
self.ui.setFrameShape(QtWidgets.QFrame.Shape.NoFrame)
|
|
21
|
+
self.ui.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken)
|
|
22
|
+
|
|
23
|
+
super().update(prev)
|
PUI/PySide6/image.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
from .label import ClickableQLabel
|
|
4
|
+
from PySide6.QtWidgets import QSizePolicy
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
class Image(QtBaseWidget):
|
|
8
|
+
def __init__(self, path):
|
|
9
|
+
super().__init__()
|
|
10
|
+
self.path = path
|
|
11
|
+
self.pixmap = None
|
|
12
|
+
|
|
13
|
+
def update(self, prev):
|
|
14
|
+
if prev and prev.ui:
|
|
15
|
+
self.ui = prev.ui
|
|
16
|
+
self.eventFilter = prev.eventFilter
|
|
17
|
+
self.curr_path = prev.curr_path
|
|
18
|
+
self.curr_path_mtime = prev.curr_path_mtime
|
|
19
|
+
self.pixmap = prev.pixmap
|
|
20
|
+
else:
|
|
21
|
+
self.ui = ClickableQLabel()
|
|
22
|
+
self.ui.clicked.connect(self._clicked)
|
|
23
|
+
self.curr_path = Prop()
|
|
24
|
+
self.curr_path_mtime = Prop()
|
|
25
|
+
|
|
26
|
+
if self._onClicked:
|
|
27
|
+
self.ui.setCursor(QtCore.Qt.PointingHandCursor)
|
|
28
|
+
|
|
29
|
+
if self.layout_weight:
|
|
30
|
+
# XXX keep aspect ratio
|
|
31
|
+
self.ui.setScaledContents(True)
|
|
32
|
+
self.ui.setSizePolicy(QSizePolicy(QSizePolicy.Policy.Ignored, QSizePolicy.Policy.Ignored))
|
|
33
|
+
else:
|
|
34
|
+
self.ui.setScaledContents(False)
|
|
35
|
+
self.ui.setSizePolicy(QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Preferred))
|
|
36
|
+
|
|
37
|
+
if self.curr_path.set(self.path) or self.curr_path_mtime.set(os.path.getmtime(self.path)):
|
|
38
|
+
self.pixmap = QtGui.QPixmap(self.path)
|
|
39
|
+
if self.layout_width is not None and self.layout_height is not None:
|
|
40
|
+
self.pixmap = self.pixmap.scaled(self.layout_width, self.layout_height, QtCore.Qt.KeepAspectRatio, mode=QtCore.Qt.SmoothTransformation)
|
|
41
|
+
elif self.layout_width is not None:
|
|
42
|
+
self.pixmap = self.pixmap.scaledToWidth(self.layout_width, mode=QtCore.Qt.SmoothTransformation)
|
|
43
|
+
elif self.layout_height is not None:
|
|
44
|
+
self.pixmap = self.pixmap.scaledToHeight(self.layout_height, mode=QtCore.Qt.SmoothTransformation)
|
|
45
|
+
|
|
46
|
+
self.ui.setPixmap(self.pixmap)
|
|
47
|
+
|
|
48
|
+
super().update(prev)
|
PUI/PySide6/label.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
|
|
4
|
+
class ClickableQLabel(QtWidgets.QLabel):
|
|
5
|
+
clicked = QtCore.Signal()
|
|
6
|
+
|
|
7
|
+
def mousePressEvent(self, ev):
|
|
8
|
+
self.clicked.emit()
|
|
9
|
+
super().mousePressEvent(ev)
|
|
10
|
+
|
|
11
|
+
class Label(QtBaseWidget):
|
|
12
|
+
def __init__(self, text, selectable=False):
|
|
13
|
+
super().__init__()
|
|
14
|
+
self.text = str(text)
|
|
15
|
+
self.selectable = selectable
|
|
16
|
+
|
|
17
|
+
def update(self, prev):
|
|
18
|
+
if prev and prev.ui:
|
|
19
|
+
self.ui = prev.ui
|
|
20
|
+
self.ui.setText(self.text)
|
|
21
|
+
else:
|
|
22
|
+
self.ui = ClickableQLabel(self.text)
|
|
23
|
+
self.ui.setTextFormat(QtCore.Qt.TextFormat.PlainText)
|
|
24
|
+
self.ui.clicked.connect(self._clicked)
|
|
25
|
+
if self._onClicked:
|
|
26
|
+
self.ui.setCursor(QtCore.Qt.PointingHandCursor)
|
|
27
|
+
|
|
28
|
+
if self.selectable:
|
|
29
|
+
self.ui.setTextInteractionFlags(QtCore.Qt.TextInteractionFlag.TextSelectableByMouse)
|
|
30
|
+
else:
|
|
31
|
+
self.ui.setTextInteractionFlags(QtCore.Qt.TextInteractionFlag.NoTextInteraction)
|
|
32
|
+
|
|
33
|
+
super().update(prev)
|