qpuiq 0.10__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of qpuiq might be problematic. Click here for more details.
- PUI/PySide6/__init__.py +49 -0
- PUI/PySide6/application.py +58 -0
- PUI/PySide6/base.py +222 -0
- PUI/PySide6/button.py +21 -0
- PUI/PySide6/canvas.py +288 -0
- PUI/PySide6/checkbox.py +32 -0
- PUI/PySide6/combobox.py +75 -0
- PUI/PySide6/dialog.py +72 -0
- PUI/PySide6/divider.py +23 -0
- PUI/PySide6/image.py +30 -0
- PUI/PySide6/label.py +33 -0
- PUI/PySide6/layout.py +72 -0
- PUI/PySide6/matplotlib.py +23 -0
- PUI/PySide6/mdi.py +33 -0
- PUI/PySide6/menu.py +85 -0
- PUI/PySide6/modal.py +132 -0
- PUI/PySide6/progressbar.py +17 -0
- PUI/PySide6/radiobutton.py +29 -0
- PUI/PySide6/scroll.py +153 -0
- PUI/PySide6/splitter.py +25 -0
- PUI/PySide6/tab.py +39 -0
- PUI/PySide6/table.py +89 -0
- PUI/PySide6/text.py +35 -0
- PUI/PySide6/textfield.py +62 -0
- PUI/PySide6/toolbar.py +57 -0
- PUI/PySide6/tree.py +120 -0
- PUI/PySide6/window.py +81 -0
- PUI/__init__.py +46 -0
- PUI/common.py +20 -0
- PUI/decorator.py +20 -0
- PUI/dom.py +238 -0
- PUI/flet/__init__.py +21 -0
- PUI/flet/application.py +42 -0
- PUI/flet/base.py +37 -0
- PUI/flet/button.py +20 -0
- PUI/flet/canvas.py +86 -0
- PUI/flet/checkbox.py +23 -0
- PUI/flet/label.py +27 -0
- PUI/flet/layout.py +50 -0
- PUI/flet/progressbar.py +21 -0
- PUI/flet/radiobutton.py +27 -0
- PUI/flet/scroll.py +83 -0
- PUI/flet/tab.py +42 -0
- PUI/flet/text.py +55 -0
- PUI/flet/textfield.py +58 -0
- PUI/flet/window.py +25 -0
- PUI/interfaces.py +97 -0
- PUI/node.py +407 -0
- PUI/state.py +698 -0
- PUI/textual/__init__.py +34 -0
- PUI/textual/application.py +82 -0
- PUI/textual/base.py +113 -0
- PUI/textual/button.py +17 -0
- PUI/textual/checkbox.py +21 -0
- PUI/textual/label.py +36 -0
- PUI/textual/layout.py +48 -0
- PUI/textual/progressbar.py +17 -0
- PUI/textual/radiobutton.py +24 -0
- PUI/textual/scroll.py +72 -0
- PUI/textual/tab.py +75 -0
- PUI/textual/text.py +32 -0
- PUI/textual/textfield.py +49 -0
- PUI/textual/window.py +7 -0
- PUI/timeline.py +36 -0
- PUI/tkinter/__init__.py +43 -0
- PUI/tkinter/application.py +49 -0
- PUI/tkinter/base.py +68 -0
- PUI/tkinter/button.py +15 -0
- PUI/tkinter/canvas.py +49 -0
- PUI/tkinter/checkbox.py +27 -0
- PUI/tkinter/label.py +17 -0
- PUI/tkinter/layout.py +114 -0
- PUI/tkinter/progressbar.py +17 -0
- PUI/tkinter/radiobutton.py +26 -0
- PUI/tkinter/scroll.py +201 -0
- PUI/tkinter/tab.py +52 -0
- PUI/tkinter/text.py +20 -0
- PUI/tkinter/textfield.py +53 -0
- PUI/tkinter/window.py +51 -0
- PUI/utils.py +15 -0
- PUI/view.py +161 -0
- PUI/wx/__init__.py +19 -0
- PUI/wx/application.py +44 -0
- PUI/wx/base.py +202 -0
- PUI/wx/button.py +16 -0
- PUI/wx/canvas.py +255 -0
- PUI/wx/checkbox.py +25 -0
- PUI/wx/combobox.py +72 -0
- PUI/wx/dialog.py +66 -0
- PUI/wx/divider.py +19 -0
- PUI/wx/label.py +18 -0
- PUI/wx/layout.py +46 -0
- PUI/wx/progressbar.py +17 -0
- PUI/wx/radiobutton.py +27 -0
- PUI/wx/scroll.py +44 -0
- PUI/wx/text.py +23 -0
- PUI/wx/textfield.py +56 -0
- PUI/wx/window.py +58 -0
- qpuiq-0.10.dist-info/LICENSE.txt +21 -0
- qpuiq-0.10.dist-info/METADATA +227 -0
- qpuiq-0.10.dist-info/RECORD +103 -0
- qpuiq-0.10.dist-info/WHEEL +5 -0
- qpuiq-0.10.dist-info/top_level.txt +1 -0
PUI/PySide6/scroll.py
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
from PySide6.QtWidgets import QSizePolicy
|
|
4
|
+
import math
|
|
5
|
+
|
|
6
|
+
class Scroll(QtBaseWidget):
|
|
7
|
+
pui_terminal = False
|
|
8
|
+
END = -0.0
|
|
9
|
+
|
|
10
|
+
def __init__(self, vertical=None, horizontal=False):
|
|
11
|
+
self.vertical = vertical
|
|
12
|
+
self.horizontal = horizontal
|
|
13
|
+
self.align_x = 0
|
|
14
|
+
self.align_y = 0
|
|
15
|
+
super().__init__()
|
|
16
|
+
|
|
17
|
+
def update(self, prev):
|
|
18
|
+
if prev and prev.ui:
|
|
19
|
+
self.ui = prev.ui
|
|
20
|
+
self.align_x = prev.align_x
|
|
21
|
+
self.align_y = prev.align_y
|
|
22
|
+
if prev.vsb_conn:
|
|
23
|
+
vsb = self.ui.verticalScrollBar()
|
|
24
|
+
vsb.valueChanged.disconnect(prev.vsb_conn)
|
|
25
|
+
vsb.rangeChanged.disconnect(prev.vsb_range_conn)
|
|
26
|
+
if prev.hsb_conn:
|
|
27
|
+
hsb = self.ui.horizontalScrollBar()
|
|
28
|
+
hsb.valueChanged.disconnect(prev.hsb_conn)
|
|
29
|
+
hsb.rangeChanged.disconnect(prev.hsb_range_conn)
|
|
30
|
+
else:
|
|
31
|
+
self.ui = QtWidgets.QScrollArea()
|
|
32
|
+
self.ui.setWidgetResizable(True)
|
|
33
|
+
if self.vertical is None:
|
|
34
|
+
self.ui.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
|
35
|
+
elif self.vertical:
|
|
36
|
+
self.ui.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOn)
|
|
37
|
+
else:
|
|
38
|
+
self.ui.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
|
39
|
+
if self.horizontal is None:
|
|
40
|
+
self.ui.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
|
41
|
+
elif self.horizontal:
|
|
42
|
+
self.ui.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOn)
|
|
43
|
+
else:
|
|
44
|
+
self.ui.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
|
45
|
+
vsb = self.ui.verticalScrollBar()
|
|
46
|
+
self.vsb_conn = vsb.valueChanged.connect(self.vsb_changed)
|
|
47
|
+
self.vsb_range_conn = vsb.rangeChanged.connect(self.vsb_range_changed)
|
|
48
|
+
hsb = self.ui.horizontalScrollBar()
|
|
49
|
+
self.hsb_conn = hsb.valueChanged.connect(self.hsb_changed)
|
|
50
|
+
self.hsb_range_conn = hsb.rangeChanged.connect(self.hsb_range_changed)
|
|
51
|
+
super().update(prev)
|
|
52
|
+
|
|
53
|
+
def addChild(self, idx, child):
|
|
54
|
+
if idx != 0:
|
|
55
|
+
return
|
|
56
|
+
if isinstance(child, QtBaseWidget) or isinstance(child, QtBaseLayout):
|
|
57
|
+
self.ui.setWidget(child.outer)
|
|
58
|
+
if not hasattr(child.outer, "origResizeEvent"):
|
|
59
|
+
child.outer.origResizeEvent = child.outer.resizeEvent
|
|
60
|
+
child.outer.setSizePolicy(QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Preferred))
|
|
61
|
+
child.outer.resizeEvent = self.onUiResized
|
|
62
|
+
elif child.children:
|
|
63
|
+
self.addChild(idx, child.children[0])
|
|
64
|
+
|
|
65
|
+
def removeChild(self, idx, child):
|
|
66
|
+
if idx != 0:
|
|
67
|
+
return
|
|
68
|
+
if isinstance(child, QtBaseWidget) or isinstance(child, QtBaseLayout):
|
|
69
|
+
child.outer.setParent(None)
|
|
70
|
+
elif child.children:
|
|
71
|
+
self.removeChild(idx, child.children[0])
|
|
72
|
+
|
|
73
|
+
def onUiResized(self, event):
|
|
74
|
+
node = self.get_node()
|
|
75
|
+
if node.destroyed:
|
|
76
|
+
return
|
|
77
|
+
node.children[0].outer.origResizeEvent(event)
|
|
78
|
+
node.children[0].outer.resizeEvent = self.onUiResized
|
|
79
|
+
if node.horizontal is False:
|
|
80
|
+
if isinstance(node.children[0], QtBaseLayout):
|
|
81
|
+
node.outer.setMinimumWidth(node.children[0].outer.sizeHint().width())
|
|
82
|
+
elif isinstance(node.children[0], QtBaseWidget):
|
|
83
|
+
node.outer.setMinimumWidth(node.children[0].outer.sizeHint().width())
|
|
84
|
+
|
|
85
|
+
if node.vertical is False:
|
|
86
|
+
if isinstance(node.children[0], QtBaseLayout):
|
|
87
|
+
node.outer.setMinimumHeight(node.children[0].outer.sizeHint().height())
|
|
88
|
+
elif isinstance(node.children[0], QtBaseWidget):
|
|
89
|
+
node.outer.setMinimumHeight(node.children[0].outer.sizeHint().height())
|
|
90
|
+
|
|
91
|
+
def scrollX(self, pos=0):
|
|
92
|
+
if math.copysign(1, pos) >= 0:
|
|
93
|
+
self.align_x = 0
|
|
94
|
+
self.hsb_offset = pos
|
|
95
|
+
else:
|
|
96
|
+
self.align_x = 1
|
|
97
|
+
self.hsb_offset = abs(pos)
|
|
98
|
+
return self
|
|
99
|
+
|
|
100
|
+
def scrollY(self, pos=0):
|
|
101
|
+
if math.copysign(1, pos) >= 0:
|
|
102
|
+
self.align_y = 0
|
|
103
|
+
self.vsb_offset = pos
|
|
104
|
+
else:
|
|
105
|
+
self.align_y = 1
|
|
106
|
+
self.vsb_offset = abs(pos)
|
|
107
|
+
return self
|
|
108
|
+
|
|
109
|
+
def hsb_changed(self, *args, **kwargs):
|
|
110
|
+
hsb = self.ui.horizontalScrollBar()
|
|
111
|
+
v = hsb.value()
|
|
112
|
+
if v < 10 and v > hsb.maximum() - 10:
|
|
113
|
+
pass
|
|
114
|
+
elif v < 10:
|
|
115
|
+
self.align_x = 0
|
|
116
|
+
elif v > hsb.maximum() - 10:
|
|
117
|
+
self.align_x = 1
|
|
118
|
+
|
|
119
|
+
def vsb_changed(self, *args, **kwargs):
|
|
120
|
+
vsb = self.ui.verticalScrollBar()
|
|
121
|
+
v = vsb.value()
|
|
122
|
+
if v < 10 and v > vsb.maximum() - 10:
|
|
123
|
+
pass
|
|
124
|
+
elif v < 10:
|
|
125
|
+
self.align_y = 0
|
|
126
|
+
elif v > vsb.maximum() - 10:
|
|
127
|
+
self.align_y = 1
|
|
128
|
+
|
|
129
|
+
def preSync(self):
|
|
130
|
+
hsb = self.ui.horizontalScrollBar()
|
|
131
|
+
if self.align_x == 0:
|
|
132
|
+
self.hsb_offset = hsb.value()
|
|
133
|
+
else:
|
|
134
|
+
self.hsb_offset = hsb.maximum() - hsb.value()
|
|
135
|
+
vsb = self.ui.verticalScrollBar()
|
|
136
|
+
if self.align_y == 0:
|
|
137
|
+
self.vsb_offset = vsb.value()
|
|
138
|
+
else:
|
|
139
|
+
self.vsb_offset = vsb.maximum() - vsb.value()
|
|
140
|
+
|
|
141
|
+
def vsb_range_changed(self, min, max):
|
|
142
|
+
vsb = self.ui.verticalScrollBar()
|
|
143
|
+
if self.align_y == 0:
|
|
144
|
+
vsb.setValue(self.vsb_offset)
|
|
145
|
+
else:
|
|
146
|
+
vsb.setValue(max - self.vsb_offset)
|
|
147
|
+
|
|
148
|
+
def hsb_range_changed(self, min, max):
|
|
149
|
+
hsb = self.ui.verticalScrollBar()
|
|
150
|
+
if self.align_y == 0:
|
|
151
|
+
hsb.setValue(self.hsb_offset)
|
|
152
|
+
else:
|
|
153
|
+
hsb.setValue(max - self.hsb_offset)
|
PUI/PySide6/splitter.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
|
|
4
|
+
class Splitter(QtBaseWidget):
|
|
5
|
+
pui_terminal = False
|
|
6
|
+
def __init__(self, vertical=False):
|
|
7
|
+
super().__init__()
|
|
8
|
+
self.vertical = vertical
|
|
9
|
+
|
|
10
|
+
def update(self, prev):
|
|
11
|
+
if prev and prev.ui:
|
|
12
|
+
self.ui = prev.ui
|
|
13
|
+
else:
|
|
14
|
+
self.ui = QtWidgets.QSplitter()
|
|
15
|
+
self.ui.setOrientation(QtCore.Qt.Orientation.Vertical if self.vertical else QtCore.Qt.Orientation.Horizontal)
|
|
16
|
+
super().update(prev)
|
|
17
|
+
|
|
18
|
+
def addChild(self, idx, child):
|
|
19
|
+
if isinstance(child, QtBaseWidget) or isinstance(child, QtBaseLayout):
|
|
20
|
+
self.ui.insertWidget(idx, child.outer)
|
|
21
|
+
else:
|
|
22
|
+
self.addChild(idx, child.children[0])
|
|
23
|
+
|
|
24
|
+
def removeChild(self, idx, child):
|
|
25
|
+
child.outer.setParent(None)
|
PUI/PySide6/tab.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
|
|
4
|
+
class Tabs(QtBaseWidget):
|
|
5
|
+
NORTH = "n"
|
|
6
|
+
SOUTH = "s"
|
|
7
|
+
EAST = "e"
|
|
8
|
+
WEST = "w"
|
|
9
|
+
pui_terminal = False
|
|
10
|
+
def __init__(self, tabposition=NORTH):
|
|
11
|
+
super().__init__()
|
|
12
|
+
self.tabposition = tabposition
|
|
13
|
+
|
|
14
|
+
def update(self, prev):
|
|
15
|
+
if prev and prev.ui:
|
|
16
|
+
self.ui = prev.ui
|
|
17
|
+
else:
|
|
18
|
+
self.ui = QtWidgets.QTabWidget()
|
|
19
|
+
super().update(prev)
|
|
20
|
+
|
|
21
|
+
def addChild(self, idx, child):
|
|
22
|
+
parent = child.parent
|
|
23
|
+
while not isinstance(parent, Tab):
|
|
24
|
+
parent = parent.parent
|
|
25
|
+
self.ui.insertTab(idx, child.outer, parent.label)
|
|
26
|
+
|
|
27
|
+
def removeChild(self, idx, child):
|
|
28
|
+
self.ui.removeTab(idx)
|
|
29
|
+
|
|
30
|
+
def postSync(self):
|
|
31
|
+
for i,c in enumerate(self.children):
|
|
32
|
+
self.ui.setTabText(i, c.label)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class Tab(PUINode):
|
|
36
|
+
pui_virtual = True
|
|
37
|
+
def __init__(self, label):
|
|
38
|
+
super().__init__()
|
|
39
|
+
self.label = label
|
PUI/PySide6/table.py
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
|
|
4
|
+
class QtTableModelAdapter(QtCore.QAbstractTableModel):
|
|
5
|
+
def __init__(self, model: "BaseTableAdapter"):
|
|
6
|
+
super().__init__()
|
|
7
|
+
self.model = model
|
|
8
|
+
|
|
9
|
+
def data(self, index, role):
|
|
10
|
+
if role == QtCore.Qt.DisplayRole:
|
|
11
|
+
return self.model.data(index.row(), index.column())
|
|
12
|
+
elif role == QtCore.Qt.EditRole:
|
|
13
|
+
return self.model.editData(index.row(), index.column())
|
|
14
|
+
|
|
15
|
+
def setData(self, index, value, role):
|
|
16
|
+
if role == QtCore.Qt.EditRole:
|
|
17
|
+
self.model.setData(index.row(), index.column(), value)
|
|
18
|
+
return True
|
|
19
|
+
|
|
20
|
+
def flags(self, index):
|
|
21
|
+
flags = super().flags(index)
|
|
22
|
+
if self.model.editable(index.row(), index.column()):
|
|
23
|
+
flags |= QtCore.Qt.ItemIsEditable
|
|
24
|
+
return flags
|
|
25
|
+
|
|
26
|
+
def headerData(self, section, orientation, role):
|
|
27
|
+
if role == QtCore.Qt.DisplayRole:
|
|
28
|
+
if orientation == QtCore.Qt.Horizontal:
|
|
29
|
+
if hasattr(self.model, "columnHeader"):
|
|
30
|
+
if self.model.columnHeader is None:
|
|
31
|
+
return None
|
|
32
|
+
else:
|
|
33
|
+
return self.model.columnHeader(section)
|
|
34
|
+
else:
|
|
35
|
+
return super().headerData(section, orientation, role)
|
|
36
|
+
else:
|
|
37
|
+
if hasattr(self.model, "rowHeader"):
|
|
38
|
+
if self.model.rowHeader is None:
|
|
39
|
+
return None
|
|
40
|
+
else:
|
|
41
|
+
return self.model.rowHeader(section)
|
|
42
|
+
else:
|
|
43
|
+
return super().headerData(section, orientation, role)
|
|
44
|
+
|
|
45
|
+
def rowCount(self, index):
|
|
46
|
+
return self.model.rowCount()
|
|
47
|
+
|
|
48
|
+
def columnCount(self, index):
|
|
49
|
+
return self.model.columnCount()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class Table(QtBaseWidget):
|
|
53
|
+
def __init__(self, model, autofit=True):
|
|
54
|
+
super().__init__()
|
|
55
|
+
self.layout_weight = 1
|
|
56
|
+
self.model = model
|
|
57
|
+
self.autofit = autofit
|
|
58
|
+
self.curr_model = None
|
|
59
|
+
|
|
60
|
+
def update(self, prev):
|
|
61
|
+
if prev and prev.ui:
|
|
62
|
+
self.ui = prev.ui
|
|
63
|
+
self.qt_model = prev.qt_model
|
|
64
|
+
self.curr_model = prev.curr_model
|
|
65
|
+
else:
|
|
66
|
+
self.qt_model = None
|
|
67
|
+
self.curr_model = Prop()
|
|
68
|
+
self.ui = QtWidgets.QTableView()
|
|
69
|
+
|
|
70
|
+
if self.model.columnHeader is None:
|
|
71
|
+
self.ui.horizontalHeader().hide()
|
|
72
|
+
else:
|
|
73
|
+
self.ui.horizontalHeader().show()
|
|
74
|
+
|
|
75
|
+
if self.model.rowHeader is None:
|
|
76
|
+
self.ui.verticalHeader().hide()
|
|
77
|
+
else:
|
|
78
|
+
self.ui.verticalHeader().show()
|
|
79
|
+
|
|
80
|
+
if self.curr_model.set(self.model):
|
|
81
|
+
self.qt_model = QtTableModelAdapter(self.model)
|
|
82
|
+
self.ui.setModel(self.qt_model)
|
|
83
|
+
else:
|
|
84
|
+
self.qt_model.refresh()
|
|
85
|
+
|
|
86
|
+
if self.autofit:
|
|
87
|
+
self.ui.resizeColumnsToContents()
|
|
88
|
+
|
|
89
|
+
super().update(prev)
|
PUI/PySide6/text.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
from ..utils import *
|
|
4
|
+
from PySide6.QtWidgets import QSizePolicy
|
|
5
|
+
|
|
6
|
+
class Text(QtBaseWidget):
|
|
7
|
+
textformat = QtCore.Qt.TextFormat.PlainText
|
|
8
|
+
def __init__(self, text, selectable=False):
|
|
9
|
+
super().__init__()
|
|
10
|
+
self.text = str(text)
|
|
11
|
+
self.selectable = selectable
|
|
12
|
+
|
|
13
|
+
def update(self, prev):
|
|
14
|
+
if prev and prev.ui:
|
|
15
|
+
self.ui = prev.ui
|
|
16
|
+
self.ui.setText(self.text)
|
|
17
|
+
else:
|
|
18
|
+
self.ui = QtWidgets.QLabel(self.text)
|
|
19
|
+
self.ui.setTextFormat(self.textformat)
|
|
20
|
+
self.ui.setAlignment(QtCore.Qt.AlignmentFlag.AlignTop)
|
|
21
|
+
self.ui.setWordWrap(True)
|
|
22
|
+
|
|
23
|
+
if self.selectable:
|
|
24
|
+
self.ui.setTextInteractionFlags(QtCore.Qt.TextInteractionFlag.TextSelectableByMouse)
|
|
25
|
+
else:
|
|
26
|
+
self.ui.setTextInteractionFlags(QtCore.Qt.TextInteractionFlag.NoTextInteraction)
|
|
27
|
+
|
|
28
|
+
super().update(prev)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class Html(Text):
|
|
32
|
+
textformat = QtCore.Qt.TextFormat.RichText
|
|
33
|
+
|
|
34
|
+
class MarkDown(Text):
|
|
35
|
+
textformat = QtCore.Qt.TextFormat.MarkdownText
|
PUI/PySide6/textfield.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
|
|
4
|
+
class TextField(QtBaseWidget):
|
|
5
|
+
def __init__(self, model, edit_model=None):
|
|
6
|
+
super().__init__()
|
|
7
|
+
self.model = model
|
|
8
|
+
self.edit_model = edit_model
|
|
9
|
+
self.editing = False
|
|
10
|
+
|
|
11
|
+
def update(self, prev):
|
|
12
|
+
model_value = str(self.model.value)
|
|
13
|
+
if prev and prev.ui:
|
|
14
|
+
self.editing = prev.editing
|
|
15
|
+
self.ui = prev.ui
|
|
16
|
+
self.curr_value = prev.curr_value
|
|
17
|
+
self.ui.node = self
|
|
18
|
+
self.ui.textChanged.disconnect()
|
|
19
|
+
if self.curr_value.set(model_value) and not self.editing:
|
|
20
|
+
self.ui.setText(model_value)
|
|
21
|
+
self.ui.textChanged.connect(self.on_textchanged)
|
|
22
|
+
self.ui.editingFinished.disconnect()
|
|
23
|
+
self.ui.editingFinished.connect(self.on_editing_finished)
|
|
24
|
+
else:
|
|
25
|
+
self.ui = QtWidgets.QLineEdit()
|
|
26
|
+
self.ui.setFocusPolicy(QtCore.Qt.ClickFocus | QtCore.Qt.NoFocus)
|
|
27
|
+
self.ui.node = self
|
|
28
|
+
self.ui.setText(model_value)
|
|
29
|
+
self.curr_value = Prop(model_value)
|
|
30
|
+
self.ui.textChanged.connect(self.on_textchanged)
|
|
31
|
+
self.ui.editingFinished.connect(self.on_editing_finished)
|
|
32
|
+
|
|
33
|
+
if self.edit_model and not self.editing:
|
|
34
|
+
self.edit_model.value = model_value
|
|
35
|
+
|
|
36
|
+
super().update(prev)
|
|
37
|
+
|
|
38
|
+
def on_editing_finished(self):
|
|
39
|
+
node = self.get_node()
|
|
40
|
+
node.editing = False
|
|
41
|
+
value = self.ui.text()
|
|
42
|
+
node.model.value = value
|
|
43
|
+
if node.edit_model:
|
|
44
|
+
node.edit_model.value = value
|
|
45
|
+
model_value = str(self.model.value)
|
|
46
|
+
self.ui.blockSignals(True)
|
|
47
|
+
self.ui.setText(model_value)
|
|
48
|
+
self.ui.blockSignals(False)
|
|
49
|
+
e = PUIEvent()
|
|
50
|
+
e.value = value
|
|
51
|
+
self._change(e)
|
|
52
|
+
node.ui.clearFocus()
|
|
53
|
+
|
|
54
|
+
def on_textchanged(self):
|
|
55
|
+
node = self.get_node()
|
|
56
|
+
node.editing = True
|
|
57
|
+
value = self.ui.text()
|
|
58
|
+
if node.edit_model:
|
|
59
|
+
node.edit_model.value = value
|
|
60
|
+
e = PUIEvent()
|
|
61
|
+
e.value = value
|
|
62
|
+
self._input(e)
|
PUI/PySide6/toolbar.py
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
|
|
4
|
+
class ToolBar(PUINode):
|
|
5
|
+
pui_outoforder = True
|
|
6
|
+
def update(self, prev):
|
|
7
|
+
if prev and prev.ui:
|
|
8
|
+
self.ui = prev.ui
|
|
9
|
+
self.actions = prev.actions
|
|
10
|
+
else:
|
|
11
|
+
self.ui = QtWidgets.QToolBar()
|
|
12
|
+
self.actions = []
|
|
13
|
+
|
|
14
|
+
super().update(prev)
|
|
15
|
+
|
|
16
|
+
def addChild(self, idx, child):
|
|
17
|
+
if idx < len(self.actions):
|
|
18
|
+
if isinstance(child, ToolBarAction):
|
|
19
|
+
self.actions.insert(idx, self.ui.insertAction(self.actions[idx], child.outer))
|
|
20
|
+
else:
|
|
21
|
+
self.actions.insert(idx, self.ui.insertWidget(self.actions[idx], child.outer))
|
|
22
|
+
else:
|
|
23
|
+
if isinstance(child, ToolBarAction):
|
|
24
|
+
self.actions.append(self.ui.addAction(child.outer))
|
|
25
|
+
else:
|
|
26
|
+
self.actions.append(self.ui.addWidget(child.outer))
|
|
27
|
+
|
|
28
|
+
def removeChild(self, idx, child):
|
|
29
|
+
self.ui.removeAction(self.actions[idx])
|
|
30
|
+
|
|
31
|
+
class ToolBarAction(PUINode):
|
|
32
|
+
def __init__(self, text, icon=None):
|
|
33
|
+
super().__init__()
|
|
34
|
+
self.text = text
|
|
35
|
+
self.icon = icon
|
|
36
|
+
self.onTriggered = None
|
|
37
|
+
|
|
38
|
+
def update(self, prev):
|
|
39
|
+
if prev and prev.ui:
|
|
40
|
+
self.ui = prev.ui
|
|
41
|
+
self.ui.setText(self.text)
|
|
42
|
+
self.ui.triggered.disconnect()
|
|
43
|
+
else:
|
|
44
|
+
self.ui = QtGui.QAction(self.text)
|
|
45
|
+
if self.icon:
|
|
46
|
+
self.ui.setIcon(self.icon)
|
|
47
|
+
self.ui.triggered.connect(self._triggered)
|
|
48
|
+
|
|
49
|
+
super().update(prev)
|
|
50
|
+
|
|
51
|
+
def _triggered(self):
|
|
52
|
+
node = self.get_node()
|
|
53
|
+
if node.onTriggered:
|
|
54
|
+
node.onTriggered[0](*node.onTriggered[1], **node.onTriggered[2])
|
|
55
|
+
|
|
56
|
+
def trigger(self, callback, *cb_args, **cb_kwargs):
|
|
57
|
+
self.onTriggered = (callback, cb_args, cb_kwargs)
|
PUI/PySide6/tree.py
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
from PySide6.QtCore import Qt, QModelIndex, QAbstractItemModel
|
|
4
|
+
|
|
5
|
+
class QAbstractItemModelAdapter(QtCore.QAbstractItemModel):
|
|
6
|
+
def __init__(self, model: "BaseTreeAdapter"):
|
|
7
|
+
super().__init__()
|
|
8
|
+
self.model = model
|
|
9
|
+
|
|
10
|
+
def index(self, row, column, parent = QtCore.QModelIndex()):
|
|
11
|
+
parent_node = parent.internalPointer() if parent.isValid() else None
|
|
12
|
+
if 0 <= row and row < self.model.rowCount(parent_node):
|
|
13
|
+
child = self.model.child(parent_node, row)
|
|
14
|
+
return self.createIndex(row, column, child)
|
|
15
|
+
return QtCore.QModelIndex()
|
|
16
|
+
|
|
17
|
+
def parent(self, index):
|
|
18
|
+
if not index.isValid():
|
|
19
|
+
return QModelIndex()
|
|
20
|
+
node = index.internalPointer()
|
|
21
|
+
parent_node = self.model.parent(node)
|
|
22
|
+
if parent_node:
|
|
23
|
+
return self.createIndex(0, 0, parent_node)
|
|
24
|
+
return QModelIndex()
|
|
25
|
+
|
|
26
|
+
def data(self, index, role):
|
|
27
|
+
if not index.isValid():
|
|
28
|
+
return None
|
|
29
|
+
node = index.internalPointer()
|
|
30
|
+
if role == QtCore.Qt.DisplayRole:
|
|
31
|
+
return self.model.data(node)
|
|
32
|
+
return None
|
|
33
|
+
|
|
34
|
+
def rowCount(self, parent):
|
|
35
|
+
parent_node = parent.internalPointer() if parent.isValid() else None
|
|
36
|
+
return self.model.rowCount(parent_node)
|
|
37
|
+
|
|
38
|
+
def columnCount(self, parent):
|
|
39
|
+
return 1
|
|
40
|
+
|
|
41
|
+
def hasChildren(self, parent):
|
|
42
|
+
parent_node = parent.internalPointer() if parent.isValid() else None
|
|
43
|
+
return self.model.rowCount(parent_node) > 0
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class Tree(QtBaseWidget):
|
|
47
|
+
def __init__(self, model):
|
|
48
|
+
super().__init__()
|
|
49
|
+
self.layout_weight = 1
|
|
50
|
+
self.model = model
|
|
51
|
+
self.curr_model = None
|
|
52
|
+
self.pendings = []
|
|
53
|
+
|
|
54
|
+
def update(self, prev):
|
|
55
|
+
if prev and prev.ui:
|
|
56
|
+
self.ui = prev.ui
|
|
57
|
+
self.qt_model = prev.qt_model
|
|
58
|
+
self.curr_model = prev.curr_model
|
|
59
|
+
else:
|
|
60
|
+
self.qt_model = None
|
|
61
|
+
self.curr_model = Prop()
|
|
62
|
+
self.ui = QtWidgets.QTreeView()
|
|
63
|
+
self.ui.setHeaderHidden(True)
|
|
64
|
+
self.ui.clicked.connect(self.on_item_clicked)
|
|
65
|
+
self.ui.doubleClicked.connect(self.on_item_double_clicked)
|
|
66
|
+
self.ui.expanded.connect(self.on_item_expanded)
|
|
67
|
+
self.ui.collapsed.connect(self.on_item_collapsed)
|
|
68
|
+
|
|
69
|
+
if self.curr_model.set(self.model):
|
|
70
|
+
self.qt_model = QAbstractItemModelAdapter(self.model)
|
|
71
|
+
self.ui.setModel(self.qt_model)
|
|
72
|
+
else:
|
|
73
|
+
self.qt_model.modelReset.emit()
|
|
74
|
+
|
|
75
|
+
for pending in self.pendings:
|
|
76
|
+
pending[0](*pending[1:])
|
|
77
|
+
self.pendings = []
|
|
78
|
+
|
|
79
|
+
super().update(prev)
|
|
80
|
+
|
|
81
|
+
def expandAll(self):
|
|
82
|
+
if self.ui:
|
|
83
|
+
self.ui.expandAll()
|
|
84
|
+
else:
|
|
85
|
+
self.pendings.append([self.expandAll])
|
|
86
|
+
return self
|
|
87
|
+
|
|
88
|
+
def collapseAll(self):
|
|
89
|
+
if self.ui:
|
|
90
|
+
self.ui.collapseAll()
|
|
91
|
+
else:
|
|
92
|
+
self.pendings.append([self.collapseAll])
|
|
93
|
+
return self
|
|
94
|
+
|
|
95
|
+
def expandable(self, enabled):
|
|
96
|
+
if self.ui:
|
|
97
|
+
self.ui.setItemsExpandable(enabled)
|
|
98
|
+
else:
|
|
99
|
+
self.pendings.append([self.expandable, enabled])
|
|
100
|
+
return self
|
|
101
|
+
|
|
102
|
+
def on_item_clicked(self, index):
|
|
103
|
+
node = self.get_node()
|
|
104
|
+
treenode = index.internalPointer()
|
|
105
|
+
node.model.clicked(treenode)
|
|
106
|
+
|
|
107
|
+
def on_item_double_clicked(self, index):
|
|
108
|
+
node = self.get_node()
|
|
109
|
+
treenode = index.internalPointer()
|
|
110
|
+
node.model.dblclicked(treenode)
|
|
111
|
+
|
|
112
|
+
def on_item_expanded(self, index):
|
|
113
|
+
node = self.get_node()
|
|
114
|
+
treenode = index.internalPointer()
|
|
115
|
+
node.model.expanded(treenode)
|
|
116
|
+
|
|
117
|
+
def on_item_collapsed(self, index):
|
|
118
|
+
node = self.get_node()
|
|
119
|
+
treenode = index.internalPointer()
|
|
120
|
+
node.model.collapsed(treenode)
|
PUI/PySide6/window.py
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
from .menu import *
|
|
4
|
+
from .modal import *
|
|
5
|
+
from .toolbar import *
|
|
6
|
+
from PySide6 import QtWidgets
|
|
7
|
+
|
|
8
|
+
class QMainWindow(QtWidgets.QMainWindow):
|
|
9
|
+
def keyPressEvent(self, event):
|
|
10
|
+
e = PUIEvent()
|
|
11
|
+
e.text = event.text()
|
|
12
|
+
self.node._keypress(e)
|
|
13
|
+
|
|
14
|
+
def mousePressEvent(self, event):
|
|
15
|
+
focused_widget = QtWidgets.QApplication.focusWidget()
|
|
16
|
+
if isinstance(focused_widget, QtWidgets.QLineEdit):
|
|
17
|
+
focused_widget.clearFocus()
|
|
18
|
+
super().mousePressEvent(event)
|
|
19
|
+
|
|
20
|
+
class Window(QtBaseWidget):
|
|
21
|
+
pui_terminal = False
|
|
22
|
+
|
|
23
|
+
def __init__(self, title=None, icon=None, size=None, maximize=None, fullscreen=None):
|
|
24
|
+
super().__init__()
|
|
25
|
+
self.title = title
|
|
26
|
+
if icon:
|
|
27
|
+
self.icon = QtGui.QIcon(icon)
|
|
28
|
+
else:
|
|
29
|
+
self.icon = None
|
|
30
|
+
self.size = size
|
|
31
|
+
self.maximize = maximize
|
|
32
|
+
self.fullscreen = fullscreen
|
|
33
|
+
|
|
34
|
+
def update(self, prev=None):
|
|
35
|
+
if prev and prev.ui:
|
|
36
|
+
self.ui = prev.ui
|
|
37
|
+
self.ui.node = self
|
|
38
|
+
self.curr_size = prev.curr_size
|
|
39
|
+
self.curr_maximize = prev.curr_maximize
|
|
40
|
+
self.curr_fullscreen = prev.curr_fullscreen
|
|
41
|
+
else:
|
|
42
|
+
self.ui = QMainWindow()
|
|
43
|
+
self.ui.node = self
|
|
44
|
+
self.ui.show()
|
|
45
|
+
self.curr_size = Prop()
|
|
46
|
+
self.curr_maximize = Prop()
|
|
47
|
+
self.curr_fullscreen = Prop()
|
|
48
|
+
|
|
49
|
+
if self.curr_size.set(self.size):
|
|
50
|
+
self.ui.resize(*self.size)
|
|
51
|
+
if self.curr_maximize.set(self.maximize):
|
|
52
|
+
self.ui.showMaximized()
|
|
53
|
+
if self.curr_fullscreen.set(self.fullscreen):
|
|
54
|
+
self.ui.showFullScreen()
|
|
55
|
+
if not self.title is None:
|
|
56
|
+
self.ui.setWindowTitle(self.title)
|
|
57
|
+
if not self.icon is None:
|
|
58
|
+
self.ui.setWindowIcon(self.icon)
|
|
59
|
+
super().update(prev)
|
|
60
|
+
|
|
61
|
+
def addChild(self, idx, child):
|
|
62
|
+
if isinstance(child, MenuBar):
|
|
63
|
+
self.ui.setMenuBar(child.outer)
|
|
64
|
+
elif isinstance(child, ToolBar):
|
|
65
|
+
self.ui.addToolBar(child.outer)
|
|
66
|
+
elif isinstance(child, Modal):
|
|
67
|
+
pass
|
|
68
|
+
elif isinstance(child, QtBaseWidget) or isinstance(child, QtBaseLayout):
|
|
69
|
+
self.ui.setCentralWidget(child.outer)
|
|
70
|
+
else:
|
|
71
|
+
self.addChild(idx, child.children[0])
|
|
72
|
+
|
|
73
|
+
def removeChild(self, idx, child):
|
|
74
|
+
if isinstance(child, MenuBar):
|
|
75
|
+
child.outer.close()
|
|
76
|
+
elif isinstance(child, Modal):
|
|
77
|
+
pass
|
|
78
|
+
elif isinstance(child, QtBaseWidget) or isinstance(child, QtBaseLayout):
|
|
79
|
+
child.outer.setParent(None)
|
|
80
|
+
else:
|
|
81
|
+
self.removeChild(idx, child.children[0])
|