Export drin noch nicht komplett
Dieser Commit ist enthalten in:
234
controllers/profile_export_controller.py
Normale Datei
234
controllers/profile_export_controller.py
Normale Datei
@ -0,0 +1,234 @@
|
||||
"""
|
||||
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, password_protect)
|
||||
|
||||
if not save_directory:
|
||||
logger.info("Kein Speicherort ausgewählt - Export abgebrochen")
|
||||
return False
|
||||
|
||||
logger.info(f"Speicherort: {save_directory}")
|
||||
|
||||
# 4. Export durchführen
|
||||
files_dict, password = self.export_service.export_account(
|
||||
account_data,
|
||||
formats,
|
||||
password_protect
|
||||
)
|
||||
|
||||
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,
|
||||
password
|
||||
)
|
||||
|
||||
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"
|
||||
)
|
||||
elif "pyzipper" in error_message.lower():
|
||||
error_message = (
|
||||
"Passwortgeschützter Export ist nicht verfügbar.\n\n"
|
||||
"Bitte installieren Sie die erforderliche Bibliothek:\n"
|
||||
"pip install pyzipper"
|
||||
)
|
||||
|
||||
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,
|
||||
password_protect: bool
|
||||
) -> Optional[str]:
|
||||
"""
|
||||
Öffnet einen Datei-Dialog zur Auswahl des Speicherorts.
|
||||
|
||||
Args:
|
||||
parent_widget: Parent-Widget
|
||||
account_data: Account-Daten
|
||||
formats: Liste der Export-Formate
|
||||
password_protect: Ob Passwortschutz aktiviert ist
|
||||
|
||||
Returns:
|
||||
Ausgewähltes Verzeichnis oder None bei Abbruch
|
||||
"""
|
||||
# Standard-Dateiname generieren
|
||||
if password_protect:
|
||||
# Bei Passwortschutz wird eine ZIP erstellt
|
||||
default_filename = self.export_service.generate_filename(
|
||||
account_data,
|
||||
"zip"
|
||||
)
|
||||
else:
|
||||
# Ohne Passwortschutz: Ersten Format als Beispiel nehmen
|
||||
first_format = formats[0] if formats else "csv"
|
||||
default_filename = self.export_service.generate_filename(
|
||||
account_data,
|
||||
first_format
|
||||
)
|
||||
|
||||
# Standard-Speicherort: Benutzer-Downloads-Ordner
|
||||
default_directory = str(Path.home() / "Downloads")
|
||||
|
||||
if password_protect:
|
||||
# Für ZIP: File-Dialog
|
||||
file_path, _ = QFileDialog.getSaveFileName(
|
||||
parent_widget,
|
||||
"Profil exportieren",
|
||||
os.path.join(default_directory, default_filename),
|
||||
"ZIP-Archiv (*.zip)"
|
||||
)
|
||||
|
||||
if not file_path:
|
||||
return None
|
||||
|
||||
# Verzeichnis aus Dateipfad extrahieren
|
||||
return os.path.dirname(file_path)
|
||||
else:
|
||||
# Für mehrere Dateien: Verzeichnis-Dialog
|
||||
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.
|
||||
|
||||
HINWEIS: Diese Funktion ist vorbereitet für zukünftige Erweiterung,
|
||||
wird aber gemäß ROADMAP.md vorerst NICHT implementiert (YAGNI).
|
||||
|
||||
Args:
|
||||
parent_widget: Parent-Widget
|
||||
account_ids: Liste von Account-IDs
|
||||
|
||||
Returns:
|
||||
True bei Erfolg, False bei Fehler
|
||||
"""
|
||||
show_warning(
|
||||
parent_widget,
|
||||
"Nicht verfügbar",
|
||||
"Mehrfach-Export ist derzeit nicht verfügbar.\n"
|
||||
"Bitte exportieren Sie Accounts einzeln."
|
||||
)
|
||||
return False
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren