316 Zeilen
10 KiB
Python
316 Zeilen
10 KiB
Python
"""
|
|
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)') |