Diensteabruf integriert

This commit is contained in:
2026-03-12 16:14:02 +01:00
parent ae956b0046
commit 9829ac9c81
10 changed files with 1136 additions and 89 deletions

View File

@@ -5,7 +5,7 @@ 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(
@@ -82,3 +82,101 @@ def ask_overwrite_append_cancel_custom(
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)

View File

@@ -57,6 +57,22 @@ def get_home_dir() -> Path:
return Path.home()
def is_absolute_path(path: _PathLike) -> bool:
"""Prüft, ob ein Pfad absolut ist."""
try:
return Path(path).is_absolute()
except Exception:
return False
def basename(path: _PathLike) -> str:
"""Gibt den finalen Namen des Pfades zurück (Dateiname oder Ordner)."""
try:
return Path(path).name
except Exception:
return ""
# ---------------------------------------------------------
# Dateisystem-Eigenschaften
# ---------------------------------------------------------
@@ -75,3 +91,11 @@ def is_case_sensitive_fs() -> bool:
# Linux praktisch immer case-sensitiv
return True
def path_suffix(path: _PathLike) -> str:
"""Gibt die Dateiendung eines Pfades zurück (inklusive Punkt)."""
try:
return Path(path).suffix
except Exception:
return ""

View File

@@ -20,6 +20,12 @@ QgsNetworkAccessManager: Type[Any]
Qgis: Type[Any]
QgsMapLayerProxyModel: Type[Any]
QgsVectorFileWriter: Type[Any] # neu: Schreib-API
QgsFeature: Type[Any]
QgsField: Type[Any]
QgsGeometry: Type[Any]
QgsFeatureRequest: Type[Any]
QgsCoordinateTransform: Type[Any]
QgsCoordinateReferenceSystem: Type[Any]
QGIS_AVAILABLE = False
@@ -36,9 +42,12 @@ try:
Qgis as _Qgis,
QgsMapLayerProxyModel as _QgsMaplLayerProxyModel,
QgsVectorFileWriter as _QgsVectorFileWriter,
QgsFeature as _QgsFeature,
QgsFeature as _QgsFeature,
QgsField as _QgsField,
QgsGeometry as _QgsGeometry,
QgsGeometry as _QgsGeometry,
QgsFeatureRequest as _QgsFeatureRequest,
QgsCoordinateTransform as _QgsCoordinateTransform,
QgsCoordinateReferenceSystem as _QgsCoordinateReferenceSystem,
)
QgsProject = _QgsProject
@@ -50,7 +59,10 @@ try:
QgsVectorFileWriter = _QgsVectorFileWriter
QgsFeature = _QgsFeature
QgsField = _QgsField
QgsGeometry = _QgsGeometry
QgsGeometry = _QgsGeometry
QgsFeatureRequest = _QgsFeatureRequest
QgsCoordinateTransform = _QgsCoordinateTransform
QgsCoordinateReferenceSystem = _QgsCoordinateReferenceSystem
QGIS_AVAILABLE = True
@@ -122,6 +134,30 @@ except Exception:
QgsRasterLayer = _MockQgsRasterLayer
class _MockQgsFeatureRequest:
def __init__(self):
self._filter_rect = None
def setFilterRect(self, rect):
self._filter_rect = rect
return self
QgsFeatureRequest = _MockQgsFeatureRequest
class _MockQgsCoordinateTransform:
def __init__(self, *args, **kwargs):
pass
def transformBoundingBox(self, rect):
return rect
class _MockQgsCoordinateReferenceSystem:
def __init__(self, *args, **kwargs):
pass
QgsCoordinateTransform = _MockQgsCoordinateTransform
QgsCoordinateReferenceSystem = _MockQgsCoordinateReferenceSystem
QgsNetworkAccessManager = _MockQgsNetworkAccessManager
class _MockQgis:

View File

@@ -18,7 +18,9 @@ QVariant: Type[Any] = object
QDockWidget: Type[Any] = object
QMessageBox: Type[Any] = object
QFileDialog: Type[Any] = object
QProgressDialog: Type[Any] = object
QEventLoop: Type[Any] = object
QTimer: Type[Any] = object
QUrl: Type[Any] = object
QNetworkRequest: Type[Any] = object
QNetworkReply: Type[Any] = object
@@ -66,6 +68,7 @@ try:
from qgis.PyQt.QtWidgets import (
QMessageBox as _QMessageBox,
QFileDialog as _QFileDialog,
QProgressDialog as _QProgressDialog,
QWidget as _QWidget,
QGridLayout as _QGridLayout,
QLabel as _QLabel,
@@ -86,6 +89,7 @@ try:
)
from qgis.PyQt.QtCore import (
QEventLoop as _QEventLoop,
QTimer as _QTimer,
QUrl as _QUrl,
QCoreApplication as _QCoreApplication,
Qt as _Qt,
@@ -100,7 +104,10 @@ try:
QT_VERSION = 6
QMessageBox = _QMessageBox
QFileDialog = _QFileDialog
QProgressDialog = _QProgressDialog
QProgressDialog = _QProgressDialog
QEventLoop = _QEventLoop
QTimer = _QTimer
QUrl = _QUrl
QNetworkRequest = _QNetworkRequest
QNetworkReply = _QNetworkReply
@@ -176,6 +183,7 @@ except (ImportError, AttributeError):
)
from PyQt5.QtCore import (
QEventLoop as _QEventLoop,
QTimer as _QTimer,
QUrl as _QUrl,
QCoreApplication as _QCoreApplication,
Qt as _Qt,
@@ -191,6 +199,7 @@ except (ImportError, AttributeError):
QMessageBox = _QMessageBox
QFileDialog = _QFileDialog
QEventLoop = _QEventLoop
QTimer = _QTimer
QUrl = _QUrl
QNetworkRequest = _QNetworkRequest
QNetworkReply = _QNetworkReply
@@ -291,6 +300,17 @@ except (ImportError, AttributeError):
QEventLoop = _MockQEventLoop
class _MockQTimer:
def __init__(self, *args, **kwargs):
self.timeout = type('Signal', (), {
'connect': lambda s, cb: None,
})()
def setSingleShot(self, v: bool) -> None: pass
def start(self, ms: int) -> None: pass
def stop(self) -> None: pass
QTimer = _MockQTimer
class _MockQUrl(str):
def isValid(self) -> bool: return True

View File

@@ -6,6 +6,7 @@ from pathlib import Path
from typing import Union
import sys
from sn_basis.functions.os_wrapper import is_absolute_path, basename
_PathLike = Union[str, Path]