Files
Projektwissen/docs/architektur/modulkarte.md
T
AndreasTharangandClaude Sonnet 5 ab416fb34c Projektwissen: Git-Vorgaben, Ticketzugriff, Tests und Einstieg
Erster Stand des Repositories AG_QGIS/Projektwissen (bisher Arbeitstitel
"Workspace", ADR 0006). Der lokale Ordner heisst weiter AG_QGIS, weil darin
auch die Plugin-Klone liegen.

Git verbindlich (ADR 0007), aus dem bisherigen Wiki-Konzept entwickelt:
- docs/leitfaden/05_git_arbeitsweise.md mit Kanal-Kette, Branch-Namen und
  Gitea-Branch-Schutz.
- Der Einstiegspunkt eines Fixes richtet sich nach dem Kanal, in dem der
  Fehler sitzt; ein Fix an testing oder stable ist erst mit der
  Rueckfuehrung nach unten abgeschlossen. Das fehlte bisher.
- Der stabile Kanal heisst stable, nicht main: der Release-Workflow in
  Repository:hidden/workflows fuehrt git checkout "$CHANNEL" aus, der
  Branchname muss also dem Kanalnamen entsprechen. Er existiert in keinem
  Plugin-Repo und ist vom Maintainer anzulegen.
- Der Mensch drueckt ab: .claude/settings.json sperrt push, merge, tag.
- scripts/hallo.py und /hallo holen den Stand aller Klone, per
  Fast-Forward wo gefahrlos; nie mergen, stashen oder verwerfen.

Ticketzugriff:
- scripts/gitea.py liest Issues, Kommentare und PRs ueber die oeffentliche
  API, ohne Token, nur GET. Schreibendes nur als Entwurf in entwuerfe/.
- Skill sn-ticket.

Tests (ADR 0009):
- docs/leitfaden/06_tests.md: Testebenen, Testpflicht, und wie eine
  Fachperson beurteilt, ob Tests fachlich sinnvoll sind.
- scripts/testkatalog.py erzeugt docs/tests/testkatalog.md per ast-Parsing,
  ohne Import und ohne QGIS. Befund: nur 100 von 332 Tests haben einen
  Docstring, sn_basis keinen einzigen von 87.
- Vorlage und erste Testkonzept-Seite mit Mermaid. Dabei gefunden und gegen
  origin geprueft: _ermittle_gebietstyp_aus_fbschl hat keinen Test, obwohl
  PR #44/#45 genau diese Funktion tolerant gemacht hat.
- docs/konzept/07_qgis_tests_plan.md: Stufenplan fuer Tests gegen echtes
  QGIS. Dabei aufgefallen: QGIS 3.40 ist seit Januar 2026 End of Life,
  qgis_min steht aber noch darauf.

Werkzeuge (ADR 0008):
- 04_werkzeuge_einrichten.md nur noch Claude Code als CLI und in VS Code.
- .vscode/ entfernt, brauchbare Einstellungen als persoenliche Vorlage.

Ausserdem: README als Einstieg neu aufgebaut, Mermaid-Diagramm in
schnittstellen.md repariert (unmaskierte Klammern, rendert seither nicht).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-04 11:57:26 +02:00

140 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`) |
| `ui/tabs/print_tab.py` ⚠ | 709 | Tab „Druck“: Druckbereich, Maßstab, Format, Themen, Legende, Atlas; nutzt `print_logic` |
### 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/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/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 |
### 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 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_layout_baufreigabe.py` | 403 | Layout „Anlage zur Baufreigabe“ (feste DIN A3/A4 quer) |
### 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 |
| `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 321 |
| `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_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 |