""" Erfolgs-Dialog für Profil-Export Zeigt exportierte Dateien und optional das generierte Passwort an. """ import os import logging import subprocess import platform from pathlib import Path from typing import List, Optional from PyQt5.QtWidgets import ( QDialog, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QFrame, QGraphicsDropShadowEffect, QApplication, QScrollArea, QWidget ) from PyQt5.QtCore import Qt from PyQt5.QtGui import QFont, QColor logger = logging.getLogger("export_success_dialog") class ExportSuccessDialog(QDialog): """Dialog zur Anzeige von Export-Erfolg""" def __init__( self, parent=None, exported_files: List[str] = None, export_directory: str = "", password: Optional[str] = None ): """ Initialisiert den Erfolgs-Dialog. Args: parent: Parent-Widget exported_files: Liste der exportierten Dateinamen export_directory: Verzeichnis wo Dateien gespeichert wurden password: Optional generiertes Passwort (nur bei Passwortschutz) """ super().__init__(parent) self.exported_files = exported_files or [] self.export_directory = export_directory self.password = password self.init_ui() def init_ui(self): """Initialisiert die UI""" # Dialog-Eigenschaften self.setWindowTitle("Export erfolgreich") self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint) self.setAttribute(Qt.WA_TranslucentBackground, True) self.setModal(True) # Dynamische Höhe basierend auf Inhalt base_height = 280 if self.password: base_height += 80 # Extra Platz für Passwort-Anzeige if len(self.exported_files) > 2: base_height += 20 * (len(self.exported_files) - 2) # Extra für mehr Dateien self.setFixedSize(500, min(base_height, 500)) # Hauptlayout main_layout = QVBoxLayout(self) main_layout.setContentsMargins(20, 20, 20, 20) # Container mit modernem Design self.container = QFrame() self.container.setObjectName("exportSuccessContainer") self.container.setStyleSheet(""" #exportSuccessContainer { background-color: white; border-radius: 12px; border: 1px solid #E5E7EB; } """) # Schatten-Effekt shadow = QGraphicsDropShadowEffect() shadow.setBlurRadius(30) shadow.setXOffset(0) shadow.setYOffset(10) shadow.setColor(QColor(0, 0, 0, 80)) self.container.setGraphicsEffect(shadow) # Container-Layout container_layout = QVBoxLayout(self.container) container_layout.setSpacing(18) container_layout.setContentsMargins(30, 25, 30, 25) # Header mit Icon und Titel header_layout = QHBoxLayout() header_layout.setSpacing(15) # Erfolgs-Icon icon_label = QLabel("✅") icon_label.setStyleSheet("font-size: 32px;") icon_label.setFixedSize(40, 40) icon_label.setAlignment(Qt.AlignCenter) # Titel title_label = QLabel("Profil exportiert!") title_font = QFont("Poppins", 16) title_font.setWeight(QFont.DemiBold) title_label.setFont(title_font) title_label.setStyleSheet("color: #1F2937;") header_layout.addWidget(icon_label) header_layout.addWidget(title_label, 1) container_layout.addLayout(header_layout) # Dateien-Liste files_label = QLabel("Dateien:") files_label.setStyleSheet("color: #6B7280; font-size: 13px; font-weight: 600;") container_layout.addWidget(files_label) # Scrollbare Liste für Dateien scroll_area = QScrollArea() scroll_area.setWidgetResizable(True) scroll_area.setFrameShape(QFrame.NoFrame) scroll_area.setStyleSheet(""" QScrollArea { background-color: #F9FAFB; border-radius: 6px; border: 1px solid #E5E7EB; } """) files_widget = QWidget() files_layout = QVBoxLayout(files_widget) files_layout.setSpacing(4) files_layout.setContentsMargins(10, 10, 10, 10) for filename in self.exported_files: file_label = QLabel(f"• {filename}") file_label.setStyleSheet(""" color: #374151; font-size: 12px; font-family: 'Courier New', monospace; padding: 2px; """) file_label.setWordWrap(True) files_layout.addWidget(file_label) files_layout.addStretch() scroll_area.setWidget(files_widget) scroll_area.setMaximumHeight(120) container_layout.addWidget(scroll_area) # Passwort-Anzeige (nur wenn Passwort vorhanden) if self.password: password_frame = QFrame() password_frame.setStyleSheet(""" QFrame { background-color: #FEF3C7; border: 1px solid #FCD34D; border-radius: 6px; padding: 12px; } """) password_layout = QVBoxLayout(password_frame) password_layout.setSpacing(8) # Warnung warning_label = QLabel("⚠ Bitte Passwort speichern!") warning_label.setStyleSheet(""" color: #92400E; font-size: 13px; font-weight: 600; """) # Passwort mit Copy-Button password_row = QHBoxLayout() password_row.setSpacing(10) password_label = QLabel(f"🔒 Passwort: {self.password}") password_label.setStyleSheet(""" color: #78350F; font-size: 13px; font-family: 'Courier New', monospace; font-weight: 600; """) password_label.setTextInteractionFlags(Qt.TextSelectableByMouse) copy_button = QPushButton("Kopieren") copy_button.setMaximumWidth(80) copy_button.setMinimumHeight(28) copy_button.setCursor(Qt.PointingHandCursor) copy_button.setStyleSheet(""" QPushButton { background-color: #F59E0B; color: white; border: none; border-radius: 4px; font-size: 12px; font-weight: 600; padding: 4px 8px; } QPushButton:hover { background-color: #D97706; } QPushButton:pressed { background-color: #B45309; } """) copy_button.clicked.connect(self.copy_password) password_row.addWidget(password_label, 1) password_row.addWidget(copy_button) password_layout.addWidget(warning_label) password_layout.addLayout(password_row) container_layout.addWidget(password_frame) # Speicherort location_label = QLabel(f"Gespeichert in:") location_label.setStyleSheet("color: #6B7280; font-size: 12px;") path_label = QLabel(self._format_path(self.export_directory)) path_label.setStyleSheet(""" color: #4B5563; font-size: 11px; font-family: 'Courier New', monospace; """) path_label.setWordWrap(True) path_label.setTextInteractionFlags(Qt.TextSelectableByMouse) container_layout.addWidget(location_label) container_layout.addWidget(path_label) # Spacer container_layout.addStretch() # Button-Layout button_layout = QHBoxLayout() button_layout.setSpacing(10) button_layout.addStretch() # Ordner öffnen Button self.open_folder_button = QPushButton("Ordner öffnen") self.open_folder_button.setMinimumHeight(38) self.open_folder_button.setMinimumWidth(120) self.open_folder_button.setCursor(Qt.PointingHandCursor) self.open_folder_button.setStyleSheet(""" QPushButton { background-color: #F3F4F6; color: #374151; border: none; border-radius: 6px; font-size: 13px; font-weight: 600; padding: 8px 16px; } QPushButton:hover { background-color: #E5E7EB; } QPushButton:pressed { background-color: #D1D5DB; } """) self.open_folder_button.clicked.connect(self.open_folder) # OK Button self.ok_button = QPushButton("OK") self.ok_button.setMinimumHeight(38) self.ok_button.setMinimumWidth(100) self.ok_button.setCursor(Qt.PointingHandCursor) self.ok_button.setStyleSheet(""" QPushButton { background-color: #10B981; color: white; border: none; border-radius: 6px; font-size: 13px; font-weight: 600; padding: 8px 16px; } QPushButton:hover { background-color: #059669; } QPushButton:pressed { background-color: #047857; } """) self.ok_button.clicked.connect(self.accept) button_layout.addWidget(self.open_folder_button) button_layout.addWidget(self.ok_button) container_layout.addLayout(button_layout) # Container zum Hauptlayout hinzufügen main_layout.addWidget(self.container) def copy_password(self): """Kopiert das Passwort in die Zwischenablage""" if self.password: clipboard = QApplication.clipboard() clipboard.setText(self.password) logger.info("Passwort in Zwischenablage kopiert") # Kurzes visuelles Feedback sender = self.sender() if sender: original_text = sender.text() sender.setText("✓ Kopiert!") sender.setStyleSheet(sender.styleSheet().replace("#F59E0B", "#10B981")) # Nach 2 Sekunden zurücksetzen from PyQt5.QtCore import QTimer QTimer.singleShot(2000, lambda: self._reset_copy_button(sender, original_text)) def _reset_copy_button(self, button, original_text): """Setzt den Copy-Button zurück""" if button: button.setText(original_text) button.setStyleSheet(button.styleSheet().replace("#10B981", "#F59E0B")) def open_folder(self): """Öffnet den Export-Ordner im Datei-Explorer""" if not self.export_directory or not os.path.exists(self.export_directory): logger.warning(f"Export-Verzeichnis existiert nicht: {self.export_directory}") return try: system = platform.system() if system == "Windows": # Windows Explorer os.startfile(self.export_directory) elif system == "Darwin": # macOS Finder subprocess.run(["open", self.export_directory]) elif system == "Linux": # Linux File Manager subprocess.run(["xdg-open", self.export_directory]) else: logger.warning(f"Unbekanntes Betriebssystem: {system}") logger.info(f"Ordner geöffnet: {self.export_directory}") except Exception as e: logger.error(f"Fehler beim Öffnen des Ordners: {e}") def _format_path(self, path: str) -> str: """ Formatiert den Pfad für die Anzeige. Kürzt zu lange Pfade. """ if not path: return "" max_length = 60 if len(path) <= max_length: return path # Pfad kürzen: Anfang ... Ende start_length = 25 end_length = max_length - start_length - 3 return f"{path[:start_length]}...{path[-end_length:]}" # Helper-Funktion für einfache Verwendung def show_export_success( parent, exported_files: List[str], export_directory: str, password: Optional[str] = None ): """ Zeigt den Export-Erfolgs-Dialog modal an. Args: parent: Parent-Widget exported_files: Liste der exportierten Dateinamen export_directory: Verzeichnis wo Dateien gespeichert wurden password: Optional generiertes Passwort """ dialog = ExportSuccessDialog(parent, exported_files, export_directory, password) dialog.exec_()