qpuiq 0.13__py3-none-any.whl → 0.14__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/base.py CHANGED
@@ -193,20 +193,20 @@ class QtBaseLayout(PUINode):
193
193
  from .modal import Modal
194
194
  from .layout import Spacer
195
195
  if isinstance(child, Spacer):
196
- self.layout.insertItem(idx, child.outer)
196
+ self.qtlayout.insertItem(idx, child.outer)
197
197
  elif isinstance(child, Modal):
198
198
  pass
199
199
  elif isinstance(child, QtBaseWidget) or isinstance(child, QtBaseLayout):
200
200
  params = {}
201
201
  if not child.layout_weight is None:
202
202
  params["stretch"] = child.layout_weight
203
- self.layout.insertWidget(idx, child.outer, **params)
203
+ self.qtlayout.insertWidget(idx, child.outer, **params)
204
204
 
205
205
  def removeChild(self, idx, child):
206
206
  from .modal import Modal
207
207
  from .layout import Spacer
208
208
  if isinstance(child, Spacer):
209
- self.layout.removeItem(child.outer)
209
+ self.qtlayout.removeItem(child.outer)
210
210
  elif isinstance(child, Modal):
211
211
  pass
212
212
  elif isinstance(child, QtBaseWidget) or isinstance(child, QtBaseLayout):
PUI/PySide6/canvas.py CHANGED
@@ -2,8 +2,7 @@ from .. import *
2
2
  from .base import *
3
3
 
4
4
  from PySide6 import QtWidgets, QtGui
5
- from PySide6.QtGui import QPainter, QColor, QPainterPath
6
- from PySide6.QtCore import QPoint
5
+ from PySide6.QtGui import QPainter, QColor, QPainterPath, QImage
7
6
 
8
7
  class PUIQtCanvas(QtWidgets.QWidget):
9
8
  def __init__(self, node, width=None, height=None):
@@ -46,6 +45,17 @@ class PUIQtCanvas(QtWidgets.QWidget):
46
45
  e.x_delta = event.pixelDelta().x()
47
46
  e.v_delta = event.angleDelta().y()
48
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
49
59
  self.node._wheel(e)
50
60
 
51
61
  def paintEvent(self, event):
@@ -61,6 +71,8 @@ class PUIQtCanvas(QtWidgets.QWidget):
61
71
  rect = QtCore.QRect(0, 0, self.width or self.geometry().width(), self.height or self.geometry().height())
62
72
  node.qpainter.fillRect(rect, bgBrush)
63
73
 
74
+ node.width = self.geometry().width()
75
+ node.height = self.geometry().height()
64
76
  node.painter(node, *node.args)
65
77
 
66
78
  node.qpainter.end()
@@ -286,3 +298,27 @@ class Canvas(QtBaseWidget):
286
298
  self.drawPolyline(shape.coords, color=stroke, width=width)
287
299
  else:
288
300
  raise RuntimeError(f"Not implemented: drawShapely({type(shape).__name__}) {dir(shape)}")
301
+
302
+ def loadImage(self, image_path):
303
+ return QImage(image_path)
304
+
305
+ 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):
306
+ if image.isNull():
307
+ return
308
+
309
+ if src_width is None:
310
+ src_width = image.width() - src_x
311
+ if src_height is None:
312
+ src_height = image.height() - src_y
313
+
314
+ source_rect = QtCore.QRect(src_x, src_y, src_width, src_height)
315
+
316
+ if width is None:
317
+ width = src_width
318
+ if height is None:
319
+ height = src_height
320
+
321
+ dest_rect = QtCore.QRect(x, y, width, height)
322
+ self.qpainter.setOpacity(opacity)
323
+ self.qpainter.drawImage(dest_rect, image, source_rect)
324
+ self.qpainter.setOpacity(1.0)
PUI/PySide6/combobox.py CHANGED
@@ -24,13 +24,16 @@ class ComboBox(QtBaseWidget):
24
24
  super().update(prev)
25
25
 
26
26
  def postSync(self):
27
+ index = 0
28
+ text = ""
29
+
27
30
  if self.index_model:
28
31
  index = self.index_model.value
29
32
  text = self.children[index].text
30
33
  elif self.text_model:
31
34
  text = str(self.text_model.value)
32
35
  try:
33
- index = [c.text for c in self.children].index(text)
36
+ index = [c.value for c in self.children].index(text)
34
37
  except:
35
38
  index = 0
36
39
 
@@ -51,11 +54,15 @@ class ComboBox(QtBaseWidget):
51
54
  def on_currentIndexChanged(self, idx):
52
55
  if self.index_model:
53
56
  self.index_model.value = idx
57
+ if self.text_model:
58
+ self.text_model.value = self.children[idx].value
54
59
  e = PUIEvent()
55
60
  e.value = idx
56
61
  self._change(e)
57
62
 
58
63
  def on_currentTextChanged(self, text):
64
+ if not self.editable:
65
+ return
59
66
  if self.text_model:
60
67
  self.text_model.value = text
61
68
  e = PUIEvent()
@@ -69,7 +76,10 @@ class ComboBox(QtBaseWidget):
69
76
  self.ui.removeItem(idx)
70
77
 
71
78
  class ComboBoxItem(PUINode):
72
- def __init__(self, text):
79
+ def __init__(self, text, value=None):
73
80
  super().__init__()
74
81
  self.id(text)
75
82
  self.text = text
83
+ if value is None:
84
+ value = text
85
+ self.value = value
PUI/PySide6/image.py CHANGED
@@ -1,5 +1,8 @@
1
1
  from .. import *
2
2
  from .base import *
3
+ from .label import ClickableQLabel
4
+ from PySide6.QtWidgets import QSizePolicy
5
+ import os
3
6
 
4
7
  class Image(QtBaseWidget):
5
8
  def __init__(self, path):
@@ -10,13 +13,28 @@ class Image(QtBaseWidget):
10
13
  def update(self, prev):
11
14
  if prev and prev.ui:
12
15
  self.ui = prev.ui
16
+ self.eventFilter = prev.eventFilter
13
17
  self.curr_path = prev.curr_path
18
+ self.curr_path_mtime = prev.curr_path_mtime
14
19
  self.pixmap = prev.pixmap
15
20
  else:
16
- self.ui = QtWidgets.QLabel()
21
+ self.ui = ClickableQLabel()
22
+ self.ui.clicked.connect(self._clicked)
17
23
  self.curr_path = Prop()
24
+ self.curr_path_mtime = Prop()
18
25
 
19
- if self.curr_path.set(self.path):
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)):
20
38
  self.pixmap = QtGui.QPixmap(self.path)
21
39
  if self.layout_width is not None and self.layout_height is not None:
22
40
  self.pixmap = self.pixmap.scaled(self.layout_width, self.layout_height, QtCore.Qt.KeepAspectRatio, mode=QtCore.Qt.SmoothTransformation)
PUI/PySide6/layout.py CHANGED
@@ -5,24 +5,24 @@ class HBox(QtBaseLayout):
5
5
  def update(self, prev):
6
6
  if prev and prev.ui:
7
7
  self.ui = prev.ui
8
- self.layout = prev.layout
8
+ self.qtlayout = prev.qtlayout
9
9
  else:
10
10
  self.ui = QtWidgets.QWidget()
11
- self.layout = QtWidgets.QHBoxLayout()
12
- self.layout.setContentsMargins(0,0,0,0)
13
- self.ui.setLayout(self.layout)
11
+ self.qtlayout = QtWidgets.QHBoxLayout()
12
+ self.qtlayout.setContentsMargins(0,0,0,0)
13
+ self.ui.setLayout(self.qtlayout)
14
14
  super().update(prev)
15
15
 
16
16
  class VBox(QtBaseLayout):
17
17
  def update(self, prev):
18
18
  if prev and prev.ui:
19
19
  self.ui = prev.ui
20
- self.layout = prev.layout
20
+ self.qtlayout = prev.qtlayout
21
21
  else:
22
22
  self.ui = QtWidgets.QWidget()
23
- self.layout = QtWidgets.QVBoxLayout()
24
- self.layout.setContentsMargins(0,0,0,0)
25
- self.ui.setLayout(self.layout)
23
+ self.qtlayout = QtWidgets.QVBoxLayout()
24
+ self.qtlayout.setContentsMargins(0,0,0,0)
25
+ self.ui.setLayout(self.qtlayout)
26
26
  super().update(prev)
27
27
 
28
28
  class Spacer(PUINode):
PUI/PySide6/tree.py CHANGED
@@ -2,6 +2,9 @@ from .. import *
2
2
  from .base import *
3
3
  from PySide6.QtCore import Qt, QModelIndex, QAbstractItemModel
4
4
 
5
+ # XXX
6
+ # If click handler triggers a model reset, dblclick handler will not be called
7
+
5
8
  class QAbstractItemModelAdapter(QtCore.QAbstractItemModel):
6
9
  def __init__(self, model: "BaseTreeAdapter"):
7
10
  super().__init__()
@@ -77,13 +80,12 @@ class QAbstractItemModelAdapter(QtCore.QAbstractItemModel):
77
80
  self.model.collapsed(node)
78
81
 
79
82
  class QTreeNodeModelAdapter(QtCore.QAbstractItemModel):
80
- def __init__(self, rootnode):
83
+ def __init__(self):
81
84
  super().__init__()
82
85
  self.node = None
83
- self.rootnode = rootnode
84
86
 
85
87
  def index(self, row, column, parent = QtCore.QModelIndex()):
86
- parent_node = parent.internalPointer() if parent.isValid() else self.rootnode
88
+ parent_node = parent.internalPointer() if parent.isValid() else self.node
87
89
  if 0 <= row and row < len(parent_node.children):
88
90
  child = parent_node.children[row]
89
91
  return self.createIndex(row, column, child)
@@ -130,14 +132,14 @@ class QTreeNodeModelAdapter(QtCore.QAbstractItemModel):
130
132
  return None
131
133
 
132
134
  def rowCount(self, parent):
133
- parent_node = parent.internalPointer() if parent.isValid() else self.rootnode
135
+ parent_node = parent.internalPointer() if parent.isValid() else self.node
134
136
  return len(parent_node.children)
135
137
 
136
138
  def columnCount(self, parent):
137
139
  return 1
138
140
 
139
141
  def hasChildren(self, parent):
140
- parent_node = parent.internalPointer() if parent.isValid() else self.rootnode
142
+ parent_node = parent.internalPointer() if parent.isValid() else self.node
141
143
  return len(parent_node.children) > 0
142
144
 
143
145
  def clicked(self, node):
@@ -167,15 +169,21 @@ class Tree(QtBaseWidget):
167
169
  self.ui = prev.ui
168
170
  self.qt_model = prev.qt_model
169
171
  self.curr_model = prev.curr_model
172
+
173
+ self.ui.clicked.disconnect()
174
+ self.ui.doubleClicked.disconnect()
175
+ self.ui.expanded.disconnect()
176
+ self.ui.collapsed.disconnect()
170
177
  else:
171
178
  self.qt_model = None
172
179
  self.curr_model = Prop()
173
180
  self.ui = QtWidgets.QTreeView()
174
181
  self.ui.setHeaderHidden(True)
175
- self.ui.clicked.connect(self.on_item_clicked)
176
- self.ui.doubleClicked.connect(self.on_item_double_clicked)
177
- self.ui.expanded.connect(self.on_item_expanded)
178
- self.ui.collapsed.connect(self.on_item_collapsed)
182
+
183
+ self.ui.clicked.connect(self.on_item_clicked)
184
+ self.ui.doubleClicked.connect(self.on_item_double_clicked)
185
+ self.ui.expanded.connect(self.on_item_expanded)
186
+ self.ui.collapsed.connect(self.on_item_collapsed)
179
187
 
180
188
  if self.model:
181
189
  if self.curr_model.set(self.model):
@@ -186,11 +194,13 @@ class Tree(QtBaseWidget):
186
194
  self.qt_model.modelReset.emit()
187
195
  else:
188
196
  if not self.qt_model:
189
- self.qt_model = QTreeNodeModelAdapter(self)
197
+ self.qt_model = QTreeNodeModelAdapter()
190
198
  self.qt_model.node = self
191
199
  self.ui.setModel(self.qt_model)
192
200
  else:
193
- self.qt_model.modelReset.emit()
201
+ self.qt_model.beginResetModel()
202
+ self.qt_model.node = self
203
+ self.qt_model.endResetModel()
194
204
 
195
205
  for pending in self.pendings:
196
206
  pending[0](*pending[1:])
@@ -239,19 +249,19 @@ class Tree(QtBaseWidget):
239
249
 
240
250
  def on_item_clicked(self, index):
241
251
  treenode = index.internalPointer()
242
- self.qt_model.clicked(treenode)
252
+ self.get_node().qt_model.clicked(treenode)
243
253
 
244
254
  def on_item_double_clicked(self, index):
245
255
  treenode = index.internalPointer()
246
- self.qt_model.dblclicked(treenode)
256
+ self.get_node().qt_model.dblclicked(treenode)
247
257
 
248
258
  def on_item_expanded(self, index):
249
259
  treenode = index.internalPointer()
250
- self.qt_model.expanded(treenode)
260
+ self.get_node().qt_model.expanded(treenode)
251
261
 
252
262
  def on_item_collapsed(self, index):
253
263
  treenode = index.internalPointer()
254
- self.qt_model.collapsed(treenode)
264
+ self.get_node().qt_model.collapsed(treenode)
255
265
 
256
266
  class TreeNode(PUINode):
257
267
  def __init__(self, data=""):
PUI/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = "0.13"
1
+ __version__ = "0.14"
2
2
 
3
3
  from .node import *
4
4
  from .view import *
PUI/common.py CHANGED
@@ -18,3 +18,9 @@ class MouseButton(IntEnum):
18
18
  MIDDLE = 4
19
19
  X1 = 8
20
20
  X2 = 16
21
+
22
+ class KeyModifier(IntEnum):
23
+ SHIFT = 1
24
+ CTRL = 2
25
+ ALT = 4
26
+ META = 8
PUI/textual/__init__.py CHANGED
@@ -30,5 +30,6 @@ class DummyWidget(TBase):
30
30
  Canvas = DummyWidget
31
31
  Combobox = DummyWidget
32
32
  ComboboxItem = DummyWidget
33
+ Divider = lambda: None
33
34
 
34
35
  PUI_BACKEND = "textual"
PUI/textual/base.py CHANGED
@@ -3,24 +3,57 @@ from textual import widgets, containers
3
3
 
4
4
  class TBase(PUINode):
5
5
  scroll = False
6
- container_x = False
7
- container_y = False
8
- strong_expand_x = False
9
- strong_expand_y = False
10
- weak_expand_x = False
11
- weak_expand_y = False
12
- nweak_expand_x = False
13
- nweak_expand_y = False
14
- strong_expand_x_children = 0
15
- strong_expand_y_children = 0
6
+ container_x = False # axis
7
+ container_y = False # axis
8
+ expand_x_prio = 0
9
+ expand_y_prio = 0
10
+ expand_x1_children = 0
11
+ expand_x2_children = 0
12
+ expand_x3_children = 0
13
+ expand_x4_children = 0
14
+ expand_y1_children = 0
15
+ expand_y2_children = 0
16
+ expand_y3_children = 0
17
+ expand_y4_children = 0
18
+ cached_tparent = None
16
19
 
17
20
  @property
18
21
  def expand_x(self):
19
- return self.strong_expand_x or (self.weak_expand_x and not self.nweak_expand_x)
22
+ parent = self.cached_tparent
23
+ expand = self.expand_x_prio
24
+ if not parent:
25
+ return False
26
+
27
+ # textual handles 1fr as shrinkable, but we need scrolller's content not to shrink
28
+ # See Exp.1 in refs/textual_layout.py
29
+ if parent.scroll:
30
+ return False
31
+
32
+ # textual populates auto(1fr) to be 1fr(1fr), but we require expanding not to go over the container
33
+ # See Exp.2 in refs/textual_layout.py
34
+ if not parent.expand_x and expand < 3:
35
+ return False
36
+
37
+ return expand
20
38
 
21
39
  @property
22
40
  def expand_y(self):
23
- return self.strong_expand_y or (self.weak_expand_y and not self.nweak_expand_y)
41
+ parent = self.cached_tparent
42
+ expand = self.expand_y_prio
43
+ if not parent:
44
+ return False
45
+
46
+ # textual handles 1fr as shrinkable, but we need scrolller's content not to shrink
47
+ # See Exp.1 in refs/textual_layout.py
48
+ if parent.scroll:
49
+ return False
50
+
51
+ # textual populates auto(1fr) to be 1fr(1fr), but we require expanding not to go over the container
52
+ # See Exp.2 in refs/textual_layout.py
53
+ if not parent.expand_y and expand < 3:
54
+ return False
55
+
56
+ return expand
24
57
 
25
58
  def tremove(self):
26
59
  self.ui.remove()
@@ -30,57 +63,58 @@ class TBase(PUINode):
30
63
  return super().destroy(direct)
31
64
 
32
65
  def update(self, prev):
33
- parent = self.tparent
66
+ super().update(prev)
67
+
68
+ self.cached_tparent = parent = self.tparent
34
69
  if parent:
35
- if not parent.scroll and len(parent.children) == 1:
36
- if parent.expand_x:
37
- self.strong_expand_x = True
38
- if parent.expand_y:
39
- self.strong_expand_y = True
70
+ if self.layout_weight:
71
+ if parent.container_x:
72
+ self.expand_x_prio = 4
73
+ if parent.container_y:
74
+ self.expand_y_prio = 4
75
+
76
+ if self.expand_x_prio >= 1:
77
+ parent.expand_x1_children += 1
78
+ if self.expand_x_prio >= 2:
79
+ parent.expand_x2_children += 1
80
+ if self.expand_x_prio >= 3:
81
+ parent.expand_x3_children += 1
82
+ if self.expand_x_prio >= 4:
83
+ parent.expand_x4_children += 1
84
+
85
+ if self.expand_y_prio >= 1:
86
+ parent.expand_y1_children += 1
87
+ if self.expand_y_prio >= 2:
88
+ parent.expand_y2_children += 1
89
+ if self.expand_y_prio >= 3:
90
+ parent.expand_y3_children += 1
91
+ if self.expand_y_prio >= 4:
92
+ parent.expand_y4_children += 1
40
93
 
41
- # request expanding from inside
94
+ def postUpdate(self):
95
+ super().postUpdate()
96
+ parent = self.cached_tparent
97
+ if parent:
42
98
  if parent.container_x:
43
- if parent.expand_y:
44
- self.strong_expand_y = True
45
- if self.layout_weight:
46
- self.strong_expand_x = True
47
- parent.strong_expand_x_children += 1
48
- p = parent
49
- while p:
50
- if isinstance(p, TBase):
51
- p.weak_expand_x = True
52
- if p==p.parent:
53
- break
54
- p = p.parent
99
+ if self.expand_x_prio < 1 and parent.expand_x1_children > 0:
100
+ self.expand_x_prio = 0
101
+ if self.expand_x_prio < 2 and parent.expand_x2_children > 0:
102
+ self.expand_x_prio = 0
103
+ if self.expand_x_prio < 3 and parent.expand_x3_children > 0:
104
+ self.expand_x_prio = 0
105
+ if self.expand_x_prio < 4 and parent.expand_x4_children > 0:
106
+ self.expand_x_prio = 0
55
107
 
56
108
  if parent.container_y:
57
- if parent.expand_x:
58
- self.strong_expand_x = True
59
- if self.layout_weight:
60
- self.strong_expand_y = True
61
- parent.strong_expand_y_children += 1
62
- p = parent
63
- while p:
64
- if isinstance(p, TBase):
65
- p.weak_expand_y = True
66
- if p==p.parent:
67
- break
68
- p = p.parent
69
-
70
- if parent.strong_expand_x_children > 0:
71
- self.nweak_expand_x = True
72
- if parent.strong_expand_y_children > 0:
73
- self.nweak_expand_y = True
74
-
75
- else:
76
- # mark root node as expanding
77
- self.strong_expand_x = True
78
- self.strong_expand_y = True
109
+ if self.expand_y_prio < 1 and parent.expand_y1_children > 0:
110
+ self.expand_y_prio = 0
111
+ if self.expand_y_prio < 2 and parent.expand_y2_children > 0:
112
+ self.expand_y_prio = 0
113
+ if self.expand_y_prio < 3 and parent.expand_y3_children > 0:
114
+ self.expand_y_prio = 0
115
+ if self.expand_y_prio < 4 and parent.expand_y4_children > 0:
116
+ self.expand_y_prio = 0
79
117
 
80
- super().update(prev)
81
-
82
- def postUpdate(self):
83
- super().postUpdate()
84
118
  self.t_update_layout()
85
119
 
86
120
  @property
@@ -106,8 +140,9 @@ class TBase(PUINode):
106
140
  height = "1fr"
107
141
 
108
142
  if self._debug:
109
- print("layout", self.key, f"{width}:{height} expand_x={self.expand_x}", f"expand_y={self.expand_y}", f"strong_x={self.strong_expand_x}", f"weak_x={self.weak_expand_x}", f"hug_x={self.nweak_expand_x}", f"strong_y={self.strong_expand_y}", f"weak_y={self.weak_expand_y}", f"hug_y={self.nweak_expand_y}")
110
- self.ui.set_styles(f"width:{width};height:{height};")
143
+ print("layout", self.key, f"{width}:{height} expand_x={self.expand_x}", f"expand_y={self.expand_y}", f"expand_x_prio={self.expand_x_prio}", f"expand_y_prio={self.expand_y_prio}")
144
+ self.ui.styles.width = width
145
+ self.ui.styles.height = height
111
146
 
112
147
  class TPUIView(PUIView):
113
148
  pui_virtual = True
PUI/textual/label.py CHANGED
@@ -13,13 +13,12 @@ class Label(TBase):
13
13
  self.widget = prev.widget
14
14
  else:
15
15
  self.ui = containers.Container()
16
- self.ui.set_styles("width: auto; height: auto;")
17
16
  if self._onClicked:
18
17
  if self.widget is None or not isinstance(self.widget, widgets.Button):
19
18
  if self.widget:
20
19
  self.widget.remove()
21
20
  self.widget = widgets.Button(self.text)
22
- self.widget.set_styles("height: auto; border-top: none; border-bottom: none;")
21
+ self.widget.set_styles("border-top: none; border-bottom: none;")
23
22
  self.widget.puinode = self
24
23
  else:
25
24
  self.widget.label = self.text
@@ -33,4 +32,5 @@ class Label(TBase):
33
32
  super().update(prev)
34
33
 
35
34
  def postUpdate(self):
35
+ super().postUpdate()
36
36
  self.ui.mount(self.widget)
PUI/textual/layout.py CHANGED
@@ -3,6 +3,8 @@ from .base import *
3
3
 
4
4
  class VBox(TBase):
5
5
  container_y = True
6
+ expand_x_prio = 1
7
+ expand_y_prio = 2
6
8
  def update(self, prev):
7
9
  if prev and prev.ui:
8
10
  self.ui = prev.ui
@@ -20,6 +22,8 @@ class VBox(TBase):
20
22
 
21
23
  class HBox(TBase):
22
24
  container_x = True
25
+ expand_x_prio = 2
26
+ expand_y_prio = 1
23
27
  def update(self, prev):
24
28
  if prev and prev.ui:
25
29
  self.ui = prev.ui
PUI/textual/scroll.py CHANGED
@@ -4,8 +4,6 @@ import math
4
4
 
5
5
  class Scroll(TBase):
6
6
  END = -0.0
7
- weak_expand_x = True
8
- weak_expand_y = True
9
7
  scroll = True
10
8
  def __init__(self, vertical=None, horizontal=False):
11
9
  self.vertical = vertical
@@ -19,23 +17,27 @@ class Scroll(TBase):
19
17
  self.ui = prev.ui
20
18
  else:
21
19
  self.ui = containers.ScrollableContainer()
20
+
22
21
  v = "auto"
23
22
  self.container_y = True
23
+ self.expand_y_prio = 3
24
24
  if self.vertical is True:
25
25
  v = "scroll"
26
26
  elif self.vertical is False:
27
27
  v = "hidden"
28
28
  self.container_y = False
29
- self.nweak_expand_y = True # discard weak_expand_x from self
29
+ self.expand_y_prio = 1
30
30
 
31
31
  h = "auto"
32
32
  self.container_x = True
33
+ self.expand_x_prio = 3
33
34
  if self.horizontal is True:
34
35
  h = "scroll"
35
36
  elif self.horizontal is False:
36
37
  h = "hidden"
37
38
  self.container_x = False
38
- self.nweak_expand_x = True # discard weak_expand_y from self
39
+ self.expand_x_prio = 1
40
+
39
41
  self.ui.set_styles(f"overflow-x: {h}; overflow-y: {v};")
40
42
 
41
43
  super().update(prev)
PUI/tkinter/canvas.py CHANGED
@@ -3,6 +3,9 @@ from .base import *
3
3
  import itertools
4
4
  class Canvas(TkBaseWidget):
5
5
  pui_terminal = True
6
+ expand_x_prio = 2
7
+ expand_y_prio = 2
8
+
6
9
  def __init__(self, painter, *args):
7
10
  super().__init__()
8
11
  self.painter = painter
PUI/wx/base.py CHANGED
@@ -45,74 +45,86 @@ class WxPUIView(PUIView):
45
45
 
46
46
  class WXBase(PUINode):
47
47
  scroll = False
48
- container_x = False
49
- container_y = False
50
- strong_expand_x = False
51
- strong_expand_y = False
52
- weak_expand_x = False
53
- weak_expand_y = False
54
- nweak_expand_x = False
55
- nweak_expand_y = False
56
- strong_expand_x_children = 0
57
- strong_expand_y_children = 0
48
+ container_x = False # axis
49
+ container_y = False # axis
50
+ expand_x_prio = 0
51
+ expand_y_prio = 0
52
+ expand_x1_children = 0
53
+ expand_x2_children = 0
54
+ expand_x3_children = 0
55
+ expand_x4_children = 0
56
+ expand_y1_children = 0
57
+ expand_y2_children = 0
58
+ expand_y3_children = 0
59
+ expand_y4_children = 0
60
+ cached_wxparent = None
58
61
 
59
62
  @property
60
63
  def expand_x(self):
61
- return self.strong_expand_x or (self.weak_expand_x and not self.nweak_expand_x)
64
+ return self.expand_x_prio
62
65
 
63
66
  @property
64
67
  def expand_y(self):
65
- return self.strong_expand_y or (self.weak_expand_y and not self.nweak_expand_y)
68
+ return self.expand_y_prio
66
69
 
67
70
  def update(self, prev):
71
+ self.cached_wxparent = parent = self.wxparent
72
+
68
73
  parent = self.wxparent
69
74
  if parent:
70
- if not parent.scroll and len(parent.children) == 1:
71
- if parent.expand_x:
72
- self.strong_expand_x = True
73
- if parent.expand_y:
74
- self.strong_expand_y = True
75
+ if self.layout_weight:
76
+ if parent.container_x:
77
+ self.expand_x_prio = 4
78
+ if parent.container_y:
79
+ self.expand_y_prio = 4
80
+
81
+ if self.expand_x_prio >= 1:
82
+ parent.expand_x1_children += 1
83
+ if self.expand_x_prio >= 2:
84
+ parent.expand_x2_children += 1
85
+ if self.expand_x_prio >= 3:
86
+ parent.expand_x3_children += 1
87
+ if self.expand_x_prio >= 4:
88
+ parent.expand_x4_children += 1
89
+
90
+ if self.expand_y_prio >= 1:
91
+ parent.expand_y1_children += 1
92
+ if self.expand_y_prio >= 2:
93
+ parent.expand_y2_children += 1
94
+ if self.expand_y_prio >= 3:
95
+ parent.expand_y3_children += 1
96
+ if self.expand_y_prio >= 4:
97
+ parent.expand_y4_children += 1
98
+
99
+ super().update(prev)
75
100
 
76
- # request expanding from inside
101
+ def postUpdate(self):
102
+ parent = self.cached_wxparent
103
+ if parent:
77
104
  if parent.container_x:
78
- if parent.expand_y:
79
- self.strong_expand_y = True
80
- if self.layout_weight:
81
- self.strong_expand_x = True
82
- parent.strong_expand_x_children += 1
83
- p = parent
84
- while p:
85
- if isinstance(p, WXBase):
86
- p.weak_expand_x = True
87
- if p==p.parent:
88
- break
89
- p = p.parent
105
+ if self.expand_x_prio < 1 and parent.expand_x1_children > 0:
106
+ self.expand_x_prio = 0
107
+ if self.expand_x_prio < 2 and parent.expand_x2_children > 0:
108
+ self.expand_x_prio = 0
109
+ if self.expand_x_prio < 3 and parent.expand_x3_children > 0:
110
+ self.expand_x_prio = 0
111
+ if self.expand_x_prio < 4 and parent.expand_x4_children > 0:
112
+ self.expand_x_prio = 0
90
113
 
91
114
  if parent.container_y:
92
- if parent.expand_x:
93
- self.strong_expand_x = True
94
- if self.layout_weight:
95
- self.strong_expand_y = True
96
- parent.strong_expand_y_children += 1
97
- p = parent
98
- while p:
99
- if isinstance(p, WXBase):
100
- p.weak_expand_y = True
101
- if p==p.parent:
102
- break
103
- p = p.parent
104
-
105
- if parent.strong_expand_x_children > 0:
106
- self.nweak_expand_x = True
107
- if parent.strong_expand_y_children > 0:
108
- self.nweak_expand_y = True
115
+ if self.expand_y_prio < 1 and parent.expand_y1_children > 0:
116
+ self.expand_y_prio = 0
117
+ if self.expand_y_prio < 2 and parent.expand_y2_children > 0:
118
+ self.expand_y_prio = 0
119
+ if self.expand_y_prio < 3 and parent.expand_y3_children > 0:
120
+ self.expand_y_prio = 0
121
+ if self.expand_y_prio < 4 and parent.expand_y4_children > 0:
122
+ self.expand_y_prio = 0
109
123
 
110
- else:
111
- # mark root node as expanding
112
- self.strong_expand_x = True
113
- self.strong_expand_y = True
124
+ if self._debug:
125
+ print("layout", self.key, f"weight={self.layout_weight}", f"expand_x={self.expand_x}", f"expand_y={self.expand_y}")
114
126
 
115
- super().update(prev)
127
+ super().postUpdate()
116
128
 
117
129
  @property
118
130
  def wxparent(self):
@@ -153,6 +165,7 @@ class WxBaseWidget(WXBase):
153
165
  class WxBaseLayout(WXBase):
154
166
  def __init__(self):
155
167
  super().__init__()
168
+ self.relayout = False
156
169
  if not isinstance(self.non_virtual_parent, WxBaseLayout):
157
170
  self.layout_padding = (11,11,11,11)
158
171
 
@@ -161,8 +174,38 @@ class WxBaseLayout(WXBase):
161
174
  self.ui = None
162
175
  super().destroy(direct)
163
176
 
177
+ def update(self, prev):
178
+ if prev and prev.ui:
179
+ self.sizerItems = prev.sizerItems
180
+ else:
181
+ self.sizerItems = []
182
+ super().update(prev)
183
+
184
+ def postUpdate(self):
185
+ super().postUpdate()
186
+
187
+ for child, si in self.sizerItems:
188
+ if child.expand_x or child.expand_y:
189
+ si.SetFlag(wx.ALL | wx.EXPAND)
190
+ else:
191
+ # si.SetFlag(wx.ALL | wx.ALIGN_CENTER)
192
+ si.SetFlag(wx.ALL) # XXX
193
+
194
+ weight = child.layout_weight
195
+ if self.container_x and child.expand_x:
196
+ si.SetProportion(weight if weight else 1 if child.expand_x else 0)
197
+ elif self.container_y and child.expand_y:
198
+ si.SetProportion(weight if weight else 1 if child.expand_y else 0)
199
+
200
+ p = 0
201
+ if child.layout_padding:
202
+ p = max(child.layout_padding)
203
+ si.SetBorder(p)
204
+
164
205
  def addChild(self, idx, child):
165
206
  from .layout import Spacer
207
+ self.relayout = True
208
+
166
209
  weight = child.layout_weight
167
210
  if weight is None:
168
211
  weight = 0
@@ -170,33 +213,34 @@ class WxBaseLayout(WXBase):
170
213
  weight = 1
171
214
  if not weight and self.container_y and child.expand_y:
172
215
  weight = 1
173
- flag = wx.ALL
174
216
 
175
- p = 0
176
- if child.layout_padding:
177
- p = max(child.layout_padding)
178
217
  if isinstance(child, WxBaseLayout):
179
- self.ui.Insert(idx, child.outer, proportion=weight, flag=flag|wx.EXPAND, border=p)
218
+ si = self.ui.Insert(idx, child.outer)
219
+ self.sizerItems.insert(idx, (child, si))
180
220
  elif isinstance(child, WxBaseWidget):
181
- if child.expand_x or child.expand_y or child.weak_expand_x or child.weak_expand_y:
182
- flag |= wx.EXPAND
183
- else:
184
- flag |= wx.ALIGN_CENTER
185
- self.ui.Insert(idx, child.outer, proportion=weight, flag=flag, border=p)
221
+ si = self.ui.Insert(idx, child.outer)
222
+ self.sizerItems.insert(idx, (child, si))
186
223
  elif isinstance(child, Spacer):
187
- self.ui.InsertStretchSpacer(idx, weight)
224
+ si = self.ui.InsertStretchSpacer(idx)
225
+ self.sizerItems.insert(idx, (child, si))
188
226
 
189
227
  def removeChild(self, idx, child):
228
+ self.relayout = True
229
+
190
230
  from .layout import Spacer
191
231
  if isinstance(child, WxBaseLayout):
192
232
  self.ui.Detach(idx)
233
+ self.sizerItems.pop(idx)
193
234
  elif isinstance(child, WxBaseWidget):
194
235
  self.ui.Detach(idx)
236
+ self.sizerItems.pop(idx)
195
237
  elif isinstance(child, Spacer):
196
238
  self.ui.Detach(idx)
239
+ self.sizerItems.pop(idx)
197
240
 
198
241
  def postSync(self):
199
- if self.ui:
242
+ if self.relayout and self.ui:
243
+ self.relayout = False
200
244
  self.ui.Layout()
201
- self.ui.Fit(getWindow(self.parent))
245
+ # self.ui.Fit(getWindow(self.parent))
202
246
  super().postSync()
PUI/wx/canvas.py CHANGED
@@ -3,8 +3,8 @@ from .base import *
3
3
  import math
4
4
 
5
5
  class Canvas(WxBaseWidget):
6
- weak_expand_x = True
7
- weak_expand_y = True
6
+ expand_x_prio = 3
7
+ expand_y_prio = 3
8
8
 
9
9
  def __init__(self, painter, *args):
10
10
  super().__init__()
PUI/wx/combobox.py CHANGED
@@ -17,20 +17,23 @@ class ComboBox(WxBaseWidget):
17
17
  else:
18
18
  self.curr_index = Prop()
19
19
  self.curr_text = Prop()
20
- self.ui = wx.ComboBox(getWindow(self.parent), choices=[])
20
+ self.ui = wx.ComboBox(getWindow(self.parent), choices=[], style=0 if self.editable else wx.CB_READONLY)
21
21
  self.ui.Bind(wx.EVT_COMBOBOX, self._combobox)
22
22
  self.ui.Bind(wx.EVT_TEXT, self._text)
23
23
 
24
24
  super().update(prev)
25
25
 
26
26
  def postSync(self):
27
+ index = 0
28
+ text = ""
29
+
27
30
  if self.index_model:
28
31
  index = self.index_model.value
29
32
  text = self.children[index].text
30
33
  elif self.text_model:
31
34
  text = str(self.text_model.value)
32
35
  try:
33
- index = [c.text for c in self.children].index(text)
36
+ index = [c.value for c in self.children].index(text)
34
37
  except:
35
38
  index = 0
36
39
 
@@ -45,11 +48,15 @@ class ComboBox(WxBaseWidget):
45
48
  idx = self.ui.GetSelection()
46
49
  if node.index_model:
47
50
  node.index_model.value = idx
51
+ if node.text_model:
52
+ node.text_model.value = self.children[idx].value
48
53
  e = PUIEvent()
49
54
  e.value = idx
50
55
  node._change(e)
51
56
 
52
57
  def _text(self, *args, **kwargs):
58
+ if not self.editable:
59
+ return
53
60
  node = self.get_node()
54
61
  text = self.ui.GetValue()
55
62
  if node.text_model:
@@ -64,9 +71,11 @@ class ComboBox(WxBaseWidget):
64
71
  def removeChild(self, idx, child):
65
72
  self.ui.Delete(idx)
66
73
 
67
-
68
74
  class ComboBoxItem(PUINode):
69
- def __init__(self, text):
75
+ def __init__(self, text, value=None):
70
76
  super().__init__()
71
77
  self.id(text)
72
78
  self.text = text
79
+ if value is None:
80
+ value = text
81
+ self.value = value
PUI/wx/layout.py CHANGED
@@ -3,6 +3,9 @@ from .base import *
3
3
 
4
4
  class HBox(WxBaseLayout):
5
5
  container_x = True
6
+ expand_x_prio = 2
7
+ expand_y_prio = 1
8
+
6
9
  def update(self, prev):
7
10
  if prev and prev.ui:
8
11
  self.ui = prev.ui
@@ -12,6 +15,9 @@ class HBox(WxBaseLayout):
12
15
 
13
16
  class VBox(WxBaseLayout):
14
17
  container_y = True
18
+ expand_x_prio = 1
19
+ expand_y_prio = 2
20
+
15
21
  def update(self, prev):
16
22
  if prev and prev.ui:
17
23
  self.ui = prev.ui
PUI/wx/scroll.py CHANGED
@@ -4,8 +4,6 @@ import wx.lib.scrolledpanel as scrolled
4
4
 
5
5
  class Scroll(WxBaseWidget):
6
6
  pui_terminal = False
7
- weak_expand_x = True
8
- weak_expand_y = True
9
7
  scroll = True
10
8
 
11
9
  END = -0.0
@@ -20,6 +18,19 @@ class Scroll(WxBaseWidget):
20
18
  self.ui = prev.ui
21
19
  else:
22
20
  self.ui = scrolled.ScrolledPanel(getWindow(self.parent))
21
+
22
+ self.container_y = True
23
+ self.expand_y_prio = 3
24
+ if self.vertical is False:
25
+ self.container_y = False
26
+ self.expand_y_prio = 1
27
+
28
+ self.container_x = True
29
+ self.expand_x_prio = 3
30
+ if self.horizontal is False:
31
+ self.container_x = False
32
+ self.expand_x_prio = 1
33
+
23
34
  super().update(prev)
24
35
 
25
36
  def addChild(self, idx, child):
@@ -1,12 +1,19 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: qpuiq
3
- Version: 0.13
3
+ Version: 0.14
4
4
  Summary: "PUI" Python Declarative UI Framework
5
5
  Home-page: https://github.com/buganini/PUI
6
6
  Author: Buganini Chiu
7
7
  Author-email: buganini@b612.tw
8
8
  Description-Content-Type: text/markdown
9
9
  License-File: LICENSE.txt
10
+ Dynamic: author
11
+ Dynamic: author-email
12
+ Dynamic: description
13
+ Dynamic: description-content-type
14
+ Dynamic: home-page
15
+ Dynamic: license-file
16
+ Dynamic: summary
10
17
 
11
18
  # What is PUI
12
19
  PUI is a reactive/declarative UI framework with two-way data binding.
@@ -205,8 +212,9 @@ Then PUI will take care of view update [(code)](https://github.com/buganini/PUI/
205
212
  * textual (Text Mode)
206
213
  * no canvas
207
214
 
208
- # Components
209
- [Reference](REFERENCE.md)
215
+ # Documents
216
+ * [Components Reference](REFERENCE.md)
217
+ * [Sizing Strategy](https://html-preview.github.io/?url=https://github.com/buganini/PUI/blob/main/doc/Sizing.html)
210
218
 
211
219
  # Used by
212
220
  * https://github.com/buganini/kikit-ui
@@ -1,5 +1,5 @@
1
- PUI/__init__.py,sha256=KjpRQ20XzEqx9cTu0YVz7wUSCWsi1lsw9ecARH2Rw7U,966
2
- PUI/common.py,sha256=iCMdJPgdKxnZObpjjYzxa_LN8eS4w0FOTfgaDwD_fGY,500
1
+ PUI/__init__.py,sha256=1cYRM8ouBVNa_BIQAMNzSyQJ5Ym-NMT-IL5Zp5mctfk,966
2
+ PUI/common.py,sha256=fUJmHOu5lSCeiOhFDF6YqulJxFqWmsneqnDZ2kZFFmM,581
3
3
  PUI/decorator.py,sha256=BN3POYv69QCDomoHENN-UA-d4wY_vfARIb5RJ2qEnS8,483
4
4
  PUI/dom.py,sha256=RgdDyv6vSFgkCoj9G2cjzQQOiymG8DwmmSoAZfxYvJM,10141
5
5
  PUI/interfaces.py,sha256=rGUciM3S6ICEVgVoahkva8yXUGpweqy1kAzhUQut40E,2182
@@ -10,16 +10,16 @@ PUI/utils.py,sha256=canb7_Uz0sQ1UZDzyDuIsfAVXzEfZCkc9F81sMY4rTE,505
10
10
  PUI/view.py,sha256=Oe6sXLHD554GnlLlO5QpY7kegngkzrmMEYRHrdzGZUQ,4623
11
11
  PUI/PySide6/__init__.py,sha256=z895ldBVUaEqfGQW4CvYhWh2F6L0qGQA1MXUHVMf9Ms,1110
12
12
  PUI/PySide6/application.py,sha256=OsIE47efST4I13txD-7rS1cTWAGhynckl45Wdb1bafk,1471
13
- PUI/PySide6/base.py,sha256=wAkvN_dxG8fKHUNH99lO2Kc9ZEENQFDkPt1hkDFSBLM,7910
13
+ PUI/PySide6/base.py,sha256=bhIxbw16l78lgkSpN4_s2cV33pObj3O3yGhtiNIJ10w,7916
14
14
  PUI/PySide6/button.py,sha256=mHfcH98dABYgksuT58fK0amSwtCM9aaYwr7Y2EArEJA,561
15
- PUI/PySide6/canvas.py,sha256=mkMjGXcQmUeV1a1HChv6KTWuh_5ao_qA-dYqCnsHo3s,9108
15
+ PUI/PySide6/canvas.py,sha256=Qad87bLpQJoh8U5hjqH3g3mSbodPwweT0TOqnB5LPyI,10416
16
16
  PUI/PySide6/checkbox.py,sha256=Rsns0BleE4g9yTDdlsD8IADU3qcQkVO2VsFVvYlNL88,900
17
- PUI/PySide6/combobox.py,sha256=mn1u4SATJbL1YVlnIecyHklRjUoXumwiyHalF3qInA0,2235
17
+ PUI/PySide6/combobox.py,sha256=mAfJ_7m-jTWBAh2Sng-BslY-_7EjIwRLbrx5IHik13I,2501
18
18
  PUI/PySide6/dialog.py,sha256=4rAyLMqd47ALDxrBGLFHS5FD75SP1I8tkMSKBdaPkv0,2364
19
19
  PUI/PySide6/divider.py,sha256=jRR8Qtdil-8JTxj8SyJydzRB_MGTKa_TxegsqkYKcXc,733
20
- PUI/PySide6/image.py,sha256=0HpyNX-iMGy-yVyanAmnQj4q-bvxJc3k9MY5tNlpiXE,1159
20
+ PUI/PySide6/image.py,sha256=uORM63K6v-1Ug4KpRJW3YHc-PpICqmRxmAzcEL6MaME,1969
21
21
  PUI/PySide6/label.py,sha256=_G8bckRPPQdzZTS3j9JaOmfRAnLragBXnyJUG9_kblU,1038
22
- PUI/PySide6/layout.py,sha256=hSnDmrir2ztgyj1gQchniwMfjcKM1GtKeXRU9YOM4QE,2617
22
+ PUI/PySide6/layout.py,sha256=lEr37sxpYWHSo_d-8asPRVjnJsiePP4g9SaKFGLCpJs,2637
23
23
  PUI/PySide6/matplotlib.py,sha256=fzVfwgmEX7s_WDtc_JULRdBOfZgcBewiH79f4ahZHQ4,825
24
24
  PUI/PySide6/mdi.py,sha256=OGE2-5--Cy-srAzM-ZexnJ1efeORQvlsH2UA7qp18iE,805
25
25
  PUI/PySide6/menu.py,sha256=Qbw_0WX56vzC2vkvn-4DXzYX0vZ-4Rq6tW1Kj_M-Qb8,2806
@@ -33,7 +33,7 @@ PUI/PySide6/table.py,sha256=TTCMf_YNKmkFiqs_qLqw3qbvFsxoBNnz9VMObx_2l3s,4800
33
33
  PUI/PySide6/text.py,sha256=4kRRZiuH-bLLJMNZ6hK9zAWOorsG-l4uujHbG6I5S20,1069
34
34
  PUI/PySide6/textfield.py,sha256=Us-UZMDCwrREwFLjPKKa3e3c_1U4WWD2kzFCe3xiY0k,2140
35
35
  PUI/PySide6/toolbar.py,sha256=NPkn99D5xK4RLBA0vxLD7EqYu5eh9ucCL2y1vSJWQl4,1800
36
- PUI/PySide6/tree.py,sha256=C50Uzh6vvGxJnxIDv3TQR95qbr6f_kbKv10jMduvz4Q,9006
36
+ PUI/PySide6/tree.py,sha256=skMsCykh8kWXFTg4Yv--PevJ58fqEeZV566ICjBVO4E,9324
37
37
  PUI/PySide6/window.py,sha256=CpkIFpleVr3oXOM6vdukahWtX5SV6cWNc1TUW84JPM4,2694
38
38
  PUI/flet/__init__.py,sha256=3YzGA0oPfu9eW8DtKQSoAsa8o6ZTGKWakYBTxGaaH8Y,438
39
39
  PUI/flet/application.py,sha256=3ZGZrAngSEkVK-WseOV-n_6ljhd86ZKBgO6Jp2PmsJA,937
@@ -50,16 +50,16 @@ PUI/flet/tab.py,sha256=T26PZ-Ma_LPUx7u9qbxEnYqxuR1-qlytWiB9TDpu7G8,997
50
50
  PUI/flet/text.py,sha256=HGnhOTDwG5pqceK8x_C6wCZj1AKuqZ9vEZB_NFwXZo4,1465
51
51
  PUI/flet/textfield.py,sha256=7BPRrdf4pv8rDM5BpZzMQ9b456kZpXm81y7sVW3K4XM,1802
52
52
  PUI/flet/window.py,sha256=NqUnGYvhk2Mpo_G2WthZOEvlU6VMx6AM-jWMKcUqGDM,650
53
- PUI/textual/__init__.py,sha256=uj_j3Z3Jvt-OLG5WSuD8mQW3rqRlv5oi7pwxKfoGFfk,709
53
+ PUI/textual/__init__.py,sha256=cPf0_BXd2Q-6w-0UHyxFQ6QLfTVDaoo7XmSCW_1kpyc,732
54
54
  PUI/textual/application.py,sha256=FNpZ1j05EbE3XNxqMBDfsU_IPQ1k2Y7xw-5KLtwuFnI,2514
55
- PUI/textual/base.py,sha256=uZhtB7Ofajc--bCilWsOGP63AxBL59y744GZFa13eIA,3580
55
+ PUI/textual/base.py,sha256=W0tfxGlZErrsCoLb9IuFjgmNa93vZFCYNgZr1V6VEjE,4821
56
56
  PUI/textual/button.py,sha256=VF7fmgi5mHeOzptZzy4oBfcuCeUURq5eFrLvN4Fgg30,436
57
57
  PUI/textual/checkbox.py,sha256=pkBxZz0qXl2KUz2-Lqap-r2Y3DBI0CET3wQgEpYKb7U,518
58
- PUI/textual/label.py,sha256=Ce5I-1sBeaKnLEIsQWK5nKMCEgwusED2fjHePIiGr90,1266
59
- PUI/textual/layout.py,sha256=poeS1TrbqR4wBiP7jj31sSr2fRav2w59-MIWZwvtZUI,1214
58
+ PUI/textual/label.py,sha256=3kwUerDSbyUPPEkLsjs0qDcyyhgOvUws2wtjovyf0_k,1220
59
+ PUI/textual/layout.py,sha256=xS3xa7UHyfKT93zW2592lV7iu6POuRJKLGyvRvtHIlQ,1302
60
60
  PUI/textual/progressbar.py,sha256=aeLiXzLOj3VWR-KUEBmmEOxJR0LACr1_-MDMOYDHx9c,501
61
61
  PUI/textual/radiobutton.py,sha256=zFKG2LeUnPXnxpxeW3cYqPwd91DQZWFUctundau-4b0,621
62
- PUI/textual/scroll.py,sha256=QeMDXgIz-5fxcL4htM2pHJFD6RAsDiijgLO9PmhJOEA,2036
62
+ PUI/textual/scroll.py,sha256=u6-tFygXZR_giVsCaePahKxTb0xTbdBHCNisQA9jpWc,1974
63
63
  PUI/textual/tab.py,sha256=wcvyH1MZZNwwout8iJDifty_lqe6YuhfRpE3F0lUTBM,2158
64
64
  PUI/textual/text.py,sha256=BHvgK3JqBU_LrnWbaaKBFxQ_50Z9lFhcdEJoVJqbcSc,782
65
65
  PUI/textual/textfield.py,sha256=u01i-fhtSEMi_6F_bPWgf5TvRUQvuudaxi58Yp6WTbg,1412
@@ -68,7 +68,7 @@ PUI/tkinter/__init__.py,sha256=VQjdak9UO-zI7n9Kr4q_B-kgCXgag2DVoWWP_QdH2uk,982
68
68
  PUI/tkinter/application.py,sha256=NxWfU9NHJuceKMdLiGeklUKU5WjYVUomGL_hJpRtrbs,1141
69
69
  PUI/tkinter/base.py,sha256=jSOKxd2uMOhVvDjBOloxdiHeNvKwEoWJo0fyVH49ttI,2663
70
70
  PUI/tkinter/button.py,sha256=zRGt_jVY6q74Jer5jm4q4H-_LznrXUzfEQwiMWtQboI,467
71
- PUI/tkinter/canvas.py,sha256=AHltKAeKP629qfosJNy9jaLwLygwtHv88aPGGt6PSgE,1609
71
+ PUI/tkinter/canvas.py,sha256=nLi46ZhgEvpZz8_aUy1DwfKct4zdABjqL-9ObS1CCMM,1654
72
72
  PUI/tkinter/checkbox.py,sha256=TOYOCKx9ux58YdYWXLkjguFG3NsgVaYlFOIrZ9ukcwI,741
73
73
  PUI/tkinter/label.py,sha256=o6hj-8qX0ZwDDbYaNsTz5oUIXKJFr-HctTeZW2NfhHE,555
74
74
  PUI/tkinter/layout.py,sha256=q1NgGlPd_dn1avIzJBeO_46NyBPCQyh3VcQ56YmUUKE,3576
@@ -81,23 +81,23 @@ PUI/tkinter/textfield.py,sha256=-jab7t5-wpIejINRftXczv0685cze-H7pm3lWigOT5w,1788
81
81
  PUI/tkinter/window.py,sha256=IIieSxxanhGIvPy0krQuLrStsL_jTUdx6TKbEf64nyQ,1606
82
82
  PUI/wx/__init__.py,sha256=j8L1kzL4CK_xeF0x5_NZekGETYP_1Dhq3-BuV1LtXoY,391
83
83
  PUI/wx/application.py,sha256=Ku_mloCyiw-KTl8a09uTIhV7uupG_7urqw8jXIwQMLc,965
84
- PUI/wx/base.py,sha256=kvpi2WVgDMW4LqaYiMhEIb0FlRG2pXvYUV04iJ_oSV4,6089
84
+ PUI/wx/base.py,sha256=3NKfMbfuH9qClFBP5bVIQtJyhnGRqsNuXwY0vvlyFnU,7596
85
85
  PUI/wx/button.py,sha256=ww3Iyn16zomP4zkQhvXTirmHBvlVMJxmiV1pfXtgrSo,447
86
- PUI/wx/canvas.py,sha256=1mWdzlMfIIe--Lx4npzo0vX2BjvijZkQDep6-AmYcdM,8493
86
+ PUI/wx/canvas.py,sha256=uL4z0ghM15IWNlvmDyV3lVw8Li4RNMJWXHvwd7jZSiw,8487
87
87
  PUI/wx/checkbox.py,sha256=XgLxsi-tk2f9bnlEvhvEZV4boBGFB3u62ZE1cs8X9tU,674
88
- PUI/wx/combobox.py,sha256=Q4KN8P3yO7KI5nKebSDYHu0noAyv-NtObkxmOsa_RrI,2052
88
+ PUI/wx/combobox.py,sha256=FoYn6AkPpxH2jHcZEp20a_peC7MbTx4MUPtbGzOskcI,2363
89
89
  PUI/wx/dialog.py,sha256=HVLVdzRkZhRndkHTYl0RgNfzIQBdtik7DIDg93Dp9JA,2572
90
90
  PUI/wx/divider.py,sha256=qnaUVpspAOND6YhZyQsZeos1LC02L-ljfdAtVp1vdzw,516
91
91
  PUI/wx/label.py,sha256=qr3hGfHtjvYjeXJSB2cD5u30LYodEzix4Q0FYw8p6p0,509
92
- PUI/wx/layout.py,sha256=jzik7K_Vfjh7uVZbZn2erqwWvILzPCP0xurcGQb4kYI,1370
92
+ PUI/wx/layout.py,sha256=nVO31_Xu4aDcTLxlz66DJ5PK2RPHk0yq6qdzyWuGVz8,1460
93
93
  PUI/wx/progressbar.py,sha256=gj5j6f-zG78XW1mEIRqiOEYMoYjG16jzS44Vnh4i148,472
94
94
  PUI/wx/radiobutton.py,sha256=x7WnCGXuNPV98MqF-tRLzMOOExim22rayNL8jAYVZWk,769
95
- PUI/wx/scroll.py,sha256=LPwRL9KZuoKrTFEWo1_zW3l_Fbaznq_2jA9GuwTp8Dc,1199
95
+ PUI/wx/scroll.py,sha256=pvRmt04XEgObpIgwl9i52Kf1wI9ubUfZM77fPHGW9zU,1494
96
96
  PUI/wx/text.py,sha256=YeIyDyHH0xBcD_iXbYSTtvL25YDtug1QJNVPvCSAqEk,544
97
97
  PUI/wx/textfield.py,sha256=BmMebfqlDJqacaKdh2SON88xF73l0csC7L7hoNjz-qs,1778
98
98
  PUI/wx/window.py,sha256=juAsn3W4SzmH8f5LDGvjwppvPD8fDObRUJ_MkQFKCIE,1847
99
- qpuiq-0.13.dist-info/LICENSE.txt,sha256=1Xwik2AmLNGoIYhAPzvNC28M08Q3EvkOe4TtlQuSd_E,1072
100
- qpuiq-0.13.dist-info/METADATA,sha256=ELthoIyCZ5CskEXuew_R1KnkFKIt1br0_1H3Z8An0NM,5716
101
- qpuiq-0.13.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
102
- qpuiq-0.13.dist-info/top_level.txt,sha256=zMudhifPite0CEVGYvdi-5W3P_dpum71xjU7_g-ZHS0,4
103
- qpuiq-0.13.dist-info/RECORD,,
99
+ qpuiq-0.14.dist-info/licenses/LICENSE.txt,sha256=1Xwik2AmLNGoIYhAPzvNC28M08Q3EvkOe4TtlQuSd_E,1072
100
+ qpuiq-0.14.dist-info/METADATA,sha256=EkKi_IUa4vM9PyZY2A8n5vTgZLXCnDnR8QGX1cZQR1s,5994
101
+ qpuiq-0.14.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
102
+ qpuiq-0.14.dist-info/top_level.txt,sha256=zMudhifPite0CEVGYvdi-5W3P_dpum71xjU7_g-ZHS0,4
103
+ qpuiq-0.14.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (70.3.0)
2
+ Generator: setuptools (80.3.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5