2026-09-04 11:57:26 +02:00
# Modulkarte
Lebende Referenz: **welche Datei tut was und wie groß ist sie** . Zweck: Agenten und Entwickler lesen gezielt statt ganze
Dateien zu laden. Zeilenzahlen Stand 02.09.2026 (`unstable` ). Bei Änderungen an Modulzuschnitt bitte mitpflegen.
Legende: ⚠ = über 600 Zeilen, nie komplett laden, per `grep -n "def "` navigieren.
## sn_basis (Repository `Plugin_SN_Basis`) – Plattform
### Einstieg und UI-Rahmen
| Datei | Zeilen | Zweck |
|---|---:|---|
| `__init__.py` | 20 | `classFactory` → `BasisPlugin` |
| `main.py` | 64 | `BasisPlugin` : baut `Navigation` , startet Verfahrensgebiet-Listener, ruft `initGui()` aller `sn_*` -Plugins nach, räumt beim Unload auf |
| `ui/navigation.py` | 127 | Menü und Toolbar „LNO Sachsen“; `add_action(text, callback, tooltip, priority)` , `finalize_menu_and_toolbar()` , `set_active_plugin()` . Enthält noch Debug-`print` und eine `TEST ACTION` |
| `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` ) |
2026-10-02 12:03:14 +02:00
| `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 |
2026-09-04 11:57:26 +02:00
### 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, ...` ) |
2026-10-02 12:03:14 +02:00
| `functions/qt_wrapper.py` ⚠ | 832 | Qt-Symbole: PyQt6 primär, PyQt5-Fallback, sonst Mock. `QT_VERSION` (0/5/6), Enum-Aliase (`DockAreaRight` , …), `exec_dialog()` |
2026-10-02 13:07:03 +02:00
| `functions/qgiscore_wrapper.py` ⚠ | 1 428 | `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` |
2026-09-04 11:57:26 +02:00
| `functions/qgisui_wrapper.py` | 258 | `iface` -Zugriffe: Hauptfenster, Docks, Menüs, Toolbars, Layoutdesigner; Mock-`iface` |
2026-10-02 12:03:14 +02:00
| `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) |
2026-09-04 11:57:26 +02:00
| `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()` |
| `functions/verfahrensgebiet_manager.py` | 217 | Zentrale Verfolgung des Verfahrensgebiet-Layers über Projektsignale; `get/set_verfahrensgebiet_layer_id` , `setup_/teardown_verfahrensgebiet_listener` |
| `functions/ly_*_wrapper.py` | 32– 98 | Layer-Helfer: Existenz, Geometrie/Featurezahl, Metadaten (Typ, CRS, Felder, Quelle), Stil (`apply_style` ), Sichtbarkeit |
| `functions/os_wrapper.py` | 102 | Pfade, Home, Groß-/Kleinschreibung des Dateisystems |
| `functions/sys_wrapper.py` | 106 | `get_plugin_root` , `join_path` , `file_exists` , `read_text` , `add_to_sys_path` , `getattr_safe` |
| `functions/landkreise.py` | 48 | Sächsische Landkreise aus `data/landkreise.json` (`LANDKREISE` , `ALLE_LANDKREISE` ) |
| `functions/laenderkennung.py` | 52 | ALKIS-Länderkennung je Aufrufer-Präfix |
2026-09-14 11:10:51 +02:00
| `functions/text_wrapper.py` | 25 | `sanitize_bezeichner(text, ersatz="_")` : Freitext → Layer-/Dateiname, Umlaute/ß/_/- bleiben erhalten |
2026-09-04 11:57:26 +02:00
### modules/ – Prüfen, Laden, Schreiben, Drucken
| Datei | Zeilen | Zweck |
|---|---:|---|
| `modules/pruef_ergebnis.py` | 196 | `pruef_ergebnis(ok, meldung, aktion, kontext)` und `PruefAktion` -Literal (Fehler-/Entscheidungscodes) |
| `modules/Pruefmanager.py` | 295 | Entscheidungsinstanz: `verarbeite(ergebnis)` fragt Nutzer oder entscheidet still (`ui_modus != "qgis"` ); `report_error` , `frage_ja_nein` , `frage_text` |
| `modules/Dateipruefer.py` | 267 | Prüft Dateipfade/GeoPackages (existiert, erzeugen, überschreiben, anhängen) |
| `modules/layerpruefer.py` | 183 | Prüft QGIS-Layer (vorhanden, Geometrietyp, CRS, Felder, editierbar) |
| `modules/linkpruefer.py` | 136 | Prüft URLs/lokale Links (Erreichbarkeit) |
| `modules/stilpruefer.py` | 82 | Prüft QML-Stildateien |
| `modules/Datenbankpruefer.py` | 40 | Prüft SQLite/GeoPackage-Datenbanken |
| `modules/DataGrabber.py` | 363 | Klassifiziert Quelle (Excel, GeoPackage, Dienst) und liefert normalisierte Zeilen; Excel-Pfad nutzt **Lazy-Import** `sn_plan41.modules.listenauswerter` |
| `modules/excel_importer.py` | 92 | Excel lesen (`openpyxl` , harte Abhängigkeit) |
| `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 |
2026-10-02 12:03:14 +02:00
| `modules/print_logic.py` ⚠ | 1 360 | `PrintLogic` , `AtlasConfig` , `RectangleCaptureTool` : Druckbereich, Maßstab, Atlas, Layoutaufruf |
2026-10-02 13:07:03 +02:00
| `modules/print_layout.py` ⚠ | 1 127 | `PrintLayout` : Layoutaufbau für § 38 / § 41 (Karte, Legende, Gitter, Schriftfeld) |
| `modules/print_kartenrand.py` | 189 | Kartenrand (Legenden, Quellenangabe, Kartenschild) überlappungsfrei anordnen: 1– 3 Legendenspalten, Rand breiter, Seite ggf. höher (#93 ) |
2026-09-04 11:57:26 +02:00
| `modules/print_layout_baufreigabe.py` | 403 | Layout „Anlage zur Baufreigabe“ (feste DIN A3/A4 quer) |
2026-10-02 12:03:14 +02:00
| `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 |
2026-10-02 12:50:13 +02:00
| `modules/basemap_legende_layout.py` | 465 | Legendensymbole aus Projektlayer-Styles zusammensetzen (weiße Flächen mit Legendenrand, #92 ), leere Hilfslayer, Legendenelement „Legende Basemap“ schreiben und platzieren |
2026-10-02 12:03:14 +02:00
| `modules/basemap_katalog.py` | 418 | Erzeugt/aktualisiert `data/basemap_legende.json` aus der basemap.de-Style-JSON (nur Standardbibliothek, eigenständig aufrufbar) |
2026-10-02 12:33:18 +02:00
| `modules/basemap_stilkorrektur.py` | 99 | Darstellungsfehler des Basemap-Layers korrigieren: Punktlinien mit Strichlänge 0 sichtbar machen (#90 ) |
2026-10-02 12:03:14 +02:00
| `modules/basemap_stilvorlagen.py` | 181 | Lokale Stilvorlagen des Basemap-Layers (QML + JSON im QGIS-Profil), Standard in `QSettings` |
2026-09-04 11:57:26 +02:00
### Sonstiges
| Pfad | Zweck |
|---|---|
| `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 |
2026-10-02 12:03:14 +02:00
| `data/basemap_legende.json` | Legendenkatalog basemap.de: Style-ID → Legendeneintrag (190 Einträge), erzeugt mit `basemap_katalog.py` , fachlich nachbearbeitet |
2026-09-04 11:57:26 +02:00
| `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` |
## sn_verfahrensgebiet (Repository `Plugin_SN_Verfahrensgebiet`) – Fachplugin
| Datei | Zeilen | Zweck |
|---|---:|---|
| `main.py` | 80 | `Verfahrensgebiet` : registriert Action (Priorität 10), erzeugt `DockWidget` mit `Pruefmanager` und `DataGrabber` |
| `ui/dockwidget.py` | 60 | Tabs `WorkingTab` , `PrintTab` , `SettingsTab` ; injiziert Services per `set_services()` |
| `ui/tabs/working_tab.py` ⚠ | 873 | Tab „Bearbeitung“: Buttons und Handler für ALKIS/Shape laden, Gemarkungen, Flurstücke, Grenzpunkte, Beteiligung, Statistik; hält viel Ablauflogik |
| `functions/verfahrensgebiet_alkis.py` | 359 | WFS-Suche `BauRaumOderBodenordnungsrecht` per Verfahrensnummer/Landkreis, `LoadStatus` |
| `functions/verfahrensgebiet_alkis_komplett.py` ⚠ | 661 | Vollständiger Ladeablauf aus ALKIS: BROR → Gemarkungen → Flurstücke → Flächenvergleich → Detailprüfung |
| `functions/verfahrensgebiet_shape_komplett.py` ⚠ | 978 | Ladeablauf aus Shape/ZIP (Mehrfachauswahl, `FBSchl` -Klassifikation, Abgleich mit BROR) – siehe `docs/aus_shape_laden_technisch.md` im Repo |
| `functions/verfahrensgebiet_dialoge.py` | 300 | Dialoge: BROR-Kombinationen, Landkreis-Objekte, Landkreisauswahl |
| `functions/verfahrensgebiet_edit_service.py` | 359 | Verfahrensgebiet aus Flurstücksauswahl bilden, ergänzen, entfernen, ersetzen |
| `functions/gemarkung_alkis.py` | 229 | Gemarkungen aus vereinfachtem ALKIS-WFS |
| `functions/flurstueck_alkis.py` | 259 | Flurstücke je Gemarkung aus ALKIS-SF-WFS (BBOX, Batches) |
| `functions/grenzpunkt_alkis.py` ⚠ | 1 674 | Grenzpunkte/`PunktortTA` gemarkungsweise, GML-Parsing, URL-sichere Batches |
| `functions/knickpunkt_pruefung.py` ⚠ | 810 | Knickpunktbasierte BROR-Prüfung, Ergebnislayer mit Kategorien |
| `functions/umringspruefung.py` | 312 | Umringsprüfung (Variante 1) |
| `functions/umringstatistik_grenzpunkte.py` | 374 | Statistik Grenzpunkte am Umring |
| `functions/beteiligung_pruefung.py` | 453 | Abgleich BI-Server-CSV mit ALKIS-Flurstücken |
| `tests/` | 12 Dateien | Mock-Modus, aktuell 157/201 grün (Baseline) |
| `docs/` | 3 Dateien | Ablaufdiagramme (Mermaid) für ALKIS- und Shape-Laden |
| `styles/` | 6 QML | BROR, Gemarkungen, Beteiligung, Verfahrensgebiet |
## sn_plan41 (Repository `Plugin_SN_Plan41`) – Fachplugin
| Datei | Zeilen | Zweck |
|---|---:|---|
| `main.py` | 71 | `Plan41` : Action mit Priorität 20, Dock mit `Pruefmanager` /`DataGrabber` |
| `ui/dockwidget.py` | 65 | Tabs `TabA` (Daten), `TabB` (Beispiel), `PrintTab` , `SettingsTab` |
| `ui/tab_a_ui.py` ⚠ | 633 | UI von Tab A: Verfahrens-GeoPackage, Linkliste, Raumfilter, VLN-API-Bereich |
| `ui/tab_a_logic.py` ⚠ | 1 239 | Fachlogik Tab A: Prüf-Pipeline (Datei, Linkliste, Stil, Layer), Abruf über `DataGrabber` /`Datenabruf` , Schreiben, Protokoll; `_SilentPruefmanagerProxy` |
| `ui/tabs/tab_b.py` | 27 | Beispiel-Tab ohne Funktion |
| `modules/listenauswerter.py` | 142 | Validiert Linklistenzeilen (Schema `ident, gruppe, kartenebene, inhalt, link, provider, stildatei` ) – wird von `sn_basis.DataGrabber` lazy importiert |
| `modules/vln_api_client.py` | 249 | HTTP-Client VLN-Karten-API v2 (Login, `X-API-Key` , Verfahren, Plan41-Datensatz, Upload) |
| `modules/vln_api_logic.py` | 379 | Ablauflogik der API-Integration in Tab A |
| `modules/vln_layer_manager.py` | 178 | GeoJSON ↔ Memory-Layer nach Geometriefamilie (Punkt/Linie/Fläche), EPSG:25833 |
| `assets/` | 33 Dateien | `Linkliste.xlsx` (44 Dienste) und QML-Stile |
| `doc/Datenbank_ERD.md` | 57 | Ziel-Datenmodell (Maßnahmen, Konten, Ausbauarten, Akteure) – Entwurf, nicht implementiert |
| `tests/` | 5 Dateien | 43/44 grün (Baseline) |
## sn_widmung (Repository `Plugin_SN_Widmung`) – Gerüst
`main.py` (Priorität 30), `ui/dockwidget.py` , `ui/tabs/tab_a.py` , `tab_b.py` : Registrierung funktioniert, Tabs enthalten nur Platzhalter. Keine Tests.
Dient als **minimales Muster** für ein neues Fachplugin (Skill `sn-neues-fachplugin` ).
## Platzhalter und Infrastruktur
| Repository | Inhalt |
|---|---|
| `Plugin_SN_FLT` , `Plugin_SN_Topografie` , `Plugin_SN_Template` | nur Release-Workflow, Metadata-Vorlage (teils noch `Plugin_SN_Neu` ), leere README |
| `Plugin_Test_Action` | Minimalplugin zum Testen der Release-Pipeline |
| `Repository` | `plugins.xml` (stable, leer), `plugins-testing.xml` , `plugins-unstable.xml` ; Branches `hidden/workflows` (zentrale Release-Orchestrierung) und `hidden/templates` |
| `Linkliste` | `linkliste.csv` → Gitea Action erzeugt XML/JSON/YAML |
| `Defaults` | Beispiel-Verfahrensdaten (JSON) und `styles/verfahrensgebiet.qml` ; nicht vom Code referenziert |
## Größte Dateien (Kandidaten für das spätere Refactoring)
| Datei | Zeilen |
|---|---:|
| `sn_verfahrensgebiet/functions/grenzpunkt_alkis.py` | 1 674 |
2026-10-02 12:03:14 +02:00
| `sn_basis/modules/print_logic.py` | 1 360 |
2026-09-04 11:57:26 +02:00
| `sn_plan41/ui/tab_a_logic.py` | 1 239 |
2026-10-02 13:07:03 +02:00
| `sn_basis/functions/qgiscore_wrapper.py` | 1 428 |
| `sn_basis/modules/print_layout.py` | 1 127 |
2026-09-04 11:57:26 +02:00
| `sn_verfahrensgebiet/functions/verfahrensgebiet_shape_komplett.py` | 978 |
| `sn_verfahrensgebiet/ui/tabs/working_tab.py` | 873 |
| `sn_verfahrensgebiet/functions/knickpunkt_pruefung.py` | 810 |
2026-10-02 12:03:14 +02:00
| `sn_basis/functions/qt_wrapper.py` | 832 |
| `sn_basis/ui/tabs/print_tab.py` | 730 |