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/Explorer.py
CHANGED
|
@@ -14,11 +14,11 @@ MONTH_ABBREVIATIONS = {
|
|
|
14
14
|
1: "Jan", 2: "Feb", 3: "Mar", 4: "Apr", 5: "May", 6: "Jun",
|
|
15
15
|
7: "Jul", 8: "Aug", 9: "Sep", StepTypes.cal: "Oct", 11: "Nov", 12: "Dec"
|
|
16
16
|
}
|
|
17
|
-
projectActionButtonSize=[20,
|
|
18
|
-
processActionButtonSize=[20,
|
|
17
|
+
projectActionButtonSize=[20,25]
|
|
18
|
+
processActionButtonSize=[20,25]
|
|
19
19
|
actionButtonSpacing=3
|
|
20
|
-
processButtonSize=[40,
|
|
21
|
-
stepButtonSize=[32,
|
|
20
|
+
processButtonSize=[40,50] #icon, button
|
|
21
|
+
stepButtonSize=[32,40]
|
|
22
22
|
headerHeight=24
|
|
23
23
|
titleHeight=22
|
|
24
24
|
subtitleHeight=14
|
|
@@ -323,12 +323,28 @@ class ModernSwitch(QWidget):
|
|
|
323
323
|
self._checked = True
|
|
324
324
|
par.FlagQueue=self._checked
|
|
325
325
|
|
|
326
|
+
# --- HOVER SETUP ---
|
|
327
|
+
self.setAttribute(Qt.WA_Hover, True)
|
|
328
|
+
self.setMouseTracking(True)
|
|
329
|
+
self._hovered = False
|
|
330
|
+
self._border_width = 1
|
|
331
|
+
self._border_width_hover = 2
|
|
332
|
+
self._border_color = QColor(0, 0, 0)
|
|
333
|
+
self._border_color_hover = QColor(240, 116, 35) # highlight
|
|
334
|
+
|
|
326
335
|
# Load image for the handle and scale it to fit the ellipse
|
|
327
336
|
self.handle_image = QPixmap(icons_path+"gear.png") # Replace with your image path
|
|
328
337
|
self.handle_image = self.handle_image.scaledToHeight(self.height() - self.handleMargin*2, Qt.SmoothTransformation)
|
|
329
338
|
|
|
330
339
|
self.setCursor(QCursor(QtCore.Qt.PointingHandCursor))
|
|
331
340
|
self.FlagAnimation=False
|
|
341
|
+
|
|
342
|
+
self.FlagRunning = False
|
|
343
|
+
self.gearMovie: QMovie = None
|
|
344
|
+
|
|
345
|
+
self._bg_color = QColor(46, 204, 113) if self._checked else QColor(175, 175, 175, 128)
|
|
346
|
+
self._handle_position = 0 # inizializzato in setSwitchLayout()
|
|
347
|
+
|
|
332
348
|
self.setSwitchLayout()
|
|
333
349
|
|
|
334
350
|
self.animation = QPropertyAnimation(self, b"handle_position", self)
|
|
@@ -357,20 +373,35 @@ class ModernSwitch(QWidget):
|
|
|
357
373
|
if par and self.gui.procdata:
|
|
358
374
|
if self.gui.procdata.ind[:-2]==par.ind[:-2]:
|
|
359
375
|
self.startTimer()
|
|
360
|
-
#self.timer.start(50) # Aggiorna ogni 50 ms
|
|
361
376
|
|
|
377
|
+
# ----------------- Hover events -----------------
|
|
378
|
+
def enterEvent(self, event):
|
|
379
|
+
self._hovered = True
|
|
380
|
+
self.update()
|
|
381
|
+
super().enterEvent(event)
|
|
382
|
+
|
|
383
|
+
def leaveEvent(self, event):
|
|
384
|
+
self._hovered = False
|
|
385
|
+
self.update()
|
|
386
|
+
super().leaveEvent(event)
|
|
387
|
+
|
|
388
|
+
# ----------------- Timer control -----------------
|
|
362
389
|
def startTimer(self):
|
|
363
390
|
if not self.FlagRunning and hasattr(self.gui,'gearMovie'):
|
|
364
391
|
self.FlagRunning=True
|
|
365
392
|
self.gearMovie=self.gui.gearMovie
|
|
366
393
|
self.timer.start(self.timerTime)
|
|
367
|
-
|
|
394
|
+
try:
|
|
395
|
+
pri.Coding.yellow('Start switch timer')
|
|
396
|
+
except Exception:
|
|
397
|
+
pass
|
|
368
398
|
|
|
369
399
|
def stopTimer(self):
|
|
370
400
|
if self.FlagRunning:
|
|
371
401
|
self.FlagRunning=False
|
|
372
402
|
self.timer.stop()
|
|
373
403
|
|
|
404
|
+
# ----------------- Property animation -----------------
|
|
374
405
|
def set_handle_position(self, pos):
|
|
375
406
|
self._handle_position = pos
|
|
376
407
|
self.update()
|
|
@@ -380,90 +411,98 @@ class ModernSwitch(QWidget):
|
|
|
380
411
|
|
|
381
412
|
handle_position = Property(int, fget=get_handle_position, fset=set_handle_position)
|
|
382
413
|
|
|
414
|
+
# ----------------- Painting -----------------
|
|
383
415
|
def paintEvent(self, event):
|
|
384
416
|
painter = QPainter(self)
|
|
385
417
|
painter.setRenderHint(QPainter.Antialiasing)
|
|
386
418
|
|
|
387
|
-
#
|
|
388
|
-
bg_rect = QRect(0, 0, self.width(), self.height())
|
|
389
|
-
|
|
390
|
-
#
|
|
419
|
+
# Background rect (rounded)
|
|
420
|
+
bg_rect = QRect(0, 0, self.width(), self.height()).adjusted(1, 1, -1, -1)
|
|
421
|
+
|
|
422
|
+
# Border pen (changes on hover)
|
|
423
|
+
if not self.isEnabled():
|
|
424
|
+
pen = QPen(self._border_color)
|
|
425
|
+
pen.setWidth(self._border_width)
|
|
426
|
+
else:
|
|
427
|
+
pen = QPen(self._border_color_hover if self._hovered else self._border_color)
|
|
428
|
+
pen.setWidth(self._border_width_hover if self._hovered else self._border_width)
|
|
429
|
+
|
|
430
|
+
painter.setPen(pen)
|
|
391
431
|
painter.setBrush(self._bg_color)
|
|
392
|
-
painter.drawRoundedRect(bg_rect
|
|
432
|
+
painter.drawRoundedRect(bg_rect, self.height() / 2, self.height() / 2)
|
|
393
433
|
|
|
394
|
-
#
|
|
434
|
+
# Handle position and size
|
|
395
435
|
handle_x = self._handle_position
|
|
396
436
|
handle_y = self.handleMargin
|
|
397
|
-
|
|
398
|
-
|
|
437
|
+
handle_w = self.handle_image.width()
|
|
438
|
+
handle_h = self.handle_image.height()
|
|
439
|
+
handle_rect = QRect(handle_x, handle_y, handle_w, handle_h)
|
|
399
440
|
|
|
400
|
-
|
|
401
|
-
if self.
|
|
402
|
-
|
|
403
|
-
handle_rect = QRect(handle_x, handle_y, handle_width, handle_height)
|
|
404
|
-
painter.drawPixmap(handle_rect, self.handle_image)
|
|
441
|
+
# Draw gear (static or animated)
|
|
442
|
+
if self.FlagRunning and self.gearMovie is not None:
|
|
443
|
+
painter.drawImage(handle_rect, self.gearMovie.currentImage())
|
|
405
444
|
else:
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
painter.setBrush(Qt.white)
|
|
410
|
-
painter.drawEllipse(handle_rect)
|
|
411
|
-
"""
|
|
412
|
-
handle_rect = QRect(handle_x, handle_y, handle_width, handle_height)
|
|
413
|
-
#painter.drawPixmap(handle_rect, self.handle_image)
|
|
414
|
-
if self.FlagRunning:
|
|
415
|
-
painter.drawImage(handle_rect,self.gearMovie.currentImage())
|
|
416
|
-
else:
|
|
417
|
-
painter.drawImage(handle_rect,self.handle_image.toImage())
|
|
418
|
-
|
|
445
|
+
painter.drawImage(handle_rect, self.handle_image.toImage())
|
|
446
|
+
|
|
447
|
+
# Draw label text
|
|
419
448
|
if self.FlagAnimation:
|
|
420
449
|
self.text_label.setText("")
|
|
421
450
|
else:
|
|
422
451
|
if self._checked:
|
|
423
452
|
self.text_label.setText("run ")
|
|
424
|
-
self.text_label.
|
|
453
|
+
self.text_label.adjustSize()
|
|
454
|
+
self.text_label.move(self.handleMargin * 2, (self.height() - self.text_label.height()) // 2)
|
|
425
455
|
else:
|
|
426
456
|
self.text_label.setText("skip")
|
|
427
|
-
self.text_label.
|
|
457
|
+
self.text_label.adjustSize()
|
|
458
|
+
self.text_label.move(self.width() - self.height() - self.handleMargin * 2,
|
|
459
|
+
(self.height() - self.text_label.height()) // 2)
|
|
428
460
|
|
|
461
|
+
# ----------------- Interaction -----------------
|
|
429
462
|
def mousePressEvent(self, event):
|
|
430
|
-
if event.button() == Qt.LeftButton and not self.FlagAnimation:
|
|
463
|
+
if event.button() == Qt.LeftButton and not self.FlagAnimation and self.isEnabled():
|
|
431
464
|
self.toggle()
|
|
432
465
|
|
|
433
466
|
def toggle(self):
|
|
434
467
|
self._checked = not self._checked
|
|
435
|
-
if self.par:
|
|
468
|
+
if self.par:
|
|
469
|
+
self.par.FlagQueue = self._checked
|
|
470
|
+
|
|
436
471
|
self.toggled.emit(self._checked)
|
|
472
|
+
|
|
473
|
+
self.animation.stop()
|
|
474
|
+
self.animation.setStartValue(self._handle_position)
|
|
437
475
|
self.animation.setEndValue(self.switchHandlePosition())
|
|
438
|
-
self.FlagAnimation=True
|
|
476
|
+
self.FlagAnimation = True
|
|
439
477
|
self.animation.start()
|
|
440
|
-
|
|
478
|
+
|
|
479
|
+
# ----------------- Layout helpers -----------------
|
|
441
480
|
def switchHandlePosition(self):
|
|
442
481
|
if self._checked:
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
handle_position = self.handleMargin
|
|
446
|
-
return handle_position
|
|
482
|
+
return self.width() - self.height() + self.handleMargin
|
|
483
|
+
return self.handleMargin
|
|
447
484
|
|
|
448
485
|
def setSwitchLayout(self):
|
|
449
|
-
self.FlagAnimation=False
|
|
486
|
+
self.FlagAnimation = False
|
|
450
487
|
if self._checked:
|
|
451
|
-
self._bg_color = QColor(46, 204, 113)
|
|
452
|
-
tip=f'{self.name if self.name else "Item"} added to run queue.'
|
|
488
|
+
self._bg_color = QColor(46, 204, 113)
|
|
489
|
+
tip = f'{self.name if self.name else "Item"} added to run queue.'
|
|
453
490
|
else:
|
|
454
|
-
tip=f'{self.name if self.name else "Item"} excluded from run queue.'
|
|
455
|
-
#text_color = self.palette().color(QPalette.WindowText)
|
|
456
491
|
self._bg_color = QColor(175, 175, 175)
|
|
457
|
-
self._bg_color.setAlpha(
|
|
492
|
+
self._bg_color.setAlpha(64)
|
|
493
|
+
tip = f'{self.name if self.name else "Item"} excluded from run queue.'
|
|
494
|
+
|
|
458
495
|
self.setToolTip(tip)
|
|
459
496
|
self.setStatusTip(tip)
|
|
460
497
|
self.set_handle_position(self.switchHandlePosition())
|
|
461
498
|
|
|
462
|
-
def setSwitch(self,FlagChecked):
|
|
463
|
-
if FlagChecked!=self._checked:
|
|
464
|
-
self._checked=FlagChecked
|
|
499
|
+
def setSwitch(self, FlagChecked: bool):
|
|
500
|
+
if FlagChecked != self._checked:
|
|
501
|
+
self._checked = FlagChecked
|
|
502
|
+
if self.par:
|
|
503
|
+
self.par.FlagQueue = self._checked
|
|
465
504
|
self.setSwitchLayout()
|
|
466
|
-
|
|
505
|
+
|
|
467
506
|
class ActionButtonBar(QWidget):
|
|
468
507
|
FlagShortCuts = True
|
|
469
508
|
|
|
@@ -495,7 +534,7 @@ class ActionButtonBar(QWidget):
|
|
|
495
534
|
setattr(self,'sep_'+icon_name[1:],separator)
|
|
496
535
|
self.buttonLayout.addWidget(separator)
|
|
497
536
|
else:
|
|
498
|
-
b =
|
|
537
|
+
b = HoverZoomToolButton(self)
|
|
499
538
|
b.setObjectName('button_'+icon_name)
|
|
500
539
|
b.setCursor(Qt.CursorShape.PointingHandCursor)
|
|
501
540
|
if FlagInvisible:
|
|
@@ -560,6 +599,7 @@ class ActionButtonBar(QWidget):
|
|
|
560
599
|
tree.FlagContexMenu=True
|
|
561
600
|
|
|
562
601
|
menu=QMenu(tree)
|
|
602
|
+
menu.setStyleSheet(gPaIRS_QMenu_style)
|
|
563
603
|
name=[]
|
|
564
604
|
act=[]
|
|
565
605
|
fun=[]
|
|
@@ -578,7 +618,7 @@ class ActionButtonBar(QWidget):
|
|
|
578
618
|
if FlagNamedBar and 'class' in bar.buttonData[type]:
|
|
579
619
|
if 'PIV'!=nameAction[:3]: nameAction=nameAction[:1].lower()+nameAction[1:]
|
|
580
620
|
if b.isCheckable():
|
|
581
|
-
nameAction=
|
|
621
|
+
nameAction=b.toolTip()
|
|
582
622
|
else:
|
|
583
623
|
nameAction='Add '+nameAction
|
|
584
624
|
act.append(QAction(b.icon(),nameAction,self))
|
|
@@ -1039,7 +1079,7 @@ class ProjectTree(PaIRSTree):
|
|
|
1039
1079
|
self.actionBar.button_close.setEnabled(FlagEnabled)
|
|
1040
1080
|
self.actionBar.button_clean.setEnabled(self.topLevelItemCount()>0)
|
|
1041
1081
|
|
|
1042
|
-
class DraggableButton(
|
|
1082
|
+
class DraggableButton(HoverZoomToolButton):
|
|
1043
1083
|
def __init__(self, data: dict = {}, buttonSize: list = processButtonSize, FlagInvisible=True, parent=None):
|
|
1044
1084
|
super().__init__(parent)
|
|
1045
1085
|
self.buttonData = data
|
|
@@ -1052,6 +1092,7 @@ class DraggableButton(QToolButton):
|
|
|
1052
1092
|
self.setIconSize(QSize(self.buttonSize[0], self.buttonSize[0]))
|
|
1053
1093
|
self.setIcon(self.buttonIcon)
|
|
1054
1094
|
self.setFixedSize(self.buttonSize[1], self.buttonSize[1])
|
|
1095
|
+
|
|
1055
1096
|
if FlagInvisible:
|
|
1056
1097
|
self.setCursor(Qt.CursorShape.OpenHandCursor)
|
|
1057
1098
|
self.setStyleSheet("QToolButton { border: none; background: none;} QToolButton::menu-indicator { image: none; }")
|
|
@@ -1103,7 +1144,7 @@ class ProcessButtonBar(QWidget):
|
|
|
1103
1144
|
super().__init__()
|
|
1104
1145
|
self.buttonLayout = QHBoxLayout()
|
|
1105
1146
|
self.buttonLayout.setContentsMargins(0, 0, 0, 0)
|
|
1106
|
-
self.buttonLayout.setSpacing(int(buttonSize[0]
|
|
1147
|
+
self.buttonLayout.setSpacing(int(buttonSize[0]/4))
|
|
1107
1148
|
self.setLayout(self.buttonLayout)
|
|
1108
1149
|
self.buttonData=buttonData
|
|
1109
1150
|
self.buttonSize = buttonSize
|
|
@@ -1123,7 +1164,7 @@ class StepButtonBar(QWidget):
|
|
|
1123
1164
|
super().__init__()
|
|
1124
1165
|
self.buttonLayout = QVBoxLayout()
|
|
1125
1166
|
self.buttonLayout.setContentsMargins(10, headerHeight+5, 0, 10)
|
|
1126
|
-
self.buttonLayout.setSpacing(int(buttonSize[0]/
|
|
1167
|
+
self.buttonLayout.setSpacing(int(buttonSize[0]/4))
|
|
1127
1168
|
self.setLayout(self.buttonLayout)
|
|
1128
1169
|
self.buttonData=buttonData
|
|
1129
1170
|
self.buttonSize = buttonSize
|
|
@@ -1135,8 +1176,7 @@ class StepButtonBar(QWidget):
|
|
|
1135
1176
|
data=buttonData[type]
|
|
1136
1177
|
|
|
1137
1178
|
if all([f in list(data) for f in ('icon', 'name', 'type')]):
|
|
1138
|
-
button =
|
|
1139
|
-
button.setIconSize(QSize(self.buttonSize[0], self.buttonSize[0]))
|
|
1179
|
+
button = HoverZoomToolButton(self, base_icon=self.buttonSize[0], zoom=1.25)
|
|
1140
1180
|
button.setFixedSize(self.buttonSize[1], self.buttonSize[1])
|
|
1141
1181
|
|
|
1142
1182
|
if FlagInvisible:
|
|
@@ -1223,7 +1263,7 @@ class ProcessTree(PaIRSTree):
|
|
|
1223
1263
|
|
|
1224
1264
|
if self.FlagBin:
|
|
1225
1265
|
columns=["#","Deleted processes"]
|
|
1226
|
-
self.setStyleSheet("""
|
|
1266
|
+
self.setStyleSheet(self.styleSheet() + """
|
|
1227
1267
|
QHeaderView::section {
|
|
1228
1268
|
color: red;
|
|
1229
1269
|
}
|
|
@@ -1353,12 +1393,12 @@ class ProcessTree(PaIRSTree):
|
|
|
1353
1393
|
if type(self).eventSender is None: type(self).eventSender=self
|
|
1354
1394
|
if event.mimeData().hasFormat('application/x-qabstractitemmodeldatalist') and type(self).eventSender!=self:
|
|
1355
1395
|
self.FlagExternalDrag=True
|
|
1356
|
-
self.setStyleSheet(self.initialStyleSheet+"QTreeWidget { background-color:
|
|
1396
|
+
self.setStyleSheet(self.initialStyleSheet+f"QTreeWidget {{ background-color: {PaIRS_faintblue}; }}")
|
|
1357
1397
|
event.accept()
|
|
1358
1398
|
elif event.mimeData().hasFormat('application/x-button') and not self.FlagBin:
|
|
1359
1399
|
self.FlagExternalDrag=True
|
|
1360
1400
|
self.dragged_items='externalItem'
|
|
1361
|
-
self.setStyleSheet(self.initialStyleSheet+"QTreeWidget { background-color:
|
|
1401
|
+
self.setStyleSheet(self.initialStyleSheet+f"QTreeWidget {{ background-color: {PaIRS_faintblue}; }}")
|
|
1362
1402
|
event.accept()
|
|
1363
1403
|
else:
|
|
1364
1404
|
super().dragEnterEvent(event)
|
|
@@ -1452,8 +1492,8 @@ class ProcessTree(PaIRSTree):
|
|
|
1452
1492
|
ITE.FlagQueue=self.TREpar.FlagQueue
|
|
1453
1493
|
ITE.ind=[self.TREpar.project,int(self.FlagBin),ind,0,0]
|
|
1454
1494
|
|
|
1495
|
+
processNames=[item[0].name for item in self.itemList[0]]+[item[0].name for item in self.restoreTree.itemList[0]]
|
|
1455
1496
|
if name is None:
|
|
1456
|
-
processNames=[item[0].name for item in self.itemList[0]]+[item[0].name for item in self.restoreTree.itemList[0]]
|
|
1457
1497
|
nameInd=1
|
|
1458
1498
|
ITE.name=f'{ITE.basename} {nameInd}'
|
|
1459
1499
|
while ITE.name in processNames:
|
|
@@ -1461,6 +1501,10 @@ class ProcessTree(PaIRSTree):
|
|
|
1461
1501
|
ITE.name=f'{ITE.basename} {nameInd}'
|
|
1462
1502
|
else:
|
|
1463
1503
|
ITE.name=name
|
|
1504
|
+
nameInd=1
|
|
1505
|
+
while ITE.name in processNames:
|
|
1506
|
+
nameInd+=1
|
|
1507
|
+
ITE.name=f'{name} ({nameInd})'
|
|
1464
1508
|
self.createParPrevs(ITE)
|
|
1465
1509
|
self.itemList[0].insert(ind,[ITE])
|
|
1466
1510
|
else:
|
|
@@ -1917,12 +1961,12 @@ class ProcessTree(PaIRSTree):
|
|
|
1917
1961
|
pixmap_list.append(icons_path+ITE.icon)
|
|
1918
1962
|
name_list.append(ITE.name)
|
|
1919
1963
|
flag_list.append(ITE.Step!=StepTypes.cal)
|
|
1920
|
-
func=lambda i, opts: self.process_loop(paths,processType,ind,ITEs[0].name,i,opts)
|
|
1964
|
+
func=lambda i, opts, cleanup_flag, rescan_flag: self.process_loop(paths,processType,ind,ITEs[0].name,i,opts,cleanup_flag,rescan_flag)
|
|
1921
1965
|
dialog = FolderLoopDialog(pixmap_list, name_list, flag_list, parent=self, paths=paths, func=func, process_name=ITEs[0].name)
|
|
1922
1966
|
dialog.exec()
|
|
1923
1967
|
return
|
|
1924
1968
|
|
|
1925
|
-
def process_loop(self,paths,processType,ind,name0,i,opts):
|
|
1969
|
+
def process_loop(self,paths,processType,ind,name0,i,opts,cleanup_flag,rescan_flag):
|
|
1926
1970
|
nProcess=self.topLevelItemCount()
|
|
1927
1971
|
path=paths[i]
|
|
1928
1972
|
name=name0+f" (.../{os.path.basename(path)}/)"
|
|
@@ -1933,6 +1977,7 @@ class ProcessTree(PaIRSTree):
|
|
|
1933
1977
|
ind_slave[2]=nProcess
|
|
1934
1978
|
ind_slave[-1]=0
|
|
1935
1979
|
|
|
1980
|
+
FlagWarning=False
|
|
1936
1981
|
for j in range(len(opts)):
|
|
1937
1982
|
ind_master[3]=j
|
|
1938
1983
|
ind_slave[3]=j
|
|
@@ -1944,10 +1989,17 @@ class ProcessTree(PaIRSTree):
|
|
|
1944
1989
|
if opts[j]==2:
|
|
1945
1990
|
INP: INPpar=self.gui.w_Input.TABpar_at(ind_new)
|
|
1946
1991
|
INP.path=myStandardPath(path)
|
|
1947
|
-
|
|
1992
|
+
if rescan_flag:
|
|
1993
|
+
flagWarning=self.rescanInputPath(ind_master,ind_new,cleanup_flag)
|
|
1994
|
+
else:
|
|
1995
|
+
flagWarning=self.gui.w_Input.scanImList(ind_new)
|
|
1996
|
+
if cleanup_flag: self.gui.w_Input.purgeImList(ind_new)
|
|
1997
|
+
INP.nimg=0
|
|
1998
|
+
if len(INP.imList[0]):
|
|
1999
|
+
if len(INP.imList[0][0]):
|
|
2000
|
+
INP.nimg=len(INP.imList[0][0])
|
|
1948
2001
|
self.gui.w_Input.checkINPpar(ind_new)
|
|
1949
2002
|
self.gui.w_Input.setINPwarn(ind_new)
|
|
1950
|
-
self.Explorer.setITElayout(ITE)
|
|
1951
2003
|
|
|
1952
2004
|
TABname=self.gui.w_Input.TABname
|
|
1953
2005
|
self.gui.bridge(TABname,ind_new)
|
|
@@ -1966,12 +2018,54 @@ class ProcessTree(PaIRSTree):
|
|
|
1966
2018
|
w.TABpar.copyfrom(currpar)
|
|
1967
2019
|
self.gui.bridge(w.TABname,ind_new)
|
|
1968
2020
|
TABpar.FlagSettingPar=FlagSettingPar
|
|
2021
|
+
self.Explorer.setITElayout(ITE)
|
|
2022
|
+
FlagWarning=FlagWarning or flagWarning or ITE.OptionDone==0
|
|
2023
|
+
|
|
1969
2024
|
#item_child=item.child(j)
|
|
1970
2025
|
#item_child.setSelected(True)
|
|
1971
2026
|
#self.setCurrentItem(item_child)
|
|
1972
2027
|
else:
|
|
1973
2028
|
self.gui.link_pars(ind_slave,ind_master,FlagSet=False)
|
|
1974
|
-
return
|
|
2029
|
+
return FlagWarning
|
|
2030
|
+
|
|
2031
|
+
def rescanInputPath(self, ind_master, ind_new, FlagNoWarning):
|
|
2032
|
+
"""Rescan input on slave using master patterns, then rebuild imList/imEx."""
|
|
2033
|
+
INP: INPpar = self.gui.w_Input.TABpar_at(ind_new) # slave
|
|
2034
|
+
INPm: INPpar = self.gui.w_Input.TABpar_at(ind_master) # master
|
|
2035
|
+
|
|
2036
|
+
# Build A (for frame_1) and B (for frame_2) from master's pattern at master's frames
|
|
2037
|
+
patm = getattr(INPm.imSet, "pattern", [])
|
|
2038
|
+
ncam = INP.inp_ncam
|
|
2039
|
+
def _pat_list(frames,ind0=0):
|
|
2040
|
+
out=[];
|
|
2041
|
+
for k in range(ncam):
|
|
2042
|
+
f = frames[k]-ind0 if k < len(frames) else -1
|
|
2043
|
+
out.append(patm[f] if isinstance(f,int) and 0 <= f < len(patm) else None)
|
|
2044
|
+
return out
|
|
2045
|
+
A = _pat_list(INPm.frame_1)
|
|
2046
|
+
B = _pat_list(INPm.frame_2,1)
|
|
2047
|
+
|
|
2048
|
+
# Rescan slave input path with patterns=A,B (maps patterns -> frame indices on slave)
|
|
2049
|
+
self.gui.w_Input.scanInputPath(ind_new, patterns=[A, B], FlagNoWarning=FlagNoWarning)
|
|
2050
|
+
|
|
2051
|
+
# Rebuild imList/imEx from frames computed on slave
|
|
2052
|
+
INP.imList, INP.imEx = INP.imSet.genListsFromFrame(
|
|
2053
|
+
INP.frame_1, INP.frame_2, INP.ind_in, INP.npairs, INP.step, INP.FlagTR_Import
|
|
2054
|
+
)
|
|
2055
|
+
# Compare slave vs master lists
|
|
2056
|
+
def _lists_differ(a, b):
|
|
2057
|
+
if len(a) != len(b): return True
|
|
2058
|
+
for x, y in zip(a, b):
|
|
2059
|
+
if x != y: return True
|
|
2060
|
+
return False
|
|
2061
|
+
|
|
2062
|
+
FlagWarning = (
|
|
2063
|
+
_lists_differ(INP.imList, INPm.imList) or
|
|
2064
|
+
_lists_differ(INP.imEx, INPm.imEx)
|
|
2065
|
+
)
|
|
2066
|
+
|
|
2067
|
+
return FlagWarning
|
|
2068
|
+
|
|
1975
2069
|
|
|
1976
2070
|
def button_delete_action(self):
|
|
1977
2071
|
self.blockSignals(True)
|
|
@@ -2296,7 +2390,8 @@ class PaIRS_Explorer(gPaIRS_Tab):
|
|
|
2296
2390
|
self.main_layout.addWidget(self.Explorer_main_splitter)
|
|
2297
2391
|
|
|
2298
2392
|
# Creazione del pulsante checkable
|
|
2299
|
-
self.binButton =
|
|
2393
|
+
self.binButton = HoverZoomToolButton(self.processButtonBar)
|
|
2394
|
+
self.binButton.setObjectName('binButton')
|
|
2300
2395
|
self.binButton.setIconSize(QSize(self.processButtonBar.buttonSize[0], self.processButtonBar.buttonSize[0]))
|
|
2301
2396
|
self.binButton.setFixedSize(self.processButtonBar.buttonSize[1], self.processButtonBar.buttonSize[1])
|
|
2302
2397
|
if self.processButtonBar.FlagInvisible:
|
|
@@ -2377,7 +2472,7 @@ class PaIRS_Explorer(gPaIRS_Tab):
|
|
|
2377
2472
|
tree.setCurrentItem(child)
|
|
2378
2473
|
self.processTree_item_selection(tree)
|
|
2379
2474
|
else:
|
|
2380
|
-
|
|
2475
|
+
show_mouse_tooltip(self,'Current step is disabled! Please, reset the subsequemt step in the process to access it.')
|
|
2381
2476
|
for t,b in self.stepButtonBar.buttons.items():
|
|
2382
2477
|
b:QToolButton
|
|
2383
2478
|
b.clicked.connect(lambda flag, butt=b, type=t: stepButtonAction(butt, type))
|
|
@@ -2492,13 +2587,22 @@ class PaIRS_Explorer(gPaIRS_Tab):
|
|
|
2492
2587
|
if item.childCount()>ind:
|
|
2493
2588
|
item_child=item.child(ind)
|
|
2494
2589
|
item_child.setHidden(not ITEs[ind+1].active)
|
|
2495
|
-
b.setVisible(
|
|
2496
|
-
|
|
2590
|
+
b.setVisible(True)
|
|
2591
|
+
#b.setVisible(c not in ITEs[0].mandatory) #b.setVisible(True)
|
|
2592
|
+
#lab.setVisible(c in ITEs[0].mandatory)
|
|
2497
2593
|
flagRunnable=all([ITEs[j].flagRun==0 for j in range(ind+2,nsteps+1)]) if ind<nsteps else True
|
|
2498
2594
|
flagRunnable=flagRunnable and ITEs[ind+1].flagRun==0 and ITEs[0].flagRun!=-2 #and len(ITEs[ind+1].link)==0
|
|
2499
2595
|
b.setEnabled(flagRunnable)
|
|
2500
|
-
lab.setEnabled(flagRunnable)
|
|
2596
|
+
#lab.setEnabled(flagRunnable)
|
|
2501
2597
|
b.setChecked(ITEs[ind+1].active)
|
|
2598
|
+
nameAction=ITEs[ind+1].name
|
|
2599
|
+
if 'PIV'!=nameAction[:3]: nameAction=nameAction[:1].lower()+nameAction[1:]
|
|
2600
|
+
if c not in ITEs[0].mandatory:
|
|
2601
|
+
nameAction=f"{'De-activate' if b.isChecked() else 'Activate'} {nameAction}"
|
|
2602
|
+
else:
|
|
2603
|
+
nameAction=f"{'Go to and edit'} {nameAction}"
|
|
2604
|
+
b.setToolTip(nameAction)
|
|
2605
|
+
b.setStatusTip(nameAction)
|
|
2502
2606
|
else:
|
|
2503
2607
|
flagRunnable=False
|
|
2504
2608
|
b.setVisible(False)
|
|
@@ -2508,10 +2612,27 @@ class PaIRS_Explorer(gPaIRS_Tab):
|
|
|
2508
2612
|
b.setChecked(False)
|
|
2509
2613
|
b.setButtonIcon()
|
|
2510
2614
|
if self.stepPage:
|
|
2511
|
-
|
|
2615
|
+
FlagChild=c in ITEs[0].children
|
|
2616
|
+
self.stepPage.items[c].setVisible(FlagChild) #and b.isChecked())
|
|
2617
|
+
FlagEnabled=b.isEnabled() or b.isChecked()
|
|
2618
|
+
self.stepPage.items[c].setEnabled(FlagEnabled)
|
|
2512
2619
|
pageButton:QPushButton=self.stepPage.items[c].findChildren(QPushButton)[0]
|
|
2620
|
+
|
|
2621
|
+
if FlagChild:
|
|
2622
|
+
ind=list(ITEs[0].children).index(c)
|
|
2623
|
+
nameAction=ITEs[ind+1].name
|
|
2624
|
+
nameAction_lowerCase=nameAction[:1].lower()+nameAction[1:] if 'PIV'!=nameAction[:3] else nameAction
|
|
2625
|
+
if b.isEnabled():
|
|
2626
|
+
toolTip="Go to and edit " + nameAction_lowerCase if b.isChecked() else b.toolTip()
|
|
2627
|
+
else:
|
|
2628
|
+
toolTip="Go to and view " + nameAction_lowerCase if b.isChecked() else nameAction+" step was excluded from the process!"
|
|
2629
|
+
self.stepPage.items[c].setToolTip(toolTip)
|
|
2630
|
+
self.stepPage.items[c].setStatusTip(toolTip)
|
|
2631
|
+
|
|
2632
|
+
self.stepPage.setProcessTextActive(not (b.isEnabled() and not b.isChecked()),c)
|
|
2633
|
+
|
|
2513
2634
|
if flagRunnable:
|
|
2514
|
-
pageButton.setIcon(b.icon())
|
|
2635
|
+
pageButton.setIcon(b.icon())
|
|
2515
2636
|
else:
|
|
2516
2637
|
pageButton.setIcon(b.iconOn)
|
|
2517
2638
|
else:
|
|
@@ -2953,13 +3074,21 @@ class StartingPage(QFrame):
|
|
|
2953
3074
|
button_margin=self.ITEM_HEIGHT-self.ICON_SIZE-self.BUTTON_LAYOUT_TOP_MARGIN
|
|
2954
3075
|
CAPTION_HEIGHT=self.ITEM_HEIGHT-self.NAME_LABEL_HEIGHT-self.TEXT_LAYOUT_SPACING
|
|
2955
3076
|
self.items={}
|
|
3077
|
+
self.textItems={}
|
|
2956
3078
|
# Itera sui dizionari nella lista
|
|
2957
3079
|
for n, process in processes.items():
|
|
2958
3080
|
# Layout orizzontale per ogni processo
|
|
2959
3081
|
widget=QWidget()
|
|
3082
|
+
widget.setObjectName("process_item")
|
|
3083
|
+
widget.setStyleSheet(f"""
|
|
3084
|
+
QWidget#process_item:hover {{
|
|
3085
|
+
background-color: {PaIRS_ghostblue};
|
|
3086
|
+
border-radius: 10px;
|
|
3087
|
+
}}
|
|
3088
|
+
""")
|
|
2960
3089
|
process_layout = QHBoxLayout(widget)
|
|
2961
3090
|
process_layout.setSpacing(self.LAYOUT_SPACING)
|
|
2962
|
-
process_layout.setContentsMargins(
|
|
3091
|
+
process_layout.setContentsMargins(10, 10, 10, 0)
|
|
2963
3092
|
|
|
2964
3093
|
# Pulsante con icona
|
|
2965
3094
|
button_layout = QHBoxLayout()
|
|
@@ -2967,6 +3096,7 @@ class StartingPage(QFrame):
|
|
|
2967
3096
|
button_layout.setContentsMargins(0, self.BUTTON_LAYOUT_TOP_MARGIN, 0, button_margin)
|
|
2968
3097
|
|
|
2969
3098
|
icon_button = QPushButton()
|
|
3099
|
+
icon_button.setObjectName("StartingPage_Button")
|
|
2970
3100
|
pixmap = QPixmap(icons_path+process['icon']).scaled(self.ICON_SIZE, self.ICON_SIZE, mode=Qt.TransformationMode.SmoothTransformation)
|
|
2971
3101
|
icon_button.setIcon(pixmap)
|
|
2972
3102
|
icon_button.setIconSize(pixmap.size())
|
|
@@ -3007,13 +3137,15 @@ class StartingPage(QFrame):
|
|
|
3007
3137
|
caption_text_edit.setFont(caption_font)
|
|
3008
3138
|
caption_text_edit.setAlignment(Qt.AlignmentFlag.AlignJustify)
|
|
3009
3139
|
caption_text_edit.setReadOnly(True)
|
|
3140
|
+
caption_text_edit.setTextInteractionFlags(Qt.NoTextInteraction)
|
|
3141
|
+
caption_text_edit.viewport().setCursor(Qt.PointingHandCursor)
|
|
3010
3142
|
caption_text_edit.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
|
3011
3143
|
caption_text_edit.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
|
3012
3144
|
caption_text_edit.setFrameStyle(QFrame.NoFrame)
|
|
3013
3145
|
#caption_text_edit.setFixedWidth(self.CAPTION_WIDTH)
|
|
3014
3146
|
caption_text_edit.setStyleSheet("background: transparent;")
|
|
3015
3147
|
caption_text_edit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
|
|
3016
|
-
|
|
3148
|
+
|
|
3017
3149
|
# Adjust height to content
|
|
3018
3150
|
caption_text_edit.document().setTextWidth(caption_text_edit.viewport().width())
|
|
3019
3151
|
caption_text_edit.setFixedHeight(CAPTION_HEIGHT)#caption_text_edit.document().size().height())
|
|
@@ -3029,7 +3161,30 @@ class StartingPage(QFrame):
|
|
|
3029
3161
|
# Aggiungi il layout orizzontale al layout principale
|
|
3030
3162
|
self.main_layout.addWidget(widget)
|
|
3031
3163
|
|
|
3164
|
+
# --- Make the whole row clickable (icon + labels + background) ---
|
|
3165
|
+
if buttonBar:
|
|
3166
|
+
|
|
3167
|
+
def make_clickable(w, callback):
|
|
3168
|
+
w.setCursor(Qt.PointingHandCursor)
|
|
3169
|
+
|
|
3170
|
+
def mouseReleaseEvent(event, cb=callback, ww=w):
|
|
3171
|
+
if event.button() == Qt.LeftButton:
|
|
3172
|
+
cb()
|
|
3173
|
+
# call base implementation to keep default behaviour
|
|
3174
|
+
QWidget.mouseReleaseEvent(ww, event)
|
|
3175
|
+
|
|
3176
|
+
w.mouseReleaseEvent = mouseReleaseEvent
|
|
3177
|
+
|
|
3178
|
+
# entire row + title + caption all trigger the same action
|
|
3179
|
+
make_clickable(widget, action(n))
|
|
3180
|
+
#make_clickable(name_label, click_callback)
|
|
3181
|
+
#make_clickable(caption_text_edit, click_callback)
|
|
3182
|
+
|
|
3032
3183
|
self.items[n]=widget
|
|
3184
|
+
self.textItems[n]={
|
|
3185
|
+
"name_label": name_label,
|
|
3186
|
+
"caption": caption_text_edit,
|
|
3187
|
+
}
|
|
3033
3188
|
|
|
3034
3189
|
self.main_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding))
|
|
3035
3190
|
|
|
@@ -3054,6 +3209,31 @@ class StartingPage(QFrame):
|
|
|
3054
3209
|
caption_font.setPixelSize(CAPTION_FONT_SIZE)
|
|
3055
3210
|
c.setFont(caption_font)
|
|
3056
3211
|
|
|
3212
|
+
def setProcessTextActive(self, active: bool, key=None):
|
|
3213
|
+
"""
|
|
3214
|
+
If active=True -> black text (active)
|
|
3215
|
+
If active=False -> light bluish text (inactive)
|
|
3216
|
+
If key is None -> apply to all items
|
|
3217
|
+
If key is provided -> apply only to that process key
|
|
3218
|
+
"""
|
|
3219
|
+
active_color = "none"
|
|
3220
|
+
inactive_color = "rgb(150, 150, 255)"
|
|
3221
|
+
|
|
3222
|
+
color = active_color if active else inactive_color
|
|
3223
|
+
|
|
3224
|
+
def apply_to(item):
|
|
3225
|
+
item["name_label"].setStyleSheet(f"color: {color};")
|
|
3226
|
+
# QTextEdit draws text in its viewport -> set color on QTextEdit itself is fine
|
|
3227
|
+
item["caption"].setStyleSheet(f"color: {color}; background: transparent;")
|
|
3228
|
+
|
|
3229
|
+
if key is None:
|
|
3230
|
+
for item in self.textItems.values():
|
|
3231
|
+
apply_to(item)
|
|
3232
|
+
else:
|
|
3233
|
+
if key in self.textItems:
|
|
3234
|
+
apply_to(self.textItems[key])
|
|
3235
|
+
|
|
3236
|
+
|
|
3057
3237
|
if __name__ == "__main__":
|
|
3058
3238
|
app = QApplication([])
|
|
3059
3239
|
app.setStyle('Fusion')
|