""" Modal Styles - Zentrale Style-Definitionen für alle Modal-Dialoge """ from typing import Dict, Any from PyQt5.QtGui import QFont class ModalStyles: """ Zentrale Style-Manager-Klasse für Progress Modals. Verwaltet alle visuellen Eigenschaften wie Farben, Größen, Fonts und CSS. """ # === FARBEN === COLORS = { # Haupt-Farben 'background': '#FFFFFF', 'background_secondary': '#F0F0F0', 'border': '#E0E0E0', # Text-Farben 'text_primary': '#1A365D', 'text_secondary': '#4A5568', 'text_muted': '#718096', # Status-Farben 'success': '#48BB78', 'error': '#F56565', 'warning': '#ED8936', 'info': '#4299E1', # Overlay (nicht mehr transparent) 'overlay': 'rgba(240, 240, 240, 255)', # Progress Bar 'progress_background': '#E2E8F0', 'progress_fill_start': '#4299E1', 'progress_fill_end': '#3182CE', } # === GRÖSSEN === SIZES = { # Modal Dimensionen 'modal_width': 450, 'modal_height': 280, # Abstände 'padding_large': 40, 'padding_medium': 24, 'padding_small': 8, 'spacing_default': 24, # Komponenten 'border_radius': 20, 'border_width': 1, 'animation_size': 80, 'progress_bar_height': 8, } # === SCHRIFTARTEN === FONTS = { 'title': { 'family': 'Poppins', 'size': 18, 'weight': QFont.Bold, 'fallback': '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif' }, 'status': { 'family': 'Inter', 'size': 14, 'weight': QFont.Normal, 'fallback': '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif' }, 'detail': { 'family': 'Inter', 'size': 12, 'weight': QFont.Normal, 'style': 'italic', 'fallback': '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif' }, 'steps': { 'family': 'Inter', 'size': 12, 'weight': QFont.Normal, 'fallback': '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif' } } # === ANIMATIONEN === ANIMATIONS = { 'fade_duration': 200, 'step_delay': 800, 'auto_close_delay': 3000, 'failsafe_timeout': 300000, # 5 Minuten } # === STYLE SHEETS === @classmethod def get_modal_container_style(cls) -> str: """Style für den Haupt-Modal-Container""" return f""" QFrame#modal_container {{ background: {cls.COLORS['background']}; border: {cls.SIZES['border_width']}px solid {cls.COLORS['border']}; border-radius: {cls.SIZES['border_radius']}px; }} """ @classmethod def get_title_label_style(cls) -> str: """Style für den Titel-Label""" font = cls.FONTS['title'] return f""" QLabel#modal_title {{ color: {cls.COLORS['text_primary']}; font-family: '{font['family']}', {font['fallback']}; margin-bottom: {cls.SIZES['padding_small']}px; }} """ @classmethod def get_status_label_style(cls) -> str: """Style für den Status-Label""" font = cls.FONTS['status'] return f""" QLabel#modal_status {{ color: {cls.COLORS['text_secondary']}; font-family: '{font['family']}', {font['fallback']}; line-height: 1.5; }} """ @classmethod def get_detail_label_style(cls) -> str: """Style für den Detail-Label""" font = cls.FONTS['detail'] return f""" QLabel#modal_detail {{ color: {cls.COLORS['text_muted']}; font-family: '{font['family']}', {font['fallback']}; font-style: {font.get('style', 'normal')}; }} """ @classmethod def get_progress_bar_style(cls) -> str: """Style für die Progress Bar""" return f""" QProgressBar {{ border: none; border-radius: {cls.SIZES['progress_bar_height'] // 2}px; background-color: {cls.COLORS['progress_background']}; text-align: center; }} QProgressBar::chunk {{ background: linear-gradient(90deg, {cls.COLORS['progress_fill_start']} 0%, {cls.COLORS['progress_fill_end']} 100%); border-radius: {cls.SIZES['progress_bar_height'] // 2}px; }} """ @classmethod def get_steps_label_style(cls) -> str: """Style für den Steps-Label""" font = cls.FONTS['steps'] return f""" QLabel {{ color: {cls.COLORS['text_muted']}; font-family: '{font['family']}', {font['fallback']}; margin: {cls.SIZES['padding_small']}px 0px; }} """ @classmethod def create_font(cls, font_type: str) -> QFont: """ Erstellt ein QFont-Objekt basierend auf dem Font-Typ. Args: font_type: Der Font-Typ ('title', 'status', 'detail', 'steps') Returns: QFont: Das konfigurierte Font-Objekt """ if font_type not in cls.FONTS: font_type = 'status' # Fallback font_config = cls.FONTS[font_type] font = QFont(font_config['family'], font_config['size']) if 'weight' in font_config: font.setWeight(font_config['weight']) if font_config.get('style') == 'italic': font.setItalic(True) return font @classmethod def get_modal_texts(cls) -> Dict[str, Dict[str, str]]: """Standard-Texte für verschiedene Modal-Typen""" return { 'account_creation': { 'title': '🔄 Account wird erstellt', 'status': 'Bitte nicht unterbrechen...', 'detail': 'Browser wird vorbereitet' }, 'login_process': { 'title': '🔐 Anmeldung läuft', 'status': 'Einen Moment bitte...', 'detail': 'Session wird wiederhergestellt' }, 'verification': { 'title': '✉️ Verifizierung läuft', 'status': 'E-Mail wird geprüft...', 'detail': 'Code wird abgerufen' }, 'generic': { 'title': '⏳ Prozess läuft', 'status': 'Bitte warten...', 'detail': '' } } @classmethod def get_platform_steps(cls, platform: str) -> list: """Plattform-spezifische Schritte für Account-Erstellung""" common_steps = [ "Browser wird vorbereitet", "Seite wird geladen", "Formular wird ausgefüllt", "Account wird erstellt" ] platform_specific = { 'instagram': common_steps + [ "Profil wird eingerichtet", "E-Mail wird verifiziert" ], 'tiktok': common_steps + [ "Geburtsdatum wird gesetzt", "Telefon wird verifiziert" ], 'facebook': common_steps + [ "Profil wird vervollständigt", "Sicherheit wird eingerichtet" ], 'gmail': [ "Google-Seite wird geladen", "Persönliche Daten werden eingegeben", "Telefonnummer wird verifiziert", "Account wird finalisiert" ], 'ok': [ "OK.ru wird geladen", "Registrierungsformular wird ausgefüllt", "Telefon wird verifiziert", "Profil wird erstellt" ], 'x': common_steps + [ "Benutzername wird generiert", "E-Mail wird verifiziert" ], 'vk': [ "VK.com wird geladen", "Telefonnummer wird eingegeben", "SMS-Code wird verifiziert", "Profil wird erstellt" ] } platform_key = platform.lower().replace('.', '').replace(' ', '') return platform_specific.get(platform_key, common_steps) class ModalTheme: """Basis-Klasse für Modal-Themes (für zukünftige Erweiterungen)""" def __init__(self, name: str): self.name = name self._overrides = {} def override_color(self, color_key: str, value: str): """Überschreibt eine Farbe für dieses Theme""" if 'colors' not in self._overrides: self._overrides['colors'] = {} self._overrides['colors'][color_key] = value def override_size(self, size_key: str, value: int): """Überschreibt eine Größe für dieses Theme""" if 'sizes' not in self._overrides: self._overrides['sizes'] = {} self._overrides['sizes'][size_key] = value def apply(self, styles: ModalStyles): """Wendet die Theme-Überschreibungen an""" if 'colors' in self._overrides: styles.COLORS.update(self._overrides['colors']) if 'sizes' in self._overrides: styles.SIZES.update(self._overrides['sizes']) # Vordefinierte Themes class DarkModalTheme(ModalTheme): """Dunkles Theme für Modals""" def __init__(self): super().__init__("dark") self.override_color('background', '#1A202C') self.override_color('background_secondary', '#2D3748') self.override_color('border', '#4A5568') self.override_color('text_primary', '#F7FAFC') self.override_color('text_secondary', '#E2E8F0') self.override_color('text_muted', '#A0AEC0') self.override_color('overlay', 'rgba(26, 32, 44, 255)')