Basemap-Legende (Basis #88): Umsetzung dokumentiert, ADR 0010, Wissensbasis
- Konzept 10_basemap_legende.md: Abschnitt 10 mit Umsetzung, Abweichungen und offenen Punkten - ADR 0010: Basemap-Legende als eigenes Legendenelement mit Hilfslayern und Legendenkatalog - schnittstellen.md: neue Projektvariablen, Abschnitt 11 Basemap-Legende - modulkarte.md: neue Module, aktualisierte Zeilenzahlen - fallstricke.md: Legendengröße vor dem ersten Zeichnen, Kartenfilter, Vektorkachel-Zoom, QT_VERSION unter QGIS 3, Mock-Lücken, Offscreen-Spike in QGIS - STATUS.md: Punkt 15; Testkatalog neu erzeugt Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -17,17 +17,18 @@ Legende: ⚠ = über 600 Zeilen, nie komplett laden, per `grep -n "def "` navigi
|
||||
| `ui/dockmanager.py` | 86 | `DockManager.show(dock)`: entfernt alle anderen `sn_dock_*`-Docks, zeigt das neue rechts an |
|
||||
| `ui/base_dockwidget.py` | 126 | `BaseDockWidget`: Titel „LNO Sachsen \| <Untertitel>“, Tabs aus Klassenattribut `tabs`, ruft `cleanup()` der Tabs beim Schließen, setzt Toolbar-Action zurück |
|
||||
| `ui/tabs/settings_tab.py` | 158 | Tab „Projekteigenschaften“: Benutzer- und Projektfelder → Projektvariablen (`SettingsLogic`) |
|
||||
| `ui/tabs/print_tab.py` ⚠ | 709 | Tab „Druck“: Druckbereich, Maßstab, Format, Themen, Legende, Atlas; nutzt `print_logic` |
|
||||
| `ui/tabs/print_tab.py` ⚠ | 730 | Tab „Druck“: Druckbereich, Maßstab, Format, Themen, Legende, Atlas, Basemap-Bereich; nutzt `print_logic` |
|
||||
| `ui/widgets/basemap_bereich.py` | 271 | Einklappbarer Bereich „Basemap“ im Druck-Tab: Auswertebereich, Legende aktualisieren, Stilvorlagen |
|
||||
|
||||
### functions/ – Wrapper-Schicht (Qt/QGIS/OS mit Mock-Fallback)
|
||||
|
||||
| Datei | Zeilen | Zweck |
|
||||
|---|---:|---|
|
||||
| `functions/__init__.py` | 50 | Re-Export vieler Wrapper (`from sn_basis.functions import QgsProject, info, ...`) |
|
||||
| `functions/qt_wrapper.py` ⚠ | 796 | Qt-Symbole: PyQt6 primär, PyQt5-Fallback, sonst Mock. `QT_VERSION` (0/5/6), Enum-Aliase (`DockAreaRight`, …), `exec_dialog()` |
|
||||
| `functions/qgiscore_wrapper.py` ⚠ | 1 122 | `qgis.core`-Symbole und Konstanten; ab Zeile ~255 Mock-Klassen; Helfer `network_head`, `get_layer_extent`, `create_buffer_layer`, `layer_exists_in_gpkg`, `polygon_zu_linie` |
|
||||
| `functions/qt_wrapper.py` ⚠ | 832 | Qt-Symbole: PyQt6 primär, PyQt5-Fallback, sonst Mock. `QT_VERSION` (0/5/6), Enum-Aliase (`DockAreaRight`, …), `exec_dialog()` |
|
||||
| `functions/qgiscore_wrapper.py` ⚠ | 1 382 | `qgis.core`-Symbole und Konstanten; ab Zeile ~255 Mock-Klassen; eigener Block für Vektorkacheln/Ausdrücke/Legende (#88); Helfer `network_head`, `get_layer_extent`, `create_buffer_layer`, `layer_exists_in_gpkg`, `polygon_zu_linie` |
|
||||
| `functions/qgisui_wrapper.py` | 258 | `iface`-Zugriffe: Hauptfenster, Docks, Menüs, Toolbars, Layoutdesigner; Mock-`iface` |
|
||||
| `functions/dialog_wrapper.py` | 393 | Dialoge: `ask_yes_no`, `show_info_dialog`, `ask_text`, Überschreiben/Anhängen/Abbrechen, `ProgressDialog`/`create_progress_dialog` |
|
||||
| `functions/dialog_wrapper.py` | 521 | Dialoge: `ask_yes_no`, `show_info_dialog`, `ask_text`, Überschreiben/Anhängen/Abbrechen, `ProgressDialog`/`create_progress_dialog`, `ask_mehrfachauswahl` (Liste mit Häkchen) |
|
||||
| `functions/message_wrapper.py` | 85 | MessageBar: `info`, `warning`, `error`, `success`, `push_message` |
|
||||
| `functions/variable_wrapper.py` | 120 | `get_variable(key, scope)`, `set_variable(...)` mit Präfix `sn_`; Mock-Speicher |
|
||||
| `functions/settings_logic.py` | 50 | `SettingsLogic.VARIABLEN`: Liste der gespeicherten Projektvariablen, `load()/save()` |
|
||||
@@ -55,9 +56,14 @@ Legende: ⚠ = über 600 Zeilen, nie komplett laden, per `grep -n "def "` navigi
|
||||
| `modules/Datenabruf.py` ⚠ | 636 | `Datenabruf.datenabruf(...)`: WFS, ArcGIS REST, OGR laden; Raumfilter Verfahrensgebiet/Puffer/ohne |
|
||||
| `modules/LayerLoader.py` | 422 | `create_layer(provider, link, thema)`, `apply_style`, `filter_by_extent`, `filter_by_layer`, `add_to_project` |
|
||||
| `modules/Datenschreiber.py` | 448 | `schreibe_Daten(...)` in GeoPackage, `lade_Layer(...)` ins Projekt, `schreibe_log(...)` HTML-Protokoll |
|
||||
| `modules/print_logic.py` ⚠ | 1 321 | `PrintLogic`, `AtlasConfig`, `RectangleCaptureTool`: Druckbereich, Maßstab, Atlas, Layoutaufruf |
|
||||
| `modules/print_layout.py` ⚠ | 1 078 | `PrintLayout`: Layoutaufbau für § 38 / § 41 (Karte, Legende, Gitter, Schriftfeld) |
|
||||
| `modules/print_logic.py` ⚠ | 1 360 | `PrintLogic`, `AtlasConfig`, `RectangleCaptureTool`: Druckbereich, Maßstab, Atlas, Layoutaufruf |
|
||||
| `modules/print_layout.py` ⚠ | 1 111 | `PrintLayout`: Layoutaufbau für § 38 / § 41 (Karte, Legende, Gitter, Schriftfeld) |
|
||||
| `modules/print_layout_baufreigabe.py` | 403 | Layout „Anlage zur Baufreigabe“ (feste DIN A3/A4 quer) |
|
||||
| `modules/basemap_legende.py` | 471 | Basemap-Legende (#88): Legendenkatalog laden, Styles → Einträge, Auswahl merken, Basemap-Layer erkennen, Auswertebereich; `BasemapLegende.aktualisiere(layout)` als Einstieg |
|
||||
| `modules/basemap_kacheln.py` | 192 | Kacheln des Basemap-Layers kachelweise über `selectByGeometry` auswerten, Renderer-Styles lesen, Zoomstufen wie der QGIS-Renderer |
|
||||
| `modules/basemap_legende_layout.py` | 396 | Legendensymbole aus Projektlayer-Styles zusammensetzen, leere Hilfslayer, Legendenelement „Legende Basemap“ schreiben und platzieren |
|
||||
| `modules/basemap_katalog.py` | 418 | Erzeugt/aktualisiert `data/basemap_legende.json` aus der basemap.de-Style-JSON (nur Standardbibliothek, eigenständig aufrufbar) |
|
||||
| `modules/basemap_stilvorlagen.py` | 181 | Lokale Stilvorlagen des Basemap-Layers (QML + JSON im QGIS-Profil), Standard in `QSettings` |
|
||||
|
||||
### Sonstiges
|
||||
|
||||
@@ -66,6 +72,7 @@ Legende: ⚠ = über 600 Zeilen, nie komplett laden, per `grep -n "def "` navigi
|
||||
| `tests/` | 13 Testdateien, `unittest`, Mock-Modus; `run_tests.py` (farbiger Runner), `test_qgis.bat` (Coverage in OSGeo4W) |
|
||||
| `styles/` | QML-Stile (Verfahrensgebiet, LSG, Denkmalschutz, Flurstücksbeschriftung) |
|
||||
| `data/landkreise.json` | Landkreise mit Kennzahl |
|
||||
| `data/basemap_legende.json` | Legendenkatalog basemap.de: Style-ID → Legendeneintrag (190 Einträge), erzeugt mit `basemap_katalog.py`, fachlich nachbearbeitet |
|
||||
| `assets/plan-qgis340ExitCrashFix.prompt.md` | KI-Planungsnotiz zum Exit-Crash (historisch) |
|
||||
| `.gitea/workflows/release.yaml`, `.gitea/templates/metadata.template` | Release-Auslöser, Vorlage für `metadata.txt` |
|
||||
|
||||
@@ -129,12 +136,12 @@ Dient als **minimales Muster** für ein neues Fachplugin (Skill `sn-neues-fachpl
|
||||
| Datei | Zeilen |
|
||||
|---|---:|
|
||||
| `sn_verfahrensgebiet/functions/grenzpunkt_alkis.py` | 1 674 |
|
||||
| `sn_basis/modules/print_logic.py` | 1 321 |
|
||||
| `sn_basis/modules/print_logic.py` | 1 360 |
|
||||
| `sn_plan41/ui/tab_a_logic.py` | 1 239 |
|
||||
| `sn_basis/functions/qgiscore_wrapper.py` | 1 122 |
|
||||
| `sn_basis/modules/print_layout.py` | 1 078 |
|
||||
| `sn_basis/functions/qgiscore_wrapper.py` | 1 382 |
|
||||
| `sn_basis/modules/print_layout.py` | 1 111 |
|
||||
| `sn_verfahrensgebiet/functions/verfahrensgebiet_shape_komplett.py` | 978 |
|
||||
| `sn_verfahrensgebiet/ui/tabs/working_tab.py` | 873 |
|
||||
| `sn_verfahrensgebiet/functions/knickpunkt_pruefung.py` | 810 |
|
||||
| `sn_basis/functions/qt_wrapper.py` | 796 |
|
||||
| `sn_basis/ui/tabs/print_tab.py` | 709 |
|
||||
| `sn_basis/functions/qt_wrapper.py` | 832 |
|
||||
| `sn_basis/ui/tabs/print_tab.py` | 730 |
|
||||
|
||||
@@ -55,6 +55,9 @@ Der Wrapper setzt das Präfix `sn_` selbst; Schlüssel **ohne** Präfix übergeb
|
||||
| `linkliste`, `tab_a_linkliste` | Plan41 Tab A | Plan41 | Pfad der Linkliste (XLSX) |
|
||||
| `tab_a_layer_id`, `Raumfilter` | Plan41 Tab A | Plan41 | Raumfilter-Einstellung |
|
||||
| `druckrechteck_xmin/xmax/ymin/ymax` | PrintTab/PrintLogic | Druck | gespeicherter Druckbereich |
|
||||
| `basemap_auswertebereich` | Basemap-Bereich im Druck-Tab | `basemap_legende` | `verfahrensgebiet` (Standard) oder `druckbereich` (Basis #88) |
|
||||
| `basemap_legende_erzeugen` | Basemap-Bereich | `print_logic` | `1`/`0`, Standard `1`: Basemap-Legende beim Erstellen einer §-38/§-41-Vorlage |
|
||||
| `basemap_legende_auswahl` | `basemap_legende`, Stilvorlage laden | Auswahldialog | JSON `{"ausgeblendet": [...], "eingeblendet": [...]}` mit Eintragsschlüsseln des Legendenkatalogs |
|
||||
| `sn_abdeckungslayer` ⚠ | PrintTab/PrintLogic | Druck (Atlas) | Atlas-Abdeckungslayer. **Schlüssel enthält bereits `sn_` → tatsächliche Variable `sn_sn_abdeckungslayer`**; funktioniert, ist aber inkonsistent |
|
||||
| `verfahrensgebietslayer` ⚠ | `print_logic.py` | `print_logic.py` | **Zweite Schreibweise neben `verfahrensgebiet_layer`** – vermutlich Altlast, beim Refactoring zusammenführen |
|
||||
|
||||
@@ -126,3 +129,25 @@ flowchart LR
|
||||
## 10. Linkliste-Repository
|
||||
|
||||
`linkliste.csv` (Semikolon, Spalten `id;gruppe;ebene;inhalt;url;provider;stil`) → Gitea Action → `linkliste.xml/json/yaml` auf `main`. Die Plan41-Laufzeit nutzt stattdessen die mitgelieferte `assets/Linkliste.xlsx` mit abweichenden Spaltennamen.
|
||||
|
||||
## 11. Basemap-Legende im Druck (Basis #88)
|
||||
|
||||
- **Welche Layouts:** `print_logic.LAYOUTS_MIT_BASEMAP_LEGENDE` (heute §38, §41). Ein Layout nutzt die Funktion,
|
||||
wenn es die Layout-Eigenschaft `sn_basemap_legende = 1` trägt (`basemap_legende_layout.markiere_layout`);
|
||||
`PrintLayout.create_single_page_layout(..., basemap_legende=True)` setzt sie und erzeugt die Legende vor dem
|
||||
Öffnen des Designers. Neue Layouts: in die Konstante aufnehmen bzw. das Kennzeichen setzen.
|
||||
- **Layout-Elemente nach ID:** `Hauptkarte` (Bezugskarte), `Legende` (Hauptlegende, Spalte und Oberkante),
|
||||
`Quellenangabe` (Unterkante der Basemap-Legende), `Legende Basemap` (das Basemap-Element selbst).
|
||||
Umbenennen dieser IDs bricht die Platzierung.
|
||||
- **Weitere Layout-Eigenschaften:** `sn_basemap_bereich`, `sn_basemap_massstab`, `sn_basemap_eintraege` (JSON),
|
||||
`sn_basemap_hilfslayer` (IDs der Hilfslayer, werden beim Aktualisieren ersetzt).
|
||||
- **Hilfslayer:** leere Speicherlayer, nicht im Layerbaum, Eigenschaften `sn_basemap_legende = <Layoutname>` und
|
||||
`skipMemoryLayersCheck = 1`. Code, der über `QgsProject.mapLayers()` iteriert, sieht sie.
|
||||
- **Basemap-Layer-Erkennung:** Vektorkachel-Layer, Quelle enthält `gdz_basemapde_vektor`; Name „basemap.de“ nur
|
||||
als Rückfall.
|
||||
- **Legendenkatalog:** `sn_basis/data/basemap_legende.json` (Style-ID → Eintrag), erzeugt/aktualisiert mit
|
||||
`python modules/basemap_katalog.py`; gehört zur Style-Version `bm_web_col` v2.
|
||||
- **Stilvorlagen:** lokal unter `<QGIS-Profil>/sn_basis/basemap_stile/`, Standard in `QSettings`
|
||||
`sn_basis/basemap_standardstil`.
|
||||
- **Neue öffentliche Funktion:** `dialog_wrapper.ask_mehrfachauswahl(titel, hinweis, eintraege, vorauswahl)` –
|
||||
Liste mit Häkchen, Gruppen, Suche; liefert gewählte Schlüssel oder `None` bei Abbruch.
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
# 0010 – Basemap-Legende als eigenes Legendenelement mit Hilfslayern und Legendenkatalog
|
||||
|
||||
Status: vorgeschlagen · Datum: 2026-10-02 · Beteiligte: Daniel Helbig, Claude Code · Ticket Plugin_SN_Basis #88
|
||||
|
||||
## Kontext
|
||||
QGIS erzeugt für Vektorkachel-Layer keine Legende (`QgsVectorTileLayer` setzt keine `QgsMapLayerLegend`,
|
||||
geprüft im Quellcode 3.40, 3.44, master). Die §-38-/§-41-Drucklayouts brauchen aber eine Legende der
|
||||
basemap.de-Objekte, die im Verfahrensgebiet tatsächlich dargestellt werden, mit der Signatur des Projektlayers.
|
||||
Die Style-JSON von basemap.de hat 569 Style-Layer mit technischen IDs; ein Legendeneintrag wie „Kreisstraße“
|
||||
verteilt sich auf bis zu 20 Styles (Kontur, Decker, Brücke, getrennte Fahrbahn …).
|
||||
|
||||
Ein Spike in QGIS 3.44.4 (offscreen, echte Kacheln, Gebiet bei Meißen, 619 ha) am 02.10.2026 ergab:
|
||||
- `QgsVectorTileLayer.selectByGeometry()` holt und dekodiert die Kacheln zur Zoomstufe des Maßstabs selbst
|
||||
(5,8 s für 10 250 Objekte, entdoppelt 3 990; Style-Zuordnung 0,5 s).
|
||||
- Hilfslayer in der **Hauptlegende** verschwinden beim Rendern, weil diese nach Karteninhalt filtert
|
||||
(`setLegendFilterByMapEnabled(True)`) und die Hilfslayer nicht in der Karte liegen. Außerdem müsste die
|
||||
Hauptlegende dafür ihre automatische Aktualisierung verlieren.
|
||||
- Ein **eigenes Legendenelement** ohne Kartenfilter zeigt alle Einträge, übersteht Speichern und Neuladen des
|
||||
Projekts; leere Speicherlayer lösen beim Schließen keine Rückfrage aus.
|
||||
|
||||
## Entscheidung
|
||||
Die Basemap-Legende ist ein **eigenes Legendenelement „Legende Basemap“** ohne Kartenfilter und ohne
|
||||
automatische Aktualisierung, dessen Einträge aus **leeren, kategorisierten Speicherlayern** stammen (je Gruppe
|
||||
und Geometrietyp, nicht im Layerbaum, mit dem Projekt gespeichert). Welche Styles zu welchem Eintrag gehören
|
||||
und welche das Symbol bilden, steht in einem **versionierten Legendenkatalog** `sn_basis/data/basemap_legende.json`,
|
||||
der aus der Style-JSON erzeugt und fachlich nachbearbeitet wird. Signaturen werden zur Laufzeit aus dem
|
||||
Projektlayer genommen, nicht aus dem Katalog.
|
||||
|
||||
## Folgen
|
||||
- Hauptlegende bleibt unverändert (Auto-Update, Kartenfilter); der Basemap-Layer selbst erscheint dort nicht,
|
||||
weil er keine Legendenknoten hat und der Filter ihn ausblendet.
|
||||
- Lokale Änderungen am Basemap-Stil (Farben, abgeschaltete Styles) wirken automatisch auch in der Legende.
|
||||
- Die Basemap-Legende ist eine Momentaufnahme; nach Änderungen an Karte oder Stil „Basemap-Legende aktualisieren“.
|
||||
- Bei einer neuen Basemap-Stilversion muss der Katalog mit `modules/basemap_katalog.py` erneuert werden;
|
||||
unbekannte Styles erscheinen bis dahin unter „Sonstiges“ (abgewählt).
|
||||
- Je Layout liegen einige leere Speicherlayer im Projekt (nicht im Layerbaum sichtbar).
|
||||
|
||||
## Verworfene Alternativen
|
||||
- **Hilfslayer in der Hauptlegende:** vom Kartenfilter ausgeblendet (Spike), und Verlust der Auto-Aktualisierung.
|
||||
- **Eigene `QgsMapLayerLegend` (Python-Unterklasse) am Vektorkachel-Layer:** wird nicht im Projekt gespeichert,
|
||||
nach Neuladen wäre die Legende weg.
|
||||
- **Legende direkt aus dem Signaturenkatalog:** zeigt die Standarddarstellung, nicht die im Projekt angepasste.
|
||||
@@ -34,3 +34,4 @@ Kurz, mit Grund.
|
||||
| 0007 | Branchmodell: drei Kanäle, `stable` als stabiler Kanal, Rückführungspflicht | vorgeschlagen |
|
||||
| 0008 | Werkzeugunterstützung auf Claude Code fokussiert | vorgeschlagen |
|
||||
| 0009 | Tests sind Teil der Definition of Done, und sie werden für Menschen dokumentiert | vorgeschlagen |
|
||||
| 0010 | Basemap-Legende als eigenes Legendenelement mit Hilfslayern und Legendenkatalog | vorgeschlagen |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Basemap-Legende und Basemap-Stilvorlagen im Druck
|
||||
|
||||
Stand 02.10.2026. Konzept zur Freigabe, Ticket **Plugin_SN_Basis #88** („Legende für basemap").
|
||||
Stand 02.10.2026. Konzept freigegeben und umgesetzt (Branch `feature/88-basemap-legende`, Abschnitt 10), Ticket **Plugin_SN_Basis #88** („Legende für basemap").
|
||||
Betroffen ist ausschließlich **`sn_basis`** (Druck); `sn_plan41` und `sn_verfahrensgebiet` nutzen den
|
||||
Druck-Tab aus `sn_basis` und bekommen die Funktion ohne eigene Änderung.
|
||||
|
||||
@@ -160,7 +160,7 @@ einem erneuten Lauf erhalten; neue oder entfallene Style-IDs werden gemeldet.
|
||||
|---|---|---|
|
||||
| Projektvariable | `basemap_auswertebereich` | `verfahrensgebiet` (Standard) oder `druckbereich` |
|
||||
| Projektvariable | `basemap_legende_erzeugen` | `1`/`0`, Standard `1` |
|
||||
| Projektvariable | `basemap_legende_ausgeblendet` | JSON-Liste der zuletzt abgewählten Eintragsschlüssel (Vorbelegung) |
|
||||
| Projektvariable | `basemap_legende_auswahl` | JSON `{"ausgeblendet": [...], "eingeblendet": [...]}` – zuletzt ab-/angewählte Einträge (Vorbelegung) |
|
||||
| Layout-Eigenschaft | `sn_basemap_legende`, `sn_basemap_bereich`, `sn_basemap_massstab`, `sn_basemap_eintraege` | Kennzeichen und letzte Einstellungen je Layout |
|
||||
| QSettings | `sn_basis/basemap_standardstil` | Name der Standard-Stilvorlage |
|
||||
| Öffentliche Funktion | `dialog_wrapper.ask_mehrfachauswahl(...)` | neuer allgemeiner Dialog |
|
||||
@@ -233,3 +233,31 @@ Ein Feature-Branch `feature/88-basemap-legende` in `Plugin_SN_Basis` von `unstab
|
||||
„kommt vor" unerheblich.
|
||||
- **Umfang:** Stilvorlagen sind fachlich eigenständig. Werden sie zu groß für einen PR, als eigenes Ticket
|
||||
abtrennen (Schritte 1–6 bleiben #88).
|
||||
|
||||
## 10. Umsetzung und Abweichungen (02.10.2026)
|
||||
|
||||
Umgesetzt in `Plugin_SN_Basis`, Branch `feature/88-basemap-legende` (drei Commits). Spike-Ergebnisse und
|
||||
Begründung der Legendenvariante: ADR 0010.
|
||||
|
||||
| Thema | Umsetzung | Abweichung vom Konzept |
|
||||
|---|---|---|
|
||||
| Legendendarstellung | Variante (b): eigenes Element „Legende Basemap“, Titel „Kartengrundlage (basemap.de)“ | Spike entschieden |
|
||||
| Platzierung | unten an der Quellenangabe verankert, wächst nach oben, 1–3 Spalten (nie über den Seitenrand), sonst Hinweis | statt „unter der Hauptlegende“: deren Höhe steht erst nach dem Rendern fest |
|
||||
| Mehrere Basemap-Layer | ausgewertet wird der erste sichtbare, Hinweis an den Nutzer | statt „je Layer eine Gruppe“ (vereinfacht) |
|
||||
| Katalog-Generator | `sn_basis/modules/basemap_katalog.py` (nur Standardbibliothek, eigenständig aufrufbar) | statt Skript im Projektwissen – so mit der sn_basis-Suite getestet |
|
||||
| Auswahl im Projekt | `basemap_legende_auswahl` (ab- und angewählte Einträge) | statt nur `…_ausgeblendet`, damit angewählte „Sonstiges“-Einträge gemerkt werden |
|
||||
| Module | `basemap_katalog`, `basemap_kacheln`, `basemap_legende`, `basemap_legende_layout`, `basemap_stilvorlagen`, `ui/widgets/basemap_bereich` | Kachelauswertung ausgelagert (Dateigröße) |
|
||||
| Einklappen | `QToolButton`-Muster wie Atlas-Bereich | `QgsCollapsibleGroupBox` nicht nötig |
|
||||
| Stilvorlagen | QML (rund 3,7 MB je Vorlage) + JSON mit Legendenauswahl, im QGIS-Profil | wie geplant |
|
||||
|
||||
**Katalog:** 434 darstellende Styles in 190 Einträgen; Beschriftungen (`Name_*`, Labeling), Nummernschilder
|
||||
(`Nummer_*`), Hintergrund, Mittellinien und kleinmaßstäbige Ortspunkte ausgeschlossen. Erster fachlicher
|
||||
Durchgang der Bezeichnungen ist gemacht; **die fachliche Abnahme steht aus.**
|
||||
|
||||
**Bekannte Punkte für die Durchsicht:**
|
||||
- „Platz“ (Verkehr, Siedlung) hat im Basemap-Stil eine weiße Füllung ohne Rand und ist in der Legende kaum zu sehen.
|
||||
- „Durchlass, Düker“ und „Baumreihe“ zeigen in der Legende kein sichtbares Symbol (Ursache noch nicht geklärt).
|
||||
- Gewässerbreiten sind zu „Fließgewässer (Linie)“ zusammengefasst; Symbol ist die 6-m-Linie.
|
||||
|
||||
**Nicht geprüft:** QGIS 4 (Qt6) – lokal nicht verfügbar. QGIS 3.44.4 (Qt5) offscreen geprüft: Auswertung,
|
||||
Dialog (echte Widgets), Legende im §-41-Layout, Stilvorlage speichern/laden am echten Layer, Basemap-Bereich.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Status des Projekts
|
||||
|
||||
Kurz und aktuell. Wird bei jedem Merge und jeder Übergabe gepflegt (Skill `sn-uebergabe`). Älteres wandert nach unten
|
||||
in „Erledigt" oder wird gelöscht. **Stand: 04.09.2026.**
|
||||
in „Erledigt" oder wird gelöscht. **Stand: 02.10.2026.**
|
||||
|
||||
## Aktuelle Phase
|
||||
|
||||
@@ -13,7 +13,7 @@ spätere Phase und beginnt erst, wenn die Test-Baseline grün ist und das Projek
|
||||
|
||||
| Person / Behörde | Schwerpunkt | Stand |
|
||||
|---|---|---|
|
||||
| Daniel Helbig (LK Meißen) | Fachfunktionen Verfahrensgebiet, Plan41, VLN-API | aktiv |
|
||||
| Daniel Helbig (LK Meißen) | Fachfunktionen Verfahrensgebiet, Plan41, VLN-API; Basemap-Legende im Druck (Basis #88, PR vorbereitet) | aktiv |
|
||||
| Michael Otto (LK Mittelsachsen) | Release-Infrastruktur, Linkliste, zuletzt Verfahrensgebiet (Shape-Laden, Beteiligung) | aktiv |
|
||||
| 22munzke | Druck/Layout-Anforderungen (Issues Basis #37–#44) | Issues |
|
||||
| weitere Behörden | Einstieg über dieses Repository | ab 09/2026 |
|
||||
@@ -63,6 +63,10 @@ spätere Phase und beginnt erst, wenn die Test-Baseline grün ist und das Projek
|
||||
(fest verdrahteter NAS-Namespace `gid/6.0` in `grenzpunkt_alkis.py`, abgeflachte WFS-Feldnamen in
|
||||
`sql=`-Filtern). Vergleich 6↔7 und Anpassungsliste: `docs/konzept/09_alkis7_umstellung.md`.
|
||||
Nächster Schritt: Gitea-Issue in `Plugin_SN_Verfahrensgebiet`.
|
||||
15. **Basemap-Legende im Druck (Basis #88).** Umgesetzt auf `Plugin_SN_Basis:feature/88-basemap-legende`
|
||||
(Konzept `docs/konzept/10_basemap_legende.md`, ADR 0010), PR steht aus. Offen: **fachliche Abnahme des
|
||||
Legendenkatalogs** `sn_basis/data/basemap_legende.json` (Bezeichnungen, Gruppen, Zusammenfassungen; drei
|
||||
Einträge ohne gut sichtbares Symbol, siehe Konzept Abschnitt 10) und Test unter QGIS 4.
|
||||
|
||||
**Hinweis zum lokalen Stand (04.09.2026):** Die Klone `Plugin_SN_Verfahrensgebiet` (4 Commits: PR #43, PR #45)
|
||||
und `Repository` (Release 26.8.4-unstable) liegen hinter `origin`. Aktualisieren mit `python scripts/hallo.py`.
|
||||
|
||||
+990
-50
File diff suppressed because one or more lines are too long
+741
-236
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,13 @@ Kurz, konkret, mit Datum und Quelle. Neue Einträge oben in der passenden Rubrik
|
||||
|
||||
## Umgebung und Werkzeuge
|
||||
|
||||
- **`qt_wrapper` meldet unter QGIS 3.44 `QT_VERSION == 6`, obwohl Qt5 läuft.** Der „PyQt6“-Zweig importiert
|
||||
`qgis.PyQt`, das unter QGIS 3 PyQt5 ist; die Qt6-Schreibweise der Enums (`Qt.ItemFlag.ItemIsUserCheckable`)
|
||||
funktioniert mit PyQt 5.15 trotzdem. `QT_VERSION` also nicht als Qt-Hauptversion verstehen, nur als
|
||||
„echtes Qt (≠ 0)“. (02.10.2026, QGIS 3.44.4 geprüft, Basis #88)
|
||||
- **Lücken im Mock-Modus:** `QgsGeometry` hat im Mock kein `fromRect`, `QgsLayoutPoint`/`QgsLayoutSize` haben
|
||||
`x`/`width` als Attribute statt als Methoden; `QgsRectangle` hatte bis Basis #88 gar keinen Mock. Tests patchen
|
||||
solche Stellen gezielt, statt die Produktionsfunktion umzubauen. (02.10.2026)
|
||||
- **QGIS 3.40 ist seit Januar 2026 End of Life.** Aktueller LTR ist 3.44, Stable 4.2 (wird 25.09.2026 LTR). `workspace.toml` und alle `metadata.template` stehen noch auf `3.40` – offene Produktentscheidung, siehe `docs/konzept/07_qgis_tests_plan.md` Abschnitt 2. (04.09.2026, QGIS-Release-Fahrplan)
|
||||
- **Zwei Qt-Welten.** QGIS 3.40/3.44 laufen mit Qt5/PyQt5, QGIS 4 mit Qt6/PyQt6. `qt_wrapper` lädt PyQt6 zuerst, dann PyQt5, sonst Mock. Enum-Zugriffe unterscheiden sich (`Qt.AlignmentFlag.AlignTop` statt `Qt.AlignTop`), deshalb nur Wrapper-Aliase verwenden. (09/2026, Code)
|
||||
- **Mock-Modus ist kein QGIS.** `python scripts/run_tests.py` läuft in Sekunden, prüft aber nur Logik gegen Mock-Klassen. Geometrieoperationen, WFS, Layouts und Signale müssen in QGIS geprüft werden (`tests/test_qgis.bat` unter Windows). Manuelle QGIS-Tests im PR dokumentieren. (09/2026)
|
||||
@@ -19,6 +26,12 @@ Kurz, konkret, mit Datum und Quelle. Neue Einträge oben in der passenden Rubrik
|
||||
|
||||
## QGIS-Tests (geplant, siehe `docs/konzept/07_qgis_tests_plan.md`)
|
||||
|
||||
- **Spike/Abnahme ohne QGIS-Oberfläche:** Skript mit `QT_QPA_PLATFORM=offscreen` über `python-qgis.bat` starten,
|
||||
das Plugin-Repo per Junction (`mklink /J <tmp>\sn_basis <Plugin_SN_Basis>`) unter dem Paketnamen in `sys.path`
|
||||
legen. Für Widgets und Dialoge `QgsApplication([], True)` (mit GUI) – ohne GUI stürzt z. B.
|
||||
`QgsSymbolLayerUtils.symbolPreviewIcon` ab. Modale Dialoge: `exec_dialog` patchen und im Ersatz die Widgets
|
||||
prüfen. Layout-Ergebnis mit `QgsLayoutExporter.renderRegionToImage` als PNG ansehen; ohne installierte Schriften
|
||||
erscheinen Texte als Kästchen. `exportToImage` liefert bei Erfolg `0`. (02.10.2026, Basis #88)
|
||||
- **`QT_QPA_PLATFORM=offscreen` muss gesetzt sein, bevor die `QgsApplication` erzeugt wird.** Danach wirkt es nicht mehr. (04.09.2026, Recherche)
|
||||
- **`qgis.utils.iface` ist nach `start_app()` `None`.** Entweder `pytest-qgis` verwenden (patcht automatisch) oder selbst `qgis.utils.iface = get_iface()` setzen – und keine Module zu früh importieren. (04.09.2026)
|
||||
- **`QgsProject.instance()` ist global.** Ohne Aufräumen zwischen den Tests beeinflussen sie sich gegenseitig. (04.09.2026)
|
||||
@@ -40,6 +53,15 @@ Kurz, konkret, mit Datum und Quelle. Neue Einträge oben in der passenden Rubrik
|
||||
|
||||
## Daten und Dienste
|
||||
|
||||
- **basemap.de-Vektorkacheln (Basis #88):** QGIS zeigt für Vektorkachel-Layer keine Legende. Objekte im Gebiet
|
||||
liefert `QgsVectorTileLayer.selectByGeometry()` (lädt die Kacheln selbst; `getRawTile` ist in Python gesperrt).
|
||||
Kacheln enden bei Zoom 15. Der Renderer prüft Styles mit `scaleToZoomLevel(maßstab, False)` und setzt
|
||||
`@vector_tile_zoom = scaleToZoom(maßstab)` – diese Variable fehlt in der Legende, zoomabhängige Strichmuster
|
||||
sind dort sonst unsichtbar. Beim Import der Style-JSON werden Beschriftungen zu Labeling (Hausnummern =
|
||||
Labeling-Style `Hauskoordinate`), `Nummer_*`-Schilder zu Renderer-Symbolen, `fill-extrusion` (3D) entfällt.
|
||||
Der Legendenkatalog `sn_basis/data/basemap_legende.json` gehört zur Style-Version `bm_web_col` v2; nach einer
|
||||
neuen Version `python modules/basemap_katalog.py` laufen lassen und Meldungen prüfen. Eine QML-Stilvorlage des
|
||||
Layers ist rund 3,7 MB groß. (02.10.2026)
|
||||
- **WFS-Beschränkungen der sächsischen ALKIS-Dienste:** POST/GML-Filter werden blockiert, URL-Länge ist begrenzt, serverseitige Feature-Limits. Deshalb arbeiten Flurstücks- und Grenzpunktabrufe mit BBOX, gemarkungsweisen Batches und Nutzerdialogen. Nicht „vereinfachen“, ohne das gegen den Dienst zu testen. Vollständig mit erprobten Anfragen: `docs/wissen/wfs_dienste.md`, Objektarten/Attribute: `docs/wissen/alkis_objektarten.md`. (Verfahrensgebiet, Code)
|
||||
- **Zwei Linklisten.** Zentrale `Linkliste/linkliste.csv` (Spalten `id;gruppe;ebene;inhalt;url;provider;stil`) und die vom Plugin genutzte `Plugin_SN_Plan41/assets/Linkliste.xlsx` (`ident, gruppe, kartenebene, inhalt, link, provider, stildatei`) sind nicht verbunden. Änderungen an Diensten in **beiden** nachziehen, bis die Zusammenführung entschieden ist. (09/2026)
|
||||
- **ArcGIS-REST-Layer nicht nach Nummer deuten.** Gleiche Layer-URLs werden in der Linkliste und im Alternativansatz unterschiedlich benannt; Bedeutung und Geometrie immer gegen die Dienstmetadaten prüfen. (Vergleich Alternativansatz 09/2026)
|
||||
@@ -50,6 +72,12 @@ Kurz, konkret, mit Datum und Quelle. Neue Einträge oben in der passenden Rubrik
|
||||
|
||||
## Code-Konventionen, die man kennen muss
|
||||
|
||||
- **Legendenelemente im Layout (QGIS 3.44):** `QgsLayoutItemLegend.adjustBoxSize()` wirkt erst, nachdem das
|
||||
Element einmal gezeichnet wurde – beim Anlegen per Code ändert es nichts. Platzbedarf vorher über
|
||||
`QgsLegendRenderer(legende.model(), einstellungen).minimumSize(QgsLayoutUtils.createRenderContextForLayout(layout, None))`
|
||||
berechnen; für mehrere Spalten zusätzlich `setSplitLayer(True)`, sonst bleibt ein Layer in einer Spalte.
|
||||
Eine Legende mit `setLegendFilterByMapEnabled(True)` blendet Layer aus, die nicht in der Karte liegen, und ihre
|
||||
Höhe steht erst nach dem Rendern fest. (02.10.2026, Spike Basis #88)
|
||||
- **Projektvariablen-Schlüssel ohne `sn_` übergeben.** `set_variable("sn_abdeckungslayer", ...)` erzeugt `sn_sn_abdeckungslayer` (Altlast in Druckmodulen; funktioniert nur, weil Lesen und Schreiben denselben Fehler machen).
|
||||
- **Zwei Schreibweisen für den Verfahrensgebiet-Layer:** `verfahrensgebiet_layer` (Manager, Fachplugins) und `verfahrensgebietslayer` (`print_logic.py`). Bis zur Bereinigung nicht auf Gleichheit vertrauen.
|
||||
- **Layer werden über Anzeigenamen gefunden** (`BROR_LAYER_NAME` usw.). Umbenennungen in der UI brechen Abläufe.
|
||||
|
||||
Reference in New Issue
Block a user