Erik, 06.10.2026: neben dem Thema eine zweite Gliederung — für welche Karten ein Dienst gedacht ist (Wege- und Gewässerplan, Neugestaltungsgrundsätze, Wertermittlung; mehrfach). Der Manager liefert dafür je Eintrag `karten` und den Katalog unter GET /linkliste/karten. Über der Dienstliste steht jetzt je Karte ein Häkchen (Katalog vom Server, Rückfall auf die drei Karten bei älterem Server). Eine oder mehrere Karten gewählt: angehakt sind die Dienste mit mindestens einer passenden Karte (linkliste.vorhaken), ohne Wahl alle wie bisher; von Hand nachjustieren bleibt möglich, eine neu geholte Liste übernimmt die Wahl. Karten im Tooltip. Fassung bleibt 0.7.0 (noch nicht ausgeliefert). Tests ohne Netz erweitert, beide grün. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
489 lines
23 KiB
Python
489 lines
23 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""Seitenleiste (andockbares Panel) des Plugins — rechts in QGIS.
|
||
|
||
Ersetzt die frühere Werkzeugleiste (Erik, 08.09.2026: „keine Toolbar, sondern eine
|
||
Seitenleiste auf der rechten Seite"). Das Panel ist reine Oberfläche: es hält keinen
|
||
Zustand der Fachlogik, sondern meldet Klicks über Rückrufe (``callbacks``) an
|
||
``VlnKartenPlugin`` und wird von dort über ``set_angemeldet`` / ``set_verfahren``
|
||
umgeschaltet.
|
||
|
||
Aufbau von oben nach unten:
|
||
1. Anmeldung — Status + Knopf (Anmelden/Abmelden)
|
||
2. Verfahren — Suchfeld (filtert) + Auswahlliste
|
||
3. Layer — Auswahl der Gruppen, laden, Änderungen speichern
|
||
4. Geodienste — die Linkliste des Verfahrens: auswählen und als Layer laden
|
||
5. Darstellung — Stil speichern (mit Häkchen „für alle Verfahren")
|
||
6. Statuszeile
|
||
|
||
Der Inhalt sitzt in einer Rollfläche: ist die Leiste höher als der Bildschirm, rollt sie,
|
||
statt das QGIS-Fenster zu strecken (Issue #1).
|
||
|
||
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
|
||
from qgis.PyQt.QtWidgets import (QCheckBox, QComboBox, QDockWidget, QFrame, QGroupBox,
|
||
QHBoxLayout, QLabel, QLineEdit, QListWidget,
|
||
QListWidgetItem, QPushButton, QScrollArea, QSizePolicy,
|
||
QVBoxLayout, QWidget)
|
||
|
||
PANEL_TITEL = "VLN Karten"
|
||
PANEL_OBJEKT = "VlnKartenPanel"
|
||
|
||
|
||
def ist_landkreis(vkz):
|
||
"""Steht ``vkz`` für einen Landkreis (oFB, 10–100) statt für ein Verfahren?
|
||
|
||
Landkreise stehen seit 0.7.0 oben in der Auswahl — gewählt lädt man dort nur die
|
||
Linkliste des Landkreises, keine Verfahrenslayer.
|
||
"""
|
||
try:
|
||
return 10 <= int(vkz) <= 100
|
||
except (TypeError, ValueError):
|
||
return False
|
||
|
||
|
||
def _klein(widget):
|
||
"""Hinweistexte eine Stufe kleiner und gedämpft — wie in QGIS-Panels üblich.
|
||
|
||
Die Farbe kommt aus der Palette (``palette(mid)``), damit der Text in hellen wie
|
||
dunklen QGIS-Themen lesbar bleibt; ``setEnabled(False)`` wäre dafür der falsche Weg,
|
||
weil es das Widget zugleich unbedienbar macht.
|
||
"""
|
||
schrift = widget.font()
|
||
schrift.setPointSizeF(max(8.0, schrift.pointSizeF() - 1.0))
|
||
widget.setFont(schrift)
|
||
widget.setWordWrap(True)
|
||
widget.setStyleSheet("color: palette(mid);")
|
||
return widget
|
||
|
||
|
||
class VlnPanel(QDockWidget):
|
||
"""Die Seitenleiste. ``callbacks`` bündelt die Rückrufe ins Plugin."""
|
||
|
||
def __init__(self, parent=None, callbacks=None):
|
||
super().__init__(PANEL_TITEL, parent)
|
||
self.setObjectName(PANEL_OBJEKT)
|
||
self.setAllowedAreas(Qt.DockWidgetArea.RightDockWidgetArea
|
||
| Qt.DockWidgetArea.LeftDockWidgetArea)
|
||
self._cb = callbacks or {}
|
||
self._verfahren = [] # [(beschriftung, vkz)] — ungefiltert
|
||
self._stumm = False # unterdrückt Signale beim programmatischen Füllen
|
||
|
||
inhalt = QWidget()
|
||
aussen = QVBoxLayout(inhalt)
|
||
aussen.setContentsMargins(8, 8, 8, 8)
|
||
aussen.setSpacing(10)
|
||
|
||
aussen.addWidget(self._bau_anmeldung())
|
||
aussen.addWidget(self._bau_verfahren())
|
||
aussen.addWidget(self._bau_layer())
|
||
aussen.addWidget(self._bau_zeichen())
|
||
aussen.addWidget(self._bau_dienste())
|
||
aussen.addWidget(self._bau_darstellung())
|
||
aussen.addStretch(1)
|
||
aussen.addWidget(self._bau_status())
|
||
|
||
inhalt.setMinimumWidth(260)
|
||
|
||
# Die Seitenleiste haengt in einer Rollflaeche, nicht direkt im Dock (Daniel Helbig,
|
||
# LK Meissen, 14.09.2026 — Issue #1 „UI-Ueberlauf"): ein QDockWidget gibt die
|
||
# Mindesthoehe seines Inhalts an das Hauptfenster weiter. Ist der Inhalt hoeher als
|
||
# der Bildschirm, waechst das QGIS-Fenster mit und sein unterer Rand rutscht ins
|
||
# Unsichtbare — samt Statusleiste. Die Rollflaeche kappt diese Weitergabe und blendet
|
||
# stattdessen einen senkrechten Rollbalken ein.
|
||
rolle = QScrollArea()
|
||
rolle.setWidget(inhalt)
|
||
rolle.setWidgetResizable(True) # Inhalt folgt der Breite des Docks
|
||
rolle.setFrameShape(QFrame.Shape.NoFrame)
|
||
rolle.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
||
rolle.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
||
# Ohne das bleibt die Mindesthoehe des Inhalts am Dock haengen und der Rollbalken
|
||
# aendert nichts an der gemeldeten Groesse. Uebrig bleibt die eigene Mindesthoehe der
|
||
# Rollflaeche (gemessen 88 px) — klein genug fuer jeden Bildschirm, gross genug,
|
||
# dass sich das Dock nicht auf einen Strich zusammenziehen laesst.
|
||
rolle.setMinimumHeight(0)
|
||
# Breite des Rollbalkens draufschlagen, sonst schneidet er die Auswahllisten an.
|
||
balken = rolle.verticalScrollBar().sizeHint().width() or 16
|
||
rolle.setMinimumWidth(260 + balken)
|
||
|
||
self.setWidget(rolle)
|
||
self.set_angemeldet(False)
|
||
|
||
# ------------------------------------------------------------------
|
||
# Aufbau
|
||
# ------------------------------------------------------------------
|
||
|
||
def _bau_anmeldung(self):
|
||
kasten = QGroupBox("Anmeldung")
|
||
lage = QVBoxLayout(kasten)
|
||
lage.setSpacing(6)
|
||
self.status_label = QLabel("Nicht angemeldet")
|
||
self.status_label.setWordWrap(True)
|
||
self.login_knopf = QPushButton("Anmelden …")
|
||
self.login_knopf.clicked.connect(lambda: self._ruf("login"))
|
||
self.logout_knopf = QPushButton("Abmelden")
|
||
self.logout_knopf.clicked.connect(lambda: self._ruf("logout"))
|
||
zeile = QHBoxLayout()
|
||
zeile.addWidget(self.login_knopf)
|
||
zeile.addWidget(self.logout_knopf)
|
||
lage.addWidget(self.status_label)
|
||
lage.addLayout(zeile)
|
||
return kasten
|
||
|
||
def _bau_verfahren(self):
|
||
kasten = QGroupBox("Verfahren")
|
||
lage = QVBoxLayout(kasten)
|
||
lage.setSpacing(6)
|
||
self.filter_feld = QLineEdit()
|
||
self.filter_feld.setPlaceholderText("filtern (Name oder Kennzeichen) …")
|
||
self.filter_feld.setClearButtonEnabled(True)
|
||
self.filter_feld.textChanged.connect(self._filter_geaendert)
|
||
self.combo = QComboBox()
|
||
self.combo.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
|
||
self.combo.setToolTip("Teilnehmergemeinschaft, für die geladen und gespeichert wird")
|
||
self.combo.currentIndexChanged.connect(self._auswahl_geaendert)
|
||
lage.addWidget(self.filter_feld)
|
||
lage.addWidget(self.combo)
|
||
return kasten
|
||
|
||
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 ~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 …)"),
|
||
("Vorerhebung", "Vorerhebung"),
|
||
("Maßnahmenblätter", "Maßnahmenblätter (mit Zeichen am Weg)"),
|
||
("Widmungen & Verkehrszeichen",
|
||
"Widmungen && Verkehrszeichen")):
|
||
haken = QCheckBox(beschriftung)
|
||
haken.setChecked(True)
|
||
lage.addWidget(haken)
|
||
self.gruppen_haken[schluessel] = haken
|
||
self.ogc_knopf = QPushButton("Layer laden")
|
||
self.ogc_knopf.setToolTip("Die angehakten Sammlungen als editierbare Layer der OGC API")
|
||
self.ogc_knopf.clicked.connect(lambda: self._ruf("load_ogc"))
|
||
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)
|
||
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_zeichen(self):
|
||
"""Verkehrszeichen setzen — Palette, Blattwahl, zwei Werkzeuge.
|
||
|
||
Die Bedienung ist dieselbe wie im Browser: erst ein Schild waehlen, dann in der Karte
|
||
zwei Klicks (Standort, Blickrichtung). Das Blatt braucht nur, wer Zeichen am Weg eines
|
||
Massnahmenblatts setzt — in der Verfahrenskarte bleibt die Auswahl leer.
|
||
"""
|
||
from .zeichen_werkzeug import ZeichenPalette
|
||
|
||
kasten = QGroupBox("Verkehrszeichen setzen")
|
||
lage = QVBoxLayout(kasten)
|
||
lage.setSpacing(6)
|
||
lage.addWidget(_klein(QLabel("Schild waehlen, dann in der Karte: erster Klick Standort, "
|
||
"zweiter Klick Blickrichtung.")))
|
||
self.palette = ZeichenPalette()
|
||
lage.addWidget(self.palette)
|
||
lage.addWidget(_klein(QLabel("Blatt (nur fuer Zeichen am Weg):")))
|
||
self.blatt_combo = QComboBox()
|
||
self.blatt_combo.setToolTip("An welches Massnahmenblatt das Zeichen gehoert")
|
||
self.blatt_combo.addItem("— kein Blatt (Verfahrenskarte) —", None)
|
||
lage.addWidget(self.blatt_combo)
|
||
zeile = QHBoxLayout()
|
||
self.schild_knopf = QPushButton("Schild setzen")
|
||
self.schild_knopf.setCheckable(True)
|
||
self.schild_knopf.setToolTip("Zwei Klicks in der Karte: Standort, dann Blickrichtung")
|
||
self.schild_knopf.clicked.connect(lambda: self._ruf("zeichen_setzen"))
|
||
self.zusatz_knopf = QPushButton("Zusatzzeichen")
|
||
self.zusatz_knopf.setCheckable(True)
|
||
self.zusatz_knopf.setToolTip("Gewaehltes Zusatzzeichen an ein vorhandenes Schild haengen")
|
||
self.zusatz_knopf.clicked.connect(lambda: self._ruf("zusatz_anhaengen"))
|
||
zeile.addWidget(self.schild_knopf)
|
||
zeile.addWidget(self.zusatz_knopf)
|
||
lage.addLayout(zeile)
|
||
return kasten
|
||
|
||
def setze_blaetter(self, blaetter):
|
||
"""Die Auswahl der Blaetter fuellen — ``[(Beschriftung, uuid)]``."""
|
||
vorher = self.blatt_combo.currentData()
|
||
self.blatt_combo.blockSignals(True)
|
||
self.blatt_combo.clear()
|
||
self.blatt_combo.addItem("— kein Blatt (Verfahrenskarte) —", None)
|
||
for text, uuid_ in blaetter or []:
|
||
self.blatt_combo.addItem(text, uuid_)
|
||
if vorher:
|
||
i = self.blatt_combo.findData(vorher)
|
||
if i >= 0:
|
||
self.blatt_combo.setCurrentIndex(i)
|
||
self.blatt_combo.blockSignals(False)
|
||
|
||
def aktuelles_blatt(self):
|
||
return self.blatt_combo.currentData()
|
||
|
||
def aktueller_zeichencode(self):
|
||
return str((self.palette.aktueller_eintrag() or {}).get("code") or "")
|
||
|
||
def werkzeug_zuruecksetzen(self):
|
||
"""Beide Werkzeugknoepfe ausrasten (wenn QGIS das Werkzeug wechselt)."""
|
||
for knopf in (self.schild_knopf, self.zusatz_knopf):
|
||
knopf.blockSignals(True)
|
||
knopf.setChecked(False)
|
||
knopf.blockSignals(False)
|
||
|
||
def _bau_dienste(self):
|
||
"""Die Linkliste des gewählten Verfahrens oder Landkreises — gepflegt landesweit und vom
|
||
Landkreis, hier nur geladen.
|
||
|
||
Die Liste kommt fertig aufgelöst vom Server; je Zeile stehen Gruppe, Untergruppe und
|
||
Herkunft dabei, damit man sieht, wo ein Dienst herkommt.
|
||
"""
|
||
kasten = QGroupBox("Geodienste (Linkliste)")
|
||
lage = QVBoxLayout(kasten)
|
||
lage.setSpacing(6)
|
||
lage.addWidget(_klein(QLabel("WMS-, WFS- und ArcGIS-Dienste für dieses Verfahren "
|
||
"oder den gewählten Landkreis.")))
|
||
# Kartenwahl (Erik, 06.10.2026): hakt vor, was für die gewählte Karte gedacht ist.
|
||
# Die Häkchen entstehen erst mit dem Katalog vom Server (set_karten).
|
||
self.karten_haken = {}
|
||
self._karten_namen = {}
|
||
self.karten_zeile = QHBoxLayout()
|
||
self.karten_zeile.setSpacing(10)
|
||
self.karten_beschriftung = _klein(QLabel("Für Karte:"))
|
||
self.karten_beschriftung.setVisible(False)
|
||
self.karten_zeile.addWidget(self.karten_beschriftung)
|
||
lage.addLayout(self.karten_zeile)
|
||
self.dienste_liste = QListWidget()
|
||
# Bewusst niedrig: die Mindesthoehe aller Kaesten zusammen ist die Mindesthoehe des
|
||
# Docks (s. Rollflaeche im Konstruktor). 140 px hier machten die Seitenleiste auf
|
||
# einem 13-Zoll-Bildschirm hoeher als das Fenster.
|
||
self.dienste_liste.setMinimumHeight(90)
|
||
self.dienste_liste.setToolTip("Angehakte Dienste werden geladen")
|
||
lage.addWidget(self.dienste_liste)
|
||
zeile = QHBoxLayout()
|
||
self.dienste_holen_knopf = QPushButton("Liste holen")
|
||
self.dienste_holen_knopf.clicked.connect(lambda: self._ruf("dienste_holen"))
|
||
self.dienste_laden_knopf = QPushButton("Ausgewählte laden")
|
||
self.dienste_laden_knopf.clicked.connect(lambda: self._ruf("dienste_laden"))
|
||
zeile.addWidget(self.dienste_holen_knopf)
|
||
zeile.addWidget(self.dienste_laden_knopf)
|
||
lage.addLayout(zeile)
|
||
self.dienste_alle = QPushButton("alle an- oder abwählen")
|
||
self.dienste_alle.setFlat(True)
|
||
self.dienste_alle.clicked.connect(self._dienste_umschalten)
|
||
lage.addWidget(self.dienste_alle)
|
||
return kasten
|
||
|
||
def _dienste_umschalten(self):
|
||
"""Alles an, wenn noch etwas aus ist; sonst alles aus."""
|
||
etwas_aus = any(self.dienste_liste.item(i).checkState() != Qt.CheckState.Checked
|
||
for i in range(self.dienste_liste.count()))
|
||
ziel = Qt.CheckState.Checked if etwas_aus else Qt.CheckState.Unchecked
|
||
for i in range(self.dienste_liste.count()):
|
||
self.dienste_liste.item(i).setCheckState(ziel)
|
||
|
||
def set_karten(self, katalog):
|
||
"""Die Kartenwahl aufbauen: je Karte ein Häkchen; eine Wahl hakt die passenden Dienste vor.
|
||
|
||
:param katalog: ``[{schluessel, name}]`` vom Server (``GET /linkliste/karten``).
|
||
"""
|
||
for haken in self.karten_haken.values():
|
||
self.karten_zeile.removeWidget(haken)
|
||
haken.deleteLater()
|
||
self.karten_haken = {}
|
||
self._karten_namen = {}
|
||
for k in katalog or []:
|
||
haken = QCheckBox(str(k.get("name") or k.get("schluessel")))
|
||
haken.setToolTip("Dienste für diese Karte vorhaken")
|
||
haken.stateChanged.connect(lambda _zustand: self._karten_anwenden())
|
||
self.karten_zeile.addWidget(haken)
|
||
self.karten_haken[str(k.get("schluessel"))] = haken
|
||
self._karten_namen[str(k.get("schluessel"))] = str(k.get("name") or k.get("schluessel"))
|
||
self.karten_beschriftung.setVisible(bool(self.karten_haken))
|
||
|
||
def gewaehlte_karten(self):
|
||
"""Schlüssel der angehakten Karten."""
|
||
return [k for k, haken in self.karten_haken.items() if haken.isChecked()]
|
||
|
||
def _karten_anwenden(self):
|
||
"""Die Dienste nach der Kartenwahl vorhaken (ohne Wahl: alle)."""
|
||
from .linkliste import vorhaken
|
||
eintraege = [self.dienste_liste.item(i) for i in range(self.dienste_liste.count())]
|
||
daten = [e.data(Qt.ItemDataRole.UserRole) or {} for e in eintraege]
|
||
for eintrag, an in zip(eintraege, vorhaken(daten, self.gewaehlte_karten())):
|
||
eintrag.setCheckState(Qt.CheckState.Checked if an else Qt.CheckState.Unchecked)
|
||
|
||
def set_dienste(self, dienste):
|
||
"""Die geholte Liste anzeigen: Name, Gruppe › Untergruppe und Herkunft, alle zunächst
|
||
angehakt."""
|
||
self.dienste_liste.clear()
|
||
for d in dienste or []:
|
||
gruppe = d.get("gruppe_name") or ""
|
||
if d.get("untergruppe"):
|
||
gruppe = "%s › %s" % (gruppe, d.get("untergruppe"))
|
||
text = "%s · %s · %s" % (d.get("name"), gruppe, d.get("herkunft_text") or "")
|
||
if d.get("stil"):
|
||
text += " · mit Stil"
|
||
eintrag = QListWidgetItem(text)
|
||
eintrag.setFlags(eintrag.flags() | Qt.ItemFlag.ItemIsUserCheckable)
|
||
eintrag.setCheckState(Qt.CheckState.Checked)
|
||
eintrag.setData(Qt.ItemDataRole.UserRole, d)
|
||
karten = ", ".join(self._karten_namen.get(k, k) for k in (d.get("karten") or []))
|
||
eintrag.setToolTip("%s\n%s%s" % (d.get("url"), d.get("beschreibung") or "",
|
||
("\nKarten: " + karten) if karten else ""))
|
||
self.dienste_liste.addItem(eintrag)
|
||
if self.gewaehlte_karten():
|
||
self._karten_anwenden()
|
||
|
||
def gewaehlte_dienste(self):
|
||
"""Die angehakten Einträge als Liste der Server-Datensätze."""
|
||
aus = []
|
||
for i in range(self.dienste_liste.count()):
|
||
e = self.dienste_liste.item(i)
|
||
if e.checkState() == Qt.CheckState.Checked:
|
||
aus.append(e.data(Qt.ItemDataRole.UserRole))
|
||
return aus
|
||
|
||
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 speichern, wer im Verfahren "
|
||
"schreiben darf (nicht bei „nur lesen“)")
|
||
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):
|
||
self.status_zeile = _klein(QLabel(""))
|
||
self.status_zeile.setToolTip("letzte Aktion")
|
||
return self.status_zeile
|
||
|
||
# ------------------------------------------------------------------
|
||
# Zustand (vom Plugin gesetzt)
|
||
# ------------------------------------------------------------------
|
||
|
||
def set_angemeldet(self, angemeldet, wer=None):
|
||
self.status_label.setText(("Angemeldet: %s" % wer) if angemeldet and wer
|
||
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.speichern_knopf,
|
||
self.schild_knopf, self.zusatz_knopf, self.palette, self.blatt_combo,
|
||
self.stil_knopf, self.vorlage_haken, self.dienste_holen_knopf,
|
||
self.dienste_laden_knopf, self.dienste_alle, self.dienste_liste,
|
||
*self.gruppen_haken.values(), *self.karten_haken.values()):
|
||
widget.setEnabled(angemeldet)
|
||
if not angemeldet:
|
||
self._stumm = True
|
||
self._verfahren = []
|
||
self.combo.clear()
|
||
self.combo.addItem("— bitte anmelden —", None)
|
||
self.filter_feld.clear()
|
||
self.dienste_liste.clear()
|
||
self._stumm = False
|
||
|
||
def set_verfahren(self, verfahren, aemter=()):
|
||
"""Die Auswahl füllen.
|
||
|
||
:param verfahren: ``[{"vkz", "name", "zugriff"}]`` aus der API; ``zugriff == "lesen"``
|
||
bekommt den Zusatz „nur lesen“ (oFB: Verfahren des eigenen Landkreises).
|
||
:param aemter: ``[{"vkz", "name"}]`` — die eigenen Landkreise stehen oben; gewählt lädt
|
||
man dort nur die Linkliste des Landkreises.
|
||
"""
|
||
eintraege = [("%s — Linkliste des Landkreises" % (a.get("name") or a["vkz"]), a["vkz"])
|
||
for a in aemter]
|
||
for v in verfahren:
|
||
text = "%s — %s" % (v["vkz"], v["name"]) if v.get("name") else str(v["vkz"])
|
||
if v.get("zugriff") == "lesen":
|
||
text += " (nur lesen)"
|
||
eintraege.append((text, v["vkz"]))
|
||
self._verfahren = eintraege
|
||
self._liste_fuellen()
|
||
|
||
def set_status(self, text):
|
||
self.status_zeile.setText(text or "")
|
||
|
||
def aktuelles_vkz(self):
|
||
return self.combo.currentData()
|
||
|
||
def aktueller_text(self):
|
||
return self.combo.currentText()
|
||
|
||
def als_vorlage(self):
|
||
return self.vorlage_haken.isChecked()
|
||
|
||
def gewaehlte_gruppen(self):
|
||
"""Namen der angehakten Layer-Gruppen (wie in ``ogc_layers.GRUPPEN``)."""
|
||
return {name for name, haken in self.gruppen_haken.items() if haken.isChecked()}
|
||
|
||
def waehle_vkz(self, vkz):
|
||
"""Setzt die Auswahl ohne Rückruf (Wiederherstellen aus der Projektdatei)."""
|
||
self._stumm = True
|
||
index = self.combo.findData(vkz) if vkz else -1
|
||
self.combo.setCurrentIndex(index if index >= 0 else 0)
|
||
self._stumm = False
|
||
|
||
def anzahl_eintraege(self):
|
||
return self.combo.count()
|
||
|
||
# ------------------------------------------------------------------
|
||
# Innenleben
|
||
# ------------------------------------------------------------------
|
||
|
||
def _liste_fuellen(self, muster=""):
|
||
"""Füllt die Auswahlliste, gefiltert; die bisherige Auswahl bleibt wenn möglich."""
|
||
vorher = self.combo.currentData()
|
||
muster = (muster or "").strip().lower()
|
||
treffer = [(t, v) for t, v in self._verfahren if muster in t.lower()]
|
||
self._stumm = True
|
||
self.combo.clear()
|
||
if not self._verfahren:
|
||
self.combo.addItem("— keine Verfahren —", None)
|
||
elif not treffer:
|
||
self.combo.addItem("— kein Treffer —", None)
|
||
else:
|
||
self.combo.addItem("— Verfahren wählen —", None)
|
||
for beschriftung, vkz in treffer:
|
||
self.combo.addItem(beschriftung, vkz)
|
||
index = self.combo.findData(vorher) if vorher else -1
|
||
self.combo.setCurrentIndex(index if index >= 0 else 0)
|
||
self._stumm = False
|
||
if index < 0 and vorher:
|
||
self._auswahl_geaendert(0)
|
||
|
||
def _filter_geaendert(self, text):
|
||
self._liste_fuellen(text)
|
||
|
||
def _auswahl_geaendert(self, _index):
|
||
if not self._stumm:
|
||
self._ruf("verfahren_gewaehlt", self.combo.currentData())
|
||
|
||
def _ruf(self, name, *args):
|
||
rueckruf = self._cb.get(name)
|
||
if rueckruf:
|
||
rueckruf(*args)
|