""" WizardBar — barra step orizzontale per workflow guidati del Linker. Si inserisce tra la toolbar e la griglia. """ from PyQt6.QtWidgets import QWidget, QHBoxLayout, QFrame, QSizePolicy from PyQt6.QtCore import Qt, pyqtSignal, QRect, QPoint from PyQt6.QtGui import QPainter, QColor, QFont, QPen, QBrush # ------------------------------------------------------------------ # # Singolo step # # ------------------------------------------------------------------ # class _StepWidget(QWidget): clicked = pyqtSignal(int) # emette il proprio indice ACTIVE = 'active' COMPLETED = 'completed' PENDING = 'pending' _COLORS = { ACTIVE: ('#5C6BC0', '#FFFFFF', '#1a1a2e', True), COMPLETED: ('#43A047', '#FFFFFF', '#444444', False), PENDING: ('#C8C8C8', '#888888', '#999999', False), } def __init__(self, index: int, label: str, parent=None): super().__init__(parent) self.index = index self.label = label self.state = self.PENDING self.setFixedHeight(40) self.setMinimumWidth(130) self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) self.setCursor(Qt.CursorShape.PointingHandCursor) def set_state(self, state: str): self.state = state self.update() def paintEvent(self, _event): p = QPainter(self) p.setRenderHint(QPainter.RenderHint.Antialiasing) h = self.height() cx = 22 # circle center X cy = h // 2 r = 11 bg, fg, lbl_color, bold = self._COLORS[self.state] # Circle p.setBrush(QBrush(QColor(bg))) p.setPen(Qt.PenStyle.NoPen) p.drawEllipse(QPoint(cx, cy), r, r) # Number or checkmark p.setPen(QPen(QColor(fg))) f = QFont('Segoe UI', 8, QFont.Weight.Bold) p.setFont(f) symbol = '✓' if self.state == self.COMPLETED else str(self.index + 1) p.drawText(QRect(cx - r, cy - r, r * 2, r * 2), Qt.AlignmentFlag.AlignCenter, symbol) # Label p.setPen(QPen(QColor(lbl_color))) lf = QFont('Segoe UI', 9, QFont.Weight.Bold if bold else QFont.Weight.Normal) p.setFont(lf) p.drawText(QRect(cx + r + 7, 0, self.width() - cx - r - 9, h), Qt.AlignmentFlag.AlignVCenter | Qt.AlignmentFlag.AlignLeft, self.label) p.end() def mousePressEvent(self, _event): if self.state != self.PENDING: self.clicked.emit(self.index) # ------------------------------------------------------------------ # # Barra wizard completa # # ------------------------------------------------------------------ # class WizardBar(QFrame): """ Barra step orizzontale con 4 fasi. Emette step_requested(index) quando l'utente clicca uno step navigabile. """ step_requested = pyqtSignal(int) STEPS = ['Carica listino', 'Aggancio', 'Revisiona'] def __init__(self, parent=None): super().__init__(parent) self.setFrameShape(QFrame.Shape.NoFrame) self.setFixedHeight(44) self.setStyleSheet('background-color: #EDE7F6; border-bottom: 1px solid #C5B8E8;') layout = QHBoxLayout(self) layout.setContentsMargins(16, 2, 16, 2) layout.setSpacing(0) self._steps: list[_StepWidget] = [] for i, label in enumerate(self.STEPS): step = _StepWidget(i, label, self) step.clicked.connect(self.step_requested) self._steps.append(step) layout.addWidget(step) if i < len(self.STEPS) - 1: sep = QFrame() sep.setFrameShape(QFrame.Shape.HLine) sep.setFixedHeight(1) sep.setFixedWidth(28) sep.setStyleSheet('background: #B39DDB; border: none;') layout.addWidget(sep) # Step 0 parte attivo self._current = 0 self._steps[0].set_state(_StepWidget.ACTIVE) # ---------------------------------------------------------------- # def set_step(self, index: int): """Avanza al passo index, marcando i precedenti come completati.""" self._current = index for i, step in enumerate(self._steps): if i < index: step.set_state(_StepWidget.COMPLETED) elif i == index: step.set_state(_StepWidget.ACTIVE) else: step.set_state(_StepWidget.PENDING) def current_step(self) -> int: return self._current def reset(self): self.set_step(0) class WizardBarValutazioni(WizardBar): """Variante della WizardBar per il workflow Valutazioni Reti.""" STEPS = ['Incolla', 'Verifica IMDB', 'Archivia']