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>
108 lines
5.3 KiB
Python
108 lines
5.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""Verkehrszeichen headless pruefen: Katalog, lokale Grafiken, Palette, Rechenregeln.
|
|
|
|
Aufruf (macOS, QGIS 4.2 im Bundle):
|
|
|
|
APP=/Applications/QGIS-final-4_2_0.app; LIB="$APP/Contents/Resources/python3.12"
|
|
QT_QPA_PLATFORM=offscreen PROJ_DATA="$APP/Contents/Resources/qgis/proj" \\
|
|
PYTHONPATH="$LIB:$LIB/lib-dynload:$LIB/site-packages" \\
|
|
"$APP/Contents/MacOS/python3.12" tools/headless_zeichen_test.py
|
|
|
|
Braucht keinen Zugangsschluessel: Katalog und Grafiken sind oeffentlich
|
|
(``/v2/zeichen/...``). Ohne Netz laeuft der Teil aus der lokalen Ablage; fehlt auch die,
|
|
werden die betroffenen Pruefungen uebersprungen und gemeldet.
|
|
"""
|
|
import os
|
|
import sys
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
from qgis.core import QgsApplication
|
|
|
|
app = QgsApplication([], True)
|
|
QgsApplication.setPrefixPath("/Applications/QGIS-final-4_2_0.app/Contents/MacOS", True)
|
|
QgsApplication.setPluginPath("/Applications/QGIS-final-4_2_0.app/Contents/PlugIns/qgis")
|
|
app.initQgis()
|
|
from qgis.PyQt.QtNetwork import QNetworkProxyFactory # noqa: E402
|
|
|
|
QNetworkProxyFactory.setUseSystemConfiguration(False)
|
|
|
|
from vln_karten import zeichen_katalog as zk # noqa: E402
|
|
from vln_karten import zeichen_werkzeug as zw # noqa: E402
|
|
from vln_karten.api_client import KartenApiClient # noqa: E402
|
|
|
|
FEHLER = []
|
|
|
|
|
|
def pruefe(bed, text):
|
|
print((" OK " if bed else " FEHL ") + text)
|
|
if not bed:
|
|
FEHLER.append(text)
|
|
|
|
|
|
print("== Rechenregeln (Zwilling zu vz_geom.js) ==")
|
|
pruefe(zw.richtung_grad((0, 0), (0, 10)) == 0.0, "Nord = 0")
|
|
pruefe(zw.richtung_grad((0, 0), (10, 0)) == 90.0, "Ost = 90")
|
|
pruefe(zw.richtung_grad((0, 0), (0, -10)) == 180.0, "Sued = 180")
|
|
pruefe(zw.richtung_grad((0, 0), (-10, 0)) == 270.0, "West = 270")
|
|
pruefe(zw.richtung_grad((0, 0), (10, 10)) == 45.0, "Nordost = 45")
|
|
pruefe(zw.richtung_grad((5, 5), (5, 5)) == 0.0, "gleicher Punkt (Doppelklick) = 0")
|
|
pruefe(zw.norm_grad(-90) == 270 and zw.norm_grad(450) == 90, "Normierung negativ/ueber 360")
|
|
pruefe(zw.norm_grad("quatsch") == 0 and zw.norm_grad(None) == 0, "Unsinn wird 0")
|
|
pruefe(zw.zusatz_ergaenzen([], "1020-30") == (["1020-30"], True), "erstes Zusatzzeichen")
|
|
pruefe(zw.zusatz_ergaenzen(["1020-30"], "1020-30") == (["1020-30"], False), "kein Doppel")
|
|
pruefe(zw.zusatz_ergaenzen(["a", "b"], "c") == (["a", "b"], False), "hoechstens zwei")
|
|
pruefe(zw.zusatz_ergaenzen(None, " ") == ([], False), "leerer Code aendert nichts")
|
|
|
|
print("== zusatz aus Text (QGIS fuehrt das Array als Textfeld) ==")
|
|
pruefe(zk._liste('["1020-30","1040-30"]') == ["1020-30", "1040-30"], "JSON-Text")
|
|
pruefe(zk._liste("1020-30, 1040-30") == ["1020-30", "1040-30"], "kommagetrennt")
|
|
pruefe(zk._liste(["1020-30"]) == ["1020-30"], "echte Liste")
|
|
pruefe(zk._liste(None) == [] and zk._liste("NULL") == [], "leer bleibt leer")
|
|
|
|
print("== Katalog und Grafiken ==")
|
|
client = KartenApiClient()
|
|
kat = zk.katalog(client, frisch=True)
|
|
if not kat.get("zeichen"):
|
|
print(" ÜBERSPRUNGEN — weder Server noch lokale Ablage erreichbar")
|
|
else:
|
|
pruefe(len(kat["zeichen"]) > 800, "Katalog: %d Zeichen, Stand %s"
|
|
% (len(kat["zeichen"]), kat.get("stand")))
|
|
pruefe(len(kat.get("kategorien", [])) >= 10, "Kategorien: %d" % len(kat.get("kategorien", [])))
|
|
ein = zk.eintrag(kat, "250")
|
|
pruefe(ein and ein["name"] and len(ein["groessen_mm"]) == 3, "Eintrag 250 vollstaendig")
|
|
geholt, fehlend = zk.sichere_svgs(client, ["250", "260", "1020-30", "9999"])
|
|
pruefe("9999" in fehlend, "unbekannter Code wird als fehlend gemeldet")
|
|
pruefe(os.path.isfile(os.path.join(zk.svg_ordner(), "250.svg")), "250.svg liegt lokal")
|
|
wurzel = zk.pfad_registrieren()
|
|
pruefe(os.path.isdir(os.path.join(wurzel, zk.ORDNER)), "SVG-Suchpfad eingetragen: " + wurzel)
|
|
|
|
print("== Stil auf die lokale Ablage umschreiben ==")
|
|
qml = "<x>'https://api.flurneuordnung-sachsen.de/v2/zeichen/svg/' || \"vz\" || '.svg'</x>"
|
|
neu, ersetzt = zk.stil_lokalisieren(qml, "https://api.flurneuordnung-sachsen.de")
|
|
pruefe(ersetzt and "vln/" in neu and "http" not in neu, "Adresse wird lokaler Name: " + neu)
|
|
unberuehrt, ersetzt2 = zk.stil_lokalisieren("<x>ohne Adresse</x>", "https://api…")
|
|
pruefe(not ersetzt2 and unberuehrt == "<x>ohne Adresse</x>", "fremder Stil bleibt, wie er ist")
|
|
|
|
print("== Palette ==")
|
|
palette = zw.ZeichenPalette()
|
|
palette.setze_katalog(kat, None)
|
|
pruefe(palette.kategorie.count() >= 12, "Kategorien in der Auswahl: %d" % palette.kategorie.count())
|
|
haeufig = palette.treffer()
|
|
pruefe(0 < len(haeufig) <= zw.PALETTE_MAX, "haeufig verwendet: %d Kacheln" % len(haeufig))
|
|
palette.suche.setText("1020-30")
|
|
pruefe([z["code"] for z in palette.treffer()] == ["1020-30"], "Suche nach der Nummer trifft genau")
|
|
palette.suche.setText("vorfahrt")
|
|
treffer = palette.treffer()
|
|
pruefe(treffer and all("vorfahrt" in (z.get("suche") or "") for z in treffer),
|
|
"Suche nach dem Namen: %d Treffer" % len(treffer))
|
|
palette.suche.clear()
|
|
palette.kategorie.setCurrentIndex(1)
|
|
pruefe(len(palette.treffer()) == zw.PALETTE_MAX, "Deckel bei %d Kacheln" % zw.PALETTE_MAX)
|
|
pruefe(palette.aktueller_eintrag() == {}, "ohne Klick kein gewaehltes Zeichen")
|
|
|
|
app.exitQgis()
|
|
print("== Ergebnis: %d Fehler ==" % len(FEHLER))
|
|
for f in FEHLER:
|
|
print(" -", f)
|
|
sys.exit(1 if FEHLER else 0)
|