Compare commits

4 Commits

5 changed files with 261 additions and 4 deletions

View File

@@ -5,7 +5,7 @@ from typing import Any
from typing import Literal, Optional from typing import Literal, Optional
from sn_basis.functions.qt_wrapper import ( from sn_basis.functions.qt_wrapper import (
QMessageBox, YES, NO, CANCEL, QT_VERSION, exec_dialog, ICON_QUESTION, QMessageBox, YES, NO, CANCEL, QT_VERSION, exec_dialog, ICON_QUESTION,
QProgressDialog, QCoreApplication, Qt, QProgressDialog, QCoreApplication, Qt, QInputDialog, QLineEdit,
) )
def ask_yes_no( def ask_yes_no(
@@ -39,6 +39,50 @@ def ask_yes_no(
return default return default
def show_info_dialog(title: str, message: str, parent: Any = None) -> None:
"""
Zeigt einen modalen Info-Dialog mit OK-Button.
Blockiert bis der Nutzer bestätigt.
"""
try:
if QT_VERSION == 0: # Mock-Modus
print(f"Mock-Modus: show_info_dialog('{title}')")
return
QMessageBox.information(parent, title, message)
except Exception as e:
print(f"⚠️ show_info_dialog Fehler: {e}")
def ask_text(
title: str,
label: str,
default_text: str = "",
parent: Any = None,
) -> tuple[str, bool]:
"""Zeigt einen modalen Texteingabe-Dialog und gibt Text + OK-Status zurück."""
try:
if QT_VERSION == 0: # Mock-Modus
print(f"Mock-Modus: ask_text('{title}') -> '{default_text}'")
return default_text, True
# PyQt6: QLineEdit.EchoMode.Normal / PyQt5: QLineEdit.Normal
echo_mode = (
getattr(QLineEdit, "Normal", None)
or getattr(getattr(QLineEdit, "EchoMode", None), "Normal", None)
or 0
)
text, accepted = QInputDialog.getText(
parent,
title,
label,
echo_mode,
default_text,
)
return str(text or ""), bool(accepted)
except Exception as e:
print(f"⚠️ ask_text Fehler: {e}")
return default_text, False
OverwriteDecision = Optional[Literal["overwrite", "append", "cancel"]] OverwriteDecision = Optional[Literal["overwrite", "append", "cancel"]]

View File

@@ -26,6 +26,13 @@ QgsGeometry: Type[Any]
QgsFeatureRequest: Type[Any] QgsFeatureRequest: Type[Any]
QgsCoordinateTransform: Type[Any] QgsCoordinateTransform: Type[Any]
QgsCoordinateReferenceSystem: Type[Any] QgsCoordinateReferenceSystem: Type[Any]
QgsPrintLayout: Type[Any]
QgsLayoutItemMap: Type[Any]
QgsLayoutItemLabel: Type[Any]
QgsLayoutPoint: Type[Any]
QgsLayoutSize: Type[Any]
QgsUnitTypes: Type[Any]
QgsLayoutItem: Type[Any]
QGIS_AVAILABLE = False QGIS_AVAILABLE = False
@@ -48,6 +55,13 @@ try:
QgsFeatureRequest as _QgsFeatureRequest, QgsFeatureRequest as _QgsFeatureRequest,
QgsCoordinateTransform as _QgsCoordinateTransform, QgsCoordinateTransform as _QgsCoordinateTransform,
QgsCoordinateReferenceSystem as _QgsCoordinateReferenceSystem, QgsCoordinateReferenceSystem as _QgsCoordinateReferenceSystem,
QgsPrintLayout as _QgsPrintLayout,
QgsLayoutItemMap as _QgsLayoutItemMap,
QgsLayoutItemLabel as _QgsLayoutItemLabel,
QgsLayoutPoint as _QgsLayoutPoint,
QgsLayoutSize as _QgsLayoutSize,
QgsUnitTypes as _QgsUnitTypes,
QgsLayoutItem as _QgsLayoutItem,
) )
QgsProject = _QgsProject QgsProject = _QgsProject
@@ -63,6 +77,13 @@ try:
QgsFeatureRequest = _QgsFeatureRequest QgsFeatureRequest = _QgsFeatureRequest
QgsCoordinateTransform = _QgsCoordinateTransform QgsCoordinateTransform = _QgsCoordinateTransform
QgsCoordinateReferenceSystem = _QgsCoordinateReferenceSystem QgsCoordinateReferenceSystem = _QgsCoordinateReferenceSystem
QgsPrintLayout = _QgsPrintLayout
QgsLayoutItemMap = _QgsLayoutItemMap
QgsLayoutItemLabel = _QgsLayoutItemLabel
QgsLayoutPoint = _QgsLayoutPoint
QgsLayoutSize = _QgsLayoutSize
QgsUnitTypes = _QgsUnitTypes
QgsLayoutItem = _QgsLayoutItem
QGIS_AVAILABLE = True QGIS_AVAILABLE = True
@@ -73,9 +94,17 @@ try:
except Exception: except Exception:
QGIS_AVAILABLE = False QGIS_AVAILABLE = False
class _MockLayoutManager:
def layoutByName(self, name: str):
return None
def addLayout(self, layout: Any) -> bool:
return True
class _MockQgsProject: class _MockQgsProject:
def __init__(self): def __init__(self):
self._variables = {} self._variables = {}
self._layout_manager = _MockLayoutManager()
@staticmethod @staticmethod
def instance() -> "_MockQgsProject": def instance() -> "_MockQgsProject":
@@ -84,6 +113,9 @@ except Exception:
def read(self) -> bool: def read(self) -> bool:
return True return True
def layoutManager(self):
return self._layout_manager
QgsProject = _MockQgsProject QgsProject = _MockQgsProject
class _MockQgsVectorLayer: class _MockQgsVectorLayer:
@@ -134,6 +166,110 @@ except Exception:
QgsRasterLayer = _MockQgsRasterLayer QgsRasterLayer = _MockQgsRasterLayer
class _MockQgsPrintLayout:
def __init__(self, project: Any):
self.project = project
self._name = ""
self._page = _MockQgsLayoutPage()
def initializeDefaults(self) -> None:
pass
def setName(self, name: str) -> None:
self._name = name
def pageCollection(self):
return self
def page(self, index: int):
return self._page
def addLayoutItem(self, item: Any) -> None:
pass
class _MockQgsLayoutPage:
def setPageSize(self, size: Any) -> None:
self.size = size
class _MockQgsLayoutItem:
class ReferencePoint:
LowerLeft = 0
class _MockQgsLayoutItemMap:
def __init__(self, layout: Any):
self.layout = layout
def setId(self, item_id: str) -> None:
pass
def setExtent(self, extent: Any) -> None:
pass
def setScale(self, scale: float) -> None:
pass
def attemptMove(self, point: Any) -> None:
pass
def attemptResize(self, size: Any) -> None:
pass
def setFollowVisibilityPreset(self, active: bool) -> None:
pass
def setFollowVisibilityPresetName(self, name: str) -> None:
pass
class _MockQgsLayoutItemLabel:
ModeHtml = 1
def __init__(self, layout: Any):
self.layout = layout
def setId(self, item_id: str) -> None:
pass
def setText(self, text: str) -> None:
pass
def setMode(self, mode: Any) -> None:
pass
def setFont(self, font: Any) -> None:
pass
def setReferencePoint(self, point: Any) -> None:
pass
def attemptMove(self, point: Any) -> None:
pass
def attemptResize(self, size: Any) -> None:
pass
class _MockQgsLayoutPoint:
def __init__(self, x: float, y: float, unit: Any):
self.x = x
self.y = y
self.unit = unit
class _MockQgsLayoutSize:
def __init__(self, width: float, height: float, unit: Any):
self.width = width
self.height = height
self.unit = unit
class _MockQgsUnitTypes:
LayoutMillimeters = 0
QgsPrintLayout = _MockQgsPrintLayout
QgsLayoutItemMap = _MockQgsLayoutItemMap
QgsLayoutItemLabel = _MockQgsLayoutItemLabel
QgsLayoutPoint = _MockQgsLayoutPoint
QgsLayoutSize = _MockQgsLayoutSize
QgsUnitTypes = _MockQgsUnitTypes
QgsLayoutItem = _MockQgsLayoutItem
class _MockQgsFeatureRequest: class _MockQgsFeatureRequest:
def __init__(self): def __init__(self):
self._filter_rect = None self._filter_rect = None

View File

@@ -76,6 +76,9 @@ except Exception:
def removeToolBar(self, *args, **kwargs): def removeToolBar(self, *args, **kwargs):
pass pass
def openLayoutDesigner(self, layout):
return layout
iface = _MockIface() iface = _MockIface()
class _MockQgsFileWidget: class _MockQgsFileWidget:
@@ -132,6 +135,13 @@ def get_main_window():
return None return None
def open_layout_designer(layout: Any) -> Any:
try:
return iface.openLayoutDesigner(layout)
except Exception:
return None
# --------------------------------------------------------- # ---------------------------------------------------------
# Dock-Handling # Dock-Handling
# --------------------------------------------------------- # ---------------------------------------------------------

View File

@@ -29,6 +29,7 @@ QWidget: Type[Any] = object
QGridLayout: Type[Any] = object QGridLayout: Type[Any] = object
QLabel: Type[Any] = object QLabel: Type[Any] = object
QLineEdit: Type[Any] = object QLineEdit: Type[Any] = object
QInputDialog: Type[Any] = object
QGroupBox: Type[Any] = object QGroupBox: Type[Any] = object
QVBoxLayout: Type[Any] = object QVBoxLayout: Type[Any] = object
QPushButton: Type[Any] = object QPushButton: Type[Any] = object
@@ -41,7 +42,9 @@ QToolButton: Type[Any] = object
QSizePolicy: Type[Any] = object QSizePolicy: Type[Any] = object
Qt: Type[Any] = object Qt: Type[Any] = object
QComboBox: Type[Any] = object QComboBox: Type[Any] = object
QCheckBox: Type[Any] = object
QHBoxLayout: Type[Any] = object QHBoxLayout: Type[Any] = object
QFont: Type[Any] = object
def exec_dialog(dialog: Any) -> Any: def exec_dialog(dialog: Any) -> Any:
@@ -73,6 +76,7 @@ try:
QGridLayout as _QGridLayout, QGridLayout as _QGridLayout,
QLabel as _QLabel, QLabel as _QLabel,
QLineEdit as _QLineEdit, QLineEdit as _QLineEdit,
QInputDialog as _QInputDialog,
QGroupBox as _QGroupBox, QGroupBox as _QGroupBox,
QVBoxLayout as _QVBoxLayout, QVBoxLayout as _QVBoxLayout,
QPushButton as _QPushButton, QPushButton as _QPushButton,
@@ -85,8 +89,10 @@ try:
QToolButton as _QToolButton, QToolButton as _QToolButton,
QSizePolicy as _QSizePolicy, QSizePolicy as _QSizePolicy,
QComboBox as _QComboBox, QComboBox as _QComboBox,
QCheckBox as _QCheckBox,
QHBoxLayout as _QHBoxLayout, QHBoxLayout as _QHBoxLayout,
) )
from qgis.PyQt.QtGui import QFont as _QFont
from qgis.PyQt.QtCore import ( from qgis.PyQt.QtCore import (
QEventLoop as _QEventLoop, QEventLoop as _QEventLoop,
QTimer as _QTimer, QTimer as _QTimer,
@@ -118,6 +124,7 @@ try:
QGridLayout = _QGridLayout QGridLayout = _QGridLayout
QLabel = _QLabel QLabel = _QLabel
QLineEdit = _QLineEdit QLineEdit = _QLineEdit
QInputDialog = _QInputDialog
QGroupBox = _QGroupBox QGroupBox = _QGroupBox
QVBoxLayout = _QVBoxLayout QVBoxLayout = _QVBoxLayout
QPushButton = _QPushButton QPushButton = _QPushButton
@@ -129,8 +136,10 @@ try:
QToolButton = _QToolButton QToolButton = _QToolButton
QSizePolicy = _QSizePolicy QSizePolicy = _QSizePolicy
QComboBox = _QComboBox QComboBox = _QComboBox
QCheckBox = _QCheckBox
QVariant = _QVariant QVariant = _QVariant
QHBoxLayout = _QHBoxLayout QHBoxLayout = _QHBoxLayout
QFont = _QFont
# ✅ QT6 ENUMS # ✅ QT6 ENUMS
YES = QMessageBox.StandardButton.Yes YES = QMessageBox.StandardButton.Yes
NO = QMessageBox.StandardButton.No NO = QMessageBox.StandardButton.No
@@ -167,6 +176,7 @@ except (ImportError, AttributeError):
QGridLayout as _QGridLayout, QGridLayout as _QGridLayout,
QLabel as _QLabel, QLabel as _QLabel,
QLineEdit as _QLineEdit, QLineEdit as _QLineEdit,
QInputDialog as _QInputDialog,
QGroupBox as _QGroupBox, QGroupBox as _QGroupBox,
QVBoxLayout as _QVBoxLayout, QVBoxLayout as _QVBoxLayout,
QPushButton as _QPushButton, QPushButton as _QPushButton,
@@ -179,8 +189,10 @@ except (ImportError, AttributeError):
QToolButton as _QToolButton, QToolButton as _QToolButton,
QSizePolicy as _QSizePolicy, QSizePolicy as _QSizePolicy,
QComboBox as _QComboBox, QComboBox as _QComboBox,
QCheckBox as _QCheckBox,
QHBoxLayout as _QHBoxLayout, QHBoxLayout as _QHBoxLayout,
) )
from PyQt5.QtGui import QFont as _QFont
from PyQt5.QtCore import ( from PyQt5.QtCore import (
QEventLoop as _QEventLoop, QEventLoop as _QEventLoop,
QTimer as _QTimer, QTimer as _QTimer,
@@ -210,6 +222,7 @@ except (ImportError, AttributeError):
QGridLayout = _QGridLayout QGridLayout = _QGridLayout
QLabel = _QLabel QLabel = _QLabel
QLineEdit = _QLineEdit QLineEdit = _QLineEdit
QInputDialog = _QInputDialog
QGroupBox = _QGroupBox QGroupBox = _QGroupBox
QVBoxLayout = _QVBoxLayout QVBoxLayout = _QVBoxLayout
QPushButton = _QPushButton QPushButton = _QPushButton
@@ -221,8 +234,10 @@ except (ImportError, AttributeError):
QToolButton = _QToolButton QToolButton = _QToolButton
QSizePolicy = _QSizePolicy QSizePolicy = _QSizePolicy
QComboBox = _QComboBox QComboBox = _QComboBox
QCheckBox = _QCheckBox
QVariant = _QVariant QVariant = _QVariant
QHBoxLayout= _QHBoxLayout QHBoxLayout= _QHBoxLayout
QFont = _QFont
# ✅ PYQT5 ENUMS # ✅ PYQT5 ENUMS
YES = QMessageBox.Yes YES = QMessageBox.Yes
@@ -294,6 +309,13 @@ except (ImportError, AttributeError):
QFileDialog = _MockQFileDialog QFileDialog = _MockQFileDialog
class _MockQInputDialog:
@staticmethod
def getText(parent, title, label, mode=None, text=""):
return text, True
QInputDialog = _MockQInputDialog
class _MockQEventLoop: class _MockQEventLoop:
def exec(self) -> int: return 0 def exec(self) -> int: return 0
def quit(self) -> None: pass def quit(self) -> None: pass
@@ -341,10 +363,17 @@ except (ImportError, AttributeError):
class _MockLabel: class _MockLabel:
def __init__(self, text: str = ""): self._text = text def __init__(self, text: str = ""): self._text = text
class _MockLineEdit: class _MockLineEdit:
Normal = 0
def __init__(self, *args, **kwargs): self._text = "" def __init__(self, *args, **kwargs): self._text = ""
def text(self) -> str: return self._text def text(self) -> str: return self._text
def setText(self, value: str) -> None: self._text = value def setText(self, value: str) -> None: self._text = value
class _MockFont:
def __init__(self, family: str = "", pointSize: int = 10):
self.family = family
self.pointSize = pointSize
class _MockButton: class _MockButton:
def __init__(self, *args, **kwargs): self.clicked = lambda *a, **k: None def __init__(self, *args, **kwargs): self.clicked = lambda *a, **k: None
@@ -355,6 +384,7 @@ except (ImportError, AttributeError):
QGroupBox = _MockWidget QGroupBox = _MockWidget
QVBoxLayout = _MockLayout QVBoxLayout = _MockLayout
QPushButton = _MockButton QPushButton = _MockButton
QFont = _MockFont
QCoreApplication = object() QCoreApplication = object()
class _MockQt: class _MockQt:
@@ -529,6 +559,22 @@ except (ImportError, AttributeError):
def setContentsMargins(self, *args, **kwargs): def setContentsMargins(self, *args, **kwargs):
pass pass
QHBoxLayout = _MockQHBoxLayout QHBoxLayout = _MockQHBoxLayout
class _MockQCheckBox:
def __init__(self, text: str = "", *args, **kwargs):
self._text = text
self._checked = False
def setText(self, text: str) -> None:
self._text = text
def isChecked(self) -> bool:
return self._checked
def setChecked(self, checked: bool) -> None:
self._checked = checked
QCheckBox = _MockQCheckBox
def exec_dialog(dialog: Any) -> Any: def exec_dialog(dialog: Any) -> Any:
return YES return YES
# --------------------------- TEST --------------------------- # --------------------------- TEST ---------------------------

View File

@@ -56,6 +56,27 @@ class Pruefmanager:
) )
info("DataGrabber Zusammenfassung", message) info("DataGrabber Zusammenfassung", message)
# ------------------------------------------------------------------
# Allgemeine Nutzerinteraktionen
# ------------------------------------------------------------------
def zeige_hinweis(self, titel: str, meldung: str) -> None:
"""Zeigt eine modale Hinweismeldung mit OK-Button."""
from sn_basis.functions.dialog_wrapper import show_info_dialog
show_info_dialog(titel, meldung, parent=self.parent)
def frage_ja_nein(self, titel: str, meldung: str, default: bool = True) -> bool:
"""Stellt eine Ja/Nein-Frage. Gibt True zurück, wenn der Nutzer Ja wählt."""
if self.ui_modus != "qgis":
return default
return ask_yes_no(titel, meldung, default=default, parent=self.parent)
def frage_text(self, titel: str, meldung: str, default_text: str = "") -> tuple[str, bool]:
"""Fragt einen Textwert ab und gibt Text + OK-Status zurück."""
from sn_basis.functions.dialog_wrapper import ask_text
if self.ui_modus != "qgis":
return default_text, True
return ask_text(titel, meldung, default_text=default_text, parent=self.parent)
# ------------------------------------------------------------------ # ------------------------------------------------------------------
# VERFAHRENS-DB-spezifische Entscheidungen # VERFAHRENS-DB-spezifische Entscheidungen
# ------------------------------------------------------------------ # ------------------------------------------------------------------