# 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 \| “, 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` ⚠ | 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` ⚠ | 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 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` | | `functions/qgisui_wrapper.py` | 258 | `iface`-Zugriffe: Hauptfenster, Docks, Menüs, Toolbars, Layoutdesigner; Mock-`iface` | | `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()` | | `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 | | `functions/text_wrapper.py` | 25 | `sanitize_bezeichner(text, ersatz="_")`: Freitext → Layer-/Dateiname, Umlaute/ß/_/- bleiben erhalten | ### 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 | | `modules/print_logic.py` ⚠ | 1 360 | `PrintLogic`, `AtlasConfig`, `RectangleCaptureTool`: Druckbereich, Maßstab, Atlas, Layoutaufruf | | `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) | | `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` | 465 | Legendensymbole aus Projektlayer-Styles zusammensetzen (weiße Flächen mit Legendenrand, #92), 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_stilkorrektur.py` | 99 | Darstellungsfehler des Basemap-Layers korrigieren: Punktlinien mit Strichlänge 0 sichtbar machen (#90) | | `modules/basemap_stilvorlagen.py` | 181 | Lokale Stilvorlagen des Basemap-Layers (QML + JSON im QGIS-Profil), Standard in `QSettings` | ### 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 | | `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` | ## 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 | | `sn_basis/modules/print_logic.py` | 1 360 | | `sn_plan41/ui/tab_a_logic.py` | 1 239 | | `sn_basis/functions/qgiscore_wrapper.py` | 1 428 | | `sn_basis/modules/print_layout.py` | 1 127 | | `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` | 832 | | `sn_basis/ui/tabs/print_tab.py` | 730 |