PaIRS-UniNa 0.2.7__cp312-cp312-win_amd64.whl → 0.2.8__cp312-cp312-win_amd64.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.
- PaIRS_UniNa/Changes.txt +18 -0
- PaIRS_UniNa/Explorer.py +3126 -3076
- PaIRS_UniNa/FolderLoop.py +561 -371
- PaIRS_UniNa/Input_Tab.py +826 -717
- PaIRS_UniNa/Input_Tab_CalVi.py +10 -12
- PaIRS_UniNa/Input_Tab_tools.py +3019 -3018
- PaIRS_UniNa/Output_Tab.py +1 -3
- PaIRS_UniNa/PaIRS.py +17 -17
- PaIRS_UniNa/PaIRS_pypacks.py +45 -0
- PaIRS_UniNa/Saving_tools.py +277 -277
- PaIRS_UniNa/Vis_Tab.py +39 -18
- PaIRS_UniNa/Whatsnew.py +4 -3
- PaIRS_UniNa/_PaIRS_PIV.pyd +0 -0
- PaIRS_UniNa/__init__.py +2 -2
- PaIRS_UniNa/gPaIRS.py +3889 -3832
- PaIRS_UniNa/icons/folder_loop_cleanup.png +0 -0
- PaIRS_UniNa/icons/folder_loop_cleanup_off.png +0 -0
- PaIRS_UniNa/icons/scan_path_loop.png +0 -0
- PaIRS_UniNa/icons/scan_path_loop_off.png +0 -0
- PaIRS_UniNa/listLib.py +301 -301
- PaIRS_UniNa/parForMulti.py +433 -433
- PaIRS_UniNa/procTools.py +46 -1
- PaIRS_UniNa/tabSplitter.py +606 -606
- PaIRS_UniNa/ui_Calibration_Tab.py +542 -542
- PaIRS_UniNa/ui_Custom_Top.py +294 -294
- PaIRS_UniNa/ui_Input_Tab.py +1098 -1098
- PaIRS_UniNa/ui_Input_Tab_CalVi.py +1280 -1280
- PaIRS_UniNa/ui_Log_Tab.py +261 -261
- PaIRS_UniNa/ui_Output_Tab.py +2360 -2360
- PaIRS_UniNa/ui_Process_Tab.py +3808 -3808
- PaIRS_UniNa/ui_Process_Tab_CalVi.py +1547 -1547
- PaIRS_UniNa/ui_Process_Tab_Disp.py +1139 -1139
- PaIRS_UniNa/ui_Process_Tab_Min.py +435 -435
- PaIRS_UniNa/ui_ResizePopup.py +203 -203
- PaIRS_UniNa/ui_Vis_Tab.py +1626 -1626
- PaIRS_UniNa/ui_Vis_Tab_CalVi.py +1249 -1249
- PaIRS_UniNa/ui_Whatsnew.py +131 -131
- PaIRS_UniNa/ui_gPairs.py +873 -873
- PaIRS_UniNa/ui_infoPaIRS.py +550 -550
- PaIRS_UniNa/whatsnew.txt +3 -2
- {pairs_unina-0.2.7.dist-info → pairs_unina-0.2.8.dist-info}/METADATA +13 -8
- {pairs_unina-0.2.7.dist-info → pairs_unina-0.2.8.dist-info}/RECORD +44 -40
- {pairs_unina-0.2.7.dist-info → pairs_unina-0.2.8.dist-info}/WHEEL +0 -0
- {pairs_unina-0.2.7.dist-info → pairs_unina-0.2.8.dist-info}/top_level.txt +0 -0
PaIRS_UniNa/tabSplitter.py
CHANGED
|
@@ -1,612 +1,612 @@
|
|
|
1
|
-
import sys
|
|
1
|
+
import sys
|
|
2
2
|
from .PaIRS_pypacks import *
|
|
3
3
|
from .Input_Tab import *
|
|
4
4
|
from .Output_Tab import *
|
|
5
5
|
from .Process_Tab import *
|
|
6
6
|
from .Log_Tab import *
|
|
7
7
|
from .Vis_Tab import *
|
|
8
|
-
|
|
9
|
-
class PaIRS_QSplitter(QSplitter):
|
|
10
|
-
minimumResizeWidth=0
|
|
11
|
-
class PaIRS_ToggleSplitterHandle(QtWidgets.QSplitterHandle):
|
|
12
|
-
minimumHandleDisplacement=200
|
|
13
|
-
def __init__(self, o: Qt.Orientation, parent: QSplitter):
|
|
14
|
-
super().__init__(o, parent)
|
|
15
|
-
self.index=parent.count()-1
|
|
16
|
-
self.limits=[None,None]
|
|
17
|
-
#pri.Coding.yellow(f'Splitter handle #{self.index}')
|
|
18
|
-
self.init_pos=None
|
|
19
|
-
return
|
|
20
|
-
|
|
21
|
-
def mousePressEvent(self, event:QMouseEvent):
|
|
22
|
-
super().mousePressEvent(event)
|
|
23
|
-
|
|
24
|
-
TABpar.FlagSettingPar=True
|
|
25
|
-
pa:PaIRS_QSplitter=self.parent()
|
|
26
|
-
visibleHandles=[]
|
|
27
|
-
widgets=[]
|
|
28
|
-
visibleWidgets=[]
|
|
29
|
-
for i in range(pa.count()):
|
|
30
|
-
handle = pa.handle(i)
|
|
31
|
-
if handle.isVisible():
|
|
32
|
-
visibleHandles.append(handle)
|
|
33
|
-
widget=pa.widget(i)
|
|
34
|
-
widgets.append(widget)
|
|
35
|
-
if widget.isVisible():
|
|
36
|
-
visibleWidgets.append(widget)
|
|
37
|
-
i=visibleHandles.index(self)
|
|
38
|
-
self.index=widgets.index(visibleWidgets[i])
|
|
39
|
-
"""
|
|
40
|
-
width=0
|
|
41
|
-
index=-1
|
|
42
|
-
sizes=pa.splitterSizes
|
|
43
|
-
#sizes=pa.sizes()
|
|
44
|
-
while self.pos().x()>width and index<pa.count()-1:
|
|
45
|
-
index+=1
|
|
46
|
-
w=pa.widget(index)
|
|
47
|
-
if w:
|
|
48
|
-
if w.isVisible():
|
|
49
|
-
width+=sizes[index]+pa.handleWidth()
|
|
50
|
-
self.index=index
|
|
51
|
-
"""
|
|
52
|
-
pri.Coding.magenta(f'pos={self.pos().x()} index={self.index}')
|
|
53
|
-
|
|
54
|
-
w=pa.widget(self.index)
|
|
55
|
-
w.setMinimumWidth(pa.minimumSizes[self.index])
|
|
56
|
-
w.widget.setMinimumWidth(pa.minimumSizes[self.index])
|
|
57
|
-
w.setMaximumWidth(pa.maximumSizes[self.index])
|
|
58
|
-
w.widget.setMaximumWidth(pa.maximumSizes[self.index])
|
|
59
|
-
|
|
60
|
-
pri.Coding.magenta(f'{w.widget.TABname} [{pa.minimumSizes[self.index]},{pa.maximumSizes[self.index]}]')
|
|
61
|
-
dwf=w.maximumWidth()-w.minimumWidth()
|
|
62
|
-
pa.splitterReleased([pa.count()-1],[+dwf],FlagReleased=False)
|
|
63
|
-
|
|
64
|
-
self.init_pos=self.pos().x()
|
|
65
|
-
self.limits=[w.minimumWidth()-w.width(),w.maximumWidth()-w.width()]
|
|
66
|
-
|
|
67
|
-
def mouseReleaseEvent(self, event:QMouseEvent):
|
|
68
|
-
super().mouseReleaseEvent(event)
|
|
69
|
-
|
|
70
|
-
TABpar.FlagSettingPar=False
|
|
71
|
-
if self.init_pos:
|
|
72
|
-
pa:PaIRS_QSplitter=self.parent()
|
|
73
|
-
w=pa.widget(self.index)
|
|
74
|
-
dw=self.pos().x()-self.init_pos
|
|
75
|
-
dwf=pa.maximumSizes[self.index]-w.minimumWidth()
|
|
76
|
-
indexes=[self.index,pa.count()-1]
|
|
77
|
-
deltaWidths=[dw,-dwf]
|
|
78
|
-
pa.splitterReleased(indexes,deltaWidths,FlagReleased=True)
|
|
79
|
-
|
|
80
|
-
w.setFixedWidth(pa.splitterSizes[self.index])
|
|
81
|
-
w.widget.setFixedWidth(pa.splitterSizes[self.index])
|
|
82
|
-
|
|
83
|
-
def mouseMoveEvent(self, event: QMouseEvent):
|
|
84
|
-
pa:PaIRS_QSplitter=self.parent()
|
|
85
|
-
#pa.splitterMoving(event.pos().x(),self.index)
|
|
86
|
-
|
|
87
|
-
pa.setSizes(pa.sizes())
|
|
88
|
-
|
|
89
|
-
pos=event.pos().x()
|
|
90
|
-
if pos and self.limits[0] and self.limits[1]:
|
|
91
|
-
pos=max([self.limits[0],pos])
|
|
92
|
-
pos=min([self.limits[1],pos])
|
|
93
|
-
pos+=self.pos().x()+self.width()
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
bar=pa.scrollArea.horizontalScrollBar()
|
|
97
|
-
val=bar.value()
|
|
98
|
-
wSA=pa.scrollArea.width()
|
|
99
|
-
#pri.Coding.magenta(f'val={val}\t pos={pos}\t wSA={wSA}')
|
|
100
|
-
if pos-val>wSA:
|
|
101
|
-
bar.setValue(pos-wSA)
|
|
102
|
-
elif pos<val:
|
|
103
|
-
bar.setValue(pos)
|
|
104
|
-
return super().mouseMoveEvent(event)
|
|
105
|
-
|
|
106
|
-
def createHandle(self):
|
|
107
|
-
handle =self.PaIRS_ToggleSplitterHandle(self.orientation(), self)
|
|
108
|
-
handle.setCursor(QCursor(Qt.SplitHCursor if self.orientation() == Qt.Horizontal else Qt.SplitVCursor))
|
|
109
|
-
return handle
|
|
110
|
-
|
|
111
|
-
def __init__(self, orientation, parent=None):
|
|
112
|
-
super().__init__(orientation, parent)
|
|
113
|
-
self.setOpaqueResize(False)
|
|
114
|
-
self.FlagInit=False
|
|
115
|
-
self.splitterSizes=[]
|
|
116
|
-
self.minimumSizes=[]
|
|
117
|
-
self.maximumSizes=[]
|
|
118
|
-
self.splitterMaximumSize=0
|
|
119
|
-
self.scrollArea:PaIRS_QScrollArea=None
|
|
120
|
-
|
|
121
|
-
def addWidget(self, widget):
|
|
122
|
-
if not self.FlagInit: i=self.count()
|
|
123
|
-
else: i=self.count()-1
|
|
124
|
-
return self.insertWidget(i,widget)
|
|
125
|
-
|
|
126
|
-
def insertWidget(self, i, widget):
|
|
127
|
-
self.splitterSizes.insert(i,widget.minimumWidth())
|
|
128
|
-
self.minimumSizes.insert(i,widget.minimumWidth())
|
|
129
|
-
self.maximumSizes.insert(i,widget.maximumWidth()+int(self.handleWidth()*0.5))
|
|
130
|
-
self.splitterMaximumSize+=self.minimumSizes[-1]+self.handleWidth()
|
|
131
|
-
widget.setMaximumWidth(widget.minimumWidth())
|
|
132
|
-
return super().insertWidget(i,widget)
|
|
133
|
-
|
|
134
|
-
def replaceWidget(self, i, widget):
|
|
135
|
-
self.splitterMaximumSize-=self.minimumSizes[i]+self.handleWidth()
|
|
136
|
-
self.splitterSizes[i]=widget.minimumWidth()
|
|
137
|
-
self.minimumSizes[i]=widget.minimumWidth()
|
|
138
|
-
self.maximumSizes[i]=widget.maximumWidth()+int(self.handleWidth()*0.5)
|
|
139
|
-
self.splitterMaximumSize+=self.minimumSizes[i]+self.handleWidth()
|
|
140
|
-
widget.setMaximumWidth(widget.minimumWidth())
|
|
141
|
-
return super().replaceWidget(i,widget)
|
|
142
|
-
|
|
143
|
-
def setHandleWidth(self, width: int) -> None:
|
|
144
|
-
self.maximumSizes=[m-int(0.5*self.handleWidth())+int(0.5*width) for m in self.maximumSizes]
|
|
145
|
-
return super().setHandleWidth(width)
|
|
146
|
-
|
|
147
|
-
def splitterReleased(self,indexes,deltaWidths,FlagReleased=True):
|
|
148
|
-
for index,dw in zip(indexes,deltaWidths):
|
|
149
|
-
w=self.widget(index)
|
|
150
|
-
self.splitterSizes[index]=max([min([self.splitterSizes[index]+dw,w.maximumWidth()]),w.minimumWidth()])
|
|
151
|
-
self.splitterResize(FlagReleased=FlagReleased)
|
|
152
|
-
pri.Coding.green(f'i= {indexes}\t dw={deltaWidths}\t Splitter sizes: {self.splitterSizes}')
|
|
153
|
-
|
|
154
|
-
def splitterResize(self,FlagVisible=None,FlagReleased=True):
|
|
155
|
-
width=0
|
|
156
|
-
if FlagReleased: self.splitterSizes[-1]=0
|
|
157
|
-
for i in range(self.count()):
|
|
158
|
-
w=self.widget(i)
|
|
159
|
-
if FlagVisible is not None: flag=FlagVisible[i]
|
|
160
|
-
else: flag=w.isVisible()
|
|
161
|
-
if flag:
|
|
162
|
-
width+=self.splitterSizes[i]+self.handleWidth()
|
|
163
|
-
pa=self.parent().parent()
|
|
164
|
-
if pa.width()>width:
|
|
165
|
-
self.splitterSizes[-1]+=pa.width()-width
|
|
166
|
-
width=pa.width()+self.handleWidth()
|
|
167
|
-
self.setFixedWidth(width)
|
|
168
|
-
self.setSizes(self.splitterSizes)
|
|
169
|
-
if FlagReleased:
|
|
170
|
-
for i in range(self.count()-1):
|
|
171
|
-
w=self.widget(i)
|
|
172
|
-
w.setFixedWidth(self.splitterSizes[i])
|
|
173
|
-
w.widget.setFixedWidth(self.splitterSizes[i])
|
|
174
|
-
return self.splitterSizes
|
|
175
|
-
|
|
176
|
-
def resizeEvent(self,event):
|
|
177
|
-
#self.splitterResize()
|
|
178
|
-
return
|
|
179
|
-
|
|
180
|
-
def setHandleVisibility(self):
|
|
181
|
-
for i in range(self.count()):
|
|
182
|
-
self.handle(i).setVisible(self.widget(i).isVisible())
|
|
183
|
-
|
|
184
|
-
class PaIRS_QScrollArea(QScrollArea):
|
|
185
|
-
def __init__(self,widgets=[],handleWidth=20,margin=0):
|
|
186
|
-
super().__init__()
|
|
187
|
-
self.handleWidth=handleWidth
|
|
188
|
-
self.margin=margin
|
|
189
|
-
|
|
190
|
-
self.setWidgetResizable(True)
|
|
191
|
-
self.container_widget = QWidget()
|
|
192
|
-
self.setWidget(self.container_widget)
|
|
193
|
-
self.main_layout = QVBoxLayout(self.container_widget)
|
|
194
|
-
self.main_layout.setContentsMargins(margin,margin,margin,margin)
|
|
195
|
-
|
|
196
|
-
self.splitter=None
|
|
197
|
-
self.setupSplitter(widgets)
|
|
198
|
-
|
|
199
|
-
def setupSplitter(self,widgets):
|
|
200
|
-
self.frames=[]
|
|
201
|
-
if not widgets:
|
|
202
|
-
return
|
|
203
|
-
if self.splitter:
|
|
204
|
-
self.main_layout.removeWidget(self.splitter)
|
|
205
|
-
self.splitter=splitter=PaIRS_QSplitter(Qt.Horizontal)
|
|
206
|
-
self.splitter.setObjectName('tabArea_splitter')
|
|
207
|
-
self.widgets=widgets
|
|
208
|
-
|
|
209
|
-
dw=0
|
|
210
|
-
# Aggiungi alcuni widget al QSplitter
|
|
211
|
-
for i,w in enumerate(widgets):
|
|
212
|
-
w:gPaIRS_Tab
|
|
213
|
-
w.blockSignals(True)
|
|
214
|
-
frame = QFrame()
|
|
215
|
-
frame_layout = QVBoxLayout(frame)
|
|
216
|
-
frame_layout.setContentsMargins(0,0,0,0)
|
|
217
|
-
frame.setMinimumWidth(w.minimumWidth())
|
|
218
|
-
frame.setMaximumWidth(w.maximumWidth())
|
|
219
|
-
dw+=max([dw,w.maximumWidth()-w.minimumWidth()])
|
|
220
|
-
|
|
221
|
-
objName=f'{w.TABname}_frame'
|
|
222
|
-
frame.setObjectName(objName)
|
|
223
|
-
frame.setStyleSheet(f"""
|
|
224
|
-
QFrame#{objName} {{
|
|
225
|
-
border: 1px solid rgba(128, 128, 128, 0.5);
|
|
226
|
-
border-radius: 15px;
|
|
227
|
-
background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 rgba(128, 128, 128, 0), stop:1 rgba(224, 224, 224, 0.25));
|
|
228
|
-
}}
|
|
229
|
-
QWidget#scrollAreaWidgetContents{{
|
|
230
|
-
background: transparent;
|
|
231
|
-
}}
|
|
232
|
-
""")
|
|
233
|
-
|
|
234
|
-
splitter.addWidget(frame)
|
|
235
|
-
splitter.setCollapsible(i,False)
|
|
236
|
-
#if i in (0,3): frame.hide()
|
|
237
|
-
frame_layout.addWidget(w)
|
|
238
|
-
setattr(frame,'widget',w)
|
|
239
|
-
frame.setVisible(False)
|
|
240
|
-
self.frames.append(frame)
|
|
241
|
-
if hasattr(w,'ui') and hasattr(w.ui,'scrollArea'):
|
|
242
|
-
w.ui.scrollArea.setObjectName('scroll_area_'+w.TABname)
|
|
243
|
-
w.blockSignals(False)
|
|
244
|
-
|
|
245
|
-
frame = QFrame()
|
|
246
|
-
objName=f'empty_frame'
|
|
247
|
-
frame.setMinimumWidth(50)
|
|
248
|
-
frame.setMaximumWidth(dw)
|
|
249
|
-
|
|
250
|
-
frame.setObjectName(objName)
|
|
251
|
-
frame.setStyleSheet(f"""
|
|
252
|
-
QFrame#{objName} {{
|
|
253
|
-
border: none;
|
|
254
|
-
background: transparent;
|
|
255
|
-
}}
|
|
256
|
-
""")
|
|
257
|
-
splitter.addWidget(frame)
|
|
258
|
-
frame.setMaximumWidth(dw)
|
|
259
|
-
setattr(frame,'TABname','Empty frame')
|
|
260
|
-
setattr(frame,'widget',frame)
|
|
261
|
-
self.frames.append(frame)
|
|
262
|
-
|
|
263
|
-
splitter.setHandleWidth(self.handleWidth)
|
|
264
|
-
splitter.scrollArea=self
|
|
265
|
-
self.main_layout.addWidget(self.splitter)
|
|
266
|
-
|
|
267
|
-
def resizeEvent(self, event: QResizeEvent):
|
|
268
|
-
self.update()
|
|
269
|
-
total_height = self.viewport().height()
|
|
270
|
-
scrollbar_height = self.horizontalScrollBar().height() if self.horizontalScrollBar().isVisible() else 0
|
|
271
|
-
available_height = total_height - scrollbar_height
|
|
272
|
-
for f,w in zip(self.frames,self.widgets):
|
|
273
|
-
f:QFrame
|
|
274
|
-
available_height=max([available_height,w.minimumHeight()])
|
|
275
|
-
for f,w in zip(self.frames,self.widgets):
|
|
276
|
-
f:QFrame
|
|
277
|
-
f.setMinimumHeight(available_height)
|
|
278
|
-
self.splitter.setMinimumHeight(available_height)
|
|
279
|
-
self.container_widget.setMinimumHeight(available_height+scrollbar_height)
|
|
280
|
-
|
|
281
|
-
return super().resizeEvent(event)
|
|
282
|
-
|
|
283
|
-
class SPLpar(TABpar):
|
|
284
|
-
sizes_default = []
|
|
285
|
-
FlagVisible_default = []
|
|
286
|
-
horizontalBarValues_default = {}
|
|
287
|
-
verticalBarValues_default = {}
|
|
288
|
-
FlagCollapsibleBoxes_default = {}
|
|
289
|
-
|
|
290
|
-
def __init__(self,Process=ProcessTypes.null,Step=StepTypes.null):
|
|
291
|
-
self.setup(Process,Step)
|
|
292
|
-
super().__init__('SPLpar','TabAreaWidget')
|
|
293
|
-
self.unchecked_fields+=[]
|
|
294
|
-
|
|
295
|
-
def setup(self,Process,Step):
|
|
296
|
-
self.Process=Process
|
|
297
|
-
self.Step=Step
|
|
298
|
-
self.sizes=[s for s in SPLpar.sizes_default]
|
|
299
|
-
self.FlagVisible=[f for f in SPLpar.FlagVisible_default]
|
|
300
|
-
self.horizontalBarValues=copy.deepcopy(SPLpar.horizontalBarValues_default)
|
|
301
|
-
self.verticalBarValues=copy.deepcopy(SPLpar.verticalBarValues_default)
|
|
302
|
-
self.FlagCollapsibleBoxes=copy.deepcopy(SPLpar.FlagCollapsibleBoxes_default)
|
|
303
|
-
|
|
304
|
-
class TabAreaWidget(gPaIRS_Tab):
|
|
305
|
-
margin=10
|
|
306
|
-
|
|
307
|
-
buttonSpacing=10
|
|
308
|
-
buttonSize=[40,30]
|
|
309
|
-
iconSize=20
|
|
310
|
-
|
|
311
|
-
widgetMinimumWidth=550
|
|
312
|
-
widgetMaximumWidth=1100
|
|
313
|
-
widgetMinimumHeight=650
|
|
314
|
-
tabAreaMinimumHeight=750
|
|
315
|
-
widgetMaximumHeight=10000
|
|
316
|
-
widgetHorizontalMargin=10
|
|
317
|
-
widgetVerticalMargin=5
|
|
318
|
-
handleWidth=20
|
|
319
|
-
|
|
320
|
-
def __init__(self, parent: QWidget = None, widgets=[],icons=[]):
|
|
321
|
-
super().__init__(parent,UiClass=None,ParClass=SPLpar)
|
|
322
|
-
if __name__ == "__main__":
|
|
323
|
-
iconW = QIcon()
|
|
324
|
-
iconW.addFile(u""+ icons_path +"logo_PaIRS.png", QSize(), QIcon.Normal, QIcon.Off)
|
|
325
|
-
self.setWindowTitle('Tab area widget')
|
|
326
|
-
self.setWindowIcon(iconW)
|
|
327
|
-
self.main_layout=QVBoxLayout()
|
|
328
|
-
|
|
329
|
-
#------------------------------------- Graphical interface: miscellanea
|
|
330
|
-
self.TABname='TabArea'
|
|
331
|
-
m=self.margin
|
|
332
|
-
self.setMinimumWidth(self.widgetMinimumWidth+m*2+self.handleWidth)
|
|
333
|
-
self.tabAreaHeight=self.buttonSize[1]+self.buttonSpacing+self.tabAreaMinimumHeight+m*4
|
|
334
|
-
#self.setMinimumHeight(self.buttonSize[1]+self.buttonSpacing+self.widgetMinimumHeight+m*4)
|
|
335
|
-
self.main_layout.setContentsMargins(m,m,m,m)
|
|
336
|
-
self.main_layout.setSpacing(self.buttonSpacing)
|
|
337
|
-
self.setLayout(self.main_layout)
|
|
338
|
-
|
|
339
|
-
self.buttonBar=QWidget()
|
|
340
|
-
self.buttonBar_layout=QHBoxLayout()
|
|
341
|
-
self.buttonBar_layout.setContentsMargins(0,0,0,0)
|
|
342
|
-
self.buttonBar_layout.setSpacing(self.buttonSpacing)
|
|
343
|
-
self.buttonBar.setLayout(self.buttonBar_layout)
|
|
344
|
-
self.buttonSpacer=QSpacerItem(self.buttonSize[0],self.buttonSize[1],QSizePolicy.Expanding, QSizePolicy.Minimum)
|
|
345
|
-
self.buttonBar_layout.addSpacerItem(self.buttonSpacer)
|
|
346
|
-
|
|
347
|
-
self.scrollArea = PaIRS_QScrollArea(handleWidth=self.handleWidth)
|
|
348
|
-
self.scrollArea.setObjectName('scroll_area_tabArea')
|
|
349
|
-
|
|
350
|
-
self.main_layout.addWidget(self.buttonBar)
|
|
351
|
-
self.main_layout.addWidget(self.scrollArea)
|
|
352
|
-
|
|
353
|
-
#------------------------------------- Declaration of parameters
|
|
354
|
-
self.SPLpar_base=SPLpar()
|
|
355
|
-
self.SPLpar:SPLpar=self.TABpar
|
|
356
|
-
self.SPLpar_old:SPLpar=self.TABpar_old
|
|
357
|
-
|
|
358
|
-
#------------------------------------- Callbacks
|
|
359
|
-
self.buttons=[]
|
|
360
|
-
self.animation = QVariantAnimation(self.scrollArea)
|
|
361
|
-
self.animation.valueChanged.connect(self.moveTo)
|
|
362
|
-
self.scrollArea.horizontalScrollBar().valueChanged.connect(self.finishAnimation)
|
|
363
|
-
|
|
364
|
-
self.setTABlayout=self.setSPLlayout
|
|
365
|
-
self.FlagAddPrev=False
|
|
366
|
-
self.FlagBridge=False
|
|
367
|
-
self.FlagAnimationRunning=False
|
|
368
|
-
|
|
369
|
-
self.setupWid()
|
|
370
|
-
if __name__ == "__main__":
|
|
371
|
-
self.app=app
|
|
372
|
-
setAppGuiPalette(self)
|
|
373
|
-
|
|
374
|
-
self.FlagDisplayControls=False
|
|
375
|
-
self.setupTabArea(widgets,icons)
|
|
376
|
-
|
|
377
|
-
def null(self):
|
|
378
|
-
return True
|
|
379
|
-
|
|
380
|
-
def setupTabArea(self,widgets,icons):
|
|
381
|
-
self.widgets=widgets
|
|
382
|
-
if not widgets: return
|
|
383
|
-
for b in self.buttons:
|
|
384
|
-
b:RichTextPushButton
|
|
385
|
-
self.buttonBar_layout.removeWidget(b)
|
|
386
|
-
b.setParent(None)
|
|
387
|
-
self.buttons=[]
|
|
388
|
-
self.setupButtons(widgets,icons)
|
|
389
|
-
self.scrollArea.setupSplitter(widgets)
|
|
390
|
-
self.scrollArea.splitter.splitterResize=self.splitterResize
|
|
391
|
-
|
|
392
|
-
self.SPLpar.sizes=[w.width() for w in widgets]+[self.scrollArea.splitter.minimumResizeWidth]
|
|
393
|
-
self.SPLpar.FlagVisible=[True for w in widgets]+[True]
|
|
394
|
-
self.SPLpar.horizontalBarValues={}
|
|
395
|
-
self.SPLpar.verticalBarValues={}
|
|
396
|
-
|
|
397
|
-
self.scrollAreas=self.findChildren(QScrollArea)
|
|
398
|
-
self.collapBoxes=[]
|
|
399
|
-
for w in self.widgets:
|
|
400
|
-
w:gPaIRS_Tab
|
|
401
|
-
self.scrollAreas+=w.findChildren(QScrollArea)
|
|
402
|
-
self.scrollAreas+=w.findChildren(QTextEdit)
|
|
403
|
-
self.scrollAreas+=w.findChildren(QTableWidget)
|
|
404
|
-
self.scrollAreas+=w.findChildren(QTreeWidget)
|
|
405
|
-
self.collapBoxes+=w.findChildren(CollapsibleBox)
|
|
406
|
-
for s in self.scrollAreas:
|
|
407
|
-
s:QScrollArea
|
|
408
|
-
if s.objectName()=='': continue
|
|
409
|
-
self.SPLpar.horizontalBarValues[s.objectName()]=s.horizontalScrollBar().value()
|
|
410
|
-
self.SPLpar.verticalBarValues[s.objectName()]=s.verticalScrollBar().value()
|
|
411
|
-
s.horizontalScrollBar().valueChanged.connect(lambda v, scrllr=s: self.updateScrollBarValue(scrllr,True))
|
|
412
|
-
s.verticalScrollBar().valueChanged.connect(lambda v, scrllr=s: self.updateScrollBarValue(scrllr,False))
|
|
413
|
-
for cB in self.collapBoxes:
|
|
414
|
-
cB:CollapsibleBox
|
|
415
|
-
self.SPLpar.FlagCollapsibleBoxes[cB.objectName()]=cB.toggle_button.isChecked()
|
|
416
|
-
cB.toggle_button.clicked.connect(lambda v, cllpbx=cB: self.updateFlagCollapsibleBox(cllpbx))
|
|
417
|
-
|
|
418
|
-
SPLpar.sizes_default=[w.width() for w in widgets]+[self.scrollArea.splitter.minimumResizeWidth]
|
|
419
|
-
SPLpar.FlagVisible_default=[True for w in widgets]+[True]
|
|
420
|
-
for k in self.SPLpar.horizontalBarValues:
|
|
421
|
-
SPLpar.horizontalBarValues_default[k]=0
|
|
422
|
-
for k in self.SPLpar.verticalBarValues:
|
|
423
|
-
SPLpar.verticalBarValues_default[k]=0
|
|
424
|
-
for k in self.SPLpar.FlagCollapsibleBoxes:
|
|
425
|
-
SPLpar.FlagCollapsibleBoxes_default[k]=True
|
|
426
|
-
#self.nullCallback()
|
|
427
|
-
#self.adjustTABparInd()
|
|
428
|
-
|
|
429
|
-
def updateFlagCollapsibleBox(self,collapBox:CollapsibleBox):
|
|
430
|
-
if self.FlagSettingPar: return
|
|
431
|
-
self.SPLpar.FlagCollapsibleBoxes[collapBox.objectName()]=collapBox.toggle_button.isChecked()
|
|
432
|
-
TABpar_ind:SPLpar=self.TABpar_at(self.TABpar.ind)
|
|
433
|
-
if TABpar_ind: TABpar_ind.FlagCollapsibleBoxes[collapBox.objectName()]=collapBox.toggle_button.isChecked()
|
|
434
|
-
|
|
435
|
-
def setFlagCollapsibleBox(self):
|
|
436
|
-
for cB in self.collapBoxes:
|
|
437
|
-
cB:CollapsibleBox
|
|
438
|
-
if cB.objectName() in self.SPLpar.FlagCollapsibleBoxes:
|
|
439
|
-
if self.SPLpar.FlagCollapsibleBoxes[cB.objectName()]!=cB.toggle_button.isChecked():
|
|
440
|
-
cB.toggle_button.setChecked(self.SPLpar.FlagCollapsibleBoxes[cB.objectName()])
|
|
441
|
-
cB.on_click()
|
|
442
|
-
|
|
443
|
-
def updateScrollBarValue(self,scrollArea:QScrollArea=None,flagHorizontal:bool=True):
|
|
444
|
-
if self.FlagAnimationRunning or self.FlagSettingPar: return
|
|
445
|
-
TABpar_ind:SPLpar=self.TABpar_at(self.TABpar.ind)
|
|
446
|
-
|
|
447
|
-
if flagHorizontal:
|
|
448
|
-
pri.Coding.magenta(f'{scrollArea.objectName()} horizontal ScrollBar value: {scrollArea.horizontalScrollBar().value()}')
|
|
449
|
-
self.SPLpar.horizontalBarValues[scrollArea.objectName()]=scrollArea.horizontalScrollBar().value()
|
|
450
|
-
if TABpar_ind: TABpar_ind.horizontalBarValues[scrollArea.objectName()]=scrollArea.horizontalScrollBar().value()
|
|
451
|
-
else:
|
|
452
|
-
pri.Coding.magenta(f'{scrollArea.objectName()} vertical ScrollBar value: {scrollArea.verticalScrollBar().value()}')
|
|
453
|
-
self.SPLpar.verticalBarValues[scrollArea.objectName()]=scrollArea.verticalScrollBar().value()
|
|
454
|
-
if TABpar_ind: TABpar_ind.verticalBarValues[scrollArea.objectName()]=scrollArea.verticalScrollBar().value()
|
|
455
|
-
|
|
456
|
-
def setScrollBarValues(self):
|
|
457
|
-
for s in self.scrollAreas:
|
|
458
|
-
s:QScrollArea
|
|
459
|
-
if s.objectName() in self.SPLpar.horizontalBarValues:
|
|
460
|
-
if self.SPLpar.horizontalBarValues[s.objectName()]!=s.horizontalScrollBar().value():
|
|
461
|
-
s.horizontalScrollBar().setValue(self.SPLpar.horizontalBarValues[s.objectName()])
|
|
462
|
-
if s.objectName() in self.SPLpar.verticalBarValues:
|
|
463
|
-
if self.SPLpar.verticalBarValues[s.objectName()]!=s.verticalScrollBar().value():
|
|
464
|
-
s.verticalScrollBar().setValue(self.SPLpar.verticalBarValues[s.objectName()])
|
|
465
|
-
|
|
466
|
-
def setupButtons(self,widgets,icons):
|
|
467
|
-
self.buttonBar_layout.removeItem(self.buttonSpacer)
|
|
468
|
-
|
|
469
|
-
mh=self.widgetHorizontalMargin
|
|
470
|
-
mv=self.widgetVerticalMargin
|
|
471
|
-
for w,icon,index in zip(widgets,icons,range(len(widgets))):
|
|
472
|
-
b=RichTextPushButton(self.buttonBar)
|
|
473
|
-
b.lyt.setStretch(0,1)
|
|
474
|
-
b.lyt.setStretch(1,0)
|
|
475
|
-
b.setFixedSize(self.buttonSize[0],self.buttonSize[1])
|
|
476
|
-
b.setStyleSheet(f"""
|
|
477
|
-
RichTextPushButton {{
|
|
478
|
-
border: 1px solid rgba(128, 128, 128, 0.5);
|
|
479
|
-
border-radius: 5px;
|
|
480
|
-
background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 rgba(128, 128, 128, 0), stop:1 rgba(224, 224, 224, 0.25));
|
|
481
|
-
}}
|
|
482
|
-
""")
|
|
483
|
-
b.setCursor(Qt.CursorShape.PointingHandCursor)
|
|
484
|
-
|
|
485
|
-
w:Input_Tab
|
|
486
|
-
if hasattr(w,'ui'):
|
|
487
|
-
if hasattr(w.ui,'name_tab'):
|
|
488
|
-
b.setToolTip(w.ui.name_tab.text().replace(' ',''))
|
|
489
|
-
b.setStatusTip(w.ui.name_tab.text().replace(' ',''))
|
|
490
|
-
if hasattr(w.ui,'scrollArea') and not self.scrollArea.styleSheet():
|
|
491
|
-
self.scrollArea.setStyleSheet(w.ui.scrollArea.styleSheet())
|
|
492
|
-
b.setIcon(QIcon(icons_path+icon+'.png'))
|
|
493
|
-
b.setIconSize(QSize(self.iconSize,self.iconSize))
|
|
494
|
-
|
|
495
|
-
self.buttonBar_layout.addWidget(b)
|
|
496
|
-
b.setVisible(False)
|
|
497
|
-
self.buttons.append(b)
|
|
498
|
-
w.buttonTab=b
|
|
499
|
-
|
|
500
|
-
def defineButtonAction():
|
|
501
|
-
butt=b
|
|
502
|
-
wid=w
|
|
503
|
-
i=index
|
|
504
|
-
return lambda: self.buttonAction(butt,wid,i,self.scrollArea)
|
|
505
|
-
b.clicked.connect(defineButtonAction())
|
|
506
|
-
setattr(w,'buttonAction',defineButtonAction())
|
|
507
|
-
|
|
508
|
-
def defineCloseTabAction():
|
|
509
|
-
butt=b
|
|
510
|
-
return lambda: self.closeTabAction(butt)
|
|
511
|
-
w.ui.button_close_tab.clicked.connect(defineCloseTabAction())
|
|
512
|
-
|
|
513
|
-
#pri.Coding.red(f"{w.ui.name_tab.text()}\t\t width: min={w.minimumWidth()}, max={w.maximumWidth()}\t height: min={w.minimumHeight()}, max={w.maximumHeight()}")
|
|
514
|
-
w.setContentsMargins(mh,mv,mh,mv)
|
|
515
|
-
w.setMinimumWidth(max([self.widgetMinimumWidth,w.minimumWidth()]))
|
|
516
|
-
w.setMaximumWidth(max([self.widgetMaximumWidth,w.maximumWidth()]))
|
|
517
|
-
w.setMinimumHeight(self.widgetMinimumHeight)
|
|
518
|
-
w.setMaximumHeight(self.widgetMaximumHeight)
|
|
519
|
-
|
|
520
|
-
self.buttonBar_layout.addItem(self.buttonSpacer)
|
|
521
|
-
|
|
522
|
-
def buttonAction(self,b:RichTextPushButton,widget:gPaIRS_Tab,index:int,scrollArea:PaIRS_QScrollArea):
|
|
523
|
-
self.openTabAction(b)
|
|
524
|
-
barValue_end=-int(0.5*scrollArea.splitter.handleWidth())
|
|
525
|
-
for i in range(index):
|
|
526
|
-
w=scrollArea.splitter.widget(i)
|
|
527
|
-
if w.isVisible():
|
|
528
|
-
barValue_end+=scrollArea.splitter.splitterSizes[i]+scrollArea.splitter.handleWidth()
|
|
529
|
-
if barValue_end!=self.scrollArea.horizontalScrollBar().value():
|
|
530
|
-
self.startAnimation(barValue_end)
|
|
531
|
-
else:
|
|
532
|
-
self.finishAnimation()
|
|
533
|
-
return
|
|
534
|
-
|
|
535
|
-
def startAnimation(self,v):
|
|
536
|
-
self.FlagAnimationRunning=True
|
|
537
|
-
self.animation.stop()
|
|
538
|
-
self.animation.setStartValue(self.scrollArea.horizontalScrollBar().value())
|
|
539
|
-
self.animation.setEndValue(v)
|
|
540
|
-
self.animation.setDuration(time_ScrollBar)
|
|
541
|
-
self.animation.finished.connect(self.finishAnimation)
|
|
542
|
-
self.animation.start()
|
|
543
|
-
|
|
544
|
-
def finishAnimation(self):
|
|
545
|
-
self.FlagAnimationRunning=False
|
|
546
|
-
self.updateScrollBarValue(self.scrollArea,flagHorizontal=True)
|
|
547
|
-
|
|
548
|
-
def moveTo(self, i):
|
|
549
|
-
self.scrollArea.horizontalScrollBar().setValue(i)
|
|
550
|
-
|
|
551
|
-
def openTabAction(self,b:RichTextPushButton):
|
|
552
|
-
self.SPLpar.FlagVisible[self.buttons.index(b)]=True
|
|
553
|
-
self.nullCallback(f'Open {b.toolTip()} tab')
|
|
554
|
-
#self.adjustTABparInd()
|
|
555
|
-
|
|
556
|
-
def closeTabAction(self,b:RichTextPushButton):
|
|
557
|
-
self.SPLpar.FlagVisible[self.buttons.index(b)]=False
|
|
558
|
-
self.nullCallback(f'Close {b.toolTip()} tab')
|
|
559
|
-
#self.adjustTABparInd()
|
|
560
|
-
|
|
561
|
-
def setSPLlayout(self):
|
|
562
|
-
#self.setUpdatesEnabled(False)
|
|
563
|
-
#if self.SPLpar.sizes!=self.scrollArea.splitter.splitterSizes:
|
|
564
|
-
self.scrollArea.splitter.splitterSizes=[s for s in self.SPLpar.sizes]
|
|
565
|
-
PaIRS_QSplitter.splitterResize(self.scrollArea.splitter,self.SPLpar.FlagVisible)
|
|
566
|
-
#if self.SPLpar_old.isDifferentFrom(self.SPLpar,fields=['FlagVisible']):
|
|
567
|
-
for w,b,f in zip(self.widgets,self.buttons,self.SPLpar.FlagVisible):
|
|
568
|
-
w:QWidget
|
|
569
|
-
w.parent().setVisible(f)
|
|
570
|
-
b:RichTextPushButton
|
|
571
|
-
b.setText('')
|
|
572
|
-
if not f:
|
|
573
|
-
fPixSize=b.font().pixelSize()
|
|
574
|
-
s=f'<sup><span style=" font-size:{fPixSize-2}px"> 🔒</span></sup>'
|
|
575
|
-
b.setText(s)
|
|
576
|
-
|
|
577
|
-
#if self.SPLpar_old.barValue!=self.SPLpar.barValue:
|
|
578
|
-
#self.scrollArea.horizontalScrollBar().setValue(self.SPLpar.barValue)
|
|
579
|
-
self.scrollArea.horizontalScrollBar().setMaximum(self.scrollArea.splitter.width()-self.scrollArea.width())
|
|
580
|
-
self.setScrollBarValues()
|
|
581
|
-
self.setFlagCollapsibleBox()
|
|
582
|
-
|
|
583
|
-
#self.setUpdatesEnabled(True)
|
|
584
|
-
#self.parent().hide()
|
|
585
|
-
#self.hide()
|
|
586
|
-
self.parent().updateGeometry()
|
|
587
|
-
self.updateGeometry()
|
|
588
|
-
#self.show()
|
|
589
|
-
#self.parent().show()
|
|
590
|
-
return
|
|
591
|
-
|
|
592
|
-
def splitterResize(self,FlagVisible=None,FlagReleased=True):
|
|
593
|
-
splitterSizes=PaIRS_QSplitter.splitterResize(self.scrollArea.splitter,FlagVisible,FlagReleased)
|
|
594
|
-
if FlagReleased:
|
|
595
|
-
self.SPLpar.sizes=[s for s in splitterSizes]
|
|
596
|
-
self.finishAnimation()
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
if __name__ == "__main__":
|
|
600
|
-
app = QApplication(sys.argv)
|
|
601
|
-
app.setStyle('Fusion')
|
|
602
|
-
|
|
603
|
-
tabAreaWidget=TabAreaWidget()
|
|
604
|
-
icons=['import_logo','export_logo','process_icon','terminal','vect_field']
|
|
605
|
-
tabs=[Input_Tab,Output_Tab,Process_Tab,Log_Tab,Vis_Tab]
|
|
606
|
-
widgets=[None]*len(tabs)
|
|
607
|
-
for i in range(len(tabs)):
|
|
608
|
-
widgets[i]=tabs[i](tabAreaWidget,False)
|
|
609
|
-
#tabAreaWidget.resize(1050,0)
|
|
610
|
-
tabAreaWidget.setupTabArea(widgets,icons)
|
|
611
|
-
tabAreaWidget.show()
|
|
612
|
-
sys.exit(app.exec())
|
|
8
|
+
|
|
9
|
+
class PaIRS_QSplitter(QSplitter):
|
|
10
|
+
minimumResizeWidth=0
|
|
11
|
+
class PaIRS_ToggleSplitterHandle(QtWidgets.QSplitterHandle):
|
|
12
|
+
minimumHandleDisplacement=200
|
|
13
|
+
def __init__(self, o: Qt.Orientation, parent: QSplitter):
|
|
14
|
+
super().__init__(o, parent)
|
|
15
|
+
self.index=parent.count()-1
|
|
16
|
+
self.limits=[None,None]
|
|
17
|
+
#pri.Coding.yellow(f'Splitter handle #{self.index}')
|
|
18
|
+
self.init_pos=None
|
|
19
|
+
return
|
|
20
|
+
|
|
21
|
+
def mousePressEvent(self, event:QMouseEvent):
|
|
22
|
+
super().mousePressEvent(event)
|
|
23
|
+
|
|
24
|
+
TABpar.FlagSettingPar=True
|
|
25
|
+
pa:PaIRS_QSplitter=self.parent()
|
|
26
|
+
visibleHandles=[]
|
|
27
|
+
widgets=[]
|
|
28
|
+
visibleWidgets=[]
|
|
29
|
+
for i in range(pa.count()):
|
|
30
|
+
handle = pa.handle(i)
|
|
31
|
+
if handle.isVisible():
|
|
32
|
+
visibleHandles.append(handle)
|
|
33
|
+
widget=pa.widget(i)
|
|
34
|
+
widgets.append(widget)
|
|
35
|
+
if widget.isVisible():
|
|
36
|
+
visibleWidgets.append(widget)
|
|
37
|
+
i=visibleHandles.index(self)
|
|
38
|
+
self.index=widgets.index(visibleWidgets[i])
|
|
39
|
+
"""
|
|
40
|
+
width=0
|
|
41
|
+
index=-1
|
|
42
|
+
sizes=pa.splitterSizes
|
|
43
|
+
#sizes=pa.sizes()
|
|
44
|
+
while self.pos().x()>width and index<pa.count()-1:
|
|
45
|
+
index+=1
|
|
46
|
+
w=pa.widget(index)
|
|
47
|
+
if w:
|
|
48
|
+
if w.isVisible():
|
|
49
|
+
width+=sizes[index]+pa.handleWidth()
|
|
50
|
+
self.index=index
|
|
51
|
+
"""
|
|
52
|
+
pri.Coding.magenta(f'pos={self.pos().x()} index={self.index}')
|
|
53
|
+
|
|
54
|
+
w=pa.widget(self.index)
|
|
55
|
+
w.setMinimumWidth(pa.minimumSizes[self.index])
|
|
56
|
+
w.widget.setMinimumWidth(pa.minimumSizes[self.index])
|
|
57
|
+
w.setMaximumWidth(pa.maximumSizes[self.index])
|
|
58
|
+
w.widget.setMaximumWidth(pa.maximumSizes[self.index])
|
|
59
|
+
|
|
60
|
+
pri.Coding.magenta(f'{w.widget.TABname} [{pa.minimumSizes[self.index]},{pa.maximumSizes[self.index]}]')
|
|
61
|
+
dwf=w.maximumWidth()-w.minimumWidth()
|
|
62
|
+
pa.splitterReleased([pa.count()-1],[+dwf],FlagReleased=False)
|
|
63
|
+
|
|
64
|
+
self.init_pos=self.pos().x()
|
|
65
|
+
self.limits=[w.minimumWidth()-w.width(),w.maximumWidth()-w.width()]
|
|
66
|
+
|
|
67
|
+
def mouseReleaseEvent(self, event:QMouseEvent):
|
|
68
|
+
super().mouseReleaseEvent(event)
|
|
69
|
+
|
|
70
|
+
TABpar.FlagSettingPar=False
|
|
71
|
+
if self.init_pos:
|
|
72
|
+
pa:PaIRS_QSplitter=self.parent()
|
|
73
|
+
w=pa.widget(self.index)
|
|
74
|
+
dw=self.pos().x()-self.init_pos
|
|
75
|
+
dwf=pa.maximumSizes[self.index]-w.minimumWidth()
|
|
76
|
+
indexes=[self.index,pa.count()-1]
|
|
77
|
+
deltaWidths=[dw,-dwf]
|
|
78
|
+
pa.splitterReleased(indexes,deltaWidths,FlagReleased=True)
|
|
79
|
+
|
|
80
|
+
w.setFixedWidth(pa.splitterSizes[self.index])
|
|
81
|
+
w.widget.setFixedWidth(pa.splitterSizes[self.index])
|
|
82
|
+
|
|
83
|
+
def mouseMoveEvent(self, event: QMouseEvent):
|
|
84
|
+
pa:PaIRS_QSplitter=self.parent()
|
|
85
|
+
#pa.splitterMoving(event.pos().x(),self.index)
|
|
86
|
+
|
|
87
|
+
pa.setSizes(pa.sizes())
|
|
88
|
+
|
|
89
|
+
pos=event.pos().x()
|
|
90
|
+
if pos and self.limits[0] and self.limits[1]:
|
|
91
|
+
pos=max([self.limits[0],pos])
|
|
92
|
+
pos=min([self.limits[1],pos])
|
|
93
|
+
pos+=self.pos().x()+self.width()
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
bar=pa.scrollArea.horizontalScrollBar()
|
|
97
|
+
val=bar.value()
|
|
98
|
+
wSA=pa.scrollArea.width()
|
|
99
|
+
#pri.Coding.magenta(f'val={val}\t pos={pos}\t wSA={wSA}')
|
|
100
|
+
if pos-val>wSA:
|
|
101
|
+
bar.setValue(pos-wSA)
|
|
102
|
+
elif pos<val:
|
|
103
|
+
bar.setValue(pos)
|
|
104
|
+
return super().mouseMoveEvent(event)
|
|
105
|
+
|
|
106
|
+
def createHandle(self):
|
|
107
|
+
handle =self.PaIRS_ToggleSplitterHandle(self.orientation(), self)
|
|
108
|
+
handle.setCursor(QCursor(Qt.SplitHCursor if self.orientation() == Qt.Horizontal else Qt.SplitVCursor))
|
|
109
|
+
return handle
|
|
110
|
+
|
|
111
|
+
def __init__(self, orientation, parent=None):
|
|
112
|
+
super().__init__(orientation, parent)
|
|
113
|
+
self.setOpaqueResize(False)
|
|
114
|
+
self.FlagInit=False
|
|
115
|
+
self.splitterSizes=[]
|
|
116
|
+
self.minimumSizes=[]
|
|
117
|
+
self.maximumSizes=[]
|
|
118
|
+
self.splitterMaximumSize=0
|
|
119
|
+
self.scrollArea:PaIRS_QScrollArea=None
|
|
120
|
+
|
|
121
|
+
def addWidget(self, widget):
|
|
122
|
+
if not self.FlagInit: i=self.count()
|
|
123
|
+
else: i=self.count()-1
|
|
124
|
+
return self.insertWidget(i,widget)
|
|
125
|
+
|
|
126
|
+
def insertWidget(self, i, widget):
|
|
127
|
+
self.splitterSizes.insert(i,widget.minimumWidth())
|
|
128
|
+
self.minimumSizes.insert(i,widget.minimumWidth())
|
|
129
|
+
self.maximumSizes.insert(i,widget.maximumWidth()+int(self.handleWidth()*0.5))
|
|
130
|
+
self.splitterMaximumSize+=self.minimumSizes[-1]+self.handleWidth()
|
|
131
|
+
widget.setMaximumWidth(widget.minimumWidth())
|
|
132
|
+
return super().insertWidget(i,widget)
|
|
133
|
+
|
|
134
|
+
def replaceWidget(self, i, widget):
|
|
135
|
+
self.splitterMaximumSize-=self.minimumSizes[i]+self.handleWidth()
|
|
136
|
+
self.splitterSizes[i]=widget.minimumWidth()
|
|
137
|
+
self.minimumSizes[i]=widget.minimumWidth()
|
|
138
|
+
self.maximumSizes[i]=widget.maximumWidth()+int(self.handleWidth()*0.5)
|
|
139
|
+
self.splitterMaximumSize+=self.minimumSizes[i]+self.handleWidth()
|
|
140
|
+
widget.setMaximumWidth(widget.minimumWidth())
|
|
141
|
+
return super().replaceWidget(i,widget)
|
|
142
|
+
|
|
143
|
+
def setHandleWidth(self, width: int) -> None:
|
|
144
|
+
self.maximumSizes=[m-int(0.5*self.handleWidth())+int(0.5*width) for m in self.maximumSizes]
|
|
145
|
+
return super().setHandleWidth(width)
|
|
146
|
+
|
|
147
|
+
def splitterReleased(self,indexes,deltaWidths,FlagReleased=True):
|
|
148
|
+
for index,dw in zip(indexes,deltaWidths):
|
|
149
|
+
w=self.widget(index)
|
|
150
|
+
self.splitterSizes[index]=max([min([self.splitterSizes[index]+dw,w.maximumWidth()]),w.minimumWidth()])
|
|
151
|
+
self.splitterResize(FlagReleased=FlagReleased)
|
|
152
|
+
pri.Coding.green(f'i= {indexes}\t dw={deltaWidths}\t Splitter sizes: {self.splitterSizes}')
|
|
153
|
+
|
|
154
|
+
def splitterResize(self,FlagVisible=None,FlagReleased=True):
|
|
155
|
+
width=0
|
|
156
|
+
if FlagReleased: self.splitterSizes[-1]=0
|
|
157
|
+
for i in range(self.count()):
|
|
158
|
+
w=self.widget(i)
|
|
159
|
+
if FlagVisible is not None: flag=FlagVisible[i]
|
|
160
|
+
else: flag=w.isVisible()
|
|
161
|
+
if flag:
|
|
162
|
+
width+=self.splitterSizes[i]+self.handleWidth()
|
|
163
|
+
pa=self.parent().parent()
|
|
164
|
+
if pa.width()>width:
|
|
165
|
+
self.splitterSizes[-1]+=pa.width()-width
|
|
166
|
+
width=pa.width()+self.handleWidth()
|
|
167
|
+
self.setFixedWidth(width)
|
|
168
|
+
self.setSizes(self.splitterSizes)
|
|
169
|
+
if FlagReleased:
|
|
170
|
+
for i in range(self.count()-1):
|
|
171
|
+
w=self.widget(i)
|
|
172
|
+
w.setFixedWidth(self.splitterSizes[i])
|
|
173
|
+
w.widget.setFixedWidth(self.splitterSizes[i])
|
|
174
|
+
return self.splitterSizes
|
|
175
|
+
|
|
176
|
+
def resizeEvent(self,event):
|
|
177
|
+
#self.splitterResize()
|
|
178
|
+
return
|
|
179
|
+
|
|
180
|
+
def setHandleVisibility(self):
|
|
181
|
+
for i in range(self.count()):
|
|
182
|
+
self.handle(i).setVisible(self.widget(i).isVisible())
|
|
183
|
+
|
|
184
|
+
class PaIRS_QScrollArea(QScrollArea):
|
|
185
|
+
def __init__(self,widgets=[],handleWidth=20,margin=0):
|
|
186
|
+
super().__init__()
|
|
187
|
+
self.handleWidth=handleWidth
|
|
188
|
+
self.margin=margin
|
|
189
|
+
|
|
190
|
+
self.setWidgetResizable(True)
|
|
191
|
+
self.container_widget = QWidget()
|
|
192
|
+
self.setWidget(self.container_widget)
|
|
193
|
+
self.main_layout = QVBoxLayout(self.container_widget)
|
|
194
|
+
self.main_layout.setContentsMargins(margin,margin,margin,margin)
|
|
195
|
+
|
|
196
|
+
self.splitter=None
|
|
197
|
+
self.setupSplitter(widgets)
|
|
198
|
+
|
|
199
|
+
def setupSplitter(self,widgets):
|
|
200
|
+
self.frames=[]
|
|
201
|
+
if not widgets:
|
|
202
|
+
return
|
|
203
|
+
if self.splitter:
|
|
204
|
+
self.main_layout.removeWidget(self.splitter)
|
|
205
|
+
self.splitter=splitter=PaIRS_QSplitter(Qt.Horizontal)
|
|
206
|
+
self.splitter.setObjectName('tabArea_splitter')
|
|
207
|
+
self.widgets=widgets
|
|
208
|
+
|
|
209
|
+
dw=0
|
|
210
|
+
# Aggiungi alcuni widget al QSplitter
|
|
211
|
+
for i,w in enumerate(widgets):
|
|
212
|
+
w:gPaIRS_Tab
|
|
213
|
+
w.blockSignals(True)
|
|
214
|
+
frame = QFrame()
|
|
215
|
+
frame_layout = QVBoxLayout(frame)
|
|
216
|
+
frame_layout.setContentsMargins(0,0,0,0)
|
|
217
|
+
frame.setMinimumWidth(w.minimumWidth())
|
|
218
|
+
frame.setMaximumWidth(w.maximumWidth())
|
|
219
|
+
dw+=max([dw,w.maximumWidth()-w.minimumWidth()])
|
|
220
|
+
|
|
221
|
+
objName=f'{w.TABname}_frame'
|
|
222
|
+
frame.setObjectName(objName)
|
|
223
|
+
frame.setStyleSheet(f"""
|
|
224
|
+
QFrame#{objName} {{
|
|
225
|
+
border: 1px solid rgba(128, 128, 128, 0.5);
|
|
226
|
+
border-radius: 15px;
|
|
227
|
+
background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 rgba(128, 128, 128, 0), stop:1 rgba(224, 224, 224, 0.25));
|
|
228
|
+
}}
|
|
229
|
+
QWidget#scrollAreaWidgetContents{{
|
|
230
|
+
background: transparent;
|
|
231
|
+
}}
|
|
232
|
+
""")
|
|
233
|
+
|
|
234
|
+
splitter.addWidget(frame)
|
|
235
|
+
splitter.setCollapsible(i,False)
|
|
236
|
+
#if i in (0,3): frame.hide()
|
|
237
|
+
frame_layout.addWidget(w)
|
|
238
|
+
setattr(frame,'widget',w)
|
|
239
|
+
frame.setVisible(False)
|
|
240
|
+
self.frames.append(frame)
|
|
241
|
+
if hasattr(w,'ui') and hasattr(w.ui,'scrollArea'):
|
|
242
|
+
w.ui.scrollArea.setObjectName('scroll_area_'+w.TABname)
|
|
243
|
+
w.blockSignals(False)
|
|
244
|
+
|
|
245
|
+
frame = QFrame()
|
|
246
|
+
objName=f'empty_frame'
|
|
247
|
+
frame.setMinimumWidth(50)
|
|
248
|
+
frame.setMaximumWidth(dw)
|
|
249
|
+
|
|
250
|
+
frame.setObjectName(objName)
|
|
251
|
+
frame.setStyleSheet(f"""
|
|
252
|
+
QFrame#{objName} {{
|
|
253
|
+
border: none;
|
|
254
|
+
background: transparent;
|
|
255
|
+
}}
|
|
256
|
+
""")
|
|
257
|
+
splitter.addWidget(frame)
|
|
258
|
+
frame.setMaximumWidth(dw)
|
|
259
|
+
setattr(frame,'TABname','Empty frame')
|
|
260
|
+
setattr(frame,'widget',frame)
|
|
261
|
+
self.frames.append(frame)
|
|
262
|
+
|
|
263
|
+
splitter.setHandleWidth(self.handleWidth)
|
|
264
|
+
splitter.scrollArea=self
|
|
265
|
+
self.main_layout.addWidget(self.splitter)
|
|
266
|
+
|
|
267
|
+
def resizeEvent(self, event: QResizeEvent):
|
|
268
|
+
self.update()
|
|
269
|
+
total_height = self.viewport().height()
|
|
270
|
+
scrollbar_height = self.horizontalScrollBar().height() if self.horizontalScrollBar().isVisible() else 0
|
|
271
|
+
available_height = total_height - scrollbar_height
|
|
272
|
+
for f,w in zip(self.frames,self.widgets):
|
|
273
|
+
f:QFrame
|
|
274
|
+
available_height=max([available_height,w.minimumHeight()])
|
|
275
|
+
for f,w in zip(self.frames,self.widgets):
|
|
276
|
+
f:QFrame
|
|
277
|
+
f.setMinimumHeight(available_height)
|
|
278
|
+
self.splitter.setMinimumHeight(available_height)
|
|
279
|
+
self.container_widget.setMinimumHeight(available_height+scrollbar_height)
|
|
280
|
+
|
|
281
|
+
return super().resizeEvent(event)
|
|
282
|
+
|
|
283
|
+
class SPLpar(TABpar):
|
|
284
|
+
sizes_default = []
|
|
285
|
+
FlagVisible_default = []
|
|
286
|
+
horizontalBarValues_default = {}
|
|
287
|
+
verticalBarValues_default = {}
|
|
288
|
+
FlagCollapsibleBoxes_default = {}
|
|
289
|
+
|
|
290
|
+
def __init__(self,Process=ProcessTypes.null,Step=StepTypes.null):
|
|
291
|
+
self.setup(Process,Step)
|
|
292
|
+
super().__init__('SPLpar','TabAreaWidget')
|
|
293
|
+
self.unchecked_fields+=[]
|
|
294
|
+
|
|
295
|
+
def setup(self,Process,Step):
|
|
296
|
+
self.Process=Process
|
|
297
|
+
self.Step=Step
|
|
298
|
+
self.sizes=[s for s in SPLpar.sizes_default]
|
|
299
|
+
self.FlagVisible=[f for f in SPLpar.FlagVisible_default]
|
|
300
|
+
self.horizontalBarValues=copy.deepcopy(SPLpar.horizontalBarValues_default)
|
|
301
|
+
self.verticalBarValues=copy.deepcopy(SPLpar.verticalBarValues_default)
|
|
302
|
+
self.FlagCollapsibleBoxes=copy.deepcopy(SPLpar.FlagCollapsibleBoxes_default)
|
|
303
|
+
|
|
304
|
+
class TabAreaWidget(gPaIRS_Tab):
|
|
305
|
+
margin=10
|
|
306
|
+
|
|
307
|
+
buttonSpacing=10
|
|
308
|
+
buttonSize=[40,30]
|
|
309
|
+
iconSize=20
|
|
310
|
+
|
|
311
|
+
widgetMinimumWidth=550
|
|
312
|
+
widgetMaximumWidth=1100
|
|
313
|
+
widgetMinimumHeight=650
|
|
314
|
+
tabAreaMinimumHeight=750
|
|
315
|
+
widgetMaximumHeight=10000
|
|
316
|
+
widgetHorizontalMargin=10
|
|
317
|
+
widgetVerticalMargin=5
|
|
318
|
+
handleWidth=20
|
|
319
|
+
|
|
320
|
+
def __init__(self, parent: QWidget = None, widgets=[],icons=[]):
|
|
321
|
+
super().__init__(parent,UiClass=None,ParClass=SPLpar)
|
|
322
|
+
if __name__ == "__main__":
|
|
323
|
+
iconW = QIcon()
|
|
324
|
+
iconW.addFile(u""+ icons_path +"logo_PaIRS.png", QSize(), QIcon.Normal, QIcon.Off)
|
|
325
|
+
self.setWindowTitle('Tab area widget')
|
|
326
|
+
self.setWindowIcon(iconW)
|
|
327
|
+
self.main_layout=QVBoxLayout()
|
|
328
|
+
|
|
329
|
+
#------------------------------------- Graphical interface: miscellanea
|
|
330
|
+
self.TABname='TabArea'
|
|
331
|
+
m=self.margin
|
|
332
|
+
self.setMinimumWidth(self.widgetMinimumWidth+m*2+self.handleWidth)
|
|
333
|
+
self.tabAreaHeight=self.buttonSize[1]+self.buttonSpacing+self.tabAreaMinimumHeight+m*4
|
|
334
|
+
#self.setMinimumHeight(self.buttonSize[1]+self.buttonSpacing+self.widgetMinimumHeight+m*4)
|
|
335
|
+
self.main_layout.setContentsMargins(m,m,m,m)
|
|
336
|
+
self.main_layout.setSpacing(self.buttonSpacing)
|
|
337
|
+
self.setLayout(self.main_layout)
|
|
338
|
+
|
|
339
|
+
self.buttonBar=QWidget()
|
|
340
|
+
self.buttonBar_layout=QHBoxLayout()
|
|
341
|
+
self.buttonBar_layout.setContentsMargins(0,0,0,0)
|
|
342
|
+
self.buttonBar_layout.setSpacing(self.buttonSpacing)
|
|
343
|
+
self.buttonBar.setLayout(self.buttonBar_layout)
|
|
344
|
+
self.buttonSpacer=QSpacerItem(self.buttonSize[0],self.buttonSize[1],QSizePolicy.Expanding, QSizePolicy.Minimum)
|
|
345
|
+
self.buttonBar_layout.addSpacerItem(self.buttonSpacer)
|
|
346
|
+
|
|
347
|
+
self.scrollArea = PaIRS_QScrollArea(handleWidth=self.handleWidth)
|
|
348
|
+
self.scrollArea.setObjectName('scroll_area_tabArea')
|
|
349
|
+
|
|
350
|
+
self.main_layout.addWidget(self.buttonBar)
|
|
351
|
+
self.main_layout.addWidget(self.scrollArea)
|
|
352
|
+
|
|
353
|
+
#------------------------------------- Declaration of parameters
|
|
354
|
+
self.SPLpar_base=SPLpar()
|
|
355
|
+
self.SPLpar:SPLpar=self.TABpar
|
|
356
|
+
self.SPLpar_old:SPLpar=self.TABpar_old
|
|
357
|
+
|
|
358
|
+
#------------------------------------- Callbacks
|
|
359
|
+
self.buttons=[]
|
|
360
|
+
self.animation = QVariantAnimation(self.scrollArea)
|
|
361
|
+
self.animation.valueChanged.connect(self.moveTo)
|
|
362
|
+
self.scrollArea.horizontalScrollBar().valueChanged.connect(self.finishAnimation)
|
|
363
|
+
|
|
364
|
+
self.setTABlayout=self.setSPLlayout
|
|
365
|
+
self.FlagAddPrev=False
|
|
366
|
+
self.FlagBridge=False
|
|
367
|
+
self.FlagAnimationRunning=False
|
|
368
|
+
|
|
369
|
+
self.setupWid()
|
|
370
|
+
if __name__ == "__main__":
|
|
371
|
+
self.app=app
|
|
372
|
+
setAppGuiPalette(self)
|
|
373
|
+
|
|
374
|
+
self.FlagDisplayControls=False
|
|
375
|
+
self.setupTabArea(widgets,icons)
|
|
376
|
+
|
|
377
|
+
def null(self):
|
|
378
|
+
return True
|
|
379
|
+
|
|
380
|
+
def setupTabArea(self,widgets,icons):
|
|
381
|
+
self.widgets=widgets
|
|
382
|
+
if not widgets: return
|
|
383
|
+
for b in self.buttons:
|
|
384
|
+
b:RichTextPushButton
|
|
385
|
+
self.buttonBar_layout.removeWidget(b)
|
|
386
|
+
b.setParent(None)
|
|
387
|
+
self.buttons=[]
|
|
388
|
+
self.setupButtons(widgets,icons)
|
|
389
|
+
self.scrollArea.setupSplitter(widgets)
|
|
390
|
+
self.scrollArea.splitter.splitterResize=self.splitterResize
|
|
391
|
+
|
|
392
|
+
self.SPLpar.sizes=[w.width() for w in widgets]+[self.scrollArea.splitter.minimumResizeWidth]
|
|
393
|
+
self.SPLpar.FlagVisible=[True for w in widgets]+[True]
|
|
394
|
+
self.SPLpar.horizontalBarValues={}
|
|
395
|
+
self.SPLpar.verticalBarValues={}
|
|
396
|
+
|
|
397
|
+
self.scrollAreas=self.findChildren(QScrollArea)
|
|
398
|
+
self.collapBoxes=[]
|
|
399
|
+
for w in self.widgets:
|
|
400
|
+
w:gPaIRS_Tab
|
|
401
|
+
self.scrollAreas+=w.findChildren(QScrollArea)
|
|
402
|
+
self.scrollAreas+=w.findChildren(QTextEdit)
|
|
403
|
+
self.scrollAreas+=w.findChildren(QTableWidget)
|
|
404
|
+
self.scrollAreas+=w.findChildren(QTreeWidget)
|
|
405
|
+
self.collapBoxes+=w.findChildren(CollapsibleBox)
|
|
406
|
+
for s in self.scrollAreas:
|
|
407
|
+
s:QScrollArea
|
|
408
|
+
if s.objectName()=='': continue
|
|
409
|
+
self.SPLpar.horizontalBarValues[s.objectName()]=s.horizontalScrollBar().value()
|
|
410
|
+
self.SPLpar.verticalBarValues[s.objectName()]=s.verticalScrollBar().value()
|
|
411
|
+
s.horizontalScrollBar().valueChanged.connect(lambda v, scrllr=s: self.updateScrollBarValue(scrllr,True))
|
|
412
|
+
s.verticalScrollBar().valueChanged.connect(lambda v, scrllr=s: self.updateScrollBarValue(scrllr,False))
|
|
413
|
+
for cB in self.collapBoxes:
|
|
414
|
+
cB:CollapsibleBox
|
|
415
|
+
self.SPLpar.FlagCollapsibleBoxes[cB.objectName()]=cB.toggle_button.isChecked()
|
|
416
|
+
cB.toggle_button.clicked.connect(lambda v, cllpbx=cB: self.updateFlagCollapsibleBox(cllpbx))
|
|
417
|
+
|
|
418
|
+
SPLpar.sizes_default=[w.width() for w in widgets]+[self.scrollArea.splitter.minimumResizeWidth]
|
|
419
|
+
SPLpar.FlagVisible_default=[True for w in widgets]+[True]
|
|
420
|
+
for k in self.SPLpar.horizontalBarValues:
|
|
421
|
+
SPLpar.horizontalBarValues_default[k]=0
|
|
422
|
+
for k in self.SPLpar.verticalBarValues:
|
|
423
|
+
SPLpar.verticalBarValues_default[k]=0
|
|
424
|
+
for k in self.SPLpar.FlagCollapsibleBoxes:
|
|
425
|
+
SPLpar.FlagCollapsibleBoxes_default[k]=True
|
|
426
|
+
#self.nullCallback()
|
|
427
|
+
#self.adjustTABparInd()
|
|
428
|
+
|
|
429
|
+
def updateFlagCollapsibleBox(self,collapBox:CollapsibleBox):
|
|
430
|
+
if self.FlagSettingPar: return
|
|
431
|
+
self.SPLpar.FlagCollapsibleBoxes[collapBox.objectName()]=collapBox.toggle_button.isChecked()
|
|
432
|
+
TABpar_ind:SPLpar=self.TABpar_at(self.TABpar.ind)
|
|
433
|
+
if TABpar_ind: TABpar_ind.FlagCollapsibleBoxes[collapBox.objectName()]=collapBox.toggle_button.isChecked()
|
|
434
|
+
|
|
435
|
+
def setFlagCollapsibleBox(self):
|
|
436
|
+
for cB in self.collapBoxes:
|
|
437
|
+
cB:CollapsibleBox
|
|
438
|
+
if cB.objectName() in self.SPLpar.FlagCollapsibleBoxes:
|
|
439
|
+
if self.SPLpar.FlagCollapsibleBoxes[cB.objectName()]!=cB.toggle_button.isChecked():
|
|
440
|
+
cB.toggle_button.setChecked(self.SPLpar.FlagCollapsibleBoxes[cB.objectName()])
|
|
441
|
+
cB.on_click()
|
|
442
|
+
|
|
443
|
+
def updateScrollBarValue(self,scrollArea:QScrollArea=None,flagHorizontal:bool=True):
|
|
444
|
+
if self.FlagAnimationRunning or self.FlagSettingPar: return
|
|
445
|
+
TABpar_ind:SPLpar=self.TABpar_at(self.TABpar.ind)
|
|
446
|
+
|
|
447
|
+
if flagHorizontal:
|
|
448
|
+
pri.Coding.magenta(f'{scrollArea.objectName()} horizontal ScrollBar value: {scrollArea.horizontalScrollBar().value()}')
|
|
449
|
+
self.SPLpar.horizontalBarValues[scrollArea.objectName()]=scrollArea.horizontalScrollBar().value()
|
|
450
|
+
if TABpar_ind: TABpar_ind.horizontalBarValues[scrollArea.objectName()]=scrollArea.horizontalScrollBar().value()
|
|
451
|
+
else:
|
|
452
|
+
pri.Coding.magenta(f'{scrollArea.objectName()} vertical ScrollBar value: {scrollArea.verticalScrollBar().value()}')
|
|
453
|
+
self.SPLpar.verticalBarValues[scrollArea.objectName()]=scrollArea.verticalScrollBar().value()
|
|
454
|
+
if TABpar_ind: TABpar_ind.verticalBarValues[scrollArea.objectName()]=scrollArea.verticalScrollBar().value()
|
|
455
|
+
|
|
456
|
+
def setScrollBarValues(self):
|
|
457
|
+
for s in self.scrollAreas:
|
|
458
|
+
s:QScrollArea
|
|
459
|
+
if s.objectName() in self.SPLpar.horizontalBarValues:
|
|
460
|
+
if self.SPLpar.horizontalBarValues[s.objectName()]!=s.horizontalScrollBar().value():
|
|
461
|
+
s.horizontalScrollBar().setValue(self.SPLpar.horizontalBarValues[s.objectName()])
|
|
462
|
+
if s.objectName() in self.SPLpar.verticalBarValues:
|
|
463
|
+
if self.SPLpar.verticalBarValues[s.objectName()]!=s.verticalScrollBar().value():
|
|
464
|
+
s.verticalScrollBar().setValue(self.SPLpar.verticalBarValues[s.objectName()])
|
|
465
|
+
|
|
466
|
+
def setupButtons(self,widgets,icons):
|
|
467
|
+
self.buttonBar_layout.removeItem(self.buttonSpacer)
|
|
468
|
+
|
|
469
|
+
mh=self.widgetHorizontalMargin
|
|
470
|
+
mv=self.widgetVerticalMargin
|
|
471
|
+
for w,icon,index in zip(widgets,icons,range(len(widgets))):
|
|
472
|
+
b=RichTextPushButton(self.buttonBar)
|
|
473
|
+
b.lyt.setStretch(0,1)
|
|
474
|
+
b.lyt.setStretch(1,0)
|
|
475
|
+
b.setFixedSize(self.buttonSize[0],self.buttonSize[1])
|
|
476
|
+
b.setStyleSheet(f"""
|
|
477
|
+
RichTextPushButton {{
|
|
478
|
+
border: 1px solid rgba(128, 128, 128, 0.5);
|
|
479
|
+
border-radius: 5px;
|
|
480
|
+
background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 rgba(128, 128, 128, 0), stop:1 rgba(224, 224, 224, 0.25));
|
|
481
|
+
}}
|
|
482
|
+
""")
|
|
483
|
+
b.setCursor(Qt.CursorShape.PointingHandCursor)
|
|
484
|
+
|
|
485
|
+
w:Input_Tab
|
|
486
|
+
if hasattr(w,'ui'):
|
|
487
|
+
if hasattr(w.ui,'name_tab'):
|
|
488
|
+
b.setToolTip(w.ui.name_tab.text().replace(' ',''))
|
|
489
|
+
b.setStatusTip(w.ui.name_tab.text().replace(' ',''))
|
|
490
|
+
if hasattr(w.ui,'scrollArea') and not self.scrollArea.styleSheet():
|
|
491
|
+
self.scrollArea.setStyleSheet(w.ui.scrollArea.styleSheet())
|
|
492
|
+
b.setIcon(QIcon(icons_path+icon+'.png'))
|
|
493
|
+
b.setIconSize(QSize(self.iconSize,self.iconSize))
|
|
494
|
+
|
|
495
|
+
self.buttonBar_layout.addWidget(b)
|
|
496
|
+
b.setVisible(False)
|
|
497
|
+
self.buttons.append(b)
|
|
498
|
+
w.buttonTab=b
|
|
499
|
+
|
|
500
|
+
def defineButtonAction():
|
|
501
|
+
butt=b
|
|
502
|
+
wid=w
|
|
503
|
+
i=index
|
|
504
|
+
return lambda: self.buttonAction(butt,wid,i,self.scrollArea)
|
|
505
|
+
b.clicked.connect(defineButtonAction())
|
|
506
|
+
setattr(w,'buttonAction',defineButtonAction())
|
|
507
|
+
|
|
508
|
+
def defineCloseTabAction():
|
|
509
|
+
butt=b
|
|
510
|
+
return lambda: self.closeTabAction(butt)
|
|
511
|
+
w.ui.button_close_tab.clicked.connect(defineCloseTabAction())
|
|
512
|
+
|
|
513
|
+
#pri.Coding.red(f"{w.ui.name_tab.text()}\t\t width: min={w.minimumWidth()}, max={w.maximumWidth()}\t height: min={w.minimumHeight()}, max={w.maximumHeight()}")
|
|
514
|
+
w.setContentsMargins(mh,mv,mh,mv)
|
|
515
|
+
w.setMinimumWidth(max([self.widgetMinimumWidth,w.minimumWidth()]))
|
|
516
|
+
w.setMaximumWidth(max([self.widgetMaximumWidth,w.maximumWidth()]))
|
|
517
|
+
w.setMinimumHeight(self.widgetMinimumHeight)
|
|
518
|
+
w.setMaximumHeight(self.widgetMaximumHeight)
|
|
519
|
+
|
|
520
|
+
self.buttonBar_layout.addItem(self.buttonSpacer)
|
|
521
|
+
|
|
522
|
+
def buttonAction(self,b:RichTextPushButton,widget:gPaIRS_Tab,index:int,scrollArea:PaIRS_QScrollArea):
|
|
523
|
+
self.openTabAction(b)
|
|
524
|
+
barValue_end=-int(0.5*scrollArea.splitter.handleWidth())
|
|
525
|
+
for i in range(index):
|
|
526
|
+
w=scrollArea.splitter.widget(i)
|
|
527
|
+
if w.isVisible():
|
|
528
|
+
barValue_end+=scrollArea.splitter.splitterSizes[i]+scrollArea.splitter.handleWidth()
|
|
529
|
+
if barValue_end!=self.scrollArea.horizontalScrollBar().value():
|
|
530
|
+
self.startAnimation(barValue_end)
|
|
531
|
+
else:
|
|
532
|
+
self.finishAnimation()
|
|
533
|
+
return
|
|
534
|
+
|
|
535
|
+
def startAnimation(self,v):
|
|
536
|
+
self.FlagAnimationRunning=True
|
|
537
|
+
self.animation.stop()
|
|
538
|
+
self.animation.setStartValue(self.scrollArea.horizontalScrollBar().value())
|
|
539
|
+
self.animation.setEndValue(v)
|
|
540
|
+
self.animation.setDuration(time_ScrollBar)
|
|
541
|
+
self.animation.finished.connect(self.finishAnimation)
|
|
542
|
+
self.animation.start()
|
|
543
|
+
|
|
544
|
+
def finishAnimation(self):
|
|
545
|
+
self.FlagAnimationRunning=False
|
|
546
|
+
self.updateScrollBarValue(self.scrollArea,flagHorizontal=True)
|
|
547
|
+
|
|
548
|
+
def moveTo(self, i):
|
|
549
|
+
self.scrollArea.horizontalScrollBar().setValue(i)
|
|
550
|
+
|
|
551
|
+
def openTabAction(self,b:RichTextPushButton):
|
|
552
|
+
self.SPLpar.FlagVisible[self.buttons.index(b)]=True
|
|
553
|
+
self.nullCallback(f'Open {b.toolTip()} tab')
|
|
554
|
+
#self.adjustTABparInd()
|
|
555
|
+
|
|
556
|
+
def closeTabAction(self,b:RichTextPushButton):
|
|
557
|
+
self.SPLpar.FlagVisible[self.buttons.index(b)]=False
|
|
558
|
+
self.nullCallback(f'Close {b.toolTip()} tab')
|
|
559
|
+
#self.adjustTABparInd()
|
|
560
|
+
|
|
561
|
+
def setSPLlayout(self):
|
|
562
|
+
#self.setUpdatesEnabled(False)
|
|
563
|
+
#if self.SPLpar.sizes!=self.scrollArea.splitter.splitterSizes:
|
|
564
|
+
self.scrollArea.splitter.splitterSizes=[s for s in self.SPLpar.sizes]
|
|
565
|
+
PaIRS_QSplitter.splitterResize(self.scrollArea.splitter,self.SPLpar.FlagVisible)
|
|
566
|
+
#if self.SPLpar_old.isDifferentFrom(self.SPLpar,fields=['FlagVisible']):
|
|
567
|
+
for w,b,f in zip(self.widgets,self.buttons,self.SPLpar.FlagVisible):
|
|
568
|
+
w:QWidget
|
|
569
|
+
w.parent().setVisible(f)
|
|
570
|
+
b:RichTextPushButton
|
|
571
|
+
b.setText('')
|
|
572
|
+
if not f:
|
|
573
|
+
fPixSize=b.font().pixelSize()
|
|
574
|
+
s=f'<sup><span style=" font-size:{fPixSize-2}px"> 🔒</span></sup>'
|
|
575
|
+
b.setText(s)
|
|
576
|
+
|
|
577
|
+
#if self.SPLpar_old.barValue!=self.SPLpar.barValue:
|
|
578
|
+
#self.scrollArea.horizontalScrollBar().setValue(self.SPLpar.barValue)
|
|
579
|
+
self.scrollArea.horizontalScrollBar().setMaximum(self.scrollArea.splitter.width()-self.scrollArea.width())
|
|
580
|
+
self.setScrollBarValues()
|
|
581
|
+
self.setFlagCollapsibleBox()
|
|
582
|
+
|
|
583
|
+
#self.setUpdatesEnabled(True)
|
|
584
|
+
#self.parent().hide()
|
|
585
|
+
#self.hide()
|
|
586
|
+
self.parent().updateGeometry()
|
|
587
|
+
self.updateGeometry()
|
|
588
|
+
#self.show()
|
|
589
|
+
#self.parent().show()
|
|
590
|
+
return
|
|
591
|
+
|
|
592
|
+
def splitterResize(self,FlagVisible=None,FlagReleased=True):
|
|
593
|
+
splitterSizes=PaIRS_QSplitter.splitterResize(self.scrollArea.splitter,FlagVisible,FlagReleased)
|
|
594
|
+
if FlagReleased:
|
|
595
|
+
self.SPLpar.sizes=[s for s in splitterSizes]
|
|
596
|
+
self.finishAnimation()
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
if __name__ == "__main__":
|
|
600
|
+
app = QApplication(sys.argv)
|
|
601
|
+
app.setStyle('Fusion')
|
|
602
|
+
|
|
603
|
+
tabAreaWidget=TabAreaWidget()
|
|
604
|
+
icons=['import_logo','export_logo','process_icon','terminal','vect_field']
|
|
605
|
+
tabs=[Input_Tab,Output_Tab,Process_Tab,Log_Tab,Vis_Tab]
|
|
606
|
+
widgets=[None]*len(tabs)
|
|
607
|
+
for i in range(len(tabs)):
|
|
608
|
+
widgets[i]=tabs[i](tabAreaWidget,False)
|
|
609
|
+
#tabAreaWidget.resize(1050,0)
|
|
610
|
+
tabAreaWidget.setupTabArea(widgets,icons)
|
|
611
|
+
tabAreaWidget.show()
|
|
612
|
+
sys.exit(app.exec())
|