PaIRS-UniNa 0.2.7__cp311-cp311-win_amd64.whl → 0.2.11__cp311-cp311-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/Calibration_Tab.py +40 -24
- PaIRS_UniNa/Changes.txt +50 -0
- PaIRS_UniNa/Explorer.py +257 -77
- PaIRS_UniNa/FolderLoop.py +196 -6
- PaIRS_UniNa/Input_Tab.py +160 -53
- PaIRS_UniNa/Input_Tab_CalVi.py +11 -12
- PaIRS_UniNa/Input_Tab_tools.py +30 -28
- PaIRS_UniNa/Output_Tab.py +1 -3
- PaIRS_UniNa/PaIRS_pypacks.py +171 -67
- PaIRS_UniNa/Process_Tab.py +19 -15
- PaIRS_UniNa/Process_Tab_Disp.py +8 -1
- PaIRS_UniNa/SPIVCalHelp.py +155 -0
- PaIRS_UniNa/Saving_tools.py +3 -0
- PaIRS_UniNa/TabTools.py +201 -9
- PaIRS_UniNa/Vis_Tab.py +221 -65
- PaIRS_UniNa/Vis_Tab_CalVi.py +139 -12
- PaIRS_UniNa/Whatsnew.py +4 -3
- PaIRS_UniNa/_PaIRS_PIV.pyd +0 -0
- PaIRS_UniNa/__init__.py +3 -3
- PaIRS_UniNa/addwidgets_ps.py +773 -97
- PaIRS_UniNa/calibView.py +5 -2
- PaIRS_UniNa/gPaIRS.py +307 -48
- PaIRS_UniNa/icons/closeAllFloat.png +0 -0
- PaIRS_UniNa/icons/defaultWinSize.png +0 -0
- PaIRS_UniNa/icons/dockVis.png +0 -0
- PaIRS_UniNa/icons/dockVis_disable.png +0 -0
- PaIRS_UniNa/icons/floatingVisSize.png +0 -0
- PaIRS_UniNa/icons/folder_loop_cleanup.png +0 -0
- PaIRS_UniNa/icons/folder_loop_cleanup_off.png +0 -0
- PaIRS_UniNa/icons/fullWinsize.png +0 -0
- PaIRS_UniNa/icons/icon_PaIRS.ico +0 -0
- PaIRS_UniNa/icons/information.png +0 -0
- PaIRS_UniNa/icons/information2.png +0 -0
- PaIRS_UniNa/icons/scan_path_loop.png +0 -0
- PaIRS_UniNa/icons/scan_path_loop_off.png +0 -0
- PaIRS_UniNa/icons/smallWinSize.png +0 -0
- PaIRS_UniNa/icons/spiv_setup_no.png +0 -0
- PaIRS_UniNa/icons/spiv_setup_ok.png +0 -0
- PaIRS_UniNa/icons/undockVis.png +0 -0
- PaIRS_UniNa/procTools.py +46 -1
- PaIRS_UniNa/rqrdpckgs.txt +7 -7
- PaIRS_UniNa/tabSplitter.py +6 -1
- PaIRS_UniNa/ui_Calibration_Tab.py +92 -59
- PaIRS_UniNa/ui_gPairs.py +92 -50
- PaIRS_UniNa/ui_infoPaIRS.py +8 -8
- PaIRS_UniNa/whatsnew.txt +2 -3
- {pairs_unina-0.2.7.dist-info → pairs_unina-0.2.11.dist-info}/METADATA +6 -8
- {pairs_unina-0.2.7.dist-info → pairs_unina-0.2.11.dist-info}/RECORD +50 -33
- {pairs_unina-0.2.7.dist-info → pairs_unina-0.2.11.dist-info}/WHEEL +1 -1
- {pairs_unina-0.2.7.dist-info → pairs_unina-0.2.11.dist-info}/top_level.txt +0 -0
PaIRS_UniNa/addwidgets_ps.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import types
|
|
1
3
|
from .PaIRS_pypacks import *
|
|
2
4
|
#from ui_Tree_Tab import Ui_TreeTab
|
|
3
5
|
|
|
@@ -9,9 +11,10 @@ InitCheck=True #False=Collap closed, True=opened
|
|
|
9
11
|
font_italic=True
|
|
10
12
|
font_weight=QFont.DemiBold
|
|
11
13
|
backgroundcolor_none=" background-color: none;"
|
|
12
|
-
backgroundcolor_changing=" background-color:
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
backgroundcolor_changing=f" background-color: {PaIRS_pink};"
|
|
15
|
+
backgroundcolor_hover=f" background-color: {PaIRS_ghostblue};"
|
|
16
|
+
border_hover = " " #"border: 1px solid gray; "
|
|
17
|
+
color_changing=f"color: {PaIRS_darkblue}; "+backgroundcolor_changing
|
|
15
18
|
|
|
16
19
|
#********************************************* Operating Widgets
|
|
17
20
|
def setSS(b,style):
|
|
@@ -53,6 +56,9 @@ class MyQLineEdit(QtWidgets.QLineEdit):
|
|
|
53
56
|
def setup(self):
|
|
54
57
|
if not self.initFlag:
|
|
55
58
|
self.initFlag=True
|
|
59
|
+
self.FlagFocusIn=False
|
|
60
|
+
self.oldFont=None
|
|
61
|
+
self.oldStyle=None
|
|
56
62
|
font_changing = QtGui.QFont(self.font())
|
|
57
63
|
font_changing.setItalic(font_italic)
|
|
58
64
|
font_changing.setWeight(font_weight)
|
|
@@ -63,21 +69,17 @@ class MyQLineEdit(QtWidgets.QLineEdit):
|
|
|
63
69
|
if hasattr(b,'setStyleSheet'):
|
|
64
70
|
if hasStyleFlag:
|
|
65
71
|
if b.styleFlag: continue
|
|
66
|
-
b.flagS=True
|
|
67
72
|
b.initialStyle=b.styleSheet()+" "+backgroundcolor_none
|
|
68
73
|
b.setEnabled(False)
|
|
69
74
|
b.disabledStyle=b.styleSheet()
|
|
70
75
|
b.setEnabled(True)
|
|
71
|
-
b.setStyleSheet(setSS(b,b.initialStyle))
|
|
72
|
-
else:
|
|
73
|
-
b.flagS=False
|
|
76
|
+
b.setStyleSheet(setSS(b,b.initialStyle)+"\n"+gPaIRS_QMenu_style)
|
|
74
77
|
if hasattr(b,'setFont'):
|
|
75
|
-
b.flagF=True
|
|
76
78
|
b.initialFont=b.font()
|
|
77
79
|
b.font_changing=font_changing
|
|
78
|
-
else:
|
|
79
|
-
b.flagF=False
|
|
80
80
|
if hasStyleFlag: b.styleFlag=True
|
|
81
|
+
self.CElabs=[w for w in self.bros if isinstance(w, ClickableEditLabel)]
|
|
82
|
+
self.CElabs_styles=[w.styleSheet() for w in self.CElabs]
|
|
81
83
|
|
|
82
84
|
def setup2(self):
|
|
83
85
|
if not self.initFlag2:
|
|
@@ -99,57 +101,106 @@ class MyQLineEdit(QtWidgets.QLineEdit):
|
|
|
99
101
|
self.setCompleterList()
|
|
100
102
|
|
|
101
103
|
def enterEvent(self, event):
|
|
102
|
-
|
|
103
|
-
|
|
104
|
+
if not self.hasFocus() and self.isEnabled():
|
|
105
|
+
self.oldFont=self.font()
|
|
106
|
+
self.oldStyle=self.styleSheet()
|
|
104
107
|
self.setFont(self.font_changing)
|
|
105
|
-
|
|
108
|
+
self.setStyleSheet(setSS(self,self.initialStyle+" "+backgroundcolor_hover)+"\n"+gPaIRS_QMenu_style)
|
|
109
|
+
for k,w in enumerate(self.CElabs):
|
|
110
|
+
self.CElabs_styles[k]=w.styleSheet()
|
|
111
|
+
w.setStyleSheet(w.styleSheet()+" "+f"""
|
|
112
|
+
ClickableEditLabel {{
|
|
113
|
+
{backgroundcolor_hover};
|
|
114
|
+
}}
|
|
115
|
+
""")
|
|
116
|
+
w.repaint()
|
|
117
|
+
super().enterEvent(event)
|
|
118
|
+
|
|
106
119
|
def leaveEvent(self, event):
|
|
120
|
+
if not self.hasFocus() and self.oldFont is not None:
|
|
121
|
+
self.setFont(self.oldFont)
|
|
122
|
+
self.setStyleSheet(self.oldStyle)
|
|
123
|
+
for k,w in enumerate(self.CElabs):
|
|
124
|
+
w.setStyleSheet(self.CElabs_styles[k])
|
|
125
|
+
w.repaint()
|
|
126
|
+
self.oldFont=None
|
|
127
|
+
self.oldStyle=None
|
|
107
128
|
super().leaveEvent(event)
|
|
108
|
-
if self.font()==self.font_changing and not self.hasFocus():
|
|
109
|
-
self.setFont(self.initialFont)
|
|
110
129
|
|
|
111
130
|
def focusInEvent(self, event):
|
|
112
131
|
super().focusInEvent(event)
|
|
113
132
|
for f in self.addfuncin:
|
|
114
133
|
self.addfuncin[f]()
|
|
115
134
|
self.focusInFun()
|
|
116
|
-
|
|
135
|
+
|
|
117
136
|
def setFocus(self):
|
|
118
137
|
super().setFocus()
|
|
119
138
|
self.focusInFun()
|
|
120
139
|
|
|
121
140
|
def focusInFun(self):
|
|
122
|
-
self.
|
|
123
|
-
|
|
141
|
+
self.setStyleFont(color_changing,self.font_changing)
|
|
142
|
+
|
|
143
|
+
def setStyleFont(self,color_changing,font):
|
|
124
144
|
for b in self.bros:
|
|
125
|
-
if (
|
|
126
|
-
|
|
127
|
-
|
|
145
|
+
if hasattr(b,'setInitalStyle') and hasattr(b,'FlagFocusIn') and b.FlagFocusIn:
|
|
146
|
+
b.setInitalStyle()
|
|
147
|
+
break
|
|
148
|
+
if not self.FlagFocusIn:
|
|
149
|
+
self.FlagFocusIn=True
|
|
150
|
+
self.setFont(font)
|
|
151
|
+
for b in self.bros:
|
|
152
|
+
if hasattr(b,'initialStyle'):
|
|
153
|
+
b.setStyleSheet(setSS(b,b.initialStyle+" "+color_changing)+"\n"+gPaIRS_QMenu_style)
|
|
154
|
+
|
|
128
155
|
def focusOutEvent(self, event):
|
|
129
156
|
super().focusOutEvent(event) #to preserve classical behaviour before adding the below
|
|
130
157
|
for f in self.addfuncout:
|
|
131
158
|
self.addfuncout[f]()
|
|
132
|
-
self.
|
|
159
|
+
self.setInitalStyle()
|
|
133
160
|
|
|
134
161
|
def clearFocus(self):
|
|
135
162
|
super().clearFocus()
|
|
136
|
-
self.
|
|
163
|
+
self.setInitalStyle()
|
|
137
164
|
|
|
138
|
-
def
|
|
139
|
-
|
|
140
|
-
|
|
165
|
+
def setInitalStyle(self):
|
|
166
|
+
if self.FlagFocusIn:
|
|
167
|
+
self.FlagFocusIn=False
|
|
168
|
+
for b in self.bros:
|
|
141
169
|
if hasattr(b,'default_stylesheet'):
|
|
142
170
|
b.setStyleSheet(b.default_stylesheet)
|
|
143
|
-
|
|
144
|
-
b.setStyleSheet(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
171
|
+
elif hasattr(b,'initialStyle'):
|
|
172
|
+
b.setStyleSheet(b.initialStyle)
|
|
173
|
+
if hasattr(b,'initialFont'):
|
|
174
|
+
b.setFont(b.initialFont)
|
|
175
|
+
for k,w in enumerate(self.CElabs):
|
|
176
|
+
self.CElabs_styles[k]=w.default_stylesheet
|
|
177
|
+
w.setStyleSheet(self.CElabs_styles[k])
|
|
178
|
+
w.repaint()
|
|
179
|
+
self.oldFont=None
|
|
180
|
+
self.oldStyle=None
|
|
181
|
+
#self.addlab.clear()
|
|
148
182
|
|
|
149
183
|
def showCompleter(self):
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
184
|
+
comp=self.completer()
|
|
185
|
+
if comp:
|
|
186
|
+
view=comp.popup()
|
|
187
|
+
# ---- focus item matching line edit text ----
|
|
188
|
+
text = (self.text() or "").strip()
|
|
189
|
+
if text:
|
|
190
|
+
model = comp.completionModel() or comp.model()
|
|
191
|
+
col = comp.completionColumn()
|
|
192
|
+
for r in range(model.rowCount()):
|
|
193
|
+
idx = model.index(r, col)
|
|
194
|
+
if not idx.isValid():
|
|
195
|
+
continue
|
|
196
|
+
if (idx.data() or "") == text:
|
|
197
|
+
comp.setCurrentRow(r)
|
|
198
|
+
view.setCurrentIndex(idx)
|
|
199
|
+
view.scrollTo(idx, QAbstractItemView.PositionAtCenter)
|
|
200
|
+
break
|
|
201
|
+
view.setStyleSheet(gPaIRS_Completer_style)
|
|
202
|
+
comp.complete()
|
|
203
|
+
|
|
153
204
|
class MyQLineEditNumber(MyQLineEdit):
|
|
154
205
|
def __init__(self,parent):
|
|
155
206
|
super().__init__(parent)
|
|
@@ -185,11 +236,14 @@ class MyQSpin(QtWidgets.QSpinBox):
|
|
|
185
236
|
self.addfuncreturn={}
|
|
186
237
|
|
|
187
238
|
self.setAccelerated(True)
|
|
188
|
-
self.setGroupSeparatorShown(True)
|
|
239
|
+
self.setGroupSeparatorShown(True)
|
|
189
240
|
|
|
190
241
|
def setup(self):
|
|
191
242
|
if not self.initFlag:
|
|
192
243
|
self.initFlag=True
|
|
244
|
+
self.FlagFocusIn=False
|
|
245
|
+
self.oldFont=None
|
|
246
|
+
self.oldStyle=None
|
|
193
247
|
font_changing = QtGui.QFont(self.font())
|
|
194
248
|
font_changing.setItalic(font_italic)
|
|
195
249
|
font_changing.setWeight(font_weight)
|
|
@@ -200,15 +254,14 @@ class MyQSpin(QtWidgets.QSpinBox):
|
|
|
200
254
|
b.initialFont=b.font()
|
|
201
255
|
b.font_changing=font_changing
|
|
202
256
|
b.styleFlag=True
|
|
203
|
-
self.spinFontObj=[]
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
257
|
+
#self.spinFontObj = self.findChildren(QtWidgets.QLineEdit)[0]
|
|
258
|
+
#self.spinFontObj.initialStyle=self.spinFontObj.styleSheet()+" "+backgroundcolor_none
|
|
259
|
+
#self.spinFontObj.font_changing=font_changing
|
|
260
|
+
|
|
208
261
|
def setFocus(self):
|
|
209
262
|
super().setFocus()
|
|
210
263
|
self.focusInFun()
|
|
211
|
-
|
|
264
|
+
|
|
212
265
|
def focusInEvent(self, event):
|
|
213
266
|
super().focusInEvent(event) #to preserve classical behaviour before adding the below
|
|
214
267
|
for f in self.addfuncin:
|
|
@@ -216,23 +269,51 @@ class MyQSpin(QtWidgets.QSpinBox):
|
|
|
216
269
|
self.focusInFun()
|
|
217
270
|
|
|
218
271
|
def focusInFun(self):
|
|
219
|
-
if not self.
|
|
272
|
+
if not self.FlagFocusIn:
|
|
273
|
+
self.FlagFocusIn=True
|
|
274
|
+
#self.spinFontObj.setStyleSheet(self.spinFontObj.initialStyle+" "+color_changing)
|
|
220
275
|
for b in self.bros:
|
|
221
|
-
b.setStyleSheet(b.initialStyle+" "+color_changing)
|
|
222
|
-
b.setFont(b.font_changing)
|
|
223
|
-
for b in self.spinFontObj:
|
|
276
|
+
b.setStyleSheet(setSS(b,b.initialStyle+" "+color_changing)+"\n"+gPaIRS_QMenu_style)
|
|
224
277
|
b.setFont(self.font_changing)
|
|
225
278
|
|
|
279
|
+
def clearFocus(self):
|
|
280
|
+
super().clearFocus()
|
|
281
|
+
self.setInitalStyle()
|
|
282
|
+
|
|
226
283
|
def focusOutEvent(self, event):
|
|
227
284
|
super().focusOutEvent(event) #to preserve classical behaviour before adding the below
|
|
228
285
|
for f in self.addfuncout:
|
|
229
286
|
self.addfuncout[f]()
|
|
230
|
-
|
|
287
|
+
self.setInitalStyle()
|
|
288
|
+
|
|
289
|
+
def setInitalStyle(self):
|
|
290
|
+
if self.FlagFocusIn:
|
|
291
|
+
self.FlagFocusIn=False
|
|
292
|
+
#self.spinFontObj.setStyleSheet(self.spinFontObj.initialStyle)
|
|
231
293
|
for b in self.bros:
|
|
232
|
-
b.setStyleSheet(b.initialStyle)
|
|
233
|
-
b.setFont(
|
|
234
|
-
|
|
235
|
-
|
|
294
|
+
b.setStyleSheet(setSS(b,b.initialStyle)+"\n"+gPaIRS_QMenu_style)
|
|
295
|
+
b.setFont(self.initialFont)
|
|
296
|
+
self.findChildren(QtWidgets.QLineEdit)[0].setFont(self.initialFont)
|
|
297
|
+
self.oldFont=None
|
|
298
|
+
self.oldStyle=None
|
|
299
|
+
|
|
300
|
+
def enterEvent(self, event):
|
|
301
|
+
super().enterEvent(event)
|
|
302
|
+
if not self.hasFocus() and self.isEnabled():
|
|
303
|
+
self.oldFont=self.font()
|
|
304
|
+
self.setFont(self.font_changing)
|
|
305
|
+
b=self #b=self.spinFontObj
|
|
306
|
+
self.oldStyle=b.styleSheet()
|
|
307
|
+
b.setStyleSheet(setSS(b,b.initialStyle+" "+backgroundcolor_hover+" "+border_hover)+"\n"+gPaIRS_QMenu_style)
|
|
308
|
+
|
|
309
|
+
def leaveEvent(self, event):
|
|
310
|
+
super().leaveEvent(event)
|
|
311
|
+
if not self.hasFocus() and self.oldFont is not None:
|
|
312
|
+
self.setFont(self.oldFont)
|
|
313
|
+
b=self #b=self.spinFontObj
|
|
314
|
+
b.setStyleSheet(self.oldStyle)
|
|
315
|
+
self.oldFont=None
|
|
316
|
+
self.oldStyle=None
|
|
236
317
|
|
|
237
318
|
def keyPressEvent(self, event):
|
|
238
319
|
super().keyPressEvent(event)
|
|
@@ -284,6 +365,9 @@ class MyQDoubleSpin(QtWidgets.QDoubleSpinBox):
|
|
|
284
365
|
def setup(self):
|
|
285
366
|
if not self.initFlag:
|
|
286
367
|
self.initFlag=True
|
|
368
|
+
self.FlagFocusIn=False
|
|
369
|
+
self.oldFont=None
|
|
370
|
+
self.oldStyle=None
|
|
287
371
|
font_changing = QtGui.QFont(self.font())
|
|
288
372
|
font_changing.setItalic(font_italic)
|
|
289
373
|
font_changing.setWeight(font_weight)
|
|
@@ -294,33 +378,67 @@ class MyQDoubleSpin(QtWidgets.QDoubleSpinBox):
|
|
|
294
378
|
b.initialFont=b.font()
|
|
295
379
|
b.font_changing=font_changing
|
|
296
380
|
b.styleFlag=True
|
|
297
|
-
self.spinFontObj=[]
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
381
|
+
#self.spinFontObj = self.findChildren(QtWidgets.QLineEdit)[0]
|
|
382
|
+
#self.spinFontObj.initialStyle=self.spinFontObj.styleSheet()+" "+backgroundcolor_none
|
|
383
|
+
#self.spinFontObj.font_changing=font_changing
|
|
384
|
+
|
|
385
|
+
def setFocus(self):
|
|
386
|
+
super().setFocus()
|
|
387
|
+
self.focusInFun()
|
|
301
388
|
|
|
302
389
|
def focusInEvent(self, event):
|
|
303
390
|
super().focusInEvent(event) #to preserve classical behaviour before adding the below
|
|
304
391
|
for f in self.addfuncin:
|
|
305
392
|
self.addfuncin[f]()
|
|
306
|
-
|
|
393
|
+
self.focusInFun()
|
|
394
|
+
|
|
395
|
+
def focusInFun(self):
|
|
396
|
+
if not self.FlagFocusIn:
|
|
397
|
+
self.FlagFocusIn=True
|
|
398
|
+
#self.spinFontObj.setStyleSheet(self.spinFontObj.initialStyle+" "+color_changing)
|
|
307
399
|
for b in self.bros:
|
|
308
|
-
b.setStyleSheet(b.initialStyle+" "+color_changing)
|
|
309
|
-
b.setFont(self.font_changing)
|
|
310
|
-
for b in self.spinFontObj:
|
|
400
|
+
b.setStyleSheet(setSS(b,b.initialStyle+" "+color_changing)+"\n"+gPaIRS_QMenu_style)
|
|
311
401
|
b.setFont(self.font_changing)
|
|
312
402
|
|
|
403
|
+
def clearFocus(self):
|
|
404
|
+
super().clearFocus()
|
|
405
|
+
self.setInitalStyle()
|
|
406
|
+
|
|
313
407
|
def focusOutEvent(self, event):
|
|
314
408
|
super().focusOutEvent(event) #to preserve classical behaviour before adding the below
|
|
315
409
|
for f in self.addfuncout:
|
|
316
410
|
self.addfuncout[f]()
|
|
317
|
-
|
|
411
|
+
self.setInitalStyle()
|
|
412
|
+
|
|
413
|
+
def setInitalStyle(self):
|
|
414
|
+
if self.FlagFocusIn:
|
|
415
|
+
self.FlagFocusIn=False
|
|
416
|
+
#self.spinFontObj.setStyleSheet(self.spinFontObj.initialStyle)
|
|
318
417
|
for b in self.bros:
|
|
319
|
-
b.setStyleSheet(b.initialStyle)
|
|
320
|
-
b.setFont(b.initialFont)
|
|
321
|
-
for b in self.spinFontObj:
|
|
418
|
+
b.setStyleSheet(setSS(b,b.initialStyle)+"\n"+gPaIRS_QMenu_style)
|
|
322
419
|
b.setFont(self.initialFont)
|
|
323
|
-
|
|
420
|
+
self.findChildren(QtWidgets.QLineEdit)[0].setFont(self.initialFont)
|
|
421
|
+
self.oldFont=None
|
|
422
|
+
self.oldStyle=None
|
|
423
|
+
|
|
424
|
+
def enterEvent(self, event):
|
|
425
|
+
super().enterEvent(event)
|
|
426
|
+
if not self.hasFocus() and self.isEnabled():
|
|
427
|
+
self.oldFont=self.font()
|
|
428
|
+
self.setFont(self.font_changing)
|
|
429
|
+
b=self #b=self.spinFontObj
|
|
430
|
+
self.oldStyle=b.styleSheet()
|
|
431
|
+
b.setStyleSheet(setSS(b,b.initialStyle+" "+backgroundcolor_hover+" "+border_hover)+"\n"+gPaIRS_QMenu_style)
|
|
432
|
+
|
|
433
|
+
def leaveEvent(self, event):
|
|
434
|
+
super().leaveEvent(event)
|
|
435
|
+
if not self.hasFocus() and self.oldFont is not None:
|
|
436
|
+
self.setFont(self.oldFont)
|
|
437
|
+
b=self #b=self.spinFontObj
|
|
438
|
+
b.setStyleSheet(self.oldStyle)
|
|
439
|
+
self.oldFont=None
|
|
440
|
+
self.oldStyle=None
|
|
441
|
+
|
|
324
442
|
def keyPressEvent(self, event):
|
|
325
443
|
super().keyPressEvent(event)
|
|
326
444
|
if event.key() in (Qt.Key.Key_Return,Qt.Key.Key_Enter) and self.hasFocus():
|
|
@@ -350,6 +468,20 @@ class CollapsibleBox(QtWidgets.QWidget):
|
|
|
350
468
|
self.toggle_button:QPushButton=None
|
|
351
469
|
self.push_button:MyToolButton=None
|
|
352
470
|
|
|
471
|
+
def initialize_widgets(self):
|
|
472
|
+
if self.content_area is None:
|
|
473
|
+
self.content_area=self.findChild(QtWidgets.QGroupBox)
|
|
474
|
+
if self.toggle_button is None:
|
|
475
|
+
self.toggle_button=self.findChild(QtWidgets.QToolButton)
|
|
476
|
+
if self.toggle_button:
|
|
477
|
+
self.toggle_button.setObjectName("CollapsibleBox_toggle")
|
|
478
|
+
self.toggle_button.setChecked(InitCheck)
|
|
479
|
+
self.toggle_button.clicked.connect(self.on_click)
|
|
480
|
+
if hasattr(self.toggle_button,'_orig_paintEvent'):
|
|
481
|
+
self.toggle_button.paintEvent = self.toggle_button._orig_paintEvent
|
|
482
|
+
if self.push_button is None:
|
|
483
|
+
self.push_button=self.findChild(MyToolButton)
|
|
484
|
+
|
|
353
485
|
def setup(self,*args):
|
|
354
486
|
if not self.initFlag:
|
|
355
487
|
if len(args):
|
|
@@ -360,29 +492,17 @@ class CollapsibleBox(QtWidgets.QWidget):
|
|
|
360
492
|
self.stretch=0
|
|
361
493
|
self.initFlag=True
|
|
362
494
|
|
|
363
|
-
|
|
364
|
-
self.content_area=self.findChild(QtWidgets.QGroupBox)
|
|
495
|
+
self.initialize_widgets()
|
|
365
496
|
self.content_area.setStyleSheet("QGroupBox{border: 1px solid gray; border-radius: 6px;}")
|
|
366
|
-
|
|
367
|
-
if self.toggle_button is None:
|
|
368
|
-
self.toggle_button=self.findChild(QtWidgets.QToolButton)
|
|
369
|
-
self.toggle_button.setChecked(InitCheck)
|
|
370
|
-
self.toggle_button.clicked.connect(self.on_click)
|
|
371
497
|
self.toggle_button.setCursor(QtCore.Qt.CursorShape.PointingHandCursor)
|
|
372
498
|
self.toggle_button.setMinimumWidth(self.toolMinimumWidth)
|
|
373
|
-
|
|
374
|
-
if self.push_button is None:
|
|
375
|
-
self.push_button=self.findChild(MyToolButton)
|
|
376
|
-
|
|
377
499
|
self.OpenStyle=\
|
|
378
500
|
"QToolButton { border: none; }\n"+\
|
|
379
|
-
"QToolButton::hover{color: rgba(0,
|
|
380
|
-
"QToolButton::focus{color: rgba(0,0,255,200);}"
|
|
501
|
+
"QToolButton::hover{color: rgba(0,116,255,200);}"
|
|
381
502
|
#"QToolButton::hover{border: none; border-radius: 6px; background-color: rgba(0, 0,128,32); }"
|
|
382
503
|
self.ClosedStyle=\
|
|
383
504
|
"QToolButton { border: 1px solid lightgray; border-radius: 6px }\n"+\
|
|
384
|
-
"QToolButton::hover{ border: 1px solid rgba(0,
|
|
385
|
-
"QToolButton::focus{ border: 1px solid rgba(0,0,255,200); border-radius: 6px; color: rgba(0,0,255,200);}" #background-color: rgba(0, 0,128,32); }"
|
|
505
|
+
"QToolButton::hover{ border: 1px solid rgba(0,116,255,200); border-radius: 6px; color: rgba(0,116,255,200);}"
|
|
386
506
|
|
|
387
507
|
self.heightToogle=self.toggle_button.minimumHeight()
|
|
388
508
|
self.heightOpened=self.minimumHeight()
|
|
@@ -579,6 +699,7 @@ class RichTextPushButton(QPushButton):
|
|
|
579
699
|
|
|
580
700
|
self.lyt=self.__lyt
|
|
581
701
|
self.lbl=self.__lbl
|
|
702
|
+
self.icnWidget=self.__icon
|
|
582
703
|
self.icn=None
|
|
583
704
|
return
|
|
584
705
|
|
|
@@ -682,8 +803,8 @@ class ClickableLabel(QLabel):
|
|
|
682
803
|
def __init__(self, *args):
|
|
683
804
|
super().__init__(*args)
|
|
684
805
|
|
|
685
|
-
self.default_stylesheet = self.styleSheet()
|
|
686
|
-
self.highlight_stylesheet = "background-color:
|
|
806
|
+
self.default_stylesheet = self.styleSheet()
|
|
807
|
+
self.highlight_stylesheet = f"background-color: {PaIRS_ghostblue}; border-radius: 3px;"
|
|
687
808
|
|
|
688
809
|
self.timer = QTimer(self)
|
|
689
810
|
self.timer.timeout.connect(self.resetHighlight)
|
|
@@ -703,6 +824,7 @@ class ClickableLabel(QLabel):
|
|
|
703
824
|
warningDialog(self.window(),Message=self.toolTip(),pixmap=pixmap,title='Info')
|
|
704
825
|
|
|
705
826
|
def highlight(self):
|
|
827
|
+
self.default_stylesheet = self.styleSheet() # <-- capture current style
|
|
706
828
|
self.setStyleSheet(self.highlight_stylesheet)
|
|
707
829
|
self.repaint()
|
|
708
830
|
|
|
@@ -719,12 +841,17 @@ class ClickableLabel(QLabel):
|
|
|
719
841
|
|
|
720
842
|
class ClickableEditLabel(ClickableLabel):
|
|
721
843
|
def setup(self):
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
844
|
+
le = QLineEdit()
|
|
845
|
+
bg = le.palette().color(QPalette.Base)
|
|
846
|
+
bg_rgba = f"rgba({bg.red()}, {bg.green()}, {bg.blue()}, {bg.alpha()})"
|
|
847
|
+
|
|
848
|
+
self.default_stylesheet = self.styleSheet() + f"""
|
|
849
|
+
ClickableEditLabel {{
|
|
850
|
+
background-color: {bg_rgba};
|
|
851
|
+
}}
|
|
852
|
+
"""
|
|
726
853
|
self.setStyleSheet(self.default_stylesheet)
|
|
727
|
-
|
|
854
|
+
le.setParent(None)
|
|
728
855
|
|
|
729
856
|
class CustomLineEdit(QLineEdit):
|
|
730
857
|
cancelEditing = Signal()
|
|
@@ -837,6 +964,372 @@ class EditableLabel(QWidget):
|
|
|
837
964
|
self.label.show()
|
|
838
965
|
self.updateLabel()
|
|
839
966
|
|
|
967
|
+
class HoverZoomToolButton(QToolButton):
|
|
968
|
+
def __init__(self, parent=None, base_icon=24, zoom=1.25):
|
|
969
|
+
super().__init__(parent)
|
|
970
|
+
|
|
971
|
+
self.zoom_factor = zoom
|
|
972
|
+
self.base_size = QSize(base_icon, base_icon)
|
|
973
|
+
self.zoom_size = QSize(
|
|
974
|
+
int(base_icon * zoom),
|
|
975
|
+
int(base_icon * zoom)
|
|
976
|
+
)
|
|
977
|
+
|
|
978
|
+
self.setIconSize(self.base_size)
|
|
979
|
+
|
|
980
|
+
self.anim = QPropertyAnimation(self, b"iconSize", self)
|
|
981
|
+
self.anim.setDuration(120)
|
|
982
|
+
self.anim.setEasingCurve(QEasingCurve.OutCubic)
|
|
983
|
+
|
|
984
|
+
# --- OVERRIDE ---
|
|
985
|
+
def setIconSize(self, size: QSize):
|
|
986
|
+
"""
|
|
987
|
+
Override setIconSize to automatically update base and zoom sizes.
|
|
988
|
+
"""
|
|
989
|
+
super().setIconSize(size)
|
|
990
|
+
self.updateFromCurrentIconSize()
|
|
991
|
+
|
|
992
|
+
def updateFromCurrentIconSize(self, zoom: float | None = None):
|
|
993
|
+
"""
|
|
994
|
+
Recompute base_size and zoom_size starting from the current iconSize().
|
|
995
|
+
Optionally updates the zoom factor.
|
|
996
|
+
"""
|
|
997
|
+
if zoom is not None:
|
|
998
|
+
self.zoom_factor = zoom
|
|
999
|
+
|
|
1000
|
+
current = self.iconSize()
|
|
1001
|
+
self.base_size = QSize(current.width(), current.height())
|
|
1002
|
+
self.zoom_size = QSize(
|
|
1003
|
+
int(current.width() * self.zoom_factor),
|
|
1004
|
+
int(current.height() * self.zoom_factor)
|
|
1005
|
+
)
|
|
1006
|
+
|
|
1007
|
+
def enterEvent(self, event):
|
|
1008
|
+
if self.isEnabled():
|
|
1009
|
+
self.anim.stop()
|
|
1010
|
+
self.anim.setStartValue(self.iconSize())
|
|
1011
|
+
self.anim.setEndValue(self.zoom_size)
|
|
1012
|
+
self.anim.start()
|
|
1013
|
+
super().enterEvent(event)
|
|
1014
|
+
|
|
1015
|
+
def leaveEvent(self, event):
|
|
1016
|
+
if self.isEnabled():
|
|
1017
|
+
self.anim.stop()
|
|
1018
|
+
self.anim.setStartValue(self.iconSize())
|
|
1019
|
+
self.anim.setEndValue(self.base_size)
|
|
1020
|
+
self.anim.start()
|
|
1021
|
+
super().leaveEvent(event)
|
|
1022
|
+
|
|
1023
|
+
def apply_native_hover_border(w, *, borderRadius=3, borderWidth=1, borderColor=str2QColor(PaIRS_gray)):
|
|
1024
|
+
"""
|
|
1025
|
+
Adds a hover border overlay while preserving native button rendering.
|
|
1026
|
+
No stylesheet is used. No subclassing (wraps paintEvent + installs eventFilter).
|
|
1027
|
+
"""
|
|
1028
|
+
|
|
1029
|
+
# ensure hover events
|
|
1030
|
+
w.setAttribute(Qt.WA_Hover, True)
|
|
1031
|
+
|
|
1032
|
+
# keep original paintEvent once
|
|
1033
|
+
if not hasattr(w, "_orig_paintEvent"):
|
|
1034
|
+
w._orig_paintEvent = w.paintEvent
|
|
1035
|
+
|
|
1036
|
+
def paintEvent_with_border(self, event):
|
|
1037
|
+
# native painting first
|
|
1038
|
+
self._orig_paintEvent(event)
|
|
1039
|
+
|
|
1040
|
+
# overlay border only on hover
|
|
1041
|
+
if self.underMouse() and self.isEnabled():
|
|
1042
|
+
p = QPainter(self)
|
|
1043
|
+
p.setRenderHint(QPainter.Antialiasing, True)
|
|
1044
|
+
|
|
1045
|
+
pen = QPen(borderColor)
|
|
1046
|
+
pen.setWidth(borderWidth)
|
|
1047
|
+
p.setPen(pen)
|
|
1048
|
+
p.setBrush(Qt.NoBrush)
|
|
1049
|
+
|
|
1050
|
+
# keep border inside widget rect
|
|
1051
|
+
d = borderWidth #/ 2.0
|
|
1052
|
+
r = self.rect().adjusted(int(d), int(d), -int(d), -int(d))
|
|
1053
|
+
p.drawRoundedRect(r, borderRadius, borderRadius)
|
|
1054
|
+
|
|
1055
|
+
p.end()
|
|
1056
|
+
|
|
1057
|
+
w.paintEvent = types.MethodType(paintEvent_with_border, w)
|
|
1058
|
+
|
|
1059
|
+
# eventFilter to trigger updates on hover transitions
|
|
1060
|
+
class _HoverUpdateFilter(type(w)):
|
|
1061
|
+
pass
|
|
1062
|
+
|
|
1063
|
+
# simpler: store filter object on widget
|
|
1064
|
+
if not hasattr(w, "_hoverBorderFilter"):
|
|
1065
|
+
from PySide6.QtCore import QObject
|
|
1066
|
+
class HoverBorderFilter(QObject):
|
|
1067
|
+
def eventFilter(self, obj, ev):
|
|
1068
|
+
if ev.type() in (QEvent.Enter, QEvent.Leave, QEvent.HoverEnter, QEvent.HoverLeave, QEvent.HoverMove):
|
|
1069
|
+
obj.update()
|
|
1070
|
+
return False
|
|
1071
|
+
|
|
1072
|
+
w._hoverBorderFilter = HoverBorderFilter(w)
|
|
1073
|
+
w.installEventFilter(w._hoverBorderFilter)
|
|
1074
|
+
|
|
1075
|
+
def apply_native_hover_glow(
|
|
1076
|
+
w:QWidget, *,
|
|
1077
|
+
borderRadius=3,
|
|
1078
|
+
glowSize=4, # spessore della sfumatura
|
|
1079
|
+
baseColor=str2QColor(PaIRS_gray)
|
|
1080
|
+
):
|
|
1081
|
+
"""
|
|
1082
|
+
Adds a soft glow around the widget border on hover,
|
|
1083
|
+
preserving native rendering (no stylesheet).
|
|
1084
|
+
"""
|
|
1085
|
+
if w.objectName()=='CollapsibleBox_toggle':
|
|
1086
|
+
pass
|
|
1087
|
+
w.setAttribute(Qt.WA_Hover, True)
|
|
1088
|
+
|
|
1089
|
+
if not hasattr(w, "_orig_paintEvent"):
|
|
1090
|
+
w._orig_paintEvent = w.paintEvent
|
|
1091
|
+
|
|
1092
|
+
def paintEvent_with_glow(self, event):
|
|
1093
|
+
# 1) Native painting
|
|
1094
|
+
self._orig_paintEvent(event)
|
|
1095
|
+
|
|
1096
|
+
if not (self.underMouse() and self.isEnabled()):
|
|
1097
|
+
return
|
|
1098
|
+
|
|
1099
|
+
p = QPainter(self)
|
|
1100
|
+
p.setRenderHint(QPainter.Antialiasing, True)
|
|
1101
|
+
p.setBrush(Qt.NoBrush)
|
|
1102
|
+
|
|
1103
|
+
# 2) Draw soft glow (outer → inner)
|
|
1104
|
+
for i in range(glowSize):
|
|
1105
|
+
alpha = int(120 * (1 - i / glowSize)) # fade out
|
|
1106
|
+
c = QColor(baseColor)
|
|
1107
|
+
c.setAlpha(alpha)
|
|
1108
|
+
|
|
1109
|
+
pen = QPen(c)
|
|
1110
|
+
pen.setWidth(1)
|
|
1111
|
+
p.setPen(pen)
|
|
1112
|
+
|
|
1113
|
+
r = self.rect().adjusted(
|
|
1114
|
+
i + 1, i + 1,
|
|
1115
|
+
-(i + 1), -(i + 1)
|
|
1116
|
+
)
|
|
1117
|
+
p.drawRoundedRect(r, borderRadius, borderRadius)
|
|
1118
|
+
|
|
1119
|
+
p.end()
|
|
1120
|
+
|
|
1121
|
+
w.paintEvent = types.MethodType(paintEvent_with_glow, w)
|
|
1122
|
+
|
|
1123
|
+
# Force repaint on hover transitions
|
|
1124
|
+
if not hasattr(w, "_hoverGlowFilter"):
|
|
1125
|
+
from PySide6.QtCore import QObject
|
|
1126
|
+
class HoverGlowFilter(QObject):
|
|
1127
|
+
def eventFilter(self, obj, ev):
|
|
1128
|
+
if ev.type() in (
|
|
1129
|
+
QEvent.Enter, QEvent.Leave,
|
|
1130
|
+
QEvent.HoverEnter, QEvent.HoverLeave, QEvent.HoverMove
|
|
1131
|
+
):
|
|
1132
|
+
obj.update()
|
|
1133
|
+
return False
|
|
1134
|
+
|
|
1135
|
+
w._hoverGlowFilter = HoverGlowFilter(w)
|
|
1136
|
+
w.installEventFilter(w._hoverGlowFilter)
|
|
1137
|
+
|
|
1138
|
+
def apply_hover_glow_label(
|
|
1139
|
+
w: QLabel,
|
|
1140
|
+
*,
|
|
1141
|
+
color=str2QColor(PaIRS_blue), #"#0051FF",
|
|
1142
|
+
blur=18,
|
|
1143
|
+
max_alpha=170,
|
|
1144
|
+
duration_ms=160,
|
|
1145
|
+
):
|
|
1146
|
+
if getattr(w, "_hoverGlowInstalled", False):
|
|
1147
|
+
w._hoverGlowColor = QColor(color)
|
|
1148
|
+
w._hoverGlowBlur = float(blur)
|
|
1149
|
+
w._hoverGlowMaxAlpha = int(max_alpha)
|
|
1150
|
+
w._hoverGlowDuration = int(duration_ms)
|
|
1151
|
+
w._hoverGlowEffect.setBlurRadius(w._hoverGlowBlur)
|
|
1152
|
+
return
|
|
1153
|
+
|
|
1154
|
+
w._hoverGlowInstalled = True
|
|
1155
|
+
w._hoverGlowColor = QColor(color)
|
|
1156
|
+
w._hoverGlowBlur = float(blur)
|
|
1157
|
+
w._hoverGlowMaxAlpha = int(max_alpha)
|
|
1158
|
+
w._hoverGlowDuration = int(duration_ms)
|
|
1159
|
+
|
|
1160
|
+
eff = QGraphicsDropShadowEffect(w)
|
|
1161
|
+
eff.setOffset(0, 0)
|
|
1162
|
+
eff.setBlurRadius(w._hoverGlowBlur)
|
|
1163
|
+
|
|
1164
|
+
c = QColor(w._hoverGlowColor)
|
|
1165
|
+
c.setAlpha(0)
|
|
1166
|
+
eff.setColor(c)
|
|
1167
|
+
|
|
1168
|
+
w.setGraphicsEffect(eff)
|
|
1169
|
+
w._hoverGlowEffect = eff
|
|
1170
|
+
|
|
1171
|
+
def _set_alpha(val):
|
|
1172
|
+
col = QColor(w._hoverGlowColor)
|
|
1173
|
+
col.setAlpha(int(val))
|
|
1174
|
+
w._hoverGlowEffect.setColor(col)
|
|
1175
|
+
|
|
1176
|
+
# ✅ Animate a plain value (no Qt property needed)
|
|
1177
|
+
w._hoverGlowAnimAlpha = QVariantAnimation(w)
|
|
1178
|
+
w._hoverGlowAnimAlpha.setEasingCurve(QEasingCurve.OutCubic)
|
|
1179
|
+
w._hoverGlowAnimAlpha.valueChanged.connect(_set_alpha)
|
|
1180
|
+
|
|
1181
|
+
class _GlowFilter(QObject):
|
|
1182
|
+
def eventFilter(self, obj, ev):
|
|
1183
|
+
if obj is not w:
|
|
1184
|
+
return False
|
|
1185
|
+
|
|
1186
|
+
t = ev.type()
|
|
1187
|
+
if t in (QEvent.Enter, QEvent.HoverEnter):
|
|
1188
|
+
w._hoverGlowAnimAlpha.stop()
|
|
1189
|
+
w._hoverGlowAnimAlpha.setDuration(w._hoverGlowDuration)
|
|
1190
|
+
w._hoverGlowAnimAlpha.setStartValue(w._hoverGlowEffect.color().alpha())
|
|
1191
|
+
w._hoverGlowAnimAlpha.setEndValue(w._hoverGlowMaxAlpha)
|
|
1192
|
+
w._hoverGlowAnimAlpha.start()
|
|
1193
|
+
|
|
1194
|
+
elif t in (QEvent.Leave, QEvent.HoverLeave):
|
|
1195
|
+
w._hoverGlowAnimAlpha.stop()
|
|
1196
|
+
w._hoverGlowAnimAlpha.setDuration(w._hoverGlowDuration)
|
|
1197
|
+
w._hoverGlowAnimAlpha.setStartValue(w._hoverGlowEffect.color().alpha())
|
|
1198
|
+
w._hoverGlowAnimAlpha.setEndValue(0)
|
|
1199
|
+
w._hoverGlowAnimAlpha.start()
|
|
1200
|
+
|
|
1201
|
+
return False
|
|
1202
|
+
|
|
1203
|
+
w._hoverGlowFilter = _GlowFilter(w)
|
|
1204
|
+
w.installEventFilter(w._hoverGlowFilter)
|
|
1205
|
+
|
|
1206
|
+
w.setAttribute(Qt.WA_Hover, True)
|
|
1207
|
+
w.setMouseTracking(True)
|
|
1208
|
+
|
|
1209
|
+
def remove_hover_glow_label(w: QLabel):
|
|
1210
|
+
"""Removes the hover glow behavior and restores a clean state."""
|
|
1211
|
+
if not getattr(w, "_hoverGlowInstalled", False):
|
|
1212
|
+
return
|
|
1213
|
+
|
|
1214
|
+
# Stop animation cleanly
|
|
1215
|
+
anim = getattr(w, "_hoverGlowAnimAlpha", None)
|
|
1216
|
+
if anim is not None:
|
|
1217
|
+
anim.stop()
|
|
1218
|
+
|
|
1219
|
+
# Remove event filter
|
|
1220
|
+
filt = getattr(w, "_hoverGlowFilter", None)
|
|
1221
|
+
if filt is not None:
|
|
1222
|
+
try:
|
|
1223
|
+
w.removeEventFilter(filt)
|
|
1224
|
+
except RuntimeError:
|
|
1225
|
+
pass
|
|
1226
|
+
|
|
1227
|
+
# Remove graphics effect
|
|
1228
|
+
w.setGraphicsEffect(None)
|
|
1229
|
+
|
|
1230
|
+
# Restore hover-related flags (safe defaults)
|
|
1231
|
+
w.setAttribute(Qt.WA_Hover, False)
|
|
1232
|
+
w.setMouseTracking(False)
|
|
1233
|
+
|
|
1234
|
+
# Cleanup attributes
|
|
1235
|
+
for attr in (
|
|
1236
|
+
"_hoverGlowInstalled",
|
|
1237
|
+
"_hoverGlowColor",
|
|
1238
|
+
"_hoverGlowBlur",
|
|
1239
|
+
"_hoverGlowMaxAlpha",
|
|
1240
|
+
"_hoverGlowDuration",
|
|
1241
|
+
"_hoverGlowEffect",
|
|
1242
|
+
"_hoverGlowAnimAlpha",
|
|
1243
|
+
"_hoverGlowFilter",
|
|
1244
|
+
):
|
|
1245
|
+
if hasattr(w, attr):
|
|
1246
|
+
delattr(w, attr)
|
|
1247
|
+
|
|
1248
|
+
class SliderHandleCursorFilter(QObject):
|
|
1249
|
+
def eventFilter(self, obj, event):
|
|
1250
|
+
if isinstance(obj, QSlider) and event.type() == QEvent.MouseMove:
|
|
1251
|
+
|
|
1252
|
+
opt = QStyleOptionSlider()
|
|
1253
|
+
obj.initStyleOption(opt)
|
|
1254
|
+
|
|
1255
|
+
handle_rect = obj.style().subControlRect(
|
|
1256
|
+
QStyle.CC_Slider,
|
|
1257
|
+
opt,
|
|
1258
|
+
QStyle.SC_SliderHandle,
|
|
1259
|
+
obj
|
|
1260
|
+
)
|
|
1261
|
+
|
|
1262
|
+
if handle_rect.contains(event.position().toPoint()):
|
|
1263
|
+
obj.setCursor(QCursor(Qt.OpenHandCursor))
|
|
1264
|
+
else:
|
|
1265
|
+
obj.unsetCursor()
|
|
1266
|
+
|
|
1267
|
+
return False
|
|
1268
|
+
|
|
1269
|
+
def changes(self,TabType,filename,title=" Changes"):
|
|
1270
|
+
FlagShow=False
|
|
1271
|
+
if self.logChanges:
|
|
1272
|
+
if self.logChanges.isVisible():
|
|
1273
|
+
FlagShow=True
|
|
1274
|
+
if FlagShow:
|
|
1275
|
+
self.logChanges.hide()
|
|
1276
|
+
self.logChanges.show()
|
|
1277
|
+
else:
|
|
1278
|
+
self.logChanges=TabType(self,True)
|
|
1279
|
+
self.logChanges.resize(720,720)
|
|
1280
|
+
self.logChanges.show()
|
|
1281
|
+
self.logChanges.ui.progress_Proc.hide()
|
|
1282
|
+
self.logChanges.ui.button_close_tab.hide()
|
|
1283
|
+
icon=QPixmap(''+ icons_path +'news.png')
|
|
1284
|
+
self.logChanges.ui.icon.setPixmap(icon)
|
|
1285
|
+
apply_hover_glow_label(self.logChanges.ui.icon)
|
|
1286
|
+
self.logChanges.setWindowIcon(self.windowIcon())
|
|
1287
|
+
self.logChanges.setWindowTitle(title)
|
|
1288
|
+
self.logChanges.ui.name_tab.setText(title)
|
|
1289
|
+
|
|
1290
|
+
self.logChanges.ui.log.setLineWrapColumnOrWidth(self.logChanges.ui.log.width()-20)
|
|
1291
|
+
base="""
|
|
1292
|
+
QTextEdit {
|
|
1293
|
+
border: 1px solid #2a2a2a;
|
|
1294
|
+
border-radius: 6px;
|
|
1295
|
+
|
|
1296
|
+
padding: 2px;
|
|
1297
|
+
|
|
1298
|
+
selection-background-color: #0051FF;
|
|
1299
|
+
selection-color: #FFFFFF;
|
|
1300
|
+
}
|
|
1301
|
+
"""
|
|
1302
|
+
self.logChanges.ui.log.setStyleSheet(base+"\n"+gPaIRS_QMenu_style)
|
|
1303
|
+
|
|
1304
|
+
def setFontPixelSize(logChanges:type(self.logChanges),fPixSize):
|
|
1305
|
+
logfont=self.font()
|
|
1306
|
+
logfont.setFamily(fontName)
|
|
1307
|
+
logfont.setPixelSize(fPixSize+2)
|
|
1308
|
+
logChanges.ui.log.setFont(logfont)
|
|
1309
|
+
fPixSize_TabNames=min([fPixSize*2,30])
|
|
1310
|
+
lab=logChanges.ui.name_tab
|
|
1311
|
+
font=lab.font()
|
|
1312
|
+
font.setPixelSize(fPixSize_TabNames)
|
|
1313
|
+
lab.setFont(font)
|
|
1314
|
+
self.logChanges.setFontPixelSize=lambda fS: setFontPixelSize(self.logChanges,fS)
|
|
1315
|
+
self.logChanges.setFontPixelSize(self.TABpar.fontPixelSize)
|
|
1316
|
+
def logResizeEvent(logChanges:type(self.logChanges),e):
|
|
1317
|
+
super(type(logChanges),logChanges).resizeEvent(e)
|
|
1318
|
+
logChanges.ui.log.setLineWrapColumnOrWidth(logChanges.ui.log.width()-20)
|
|
1319
|
+
self.logChanges.ui.log.resizeEvent=lambda e: logResizeEvent(self.logChanges,e)
|
|
1320
|
+
|
|
1321
|
+
self.logChanges.ui.icon.addfuncclick['whatsnew']=self.whatsNew
|
|
1322
|
+
self.logChanges.ui.icon.setCustomCursor()
|
|
1323
|
+
|
|
1324
|
+
try:
|
|
1325
|
+
file = open(filename, "rb")
|
|
1326
|
+
content = file.read().decode("utf-8")
|
|
1327
|
+
self.logChanges.ui.log.setText(content)
|
|
1328
|
+
file.close()
|
|
1329
|
+
except Exception as inst:
|
|
1330
|
+
pri.Error.red(f'There was a problem while reading the file {filename}:\n{inst}')
|
|
1331
|
+
self.logChanges.ui.log.setText(f'No information about PaIRS-UniNa updates available!\n\nSorry for this, try to reinstall PaIRS-UniNa or alternatively contact the authors at {__mail__}.')
|
|
1332
|
+
return
|
|
840
1333
|
|
|
841
1334
|
#********************************************* Matplotlib
|
|
842
1335
|
import io
|
|
@@ -905,7 +1398,7 @@ class MplCanvas(FigureCanvasQTAgg):
|
|
|
905
1398
|
lbl=QLabel(fig2)
|
|
906
1399
|
lbl.setAlignment(QtCore.Qt.AlignCenter)
|
|
907
1400
|
with io.BytesIO() as buffer:
|
|
908
|
-
self.fig.savefig(buffer)
|
|
1401
|
+
self.fig.savefig(buffer, bbox_inches='tight', pad_inches=0)
|
|
909
1402
|
pixmap = QPixmap(QImage.fromData(buffer.getvalue()))
|
|
910
1403
|
lbl.setPixmap(pixmap)
|
|
911
1404
|
lbl.setScaledContents(False)
|
|
@@ -917,8 +1410,6 @@ class MplCanvas(FigureCanvasQTAgg):
|
|
|
917
1410
|
lay.addWidget(lbl)
|
|
918
1411
|
lay.addWidget(lbl2)
|
|
919
1412
|
|
|
920
|
-
self.fig2.append(fig2)
|
|
921
|
-
|
|
922
1413
|
def closeFig2(event):
|
|
923
1414
|
type(fig2).closeEvent(fig2,event)
|
|
924
1415
|
self.fig2.pop(self.fig2.index(fig2))
|
|
@@ -936,7 +1427,7 @@ class MplCanvas(FigureCanvasQTAgg):
|
|
|
936
1427
|
fig2.scaleFactor=fig2.scaleFactor*scale
|
|
937
1428
|
fig2.scaleFactor=min([fig2.scaleFactor,1.5])
|
|
938
1429
|
fig2.scaleFactor=max([fig2.scaleFactor,0.5])
|
|
939
|
-
fig2.setFixedSize(s0*fig2.scaleFactor)
|
|
1430
|
+
fig2.setFixedSize(fig2.s0*fig2.scaleFactor)
|
|
940
1431
|
lbl.setPixmap(pixmap.scaled(pixmap.size()*fig2.scaleFactor,mode=Qt.TransformationMode.SmoothTransformation))
|
|
941
1432
|
return
|
|
942
1433
|
fig2.resizeFig2=resizeFig2
|
|
@@ -988,6 +1479,7 @@ class MplCanvas(FigureCanvasQTAgg):
|
|
|
988
1479
|
fig2.lbl:QLabel=lbl
|
|
989
1480
|
def contextMenuEventFig2(event):
|
|
990
1481
|
contextMenu = QMenu()
|
|
1482
|
+
contextMenu.setStyleSheet(gPaIRS_QMenu_style)
|
|
991
1483
|
copy2clipboard = contextMenu.addAction("Copy to clipboard ("+QS_copy2clipboard.key().toString(QKeySequence.NativeText)+")")
|
|
992
1484
|
contextMenu.addSeparator()
|
|
993
1485
|
scaleDown = contextMenu.addAction("Scale down ("+QS_scaleDown.key().toString(QKeySequence.NativeText)+")")
|
|
@@ -1028,9 +1520,11 @@ class MplCanvas(FigureCanvasQTAgg):
|
|
|
1028
1520
|
|
|
1029
1521
|
fig2.show()
|
|
1030
1522
|
fig2.setFixedSize(fig2.width(), fig2.height())
|
|
1031
|
-
s0=fig2.size()
|
|
1523
|
+
fig2.s0=fig2.size()
|
|
1032
1524
|
|
|
1525
|
+
self.fig2.append(fig2)
|
|
1033
1526
|
self.posWindow(len(self.fig2)-1)
|
|
1527
|
+
|
|
1034
1528
|
"""
|
|
1035
1529
|
fgeo = fig2.frameGeometry()
|
|
1036
1530
|
centerPoint = QGuiApplication.primaryScreen().availableGeometry().center()
|
|
@@ -1039,7 +1533,7 @@ class MplCanvas(FigureCanvasQTAgg):
|
|
|
1039
1533
|
"""
|
|
1040
1534
|
|
|
1041
1535
|
def showTip(self,obj,message):
|
|
1042
|
-
|
|
1536
|
+
show_mouse_tooltip(obj,message)
|
|
1043
1537
|
|
|
1044
1538
|
def posWindow(self,ind):
|
|
1045
1539
|
w=h=0
|
|
@@ -1115,12 +1609,12 @@ def setAppGuiPalette(self:QWidget,palette:QPalette=None):
|
|
|
1115
1609
|
c.setPalette(palette)
|
|
1116
1610
|
if hasattr(c,'initialStyle') and hasattr(c, 'setStyleSheet'):
|
|
1117
1611
|
c.setStyleSheet(c.initialStyle)
|
|
1118
|
-
for c in f.findChildren(
|
|
1119
|
-
c
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1612
|
+
for c in f.findChildren(MyQLineEdit):
|
|
1613
|
+
c.initFlag=False
|
|
1614
|
+
c.styleFlag=False
|
|
1615
|
+
c.setup()
|
|
1616
|
+
for c in f.findChildren(ClickableEditLabel):
|
|
1617
|
+
c.setup()
|
|
1124
1618
|
for c in f.findChildren(QObject):
|
|
1125
1619
|
if hasattr(c,'setup2'):
|
|
1126
1620
|
c.initFlag2=False
|
|
@@ -1131,3 +1625,185 @@ def setAppGuiPalette(self:QWidget,palette:QPalette=None):
|
|
|
1131
1625
|
if hasattr(self,'w_Vis'): self.w_Vis.addPlotToolBar()
|
|
1132
1626
|
except:
|
|
1133
1627
|
pri.Error.red("***** Error while setting the application palette! *****")
|
|
1628
|
+
|
|
1629
|
+
class Toast(QFrame):
|
|
1630
|
+
"""
|
|
1631
|
+
Tooltip-like custom toast that appears at the current mouse cursor position.
|
|
1632
|
+
Non-native, does not steal focus. Auto-hides after timeout_ms.
|
|
1633
|
+
"""
|
|
1634
|
+
|
|
1635
|
+
def __init__(
|
|
1636
|
+
self,
|
|
1637
|
+
parent: QWidget,
|
|
1638
|
+
msg: str,
|
|
1639
|
+
*,
|
|
1640
|
+
timeout_ms: int = 2500,
|
|
1641
|
+
offset: QPoint = QPoint(10, 15), # offset from cursor
|
|
1642
|
+
min_width: int = 0,
|
|
1643
|
+
max_width: int = 460,
|
|
1644
|
+
fade_in_ms: int = 80,
|
|
1645
|
+
fade_out_ms: int = 130,
|
|
1646
|
+
):
|
|
1647
|
+
super().__init__(parent)
|
|
1648
|
+
|
|
1649
|
+
self.setObjectName("PaIRSToast")
|
|
1650
|
+
self.setWindowFlags(Qt.FramelessWindowHint | Qt.ToolTip)
|
|
1651
|
+
#self.setAttribute(Qt.WA_TranslucentBackground, True)
|
|
1652
|
+
self.setAttribute(Qt.WA_ShowWithoutActivating, True)
|
|
1653
|
+
|
|
1654
|
+
self._label = QLabel(msg, self)
|
|
1655
|
+
self._label.setObjectName("PaIRSToastLabel")
|
|
1656
|
+
self._label.setWordWrap(True)
|
|
1657
|
+
|
|
1658
|
+
lay = QHBoxLayout(self)
|
|
1659
|
+
lay.setContentsMargins(4,3,4,3)
|
|
1660
|
+
lay.addWidget(self._label)
|
|
1661
|
+
|
|
1662
|
+
# Classic tooltip-like styling
|
|
1663
|
+
self.setStyleSheet("""
|
|
1664
|
+
QFrame#PaIRSToast {
|
|
1665
|
+
background-color: #ffffdc; /* classic tooltip-ish */
|
|
1666
|
+
color: #000000;
|
|
1667
|
+
border: 1px solid rgba(0, 0, 0, 0.45);
|
|
1668
|
+
border-radius: 4px;
|
|
1669
|
+
}
|
|
1670
|
+
QLabel#PaIRSToastLabel {
|
|
1671
|
+
color: #000000;
|
|
1672
|
+
}
|
|
1673
|
+
""")
|
|
1674
|
+
|
|
1675
|
+
# Width clamp + nice wrapping
|
|
1676
|
+
# Reset any previous constraints (important if a previous tooltip was wider)
|
|
1677
|
+
self.setMinimumSize(min_width, 0)
|
|
1678
|
+
self.setMaximumSize(max_width, 16777215)
|
|
1679
|
+
|
|
1680
|
+
self._label.setMinimumSize(min_width, 0)
|
|
1681
|
+
self._label.setMaximumSize(max_width, 16777215)
|
|
1682
|
+
|
|
1683
|
+
# Make sure the label doesn't "expand"
|
|
1684
|
+
self._label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
|
|
1685
|
+
|
|
1686
|
+
font=self.window().font()
|
|
1687
|
+
self._label.setFont(font)
|
|
1688
|
+
self._apply_size(msg)
|
|
1689
|
+
|
|
1690
|
+
# Position at cursor (global)
|
|
1691
|
+
self._move_to_cursor(offset)
|
|
1692
|
+
|
|
1693
|
+
# Opacity animation
|
|
1694
|
+
self.setWindowOpacity(0.0)
|
|
1695
|
+
self._anim = QPropertyAnimation(self, b"windowOpacity", self)
|
|
1696
|
+
self._anim.setEasingCurve(QEasingCurve.OutCubic)
|
|
1697
|
+
|
|
1698
|
+
# Auto hide
|
|
1699
|
+
self._timer = QTimer(self)
|
|
1700
|
+
self._timer.setSingleShot(True)
|
|
1701
|
+
self._timer.timeout.connect(lambda: self.fade_out(duration_ms=fade_out_ms))
|
|
1702
|
+
|
|
1703
|
+
self.show()
|
|
1704
|
+
self.raise_()
|
|
1705
|
+
self.fade_in(duration_ms=fade_in_ms)
|
|
1706
|
+
self._timer.start(timeout_ms)
|
|
1707
|
+
|
|
1708
|
+
def _apply_size(self, msg: str):
|
|
1709
|
+
self._label.setText(msg)
|
|
1710
|
+
|
|
1711
|
+
# Let QLabel compute the correct wrapped size
|
|
1712
|
+
self._label.adjustSize()
|
|
1713
|
+
sh = self._label.sizeHint()
|
|
1714
|
+
|
|
1715
|
+
# Lock label to its real hint size
|
|
1716
|
+
self._label.setFixedSize(sh)
|
|
1717
|
+
|
|
1718
|
+
# Now shrink the frame to content + margins
|
|
1719
|
+
self.adjustSize()
|
|
1720
|
+
|
|
1721
|
+
# Lock the whole toaster too (prevents extra blank area)
|
|
1722
|
+
self.setFixedSize(self.sizeHint())
|
|
1723
|
+
|
|
1724
|
+
def caret_global_pos(self, edit, offset):
|
|
1725
|
+
"""
|
|
1726
|
+
Returns a stable global position near the text caret.
|
|
1727
|
+
Works for QLineEdit, QTextEdit, QPlainTextEdit.
|
|
1728
|
+
"""
|
|
1729
|
+
if hasattr(edit, "cursorRect"):
|
|
1730
|
+
r = edit.cursorRect() # widget coords
|
|
1731
|
+
|
|
1732
|
+
# Anchor to bottom-left of caret rect (more stable than bottomRight)
|
|
1733
|
+
p = edit.mapToGlobal(r.bottomLeft())
|
|
1734
|
+
p += offset
|
|
1735
|
+
|
|
1736
|
+
# Clamp to screen to avoid off-screen placement
|
|
1737
|
+
screen = QApplication.screenAt(QCursor.pos()) or edit.screen()
|
|
1738
|
+
if screen:
|
|
1739
|
+
geo = screen.availableGeometry()
|
|
1740
|
+
x = min(max(p.x(), geo.left()), geo.right())
|
|
1741
|
+
y = min(max(p.y(), geo.top()), geo.bottom())
|
|
1742
|
+
return QPoint(x, y)
|
|
1743
|
+
|
|
1744
|
+
return p
|
|
1745
|
+
|
|
1746
|
+
# Fallback: mouse cursor
|
|
1747
|
+
return QCursor.pos() + offset
|
|
1748
|
+
|
|
1749
|
+
def _move_to_cursor(self, offset: QPoint):
|
|
1750
|
+
parent:QLineEdit = self.parent()
|
|
1751
|
+
if parent and hasattr(parent, "cursorRect"):
|
|
1752
|
+
p=self.caret_global_pos(parent,QPoint(0,6))
|
|
1753
|
+
else:
|
|
1754
|
+
p=self.caret_global_pos(parent,offset)
|
|
1755
|
+
|
|
1756
|
+
# Keep inside the current screen geometry
|
|
1757
|
+
screen = self.screen()
|
|
1758
|
+
if screen is None:
|
|
1759
|
+
self.move(p)
|
|
1760
|
+
return
|
|
1761
|
+
|
|
1762
|
+
geo = screen.availableGeometry()
|
|
1763
|
+
self.adjustSize()
|
|
1764
|
+
w, h = self.width(), self.height()
|
|
1765
|
+
|
|
1766
|
+
x = p.x()
|
|
1767
|
+
y = p.y()
|
|
1768
|
+
|
|
1769
|
+
if x + w > geo.right():
|
|
1770
|
+
x = geo.right() - w
|
|
1771
|
+
if y + h > geo.bottom():
|
|
1772
|
+
y = geo.bottom() - h
|
|
1773
|
+
if x < geo.left():
|
|
1774
|
+
x = geo.left()
|
|
1775
|
+
if y < geo.top():
|
|
1776
|
+
y = geo.top()
|
|
1777
|
+
|
|
1778
|
+
self.move(QPoint(x, y))
|
|
1779
|
+
|
|
1780
|
+
def fade_in(self, *, duration_ms: int = 80):
|
|
1781
|
+
self._anim.stop()
|
|
1782
|
+
self._anim.setDuration(duration_ms)
|
|
1783
|
+
self._anim.setStartValue(self.windowOpacity())
|
|
1784
|
+
self._anim.setEndValue(1.0)
|
|
1785
|
+
self._anim.start()
|
|
1786
|
+
|
|
1787
|
+
def fade_out(self, *, duration_ms: int = 130):
|
|
1788
|
+
self._anim.stop()
|
|
1789
|
+
self._anim.setDuration(duration_ms)
|
|
1790
|
+
self._anim.setStartValue(self.windowOpacity())
|
|
1791
|
+
self._anim.setEndValue(0.0)
|
|
1792
|
+
self._anim.finished.connect(self.close)
|
|
1793
|
+
self._anim.start()
|
|
1794
|
+
|
|
1795
|
+
def show_mouse_tooltip(parent: QWidget, msg: str, *, timeout_ms: int = 2500):
|
|
1796
|
+
"""
|
|
1797
|
+
Convenience function: show a tooltip-like toaster at the mouse cursor.
|
|
1798
|
+
Keeps a reference on parent to avoid garbage collection.
|
|
1799
|
+
"""
|
|
1800
|
+
old = getattr(parent, "_pairs_mouse_toaster", None)
|
|
1801
|
+
if old is not None and old.isVisible():
|
|
1802
|
+
old.close()
|
|
1803
|
+
|
|
1804
|
+
if msg:
|
|
1805
|
+
t = Toast(parent, msg, timeout_ms=timeout_ms)
|
|
1806
|
+
else: t=None
|
|
1807
|
+
parent._pairs_mouse_toaster = t
|
|
1808
|
+
return t
|
|
1809
|
+
|