""" LoadingModal pour PyQt6 - Modal de chargement avec barre de progression. """ from PyQt6.QtWidgets import QDialog, QVBoxLayout, QLabel, QProgressBar from PyQt6.QtCore import Qt, QTimer from PyQt6.QtGui import QFont class LoadingModal(QDialog): """Modal de chargement avec barre de progression déterminée ou indéterminée.""" def __init__(self, parent, title: str = "Loading", message: str = "Please wait...", determinate: bool = False): """ Créer une modal de chargement. Args: parent: Widget parent title: Titre message: Message de chargement determinate: Si True, barre de progression déterminée (0→100). Sinon, indéterminée """ super().__init__(parent) self.setWindowTitle(title) self.setModal(False) self.setFixedSize(500, 250) self.setStyleSheet(""" QDialog { background-color: #212121; border-radius: 8px; } QLabel { color: #ffffff; } """) # Layout layout = QVBoxLayout() layout.setContentsMargins(30, 30, 30, 30) layout.setSpacing(15) # Titre title_label = QLabel(title) title_font = QFont() title_font.setPointSize(16) title_font.setBold(True) title_label.setFont(title_font) layout.addWidget(title_label) # Message self._msg_label = QLabel(message) msg_font = QFont() msg_font.setPointSize(11) self._msg_label.setFont(msg_font) layout.addWidget(self._msg_label) # Progress bar self._progress = QProgressBar() self._progress.setStyleSheet(""" QProgressBar { background-color: #3a3a3a; border: none; border-radius: 5px; height: 8px; } QProgressBar::chunk { background-color: #2196F3; border-radius: 5px; } """) if determinate: self._progress.setMinimum(0) self._progress.setMaximum(100) self._progress.setValue(0) self._determinate = True else: self._progress.setMinimum(0) self._progress.setMaximum(0) self._determinate = False self._animation_timer = QTimer() self._animation_timer.timeout.connect(self._animate_progress) self._animation_timer.start(50) layout.addWidget(self._progress) layout.addStretch() self.setLayout(layout) # Centre la modal self.move(parent.x() + parent.width() // 2 - 250, parent.y() + parent.height() // 2 - 125) def update_message(self, message: str): """Mettre à jour le message.""" try: self._msg_label.setText(message) self.repaint() except Exception: pass def set_progress(self, value: float): """Définir la progression (0.0 à 1.0) si en mode déterminé.""" try: if self._determinate: percent = max(0, min(100, int(value * 100))) self._progress.setValue(percent) self.repaint() except Exception: pass def _animate_progress(self): """Animation pour la barre indéterminée.""" try: if not self._determinate: current = self._progress.value() self._progress.setValue((current + 5) % 100) except Exception: pass def close(self): """Fermer la modal.""" try: if hasattr(self, '_animation_timer'): self._animation_timer.stop() self.hide() self.deleteLater() except Exception: pass def closeEvent(self, event): """Gérer la fermeture.""" try: if hasattr(self, '_animation_timer'): self._animation_timer.stop() except Exception: pass event.accept()