10 Commits

Author SHA1 Message Date
faed780dbf Merge pull request 'Meldung bei fehlender Verfahrensnummer geändert' (#4) from 22ottomi/Plugin_SN_Verfahrensgebiet:main into main
Reviewed-on: #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
2e2799930d Merge pull request 'Text geändert' (#3) from 22ottomi/Plugin_SN_Verfahrensgebiet:main into main
Reviewed-on: #3
2025-11-20 11:23:54 +01:00
01cbb76dcd Text geändert
Zum Testen eines Pull-Request den Text geändert
2025-11-20 11:23:17 +01:00
1c3de100e4 README.md aktualisiert 2025-11-20 11:22:28 +01:00
34d8253919 README.md aktualisiert 2025-11-20 11:21:39 +01:00
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
8 changed files with 176 additions and 297 deletions

View File

@@ -1,7 +1,6 @@
import os
from enum import Enum
from qgis.core import (
QgsVectorLayer, QgsProject, QgsFeature, QgsField,
QgsFeatureRequest, QgsGeometry
QgsVectorLayer, QgsProject, QgsFeature, QgsField, QgsGeometry
)
from qgis.PyQt.QtWidgets import QMessageBox
from qgis.PyQt.QtCore import QVariant
@@ -10,32 +9,46 @@ from sn_basis 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 alkis_verfahrensgebiet(tab_widget):
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",
"Die Projektvariable 'sn_verfahrensnummer' ist nicht gesetzt.")
tab_widget.setze_haken(tab_widget.haken1, False)
return None, False
"In den Projekteigenschaften ist noch keine Verfahrensnummer eingetragen!")
return None, LoadStatus.NONE
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
# 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 = (
@@ -47,39 +60,31 @@ def alkis_verfahrensgebiet(tab_widget):
if not temp_layer.isValid():
QMessageBox.critical(tab_widget, "Fehler", "Layer konnte nicht geladen werden.")
return None, False
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, 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)
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, False
return None, LoadStatus.NONE
# Memory-Layer mit festem Namen "Verfahrensgebiet"
# Memory-Layer erzeugen
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
# Status: FIRST oder RELOAD
return memory_layer, status

22
main.py
View File

@@ -2,7 +2,6 @@ from qgis.utils import plugins
from sn_basis.ui.dockmanager import DockManager
from .ui.dockwidget import DockWidget
class Verfahrensgebiet:
def __init__(self, iface):
self.iface = iface
@@ -13,8 +12,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,12 +33,22 @@ 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.setObjectName(self.dock_name)
@@ -49,4 +61,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)

View File

@@ -2,7 +2,7 @@
name=LNO Sachsen | Verfahrensgebiet
qgisMinimumVersion=3.0
description=Plugin zum Erzeugen eines Objektes "Verfahrensgebiet"
version=25.11.3
version=25.11.4
author=Michael Otto
email=michael.otto@landkreis-mittelsachsen.de
about=Plugin zum Erzeugen eines Objektes "Verfahrensgebiet"

View File

@@ -1,8 +1,7 @@
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_verfahrensgebiet.ui.tabs.working_tab import WorkingTab
from sn_basis.ui.base_dockwidget import BaseDockWidget
class DockWidget(BaseDockWidget):
tabs = [TabA, SettingsTab]
tabs = [WorkingTab, SettingsTab]

View File

@@ -1,140 +0,0 @@
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
<qgis version="3.40.7-Bratislava" styleCategories="Symbology">
<renderer-v2 referencescale="-1" forceraster="0" enableorderby="0" type="singleSymbol" symbollevels="0">
<symbols>
<symbol is_animated="0" frame_rate="10" clip_to_extent="1" type="fill" alpha="1" force_rhr="0" name="0">
<data_defined_properties>
<Option type="Map">
<Option type="QString" value="" name="name"/>
<Option name="properties"/>
<Option type="QString" value="collection" name="type"/>
</Option>
</data_defined_properties>
<layer locked="0" id="{feca00b2-500a-4c9a-b285-67ba2d99d8f6}" enabled="1" class="SimpleLine" pass="0">
<Option type="Map">
<Option type="QString" value="0" name="align_dash_pattern"/>
<Option type="QString" value="square" name="capstyle"/>
<Option type="QString" value="5;2" name="customdash"/>
<Option type="QString" value="3x:0,0,0,0,0,0" name="customdash_map_unit_scale"/>
<Option type="QString" value="MM" name="customdash_unit"/>
<Option type="QString" value="0" name="dash_pattern_offset"/>
<Option type="QString" value="3x:0,0,0,0,0,0" name="dash_pattern_offset_map_unit_scale"/>
<Option type="QString" value="MM" name="dash_pattern_offset_unit"/>
<Option type="QString" value="0" name="draw_inside_polygon"/>
<Option type="QString" value="round" name="joinstyle"/>
<Option type="QString" value="215,168,255,255,rgb:0.84313725490196079,0.6588235294117647,1,1" name="line_color"/>
<Option type="QString" value="solid" name="line_style"/>
<Option type="QString" value="1.5" name="line_width"/>
<Option type="QString" value="MM" name="line_width_unit"/>
<Option type="QString" value="-0.75" name="offset"/>
<Option type="QString" value="3x:0,0,0,0,0,0" name="offset_map_unit_scale"/>
<Option type="QString" value="MM" name="offset_unit"/>
<Option type="QString" value="0" name="ring_filter"/>
<Option type="QString" value="0" name="trim_distance_end"/>
<Option type="QString" value="3x:0,0,0,0,0,0" name="trim_distance_end_map_unit_scale"/>
<Option type="QString" value="MM" name="trim_distance_end_unit"/>
<Option type="QString" value="0" name="trim_distance_start"/>
<Option type="QString" value="3x:0,0,0,0,0,0" name="trim_distance_start_map_unit_scale"/>
<Option type="QString" value="MM" name="trim_distance_start_unit"/>
<Option type="QString" value="0" name="tweak_dash_pattern_on_corners"/>
<Option type="QString" value="0" name="use_custom_dash"/>
<Option type="QString" value="3x:0,0,0,0,0,0" name="width_map_unit_scale"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option type="QString" value="" name="name"/>
<Option name="properties"/>
<Option type="QString" value="collection" name="type"/>
</Option>
</data_defined_properties>
</layer>
<layer locked="0" id="{fdc4d6fd-0995-41df-bbfb-19970b4fc2cc}" enabled="1" class="SimpleLine" pass="0">
<Option type="Map">
<Option type="QString" value="0" name="align_dash_pattern"/>
<Option type="QString" value="square" name="capstyle"/>
<Option type="QString" value="5;2" name="customdash"/>
<Option type="QString" value="3x:0,0,0,0,0,0" name="customdash_map_unit_scale"/>
<Option type="QString" value="MM" name="customdash_unit"/>
<Option type="QString" value="0" name="dash_pattern_offset"/>
<Option type="QString" value="3x:0,0,0,0,0,0" name="dash_pattern_offset_map_unit_scale"/>
<Option type="QString" value="MM" name="dash_pattern_offset_unit"/>
<Option type="QString" value="0" name="draw_inside_polygon"/>
<Option type="QString" value="round" name="joinstyle"/>
<Option type="QString" value="204,174,137,255,rgb:0.80000000000000004,0.68235294117647061,0.53725490196078429,1" name="line_color"/>
<Option type="QString" value="solid" name="line_style"/>
<Option type="QString" value="0.5" name="line_width"/>
<Option type="QString" value="MM" name="line_width_unit"/>
<Option type="QString" value="0" name="offset"/>
<Option type="QString" value="3x:0,0,0,0,0,0" name="offset_map_unit_scale"/>
<Option type="QString" value="MM" name="offset_unit"/>
<Option type="QString" value="0" name="ring_filter"/>
<Option type="QString" value="0" name="trim_distance_end"/>
<Option type="QString" value="3x:0,0,0,0,0,0" name="trim_distance_end_map_unit_scale"/>
<Option type="QString" value="MM" name="trim_distance_end_unit"/>
<Option type="QString" value="0" name="trim_distance_start"/>
<Option type="QString" value="3x:0,0,0,0,0,0" name="trim_distance_start_map_unit_scale"/>
<Option type="QString" value="MM" name="trim_distance_start_unit"/>
<Option type="QString" value="0" name="tweak_dash_pattern_on_corners"/>
<Option type="QString" value="0" name="use_custom_dash"/>
<Option type="QString" value="3x:0,0,0,0,0,0" name="width_map_unit_scale"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option type="QString" value="" name="name"/>
<Option name="properties"/>
<Option type="QString" value="collection" name="type"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</symbols>
<rotation/>
<sizescale/>
<data-defined-properties>
<Option type="Map">
<Option type="QString" value="" name="name"/>
<Option name="properties"/>
<Option type="QString" value="collection" name="type"/>
</Option>
</data-defined-properties>
</renderer-v2>
<selection mode="Default">
<selectionColor invalid="1"/>
<selectionSymbol>
<symbol is_animated="0" frame_rate="10" clip_to_extent="1" type="fill" alpha="1" force_rhr="0" name="">
<data_defined_properties>
<Option type="Map">
<Option type="QString" value="" name="name"/>
<Option name="properties"/>
<Option type="QString" value="collection" name="type"/>
</Option>
</data_defined_properties>
<layer locked="0" id="{f18003f5-220a-487f-8a6d-b24facc4c1a5}" enabled="1" class="SimpleFill" pass="0">
<Option type="Map">
<Option type="QString" value="3x:0,0,0,0,0,0" name="border_width_map_unit_scale"/>
<Option type="QString" value="0,0,255,255,rgb:0,0,1,1" name="color"/>
<Option type="QString" value="bevel" name="joinstyle"/>
<Option type="QString" value="0,0" name="offset"/>
<Option type="QString" value="3x:0,0,0,0,0,0" name="offset_map_unit_scale"/>
<Option type="QString" value="MM" name="offset_unit"/>
<Option type="QString" value="35,35,35,255,rgb:0.13725490196078433,0.13725490196078433,0.13725490196078433,1" name="outline_color"/>
<Option type="QString" value="solid" name="outline_style"/>
<Option type="QString" value="0.26" name="outline_width"/>
<Option type="QString" value="MM" name="outline_width_unit"/>
<Option type="QString" value="solid" name="style"/>
</Option>
<data_defined_properties>
<Option type="Map">
<Option type="QString" value="" name="name"/>
<Option name="properties"/>
<Option type="QString" value="collection" name="type"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</selectionSymbol>
</selection>
<blendMode>0</blendMode>
<featureBlendMode>0</featureBlendMode>
<layerGeometryType>2</layerGeometryType>
</qgis>

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("")

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)

112
ui/tabs/working_tab.py Normal file
View File

@@ -0,0 +1,112 @@
from qgis.PyQt.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QMessageBox
from qgis.PyQt.QtCore import Qt
from qgis.core import Qgis, QgsProject, QgsMessageLog
from qgis.utils import iface
from sn_verfahrensgebiet.functions.verfahrensgebiet_alkis import verfahrensgebiet_alkis, LoadStatus
from sn_basis.functions.messages import success, info, warning, error
from sn_basis.functions.styles 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 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)
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():
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")
self.setze_haken(self.haken_verf, True)
# 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:
info("Verfahrensgebiet", "Vorhandener Layer wurde behalten.", duration=4)
elif status == LoadStatus.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("")