386 Zeilen
12 KiB
Python
386 Zeilen
12 KiB
Python
"""
|
|
Modal Manager - Zentraler Manager für alle Progress-Modals
|
|
"""
|
|
|
|
import logging
|
|
from typing import Optional, Dict, Any
|
|
from PyQt5.QtCore import QObject, pyqtSignal, QTimer
|
|
from PyQt5.QtWidgets import QWidget
|
|
|
|
from views.widgets.progress_modal import ProgressModal
|
|
from styles.modal_styles import ModalStyles
|
|
|
|
logger = logging.getLogger("modal_manager")
|
|
|
|
|
|
class ModalManager(QObject):
|
|
"""
|
|
Zentraler Manager für alle Progress-Modals.
|
|
Koordiniert das Anzeigen und Verstecken von Modals während Automatisierungsprozessen.
|
|
"""
|
|
|
|
# Signale
|
|
modal_shown = pyqtSignal(str) # Modal-Typ
|
|
modal_hidden = pyqtSignal(str) # Modal-Typ
|
|
modal_force_closed = pyqtSignal(str) # Modal-Typ
|
|
|
|
def __init__(self, parent_window: QWidget = None, language_manager=None, style_manager=None):
|
|
super().__init__()
|
|
self.parent_window = parent_window
|
|
self.language_manager = language_manager
|
|
self.style_manager = style_manager or ModalStyles()
|
|
|
|
# Aktive Modals verwalten
|
|
self.active_modals: Dict[str, ProgressModal] = {}
|
|
self.modal_stack = [] # Stack für verschachtelte Modals
|
|
|
|
# Auto-Hide Timer für Fehler-Modals
|
|
self.auto_hide_timers: Dict[str, QTimer] = {}
|
|
|
|
logger.info("ModalManager initialisiert")
|
|
|
|
def show_modal(self, modal_type: str, title: str = None, status: str = None, detail: str = None) -> bool:
|
|
"""
|
|
Zeigt ein Progress-Modal an.
|
|
|
|
Args:
|
|
modal_type: Typ des Modals ('account_creation', 'login_process', etc.)
|
|
title: Optional - benutzerdefinierter Titel
|
|
status: Optional - benutzerdefinierter Status
|
|
detail: Optional - benutzerdefinierter Detail-Text
|
|
|
|
Returns:
|
|
bool: True wenn Modal erfolgreich angezeigt wurde
|
|
"""
|
|
try:
|
|
# Prüfe ob Modal bereits aktiv ist
|
|
if modal_type in self.active_modals:
|
|
logger.warning(f"Modal '{modal_type}' ist bereits aktiv")
|
|
return False
|
|
|
|
# Erstelle neues Modal
|
|
modal = ProgressModal(
|
|
parent=self.parent_window,
|
|
modal_type=modal_type,
|
|
language_manager=self.language_manager,
|
|
style_manager=self.style_manager
|
|
)
|
|
|
|
# Verbinde Signale
|
|
modal.force_closed.connect(lambda: self._handle_force_close(modal_type))
|
|
|
|
# Speichere Modal
|
|
self.active_modals[modal_type] = modal
|
|
self.modal_stack.append(modal_type)
|
|
|
|
# Benutzerdefinierte Texte setzen (falls angegeben)
|
|
if title or status or detail:
|
|
if title:
|
|
modal.title_label.setText(title)
|
|
if status:
|
|
modal.status_label.setText(status)
|
|
if detail:
|
|
modal.detail_label.setText(detail)
|
|
modal.detail_label.setVisible(True)
|
|
|
|
# Modal anzeigen
|
|
modal.show_process(modal_type)
|
|
|
|
# Signal senden
|
|
self.modal_shown.emit(modal_type)
|
|
|
|
logger.info(f"Modal '{modal_type}' angezeigt")
|
|
return True
|
|
|
|
except Exception as e:
|
|
logger.error(f"Fehler beim Anzeigen des Modals '{modal_type}': {e}")
|
|
return False
|
|
|
|
def hide_modal(self, modal_type: str) -> bool:
|
|
"""
|
|
Versteckt ein spezifisches Modal.
|
|
|
|
Args:
|
|
modal_type: Typ des zu versteckenden Modals
|
|
|
|
Returns:
|
|
bool: True wenn Modal erfolgreich versteckt wurde
|
|
"""
|
|
try:
|
|
if modal_type not in self.active_modals:
|
|
logger.warning(f"Modal '{modal_type}' ist nicht aktiv")
|
|
return False
|
|
|
|
modal = self.active_modals[modal_type]
|
|
|
|
# Modal verstecken
|
|
modal.hide_process()
|
|
|
|
# Aus aktiven Modals entfernen
|
|
del self.active_modals[modal_type]
|
|
|
|
# Aus Stack entfernen
|
|
if modal_type in self.modal_stack:
|
|
self.modal_stack.remove(modal_type)
|
|
|
|
# Auto-Hide Timer stoppen (falls vorhanden)
|
|
if modal_type in self.auto_hide_timers:
|
|
self.auto_hide_timers[modal_type].stop()
|
|
del self.auto_hide_timers[modal_type]
|
|
|
|
# Modal löschen
|
|
modal.deleteLater()
|
|
|
|
# Signal senden
|
|
self.modal_hidden.emit(modal_type)
|
|
|
|
logger.info(f"Modal '{modal_type}' versteckt")
|
|
return True
|
|
|
|
except Exception as e:
|
|
logger.error(f"Fehler beim Verstecken des Modals '{modal_type}': {e}")
|
|
return False
|
|
|
|
def update_modal_status(self, modal_type: str, status: str, detail: str = None) -> bool:
|
|
"""
|
|
Aktualisiert den Status eines aktiven Modals.
|
|
|
|
Args:
|
|
modal_type: Typ des Modals
|
|
status: Neuer Status-Text
|
|
detail: Optional - neuer Detail-Text
|
|
|
|
Returns:
|
|
bool: True wenn Update erfolgreich war
|
|
"""
|
|
try:
|
|
if modal_type not in self.active_modals:
|
|
logger.warning(f"Modal '{modal_type}' ist nicht aktiv für Status-Update")
|
|
return False
|
|
|
|
modal = self.active_modals[modal_type]
|
|
modal.update_status(status, detail)
|
|
|
|
logger.debug(f"Modal '{modal_type}' Status aktualisiert: {status}")
|
|
return True
|
|
|
|
except Exception as e:
|
|
logger.error(f"Fehler beim Aktualisieren des Modal-Status '{modal_type}': {e}")
|
|
return False
|
|
|
|
def show_modal_error(self, modal_type: str, error_message: str, auto_close_seconds: int = 3) -> bool:
|
|
"""
|
|
Zeigt eine Fehlermeldung in einem Modal an.
|
|
|
|
Args:
|
|
modal_type: Typ des Modals
|
|
error_message: Fehlermeldung
|
|
auto_close_seconds: Sekunden bis automatisches Schließen
|
|
|
|
Returns:
|
|
bool: True wenn Fehler erfolgreich angezeigt wurde
|
|
"""
|
|
try:
|
|
if modal_type not in self.active_modals:
|
|
# Erstelle neues Error-Modal
|
|
self.show_modal(modal_type, "❌ Fehler aufgetreten", error_message)
|
|
modal = self.active_modals[modal_type]
|
|
else:
|
|
modal = self.active_modals[modal_type]
|
|
|
|
modal.show_error(error_message, auto_close_seconds)
|
|
|
|
# Auto-Hide Timer setzen
|
|
if auto_close_seconds > 0:
|
|
timer = QTimer()
|
|
timer.setSingleShot(True)
|
|
timer.timeout.connect(lambda: self.hide_modal(modal_type))
|
|
timer.start(auto_close_seconds * 1000)
|
|
self.auto_hide_timers[modal_type] = timer
|
|
|
|
logger.info(f"Fehler in Modal '{modal_type}' angezeigt: {error_message}")
|
|
return True
|
|
|
|
except Exception as e:
|
|
logger.error(f"Fehler beim Anzeigen des Modal-Fehlers '{modal_type}': {e}")
|
|
return False
|
|
|
|
def hide_all_modals(self):
|
|
"""Versteckt alle aktiven Modals"""
|
|
modal_types = list(self.active_modals.keys())
|
|
|
|
for modal_type in modal_types:
|
|
self.hide_modal(modal_type)
|
|
|
|
logger.info("Alle Modals versteckt")
|
|
|
|
def is_modal_active(self, modal_type: str) -> bool:
|
|
"""
|
|
Prüft ob ein bestimmtes Modal aktiv ist.
|
|
|
|
Args:
|
|
modal_type: Typ des zu prüfenden Modals
|
|
|
|
Returns:
|
|
bool: True wenn Modal aktiv ist
|
|
"""
|
|
return modal_type in self.active_modals
|
|
|
|
def get_active_modals(self) -> list:
|
|
"""
|
|
Gibt eine Liste aller aktiven Modal-Typen zurück.
|
|
|
|
Returns:
|
|
list: Liste der aktiven Modal-Typen
|
|
"""
|
|
return list(self.active_modals.keys())
|
|
|
|
def get_current_modal(self) -> Optional[str]:
|
|
"""
|
|
Gibt den aktuell obersten Modal-Typ zurück.
|
|
|
|
Returns:
|
|
Optional[str]: Modal-Typ oder None wenn kein Modal aktiv
|
|
"""
|
|
return self.modal_stack[-1] if self.modal_stack else None
|
|
|
|
def _handle_force_close(self, modal_type: str):
|
|
"""
|
|
Behandelt das zwangsweise Schließen eines Modals (durch Timeout).
|
|
|
|
Args:
|
|
modal_type: Typ des geschlossenen Modals
|
|
"""
|
|
logger.warning(f"Modal '{modal_type}' wurde zwangsweise geschlossen")
|
|
|
|
# Modal aus aktiven Modals entfernen
|
|
if modal_type in self.active_modals:
|
|
del self.active_modals[modal_type]
|
|
|
|
# Aus Stack entfernen
|
|
if modal_type in self.modal_stack:
|
|
self.modal_stack.remove(modal_type)
|
|
|
|
# Signal senden
|
|
self.modal_force_closed.emit(modal_type)
|
|
|
|
def handle_event(self, action: str, modal_type: str, **kwargs):
|
|
"""
|
|
Zentrale Event-Behandlung für Modal-Aktionen.
|
|
|
|
Args:
|
|
action: Aktion ('show', 'hide', 'update', 'error')
|
|
modal_type: Typ des Modals
|
|
**kwargs: Zusätzliche Parameter je nach Aktion
|
|
"""
|
|
try:
|
|
if action == 'show':
|
|
title = kwargs.get('title')
|
|
status = kwargs.get('status')
|
|
detail = kwargs.get('detail')
|
|
self.show_modal(modal_type, title, status, detail)
|
|
|
|
elif action == 'hide':
|
|
self.hide_modal(modal_type)
|
|
|
|
elif action == 'update':
|
|
status = kwargs.get('status', '')
|
|
detail = kwargs.get('detail')
|
|
self.update_modal_status(modal_type, status, detail)
|
|
|
|
elif action == 'error':
|
|
error_message = kwargs.get('error_message', 'Unbekannter Fehler')
|
|
auto_close = kwargs.get('auto_close_seconds', 3)
|
|
self.show_modal_error(modal_type, error_message, auto_close)
|
|
|
|
else:
|
|
logger.warning(f"Unbekannte Modal-Aktion: {action}")
|
|
|
|
except Exception as e:
|
|
logger.error(f"Fehler bei Modal-Event-Behandlung: {e}")
|
|
|
|
def set_parent_window(self, parent_window: QWidget):
|
|
"""
|
|
Setzt das Parent-Fenster für neue Modals.
|
|
|
|
Args:
|
|
parent_window: Das Parent-Widget
|
|
"""
|
|
self.parent_window = parent_window
|
|
logger.debug("Parent-Fenster für ModalManager gesetzt")
|
|
|
|
|
|
# Globale Instanz für einfachen Zugriff
|
|
_global_modal_manager: Optional[ModalManager] = None
|
|
|
|
|
|
def get_modal_manager() -> Optional[ModalManager]:
|
|
"""
|
|
Gibt die globale ModalManager-Instanz zurück.
|
|
|
|
Returns:
|
|
Optional[ModalManager]: Die globale Instanz oder None
|
|
"""
|
|
return _global_modal_manager
|
|
|
|
|
|
def set_modal_manager(modal_manager: ModalManager):
|
|
"""
|
|
Setzt die globale ModalManager-Instanz.
|
|
|
|
Args:
|
|
modal_manager: Die zu setzende ModalManager-Instanz
|
|
"""
|
|
global _global_modal_manager
|
|
_global_modal_manager = modal_manager
|
|
|
|
|
|
def show_progress_modal(modal_type: str, **kwargs) -> bool:
|
|
"""
|
|
Convenience-Funktion zum Anzeigen eines Progress-Modals.
|
|
|
|
Args:
|
|
modal_type: Typ des Modals
|
|
**kwargs: Zusätzliche Parameter
|
|
|
|
Returns:
|
|
bool: True wenn erfolgreich
|
|
"""
|
|
manager = get_modal_manager()
|
|
if manager:
|
|
return manager.show_modal(modal_type, **kwargs)
|
|
return False
|
|
|
|
|
|
def hide_progress_modal(modal_type: str) -> bool:
|
|
"""
|
|
Convenience-Funktion zum Verstecken eines Progress-Modals.
|
|
|
|
Args:
|
|
modal_type: Typ des Modals
|
|
|
|
Returns:
|
|
bool: True wenn erfolgreich
|
|
"""
|
|
manager = get_modal_manager()
|
|
if manager:
|
|
return manager.hide_modal(modal_type)
|
|
return False
|
|
|
|
|
|
def update_progress_modal(modal_type: str, status: str, detail: str = None) -> bool:
|
|
"""
|
|
Convenience-Funktion zum Aktualisieren eines Progress-Modals.
|
|
|
|
Args:
|
|
modal_type: Typ des Modals
|
|
status: Neuer Status
|
|
detail: Optional - neuer Detail-Text
|
|
|
|
Returns:
|
|
bool: True wenn erfolgreich
|
|
"""
|
|
manager = get_modal_manager()
|
|
if manager:
|
|
return manager.update_modal_status(modal_type, status, detail)
|
|
return False |