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.

Files changed (103) hide show
  1. PUI/PySide6/__init__.py +49 -0
  2. PUI/PySide6/application.py +58 -0
  3. PUI/PySide6/base.py +222 -0
  4. PUI/PySide6/button.py +21 -0
  5. PUI/PySide6/canvas.py +288 -0
  6. PUI/PySide6/checkbox.py +32 -0
  7. PUI/PySide6/combobox.py +75 -0
  8. PUI/PySide6/dialog.py +72 -0
  9. PUI/PySide6/divider.py +23 -0
  10. PUI/PySide6/image.py +30 -0
  11. PUI/PySide6/label.py +33 -0
  12. PUI/PySide6/layout.py +72 -0
  13. PUI/PySide6/matplotlib.py +23 -0
  14. PUI/PySide6/mdi.py +33 -0
  15. PUI/PySide6/menu.py +85 -0
  16. PUI/PySide6/modal.py +132 -0
  17. PUI/PySide6/progressbar.py +17 -0
  18. PUI/PySide6/radiobutton.py +29 -0
  19. PUI/PySide6/scroll.py +153 -0
  20. PUI/PySide6/splitter.py +25 -0
  21. PUI/PySide6/tab.py +39 -0
  22. PUI/PySide6/table.py +89 -0
  23. PUI/PySide6/text.py +35 -0
  24. PUI/PySide6/textfield.py +62 -0
  25. PUI/PySide6/toolbar.py +57 -0
  26. PUI/PySide6/tree.py +120 -0
  27. PUI/PySide6/window.py +81 -0
  28. PUI/__init__.py +46 -0
  29. PUI/common.py +20 -0
  30. PUI/decorator.py +20 -0
  31. PUI/dom.py +238 -0
  32. PUI/flet/__init__.py +21 -0
  33. PUI/flet/application.py +42 -0
  34. PUI/flet/base.py +37 -0
  35. PUI/flet/button.py +20 -0
  36. PUI/flet/canvas.py +86 -0
  37. PUI/flet/checkbox.py +23 -0
  38. PUI/flet/label.py +27 -0
  39. PUI/flet/layout.py +50 -0
  40. PUI/flet/progressbar.py +21 -0
  41. PUI/flet/radiobutton.py +27 -0
  42. PUI/flet/scroll.py +83 -0
  43. PUI/flet/tab.py +42 -0
  44. PUI/flet/text.py +55 -0
  45. PUI/flet/textfield.py +58 -0
  46. PUI/flet/window.py +25 -0
  47. PUI/interfaces.py +97 -0
  48. PUI/node.py +407 -0
  49. PUI/state.py +698 -0
  50. PUI/textual/__init__.py +34 -0
  51. PUI/textual/application.py +82 -0
  52. PUI/textual/base.py +113 -0
  53. PUI/textual/button.py +17 -0
  54. PUI/textual/checkbox.py +21 -0
  55. PUI/textual/label.py +36 -0
  56. PUI/textual/layout.py +48 -0
  57. PUI/textual/progressbar.py +17 -0
  58. PUI/textual/radiobutton.py +24 -0
  59. PUI/textual/scroll.py +72 -0
  60. PUI/textual/tab.py +75 -0
  61. PUI/textual/text.py +32 -0
  62. PUI/textual/textfield.py +49 -0
  63. PUI/textual/window.py +7 -0
  64. PUI/timeline.py +36 -0
  65. PUI/tkinter/__init__.py +43 -0
  66. PUI/tkinter/application.py +49 -0
  67. PUI/tkinter/base.py +68 -0
  68. PUI/tkinter/button.py +15 -0
  69. PUI/tkinter/canvas.py +49 -0
  70. PUI/tkinter/checkbox.py +27 -0
  71. PUI/tkinter/label.py +17 -0
  72. PUI/tkinter/layout.py +114 -0
  73. PUI/tkinter/progressbar.py +17 -0
  74. PUI/tkinter/radiobutton.py +26 -0
  75. PUI/tkinter/scroll.py +201 -0
  76. PUI/tkinter/tab.py +52 -0
  77. PUI/tkinter/text.py +20 -0
  78. PUI/tkinter/textfield.py +53 -0
  79. PUI/tkinter/window.py +51 -0
  80. PUI/utils.py +15 -0
  81. PUI/view.py +161 -0
  82. PUI/wx/__init__.py +19 -0
  83. PUI/wx/application.py +44 -0
  84. PUI/wx/base.py +202 -0
  85. PUI/wx/button.py +16 -0
  86. PUI/wx/canvas.py +255 -0
  87. PUI/wx/checkbox.py +25 -0
  88. PUI/wx/combobox.py +72 -0
  89. PUI/wx/dialog.py +66 -0
  90. PUI/wx/divider.py +19 -0
  91. PUI/wx/label.py +18 -0
  92. PUI/wx/layout.py +46 -0
  93. PUI/wx/progressbar.py +17 -0
  94. PUI/wx/radiobutton.py +27 -0
  95. PUI/wx/scroll.py +44 -0
  96. PUI/wx/text.py +23 -0
  97. PUI/wx/textfield.py +56 -0
  98. PUI/wx/window.py +58 -0
  99. qpuiq-0.10.dist-info/LICENSE.txt +21 -0
  100. qpuiq-0.10.dist-info/METADATA +227 -0
  101. qpuiq-0.10.dist-info/RECORD +103 -0
  102. qpuiq-0.10.dist-info/WHEEL +5 -0
  103. qpuiq-0.10.dist-info/top_level.txt +1 -0
@@ -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)}")
@@ -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)