HoDA_Radio/app/ui/windows/splash_screen.py
2025-09-26 19:27:59 +02:00

159 lines
6.3 KiB
Python

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()