""" sn_basis/functions/dialog_wrapper.py – Benutzer-Dialoge (Qt5/6/Mock-kompatibel) """ from typing import Any from typing import Literal, Optional from sn_basis.functions.qt_wrapper import ( QMessageBox, YES, NO, CANCEL, QT_VERSION, exec_dialog, ICON_QUESTION, QProgressDialog, QCoreApplication, Qt, ) def ask_yes_no( title: str, message: str, default: bool = True, parent: Any = None, ) -> bool: """ Stellt Ja/Nein-Frage. Funktioniert in PyQt5/6 UND Mock-Modus. """ try: if QT_VERSION == 0: # Mock-Modus print(f"🔍 Mock-Modus: ask_yes_no('{title}') → {default}") return default # ✅ KORREKT: Verwende YES/NO-Aliase aus qt_wrapper! buttons = YES | NO default_button = YES if default else NO result = QMessageBox.question( parent, title, message, buttons, default_button ) # ✅ int(result) == int(YES) funktioniert Qt5/6/Mock print(f"DEBUG ask_yes_no: result={result}, YES={YES}, match={int(result) == int(YES)}") return int(result) == int(YES) except Exception as e: print(f"⚠️ ask_yes_no Fehler: {e}") return default OverwriteDecision = Optional[Literal["overwrite", "append", "cancel"]] def ask_overwrite_append_cancel_custom( parent, title: str, message: str, ) -> Literal["overwrite", "append", "cancel"]: """Zeigt Dialog mit benutzerdefinierten Buttons: Überschreiben/Anhängen/Abbrechen. Parameters ---------- parent : Eltern-Widget oder None. title : str Dialog-Titel. message : str Hauptmeldung mit Erklärung. Returns ------- Literal["overwrite", "append", "cancel"] Genaue Entscheidung des Nutzers. """ msg = QMessageBox(parent) msg.setIcon(ICON_QUESTION) msg.setWindowTitle(title) msg.setText(message) # Eigene Buttons mit exakten Texten overwrite_btn = msg.addButton("Überschreiben", QMessageBox.ButtonRole.AcceptRole) append_btn = msg.addButton("Anhängen", QMessageBox.ButtonRole.ActionRole) cancel_btn = msg.addButton("Abbrechen", QMessageBox.ButtonRole.RejectRole) exec_dialog(msg) clicked = msg.clickedButton() if clicked == overwrite_btn: return "overwrite" elif clicked == append_btn: return "append" else: # cancel_btn return "cancel" class ProgressDialog: def __init__(self, total: int, title: str = "Fortschritt", label: str = "Verarbeite..."): self.total = max(total, 1) self._canceled = False if QT_VERSION == 0: self.value = 0 self.label = label self.title = title return self._dlg = QProgressDialog(label, "Abbrechen", 0, self.total) self._dlg.setWindowTitle(title) # Qt5 vs Qt6: WindowModality-Enum unterschiedlich verfügbar modality = None if hasattr(Qt, "WindowModality"): try: modality = Qt.WindowModality.WindowModal except Exception: modality = None if modality is None and hasattr(Qt, "WindowModal"): modality = Qt.WindowModal if modality is not None: try: self._dlg.setWindowModality(modality) except Exception: pass self._dlg.setMinimumDuration(0) self._dlg.setAutoClose(False) self._dlg.setAutoReset(False) self._dlg.setValue(0) def on_cancel(): if self._dlg and self._dlg.value() >= self.total: # OK-Button am Ende self._dlg.close() return self._canceled = True self._dlg.close() try: self._dlg.canceled.connect(on_cancel) except Exception: pass def set_total(self, total: int) -> None: self.total = max(total, 1) if QT_VERSION == 0: return if self._dlg is not None: self._dlg.setMaximum(self.total) def set_value(self, value: int) -> None: if QT_VERSION == 0: self.value = value return if self._dlg is not None: self._dlg.setValue(min(value, self.total)) if value >= self.total: self._dlg.setLabelText("Fertig. Klicken Sie auf OK, um das Fenster zu schließen.") self._dlg.setCancelButtonText("OK") QCoreApplication.processEvents() def set_label(self, text: str) -> None: if QT_VERSION == 0: self.label = text return if self._dlg is not None: self._dlg.setLabelText(text) QCoreApplication.processEvents() def is_canceled(self) -> bool: if QT_VERSION == 0: return self._canceled if self._dlg is not None: return self._canceled or self._dlg.wasCanceled() return self._canceled def close(self) -> None: if QT_VERSION == 0: return if self._dlg is not None: self._dlg.close() def create_progress_dialog(total: int, title: str = "Fortschritt", label: str = "Verarbeite...") -> ProgressDialog: return ProgressDialog(total, title, label)