Compare commits

..
Author SHA1 Message Date
release-bot 1a2d3109d4 Release 26.4.1-unstable 2026-04-08 12:52:25 +00:00
Daniel 41b272092e Merge pull request 'verfahrensgebiet-Vaiable wird sauber gesetzt' (#8) from bug/Verfahrensgebiet_nicht_übernommen into unstable
Reviewed-on: AG_QGIS/Plugin_SN_Verfahrensgebiet#8
2026-04-08 14:38:20 +02:00
Daniel 5be2d3b4f9 verfahrensgebiet-Vaiable wird sauber gesetzt 2026-04-08 14:36:39 +02:00
release-bot 62fae1c431 Release 26.3.3-unstable 2026-03-27 10:28:23 +00:00
Daniel 5531db9071 Merge pull request 'Verfahrensgebiet-Layerauswahl nach sn_verfahrensgebiet verschoben' (#7) from refactor/Verfahrensgebiet-Auswahl_nach_sn_Verfahrensgebiet into unstable
Reviewed-on: AG_QGIS/Plugin_SN_Verfahrensgebiet#7
2026-03-27 11:27:13 +01:00
Daniel 1796a7d5c0 Verfahrensgebiet-Layerauswahl nach sn_verfahrensgebiet verschoben 2026-03-27 11:19:07 +01:00
release-bot 98077e47cf Release 26.3.2-unstable 2026-03-26 20:48:56 +00:00
Daniel df0ebc5543 Merge pull request 'printtab aus sn_basis eingefügt' (#6) from refactor/Druckfunktion-in-sn_basis2 into unstable
Reviewed-on: AG_QGIS/Plugin_SN_Verfahrensgebiet#6
2026-03-26 21:42:25 +01:00
Daniel e4de5950a7 printtab aus sn_basis eingefügt 2026-03-26 20:16:02 +01:00
release-bot 52cf55d242 Release 26.3.1-unstable 2026-03-25 08:10:05 +00:00
22ottomi 195a3d949b changelog.txt aktualisiert 2026-03-25 09:05:55 +01:00
Michael Otto 472bf1b304 Umstellung auf neuen Release Workflow 2026-03-25 08:38:51 +01:00
Michael Otto 9f4e83257f Release-Workflow hinzugefügt und plugin.info zu plugin.cfg umbenannt 2026-03-13 14:03:12 +01:00
Michael Otto 06198f3e15 Add plugin.info based on metadata.txt 2026-03-13 08:39:31 +01:00
Michael Otto 85ac7597a5 Add .gitea from Plugin_Test_Action main 2026-03-13 08:28:57 +01:00
Daniel 229207e4dd Merge pull request 'auf wrapper/Prüfer umgestellt, Verfahrensgebiet aus ALKIS laden funktioniert' (#5) from Daniel/Plugin_SN_Verfahrensgebiet:main into main
Reviewed-on: AG_QGIS/Plugin_SN_Verfahrensgebiet#5
2026-03-06 10:31:55 +01:00
Daniel 797ff85e35 Merge pull request 'auf wrapper/Prüfer umgestellt, Verfahrensgebiet aus ALKIS laden funktioniert' (#1) from dev into main
Reviewed-on: #1
2026-03-06 10:30:28 +01:00
Daniel c265bb3dcf auf wrapper/Prüfer umgestellt, Verfahrensgebiet aus ALKIS laden funktioniert 2026-03-06 10:11:17 +01:00
22ottomi faed780dbf Merge pull request 'Meldung bei fehlender Verfahrensnummer geändert' (#4) from 22ottomi/Plugin_SN_Verfahrensgebiet:main into main
Reviewed-on: AG_QGIS/Plugin_SN_Verfahrensgebiet#4
2025-11-20 12:25:11 +01:00
Michael Otto 6a7e2c28f6 Merge branch 'main' of https://entwicklung.flurneuordnung-sachsen.de/22ottomi/Plugin_SN_Verfahrensgebiet 2025-11-20 12:20:07 +01:00
Michael Otto 0be47794b0 Meldung bei fehlender Verfahrensnummer geändert 2025-11-20 12:19:43 +01:00
22ottomi 2e2799930d Merge pull request 'Text geändert' (#3) from 22ottomi/Plugin_SN_Verfahrensgebiet:main into main
Reviewed-on: AG_QGIS/Plugin_SN_Verfahrensgebiet#3
2025-11-20 11:23:54 +01:00
22ottomi 01cbb76dcd Text geändert
Zum Testen eines Pull-Request den Text geändert
2025-11-20 11:23:17 +01:00
22ottomi 1c3de100e4 README.md aktualisiert 2025-11-20 11:22:28 +01:00
22ottomi 34d8253919 README.md aktualisiert 2025-11-20 11:21:39 +01:00
22ottomi 178487f22e README.md aktualisiert 2025-11-20 10:11:49 +01:00
Michael Otto cc757452bc Ablauf optimiert 2025-11-18 16:10:58 +01:00
Michael Otto bf479bdb64 25.11.4 2025-11-18 12:45:48 +01:00
11 changed files with 466 additions and 213 deletions
+133
View File
@@ -0,0 +1,133 @@
name: Release Plugin
run-name: "Release | ${{ github.ref_name }}"
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: alpine-latest
defaults:
run:
shell: bash
steps:
- name: Notwendige Abhängigkeiten installieren
shell: sh
run: |
apk add --no-cache bash git jq curl
- name: Code holen
run: |
REPO_URL="https://${RELEASE_TOKEN}:x-oauth-basic@${{ vars.RELEASE_URL }}/${GITHUB_REPOSITORY}.git"
git clone "$REPO_URL" repo
cd repo
git checkout "$TAG"
env:
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
TAG: "${{ github.ref_name }}"
- name: Version und Kanal bestimmen
id: releaseinfo
run: |
TAG="${{ github.ref_name }}"
RAW_VERSION="${TAG#v}"
VERSION="${RAW_VERSION%%-*}"
# Channel und Suffix automatisch bestimmen anhand des Tag-Suffix
case "$RAW_VERSION" in
*-testing*|*-t|*-T)
CHANNEL="testing"
PRERELEASE="true"
SUFFIX="-testing"
;;
*-unstable*|*-u|*-U)
CHANNEL="unstable"
PRERELEASE="true"
SUFFIX="-unstable"
;;
*)
CHANNEL="stable"
PRERELEASE="false"
SUFFIX=""
;;
esac
# Output setzen
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "channel=$CHANNEL" >> $GITHUB_OUTPUT
echo "prerelease=$PRERELEASE" >> $GITHUB_OUTPUT
# Optional Debug
echo "VERSION=$VERSION"
echo "CHANNEL=$CHANNEL"
echo "PRERELEASE=$PRERELEASE"
# - name: plugin.cfg einlesen
# id: config
# run: |
# cd repo
# while read -r line || [ -n "$line" ]; do
# key="${line%%=*}"
# value="${line#*=}"
# echo "$key=$value" >> $GITHUB_OUTPUT
# done < plugin.cfg
- name: Payload erzeugen
id: payload
run: |
cd repo
NAME="${GITHUB_REPOSITORY##*/}"
GROUP="${GITHUB_REPOSITORY%%/*}"
VERSION="${{ steps.releaseinfo.outputs.version }}"
CHANNEL="${{ steps.releaseinfo.outputs.channel }}"
PRERELEASE="${{ steps.releaseinfo.outputs.prerelease }}"
ZIP_FOLDER="${{ vars.ZIP_FOLDER }}"
ZIP_FILE="${ZIP_FOLDER}.zip"
TAG="${{ github.ref_name }}"
#GIT_URL=${GITHUB_REPOSITORY}
jq -n \
--arg name "$NAME" \
--arg group "$GROUP" \
--arg version "$VERSION" \
--arg channel "$CHANNEL" \
--arg prerelease "$PRERELEASE" \
--arg zip_folder "$ZIP_FOLDER" \
--arg zip_file "$ZIP_FILE" \
--arg tag "$TAG" \
'{
name: $name,
group: $group,
version: $version,
channel: $channel,
prerelease: ($prerelease == "true"),
zip_folder: $zip_folder,
zip_file: $zip_file,
tag: $tag
}' > payload.json
cat payload.json
- name: Repository aktualisieren
run: |
NAME="${GITHUB_REPOSITORY##*/}"
TAG="${{ steps.releaseinfo.outputs.version }}"-"${{ steps.releaseinfo.outputs.channel }}"
PAYLOAD_B64=$(base64 -w0 repo/payload.json)
JSON="{\"ref\":\"hidden/workflows\",\"inputs\":{\"payload\":\"$PAYLOAD_B64\",\"name\":\"$NAME\",\"tag\":\"$TAG\"}}"
curl -X POST \
-H "Authorization: token ${{ secrets.RELEASE_TOKEN }}" \
-H "Content-Type: application/json" \
-d "$JSON" \
"https://${{ vars.RELEASE_URL }}/api/v1/repos/${OWNER}/Repository/actions/workflows/${WORKFLOW}/dispatches"
env:
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
OWNER: "AG_QGIS"
WORKFLOW: "release.yaml"
+9
View File
@@ -0,0 +1,9 @@
---
Version 26.4.1-unstable:
---
Version 26.3.3-unstable:
---
Version 26.3.2-unstable:
---
Version 26.3.1-unstable:
- erster Test als echtes PlugIn
+91
View File
@@ -0,0 +1,91 @@
#sn_verfahrensgebiet/functions/verfahrensgebiet_alkis
from enum import Enum
from sn_basis.functions import (
QgsVectorLayer, QgsProject, QgsFeature, QgsField, QgsGeometry
)
from sn_basis.functions import QMessageBox
from sn_basis.functions.qt_wrapper import QVariant
from sn_basis.functions.variable_wrapper import get_variable
alkis_NAS_url = "https://geodienste.sachsen.de/aaa/public_alkis/nas/wfs"
typename = "adv:AX_BauRaumOderBodenordnungsrecht"
class LoadStatus(Enum):
NONE = "none" # nichts geladen
FIRST = "first" # erstmalig geladen
RELOAD = "reload" # neu geladen
KEEP = "keep" # vorhandener Layer behalten
def _check_existing_layer(tab_widget):
project = QgsProject.instance()
existing_layers = project.mapLayersByName("Verfahrensgebiet")
if not existing_layers:
return None, LoadStatus.FIRST
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())
return None, LoadStatus.RELOAD
else:
return existing_layers[0], LoadStatus.KEEP
def verfahrensgebiet_alkis(tab_widget):
verfahrensnummer = get_variable("verfahrensnummer")
if not verfahrensnummer:
QMessageBox.critical(tab_widget, "Fehler",
"In den Projekteigenschaften ist noch keine Verfahrensnummer eingetragen!")
return None, LoadStatus.NONE
# Vorhandenen Layer prüfen
existing, status = _check_existing_layer(tab_widget)
if status == LoadStatus.KEEP:
return existing, status
# 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, LoadStatus.NONE
features = list(temp_layer.getFeatures())
if not features:
QMessageBox.critical(tab_widget, "Fehler",
f"Verfahrenskennzeichen {verfahrensnummer} nicht im WFS gefunden.")
return None, LoadStatus.NONE
union_geom = QgsGeometry.unaryUnion([f.geometry() for f in features])
if union_geom is None or union_geom.isEmpty():
QMessageBox.critical(tab_widget, "Fehler", "Keine Geometrien zum Verschmelzen gefunden.")
return None, LoadStatus.NONE
# Memory-Layer erzeugen
crs = temp_layer.crs().authid()
memory_layer = QgsVectorLayer(f"Polygon?crs={crs}", "Verfahrensgebiet", "memory")
pr = memory_layer.dataProvider()
pr.addAttributes([QgsField("VKZ", QVariant.String)])
memory_layer.updateFields()
feat_union = QgsFeature()
feat_union.setGeometry(union_geom)
feat_union.setAttributes([verfahrensnummer])
pr.addFeatures([feat_union])
memory_layer.updateExtents()
# Status: FIRST oder RELOAD
return memory_layer, status
-85
View File
@@ -1,85 +0,0 @@
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
+27 -6
View File
@@ -1,11 +1,14 @@
from qgis.utils import plugins
from sn_basis.ui.dockmanager import DockManager
from .ui.dockwidget import DockWidget
from sn_basis.modules.DataGrabber import DataGrabber
from sn_basis.modules.Pruefmanager import Pruefmanager
class Verfahrensgebiet:
def __init__(self, iface):
self.iface = iface
self.pruefmanager = Pruefmanager(ui_modus="qgis")
self.data_grabber = DataGrabber(pruefmanager=self.pruefmanager)
self.action = None
self.dockwidget = None
@@ -13,8 +16,11 @@ class Verfahrensgebiet:
self.plugin_name = self.__class__.__name__
self.dock_name = f"sn_dock_{self.plugin_name.lower()}"
def _basis(self):
return plugins.get("sn_basis")
def initGui(self):
basis = plugins.get("sn_basis")
basis = self._basis()
if basis and basis.ui:
self.action = basis.ui.add_action(
self.plugin_name,
@@ -31,14 +37,29 @@ class Verfahrensgebiet:
self.dockwidget = None
if self.action:
basis = plugins.get("sn_basis")
basis = self._basis()
if basis and basis.ui:
# Action aus Menü und Toolbar entfernen
basis.ui.remove_action(self.action)
self.action = None
# def run(self):
# if not self.dockwidget:
# self.dockwidget = DockWidget(self.iface.mainWindow(), subtitle=self.plugin_name)
# self.dockwidget.setObjectName(self.dock_name)
# self.dockwidget.action = self.action
# DockManager.show(self.dockwidget)
# basis = self._basis()
# if basis and basis.ui:
# basis.ui.set_active_plugin(self.action)
def run(self):
self.dockwidget = DockWidget(self.iface.mainWindow(), subtitle=self.plugin_name)
self.dockwidget = DockWidget(
self.iface.mainWindow(),
subtitle=self.plugin_name,
pruefmanager=self.pruefmanager,
data_grabber=self.data_grabber,
)
self.dockwidget.setObjectName(self.dock_name)
# Action-Referenz im Dock speichern
@@ -49,4 +70,4 @@ class Verfahrensgebiet:
# Toolbar-Button als aktiv markieren
basis = plugins.get("sn_basis")
if basis and basis.ui:
basis.ui.set_active_plugin(self.action)
basis.ui.set_active_plugin(self.action)
+10 -10
View File
@@ -1,13 +1,13 @@
[general]
version=26.4.1-unstable
name=LNO Sachsen | Verfahrensgebiet
qgisMinimumVersion=3.0
description=Plugin zum Erzeugen eines Objektes "Verfahrensgebiet"
version=25.11.3
author=Michael Otto
email=michael.otto@landkreis-mittelsachsen.de
about=Plugin zum Erzeugen eines Objektes "Verfahrensgebiet"
category=Plugins
homepage=https://entwicklung.vln-sn.de/AG_QGIS/Plugin_SN_Verfahrensgebiet
repository=https://entwicklung.vln-sn.de/AG_QGIS/Repository
supportsQt6=true
experimental=true
author=Daniel Helbig, Michael Otto
homepage=https://entwicklung.flurneuordnung-sachsen.de/AG_QGIS/Plugin_SN_Verfahrensgebiet
tracker=https://entwicklung.flurneuordnung-sachsen.de/AG_QGIS/Plugin_SN_Verfahrensgebiet/issues
repository=https://entwicklung.flurneuordnung-sachsen.de/AG_QGIS/Plugin_SN_Verfahrensgebiet/src/branch/unstable/
qgisMinimumVersion=3.40
experimental=true
deprecated=false
supportsQt6=true
+34 -3
View File
@@ -1,8 +1,39 @@
from sn_basis.ui.tabs.settings_tab import SettingsTab
from sn_verfahrensgebiet.ui.tabs.tab_a import TabA
from sn_verfahrensgebiet.ui.tabs.tab_b import TabB
from sn_basis.ui.tabs.print_tab import PrintTab
from sn_verfahrensgebiet.ui.tabs.working_tab import WorkingTab
from sn_basis.ui.base_dockwidget import BaseDockWidget
from sn_basis.functions.qt_wrapper import QTabWidget
from sn_basis.functions.message_wrapper import error
class DockWidget(BaseDockWidget):
tabs = [TabA, SettingsTab]
tabs = [WorkingTab, PrintTab, SettingsTab]
def __init__(self, parent=None, subtitle="", pruefmanager=None, data_grabber=None):
super().__init__(parent, subtitle)
self.pruefmanager = pruefmanager
self.data_grabber = data_grabber
self._init_tabs_with_services()
def _init_tabs_with_services(self):
"""Tabs neu aufbauen und Services (z.B. fuer PrintTab) injizieren."""
try:
self.setWidget(None)
tab_widget = QTabWidget()
for tab_class in self.tabs:
tab_instance = tab_class(self)
tab_title = getattr(tab_class, "tab_title", tab_class.__name__)
tab_widget.addTab(tab_instance, tab_title)
if hasattr(tab_instance, "set_services"):
tab_instance.set_services(
pruefmanager=self.pruefmanager,
data_grabber=self.data_grabber,
)
self.setWidget(tab_widget)
except Exception as e:
error("Services-Tabs konnten nicht initialisiert werden", str(e))
-98
View File
@@ -1,98 +0,0 @@
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 = "Bearbeitung"
def __init__(self, parent=None):
super().__init__(parent)
layout = QVBoxLayout()
layout.setAlignment(Qt.AlignmentFlag.AlignTop)
# Abschnitt 1: Verfahrensgebiet
row_verf_header = QHBoxLayout()
lbl_verf = QLabel("<b>Verfahrensgebiet</b>")
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("<b>Flurstücke</b>")
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("")
-11
View File
@@ -1,11 +0,0 @@
from qgis.PyQt.QtWidgets import QWidget, QVBoxLayout, QLabel, QTextEdit
class TabB(QWidget):
tab_title = "Tab B"
def __init__(self, parent=None):
super().__init__(parent)
layout = QVBoxLayout()
layout.addWidget(QLabel("Plugin1 – Tab B"))
layout.addWidget(QTextEdit("Mehrzeiliger Text für Plugin1"))
self.setLayout(layout)
+162
View File
@@ -0,0 +1,162 @@
from sn_basis.functions.qt_wrapper import QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QMessageBox
from sn_basis.functions.qt_wrapper import Qt
from sn_basis.functions import Qgis, QgsProject #QgsMessageLog
from sn_basis.functions.qgisui_wrapper import QgsMapLayerComboBox
from sn_basis.functions.qgiscore_wrapper import QgsMapLayerProxyModel
from sn_basis.functions.verfahrensgebiet_manager import get_verfahrensgebiet_layer_id, set_verfahrensgebiet_layer_id
from qgis.utils import iface
from sn_verfahrensgebiet.functions.verfahrensgebiet_alkis import verfahrensgebiet_alkis, LoadStatus
from sn_basis.functions.message_wrapper import success, info, warning, error
from sn_basis.functions.ly_style_wrapper import apply_style
class WorkingTab(QWidget):
tab_title = "Bearbeitung"
def __init__(self, parent=None):
super().__init__(parent)
layout = QVBoxLayout()
layout.setAlignment(Qt.AlignmentFlag.AlignTop)
# Abschnitt 1: Verfahrensgebiet
row_verf_header = QHBoxLayout()
lbl_verf = QLabel("<b>Verfahrensgebiet</b>")
self.haken_verf = self._haken_label()
row_verf_header.addWidget(lbl_verf)
row_verf_header.addWidget(self.haken_verf)
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 1b: Verfahrensgebiet-Layer auswählen
row_layer_label = QHBoxLayout()
lbl_layer = QLabel("Oder: Verfahrensgebiet-Layer auswählen")
lbl_layer.setStyleSheet("font-style: italic; color: gray; margin-top: 8px;")
row_layer_label.addWidget(lbl_layer)
row_layer_label.addStretch()
layout.addLayout(row_layer_label)
self.verf_layer_combo = QgsMapLayerComboBox(self)
self.verf_layer_combo.setFilters(QgsMapLayerProxyModel.VectorLayer)
self.verf_layer_combo.setToolTip("Wähle den Verfahrensgebiet-Layer, oder lasse es leer für Automatik")
self.verf_layer_combo.layerChanged.connect(self._on_verf_layer_changed)
layout.addWidget(self.verf_layer_combo)
# Abschnitt 2: Flurstücke (Platzhalter für spätere Implementierung)
row_flurst_header = QHBoxLayout()
lbl_flurst = QLabel("<b>Flurstücke</b>")
self.haken_flurst = self._haken_label()
row_flurst_header.addWidget(lbl_flurst)
row_flurst_header.addWidget(self.haken_flurst)
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)
# Signale verbinden
self.btn_verf_alkis.clicked.connect(self.handle_verf_alkis)
# self.btn_verf_shape.clicked.connect(self.handle_verf_shape)
# self.btn_flurst_alkis.clicked.connect(self.handle_flurst_alkis)
# self.btn_flurst_shape.clicked.connect(self.handle_flurst_shape)
# Beim Init: aktuelle Verfahrensgebiet-Layer-ID laden und im Dropdown anzeigen
self._restore_verf_layer_selection()
def handle_verf_alkis(self):
self._set_busy(self.btn_verf_alkis, True)
try:
layer, status = verfahrensgebiet_alkis(self)
if not layer or not layer.isValid():
set_verfahrensgebiet_layer_id("")
return
if status in (LoadStatus.FIRST, LoadStatus.RELOAD):
# Gemeinsame Logik für erstmaliges und erneutes Laden
QgsProject.instance().addMapLayer(layer)
iface.mapCanvas().setExtent(layer.extent())
#iface.mapCanvas().refresh()
apply_style(layer, "verfahrensgebiet.qml")
iface.mapCanvas().refresh()
self.setze_haken(self.haken_verf, True)
# Dropdown + Variable explizit synchronisieren.
self.verf_layer_combo.setLayer(layer)
self._on_verf_layer_changed(layer)
# Unterschied nur in der Meldung
msg = "erstmalig geladen" if status == LoadStatus.FIRST else "neu geladen"
success("Verfahrensgebiet", f"Layer wurde {msg}.", duration=5)
elif status == LoadStatus.KEEP:
self.verf_layer_combo.setLayer(layer)
self._on_verf_layer_changed(layer)
info("Verfahrensgebiet", "Vorhandener Layer wurde behalten.", duration=4)
elif status == LoadStatus.NONE:
self._on_verf_layer_changed(None)
warning("Verfahrensgebiet", "Layer konnte nicht geladen werden.", duration=None)
finally:
self._set_busy(self.btn_verf_alkis, False)
def _set_busy(self, button: QPushButton, busy: bool):
button.setEnabled(not busy)
if busy:
button.setText("Lade ...")
else:
button.setText("Aus ALKIS laden")
def _haken_label(self) -> QLabel:
label = QLabel()
label.setFixedSize(20, 20)
label.setAlignment(Qt.AlignmentFlag.AlignCenter)
label.setText("") # Start ohne Haken
return label
def setze_haken(self, label: QLabel, aktiv: bool):
"""Zeigt oder entfernt den grünen Haken (Unicode), ohne Theme-Icons."""
if aktiv:
label.setText("✓")
label.setStyleSheet("color: #2ea043; font-weight: bold;")
else:
label.setText("")
label.setStyleSheet("")
def _on_verf_layer_changed(self, layer) -> None:
"""Callback: Nutzer hat einen anderen Layer im Dropdown gewählt."""
if layer and layer.isValid():
# Speichere die Layer-ID in der zentralen Variable
set_verfahrensgebiet_layer_id(layer.id())
else:
# Layer is None oder invalid; leere die Variable
set_verfahrensgebiet_layer_id("")
def _restore_verf_layer_selection(self) -> None:
"""Beim Tab-Init: Lade die zuletzt gespeicherte Verfahrensgebiet-Layer-ID."""
layer_id = get_verfahrensgebiet_layer_id()
if layer_id:
# Versuche, den Layer im Projekt zu finden
try:
project = QgsProject.instance()
layer = project.mapLayer(layer_id)
if layer and layer.isValid():
self.verf_layer_combo.setLayer(layer)
except Exception:
pass