Popup Fenster nach Vorne
Dieser Commit ist enthalten in:
@ -15,7 +15,10 @@
|
||||
"Bash(claude mcp)",
|
||||
"Bash(claude mcp:*)",
|
||||
"Bash(sqlite3:*)",
|
||||
"Bash(python -m pip install:*)"
|
||||
"Bash(python -m pip install:*)",
|
||||
"Bash(python -m pytest teststest_generator_tab_factory.py -v)",
|
||||
"Bash(python tests:*)",
|
||||
"Bash(python tests/test_generator_tab_factory.py)"
|
||||
],
|
||||
"deny": [],
|
||||
"defaultMode": "acceptEdits",
|
||||
|
||||
@ -5,9 +5,9 @@
|
||||
## Project Overview
|
||||
|
||||
- **Path**: `A:\GiTea\AccountForger`
|
||||
- **Files**: 990 files
|
||||
- **Size**: 182.0 MB
|
||||
- **Last Modified**: 2025-09-14 18:54
|
||||
- **Files**: 1024 files
|
||||
- **Size**: 184.1 MB
|
||||
- **Last Modified**: 2025-10-03 01:25
|
||||
|
||||
## Technology Stack
|
||||
|
||||
@ -296,6 +296,7 @@ styles/
|
||||
│ ├── modal_styles.py
|
||||
│ └── __init__.py
|
||||
tests/
|
||||
│ ├── test_generator_tab_factory.py
|
||||
│ ├── test_method_rotation.py
|
||||
│ ├── bright_data/
|
||||
│ │ └── logs/
|
||||
@ -383,6 +384,7 @@ views/
|
||||
│ ├── accounts_tab.py
|
||||
│ ├── facebook_generator_tab.py
|
||||
│ ├── generator_tab.py
|
||||
│ ├── generator_tab_factory.py
|
||||
│ └── settings_tab.py
|
||||
└── widgets/
|
||||
├── account_card.py
|
||||
@ -423,3 +425,7 @@ This project is managed with Claude Project Manager. To work with this project:
|
||||
- README updated on 2025-09-13 20:45:18
|
||||
- README updated on 2025-09-14 11:33:43
|
||||
- README updated on 2025-09-14 18:54:48
|
||||
- README updated on 2025-09-17 19:46:22
|
||||
- README updated on 2025-09-21 10:31:22
|
||||
- README updated on 2025-09-24 19:25:49
|
||||
- README updated on 2025-10-03 20:29:19
|
||||
|
||||
@ -7,7 +7,7 @@ from PyQt5.QtCore import QObject
|
||||
from typing import Dict, Any, Optional, Tuple
|
||||
import random
|
||||
|
||||
from views.tabs.generator_tab import GeneratorTab
|
||||
from views.tabs.generator_tab_factory import GeneratorTabFactory
|
||||
from views.tabs.accounts_tab import AccountsTab
|
||||
# SettingsTab import entfernt - wird nicht mehr verwendet
|
||||
|
||||
@ -86,10 +86,13 @@ class BasePlatformController(QObject):
|
||||
|
||||
def create_generator_tab(self):
|
||||
"""
|
||||
Erstellt den Generator-Tab.
|
||||
Diese Methode sollte von Unterklassen überschrieben werden.
|
||||
Erstellt den Generator-Tab mit der Factory.
|
||||
Unterklassen können diese Methode überschreiben für spezielle Anforderungen.
|
||||
|
||||
Returns:
|
||||
QWidget: Plattform-spezifischer oder generischer Generator-Tab
|
||||
"""
|
||||
return GeneratorTab(self.platform_name, self.language_manager)
|
||||
return GeneratorTabFactory.create_tab(self.platform_name, self.language_manager)
|
||||
|
||||
def create_accounts_tab(self):
|
||||
"""
|
||||
|
||||
@ -11,7 +11,7 @@ from typing import Dict, Any
|
||||
|
||||
from controllers.platform_controllers.base_controller import BasePlatformController
|
||||
from controllers.platform_controllers.base_worker_thread import BaseAccountCreationWorkerThread
|
||||
from views.tabs.generator_tab import GeneratorTab # Verwende generischen GeneratorTab
|
||||
from views.tabs.generator_tab_factory import GeneratorTabFactory # Factory Pattern für Tab-Erstellung
|
||||
from views.widgets.forge_animation_widget import ForgeAnimationDialog # Forge Dialog für Animation
|
||||
|
||||
from social_networks.facebook.facebook_automation import FacebookAutomation
|
||||
@ -127,38 +127,39 @@ class FacebookController(BasePlatformController):
|
||||
def get_generator_tab(self):
|
||||
"""
|
||||
Erstellt und konfiguriert den Generator-Tab für Facebook.
|
||||
|
||||
Verwendet die Factory für saubere Tab-Erstellung.
|
||||
|
||||
Returns:
|
||||
GeneratorTab: Konfigurierter Tab für Facebook mit Geschlechtsauswahl
|
||||
QWidget: Facebook-spezifischer Tab mit Geschlechtsauswahl
|
||||
"""
|
||||
# Erstelle generischen Generator-Tab
|
||||
generator_tab = GeneratorTab(
|
||||
# Verwende Factory Pattern für Tab-Erstellung
|
||||
# Die Factory entscheidet, welche Tab-Implementierung verwendet wird
|
||||
generator_tab = GeneratorTabFactory.create_tab(
|
||||
"Facebook",
|
||||
self.language_manager
|
||||
)
|
||||
|
||||
# Facebook-spezifische Konfiguration
|
||||
self._configure_facebook_fields(generator_tab)
|
||||
|
||||
# Verbinde Signale
|
||||
generator_tab.start_requested.connect(self.handle_generation_request)
|
||||
generator_tab.stop_requested.connect(self.stop_generation)
|
||||
|
||||
|
||||
# Verbinde Signale unabhängig von der Tab-Implementierung
|
||||
# Alle Tabs müssen diese Signale unterstützen (Interface-Kontrakt)
|
||||
if hasattr(generator_tab, 'start_requested'):
|
||||
generator_tab.start_requested.connect(self.handle_generation_request)
|
||||
if hasattr(generator_tab, 'stop_requested'):
|
||||
generator_tab.stop_requested.connect(self.stop_generation)
|
||||
|
||||
return generator_tab
|
||||
|
||||
def _configure_facebook_fields(self, generator_tab):
|
||||
"""
|
||||
Konfiguriert Facebook-spezifische Felder im Generator-Tab.
|
||||
|
||||
Legacy-Methode für Abwärtskompatibilität.
|
||||
Die Konfiguration erfolgt jetzt in FacebookGeneratorTab.
|
||||
|
||||
Args:
|
||||
generator_tab: Der zu konfigurierende Tab
|
||||
"""
|
||||
# Facebook-spezifische Konfiguration
|
||||
# Der GeneratorTab kann für Facebook-spezifische Felder erweitert werden
|
||||
# Geschlecht wird aus den Parametern extrahiert
|
||||
# Vor- und Nachnamen werden im Worker-Thread aus full_name extrahiert
|
||||
|
||||
logger.debug("Facebook-spezifische Felder konfiguriert (inkl. Geschlechtsauswahl)")
|
||||
# Diese Methode ist nicht mehr nötig, da FacebookGeneratorTab
|
||||
# bereits alle Facebook-spezifischen Felder enthält
|
||||
# Behalten für Abwärtskompatibilität
|
||||
pass
|
||||
|
||||
def handle_generation_request(self, params: Dict[str, Any]):
|
||||
"""
|
||||
|
||||
@ -89,8 +89,8 @@ class GmailController(BasePlatformController):
|
||||
|
||||
def create_generator_tab(self):
|
||||
"""Erstellt den Generator-Tab und verbindet die Signale"""
|
||||
from views.tabs.generator_tab import GeneratorTab
|
||||
generator_tab = GeneratorTab(self.platform_name, self.language_manager)
|
||||
# Verwende die Basisimplementierung, die die GeneratorTabFactory nutzt
|
||||
generator_tab = super().create_generator_tab()
|
||||
|
||||
# Signal verbinden
|
||||
generator_tab.start_requested.connect(self.start_account_creation)
|
||||
|
||||
@ -11,7 +11,7 @@ from typing import Dict, Any
|
||||
|
||||
from controllers.platform_controllers.base_controller import BasePlatformController
|
||||
from controllers.platform_controllers.base_worker_thread import BaseAccountCreationWorkerThread
|
||||
from views.tabs.generator_tab import GeneratorTab
|
||||
from views.tabs.generator_tab_factory import GeneratorTabFactory
|
||||
from views.tabs.accounts_tab import AccountsTab
|
||||
from views.tabs.settings_tab import SettingsTab
|
||||
from views.widgets.forge_animation_widget import ForgeAnimationDialog
|
||||
@ -178,7 +178,8 @@ class InstagramController(BasePlatformController):
|
||||
|
||||
def create_generator_tab(self):
|
||||
"""Erstellt den Instagram-Generator-Tab."""
|
||||
generator_tab = GeneratorTab(self.platform_name, self.language_manager)
|
||||
# Verwende die Basisimplementierung, die die GeneratorTabFactory nutzt
|
||||
generator_tab = super().create_generator_tab()
|
||||
|
||||
# Instagram-spezifische Anpassungen
|
||||
# Diese Methode überschreiben, wenn spezifische Anpassungen benötigt werden
|
||||
@ -412,4 +413,4 @@ class InstagramController(BasePlatformController):
|
||||
"birthday": "Geburtsdatum"
|
||||
}
|
||||
|
||||
return field_labels.get(field_type, field_type.capitalize())
|
||||
return field_labels.get(field_type, field_type.capitalize())
|
||||
|
||||
@ -7,7 +7,6 @@ from PyQt5.QtCore import QThread, pyqtSignal
|
||||
|
||||
from controllers.platform_controllers.base_controller import BasePlatformController
|
||||
from controllers.platform_controllers.base_worker_thread import BaseAccountCreationWorkerThread
|
||||
from views.tabs.generator_tab import GeneratorTab
|
||||
from views.widgets.forge_animation_widget import ForgeAnimationDialog
|
||||
|
||||
from social_networks.ok_ru.ok_ru_automation import OkRuAutomation
|
||||
@ -44,7 +43,8 @@ class OkRuController(BasePlatformController):
|
||||
|
||||
def create_generator_tab(self):
|
||||
"""Erstellt den Generator-Tab für OK.ru."""
|
||||
generator_tab = GeneratorTab(self.platform_name, self.language_manager)
|
||||
# Verwende die Basisimplementierung, die die GeneratorTabFactory nutzt
|
||||
generator_tab = super().create_generator_tab()
|
||||
|
||||
# OK.ru verwendet nur Telefon-Registrierung
|
||||
# Keine spezielle Konfiguration nötig, da GeneratorTab standardmäßig alle Felder hat
|
||||
@ -190,4 +190,4 @@ class OkRuController(BasePlatformController):
|
||||
self.forge_dialog = None
|
||||
|
||||
# Normale Verarbeitung
|
||||
self.handle_account_created(result)
|
||||
self.handle_account_created(result)
|
||||
|
||||
@ -10,7 +10,7 @@ from typing import Dict, Any
|
||||
|
||||
from controllers.platform_controllers.base_controller import BasePlatformController
|
||||
from controllers.platform_controllers.base_worker_thread import BaseAccountCreationWorkerThread
|
||||
from views.tabs.generator_tab import GeneratorTab
|
||||
from views.tabs.generator_tab_factory import GeneratorTabFactory
|
||||
from views.tabs.accounts_tab import AccountsTab
|
||||
from views.tabs.settings_tab import SettingsTab
|
||||
from views.widgets.forge_animation_widget import ForgeAnimationDialog
|
||||
@ -183,7 +183,8 @@ class TikTokController(BasePlatformController):
|
||||
|
||||
def create_generator_tab(self):
|
||||
"""Erstellt den TikTok-Generator-Tab."""
|
||||
generator_tab = GeneratorTab(self.platform_name, self.language_manager)
|
||||
# Verwende die Basisimplementierung, die die GeneratorTabFactory nutzt
|
||||
generator_tab = super().create_generator_tab()
|
||||
|
||||
# TikTok-spezifische Anpassungen
|
||||
# Diese Methode überschreiben, wenn spezifische Anpassungen benötigt werden
|
||||
@ -416,4 +417,4 @@ class TikTokController(BasePlatformController):
|
||||
self.forge_dialog = None
|
||||
|
||||
# Normale Verarbeitung
|
||||
self.handle_account_created(result)
|
||||
self.handle_account_created(result)
|
||||
|
||||
@ -11,7 +11,7 @@ from typing import Dict, Any, Tuple
|
||||
|
||||
from controllers.platform_controllers.base_controller import BasePlatformController
|
||||
from controllers.platform_controllers.base_worker_thread import BaseAccountCreationWorkerThread
|
||||
from views.tabs.generator_tab import GeneratorTab
|
||||
from views.tabs.generator_tab_factory import GeneratorTabFactory
|
||||
from views.tabs.accounts_tab import AccountsTab
|
||||
from views.tabs.settings_tab import SettingsTab
|
||||
from views.widgets.forge_animation_widget import ForgeAnimationDialog
|
||||
@ -180,7 +180,8 @@ class XController(BasePlatformController):
|
||||
|
||||
def create_generator_tab(self):
|
||||
"""Erstellt den X-Generator-Tab."""
|
||||
generator_tab = GeneratorTab(self.platform_name, self.language_manager)
|
||||
# Verwende die Basisimplementierung, die die GeneratorTabFactory nutzt
|
||||
generator_tab = super().create_generator_tab()
|
||||
|
||||
# X-spezifische Anpassungen
|
||||
# Diese Methode überschreiben, wenn spezifische Anpassungen benötigt werden
|
||||
@ -414,4 +415,4 @@ class XController(BasePlatformController):
|
||||
"birthday": "Geburtsdatum"
|
||||
}
|
||||
|
||||
return field_labels.get(field_type, field_type.capitalize())
|
||||
return field_labels.get(field_type, field_type.capitalize())
|
||||
|
||||
Binäre Datei nicht angezeigt.
150
tests/test_generator_tab_factory.py
Normale Datei
150
tests/test_generator_tab_factory.py
Normale Datei
@ -0,0 +1,150 @@
|
||||
"""
|
||||
Unit-Tests für GeneratorTabFactory.
|
||||
Validiert die Factory-Implementierung und plattform-spezifische Tab-Erstellung.
|
||||
"""
|
||||
|
||||
import unittest
|
||||
import sys
|
||||
import os
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
# Füge Projekt-Root zum Path hinzu
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from PyQt5.QtWidgets import QApplication, QWidget
|
||||
from views.tabs.generator_tab_factory import GeneratorTabFactory, create_generator_tab
|
||||
from views.tabs.generator_tab import GeneratorTab
|
||||
|
||||
|
||||
class TestGeneratorTabFactory(unittest.TestCase):
|
||||
"""
|
||||
Test-Suite für GeneratorTabFactory.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""Erstelle QApplication für Qt-Widgets."""
|
||||
if not QApplication.instance():
|
||||
cls.app = QApplication([])
|
||||
else:
|
||||
cls.app = QApplication.instance()
|
||||
|
||||
def setUp(self):
|
||||
"""Setup vor jedem Test."""
|
||||
# Registry zurücksetzen
|
||||
GeneratorTabFactory.clear_registry()
|
||||
self.language_manager = MagicMock()
|
||||
|
||||
def test_create_generic_tab_for_unknown_platform(self):
|
||||
"""Test: Factory erstellt generischen Tab für unbekannte Plattform."""
|
||||
tab = GeneratorTabFactory.create_tab("unknown_platform", self.language_manager)
|
||||
|
||||
self.assertIsInstance(tab, QWidget)
|
||||
self.assertIsInstance(tab, GeneratorTab)
|
||||
|
||||
def test_create_facebook_tab(self):
|
||||
"""Test: Factory erstellt FacebookGeneratorTab für Facebook."""
|
||||
tab = GeneratorTabFactory.create_tab("facebook", self.language_manager)
|
||||
|
||||
self.assertIsInstance(tab, QWidget)
|
||||
# Prüfe ob es der Facebook-spezifische Tab ist
|
||||
# FacebookGeneratorTab hat gender_male, gender_female, gender_custom Attribute
|
||||
self.assertTrue(hasattr(tab, 'gender_male'), "Facebook-Tab sollte gender_male haben")
|
||||
self.assertTrue(hasattr(tab, 'gender_female'), "Facebook-Tab sollte gender_female haben")
|
||||
self.assertTrue(hasattr(tab, 'gender_custom'), "Facebook-Tab sollte gender_custom haben")
|
||||
|
||||
def test_case_insensitive_platform_names(self):
|
||||
"""Test: Plattform-Namen sind case-insensitive."""
|
||||
tab1 = GeneratorTabFactory.create_tab("FACEBOOK", self.language_manager)
|
||||
tab2 = GeneratorTabFactory.create_tab("Facebook", self.language_manager)
|
||||
tab3 = GeneratorTabFactory.create_tab("facebook", self.language_manager)
|
||||
|
||||
# Alle sollten Facebook-Tabs sein
|
||||
for tab in [tab1, tab2, tab3]:
|
||||
self.assertTrue(hasattr(tab, 'gender_male'))
|
||||
|
||||
def test_registry_functionality(self):
|
||||
"""Test: Tab-Registry funktioniert korrekt."""
|
||||
# Erstelle Mock-Tab-Klasse
|
||||
class MockTab(QWidget):
|
||||
def __init__(self, platform, language_manager):
|
||||
super().__init__()
|
||||
self.platform = platform
|
||||
self.language_manager = language_manager
|
||||
|
||||
# Registriere Mock-Tab
|
||||
GeneratorTabFactory.register_tab("test_platform", MockTab)
|
||||
|
||||
# Erstelle Tab
|
||||
tab = GeneratorTabFactory.create_tab("test_platform", self.language_manager)
|
||||
|
||||
self.assertIsInstance(tab, MockTab)
|
||||
self.assertEqual(tab.platform, "test_platform")
|
||||
|
||||
def test_lazy_loading(self):
|
||||
"""Test: Tabs werden lazy geladen."""
|
||||
# Registry sollte initial leer sein
|
||||
self.assertEqual(len(GeneratorTabFactory._tab_registry), 0)
|
||||
|
||||
# Erstelle Facebook-Tab
|
||||
tab = GeneratorTabFactory.create_tab("facebook", self.language_manager)
|
||||
|
||||
# Jetzt sollte Facebook in Registry sein
|
||||
self.assertIn("facebook", GeneratorTabFactory._tab_registry)
|
||||
|
||||
def test_get_supported_platforms(self):
|
||||
"""Test: Liste der unterstützten Plattformen."""
|
||||
platforms = GeneratorTabFactory.get_supported_platforms()
|
||||
|
||||
# Sollte bekannte Plattformen enthalten
|
||||
self.assertIn("facebook", platforms)
|
||||
self.assertIn("instagram", platforms)
|
||||
self.assertIn("tiktok", platforms)
|
||||
self.assertIn("x", platforms)
|
||||
|
||||
def test_is_platform_supported(self):
|
||||
"""Test: Plattform-Support-Prüfung."""
|
||||
self.assertTrue(GeneratorTabFactory.is_platform_supported("facebook"))
|
||||
self.assertTrue(GeneratorTabFactory.is_platform_supported("FACEBOOK"))
|
||||
self.assertFalse(GeneratorTabFactory.is_platform_supported("unknown"))
|
||||
|
||||
def test_convenience_function(self):
|
||||
"""Test: Convenience-Funktion create_generator_tab."""
|
||||
tab = create_generator_tab("facebook", self.language_manager)
|
||||
|
||||
self.assertIsInstance(tab, QWidget)
|
||||
self.assertTrue(hasattr(tab, 'gender_male'))
|
||||
|
||||
def test_error_handling_fallback(self):
|
||||
"""Test: Factory fällt auf generischen Tab zurück bei Fehlern."""
|
||||
# Simuliere einen Fehler beim Tab-Erstellen
|
||||
with patch('views.tabs.facebook_generator_tab.FacebookGeneratorTab.__init__',
|
||||
side_effect=Exception("Test error")):
|
||||
|
||||
tab = GeneratorTabFactory.create_tab("facebook", self.language_manager)
|
||||
|
||||
# Sollte auf generischen Tab zurückfallen
|
||||
self.assertIsInstance(tab, GeneratorTab)
|
||||
|
||||
def test_signal_compatibility(self):
|
||||
"""Test: Alle Tabs haben die erforderlichen Signale."""
|
||||
platforms = ["facebook", "instagram", "tiktok", "x"]
|
||||
|
||||
for platform in platforms:
|
||||
tab = GeneratorTabFactory.create_tab(platform, self.language_manager)
|
||||
|
||||
# Prüfe erforderliche Signale
|
||||
self.assertTrue(hasattr(tab, 'start_requested'),
|
||||
f"{platform}-Tab sollte start_requested Signal haben")
|
||||
self.assertTrue(hasattr(tab, 'stop_requested'),
|
||||
f"{platform}-Tab sollte stop_requested Signal haben")
|
||||
self.assertTrue(hasattr(tab, 'account_created'),
|
||||
f"{platform}-Tab sollte account_created Signal haben")
|
||||
|
||||
def tearDown(self):
|
||||
"""Cleanup nach jedem Test."""
|
||||
GeneratorTabFactory.clear_registry()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@ -30,8 +30,10 @@ class FacebookGeneratorTab(QWidget):
|
||||
self.init_ui()
|
||||
|
||||
if self.language_manager:
|
||||
self.language_manager.language_changed.connect(self.update_texts)
|
||||
self.update_texts()
|
||||
# Nur echte LanguageManager haben language_changed Signal
|
||||
if hasattr(self.language_manager, 'language_changed'):
|
||||
self.language_manager.language_changed.connect(self.update_texts)
|
||||
self.update_texts()
|
||||
|
||||
def init_ui(self):
|
||||
"""Initialisiert die UI mit Facebook-spezifischen Feldern."""
|
||||
|
||||
@ -29,8 +29,10 @@ class GeneratorTab(QWidget):
|
||||
self.language_manager = language_manager
|
||||
self.init_ui()
|
||||
if self.language_manager:
|
||||
self.language_manager.language_changed.connect(self.update_texts)
|
||||
self.update_texts()
|
||||
# Nur echte LanguageManager haben language_changed Signal
|
||||
if hasattr(self.language_manager, 'language_changed'):
|
||||
self.language_manager.language_changed.connect(self.update_texts)
|
||||
self.update_texts()
|
||||
|
||||
def init_ui(self):
|
||||
"""Initialisiert die Benutzeroberfläche."""
|
||||
|
||||
185
views/tabs/generator_tab_factory.py
Normale Datei
185
views/tabs/generator_tab_factory.py
Normale Datei
@ -0,0 +1,185 @@
|
||||
"""
|
||||
Factory Pattern für die Erstellung plattform-spezifischer Generator-Tabs.
|
||||
Clean Architecture Implementation für erweiterbare Tab-Generierung.
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import Optional, Dict, Type
|
||||
from PyQt5.QtWidgets import QWidget
|
||||
|
||||
# Base imports
|
||||
from views.tabs.generator_tab import GeneratorTab
|
||||
|
||||
logger = logging.getLogger("generator_tab_factory")
|
||||
|
||||
|
||||
class GeneratorTabFactory:
|
||||
"""
|
||||
Factory-Klasse zur Erstellung plattform-spezifischer Generator-Tabs.
|
||||
|
||||
Diese Factory verwendet das Strategy Pattern intern, um verschiedene
|
||||
Tab-Implementierungen basierend auf der Plattform zu erstellen.
|
||||
Neue Plattformen können einfach durch Hinzufügen zur Registry erweitert werden.
|
||||
"""
|
||||
|
||||
# Registry für plattform-spezifische Tabs
|
||||
# Key: Plattform-Name (lowercase), Value: Tab-Klasse
|
||||
_tab_registry: Dict[str, Type[QWidget]] = {}
|
||||
|
||||
@classmethod
|
||||
def register_tab(cls, platform: str, tab_class: Type[QWidget]) -> None:
|
||||
"""
|
||||
Registriert eine Tab-Klasse für eine bestimmte Plattform.
|
||||
|
||||
Args:
|
||||
platform: Name der Plattform (wird zu lowercase konvertiert)
|
||||
tab_class: Die Tab-Klasse für diese Plattform
|
||||
"""
|
||||
platform_lower = platform.lower()
|
||||
cls._tab_registry[platform_lower] = tab_class
|
||||
logger.info(f"Tab-Klasse {tab_class.__name__} für Plattform '{platform}' registriert")
|
||||
|
||||
@classmethod
|
||||
def create_tab(cls, platform: str, language_manager: Optional[object] = None) -> QWidget:
|
||||
"""
|
||||
Erstellt einen Generator-Tab für die angegebene Plattform.
|
||||
|
||||
Diese Methode verwendet Lazy Loading für plattform-spezifische Tabs,
|
||||
um zirkuläre Imports zu vermeiden und die Performance zu optimieren.
|
||||
|
||||
Args:
|
||||
platform: Name der Plattform
|
||||
language_manager: Optionaler Language Manager für Internationalisierung
|
||||
|
||||
Returns:
|
||||
QWidget: Der erstellte Generator-Tab
|
||||
|
||||
Raises:
|
||||
ValueError: Wenn die Plattform nicht unterstützt wird
|
||||
"""
|
||||
platform_lower = platform.lower()
|
||||
|
||||
# Lazy Loading und Registrierung für bekannte Plattformen
|
||||
if platform_lower not in cls._tab_registry:
|
||||
cls._lazy_load_platform_tab(platform_lower)
|
||||
|
||||
# Tab-Klasse aus Registry holen
|
||||
tab_class = cls._tab_registry.get(platform_lower)
|
||||
|
||||
if tab_class:
|
||||
logger.info(f"Erstelle {tab_class.__name__} für Plattform '{platform}'")
|
||||
try:
|
||||
return tab_class(platform, language_manager)
|
||||
except Exception as e:
|
||||
logger.error(f"Fehler beim Erstellen des Tabs für '{platform}': {e}")
|
||||
logger.info(f"Fallback auf generischen GeneratorTab für '{platform}'")
|
||||
return GeneratorTab(platform, language_manager)
|
||||
else:
|
||||
# Fallback auf generischen Tab
|
||||
logger.info(f"Verwende generischen GeneratorTab für Plattform '{platform}'")
|
||||
return GeneratorTab(platform, language_manager)
|
||||
|
||||
@classmethod
|
||||
def _lazy_load_platform_tab(cls, platform: str) -> None:
|
||||
"""
|
||||
Lädt plattform-spezifische Tab-Klassen lazy (bei Bedarf).
|
||||
|
||||
Dies vermeidet zirkuläre Imports und verbessert die Startzeit,
|
||||
indem nur benötigte Module geladen werden.
|
||||
|
||||
Args:
|
||||
platform: Name der Plattform (lowercase)
|
||||
"""
|
||||
try:
|
||||
if platform == "facebook":
|
||||
from views.tabs.facebook_generator_tab import FacebookGeneratorTab
|
||||
cls.register_tab("facebook", FacebookGeneratorTab)
|
||||
|
||||
elif platform == "instagram":
|
||||
# Instagram verwendet möglicherweise einen spezifischen Tab
|
||||
# Vorerst den generischen Tab verwenden
|
||||
cls.register_tab("instagram", GeneratorTab)
|
||||
|
||||
elif platform == "tiktok":
|
||||
# TikTok könnte einen eigenen Tab haben
|
||||
# Prüfe ob TikTokGeneratorTab existiert
|
||||
try:
|
||||
from views.tabs.tiktok_generator_tab import TikTokGeneratorTab
|
||||
cls.register_tab("tiktok", TikTokGeneratorTab)
|
||||
except ImportError:
|
||||
# Fallback auf generischen Tab
|
||||
cls.register_tab("tiktok", GeneratorTab)
|
||||
|
||||
elif platform == "x":
|
||||
# X (Twitter) Tab
|
||||
try:
|
||||
from views.tabs.x_generator_tab import XGeneratorTab
|
||||
cls.register_tab("x", XGeneratorTab)
|
||||
except ImportError:
|
||||
cls.register_tab("x", GeneratorTab)
|
||||
|
||||
else:
|
||||
# Unbekannte Plattform - verwende generischen Tab
|
||||
cls.register_tab(platform, GeneratorTab)
|
||||
|
||||
except ImportError as e:
|
||||
logger.warning(f"Konnte spezifischen Tab für '{platform}' nicht laden: {e}")
|
||||
# Registriere generischen Tab als Fallback
|
||||
cls.register_tab(platform, GeneratorTab)
|
||||
|
||||
@classmethod
|
||||
def get_supported_platforms(cls) -> list:
|
||||
"""
|
||||
Gibt eine Liste der unterstützten Plattformen zurück.
|
||||
|
||||
Returns:
|
||||
list: Liste der Plattform-Namen
|
||||
"""
|
||||
# Bekannte Plattformen, die lazy geladen werden können
|
||||
known_platforms = ["facebook", "instagram", "tiktok", "x"]
|
||||
|
||||
# Bereits registrierte Plattformen hinzufügen
|
||||
registered = list(cls._tab_registry.keys())
|
||||
|
||||
# Kombiniere und entferne Duplikate
|
||||
all_platforms = list(set(known_platforms + registered))
|
||||
all_platforms.sort()
|
||||
|
||||
return all_platforms
|
||||
|
||||
@classmethod
|
||||
def is_platform_supported(cls, platform: str) -> bool:
|
||||
"""
|
||||
Prüft, ob eine Plattform unterstützt wird.
|
||||
|
||||
Args:
|
||||
platform: Name der Plattform
|
||||
|
||||
Returns:
|
||||
bool: True wenn unterstützt, sonst False
|
||||
"""
|
||||
return platform.lower() in cls.get_supported_platforms()
|
||||
|
||||
@classmethod
|
||||
def clear_registry(cls) -> None:
|
||||
"""
|
||||
Löscht die Tab-Registry.
|
||||
Hauptsächlich für Tests und Cleanup.
|
||||
"""
|
||||
cls._tab_registry.clear()
|
||||
logger.debug("Tab-Registry gelöscht")
|
||||
|
||||
|
||||
# Convenience-Funktion für direkten Import
|
||||
def create_generator_tab(platform: str, language_manager: Optional[object] = None) -> QWidget:
|
||||
"""
|
||||
Convenience-Funktion zum Erstellen eines Generator-Tabs.
|
||||
|
||||
Args:
|
||||
platform: Name der Plattform
|
||||
language_manager: Optionaler Language Manager
|
||||
|
||||
Returns:
|
||||
QWidget: Der erstellte Generator-Tab
|
||||
"""
|
||||
return GeneratorTabFactory.create_tab(platform, language_manager)
|
||||
@ -23,13 +23,13 @@ class ForgeAnimationDialog(QDialog):
|
||||
# Timer für das regelmäßige Nach-vorne-Holen
|
||||
self.raise_timer = QTimer()
|
||||
self.raise_timer.timeout.connect(self._raise_to_front)
|
||||
self.raise_timer.setInterval(500) # Alle 500ms
|
||||
self.raise_timer.setInterval(1000) # Alle 1000ms (weniger aggressiv)
|
||||
|
||||
def init_ui(self):
|
||||
"""Initialisiert die UI mit verbessertem Design"""
|
||||
# Dialog-Fenster ohne Stay-on-Top, um Browser nicht zu blockieren
|
||||
# Entfernt Qt.WindowStaysOnTopHint, da dies den Browser-Fokus stören kann
|
||||
self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint)
|
||||
# Dialog-Fenster mit Stay-on-Top für Sichtbarkeit
|
||||
# WindowStaysOnTopHint sorgt dafür, dass die Warnung immer sichtbar bleibt
|
||||
self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
|
||||
self.setModal(False) # Nicht modal - blockiert nicht das Hauptfenster
|
||||
self.setFixedSize(650, 600) # Ursprüngliche Größe beibehalten
|
||||
|
||||
@ -187,8 +187,8 @@ class ForgeAnimationDialog(QDialog):
|
||||
def start_animation(self):
|
||||
"""Zeigt den Dialog an"""
|
||||
self.status_label.setText("Initialisiere...")
|
||||
# Timer deaktiviert - verhindert Fokus-Probleme mit dem Browser
|
||||
# self.raise_timer.start() # Deaktiviert: Stört Browser-Interaktion
|
||||
# Timer aktiviert als Fallback für Window-Manager die TopHint ignorieren
|
||||
self.raise_timer.start() # Fallback: Hält Dialog zuverlässig im Vordergrund
|
||||
|
||||
def stop_animation(self):
|
||||
"""Stoppt die Animation und den Timer"""
|
||||
@ -227,9 +227,9 @@ class ForgeAnimationDialog(QDialog):
|
||||
super().keyPressEvent(event)
|
||||
|
||||
def _raise_to_front(self):
|
||||
"""Holt den Dialog in den Vordergrund"""
|
||||
"""Holt den Dialog in den Vordergrund ohne Fokus zu stehlen"""
|
||||
self.raise_()
|
||||
# Nicht activateWindow() aufrufen - das holt das Hauptfenster mit
|
||||
# Nicht activateWindow() aufrufen - das würde den Fokus vom Browser stehlen
|
||||
|
||||
def show(self):
|
||||
"""Überschreibt show() um den Dialog richtig zu positionieren"""
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren