forked from AG_QGIS/Plugin_SN_Basis
qt_wrapper, dialog;wrapper, Pruef_ergebnis und Pruefmanager überarbeitet, so dass die Übergaben jetzt stimmen. Nutzerabfragen werden tatsächlich ausgelöst- Nutzerabfrage Datei überschreiebn... ist noch Blödsinn
This commit is contained in:
@@ -1,66 +1,45 @@
|
||||
"""
|
||||
sn_basis/modules/Pruefmanager.py
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
from typing import Optional, Any
|
||||
|
||||
from sn_basis.functions import (
|
||||
ask_yes_no,
|
||||
info,
|
||||
warning,
|
||||
error,
|
||||
set_layer_visible,
|
||||
)
|
||||
|
||||
from sn_basis.functions import ask_yes_no, info, warning, error
|
||||
from sn_basis.modules.pruef_ergebnis import pruef_ergebnis, PruefAktion
|
||||
|
||||
print("DEBUG: Pruefmanager DATEI GELADEN:", __file__)
|
||||
|
||||
class Pruefmanager:
|
||||
"""
|
||||
Zentrale Verarbeitung von pruef_ergebnis-Objekten.
|
||||
|
||||
Erwartete öffentliche API (verwendet von Core-Komponenten wie DataGrabber):
|
||||
- report_error(thema, meldung, *, aktion: Optional[PruefAktion]=None, kontext=None) -> None
|
||||
- request_decision(pruef_res) -> str
|
||||
- report_summary(summary: dict) -> None
|
||||
- verarbeite(ergebnis: pruef_ergebnis) -> pruef_ergebnis
|
||||
"""
|
||||
|
||||
def __init__(self, ui_modus: str = "qgis", parent: Optional[Any] = None):
|
||||
def __init__(self, ui_modus: str = "qgis", parent: Optional[Any] = None) -> None:
|
||||
self.ui_modus = ui_modus
|
||||
self.parent = parent
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Basis-API: Meldungen / Zusammenfassungen
|
||||
# ---------------------------------------------------------------------
|
||||
def report_error(self, thema: str, meldung: str, *, aktion: Optional[PruefAktion] = None, kontext: Optional[Any] = None) -> None:
|
||||
"""
|
||||
Einheitliche Meldung für Fehler/Warnungen aus dem Core.
|
||||
Keine Rückgabe; dient als zentraler Hook für Logging/UI.
|
||||
"""
|
||||
# ------------------------------------------------------------------
|
||||
# Meldungen / Zusammenfassungen
|
||||
# ------------------------------------------------------------------
|
||||
def report_error(
|
||||
self,
|
||||
thema: str,
|
||||
meldung: str,
|
||||
*,
|
||||
aktion: Optional[PruefAktion] = None,
|
||||
kontext: Optional[Any] = None,
|
||||
) -> None:
|
||||
critical_actions = {
|
||||
"netzwerkfehler",
|
||||
"pruefe_exception",
|
||||
"save_exception",
|
||||
"layer_create_failed",
|
||||
"read_error",
|
||||
"open_error",
|
||||
"netzwerkfehler", "pruefe_exception", "save_exception",
|
||||
"layer_create_failed", "read_error", "open_error",
|
||||
}
|
||||
warn_actions = {
|
||||
"datei_nicht_gefunden",
|
||||
"pfad_nicht_gefunden",
|
||||
"url_nicht_erreichbar",
|
||||
"falsche_endung",
|
||||
"kein_header",
|
||||
"kein_arbeitsblatt",
|
||||
"datei_nicht_gefunden", "pfad_nicht_gefunden", "url_nicht_erreichbar",
|
||||
"falsche_endung", "kein_header", "kein_arbeitsblatt",
|
||||
}
|
||||
|
||||
if aktion in critical_actions:
|
||||
error(thema, meldung)
|
||||
return
|
||||
|
||||
if aktion in warn_actions:
|
||||
warning(thema, meldung)
|
||||
return
|
||||
|
||||
# Default: informative Warnung
|
||||
warning(thema, meldung)
|
||||
|
||||
def report_summary(self, summary: dict) -> None:
|
||||
@@ -75,202 +54,159 @@ class Pruefmanager:
|
||||
f"Dienste ausserhalb: {len(ausserhalb)}\n"
|
||||
f"Fehler: {len(fehler)}"
|
||||
)
|
||||
|
||||
info("DataGrabber Zusammenfassung", message)
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Entscheidungs-API
|
||||
# ---------------------------------------------------------------------
|
||||
def request_decision(self, pruef_res: Any) -> str:
|
||||
"""
|
||||
Synchronously request a decision from the user (or return a default in headless mode).
|
||||
# ------------------------------------------------------------------
|
||||
# VERFAHRENS-DB-spezifische Entscheidungen
|
||||
# ------------------------------------------------------------------
|
||||
def _handle_datei_existiert(self, ergebnis: pruef_ergebnis) -> pruef_ergebnis:
|
||||
if self.ui_modus != "qgis":
|
||||
return ergebnis
|
||||
|
||||
Returns one of:
|
||||
- "abort"
|
||||
- "continue"
|
||||
- "temporaer_erzeugen"
|
||||
- "ignore"
|
||||
"""
|
||||
aktion = getattr(pruef_res, "aktion", None)
|
||||
meldung = getattr(pruef_res, "meldung", str(pruef_res))
|
||||
pfad = ergebnis.kontext
|
||||
pfad_str = str(pfad) if pfad else "unbekannt"
|
||||
|
||||
titel = "Verfahrens-DB existiert bereits"
|
||||
meldung = (
|
||||
f"Die Datei '{pfad_str}' existiert bereits.\n\n"
|
||||
"Was soll geschehen?\n\n"
|
||||
"• **Überschreiben**: Bestehende Layer ersetzen\n"
|
||||
"• **Anhängen**: Neue Layer hinzufügen\n"
|
||||
"• **Überspringen**: Nur temporäre Layer erzeugen"
|
||||
)
|
||||
|
||||
# Vereinfacht: Erst Überschreiben? → Dann Anhängen? → Überspringen
|
||||
if ask_yes_no(
|
||||
titel,
|
||||
f"{meldung}\n\n**Überschreiben** (alle Layer ersetzen)?",
|
||||
default=False,
|
||||
parent=self.parent
|
||||
):
|
||||
return pruef_ergebnis(
|
||||
ok=True,
|
||||
aktion="datei_existiert_ueberschreiben",
|
||||
kontext=ergebnis.kontext,
|
||||
)
|
||||
|
||||
if ask_yes_no(
|
||||
titel,
|
||||
f"{meldung}\n\n**Anhängen** (neue Layer hinzufügen)?",
|
||||
default=False,
|
||||
parent=self.parent
|
||||
):
|
||||
return pruef_ergebnis(
|
||||
ok=True,
|
||||
aktion="datei_existiert_anhaengen",
|
||||
kontext=ergebnis.kontext,
|
||||
)
|
||||
|
||||
if ask_yes_no(
|
||||
titel,
|
||||
f"{meldung}\n\n**Überspringen** (nur temporäre Layer)?",
|
||||
default=True,
|
||||
parent=self.parent
|
||||
):
|
||||
return pruef_ergebnis(
|
||||
ok=True,
|
||||
aktion="datei_existiert_ueberspringen",
|
||||
kontext=ergebnis.kontext,
|
||||
)
|
||||
|
||||
return ergebnis
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Basis-Entscheidungen (KORREKT: → pruef_ergebnis)
|
||||
# ------------------------------------------------------------------
|
||||
def _handle_basic_decision(self, ergebnis: pruef_ergebnis) -> pruef_ergebnis:
|
||||
"""Basis-Entscheidung für einfache Ja/Nein-Fragen."""
|
||||
print(f"DEBUG _handle_basic_decision: aktion='{ergebnis.aktion}', ui_modus='{self.ui_modus}'")
|
||||
|
||||
if self.ui_modus != "qgis":
|
||||
print("DEBUG: Nicht QGIS → ergebnis unverändert")
|
||||
return ergebnis
|
||||
|
||||
title_map = {
|
||||
"leereingabe_erlaubt": "Ohne Eingabe fortfahren",
|
||||
"standarddatei_vorschlagen": "Standarddatei verwenden",
|
||||
"temporaer_erlaubt": "Temporäre Layer erzeugen",
|
||||
"layer_unsichtbar": "Layer einblenden",
|
||||
}
|
||||
|
||||
title = title_map.get(ergebnis.aktion, "Entscheidung erforderlich")
|
||||
meldung = ergebnis.meldung or ""
|
||||
|
||||
try:
|
||||
print(f"DEBUG ask_yes_no: title='{title}', meldung='{meldung[:50]}...'")
|
||||
yes = ask_yes_no(title, meldung, default=False, parent=self.parent)
|
||||
print(f"DEBUG ask_yes_no: yes={yes}")
|
||||
except Exception as e:
|
||||
print(f"DEBUG ask_yes_no Exception: {e}")
|
||||
return ergebnis
|
||||
|
||||
if not yes:
|
||||
print("DEBUG: Nutzer sagte Nein → ok=False")
|
||||
return ergebnis
|
||||
|
||||
# Nutzer sagte Ja
|
||||
if ergebnis.aktion == "temporaer_erlaubt":
|
||||
print("DEBUG: temporaer_erlaubt bestätigt → ok=True")
|
||||
return pruef_ergebnis(
|
||||
ok=True,
|
||||
aktion="temporaer_erlaubt",
|
||||
kontext=ergebnis.kontext
|
||||
)
|
||||
|
||||
print("DEBUG: Andere Aktion bestätigt → ok=True, aktion='ok'")
|
||||
return pruef_ergebnis(
|
||||
ok=True,
|
||||
aktion="ok",
|
||||
kontext=ergebnis.kontext
|
||||
)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Hauptlogik: verarbeite() (KORRIGIERT!)
|
||||
# ------------------------------------------------------------------
|
||||
def verarbeite(self, ergebnis: pruef_ergebnis) -> pruef_ergebnis:
|
||||
print("🔥 verarbeite() START")
|
||||
print("DEBUG Pruefmanager:", ergebnis.ok, ergebnis.aktion)
|
||||
print("DEBUG ergebnis.aktion TYPE:", type(ergebnis.aktion), repr(ergebnis.aktion))
|
||||
|
||||
# 1. Erfolg → direkt weiter
|
||||
print("🔍 Schritt 1: Prüfe ergebnis.ok =", ergebnis.ok)
|
||||
if ergebnis.ok:
|
||||
print("✅ Schritt 1: ok=True → return")
|
||||
return ergebnis
|
||||
|
||||
# 2. VERFAHRENS-DB: Bestehende Datei
|
||||
print("🔍 Schritt 2: Prüfe datei_existiert =", ergebnis.aktion == "datei_existiert")
|
||||
if ergebnis.aktion == "datei_existiert":
|
||||
print("✅ Schritt 2: _handle_datei_existiert")
|
||||
return self._handle_datei_existiert(ergebnis)
|
||||
|
||||
# 3. Basis interaktive Aktionen
|
||||
print("🔍 Schritt 3: Definiere interactive_actions")
|
||||
interactive_actions = {
|
||||
"leereingabe_erlaubt",
|
||||
"standarddatei_vorschlagen",
|
||||
"standarddatei_vorschlagen",
|
||||
"temporaer_erlaubt",
|
||||
"layer_unsichtbar",
|
||||
}
|
||||
print("DEBUG interactive_actions:", repr(interactive_actions))
|
||||
print("DEBUG ergebnis.aktion in interactive_actions?", ergebnis.aktion in interactive_actions)
|
||||
|
||||
if ergebnis.aktion in interactive_actions:
|
||||
print("✅ Schritt 3: Interaktive Aktion → _handle_basic_decision")
|
||||
decision = self._handle_basic_decision(ergebnis)
|
||||
print(f"DEBUG: _handle_basic_decision Ergebnis: ok={decision.ok}, aktion='{decision.aktion}'")
|
||||
return decision
|
||||
|
||||
if aktion in interactive_actions:
|
||||
if self.ui_modus == "qgis":
|
||||
title_map = {
|
||||
"leereingabe_erlaubt": "Ohne Eingabe fortfahren",
|
||||
"standarddatei_vorschlagen": "Standarddatei verwenden",
|
||||
"temporaer_erlaubt": "Temporäre Datei erzeugen",
|
||||
"layer_unsichtbar": "Layer einblenden",
|
||||
}
|
||||
title = title_map.get(aktion, "Entscheidung erforderlich")
|
||||
try:
|
||||
yes = ask_yes_no(title, meldung, default=False, parent=self.parent)
|
||||
except Exception:
|
||||
return "abort"
|
||||
if yes:
|
||||
if aktion == "temporaer_erlaubt":
|
||||
return "temporaer_erzeugen"
|
||||
return "continue"
|
||||
return "abort"
|
||||
|
||||
if self.ui_modus == "headless":
|
||||
return "abort"
|
||||
|
||||
informational_actions = {
|
||||
"leer",
|
||||
"datei_nicht_gefunden",
|
||||
"pfad_nicht_gefunden",
|
||||
"url_nicht_erreichbar",
|
||||
"netzwerkfehler",
|
||||
"falscher_geotyp",
|
||||
"layer_leer",
|
||||
"falscher_layertyp",
|
||||
"falsches_crs",
|
||||
"felder_fehlen",
|
||||
"datenquelle_unerwartet",
|
||||
"layer_nicht_editierbar",
|
||||
"kein_header",
|
||||
"kein_arbeitsblatt",
|
||||
"read_error",
|
||||
"open_error",
|
||||
"pflichtfelder_fehlen",
|
||||
}
|
||||
if aktion in informational_actions:
|
||||
return "abort"
|
||||
|
||||
return "abort"
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Höhere Abstraktion: verarbeite
|
||||
# ---------------------------------------------------------------------
|
||||
def verarbeite(self, ergebnis: pruef_ergebnis) -> pruef_ergebnis:
|
||||
"""
|
||||
Verarbeitet ein pruef_ergebnis-Objekt und führt ggf. Nutzerinteraktion durch.
|
||||
Liefert ein ggf. modifiziertes pruef_ergebnis zurück.
|
||||
"""
|
||||
if ergebnis.ok:
|
||||
return ergebnis
|
||||
|
||||
aktion = ergebnis.aktion
|
||||
kontext = ergebnis.kontext
|
||||
meldung = ergebnis.meldung
|
||||
|
||||
# Zentrale Meldung
|
||||
self.report_error(aktion or "pruefung", meldung or "", aktion=aktion, kontext=kontext)
|
||||
|
||||
# Interaktive Entscheidungen
|
||||
if aktion in ("leereingabe_erlaubt", "standarddatei_vorschlagen", "temporaer_erlaubt", "layer_unsichtbar"):
|
||||
decision = self.request_decision(ergebnis)
|
||||
if decision == "temporaer_erzeugen":
|
||||
return pruef_ergebnis(ok=True, meldung="Temporäre Datei soll erzeugt werden.", aktion="temporaer_erzeugen", kontext=None)
|
||||
if decision == "continue":
|
||||
return pruef_ergebnis(ok=True, meldung="Fortgefahren.", aktion="ok", kontext=kontext)
|
||||
return ergebnis # abort / unverändert
|
||||
|
||||
# Spezielle Excel/Importer-Fälle: klare Meldungen, keine interaktive Entscheidung
|
||||
if aktion == "kein_header":
|
||||
warning("Excel-Import", meldung or "")
|
||||
return ergebnis
|
||||
|
||||
if aktion == "kein_arbeitsblatt":
|
||||
warning("Excel-Import", meldung or "")
|
||||
return ergebnis
|
||||
|
||||
if aktion in ("read_error", "open_error"):
|
||||
error("Excel-Import", meldung or "")
|
||||
return ergebnis
|
||||
|
||||
if aktion == "datei_nicht_gefunden":
|
||||
warning("Datei nicht gefunden", meldung or "")
|
||||
return ergebnis
|
||||
|
||||
# Spezieller Fall: layer_unsichtbar (falls nicht interaktiv behandelt)
|
||||
if aktion == "layer_unsichtbar":
|
||||
if kontext is not None:
|
||||
try:
|
||||
set_layer_visible(kontext, True)
|
||||
return pruef_ergebnis(ok=True, meldung="Layer wurde eingeblendet.", aktion="ok", kontext=kontext)
|
||||
except Exception:
|
||||
return ergebnis
|
||||
return ergebnis
|
||||
|
||||
# Standard: keine Änderung
|
||||
# 4. Fehler behandeln
|
||||
print("❌ Schritt 4: FEHLER BEHANDELN")
|
||||
self.report_error(
|
||||
thema=ergebnis.aktion or "pruefung",
|
||||
meldung=ergebnis.meldung or "",
|
||||
aktion=ergebnis.aktion,
|
||||
kontext=ergebnis.kontext,
|
||||
)
|
||||
print("🔥 verarbeite() ENDE mit ok=False")
|
||||
return ergebnis
|
||||
def ask_overwrite_append_cancel(self, layer_name: str, default: str = "overwrite") -> str:
|
||||
"""
|
||||
Zeigt dem Nutzer eine Auswahl für einen bereits existierenden Layer an.
|
||||
|
||||
Rückgabe
|
||||
-------
|
||||
str
|
||||
Einer der Werte: "overwrite", "append", "cancel".
|
||||
|
||||
Verhalten
|
||||
--------
|
||||
- Verwendet bevorzugt die UI-Wrapper-Funktion `qt_wrapper` / `qgisui_wrapper`,
|
||||
falls vorhanden (z. B. ein QMessageBox-Dialog mit drei Buttons).
|
||||
- Im Mock- oder Headless-Modus (kein Qt/QGIS verfügbar) wird der übergebene
|
||||
`default`-Wert zurückgegeben.
|
||||
- Alle Nutzerinteraktionen laufen über diese zentrale Methode, damit das
|
||||
Plugin an einer Stelle gesteuert und ggf. getested werden kann.
|
||||
|
||||
Parameter
|
||||
---------
|
||||
layer_name:
|
||||
Anzeigename des Layers, der bereits existiert (wird im Dialog angezeigt).
|
||||
default:
|
||||
Rückgabewert im Headless/Mock-Modus oder wenn der Dialog nicht verfügbar ist.
|
||||
Gültige Werte: "overwrite", "append", "cancel". Standard: "overwrite".
|
||||
"""
|
||||
# Validierung des Defaults
|
||||
if default not in ("overwrite", "append", "cancel"):
|
||||
default = "overwrite"
|
||||
|
||||
# Versuche, eine UI-Wrapper-Funktion zu verwenden, falls vorhanden
|
||||
try:
|
||||
# qgisui_wrapper kann eine spezialisierte Dialogfunktion bereitstellen
|
||||
from sn_basis.functions import qgisui_wrapper as qgisui
|
||||
ask_fn = getattr(qgisui, "ask_overwrite_append_cancel", None)
|
||||
if callable(ask_fn):
|
||||
# Die Wrapper-Funktion soll genau die drei Strings zurückgeben
|
||||
choice = ask_fn(layer_name)
|
||||
if choice in ("overwrite", "append", "cancel"):
|
||||
return choice
|
||||
except Exception:
|
||||
# Falls Import/Wrapper fehlschlägt, weiter zum Qt-Fallback
|
||||
pass
|
||||
|
||||
# Fallback: direkte Qt-Dialoge über qt_wrapper (wenn verfügbar)
|
||||
try:
|
||||
from sn_basis.functions import qt_wrapper as qt
|
||||
QMessageBox = getattr(qt, "QMessageBox", None)
|
||||
if QMessageBox is not None:
|
||||
# Erzeuge und konfiguriere Dialog
|
||||
msg = QMessageBox()
|
||||
msg.setWindowTitle("Layer bereits vorhanden")
|
||||
msg.setText(f"Der Layer '{layer_name}' existiert bereits. Was möchten Sie tun?")
|
||||
overwrite_btn = msg.addButton("Überschreiben", QMessageBox.AcceptRole)
|
||||
append_btn = msg.addButton("Anhängen", QMessageBox.AcceptRole)
|
||||
cancel_btn = msg.addButton("Abbrechen", QMessageBox.RejectRole)
|
||||
msg.setDefaultButton(overwrite_btn)
|
||||
# Blockierend anzeigen
|
||||
msg.exec_()
|
||||
clicked = msg.clickedButton()
|
||||
if clicked == overwrite_btn:
|
||||
return "overwrite"
|
||||
if clicked == append_btn:
|
||||
return "append"
|
||||
return "cancel"
|
||||
except Exception:
|
||||
# Qt nicht verfügbar oder Fehler beim Dialogaufbau
|
||||
pass
|
||||
|
||||
# Headless / Mock: gib Default zurück
|
||||
return default
|
||||
|
||||
Reference in New Issue
Block a user