304 Zeilen
11 KiB
Python
304 Zeilen
11 KiB
Python
"""
|
|
Controller für Profil-Export
|
|
|
|
Orchestriert den Export-Prozess von Account-Profilen.
|
|
"""
|
|
|
|
import os
|
|
import logging
|
|
from typing import Optional, Dict, Any
|
|
from pathlib import Path
|
|
|
|
from PyQt5.QtWidgets import QFileDialog
|
|
|
|
from database.db_manager import DatabaseManager
|
|
from utils.profile_export_service import ProfileExportService
|
|
from views.dialogs.profile_export_dialog import show_export_dialog
|
|
from views.dialogs.export_success_dialog import show_export_success
|
|
from views.widgets.modern_message_box import show_error, show_warning
|
|
|
|
logger = logging.getLogger("profile_export_controller")
|
|
|
|
|
|
class ProfileExportController:
|
|
"""Controller für Account-Profil-Export"""
|
|
|
|
def __init__(self, db_manager: DatabaseManager):
|
|
"""
|
|
Initialisiert den Export-Controller.
|
|
|
|
Args:
|
|
db_manager: Datenbank-Manager
|
|
"""
|
|
self.db_manager = db_manager
|
|
self.export_service = ProfileExportService()
|
|
|
|
def export_account(self, parent_widget, account_id: int) -> bool:
|
|
"""
|
|
Startet den Export-Prozess für einen Account.
|
|
|
|
Args:
|
|
parent_widget: Parent-Widget für Dialoge
|
|
account_id: ID des zu exportierenden Accounts
|
|
|
|
Returns:
|
|
True bei Erfolg, False bei Fehler oder Abbruch
|
|
"""
|
|
try:
|
|
# 1. Account-Daten aus DB laden
|
|
logger.info(f"Starte Export für Account-ID: {account_id}")
|
|
account_data = self.db_manager.get_account(account_id)
|
|
|
|
if not account_data:
|
|
logger.error(f"Account nicht gefunden: ID {account_id}")
|
|
show_error(
|
|
parent_widget,
|
|
"Account nicht gefunden",
|
|
f"Account mit ID {account_id} konnte nicht gefunden werden."
|
|
)
|
|
return False
|
|
|
|
username = account_data.get("username", "Unbekannt")
|
|
logger.info(f"Account geladen: {username}")
|
|
|
|
# 2. Export-Dialog anzeigen
|
|
accepted, formats, password_protect = show_export_dialog(parent_widget, username)
|
|
|
|
if not accepted:
|
|
logger.info("Export abgebrochen durch Nutzer")
|
|
return False
|
|
|
|
logger.info(f"Export-Optionen: Formate={formats}, Passwort={password_protect}")
|
|
|
|
# 3. Speicherort wählen
|
|
save_directory = self._select_save_location(parent_widget, account_data, formats)
|
|
|
|
if not save_directory:
|
|
logger.info("Kein Speicherort ausgewählt - Export abgebrochen")
|
|
return False
|
|
|
|
logger.info(f"Speicherort: {save_directory}")
|
|
|
|
# 4. Export durchführen (ohne Passwortschutz)
|
|
files_dict = self.export_service.export_account(
|
|
account_data,
|
|
formats,
|
|
password_protect=False
|
|
)
|
|
|
|
if not files_dict:
|
|
logger.error("Keine Dateien wurden generiert")
|
|
show_error(
|
|
parent_widget,
|
|
"Export fehlgeschlagen",
|
|
"Beim Export ist ein Fehler aufgetreten."
|
|
)
|
|
return False
|
|
|
|
# 5. Dateien speichern
|
|
saved_files = []
|
|
for filename, content in files_dict.items():
|
|
file_path = os.path.join(save_directory, filename)
|
|
try:
|
|
with open(file_path, 'wb') as f:
|
|
f.write(content)
|
|
saved_files.append(filename)
|
|
logger.info(f"Datei gespeichert: {filename}")
|
|
except Exception as e:
|
|
logger.error(f"Fehler beim Speichern von {filename}: {e}")
|
|
show_error(
|
|
parent_widget,
|
|
"Fehler beim Speichern",
|
|
f"Datei {filename} konnte nicht gespeichert werden:\n{str(e)}"
|
|
)
|
|
return False
|
|
|
|
# 6. Erfolgs-Dialog anzeigen
|
|
show_export_success(
|
|
parent_widget,
|
|
saved_files,
|
|
save_directory
|
|
)
|
|
|
|
logger.info(f"Export erfolgreich: {len(saved_files)} Datei(en) gespeichert")
|
|
return True
|
|
|
|
except Exception as e:
|
|
logger.error(f"Fehler beim Export: {e}", exc_info=True)
|
|
|
|
# Benutzerfreundliche Fehlermeldungen
|
|
error_message = str(e)
|
|
|
|
if "reportlab" in error_message.lower():
|
|
error_message = (
|
|
"PDF-Export ist nicht verfügbar.\n\n"
|
|
"Bitte installieren Sie die erforderlichen Bibliotheken:\n"
|
|
"pip install reportlab svglib"
|
|
)
|
|
|
|
show_error(
|
|
parent_widget,
|
|
"Export fehlgeschlagen",
|
|
f"Beim Export ist ein Fehler aufgetreten:\n\n{error_message}"
|
|
)
|
|
return False
|
|
|
|
def _select_save_location(
|
|
self,
|
|
parent_widget,
|
|
account_data: Dict[str, Any],
|
|
formats: list
|
|
) -> Optional[str]:
|
|
"""
|
|
Öffnet einen Verzeichnis-Dialog zur Auswahl des Speicherorts.
|
|
|
|
Args:
|
|
parent_widget: Parent-Widget
|
|
account_data: Account-Daten
|
|
formats: Liste der Export-Formate
|
|
|
|
Returns:
|
|
Ausgewähltes Verzeichnis oder None bei Abbruch
|
|
"""
|
|
# Standard-Speicherort: Benutzer-Downloads-Ordner
|
|
default_directory = str(Path.home() / "Downloads")
|
|
|
|
# Verzeichnis-Dialog für mehrere Dateien
|
|
directory = QFileDialog.getExistingDirectory(
|
|
parent_widget,
|
|
"Speicherort für Export auswählen",
|
|
default_directory
|
|
)
|
|
|
|
return directory if directory else None
|
|
|
|
def export_multiple_accounts(self, parent_widget, account_ids: list) -> bool:
|
|
"""
|
|
Exportiert mehrere Accounts gleichzeitig.
|
|
|
|
Args:
|
|
parent_widget: Parent-Widget
|
|
account_ids: Liste von Account-IDs
|
|
|
|
Returns:
|
|
True bei Erfolg, False bei Fehler
|
|
"""
|
|
try:
|
|
if not account_ids:
|
|
logger.warning("Keine Account-IDs zum Export übergeben")
|
|
return False
|
|
|
|
logger.info(f"Starte Batch-Export für {len(account_ids)} Accounts")
|
|
|
|
# 1. Alle Account-Daten laden
|
|
accounts_data = []
|
|
for account_id in account_ids:
|
|
account_data = self.db_manager.get_account(account_id)
|
|
if account_data:
|
|
accounts_data.append(account_data)
|
|
else:
|
|
logger.warning(f"Account ID {account_id} nicht gefunden")
|
|
|
|
if not accounts_data:
|
|
show_error(
|
|
parent_widget,
|
|
"Keine Accounts gefunden",
|
|
"Keiner der ausgewählten Accounts konnte geladen werden."
|
|
)
|
|
return False
|
|
|
|
logger.info(f"{len(accounts_data)} Accounts erfolgreich geladen")
|
|
|
|
# 2. Export-Dialog anzeigen
|
|
accepted, formats, _ = show_export_dialog(parent_widget, f"{len(accounts_data)} Accounts")
|
|
|
|
if not accepted:
|
|
logger.info("Batch-Export abgebrochen durch Nutzer")
|
|
return False
|
|
|
|
logger.info(f"Batch-Export-Optionen: Formate={formats}")
|
|
|
|
# 3. Hauptordner wählen
|
|
from datetime import datetime
|
|
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M")
|
|
suggested_folder_name = f"AccountForge_Export_{timestamp}"
|
|
|
|
save_directory = QFileDialog.getExistingDirectory(
|
|
parent_widget,
|
|
"Hauptordner für Batch-Export auswählen",
|
|
str(Path.home() / "Downloads" / suggested_folder_name)
|
|
)
|
|
|
|
if not save_directory:
|
|
logger.info("Kein Speicherort ausgewählt - Export abgebrochen")
|
|
return False
|
|
|
|
# Hauptordner erstellen falls nicht vorhanden
|
|
os.makedirs(save_directory, exist_ok=True)
|
|
logger.info(f"Batch-Export-Ordner: {save_directory}")
|
|
|
|
# 4. Für jeden Account exportieren
|
|
exported_files = []
|
|
failed_accounts = []
|
|
|
|
for account_data in accounts_data:
|
|
username = account_data.get("username", "unknown")
|
|
platform = account_data.get("platform", "unknown").lower()
|
|
|
|
try:
|
|
# Plattform-Unterordner erstellen
|
|
platform_dir = os.path.join(save_directory, platform)
|
|
os.makedirs(platform_dir, exist_ok=True)
|
|
|
|
# Export durchführen
|
|
files_dict = self.export_service.export_account(
|
|
account_data,
|
|
formats,
|
|
password_protect=False
|
|
)
|
|
|
|
# Dateien mit vereinfachten Namen speichern (ohne Timestamp)
|
|
for filename, content in files_dict.items():
|
|
# Vereinfachter Name: username.extension
|
|
ext = filename.split('.')[-1]
|
|
simple_filename = f"{username}.{ext}"
|
|
file_path = os.path.join(platform_dir, simple_filename)
|
|
|
|
with open(file_path, 'wb') as f:
|
|
f.write(content)
|
|
|
|
exported_files.append(f"{platform}/{simple_filename}")
|
|
logger.info(f"Exportiert: {platform}/{simple_filename}")
|
|
|
|
except Exception as e:
|
|
logger.error(f"Fehler beim Export von {username}: {e}")
|
|
failed_accounts.append(username)
|
|
|
|
# 5. Erfolgs-Dialog anzeigen
|
|
show_export_success(
|
|
parent_widget,
|
|
exported_files,
|
|
save_directory
|
|
)
|
|
|
|
if failed_accounts:
|
|
show_warning(
|
|
parent_widget,
|
|
"Teilweise erfolgreich",
|
|
f"Export abgeschlossen, aber {len(failed_accounts)} Account(s) fehlgeschlagen:\n" +
|
|
"\n".join(f"- {name}" for name in failed_accounts[:5]) +
|
|
(f"\n... und {len(failed_accounts)-5} weitere" if len(failed_accounts) > 5 else "")
|
|
)
|
|
|
|
logger.info(f"Batch-Export erfolgreich: {len(exported_files)} Datei(en)")
|
|
return True
|
|
|
|
except Exception as e:
|
|
logger.error(f"Fehler beim Batch-Export: {e}", exc_info=True)
|
|
show_error(
|
|
parent_widget,
|
|
"Batch-Export fehlgeschlagen",
|
|
f"Beim Batch-Export ist ein Fehler aufgetreten:\n\n{str(e)}"
|
|
)
|
|
return False
|