Nur noch OGC: Aenderungen speichern in der Seitenleiste, GeoJSON-Weg entfernt

Erik, 08.09.2026: "in die GUI das Speichern via OGC einbauen, GeoJSON nicht mehr
verwenden."

- Seitenleiste hat jetzt zwei Bloecke: "Layer" (Auswahl, laden, Aenderungen
  speichern) und "Darstellung" (Stil, Vorlage-Haken).
- Neuer Knopf "Aenderungen speichern" -> VlnKartenPlugin.run_save_edits():
  schliesst die offenen Bearbeitungssitzungen ALLER geladenen OAPIF-Layer auf
  einmal; ohne offene Bearbeitung kommt ein Hinweis statt einer Aktion.
  Zurueckgeschrieben wird ohnehin je Feature (Part 4), der Knopf beendet nur die
  Sitzung.
- Der GeoJSON-Weg ist raus: die vier Datensatz-Knoepfe, "Aktiven Layer
  hochladen", DATASETS, run_load_dataset, run_upload_active_layer,
  _confirm_replace_existing, vln_karten/layer_manager.py sowie
  KartenApiClient.load_layer_complete/save_feature_collection.
- Stil-Hinweise angepasst: den Stil des eigenen Verfahrens darf jeder speichern,
  die Vorlage nur die Gruppe MODUL_KARTENSTIL (Server-PR #565).

Geprueft headless mit QGIS 4.2 gegen die Live-API (TG Test 27998): ohne
Bearbeitung Hinweis, mit Aenderung Sitzung geschlossen, API zaehlt +1, Feature
sichtbar, danach wieder aufgeraeumt. Panel-Test deckt die neuen Knoepfe ab.
metadata.txt 0.5.0.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
erik
2026-09-08 10:06:45 +02:00
co-authored by Claude Fable 5.1
parent 1680b4ede3
commit 6b0ce65c61
7 changed files with 92 additions and 468 deletions
+41 -40
View File
@@ -10,9 +10,14 @@ umgeschaltet.
Aufbau von oben nach unten:
1. Anmeldung — Status + Knopf (Anmelden/Abmelden)
2. Verfahren — Suchfeld (filtert) + Auswahlliste
3. OGC API — alle Layer laden, Stil speichern (mit Häkchen „für alle Verfahren")
4. Klassisch — die einzelnen GeoJSON-Datensätze, aktiven Layer hochladen
3. Layer — Auswahl der Gruppen, laden, Änderungen speichern
4. Darstellung — Stil speichern (mit Häkchen „für alle Verfahren")
5. Statuszeile
Der frühere GeoJSON-Weg (Kopie laden, später als Ganzes hochladen) ist am 08.09.2026
entfallen (Erik: „das Speichern via OGC einbauen, GeoJSON nicht mehr verwenden"). Über
die OGC API schreibt QGIS jede Änderung einzeln zurück; „Änderungen speichern" schließt
nur die offenen Bearbeitungssitzungen.
"""
from qgis.PyQt.QtCore import Qt
@@ -42,7 +47,7 @@ def _klein(widget):
class VlnPanel(QDockWidget):
"""Die Seitenleiste. ``callbacks`` bündelt die Rückrufe ins Plugin."""
def __init__(self, parent=None, callbacks=None, datensaetze=()):
def __init__(self, parent=None, callbacks=None):
super().__init__(PANEL_TITEL, parent)
self.setObjectName(PANEL_OBJEKT)
self.setAllowedAreas(Qt.DockWidgetArea.RightDockWidgetArea
@@ -58,8 +63,8 @@ class VlnPanel(QDockWidget):
aussen.addWidget(self._bau_anmeldung())
aussen.addWidget(self._bau_verfahren())
aussen.addWidget(self._bau_ogc())
aussen.addWidget(self._bau_klassisch(datensaetze))
aussen.addWidget(self._bau_layer())
aussen.addWidget(self._bau_darstellung())
aussen.addStretch(1)
aussen.addWidget(self._bau_status())
@@ -104,13 +109,13 @@ class VlnPanel(QDockWidget):
lage.addWidget(self.combo)
return kasten
def _bau_ogc(self):
kasten = QGroupBox("OGC API (empfohlen)")
def _bau_layer(self):
kasten = QGroupBox("Layer")
lage = QVBoxLayout(kasten)
lage.setSpacing(6)
# Jede Sammlung kostet beim Anlegen rund eine halbe Sekunde (der Provider fragt
# Sammlung, Schema, Stil, OPTIONS und die erste Seite ab). Wer nur einen Teil braucht,
# ist mit der Auswahl deutlich schneller: 27 Layer ~16 s, die Vorerhebung allein ~2 s.
# ist mit der Auswahl deutlich schneller: 27 Layer ~14 s, die Vorerhebung allein ~2 s.
lage.addWidget(_klein(QLabel("Was geladen wird:")))
self.gruppen_haken = {}
for schluessel, beschriftung in (("Verfahren", "Verfahren (Umring, Plan 41, KAS …)"),
@@ -121,40 +126,37 @@ class VlnPanel(QDockWidget):
lage.addWidget(haken)
self.gruppen_haken[schluessel] = haken
self.ogc_knopf = QPushButton("Layer laden")
self.ogc_knopf.setToolTip("Die angehakten Sammlungen als editierbare OAPIF-Layer; "
"QGIS schreibt Änderungen direkt zurück")
self.ogc_knopf.setToolTip("Die angehakten Sammlungen als editierbare Layer der OGC API")
self.ogc_knopf.clicked.connect(lambda: self._ruf("load_ogc"))
self.stil_knopf = QPushButton("Stil des aktiven Layers speichern")
self.stil_knopf.setToolTip("Braucht die Gruppe MODUL_KARTENSTIL (Verbandsmitarbeiter "
"immer)")
self.stil_knopf.clicked.connect(lambda: self._ruf("save_style"))
self.vorlage_haken = QCheckBox("als Vorlage für alle Verfahren")
self.vorlage_haken.setToolTip("Der Stil gilt dann für diese Art in jedem Verfahren, "
"z. B. für jede Karte alter Stand")
lage.addWidget(self.ogc_knopf)
lage.addWidget(self.stil_knopf)
lage.addWidget(self.vorlage_haken)
return kasten
def _bau_klassisch(self, datensaetze):
kasten = QGroupBox("Klassisch (GeoJSON)")
lage = QVBoxLayout(kasten)
lage.setSpacing(6)
lage.addWidget(_klein(QLabel("Lädt eine Kopie; Änderungen gehen erst mit "
"„Aktiven Layer hochladen“ zurück.")))
self.datensatz_knoepfe = []
for schluessel, beschriftung in datensaetze:
knopf = QPushButton(beschriftung)
knopf.clicked.connect(lambda _=False, s=schluessel: self._ruf("load_dataset", s))
lage.addWidget(knopf)
self.datensatz_knoepfe.append(knopf)
linie = QFrame()
linie.setFrameShape(QFrame.Shape.HLine)
linie.setFrameShadow(QFrame.Shadow.Sunken)
self.speichern_knopf = QPushButton("Änderungen speichern")
self.speichern_knopf.setToolTip("Schließt die offenen Bearbeitungssitzungen aller "
"geladenen VLN-Layer; jede Änderung geht einzeln an "
"die API")
self.speichern_knopf.clicked.connect(lambda: self._ruf("save_edits"))
lage.addWidget(self.ogc_knopf)
lage.addWidget(linie)
self.upload_knopf = QPushButton("Aktiven Layer hochladen")
self.upload_knopf.clicked.connect(lambda: self._ruf("upload"))
lage.addWidget(self.upload_knopf)
lage.addWidget(self.speichern_knopf)
lage.addWidget(_klein(QLabel("Bearbeiten wie gewohnt über den Stift; Speichern schreibt "
"jede Änderung sofort zurück.")))
return kasten
def _bau_darstellung(self):
kasten = QGroupBox("Darstellung")
lage = QVBoxLayout(kasten)
lage.setSpacing(6)
self.stil_knopf = QPushButton("Stil des aktiven Layers speichern")
self.stil_knopf.setToolTip("Den Stil dieses Verfahrens darf jeder speichern, der das "
"Verfahren sieht")
self.stil_knopf.clicked.connect(lambda: self._ruf("save_style"))
self.vorlage_haken = QCheckBox("als Vorlage für alle Verfahren")
self.vorlage_haken.setToolTip("Gilt dann für diese Art in jedem Verfahren, z. B. für "
"jede Karte alter Stand — nur für die Gruppe "
"MODUL_KARTENSTIL")
lage.addWidget(self.stil_knopf)
lage.addWidget(self.vorlage_haken)
return kasten
def _bau_status(self):
@@ -171,9 +173,8 @@ class VlnPanel(QDockWidget):
else ("Angemeldet" if angemeldet else "Nicht angemeldet"))
self.login_knopf.setVisible(not angemeldet)
self.logout_knopf.setVisible(angemeldet)
for widget in (self.filter_feld, self.combo, self.ogc_knopf, self.stil_knopf,
self.vorlage_haken, self.upload_knopf, *self.gruppen_haken.values(),
*self.datensatz_knoepfe):
for widget in (self.filter_feld, self.combo, self.ogc_knopf, self.speichern_knopf,
self.stil_knopf, self.vorlage_haken, *self.gruppen_haken.values()):
widget.setEnabled(angemeldet)
if not angemeldet:
self._stumm = True