Schilder setzen wie im Browser: Palette und zwei Kartenwerkzeuge

Bisher konnte man die Zeichen in QGIS nur sehen und ihre Attribute von Hand tippen. Jetzt
gibt es dieselbe Bedienung wie im Web (Erik, 21.09.2026; Nutzerkreis sind TG-Mitarbeiter
und der Landkreis):

* Neues Modul zeichen_werkzeug.py mit der Palette (Suchfeld nach Nummer oder Name,
  Kategorie, Kacheln aus den lokal abgelegten Vorschaubildern, Deckel bei 96 wie im
  Browser) und zwei Kartenwerkzeugen: "Schild setzen" (erster Klick Standort, zweiter
  Klick Blickrichtung; unter 0,5 m bleibt die Drehung 0) und "Zusatzzeichen" (Klick auf ein
  vorhandenes Schild haengt es darunter, kein Doppel, hoechstens zwei).
* Die Rechenregeln sind Zwillinge von vz_geom.js (vzRichtungGrad, vzNormGrad,
  vzZusatzErgaenzen) -- dieselben Werte, hier in Python, mit denselben Pruefpunkten.
* Zeichen am Weg eines Blattes brauchen ein Blatt: die Auswahl fuellt sich aus den
  geladenen Blatt-Layern, eine eigene Abfrage braucht es nicht. In der Verfahrenskarte
  bleibt sie leer.
* Seitenleiste: neue Gruppe "Verkehrszeichen setzen". Der Katalog kommt beim Start und nach
  dem Anmelden in die Palette (oeffentlich, faellt auf die lokale Ablage zurueck).

Neuer Test tools/headless_zeichen_test.py (QGIS 4.2 offscreen, ohne Zugangsschluessel):
30 Pruefungen gruen -- Rechenregeln, zusatz aus Text, Katalog, lokale Ablage, Umschreiben
des Stils, Palette mit Suche und Deckel. tools/headless_panel_test.py bleibt gruen; die
Leiste ist jetzt 1372 px hoch und rollt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
KAI
2026-09-21 11:34:48 +02:00
co-authored by Claude Opus 5
parent d79dff1093
commit 9c2c1c57af
4 changed files with 568 additions and 1 deletions
+71
View File
@@ -34,6 +34,7 @@ class VlnKartenPlugin:
self.client = KartenApiClient()
self.actions = []
self.panel = None
self._werkzeuge = {"schild": None, "zusatz": None} # Kartenwerkzeuge, faul gebaut
# ------------------------------------------------------------------
# Plugin-Lebenszyklus
@@ -54,6 +55,8 @@ class VlnKartenPlugin:
"dienste_holen": self.run_dienste_holen,
"dienste_laden": self.run_dienste_laden,
"save_style": self.run_save_style,
"zeichen_setzen": self.run_zeichen_setzen,
"zusatz_anhaengen": self.run_zusatz_anhaengen,
},
)
self.iface.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self.panel)
@@ -83,6 +86,9 @@ class VlnKartenPlugin:
if api_key:
self.client = KartenApiClient(api_key=api_key, mail=mail)
QTimer.singleShot(0, self.populate_verfahren)
# Der Zeichenkatalog ist oeffentlich und liegt lokal — er kostet nichts und die
# Palette ist damit gleich nach dem Start bedienbar.
QTimer.singleShot(0, self._katalog_laden)
else:
QTimer.singleShot(1500, self.run_login)
@@ -126,6 +132,7 @@ class VlnKartenPlugin:
settings.setValue("mail", client.mail or dialog.mail())
settings.endGroup()
self._katalog_laden() # Palette fuellen (oeffentlicher Katalog)
self.iface.messageBar().pushMessage(
"VLN Karten",
"Angemeldet als %s — der API-Key ist gespeichert und gilt auch nach einem "
@@ -260,6 +267,70 @@ class VlnKartenPlugin:
self.iface, self.client.base_url, vkz, self.panel.aktueller_text(), collections,
authcfg, api_key=None if authcfg else self.client.api_key, client=self.client)
# ------------------------------------------------------------------
# Verkehrszeichen setzen
# ------------------------------------------------------------------
def _zeichen_melden(self, text, fehler=False):
self.panel.set_status(text)
if fehler:
self.iface.messageBar().pushMessage("VLN Karten", text, level=Qgis.Warning,
duration=6)
def _werkzeug(self, art):
"""Das Kartenwerkzeug bauen (einmal je Art) — beide teilen Palette und Blattwahl."""
from . import zeichen_werkzeug as zwm
if self._werkzeuge.get(art) is None:
canvas = self.iface.mapCanvas()
code = self.panel.aktueller_zeichencode
if art == "schild":
self._werkzeuge[art] = zwm.SchildSetzen(canvas, self.iface, code,
self._zeichen_melden,
self.panel.aktuelles_blatt)
else:
self._werkzeuge[art] = zwm.ZusatzAnhaengen(canvas, self.iface, code,
self._zeichen_melden)
return self._werkzeuge[art]
def _werkzeug_schalten(self, art, knopf):
canvas = self.iface.mapCanvas()
if not knopf.isChecked():
canvas.unsetMapTool(self._werkzeuge.get(art))
return
# Nur eines von beiden zur Zeit.
self.panel.werkzeug_zuruecksetzen()
knopf.setChecked(True)
werkzeug = self._werkzeug(art)
if hasattr(werkzeug, "reset"):
werkzeug.reset()
canvas.setMapTool(werkzeug)
def run_zeichen_setzen(self):
"""Werkzeug „Schild setzen" ein- oder ausschalten."""
self._blaetter_auffrischen()
self._werkzeug_schalten("schild", self.panel.schild_knopf)
def run_zusatz_anhaengen(self):
"""Werkzeug „Zusatzzeichen anhaengen" ein- oder ausschalten."""
self._werkzeug_schalten("zusatz", self.panel.zusatz_knopf)
def _blaetter_auffrischen(self):
"""Die Blattwahl aus den geladenen Layern fuellen (keine eigene Abfrage noetig)."""
try:
from . import zeichen_werkzeug as zwm
self.panel.setze_blaetter(zwm.blaetter_im_projekt())
except Exception: # noqa: BLE001
pass
def _katalog_laden(self):
"""Den Zeichenkatalog in die Palette holen (Server, sonst lokale Ablage)."""
try:
from . import zeichen_katalog as zk
self.panel.palette.setze_katalog(zk.katalog(self.client), self.client)
except Exception: # noqa: BLE001
pass # ohne Katalog bleibt die Palette leer
def run_save_edits(self):
"""Offene Bearbeitungssitzungen aller geladenen VLN-Layer schließen.