PaIRS-UniNa 0.2.9__cp310-cp310-macosx_11_0_universal2.whl → 0.2.11__cp310-cp310-macosx_11_0_universal2.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.
Files changed (37) hide show
  1. PaIRS_UniNa/Calibration_Tab.py +29 -28
  2. PaIRS_UniNa/Changes.txt +23 -0
  3. PaIRS_UniNa/Explorer.py +171 -73
  4. PaIRS_UniNa/Input_Tab.py +2 -4
  5. PaIRS_UniNa/Input_Tab_CalVi.py +1 -0
  6. PaIRS_UniNa/Input_Tab_tools.py +27 -23
  7. PaIRS_UniNa/PaIRS_pypacks.py +126 -67
  8. PaIRS_UniNa/Process_Tab.py +19 -15
  9. PaIRS_UniNa/Process_Tab_Disp.py +8 -1
  10. PaIRS_UniNa/Saving_tools.py +3 -0
  11. PaIRS_UniNa/TabTools.py +201 -9
  12. PaIRS_UniNa/Vis_Tab.py +183 -48
  13. PaIRS_UniNa/Vis_Tab_CalVi.py +139 -12
  14. PaIRS_UniNa/_PaIRS_PIV.so +0 -0
  15. PaIRS_UniNa/__init__.py +3 -3
  16. PaIRS_UniNa/addwidgets_ps.py +773 -97
  17. PaIRS_UniNa/calibView.py +5 -2
  18. PaIRS_UniNa/gPaIRS.py +249 -48
  19. PaIRS_UniNa/icons/closeAllFloat.png +0 -0
  20. PaIRS_UniNa/icons/defaultWinSize.png +0 -0
  21. PaIRS_UniNa/icons/dockVis.png +0 -0
  22. PaIRS_UniNa/icons/dockVis_disable.png +0 -0
  23. PaIRS_UniNa/icons/floatingVisSize.png +0 -0
  24. PaIRS_UniNa/icons/fullWinsize.png +0 -0
  25. PaIRS_UniNa/icons/icon_PaIRS.ico +0 -0
  26. PaIRS_UniNa/icons/smallWinSize.png +0 -0
  27. PaIRS_UniNa/icons/undockVis.png +0 -0
  28. PaIRS_UniNa/rqrdpckgs.txt +7 -7
  29. PaIRS_UniNa/tabSplitter.py +6 -1
  30. PaIRS_UniNa/ui_Calibration_Tab.py +3 -3
  31. PaIRS_UniNa/ui_gPairs.py +92 -50
  32. PaIRS_UniNa/ui_infoPaIRS.py +8 -8
  33. PaIRS_UniNa/whatsnew.txt +2 -4
  34. {pairs_unina-0.2.9.dist-info → pairs_unina-0.2.11.dist-info}/METADATA +6 -14
  35. {pairs_unina-0.2.9.dist-info → pairs_unina-0.2.11.dist-info}/RECORD +37 -28
  36. {pairs_unina-0.2.9.dist-info → pairs_unina-0.2.11.dist-info}/WHEEL +1 -1
  37. {pairs_unina-0.2.9.dist-info → pairs_unina-0.2.11.dist-info}/top_level.txt +0 -0
@@ -64,7 +64,7 @@ class Calibration_Tab(gPaIRS_Tab):
64
64
  setAppGuiPalette(self)
65
65
 
66
66
  self.ui.button_info.setStyleSheet("border: none;")
67
-
67
+ self.ui.calTree.contextMenuEvent=lambda ev: calTreeContextMenuEvent(self.ui.calTree,self,ev)
68
68
  #------------------------------------- Declaration of parameters
69
69
  self.CALpar_base=CALpar()
70
70
  self.CALpar:CALpar=self.TABpar
@@ -171,12 +171,12 @@ class Calibration_Tab(gPaIRS_Tab):
171
171
  #*************************************************** Buttons
172
172
  #******************** Actions
173
173
  def button_CalVi_action(self):
174
- if self.CALpar.FlagSPIVCal and self.ui.button_info.isVisible() and self.ui.button_CalVi.isChecked():
174
+ if CALpar.FlagSPIVCal and self.ui.button_info.isVisible() and self.ui.button_CalVi.isChecked():
175
175
  showSPIVCalHelp(self,self.dontShowAgainSPIVCalHelp)
176
176
  self.CALpar.FlagCalVi=self.ui.button_CalVi.isChecked()
177
177
 
178
178
  def dontShowAgainSPIVCalHelp(self):
179
- self.CALpar.FlagSPIVCal = False
179
+ CALpar.FlagSPIVCal = False
180
180
 
181
181
  def button_info_action(self):
182
182
  showSPIVCalHelp(self)
@@ -186,7 +186,7 @@ class Calibration_Tab(gPaIRS_Tab):
186
186
  self.CALpar.calEx=deep_duplicate(self.ui.calTree.calEx)
187
187
 
188
188
  def button_import_action(self):
189
- if self.CALpar.FlagSPIVCal and self.ui.button_info.isVisible():
189
+ if CALpar.FlagSPIVCal and self.ui.button_info.isVisible():
190
190
  showSPIVCalHelp(self,self.dontShowAgainSPIVCalHelp)
191
191
  filenames, _ = QFileDialog.getOpenFileNames(self,\
192
192
  "Select calibration files from the current directory", filter='*.cal',\
@@ -309,30 +309,31 @@ class Calibration_Tab(gPaIRS_Tab):
309
309
  self.ui.calTree.topLevelItem(self.CALpar.row).setSelected(True)
310
310
 
311
311
  #*************************************************** Context Menu
312
- def contextMenuEvent(self, event):
313
- menu=QMenu(self)
314
- name=[]
315
- act=[]
316
- fun=[]
317
- for nb in self.calibrationTreeButtons:
318
- if '-' not in nb and '|' not in nb:
319
- b:QPushButton=getattr(self.ui,'button_'+nb)
320
- if b.isVisible() and b.isEnabled():
321
- if hasattr(self,'button_'+nb+'_callback'):
322
- name.append(nb)
323
- act.append(QAction(b.icon(),toPlainText(b.toolTip().split('.')[0]),self))
324
- menu.addAction(act[-1])
325
- callback=getattr(self,'button_'+nb+'_callback')
326
- fun.append(callback)
327
- elif '|' in nb:
328
- if len(act): menu.addSeparator()
329
-
330
- if len(act):
331
- action = menu.exec(self.mapToGlobal(event.pos()))
332
- for nb,a,f in zip(name,act,fun):
333
- if a==action:
334
- TABpar.FlagSettingPar=False
335
- f()
312
+ def calTreeContextMenuEvent(obj, self, event):
313
+ menu=QMenu(obj)
314
+ menu.setStyleSheet(gPaIRS_QMenu_style)
315
+ name=[]
316
+ act=[]
317
+ fun=[]
318
+ for nb in self.calibrationTreeButtons:
319
+ if '-' not in nb and '|' not in nb:
320
+ b:QPushButton=getattr(self.ui,'button_'+nb)
321
+ if b.isVisible() and b.isEnabled():
322
+ if hasattr(self,'button_'+nb+'_callback'):
323
+ name.append(nb)
324
+ act.append(QAction(b.icon(),toPlainText(b.toolTip().split('.')[0]),self))
325
+ menu.addAction(act[-1])
326
+ callback=getattr(self,'button_'+nb+'_callback')
327
+ fun.append(callback)
328
+ elif '|' in nb:
329
+ if len(act): menu.addSeparator()
330
+
331
+ if len(act):
332
+ action = menu.exec(obj.mapToGlobal(event.pos()))
333
+ for nb,a,f in zip(name,act,fun):
334
+ if a==action:
335
+ TABpar.FlagSettingPar=False
336
+ f()
336
337
 
337
338
  if __name__ == "__main__":
338
339
  import sys
PaIRS_UniNa/Changes.txt CHANGED
@@ -1,3 +1,26 @@
1
+ ********* Changes in version 0.2.11 (2026.02.02) **********
2
+ Bug fixes:
3
+ - fixed an issue preventing correct restoration of reshape/resize settings in the Output tab at startup of the interface.
4
+
5
+ User-interface enhancements:
6
+ - minor UI restyling aimed at improving visual feedback, with clearer highlighting of widgets involved in user interactions;
7
+ - introduced the functionality to detach the Vis plot area from the main window, enabling users to visualize images and results more comfortably and effectively in a separate floating window;
8
+ - added a dedicated Window menu, allowing users to quickly apply convenient interface layouts and better manage detached windows.
9
+
10
+
11
+
12
+ ********* Changes in version 0.2.10 (2026.01.05) **********
13
+ Bug fixes:
14
+ - fixed a bug affecting the "Edit list" functionality of the image-tree in the Input tab; the feature is now fully operational and behaves as expected;
15
+ - fixed a minor issue that could affect the correct assessment of the PIV process stability.
16
+
17
+ User-interface enhancements:
18
+ - minor UI restyling aimed at improving visual feedback, with clearer highlighting of widgets involved in user interactions;
19
+ - improved the visualization of contextual help messages, providing clearer and more consistent tooltip-like feedback within the interface;
20
+ - enhanced the management and restoration of global tab settings to ensure better consistency when loading previously saved workspaces.
21
+
22
+
23
+
1
24
  ********* Changes in version 0.2.9 (2025.12.12) **********
2
25
  Bug fixes:
3
26
  - fixed a bug in the batch folder-copy tool enabling automatic removal of incomplete image pairs and a full re-scan of destination folders to detect and resolve any image-set mismatches.
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,24]
18
- processActionButtonSize=[20,24]
17
+ projectActionButtonSize=[20,25]
18
+ processActionButtonSize=[20,25]
19
19
  actionButtonSpacing=3
20
- processButtonSize=[40,40] #icon, button
21
- stepButtonSize=[32,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
- pri.Coding.yellow('Start switch timer')
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
- # Draw background ellipse with border
388
- bg_rect = QRect(0, 0, self.width(), self.height())
389
-
390
- # Draw filled background ellipse
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.adjusted(1, 1, -1, -1), self.height() / 2, self.height() / 2)
432
+ painter.drawRoundedRect(bg_rect, self.height() / 2, self.height() / 2)
393
433
 
394
- # Calculate position and scale for image
434
+ # Handle position and size
395
435
  handle_x = self._handle_position
396
436
  handle_y = self.handleMargin
397
- handle_width = self.handle_image.width()
398
- handle_height = self.handle_image.height()
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._checked:
402
- # Draw handle image
403
- handle_rect = QRect(handle_x, handle_y, handle_width, handle_height)
404
- painter.drawPixmap(handle_rect, self.handle_image)
405
- else:
406
- # Draw handle circle
407
- handle_radius = self.height() - self.handleMargin*2
408
- handle_rect = QRect(self._handle_position, self.handleMargin, handle_radius, handle_radius)
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())
441
+ # Draw gear (static or animated)
442
+ if self.FlagRunning and self.gearMovie is not None:
443
+ painter.drawImage(handle_rect, self.gearMovie.currentImage())
416
444
  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.move(self.handleMargin*2, (self.height() - self.text_label.height()) // 2)
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.move(self.width() - self.height() - self.handleMargin*2, (self.height() - self.text_label.height()) // 2)
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: self.par.FlagQueue = self._checked
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
- handle_position = self.width() - self.height() + self.handleMargin
444
- else:
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) #QColor(0, 122, 204) ù
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(0.5)
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 = QToolButton(self)
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=f"{'De-activate' if b.isChecked() else 'Activate'} {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(QToolButton):
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] / 2))
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]/2))
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 = QToolButton(self)
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: rgba(0, 116, 255, 0.2); }")
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: rgba(0, 116, 255, 0.2); }")
1401
+ self.setStyleSheet(self.initialStyleSheet+f"QTreeWidget {{ background-color: {PaIRS_faintblue}; }}")
1362
1402
  event.accept()
1363
1403
  else:
1364
1404
  super().dragEnterEvent(event)
@@ -2350,7 +2390,8 @@ class PaIRS_Explorer(gPaIRS_Tab):
2350
2390
  self.main_layout.addWidget(self.Explorer_main_splitter)
2351
2391
 
2352
2392
  # Creazione del pulsante checkable
2353
- self.binButton = QToolButton(self.processButtonBar)
2393
+ self.binButton = HoverZoomToolButton(self.processButtonBar)
2394
+ self.binButton.setObjectName('binButton')
2354
2395
  self.binButton.setIconSize(QSize(self.processButtonBar.buttonSize[0], self.processButtonBar.buttonSize[0]))
2355
2396
  self.binButton.setFixedSize(self.processButtonBar.buttonSize[1], self.processButtonBar.buttonSize[1])
2356
2397
  if self.processButtonBar.FlagInvisible:
@@ -2431,7 +2472,7 @@ class PaIRS_Explorer(gPaIRS_Tab):
2431
2472
  tree.setCurrentItem(child)
2432
2473
  self.processTree_item_selection(tree)
2433
2474
  else:
2434
- showTip(self,'Current step is disabled! Please, reset the subsequemt step in the process to access it.')
2475
+ show_mouse_tooltip(self,'Current step is disabled! Please, reset the subsequemt step in the process to access it.')
2435
2476
  for t,b in self.stepButtonBar.buttons.items():
2436
2477
  b:QToolButton
2437
2478
  b.clicked.connect(lambda flag, butt=b, type=t: stepButtonAction(butt, type))
@@ -2546,13 +2587,22 @@ class PaIRS_Explorer(gPaIRS_Tab):
2546
2587
  if item.childCount()>ind:
2547
2588
  item_child=item.child(ind)
2548
2589
  item_child.setHidden(not ITEs[ind+1].active)
2549
- b.setVisible(c not in ITEs[0].mandatory) #b.setVisible(True)
2550
- lab.setVisible(c in ITEs[0].mandatory)
2590
+ b.setVisible(True)
2591
+ #b.setVisible(c not in ITEs[0].mandatory) #b.setVisible(True)
2592
+ #lab.setVisible(c in ITEs[0].mandatory)
2551
2593
  flagRunnable=all([ITEs[j].flagRun==0 for j in range(ind+2,nsteps+1)]) if ind<nsteps else True
2552
2594
  flagRunnable=flagRunnable and ITEs[ind+1].flagRun==0 and ITEs[0].flagRun!=-2 #and len(ITEs[ind+1].link)==0
2553
2595
  b.setEnabled(flagRunnable)
2554
- lab.setEnabled(flagRunnable)
2596
+ #lab.setEnabled(flagRunnable)
2555
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)
2556
2606
  else:
2557
2607
  flagRunnable=False
2558
2608
  b.setVisible(False)
@@ -2562,10 +2612,27 @@ class PaIRS_Explorer(gPaIRS_Tab):
2562
2612
  b.setChecked(False)
2563
2613
  b.setButtonIcon()
2564
2614
  if self.stepPage:
2565
- self.stepPage.items[c].setVisible(c in ITEs[0].children) #and b.isChecked())
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)
2566
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
+
2567
2634
  if flagRunnable:
2568
- pageButton.setIcon(b.icon())
2635
+ pageButton.setIcon(b.icon())
2569
2636
  else:
2570
2637
  pageButton.setIcon(b.iconOn)
2571
2638
  else:
@@ -3007,16 +3074,17 @@ class StartingPage(QFrame):
3007
3074
  button_margin=self.ITEM_HEIGHT-self.ICON_SIZE-self.BUTTON_LAYOUT_TOP_MARGIN
3008
3075
  CAPTION_HEIGHT=self.ITEM_HEIGHT-self.NAME_LABEL_HEIGHT-self.TEXT_LAYOUT_SPACING
3009
3076
  self.items={}
3077
+ self.textItems={}
3010
3078
  # Itera sui dizionari nella lista
3011
3079
  for n, process in processes.items():
3012
3080
  # Layout orizzontale per ogni processo
3013
3081
  widget=QWidget()
3014
3082
  widget.setObjectName("process_item")
3015
- widget.setStyleSheet("""
3016
- QWidget#process_item:hover {
3017
- background-color: rgba(64, 64, 255, 33);
3083
+ widget.setStyleSheet(f"""
3084
+ QWidget#process_item:hover {{
3085
+ background-color: {PaIRS_ghostblue};
3018
3086
  border-radius: 10px;
3019
- }
3087
+ }}
3020
3088
  """)
3021
3089
  process_layout = QHBoxLayout(widget)
3022
3090
  process_layout.setSpacing(self.LAYOUT_SPACING)
@@ -3028,6 +3096,7 @@ class StartingPage(QFrame):
3028
3096
  button_layout.setContentsMargins(0, self.BUTTON_LAYOUT_TOP_MARGIN, 0, button_margin)
3029
3097
 
3030
3098
  icon_button = QPushButton()
3099
+ icon_button.setObjectName("StartingPage_Button")
3031
3100
  pixmap = QPixmap(icons_path+process['icon']).scaled(self.ICON_SIZE, self.ICON_SIZE, mode=Qt.TransformationMode.SmoothTransformation)
3032
3101
  icon_button.setIcon(pixmap)
3033
3102
  icon_button.setIconSize(pixmap.size())
@@ -3112,6 +3181,10 @@ class StartingPage(QFrame):
3112
3181
  #make_clickable(caption_text_edit, click_callback)
3113
3182
 
3114
3183
  self.items[n]=widget
3184
+ self.textItems[n]={
3185
+ "name_label": name_label,
3186
+ "caption": caption_text_edit,
3187
+ }
3115
3188
 
3116
3189
  self.main_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding))
3117
3190
 
@@ -3136,6 +3209,31 @@ class StartingPage(QFrame):
3136
3209
  caption_font.setPixelSize(CAPTION_FONT_SIZE)
3137
3210
  c.setFont(caption_font)
3138
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
+
3139
3237
  if __name__ == "__main__":
3140
3238
  app = QApplication([])
3141
3239
  app.setStyle('Fusion')
PaIRS_UniNa/Input_Tab.py CHANGED
@@ -611,6 +611,7 @@ class Input_Tab(gPaIRS_Tab):
611
611
 
612
612
  def button_example_list_action(self):
613
613
  INPpar.FlagExample=self.ui.button_example_list.isChecked()
614
+ self.layoutExampleImageList()
614
615
  self.containerExImTree.setVisible(INPpar.FlagExample)
615
616
  return True
616
617
 
@@ -643,10 +644,7 @@ class Input_Tab(gPaIRS_Tab):
643
644
 
644
645
  @Slot(str)
645
646
  def show_import_tooltip(self, msg: str):
646
- btn = self.ui.button_import
647
- pos = btn.mapToGlobal(btn.rect().center())
648
- QToolTip.showText(pos, msg, btn)
649
- QTimer.singleShot(2000, QToolTip.hideText)
647
+ show_mouse_tooltip(self,msg)
650
648
 
651
649
  #******************** Settings
652
650
  """
@@ -178,6 +178,7 @@ class Input_Tab_CalVi(gPaIRS_Tab):
178
178
 
179
179
  def listContextMenuEvent(self, list_images:QTableWidget, event):
180
180
  menu=QMenu(list_images)
181
+ menu.setStyleSheet(gPaIRS_QMenu_style)
181
182
  buttons=['import', 'import_plane',
182
183
  -1,'down','up',
183
184
  -1,'delete','clean']