PaIRS-UniNa 0.2.9__cp312-cp312-win_amd64.whl → 0.2.10__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/Calibration_Tab.py +4 -3
- PaIRS_UniNa/Changes.txt +12 -0
- PaIRS_UniNa/Explorer.py +222 -68
- PaIRS_UniNa/Input_Tab.py +2 -4
- PaIRS_UniNa/Input_Tab_CalVi.py +1 -0
- PaIRS_UniNa/Input_Tab_tools.py +14 -10
- PaIRS_UniNa/PaIRS_pypacks.py +18 -65
- PaIRS_UniNa/Process_Tab.py +19 -15
- PaIRS_UniNa/Process_Tab_Disp.py +8 -1
- PaIRS_UniNa/Saving_tools.py +2 -0
- PaIRS_UniNa/TabTools.py +165 -6
- PaIRS_UniNa/Vis_Tab.py +11 -4
- PaIRS_UniNa/Vis_Tab_CalVi.py +1 -2
- PaIRS_UniNa/_PaIRS_PIV.pyd +0 -0
- PaIRS_UniNa/__init__.py +3 -3
- PaIRS_UniNa/addwidgets_ps.py +570 -70
- PaIRS_UniNa/gPaIRS.py +60 -17
- PaIRS_UniNa/rqrdpckgs.txt +7 -7
- PaIRS_UniNa/ui_Calibration_Tab.py +3 -3
- PaIRS_UniNa/ui_gPairs.py +8 -8
- PaIRS_UniNa/whatsnew.txt +2 -4
- {pairs_unina-0.2.9.dist-info → pairs_unina-0.2.10.dist-info}/METADATA +7 -14
- {pairs_unina-0.2.9.dist-info → pairs_unina-0.2.10.dist-info}/RECORD +25 -25
- {pairs_unina-0.2.9.dist-info → pairs_unina-0.2.10.dist-info}/WHEEL +0 -0
- {pairs_unina-0.2.9.dist-info → pairs_unina-0.2.10.dist-info}/top_level.txt +0 -0
PaIRS_UniNa/addwidgets_ps.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
from .PaIRS_pypacks import *
|
|
2
3
|
#from ui_Tree_Tab import Ui_TreeTab
|
|
3
4
|
|
|
@@ -10,8 +11,9 @@ font_italic=True
|
|
|
10
11
|
font_weight=QFont.DemiBold
|
|
11
12
|
backgroundcolor_none=" background-color: none;"
|
|
12
13
|
backgroundcolor_changing=" background-color: rgb(255,230,230);"
|
|
14
|
+
backgroundcolor_hover=" background-color: rgba(0, 116, 255, 0.1);"
|
|
15
|
+
border_hover = " " #"border: 1px solid gray; "
|
|
13
16
|
color_changing="color: rgb(33,33,255); "+backgroundcolor_changing
|
|
14
|
-
color_changing_black="color: rgb(0,0,0); "+backgroundcolor_changing
|
|
15
17
|
|
|
16
18
|
#********************************************* Operating Widgets
|
|
17
19
|
def setSS(b,style):
|
|
@@ -53,6 +55,9 @@ class MyQLineEdit(QtWidgets.QLineEdit):
|
|
|
53
55
|
def setup(self):
|
|
54
56
|
if not self.initFlag:
|
|
55
57
|
self.initFlag=True
|
|
58
|
+
self.FlagFocusIn=False
|
|
59
|
+
self.oldFont=None
|
|
60
|
+
self.oldStyle=None
|
|
56
61
|
font_changing = QtGui.QFont(self.font())
|
|
57
62
|
font_changing.setItalic(font_italic)
|
|
58
63
|
font_changing.setWeight(font_weight)
|
|
@@ -63,21 +68,17 @@ class MyQLineEdit(QtWidgets.QLineEdit):
|
|
|
63
68
|
if hasattr(b,'setStyleSheet'):
|
|
64
69
|
if hasStyleFlag:
|
|
65
70
|
if b.styleFlag: continue
|
|
66
|
-
b.flagS=True
|
|
67
71
|
b.initialStyle=b.styleSheet()+" "+backgroundcolor_none
|
|
68
72
|
b.setEnabled(False)
|
|
69
73
|
b.disabledStyle=b.styleSheet()
|
|
70
74
|
b.setEnabled(True)
|
|
71
75
|
b.setStyleSheet(setSS(b,b.initialStyle))
|
|
72
|
-
else:
|
|
73
|
-
b.flagS=False
|
|
74
76
|
if hasattr(b,'setFont'):
|
|
75
|
-
b.flagF=True
|
|
76
77
|
b.initialFont=b.font()
|
|
77
78
|
b.font_changing=font_changing
|
|
78
|
-
else:
|
|
79
|
-
b.flagF=False
|
|
80
79
|
if hasStyleFlag: b.styleFlag=True
|
|
80
|
+
self.CElabs=[w for w in self.bros if isinstance(w, ClickableEditLabel)]
|
|
81
|
+
self.CElabs_styles=[w.styleSheet() for w in self.CElabs]
|
|
81
82
|
|
|
82
83
|
def setup2(self):
|
|
83
84
|
if not self.initFlag2:
|
|
@@ -99,52 +100,84 @@ class MyQLineEdit(QtWidgets.QLineEdit):
|
|
|
99
100
|
self.setCompleterList()
|
|
100
101
|
|
|
101
102
|
def enterEvent(self, event):
|
|
102
|
-
|
|
103
|
-
|
|
103
|
+
if not self.hasFocus() and self.isEnabled():
|
|
104
|
+
self.oldFont=self.font()
|
|
105
|
+
self.oldStyle=self.styleSheet()
|
|
104
106
|
self.setFont(self.font_changing)
|
|
105
|
-
|
|
107
|
+
self.setStyleSheet(setSS(self,self.initialStyle+" "+backgroundcolor_hover))
|
|
108
|
+
for k,w in enumerate(self.CElabs):
|
|
109
|
+
self.CElabs_styles[k]=w.styleSheet()
|
|
110
|
+
w.setStyleSheet(w.styleSheet()+" "+f"""
|
|
111
|
+
ClickableEditLabel {{
|
|
112
|
+
{backgroundcolor_hover};
|
|
113
|
+
}}
|
|
114
|
+
""")
|
|
115
|
+
w.repaint()
|
|
116
|
+
super().enterEvent(event)
|
|
117
|
+
|
|
106
118
|
def leaveEvent(self, event):
|
|
119
|
+
if not self.hasFocus() and self.oldFont is not None:
|
|
120
|
+
self.setFont(self.oldFont)
|
|
121
|
+
self.setStyleSheet(self.oldStyle)
|
|
122
|
+
for k,w in enumerate(self.CElabs):
|
|
123
|
+
w.setStyleSheet(self.CElabs_styles[k])
|
|
124
|
+
w.repaint()
|
|
125
|
+
self.oldFont=None
|
|
126
|
+
self.oldStyle=None
|
|
107
127
|
super().leaveEvent(event)
|
|
108
|
-
if self.font()==self.font_changing and not self.hasFocus():
|
|
109
|
-
self.setFont(self.initialFont)
|
|
110
128
|
|
|
111
129
|
def focusInEvent(self, event):
|
|
112
130
|
super().focusInEvent(event)
|
|
113
131
|
for f in self.addfuncin:
|
|
114
132
|
self.addfuncin[f]()
|
|
115
133
|
self.focusInFun()
|
|
116
|
-
|
|
134
|
+
|
|
117
135
|
def setFocus(self):
|
|
118
136
|
super().setFocus()
|
|
119
137
|
self.focusInFun()
|
|
120
138
|
|
|
121
139
|
def focusInFun(self):
|
|
122
|
-
self.
|
|
123
|
-
|
|
140
|
+
self.setStyleFont(color_changing,self.font_changing)
|
|
141
|
+
|
|
142
|
+
def setStyleFont(self,color_changing,font):
|
|
124
143
|
for b in self.bros:
|
|
125
|
-
if (
|
|
126
|
-
|
|
144
|
+
if hasattr(b,'setInitalStyle') and hasattr(b,'FlagFocusIn') and b.FlagFocusIn:
|
|
145
|
+
b.setInitalStyle()
|
|
146
|
+
break
|
|
147
|
+
if not self.FlagFocusIn:
|
|
148
|
+
self.FlagFocusIn=True
|
|
149
|
+
self.setFont(font)
|
|
150
|
+
for b in self.bros:
|
|
151
|
+
if hasattr(b,'initialStyle'):
|
|
152
|
+
b.setStyleSheet(setSS(b,b.initialStyle+" "+color_changing))
|
|
127
153
|
|
|
128
154
|
def focusOutEvent(self, event):
|
|
129
155
|
super().focusOutEvent(event) #to preserve classical behaviour before adding the below
|
|
130
156
|
for f in self.addfuncout:
|
|
131
157
|
self.addfuncout[f]()
|
|
132
|
-
self.
|
|
158
|
+
self.setInitalStyle()
|
|
133
159
|
|
|
134
160
|
def clearFocus(self):
|
|
135
161
|
super().clearFocus()
|
|
136
|
-
self.
|
|
162
|
+
self.setInitalStyle()
|
|
137
163
|
|
|
138
|
-
def
|
|
139
|
-
|
|
140
|
-
|
|
164
|
+
def setInitalStyle(self):
|
|
165
|
+
if self.FlagFocusIn:
|
|
166
|
+
self.FlagFocusIn=False
|
|
167
|
+
for b in self.bros:
|
|
141
168
|
if hasattr(b,'default_stylesheet'):
|
|
142
169
|
b.setStyleSheet(b.default_stylesheet)
|
|
143
|
-
|
|
144
|
-
b.setStyleSheet(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
170
|
+
elif hasattr(b,'initialStyle'):
|
|
171
|
+
b.setStyleSheet(b.initialStyle)
|
|
172
|
+
if hasattr(b,'initialFont'):
|
|
173
|
+
b.setFont(b.initialFont)
|
|
174
|
+
for k,w in enumerate(self.CElabs):
|
|
175
|
+
self.CElabs_styles[k]=w.default_stylesheet
|
|
176
|
+
w.setStyleSheet(self.CElabs_styles[k])
|
|
177
|
+
w.repaint()
|
|
178
|
+
self.oldFont=None
|
|
179
|
+
self.oldStyle=None
|
|
180
|
+
#self.addlab.clear()
|
|
148
181
|
|
|
149
182
|
def showCompleter(self):
|
|
150
183
|
if self.completer():
|
|
@@ -185,11 +218,14 @@ class MyQSpin(QtWidgets.QSpinBox):
|
|
|
185
218
|
self.addfuncreturn={}
|
|
186
219
|
|
|
187
220
|
self.setAccelerated(True)
|
|
188
|
-
self.setGroupSeparatorShown(True)
|
|
221
|
+
self.setGroupSeparatorShown(True)
|
|
189
222
|
|
|
190
223
|
def setup(self):
|
|
191
224
|
if not self.initFlag:
|
|
192
225
|
self.initFlag=True
|
|
226
|
+
self.FlagFocusIn=False
|
|
227
|
+
self.oldFont=None
|
|
228
|
+
self.oldStyle=None
|
|
193
229
|
font_changing = QtGui.QFont(self.font())
|
|
194
230
|
font_changing.setItalic(font_italic)
|
|
195
231
|
font_changing.setWeight(font_weight)
|
|
@@ -200,15 +236,14 @@ class MyQSpin(QtWidgets.QSpinBox):
|
|
|
200
236
|
b.initialFont=b.font()
|
|
201
237
|
b.font_changing=font_changing
|
|
202
238
|
b.styleFlag=True
|
|
203
|
-
self.spinFontObj=[]
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
239
|
+
#self.spinFontObj = self.findChildren(QtWidgets.QLineEdit)[0]
|
|
240
|
+
#self.spinFontObj.initialStyle=self.spinFontObj.styleSheet()+" "+backgroundcolor_none
|
|
241
|
+
#self.spinFontObj.font_changing=font_changing
|
|
242
|
+
|
|
208
243
|
def setFocus(self):
|
|
209
244
|
super().setFocus()
|
|
210
245
|
self.focusInFun()
|
|
211
|
-
|
|
246
|
+
|
|
212
247
|
def focusInEvent(self, event):
|
|
213
248
|
super().focusInEvent(event) #to preserve classical behaviour before adding the below
|
|
214
249
|
for f in self.addfuncin:
|
|
@@ -216,23 +251,51 @@ class MyQSpin(QtWidgets.QSpinBox):
|
|
|
216
251
|
self.focusInFun()
|
|
217
252
|
|
|
218
253
|
def focusInFun(self):
|
|
219
|
-
if not self.
|
|
254
|
+
if not self.FlagFocusIn:
|
|
255
|
+
self.FlagFocusIn=True
|
|
256
|
+
#self.spinFontObj.setStyleSheet(self.spinFontObj.initialStyle+" "+color_changing)
|
|
220
257
|
for b in self.bros:
|
|
221
|
-
b.setStyleSheet(b.initialStyle+" "+color_changing)
|
|
222
|
-
b.setFont(b.font_changing)
|
|
223
|
-
for b in self.spinFontObj:
|
|
258
|
+
b.setStyleSheet(setSS(b,b.initialStyle+" "+color_changing))
|
|
224
259
|
b.setFont(self.font_changing)
|
|
225
260
|
|
|
261
|
+
def clearFocus(self):
|
|
262
|
+
super().clearFocus()
|
|
263
|
+
self.setInitalStyle()
|
|
264
|
+
|
|
226
265
|
def focusOutEvent(self, event):
|
|
227
266
|
super().focusOutEvent(event) #to preserve classical behaviour before adding the below
|
|
228
267
|
for f in self.addfuncout:
|
|
229
268
|
self.addfuncout[f]()
|
|
230
|
-
|
|
269
|
+
self.setInitalStyle()
|
|
270
|
+
|
|
271
|
+
def setInitalStyle(self):
|
|
272
|
+
if self.FlagFocusIn:
|
|
273
|
+
self.FlagFocusIn=False
|
|
274
|
+
#self.spinFontObj.setStyleSheet(self.spinFontObj.initialStyle)
|
|
231
275
|
for b in self.bros:
|
|
232
|
-
b.setStyleSheet(b.initialStyle)
|
|
233
|
-
b.setFont(
|
|
234
|
-
|
|
235
|
-
|
|
276
|
+
b.setStyleSheet(setSS(b,b.initialStyle))
|
|
277
|
+
b.setFont(self.initialFont)
|
|
278
|
+
self.findChildren(QtWidgets.QLineEdit)[0].setFont(self.initialFont)
|
|
279
|
+
self.oldFont=None
|
|
280
|
+
self.oldStyle=None
|
|
281
|
+
|
|
282
|
+
def enterEvent(self, event):
|
|
283
|
+
super().enterEvent(event)
|
|
284
|
+
if not self.hasFocus() and self.isEnabled():
|
|
285
|
+
self.oldFont=self.font()
|
|
286
|
+
self.setFont(self.font_changing)
|
|
287
|
+
b=self #b=self.spinFontObj
|
|
288
|
+
self.oldStyle=b.styleSheet()
|
|
289
|
+
b.setStyleSheet(setSS(b,b.initialStyle+" "+backgroundcolor_hover+" "+border_hover))
|
|
290
|
+
|
|
291
|
+
def leaveEvent(self, event):
|
|
292
|
+
super().leaveEvent(event)
|
|
293
|
+
if not self.hasFocus() and self.oldFont is not None:
|
|
294
|
+
self.setFont(self.oldFont)
|
|
295
|
+
b=self #b=self.spinFontObj
|
|
296
|
+
b.setStyleSheet(self.oldStyle)
|
|
297
|
+
self.oldFont=None
|
|
298
|
+
self.oldStyle=None
|
|
236
299
|
|
|
237
300
|
def keyPressEvent(self, event):
|
|
238
301
|
super().keyPressEvent(event)
|
|
@@ -284,6 +347,9 @@ class MyQDoubleSpin(QtWidgets.QDoubleSpinBox):
|
|
|
284
347
|
def setup(self):
|
|
285
348
|
if not self.initFlag:
|
|
286
349
|
self.initFlag=True
|
|
350
|
+
self.FlagFocusIn=False
|
|
351
|
+
self.oldFont=None
|
|
352
|
+
self.oldStyle=None
|
|
287
353
|
font_changing = QtGui.QFont(self.font())
|
|
288
354
|
font_changing.setItalic(font_italic)
|
|
289
355
|
font_changing.setWeight(font_weight)
|
|
@@ -294,33 +360,67 @@ class MyQDoubleSpin(QtWidgets.QDoubleSpinBox):
|
|
|
294
360
|
b.initialFont=b.font()
|
|
295
361
|
b.font_changing=font_changing
|
|
296
362
|
b.styleFlag=True
|
|
297
|
-
self.spinFontObj=[]
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
363
|
+
#self.spinFontObj = self.findChildren(QtWidgets.QLineEdit)[0]
|
|
364
|
+
#self.spinFontObj.initialStyle=self.spinFontObj.styleSheet()+" "+backgroundcolor_none
|
|
365
|
+
#self.spinFontObj.font_changing=font_changing
|
|
366
|
+
|
|
367
|
+
def setFocus(self):
|
|
368
|
+
super().setFocus()
|
|
369
|
+
self.focusInFun()
|
|
301
370
|
|
|
302
371
|
def focusInEvent(self, event):
|
|
303
372
|
super().focusInEvent(event) #to preserve classical behaviour before adding the below
|
|
304
373
|
for f in self.addfuncin:
|
|
305
374
|
self.addfuncin[f]()
|
|
306
|
-
|
|
375
|
+
self.focusInFun()
|
|
376
|
+
|
|
377
|
+
def focusInFun(self):
|
|
378
|
+
if not self.FlagFocusIn:
|
|
379
|
+
self.FlagFocusIn=True
|
|
380
|
+
#self.spinFontObj.setStyleSheet(self.spinFontObj.initialStyle+" "+color_changing)
|
|
307
381
|
for b in self.bros:
|
|
308
|
-
b.setStyleSheet(b.initialStyle+" "+color_changing)
|
|
309
|
-
b.setFont(self.font_changing)
|
|
310
|
-
for b in self.spinFontObj:
|
|
382
|
+
b.setStyleSheet(setSS(b,b.initialStyle+" "+color_changing))
|
|
311
383
|
b.setFont(self.font_changing)
|
|
312
384
|
|
|
385
|
+
def clearFocus(self):
|
|
386
|
+
super().clearFocus()
|
|
387
|
+
self.setInitalStyle()
|
|
388
|
+
|
|
313
389
|
def focusOutEvent(self, event):
|
|
314
390
|
super().focusOutEvent(event) #to preserve classical behaviour before adding the below
|
|
315
391
|
for f in self.addfuncout:
|
|
316
392
|
self.addfuncout[f]()
|
|
317
|
-
|
|
393
|
+
self.setInitalStyle()
|
|
394
|
+
|
|
395
|
+
def setInitalStyle(self):
|
|
396
|
+
if self.FlagFocusIn:
|
|
397
|
+
self.FlagFocusIn=False
|
|
398
|
+
#self.spinFontObj.setStyleSheet(self.spinFontObj.initialStyle)
|
|
318
399
|
for b in self.bros:
|
|
319
|
-
b.setStyleSheet(b.initialStyle)
|
|
320
|
-
b.setFont(b.initialFont)
|
|
321
|
-
for b in self.spinFontObj:
|
|
400
|
+
b.setStyleSheet(setSS(b,b.initialStyle))
|
|
322
401
|
b.setFont(self.initialFont)
|
|
323
|
-
|
|
402
|
+
self.findChildren(QtWidgets.QLineEdit)[0].setFont(self.initialFont)
|
|
403
|
+
self.oldFont=None
|
|
404
|
+
self.oldStyle=None
|
|
405
|
+
|
|
406
|
+
def enterEvent(self, event):
|
|
407
|
+
super().enterEvent(event)
|
|
408
|
+
if not self.hasFocus() and self.isEnabled():
|
|
409
|
+
self.oldFont=self.font()
|
|
410
|
+
self.setFont(self.font_changing)
|
|
411
|
+
b=self #b=self.spinFontObj
|
|
412
|
+
self.oldStyle=b.styleSheet()
|
|
413
|
+
b.setStyleSheet(setSS(b,b.initialStyle+" "+backgroundcolor_hover+" "+border_hover))
|
|
414
|
+
|
|
415
|
+
def leaveEvent(self, event):
|
|
416
|
+
super().leaveEvent(event)
|
|
417
|
+
if not self.hasFocus() and self.oldFont is not None:
|
|
418
|
+
self.setFont(self.oldFont)
|
|
419
|
+
b=self #b=self.spinFontObj
|
|
420
|
+
b.setStyleSheet(self.oldStyle)
|
|
421
|
+
self.oldFont=None
|
|
422
|
+
self.oldStyle=None
|
|
423
|
+
|
|
324
424
|
def keyPressEvent(self, event):
|
|
325
425
|
super().keyPressEvent(event)
|
|
326
426
|
if event.key() in (Qt.Key.Key_Return,Qt.Key.Key_Enter) and self.hasFocus():
|
|
@@ -366,6 +466,7 @@ class CollapsibleBox(QtWidgets.QWidget):
|
|
|
366
466
|
|
|
367
467
|
if self.toggle_button is None:
|
|
368
468
|
self.toggle_button=self.findChild(QtWidgets.QToolButton)
|
|
469
|
+
self.toggle_button.setObjectName("CollapsibleBox_toggle")
|
|
369
470
|
self.toggle_button.setChecked(InitCheck)
|
|
370
471
|
self.toggle_button.clicked.connect(self.on_click)
|
|
371
472
|
self.toggle_button.setCursor(QtCore.Qt.CursorShape.PointingHandCursor)
|
|
@@ -579,6 +680,7 @@ class RichTextPushButton(QPushButton):
|
|
|
579
680
|
|
|
580
681
|
self.lyt=self.__lyt
|
|
581
682
|
self.lbl=self.__lbl
|
|
683
|
+
self.icnWidget=self.__icon
|
|
582
684
|
self.icn=None
|
|
583
685
|
return
|
|
584
686
|
|
|
@@ -682,8 +784,8 @@ class ClickableLabel(QLabel):
|
|
|
682
784
|
def __init__(self, *args):
|
|
683
785
|
super().__init__(*args)
|
|
684
786
|
|
|
685
|
-
self.default_stylesheet = self.styleSheet()
|
|
686
|
-
self.highlight_stylesheet = "background-color:
|
|
787
|
+
self.default_stylesheet = self.styleSheet()
|
|
788
|
+
self.highlight_stylesheet = "background-color: rgba(0, 116, 255, 0.1); border-radius: 3px;"
|
|
687
789
|
|
|
688
790
|
self.timer = QTimer(self)
|
|
689
791
|
self.timer.timeout.connect(self.resetHighlight)
|
|
@@ -703,6 +805,7 @@ class ClickableLabel(QLabel):
|
|
|
703
805
|
warningDialog(self.window(),Message=self.toolTip(),pixmap=pixmap,title='Info')
|
|
704
806
|
|
|
705
807
|
def highlight(self):
|
|
808
|
+
self.default_stylesheet = self.styleSheet() # <-- capture current style
|
|
706
809
|
self.setStyleSheet(self.highlight_stylesheet)
|
|
707
810
|
self.repaint()
|
|
708
811
|
|
|
@@ -719,12 +822,17 @@ class ClickableLabel(QLabel):
|
|
|
719
822
|
|
|
720
823
|
class ClickableEditLabel(ClickableLabel):
|
|
721
824
|
def setup(self):
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
825
|
+
le = QLineEdit()
|
|
826
|
+
bg = le.palette().color(QPalette.Base)
|
|
827
|
+
bg_rgba = f"rgba({bg.red()}, {bg.green()}, {bg.blue()}, {bg.alpha()})"
|
|
828
|
+
|
|
829
|
+
self.default_stylesheet = self.styleSheet() + f"""
|
|
830
|
+
ClickableEditLabel {{
|
|
831
|
+
background-color: {bg_rgba};
|
|
832
|
+
}}
|
|
833
|
+
"""
|
|
726
834
|
self.setStyleSheet(self.default_stylesheet)
|
|
727
|
-
|
|
835
|
+
le.setParent(None)
|
|
728
836
|
|
|
729
837
|
class CustomLineEdit(QLineEdit):
|
|
730
838
|
cancelEditing = Signal()
|
|
@@ -837,6 +945,238 @@ class EditableLabel(QWidget):
|
|
|
837
945
|
self.label.show()
|
|
838
946
|
self.updateLabel()
|
|
839
947
|
|
|
948
|
+
def setButtonHoverStyle(w:QWidget,FlagBorder=True,borderRadius=6,FlagCls=True):
|
|
949
|
+
if FlagCls:
|
|
950
|
+
cls = w.metaObject().className()
|
|
951
|
+
base = w.styleSheet() or ""
|
|
952
|
+
if cls not in base: base=f"{cls} {{" +f"{base}"+"}"
|
|
953
|
+
if base and not base.endswith("\n"):
|
|
954
|
+
base += "\n"
|
|
955
|
+
else: cls=base=''
|
|
956
|
+
|
|
957
|
+
""""
|
|
958
|
+
style = (
|
|
959
|
+
f"{cls}:hover {{"
|
|
960
|
+
"background: qlineargradient("
|
|
961
|
+
"x1:0, y1:0, x2:0, y2:1, "
|
|
962
|
+
"stop:0 rgba(0, 116, 255, 0.05), "
|
|
963
|
+
"stop:0.2 rgba(0, 116, 255, 0.15), "
|
|
964
|
+
"stop:0.8 rgba(0, 116, 255, 0.15), "
|
|
965
|
+
"stop:1 rgba(0, 116, 255, 0.05));"
|
|
966
|
+
f"border-radius: {borderRadius}px;"
|
|
967
|
+
f"{'border: 1px solid gray;' if FlagBorder else ''}"
|
|
968
|
+
"padding: 2px 2px;"
|
|
969
|
+
"}"
|
|
970
|
+
)
|
|
971
|
+
"""
|
|
972
|
+
|
|
973
|
+
style = (
|
|
974
|
+
f"{cls}:hover {{"
|
|
975
|
+
f"border-radius: {borderRadius}px;"
|
|
976
|
+
f"background-color: none;"
|
|
977
|
+
f"{'border: 1px solid gray;' if FlagBorder else ''}"
|
|
978
|
+
"padding: 2px 2px;"
|
|
979
|
+
"}"
|
|
980
|
+
)
|
|
981
|
+
|
|
982
|
+
w.setStyleSheet(base + style)
|
|
983
|
+
|
|
984
|
+
def apply_hover_glow_label(
|
|
985
|
+
w: QLabel,
|
|
986
|
+
*,
|
|
987
|
+
color="#0051FF",
|
|
988
|
+
blur=18,
|
|
989
|
+
max_alpha=170,
|
|
990
|
+
duration_ms=160,
|
|
991
|
+
):
|
|
992
|
+
if getattr(w, "_hoverGlowInstalled", False):
|
|
993
|
+
w._hoverGlowColor = QColor(color)
|
|
994
|
+
w._hoverGlowBlur = float(blur)
|
|
995
|
+
w._hoverGlowMaxAlpha = int(max_alpha)
|
|
996
|
+
w._hoverGlowDuration = int(duration_ms)
|
|
997
|
+
w._hoverGlowEffect.setBlurRadius(w._hoverGlowBlur)
|
|
998
|
+
return
|
|
999
|
+
|
|
1000
|
+
w._hoverGlowInstalled = True
|
|
1001
|
+
w._hoverGlowColor = QColor(color)
|
|
1002
|
+
w._hoverGlowBlur = float(blur)
|
|
1003
|
+
w._hoverGlowMaxAlpha = int(max_alpha)
|
|
1004
|
+
w._hoverGlowDuration = int(duration_ms)
|
|
1005
|
+
|
|
1006
|
+
eff = QGraphicsDropShadowEffect(w)
|
|
1007
|
+
eff.setOffset(0, 0)
|
|
1008
|
+
eff.setBlurRadius(w._hoverGlowBlur)
|
|
1009
|
+
|
|
1010
|
+
c = QColor(w._hoverGlowColor)
|
|
1011
|
+
c.setAlpha(0)
|
|
1012
|
+
eff.setColor(c)
|
|
1013
|
+
|
|
1014
|
+
w.setGraphicsEffect(eff)
|
|
1015
|
+
w._hoverGlowEffect = eff
|
|
1016
|
+
|
|
1017
|
+
def _set_alpha(val):
|
|
1018
|
+
col = QColor(w._hoverGlowColor)
|
|
1019
|
+
col.setAlpha(int(val))
|
|
1020
|
+
w._hoverGlowEffect.setColor(col)
|
|
1021
|
+
|
|
1022
|
+
# ✅ Animate a plain value (no Qt property needed)
|
|
1023
|
+
w._hoverGlowAnimAlpha = QVariantAnimation(w)
|
|
1024
|
+
w._hoverGlowAnimAlpha.setEasingCurve(QEasingCurve.OutCubic)
|
|
1025
|
+
w._hoverGlowAnimAlpha.valueChanged.connect(_set_alpha)
|
|
1026
|
+
|
|
1027
|
+
class _GlowFilter(QObject):
|
|
1028
|
+
def eventFilter(self, obj, ev):
|
|
1029
|
+
if obj is not w:
|
|
1030
|
+
return False
|
|
1031
|
+
|
|
1032
|
+
t = ev.type()
|
|
1033
|
+
if t in (QEvent.Enter, QEvent.HoverEnter):
|
|
1034
|
+
w._hoverGlowAnimAlpha.stop()
|
|
1035
|
+
w._hoverGlowAnimAlpha.setDuration(w._hoverGlowDuration)
|
|
1036
|
+
w._hoverGlowAnimAlpha.setStartValue(w._hoverGlowEffect.color().alpha())
|
|
1037
|
+
w._hoverGlowAnimAlpha.setEndValue(w._hoverGlowMaxAlpha)
|
|
1038
|
+
w._hoverGlowAnimAlpha.start()
|
|
1039
|
+
|
|
1040
|
+
elif t in (QEvent.Leave, QEvent.HoverLeave):
|
|
1041
|
+
w._hoverGlowAnimAlpha.stop()
|
|
1042
|
+
w._hoverGlowAnimAlpha.setDuration(w._hoverGlowDuration)
|
|
1043
|
+
w._hoverGlowAnimAlpha.setStartValue(w._hoverGlowEffect.color().alpha())
|
|
1044
|
+
w._hoverGlowAnimAlpha.setEndValue(0)
|
|
1045
|
+
w._hoverGlowAnimAlpha.start()
|
|
1046
|
+
|
|
1047
|
+
return False
|
|
1048
|
+
|
|
1049
|
+
w._hoverGlowFilter = _GlowFilter(w)
|
|
1050
|
+
w.installEventFilter(w._hoverGlowFilter)
|
|
1051
|
+
|
|
1052
|
+
w.setAttribute(Qt.WA_Hover, True)
|
|
1053
|
+
w.setMouseTracking(True)
|
|
1054
|
+
|
|
1055
|
+
def remove_hover_glow_label(w: QLabel):
|
|
1056
|
+
"""Removes the hover glow behavior and restores a clean state."""
|
|
1057
|
+
if not getattr(w, "_hoverGlowInstalled", False):
|
|
1058
|
+
return
|
|
1059
|
+
|
|
1060
|
+
# Stop animation cleanly
|
|
1061
|
+
anim = getattr(w, "_hoverGlowAnimAlpha", None)
|
|
1062
|
+
if anim is not None:
|
|
1063
|
+
anim.stop()
|
|
1064
|
+
|
|
1065
|
+
# Remove event filter
|
|
1066
|
+
filt = getattr(w, "_hoverGlowFilter", None)
|
|
1067
|
+
if filt is not None:
|
|
1068
|
+
try:
|
|
1069
|
+
w.removeEventFilter(filt)
|
|
1070
|
+
except RuntimeError:
|
|
1071
|
+
pass
|
|
1072
|
+
|
|
1073
|
+
# Remove graphics effect
|
|
1074
|
+
w.setGraphicsEffect(None)
|
|
1075
|
+
|
|
1076
|
+
# Restore hover-related flags (safe defaults)
|
|
1077
|
+
w.setAttribute(Qt.WA_Hover, False)
|
|
1078
|
+
w.setMouseTracking(False)
|
|
1079
|
+
|
|
1080
|
+
# Cleanup attributes
|
|
1081
|
+
for attr in (
|
|
1082
|
+
"_hoverGlowInstalled",
|
|
1083
|
+
"_hoverGlowColor",
|
|
1084
|
+
"_hoverGlowBlur",
|
|
1085
|
+
"_hoverGlowMaxAlpha",
|
|
1086
|
+
"_hoverGlowDuration",
|
|
1087
|
+
"_hoverGlowEffect",
|
|
1088
|
+
"_hoverGlowAnimAlpha",
|
|
1089
|
+
"_hoverGlowFilter",
|
|
1090
|
+
):
|
|
1091
|
+
if hasattr(w, attr):
|
|
1092
|
+
delattr(w, attr)
|
|
1093
|
+
|
|
1094
|
+
class SliderHandleCursorFilter(QObject):
|
|
1095
|
+
def eventFilter(self, obj, event):
|
|
1096
|
+
if isinstance(obj, QSlider) and event.type() == QEvent.MouseMove:
|
|
1097
|
+
|
|
1098
|
+
opt = QStyleOptionSlider()
|
|
1099
|
+
obj.initStyleOption(opt)
|
|
1100
|
+
|
|
1101
|
+
handle_rect = obj.style().subControlRect(
|
|
1102
|
+
QStyle.CC_Slider,
|
|
1103
|
+
opt,
|
|
1104
|
+
QStyle.SC_SliderHandle,
|
|
1105
|
+
obj
|
|
1106
|
+
)
|
|
1107
|
+
|
|
1108
|
+
if handle_rect.contains(event.position().toPoint()):
|
|
1109
|
+
obj.setCursor(QCursor(Qt.OpenHandCursor))
|
|
1110
|
+
else:
|
|
1111
|
+
obj.unsetCursor()
|
|
1112
|
+
|
|
1113
|
+
return False
|
|
1114
|
+
|
|
1115
|
+
|
|
1116
|
+
def changes(self,TabType,filename,title=" Changes"):
|
|
1117
|
+
FlagShow=False
|
|
1118
|
+
if self.logChanges:
|
|
1119
|
+
if self.logChanges.isVisible():
|
|
1120
|
+
FlagShow=True
|
|
1121
|
+
if FlagShow:
|
|
1122
|
+
self.logChanges.hide()
|
|
1123
|
+
self.logChanges.show()
|
|
1124
|
+
else:
|
|
1125
|
+
self.logChanges=TabType(self,True)
|
|
1126
|
+
self.logChanges.resize(720,720)
|
|
1127
|
+
self.logChanges.show()
|
|
1128
|
+
self.logChanges.ui.progress_Proc.hide()
|
|
1129
|
+
self.logChanges.ui.button_close_tab.hide()
|
|
1130
|
+
icon=QPixmap(''+ icons_path +'news.png')
|
|
1131
|
+
self.logChanges.ui.icon.setPixmap(icon)
|
|
1132
|
+
apply_hover_glow_label(self.logChanges.ui.icon)
|
|
1133
|
+
self.logChanges.setWindowIcon(self.windowIcon())
|
|
1134
|
+
self.logChanges.setWindowTitle(title)
|
|
1135
|
+
self.logChanges.ui.name_tab.setText(title)
|
|
1136
|
+
|
|
1137
|
+
self.logChanges.ui.log.setLineWrapColumnOrWidth(self.logChanges.ui.log.width()-20)
|
|
1138
|
+
base="""
|
|
1139
|
+
QTextEdit {
|
|
1140
|
+
border: 1px solid #2a2a2a;
|
|
1141
|
+
border-radius: 6px;
|
|
1142
|
+
|
|
1143
|
+
padding: 2px;
|
|
1144
|
+
|
|
1145
|
+
selection-background-color: #0051FF;
|
|
1146
|
+
selection-color: #FFFFFF;
|
|
1147
|
+
}
|
|
1148
|
+
"""
|
|
1149
|
+
self.logChanges.ui.log.setStyleSheet(base+"\n"+gPaIRS_QMenu_style)
|
|
1150
|
+
|
|
1151
|
+
def setFontPixelSize(logChanges:type(self.logChanges),fPixSize):
|
|
1152
|
+
logfont=self.font()
|
|
1153
|
+
logfont.setFamily(fontName)
|
|
1154
|
+
logfont.setPixelSize(fPixSize+2)
|
|
1155
|
+
logChanges.ui.log.setFont(logfont)
|
|
1156
|
+
fPixSize_TabNames=min([fPixSize*2,30])
|
|
1157
|
+
lab=logChanges.ui.name_tab
|
|
1158
|
+
font=lab.font()
|
|
1159
|
+
font.setPixelSize(fPixSize_TabNames)
|
|
1160
|
+
lab.setFont(font)
|
|
1161
|
+
self.logChanges.setFontPixelSize=lambda fS: setFontPixelSize(self.logChanges,fS)
|
|
1162
|
+
self.logChanges.setFontPixelSize(self.TABpar.fontPixelSize)
|
|
1163
|
+
def logResizeEvent(logChanges:type(self.logChanges),e):
|
|
1164
|
+
super(type(logChanges),logChanges).resizeEvent(e)
|
|
1165
|
+
logChanges.ui.log.setLineWrapColumnOrWidth(logChanges.ui.log.width()-20)
|
|
1166
|
+
self.logChanges.ui.log.resizeEvent=lambda e: logResizeEvent(self.logChanges,e)
|
|
1167
|
+
|
|
1168
|
+
self.logChanges.ui.icon.addfuncclick['whatsnew']=self.whatsNew
|
|
1169
|
+
self.logChanges.ui.icon.setCustomCursor()
|
|
1170
|
+
|
|
1171
|
+
try:
|
|
1172
|
+
file = open(filename, "rb")
|
|
1173
|
+
content = file.read().decode("utf-8")
|
|
1174
|
+
self.logChanges.ui.log.setText(content)
|
|
1175
|
+
file.close()
|
|
1176
|
+
except Exception as inst:
|
|
1177
|
+
pri.Error.red(f'There was a problem while reading the file {filename}:\n{inst}')
|
|
1178
|
+
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__}.')
|
|
1179
|
+
return
|
|
840
1180
|
|
|
841
1181
|
#********************************************* Matplotlib
|
|
842
1182
|
import io
|
|
@@ -988,6 +1328,7 @@ class MplCanvas(FigureCanvasQTAgg):
|
|
|
988
1328
|
fig2.lbl:QLabel=lbl
|
|
989
1329
|
def contextMenuEventFig2(event):
|
|
990
1330
|
contextMenu = QMenu()
|
|
1331
|
+
contextMenu.setStyleSheet(self.parent().parent().gui.ui.menu.styleSheet())
|
|
991
1332
|
copy2clipboard = contextMenu.addAction("Copy to clipboard ("+QS_copy2clipboard.key().toString(QKeySequence.NativeText)+")")
|
|
992
1333
|
contextMenu.addSeparator()
|
|
993
1334
|
scaleDown = contextMenu.addAction("Scale down ("+QS_scaleDown.key().toString(QKeySequence.NativeText)+")")
|
|
@@ -1039,7 +1380,7 @@ class MplCanvas(FigureCanvasQTAgg):
|
|
|
1039
1380
|
"""
|
|
1040
1381
|
|
|
1041
1382
|
def showTip(self,obj,message):
|
|
1042
|
-
|
|
1383
|
+
show_mouse_tooltip(obj,message)
|
|
1043
1384
|
|
|
1044
1385
|
def posWindow(self,ind):
|
|
1045
1386
|
w=h=0
|
|
@@ -1115,12 +1456,12 @@ def setAppGuiPalette(self:QWidget,palette:QPalette=None):
|
|
|
1115
1456
|
c.setPalette(palette)
|
|
1116
1457
|
if hasattr(c,'initialStyle') and hasattr(c, 'setStyleSheet'):
|
|
1117
1458
|
c.setStyleSheet(c.initialStyle)
|
|
1118
|
-
for c in f.findChildren(
|
|
1119
|
-
c
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1459
|
+
for c in f.findChildren(MyQLineEdit):
|
|
1460
|
+
c.initFlag=False
|
|
1461
|
+
c.styleFlag=False
|
|
1462
|
+
c.setup()
|
|
1463
|
+
for c in f.findChildren(ClickableEditLabel):
|
|
1464
|
+
c.setup()
|
|
1124
1465
|
for c in f.findChildren(QObject):
|
|
1125
1466
|
if hasattr(c,'setup2'):
|
|
1126
1467
|
c.initFlag2=False
|
|
@@ -1131,3 +1472,162 @@ def setAppGuiPalette(self:QWidget,palette:QPalette=None):
|
|
|
1131
1472
|
if hasattr(self,'w_Vis'): self.w_Vis.addPlotToolBar()
|
|
1132
1473
|
except:
|
|
1133
1474
|
pri.Error.red("***** Error while setting the application palette! *****")
|
|
1475
|
+
|
|
1476
|
+
|
|
1477
|
+
class Toast(QFrame):
|
|
1478
|
+
"""
|
|
1479
|
+
Tooltip-like custom toast that appears at the current mouse cursor position.
|
|
1480
|
+
Non-native, does not steal focus. Auto-hides after timeout_ms.
|
|
1481
|
+
"""
|
|
1482
|
+
|
|
1483
|
+
def __init__(
|
|
1484
|
+
self,
|
|
1485
|
+
parent: QWidget,
|
|
1486
|
+
msg: str,
|
|
1487
|
+
*,
|
|
1488
|
+
timeout_ms: int = 2500,
|
|
1489
|
+
offset: QPoint = QPoint(10, 15), # offset from cursor
|
|
1490
|
+
min_width: int = 0,
|
|
1491
|
+
max_width: int = 460,
|
|
1492
|
+
fade_in_ms: int = 80,
|
|
1493
|
+
fade_out_ms: int = 130,
|
|
1494
|
+
):
|
|
1495
|
+
super().__init__(parent)
|
|
1496
|
+
|
|
1497
|
+
self.setObjectName("PaIRSToast")
|
|
1498
|
+
self.setWindowFlags(Qt.FramelessWindowHint | Qt.ToolTip)
|
|
1499
|
+
#self.setAttribute(Qt.WA_TranslucentBackground, True)
|
|
1500
|
+
self.setAttribute(Qt.WA_ShowWithoutActivating, True)
|
|
1501
|
+
|
|
1502
|
+
self._label = QLabel(msg, self)
|
|
1503
|
+
self._label.setObjectName("PaIRSToastLabel")
|
|
1504
|
+
self._label.setWordWrap(True)
|
|
1505
|
+
|
|
1506
|
+
lay = QHBoxLayout(self)
|
|
1507
|
+
lay.setContentsMargins(4,3,4,3)
|
|
1508
|
+
lay.addWidget(self._label)
|
|
1509
|
+
|
|
1510
|
+
# Classic tooltip-like styling
|
|
1511
|
+
self.setStyleSheet("""
|
|
1512
|
+
QFrame#PaIRSToast {
|
|
1513
|
+
background-color: #ffffdc; /* classic tooltip-ish */
|
|
1514
|
+
color: #000000;
|
|
1515
|
+
border: 1px solid rgba(0, 0, 0, 0.45);
|
|
1516
|
+
border-radius: 4px;
|
|
1517
|
+
}
|
|
1518
|
+
QLabel#PaIRSToastLabel {
|
|
1519
|
+
color: #000000;
|
|
1520
|
+
}
|
|
1521
|
+
""")
|
|
1522
|
+
|
|
1523
|
+
# Width clamp + nice wrapping
|
|
1524
|
+
# Reset any previous constraints (important if a previous tooltip was wider)
|
|
1525
|
+
self.setMinimumSize(min_width, 0)
|
|
1526
|
+
self.setMaximumSize(max_width, 16777215)
|
|
1527
|
+
|
|
1528
|
+
self._label.setMinimumSize(min_width, 0)
|
|
1529
|
+
self._label.setMaximumSize(max_width, 16777215)
|
|
1530
|
+
|
|
1531
|
+
# Make sure the label doesn't "expand"
|
|
1532
|
+
self._label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
|
|
1533
|
+
|
|
1534
|
+
font=self.window().font()
|
|
1535
|
+
self._label.setFont(font)
|
|
1536
|
+
self._apply_size(msg)
|
|
1537
|
+
|
|
1538
|
+
# Position at cursor (global)
|
|
1539
|
+
self._move_to_cursor(offset)
|
|
1540
|
+
|
|
1541
|
+
# Opacity animation
|
|
1542
|
+
self.setWindowOpacity(0.0)
|
|
1543
|
+
self._anim = QPropertyAnimation(self, b"windowOpacity", self)
|
|
1544
|
+
self._anim.setEasingCurve(QEasingCurve.OutCubic)
|
|
1545
|
+
|
|
1546
|
+
# Auto hide
|
|
1547
|
+
self._timer = QTimer(self)
|
|
1548
|
+
self._timer.setSingleShot(True)
|
|
1549
|
+
self._timer.timeout.connect(lambda: self.fade_out(duration_ms=fade_out_ms))
|
|
1550
|
+
|
|
1551
|
+
self.show()
|
|
1552
|
+
self.raise_()
|
|
1553
|
+
self.fade_in(duration_ms=fade_in_ms)
|
|
1554
|
+
self._timer.start(timeout_ms)
|
|
1555
|
+
|
|
1556
|
+
def _apply_size(self, msg: str):
|
|
1557
|
+
self._label.setText(msg)
|
|
1558
|
+
|
|
1559
|
+
# Let QLabel compute the correct wrapped size
|
|
1560
|
+
self._label.adjustSize()
|
|
1561
|
+
sh = self._label.sizeHint()
|
|
1562
|
+
|
|
1563
|
+
# Lock label to its real hint size
|
|
1564
|
+
self._label.setFixedSize(sh)
|
|
1565
|
+
|
|
1566
|
+
# Now shrink the frame to content + margins
|
|
1567
|
+
self.adjustSize()
|
|
1568
|
+
|
|
1569
|
+
# Lock the whole toaster too (prevents extra blank area)
|
|
1570
|
+
self.setFixedSize(self.sizeHint())
|
|
1571
|
+
|
|
1572
|
+
def _move_to_cursor(self, offset: QPoint):
|
|
1573
|
+
parent = self.parent()
|
|
1574
|
+
if hasattr(parent, "cursorRect"):
|
|
1575
|
+
rect = parent.cursorRect() # QRect in coordinate del widget
|
|
1576
|
+
p = parent.mapToGlobal(rect.bottomRight())
|
|
1577
|
+
else:
|
|
1578
|
+
p = QCursor.pos() + offset
|
|
1579
|
+
|
|
1580
|
+
# Keep inside the current screen geometry
|
|
1581
|
+
screen = self.screen()
|
|
1582
|
+
if screen is None:
|
|
1583
|
+
self.move(p)
|
|
1584
|
+
return
|
|
1585
|
+
|
|
1586
|
+
geo = screen.availableGeometry()
|
|
1587
|
+
self.adjustSize()
|
|
1588
|
+
w, h = self.width(), self.height()
|
|
1589
|
+
|
|
1590
|
+
x = p.x()
|
|
1591
|
+
y = p.y()
|
|
1592
|
+
|
|
1593
|
+
if x + w > geo.right():
|
|
1594
|
+
x = geo.right() - w
|
|
1595
|
+
if y + h > geo.bottom():
|
|
1596
|
+
y = geo.bottom() - h
|
|
1597
|
+
if x < geo.left():
|
|
1598
|
+
x = geo.left()
|
|
1599
|
+
if y < geo.top():
|
|
1600
|
+
y = geo.top()
|
|
1601
|
+
|
|
1602
|
+
self.move(QPoint(x, y))
|
|
1603
|
+
|
|
1604
|
+
def fade_in(self, *, duration_ms: int = 80):
|
|
1605
|
+
self._anim.stop()
|
|
1606
|
+
self._anim.setDuration(duration_ms)
|
|
1607
|
+
self._anim.setStartValue(self.windowOpacity())
|
|
1608
|
+
self._anim.setEndValue(1.0)
|
|
1609
|
+
self._anim.start()
|
|
1610
|
+
|
|
1611
|
+
def fade_out(self, *, duration_ms: int = 130):
|
|
1612
|
+
self._anim.stop()
|
|
1613
|
+
self._anim.setDuration(duration_ms)
|
|
1614
|
+
self._anim.setStartValue(self.windowOpacity())
|
|
1615
|
+
self._anim.setEndValue(0.0)
|
|
1616
|
+
self._anim.finished.connect(self.close)
|
|
1617
|
+
self._anim.start()
|
|
1618
|
+
|
|
1619
|
+
def show_mouse_tooltip(parent: QWidget, msg: str, *, timeout_ms: int = 2500):
|
|
1620
|
+
"""
|
|
1621
|
+
Convenience function: show a tooltip-like toaster at the mouse cursor.
|
|
1622
|
+
Keeps a reference on parent to avoid garbage collection.
|
|
1623
|
+
"""
|
|
1624
|
+
old = getattr(parent, "_pairs_mouse_toaster", None)
|
|
1625
|
+
if old is not None and old.isVisible():
|
|
1626
|
+
old.close()
|
|
1627
|
+
|
|
1628
|
+
if msg:
|
|
1629
|
+
t = Toast(parent, msg, timeout_ms=timeout_ms)
|
|
1630
|
+
else: t=None
|
|
1631
|
+
parent._pairs_mouse_toaster = t
|
|
1632
|
+
return t
|
|
1633
|
+
|