from PyQt6.QtWidgets import QWidget, QVBoxLayout, QLabel, QApplication from PyQt6.QtCore import Qt, pyqtSignal, QTimer from PyQt6.QtGui import QPixmap from app.core.main_manager import MainManager from app.ui.widgets.loading_spinner import LoadingSpinner import app.utils.paths as paths class SplashScreen(QWidget): finished = pyqtSignal(bool) # True si succès, False si échec/interruption def __init__(self, parent=None, preload_function=None): super().__init__(parent) self.preload_function = preload_function self.preload_result = True self.main_manager = MainManager.get_instance() self.theme_manager = self.main_manager.get_theme_manager() self.settings_manager = self.main_manager.get_settings_manager() self.language_manager = self.main_manager.get_language_manager() self.setup_ui() if self.preload_function: self.start_preloading() else: # Pas de préchargement, fermer immédiatement QTimer.singleShot(100, lambda: self.finished.emit(True)) def setup_ui(self): # Configuration de la fenêtre self.setWindowFlags(Qt.WindowType.FramelessWindowHint | Qt.WindowType.WindowStaysOnTopHint) self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground) self.setFixedSize(800, 600) # Layout principal layout = QVBoxLayout(self) layout.setAlignment(Qt.AlignmentFlag.AlignCenter) layout.setSpacing(60) layout.setContentsMargins(80, 80, 80, 80) # Image splash self.image_label = QLabel() self.image_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.load_splash_image() layout.addWidget(self.image_label) # Texte de progression self.progress_label = QLabel("Chargement...") self.progress_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.progress_label.setStyleSheet("font-size: 14px; color: #666;") layout.addWidget(self.progress_label) # Spinner de chargement self.spinner = LoadingSpinner(50, self) spinner_layout = QVBoxLayout() spinner_layout.setAlignment(Qt.AlignmentFlag.AlignCenter) spinner_layout.addWidget(self.spinner) layout.addLayout(spinner_layout) # Appliquer le thème self.apply_theme() # Centrer la fenêtre self.center_on_screen() def start_preloading(self): """Démarre le préchargement avec un délai pour permettre l'affichage du splash""" # Laisser le temps au splash de s'afficher QTimer.singleShot(200, self.do_preloading) def do_preloading(self): """Effectue le préchargement dans le thread principal""" try: # Fonction callback pour mettre à jour le texte def progress_callback(text): self.progress_label.setText(text) # Traiter les événements pour que l'UI se mette à jour QApplication.processEvents() # Appeler la fonction de préchargement success = self.preload_function(progress_callback) self.preload_result = success except Exception: self.preload_result = False # Attendre un peu puis fermer QTimer.singleShot(300, self.close_splash) def close_splash(self): """Ferme le splash screen et émet le signal""" if hasattr(self, 'spinner'): self.spinner.stop() self.finished.emit(self.preload_result) self.close() def load_splash_image(self): """Charge l'image splash depuis la config""" try: splash_image_path = paths.get_asset_path(self.settings_manager.get_config("splash_image")) if splash_image_path: # Essayer le chemin depuis la config if not splash_image_path.startswith('/') and not splash_image_path.startswith('\\') and ':' not in splash_image_path: # Chemin relatif, le résoudre depuis le dossier assets splash_image_path = paths.get_asset_path(splash_image_path) pixmap = QPixmap(splash_image_path) if not pixmap.isNull(): # Redimensionner l'image scaled_pixmap = pixmap.scaled(400, 300, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation) self.image_label.setPixmap(scaled_pixmap) return # Fallback : essayer l'icône par défaut fallback_path = paths.get_asset_path("icon.png") pixmap = QPixmap(fallback_path) if not pixmap.isNull(): scaled_pixmap = pixmap.scaled(240, 240, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation) self.image_label.setPixmap(scaled_pixmap) else: # Dernier fallback : texte self.image_label.setText("🚀") self.image_label.setStyleSheet("font-size: 48px;") except Exception: # En cas d'erreur, afficher un emoji self.image_label.setText("🚀") self.image_label.setStyleSheet("font-size: 48px;") def apply_theme(self): """Applique le thème actuel""" theme = self.theme_manager.get_theme() style = f""" QWidget {{ background-color: {theme.get_color("background_color")}; border-radius: 15px; border: 2px solid {theme.get_color("primary_color")}; }} QLabel {{ color: {theme.get_color("text_color")}; background: transparent; border: none; }} """ self.setStyleSheet(style) def center_on_screen(self): """Centre la fenêtre sur l'écran""" screen = QApplication.primaryScreen() screen_geometry = screen.geometry() x = (screen_geometry.width() - self.width()) // 2 y = (screen_geometry.height() - self.height()) // 2 self.move(x, y) def show_splash(self): """Affiche le splash screen""" self.show() self.raise_() self.activateWindow()