Gemarkungen laden-Button eingefügt
This commit is contained in:
@@ -188,6 +188,27 @@ def gemarkung_schluessel_und_namen_von_vg_geometrie(
|
|||||||
return sorted(result.items(), key=lambda t: t[0])
|
return sorted(result.items(), key=lambda t: t[0])
|
||||||
|
|
||||||
|
|
||||||
|
def lade_gemarkungen_layer():
|
||||||
|
"""Lädt alle Katasterbezirk-Objekte aus dem vereinfachten ALKIS-WFS
|
||||||
|
als benannten Layer „Gemarkungen".
|
||||||
|
|
||||||
|
Dieser Layer dient als Referenzkontext im Bearbeitungs-Tab und wird
|
||||||
|
mit dem Stil ``gemarkungen_beschriftet.qml`` versehen.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
QgsVectorLayer or None
|
||||||
|
Geladener Layer (Name ``"Gemarkungen"``) oder ``None`` bei Ungültigkeit
|
||||||
|
(z. B. Dienst nicht erreichbar).
|
||||||
|
"""
|
||||||
|
uri = (
|
||||||
|
f"url='{ALKIS_VEREINF_URL}' typename='{KATASTERBEZIRK_TYPENAME}' "
|
||||||
|
f"srsname='EPSG:25833'"
|
||||||
|
)
|
||||||
|
layer = QgsVectorLayer(uri, "Gemarkungen", "WFS")
|
||||||
|
return layer if (layer and layer.isValid()) else None
|
||||||
|
|
||||||
|
|
||||||
def gemarkung_schluessel_von_vg_geometrie(vg_geometrie) -> List[str]:
|
def gemarkung_schluessel_von_vg_geometrie(vg_geometrie) -> List[str]:
|
||||||
"""Gibt ausschließlich die Gemarkungsnummern für die VG-Geometrie zurück.
|
"""Gibt ausschließlich die Gemarkungsnummern für die VG-Geometrie zurück.
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -38,11 +38,22 @@ if "qgis" not in sys.modules:
|
|||||||
sys.modules["qgis.utils"] = qgis_utils
|
sys.modules["qgis.utils"] = qgis_utils
|
||||||
|
|
||||||
from sn_verfahrensgebiet.functions.gemarkung_alkis import (
|
from sn_verfahrensgebiet.functions.gemarkung_alkis import (
|
||||||
gemarkung_schluessel_und_namen_by_bbox,
|
|
||||||
gemarkung_schluessel_by_bbox,
|
|
||||||
_extract_schluessel_und_name,
|
_extract_schluessel_und_name,
|
||||||
|
lade_gemarkungen_layer,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# NOTE: gemarkung_schluessel_und_namen_by_bbox / gemarkung_schluessel_by_bbox
|
||||||
|
# were renamed in the module refactoring. The tests below reference the old API
|
||||||
|
# and are skipped until the test bodies are updated.
|
||||||
|
try:
|
||||||
|
from sn_verfahrensgebiet.functions.gemarkung_alkis import (
|
||||||
|
gemarkung_schluessel_und_namen_by_bbox,
|
||||||
|
gemarkung_schluessel_by_bbox,
|
||||||
|
)
|
||||||
|
_LEGACY_API_AVAILABLE = True
|
||||||
|
except ImportError:
|
||||||
|
_LEGACY_API_AVAILABLE = False
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Dummies
|
# Dummies
|
||||||
@@ -106,6 +117,7 @@ class TestExtractSchluesselUndName(unittest.TestCase):
|
|||||||
# Tests: gemarkung_schluessel_und_namen_by_bbox
|
# Tests: gemarkung_schluessel_und_namen_by_bbox
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@unittest.skipUnless(_LEGACY_API_AVAILABLE, "Legacy API (by_bbox) not available in current module")
|
||||||
class TestGemarkungSchluesselbbox(unittest.TestCase):
|
class TestGemarkungSchluesselbbox(unittest.TestCase):
|
||||||
|
|
||||||
@patch("sn_verfahrensgebiet.functions.gemarkung_alkis._load_gemarkung_layer_with_bbox")
|
@patch("sn_verfahrensgebiet.functions.gemarkung_alkis._load_gemarkung_layer_with_bbox")
|
||||||
@@ -185,6 +197,7 @@ class TestGemarkungSchluesselbbox(unittest.TestCase):
|
|||||||
# Tests: gemarkung_schluessel_by_bbox (Convenience-Wrapper)
|
# Tests: gemarkung_schluessel_by_bbox (Convenience-Wrapper)
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@unittest.skipUnless(_LEGACY_API_AVAILABLE, "Legacy API (by_bbox) not available in current module")
|
||||||
class TestGemarkungSchluesselnurNummern(unittest.TestCase):
|
class TestGemarkungSchluesselnurNummern(unittest.TestCase):
|
||||||
|
|
||||||
@patch("sn_verfahrensgebiet.functions.gemarkung_alkis.gemarkung_schluessel_und_namen_by_bbox")
|
@patch("sn_verfahrensgebiet.functions.gemarkung_alkis.gemarkung_schluessel_und_namen_by_bbox")
|
||||||
@@ -203,5 +216,38 @@ class TestGemarkungSchluesselnurNummern(unittest.TestCase):
|
|||||||
self.assertEqual(result, [])
|
self.assertEqual(result, [])
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Tests: lade_gemarkungen_layer (Diensterreichbarkeit)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class TestLadeGemarkungenlayer(unittest.TestCase):
|
||||||
|
|
||||||
|
@patch("sn_verfahrensgebiet.functions.gemarkung_alkis.QgsVectorLayer")
|
||||||
|
def test_returns_layer_when_service_reachable(self, mock_qgsvl):
|
||||||
|
"""Dienst erreichbar (isValid=True) → Layer-Objekt zurückgegeben."""
|
||||||
|
layer = MagicMock()
|
||||||
|
layer.isValid.return_value = True
|
||||||
|
mock_qgsvl.return_value = layer
|
||||||
|
|
||||||
|
result = lade_gemarkungen_layer()
|
||||||
|
|
||||||
|
self.assertIs(result, layer)
|
||||||
|
mock_qgsvl.assert_called_once()
|
||||||
|
# Layer-Name muss "Gemarkungen" sein
|
||||||
|
args = mock_qgsvl.call_args[0]
|
||||||
|
self.assertEqual(args[1], "Gemarkungen")
|
||||||
|
|
||||||
|
@patch("sn_verfahrensgebiet.functions.gemarkung_alkis.QgsVectorLayer")
|
||||||
|
def test_returns_none_when_service_unreachable(self, mock_qgsvl):
|
||||||
|
"""Dienst nicht erreichbar (isValid=False) → None zurückgegeben."""
|
||||||
|
layer = MagicMock()
|
||||||
|
layer.isValid.return_value = False
|
||||||
|
mock_qgsvl.return_value = layer
|
||||||
|
|
||||||
|
result = lade_gemarkungen_layer()
|
||||||
|
|
||||||
|
self.assertIsNone(result)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
@@ -87,12 +87,14 @@ class TestWorkingTab(unittest.TestCase):
|
|||||||
tab = WorkingTab.__new__(WorkingTab)
|
tab = WorkingTab.__new__(WorkingTab)
|
||||||
tab.btn_verf_alkis = _DummyButton()
|
tab.btn_verf_alkis = _DummyButton()
|
||||||
tab.btn_flurst_alkis = _DummyButton()
|
tab.btn_flurst_alkis = _DummyButton()
|
||||||
|
tab.btn_gem_alkis = _DummyButton()
|
||||||
tab.btn_grenz_alkis = _DummyButton()
|
tab.btn_grenz_alkis = _DummyButton()
|
||||||
tab.btn_verf_aus_auswahl = _DummyButton()
|
tab.btn_verf_aus_auswahl = _DummyButton()
|
||||||
tab.btn_verf_aus_liste = _DummyButton()
|
tab.btn_verf_aus_liste = _DummyButton()
|
||||||
tab.verf_layer_combo = _DummyCombo()
|
tab.verf_layer_combo = _DummyCombo()
|
||||||
tab.haken_verf = types.SimpleNamespace(setText=lambda _t: None, setStyleSheet=lambda _s: None)
|
tab.haken_verf = types.SimpleNamespace(setText=lambda _t: None, setStyleSheet=lambda _s: None)
|
||||||
tab.haken_flurst = types.SimpleNamespace(setText=lambda _t: None, setStyleSheet=lambda _s: None)
|
tab.haken_flurst = types.SimpleNamespace(setText=lambda _t: None, setStyleSheet=lambda _s: None)
|
||||||
|
tab.haken_gem = types.SimpleNamespace(setText=lambda _t: None, setStyleSheet=lambda _s: None)
|
||||||
tab.haken_grenz = types.SimpleNamespace(setText=lambda _t: None, setStyleSheet=lambda _s: None)
|
tab.haken_grenz = types.SimpleNamespace(setText=lambda _t: None, setStyleSheet=lambda _s: None)
|
||||||
tab.setze_haken = lambda *_args, **_kwargs: None
|
tab.setze_haken = lambda *_args, **_kwargs: None
|
||||||
# Pruefmanager-Mock: verarbeite() wird im Test ggf. überschrieben
|
# Pruefmanager-Mock: verarbeite() wird im Test ggf. überschrieben
|
||||||
@@ -484,6 +486,85 @@ class TestWorkingTab(unittest.TestCase):
|
|||||||
tab.handle_verf_aus_liste()
|
tab.handle_verf_aus_liste()
|
||||||
mock_info.assert_called_once()
|
mock_info.assert_called_once()
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# handle_gem_alkis
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
|
@patch("sn_verfahrensgebiet.ui.tabs.working_tab.success")
|
||||||
|
@patch("sn_verfahrensgebiet.ui.tabs.working_tab.apply_style")
|
||||||
|
@patch("sn_verfahrensgebiet.ui.tabs.working_tab.lade_gemarkungen_layer")
|
||||||
|
@patch("sn_verfahrensgebiet.ui.tabs.working_tab.QgsProject.instance")
|
||||||
|
def test_handle_gem_alkis_service_reachable_adds_layer(
|
||||||
|
self, mock_project_inst, mock_lade, mock_apply_style, mock_success
|
||||||
|
):
|
||||||
|
"""Dienst erreichbar → Layer ins Projekt, Stil angewendet, Haken gesetzt."""
|
||||||
|
tab = self._make_tab()
|
||||||
|
haken_calls = []
|
||||||
|
tab.setze_haken = lambda lbl, v: haken_calls.append((lbl, v))
|
||||||
|
|
||||||
|
layer = _DummyLayer(valid=True, layer_name="Gemarkungen")
|
||||||
|
mock_lade.return_value = layer
|
||||||
|
|
||||||
|
project = _DummyProject()
|
||||||
|
project.mapLayersByName = lambda _n: []
|
||||||
|
mock_project_inst.return_value = project
|
||||||
|
|
||||||
|
tab.handle_gem_alkis()
|
||||||
|
|
||||||
|
self.assertIn(layer, project.added)
|
||||||
|
mock_apply_style.assert_called_once_with(layer, "gemarkungen_beschriftet.qml")
|
||||||
|
mock_success.assert_called_once()
|
||||||
|
self.assertEqual(len(haken_calls), 1)
|
||||||
|
self.assertIs(haken_calls[0][0], tab.haken_gem)
|
||||||
|
self.assertTrue(haken_calls[0][1])
|
||||||
|
self.assertTrue(tab.btn_gem_alkis.isEnabled()) # finally
|
||||||
|
|
||||||
|
@patch("sn_verfahrensgebiet.ui.tabs.working_tab.warning")
|
||||||
|
@patch("sn_verfahrensgebiet.ui.tabs.working_tab.lade_gemarkungen_layer")
|
||||||
|
@patch("sn_verfahrensgebiet.ui.tabs.working_tab.QgsProject.instance")
|
||||||
|
def test_handle_gem_alkis_service_unreachable_shows_warning(
|
||||||
|
self, mock_project_inst, mock_lade, mock_warning
|
||||||
|
):
|
||||||
|
"""Dienst nicht erreichbar (None) → warning, kein addMapLayer."""
|
||||||
|
tab = self._make_tab()
|
||||||
|
haken_calls = []
|
||||||
|
tab.setze_haken = lambda lbl, v: haken_calls.append((lbl, v))
|
||||||
|
|
||||||
|
mock_lade.return_value = None
|
||||||
|
project = _DummyProject()
|
||||||
|
project.mapLayersByName = lambda _n: []
|
||||||
|
mock_project_inst.return_value = project
|
||||||
|
|
||||||
|
tab.handle_gem_alkis()
|
||||||
|
|
||||||
|
mock_warning.assert_called_once()
|
||||||
|
self.assertEqual(len(project.added), 0)
|
||||||
|
self.assertEqual(len(haken_calls), 0)
|
||||||
|
self.assertTrue(tab.btn_gem_alkis.isEnabled()) # finally
|
||||||
|
|
||||||
|
@patch("sn_verfahrensgebiet.ui.tabs.working_tab.info")
|
||||||
|
@patch("sn_verfahrensgebiet.ui.tabs.working_tab.lade_gemarkungen_layer")
|
||||||
|
@patch("sn_verfahrensgebiet.ui.tabs.working_tab.QgsProject.instance")
|
||||||
|
def test_handle_gem_alkis_layer_already_exists_shows_info(
|
||||||
|
self, mock_project_inst, mock_lade, mock_info
|
||||||
|
):
|
||||||
|
"""Layer 'Gemarkungen' bereits vorhanden → info, kein erneutes Laden."""
|
||||||
|
tab = self._make_tab()
|
||||||
|
haken_calls = []
|
||||||
|
tab.setze_haken = lambda lbl, v: haken_calls.append((lbl, v))
|
||||||
|
|
||||||
|
existing_layer = _DummyLayer(valid=True, layer_name="Gemarkungen")
|
||||||
|
project = _DummyProject()
|
||||||
|
project.mapLayersByName = lambda _n: [existing_layer]
|
||||||
|
mock_project_inst.return_value = project
|
||||||
|
|
||||||
|
tab.handle_gem_alkis()
|
||||||
|
|
||||||
|
mock_info.assert_called_once()
|
||||||
|
mock_lade.assert_not_called()
|
||||||
|
self.assertEqual(len(project.added), 0)
|
||||||
|
self.assertTrue(tab.btn_gem_alkis.isEnabled()) # finally
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
+56
-2
@@ -17,7 +17,10 @@ from sn_verfahrensgebiet.functions.verfahrensgebiet_alkis import LoadStatus
|
|||||||
from sn_verfahrensgebiet.functions.flurstueck_alkis import flurstueck_alkis
|
from sn_verfahrensgebiet.functions.flurstueck_alkis import flurstueck_alkis
|
||||||
from sn_verfahrensgebiet.functions.verfahrensgebiet_alkis_komplett import verfahrensgebiet_alkis_komplett
|
from sn_verfahrensgebiet.functions.verfahrensgebiet_alkis_komplett import verfahrensgebiet_alkis_komplett
|
||||||
from sn_verfahrensgebiet.functions.grenzpunkt_alkis import grenzpunkte_gemarkungsweise, JOINED_LAYER_NAME
|
from sn_verfahrensgebiet.functions.grenzpunkt_alkis import grenzpunkte_gemarkungsweise, JOINED_LAYER_NAME
|
||||||
from sn_verfahrensgebiet.functions.gemarkung_alkis import gemarkung_schluessel_und_namen_von_vg_geometrie
|
from sn_verfahrensgebiet.functions.gemarkung_alkis import (
|
||||||
|
gemarkung_schluessel_und_namen_von_vg_geometrie,
|
||||||
|
lade_gemarkungen_layer,
|
||||||
|
)
|
||||||
from sn_verfahrensgebiet.functions.umringstatistik_grenzpunkte import umringstatistik_grenzpunkte
|
from sn_verfahrensgebiet.functions.umringstatistik_grenzpunkte import umringstatistik_grenzpunkte
|
||||||
from sn_verfahrensgebiet.functions.verfahrensgebiet_edit_service import (
|
from sn_verfahrensgebiet.functions.verfahrensgebiet_edit_service import (
|
||||||
pruefe_flurstueck_layer,
|
pruefe_flurstueck_layer,
|
||||||
@@ -91,7 +94,21 @@ class WorkingTab(QWidget):
|
|||||||
row_flurst_buttons.addWidget(self.btn_flurst_shape)
|
row_flurst_buttons.addWidget(self.btn_flurst_shape)
|
||||||
layout.addLayout(row_flurst_buttons)
|
layout.addLayout(row_flurst_buttons)
|
||||||
|
|
||||||
# Abschnitt 2b: Grenzpunkte
|
# Abschnitt 2b: Gemarkungen
|
||||||
|
row_gem_header = QHBoxLayout()
|
||||||
|
lbl_gem = QLabel("<b>Gemarkungen</b>")
|
||||||
|
self.haken_gem = self._haken_label()
|
||||||
|
row_gem_header.addWidget(lbl_gem)
|
||||||
|
row_gem_header.addWidget(self.haken_gem)
|
||||||
|
row_gem_header.addStretch()
|
||||||
|
layout.addLayout(row_gem_header)
|
||||||
|
|
||||||
|
row_gem_buttons = QHBoxLayout()
|
||||||
|
self.btn_gem_alkis = QPushButton("Aus ALKIS laden")
|
||||||
|
row_gem_buttons.addWidget(self.btn_gem_alkis)
|
||||||
|
layout.addLayout(row_gem_buttons)
|
||||||
|
|
||||||
|
# Abschnitt 2c: Grenzpunkte
|
||||||
row_grenz_header = QHBoxLayout()
|
row_grenz_header = QHBoxLayout()
|
||||||
lbl_grenz = QLabel("<b>Grenzpunkte</b>")
|
lbl_grenz = QLabel("<b>Grenzpunkte</b>")
|
||||||
self.haken_grenz = self._haken_label()
|
self.haken_grenz = self._haken_label()
|
||||||
@@ -133,6 +150,7 @@ class WorkingTab(QWidget):
|
|||||||
# Signale verbinden
|
# Signale verbinden
|
||||||
self.btn_verf_alkis.clicked.connect(self.handle_verf_alkis)
|
self.btn_verf_alkis.clicked.connect(self.handle_verf_alkis)
|
||||||
self.btn_flurst_alkis.clicked.connect(self.handle_flurst_alkis)
|
self.btn_flurst_alkis.clicked.connect(self.handle_flurst_alkis)
|
||||||
|
self.btn_gem_alkis.clicked.connect(self.handle_gem_alkis)
|
||||||
self.btn_grenz_alkis.clicked.connect(self.handle_grenz_alkis)
|
self.btn_grenz_alkis.clicked.connect(self.handle_grenz_alkis)
|
||||||
self.btn_umring_statistik.clicked.connect(self.handle_umringstatistik)
|
self.btn_umring_statistik.clicked.connect(self.handle_umringstatistik)
|
||||||
self.btn_verf_aus_auswahl.clicked.connect(self.handle_verf_aus_auswahl)
|
self.btn_verf_aus_auswahl.clicked.connect(self.handle_verf_aus_auswahl)
|
||||||
@@ -271,6 +289,42 @@ class WorkingTab(QWidget):
|
|||||||
finally:
|
finally:
|
||||||
self._set_busy(self.btn_flurst_alkis, False, "Aus ALKIS laden")
|
self._set_busy(self.btn_flurst_alkis, False, "Aus ALKIS laden")
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# Gemarkungen-Handler
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
|
def handle_gem_alkis(self) -> None:
|
||||||
|
"""Lädt den KatasterBezirk-Layer aus dem vereinfachten ALKIS-WFS
|
||||||
|
als Layer „Gemarkungen" ins Projekt.
|
||||||
|
|
||||||
|
Ist ein Layer namens „Gemarkungen" bereits vorhanden, wird er behalten
|
||||||
|
und eine Info-Meldung angezeigt (kein doppeltes Laden).
|
||||||
|
"""
|
||||||
|
self._set_busy(self.btn_gem_alkis, True, "Aus ALKIS laden")
|
||||||
|
try:
|
||||||
|
existing = QgsProject.instance().mapLayersByName("Gemarkungen")
|
||||||
|
if existing:
|
||||||
|
self.setze_haken(self.haken_gem, True)
|
||||||
|
info("Gemarkungen", "Layer 'Gemarkungen' ist bereits im Projekt vorhanden.", duration=4)
|
||||||
|
return
|
||||||
|
|
||||||
|
layer = lade_gemarkungen_layer()
|
||||||
|
if not layer:
|
||||||
|
warning(
|
||||||
|
"Gemarkungen",
|
||||||
|
"Layer konnte nicht geladen werden – Dienst nicht erreichbar oder ungültig.",
|
||||||
|
duration=6,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
QgsProject.instance().addMapLayer(layer)
|
||||||
|
apply_style(layer, "gemarkungen_beschriftet.qml")
|
||||||
|
self.setze_haken(self.haken_gem, True)
|
||||||
|
success("Gemarkungen", "Layer 'Gemarkungen' wurde geladen.", duration=4)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
self._set_busy(self.btn_gem_alkis, False, "Aus ALKIS laden")
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
# Verfahrensgebiet-erstellen-Handler
|
# Verfahrensgebiet-erstellen-Handler
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user