From f69ee89a3c004553ee2640e67772db94b479e3ba Mon Sep 17 00:00:00 2001 From: Michael Otto Date: Tue, 18 Nov 2025 12:36:35 +0100 Subject: [PATCH] Erste Version Verfahrensgebiet aus ALKIS laden --- logic/alkis_verfahrensgebiet.py | 85 +++++++++++++++++++ ui/dockwidget.py | 2 +- ui/tabs/Verfahrensgebiet.qml | 140 ++++++++++++++++++++++++++++++++ ui/tabs/tab_a.py | 98 ++++++++++++++++++++-- 4 files changed, 318 insertions(+), 7 deletions(-) create mode 100644 logic/alkis_verfahrensgebiet.py create mode 100644 ui/tabs/Verfahrensgebiet.qml diff --git a/logic/alkis_verfahrensgebiet.py b/logic/alkis_verfahrensgebiet.py new file mode 100644 index 0000000..4977de0 --- /dev/null +++ b/logic/alkis_verfahrensgebiet.py @@ -0,0 +1,85 @@ +import os +from qgis.core import ( + QgsVectorLayer, QgsProject, QgsFeature, QgsField, + QgsFeatureRequest, QgsGeometry +) +from qgis.PyQt.QtWidgets import QMessageBox +from qgis.PyQt.QtCore import QVariant +from sn_basis import get_variable + +alkis_NAS_url = "https://geodienste.sachsen.de/aaa/public_alkis/nas/wfs" +typename = "adv:AX_BauRaumOderBodenordnungsrecht" + + +def alkis_verfahrensgebiet(tab_widget): + verfahrensnummer = get_variable("verfahrensnummer") + if not verfahrensnummer: + QMessageBox.critical(tab_widget, "Fehler", + "Die Projektvariable 'sn_verfahrensnummer' ist nicht gesetzt.") + tab_widget.setze_haken(tab_widget.haken1, False) + return None, False + + project = QgsProject.instance() + existing_layers = project.mapLayersByName("Verfahrensgebiet") + if existing_layers: + reply = QMessageBox.question( + tab_widget, + "Layer bereits vorhanden", + "Der Layer 'Verfahrensgebiet' existiert bereits.\n" + "Möchten Sie ihn löschen und neu laden?", + QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, + QMessageBox.StandardButton.No + ) + if reply == QMessageBox.StandardButton.Yes: + for lyr in existing_layers: + project.removeMapLayer(lyr.id()) + else: + # Vorhandenen Layer zurückgeben, kein Neu-Laden + return existing_layers[0], False + + # WFS mit Filter laden + wfs_uri_find = ( + f"url='{alkis_NAS_url}' typename='{typename}' srsname='EPSG:25833' " + f"sql=SELECT * FROM AX_BauRaumOderBodenordnungsrecht " + f"WHERE bezeichnung LIKE '{verfahrensnummer}%'" + ) + temp_layer = QgsVectorLayer(wfs_uri_find, "TempVerfahrensgebiet", "WFS") + + if not temp_layer.isValid(): + QMessageBox.critical(tab_widget, "Fehler", "Layer konnte nicht geladen werden.") + return None, False + + features = list(temp_layer.getFeatures()) + if not features: + QMessageBox.critical(tab_widget, "Fehler", + f"Verfahrenskennzeichen {verfahrensnummer} nicht im WFS gefunden.") + return None, False + + # Geometrie bestimmen + if len(features) == 1: + union_geom = features[0].geometry() + else: + geoms = [f.geometry() for f in features] + union_geom = QgsGeometry.unaryUnion(geoms) + + if union_geom is None or union_geom.isEmpty(): + QMessageBox.critical(tab_widget, "Fehler", "Keine Geometrien zum Verschmelzen gefunden.") + return None, False + + # Memory-Layer mit festem Namen "Verfahrensgebiet" + crs = temp_layer.crs().authid() + memory_layer = QgsVectorLayer(f"Polygon?crs={crs}", "Verfahrensgebiet", "memory") + pr = memory_layer.dataProvider() + + # Feld "VKZ" hinzufügen + pr.addAttributes([QgsField("VKZ", QVariant.String)]) + memory_layer.updateFields() + + # Feature mit Geometrie erstellen + feat_union = QgsFeature() + feat_union.setGeometry(union_geom) + feat_union.setAttributes([verfahrensnummer]) + pr.addFeatures([feat_union]) + memory_layer.updateExtents() + + return memory_layer, True diff --git a/ui/dockwidget.py b/ui/dockwidget.py index 8b89ead..876aa9b 100644 --- a/ui/dockwidget.py +++ b/ui/dockwidget.py @@ -5,4 +5,4 @@ from sn_basis.ui.base_dockwidget import BaseDockWidget class DockWidget(BaseDockWidget): - tabs = [TabA, TabB, SettingsTab] + tabs = [TabA, SettingsTab] diff --git a/ui/tabs/Verfahrensgebiet.qml b/ui/tabs/Verfahrensgebiet.qml new file mode 100644 index 0000000..474e368 --- /dev/null +++ b/ui/tabs/Verfahrensgebiet.qml @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 2 + diff --git a/ui/tabs/tab_a.py b/ui/tabs/tab_a.py index eb55762..d01b568 100644 --- a/ui/tabs/tab_a.py +++ b/ui/tabs/tab_a.py @@ -1,12 +1,98 @@ -from qgis.PyQt.QtWidgets import QWidget, QVBoxLayout, QLabel, QLineEdit +from qgis.PyQt.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QMessageBox +from qgis.PyQt.QtGui import QIcon, QPixmap +from qgis.PyQt.QtCore import Qt, QTimer +from qgis.core import Qgis, QgsProject, QgsMessageLog +from qgis.utils import iface +import os + +from sn_verfahrensgebiet.logic.alkis_verfahrensgebiet import alkis_verfahrensgebiet +from sn_basis.logic.utils import zoom_to_layer class TabA(QWidget): - tab_title = "Tab A" - + tab_title = "Bearbeitung" + def __init__(self, parent=None): super().__init__(parent) + layout = QVBoxLayout() - layout.addWidget(QLabel("Plugin1 – Tab A")) - layout.addWidget(QLineEdit("Feld A1")) - layout.addWidget(QLineEdit("Feld A2")) + layout.setAlignment(Qt.AlignmentFlag.AlignTop) + + # Abschnitt 1: Verfahrensgebiet + row_verf_header = QHBoxLayout() + lbl_verf = QLabel("Verfahrensgebiet") + self.haken1 = self._haken_label() + row_verf_header.addWidget(lbl_verf) + row_verf_header.addWidget(self.haken1) + row_verf_header.addStretch() + layout.addLayout(row_verf_header) + + row_verf_buttons = QHBoxLayout() + self.btn_verf_alkis = QPushButton("Aus ALKIS laden") + self.btn_verf_shape = QPushButton("Aus Shape laden") + row_verf_buttons.addWidget(self.btn_verf_alkis) + row_verf_buttons.addWidget(self.btn_verf_shape) + layout.addLayout(row_verf_buttons) + + # Abschnitt 2: Flurstücke + row_flurst_header = QHBoxLayout() + lbl_flurst = QLabel("Flurstücke") + self.haken2 = self._haken_label() + row_flurst_header.addWidget(lbl_flurst) + row_flurst_header.addWidget(self.haken2) + row_flurst_header.addStretch() + layout.addLayout(row_flurst_header) + + row_flurst_buttons = QHBoxLayout() + self.btn_flurst_alkis = QPushButton("Aus ALKIS laden") + self.btn_flurst_shape = QPushButton("Aus Shape laden") + row_flurst_buttons.addWidget(self.btn_flurst_alkis) + row_flurst_buttons.addWidget(self.btn_flurst_shape) + layout.addLayout(row_flurst_buttons) + + layout.addStretch() self.setLayout(layout) + + # Beispiel: Haken anzeigen nach Klick + # self.button1.clicked.connect(lambda: alkis_verfahrensgebiet(self)) + self.btn_verf_alkis.clicked.connect(lambda: self.handle_button1()) + + #self.button2.clicked.connect(lambda: self.setze_haken(self.haken2, True)) + + def handle_button1(self): + layer, neu_geladen = alkis_verfahrensgebiet(self) + + if not layer or not layer.isValid(): + return + + if neu_geladen: + QgsProject.instance().addMapLayer(layer) + iface.mapCanvas().setExtent(layer.extent()) + iface.mapCanvas().refresh() + # Beispiel: Haken setzen oder Meldung ausgeben + self.setze_haken(self.haken1, True) + # QMessageBox.information(self, "Info", "Layer 'Verfahrensgebiet' wurde neu geladen.") + else: + # Kein Zoom, kein Neu-Laden + QgsMessageLog.logMessage("Vorhandener Layer behalten.", "sn_verfahrensgebiet", level=Qgis.Info) + + + def _haken_label(self): + label = QLabel() + label.setFixedSize(20, 20) +# label.setAlignment(Qt.AlignCenter) + label.setAlignment(Qt.AlignmentFlag.AlignCenter) + label.setScaledContents(False) + label.setText("") + return label + + def setze_haken(self, label: QLabel, aktiv: bool): + """Zeigt oder entfernt den grünen Haken.""" + if aktiv: + # grünes Unicode-Häkchen + label.setPixmap(QPixmap()) + label.setText("✓") + label.setStyleSheet("color: #2ea043; font-weight: bold;") + else: + label.setPixmap(QPixmap()) + label.setText("") + label.setStyleSheet("")