Die Basemap-Styles „Platz“ (Verkehrsfläche, weitere Nutzung) haben eine rein weiße Füllung
ohne Umrandung und waren auf dem weißen Legendenhintergrund unsichtbar. baue_symbole gibt
solchen Flächensymbolen jetzt in der Legende eine dünne graue Randlinie (0,15 mm). Erkannt
wird das an Füllfarbe und fehlender Kontur (braucht_legendenrand), nicht an Style-Namen; der
Basemap-Layer in der Karte bleibt unverändert. Wrapper: QgsSimpleLineSymbolLayer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
basemap.de zeichnet Punktlinien mit Strichlänge 0 und runder Linienkappe (MapLibre-Muster);
QGIS übernimmt das beim Import 1:1, Qt zeichnet Striche der Länge 0 aber nicht. Baumreihen,
Hecken, Durchlässe, Seilbahnen u. a. (12 Styles) fehlten dadurch in Karte und Legende.
Neues Modul basemap_stilkorrektur: korrigiere_punktlinien(layer) ersetzt Strichlänge 0 durch
0,01 im festen Strichmuster und in den array(...)-Mustern des zoomabhängigen Ausdrucks;
idempotent, andere Styles unverändert. Ausgelöst per Knopf „Punktlinien korrigieren“ im
Basemap-Bereich, sicherbar als Stilvorlage. Wrapper: PROPERTY_CUSTOM_DASH,
QgsProperty.fromExpression im Mock.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Beim Erstellen einer §38-/§41-Vorlage wertet BasemapLegende die Kacheln des sichtbaren
basemap.de-Layers im Verfahrensgebiet (wahlweise Druckbereich) kachelweise über
selectByGeometry aus, prüft die Renderer-Styles mit derselben Zoomlogik wie QGIS und
bildet daraus Legendeneinträge. Ein Mehrfachauswahl-Dialog (neu: ask_mehrfachauswahl)
lässt Kategorien abwählen; die Auswahl wird im Projekt gemerkt. Die gewählten Einträge
stehen mit der Signatur des Projektlayers (zoomabhängige Werte festgeschrieben) in
einem eigenen Legendenelement über der Quellenangabe. Ein eigenes Element ist nötig,
weil die nach Karteninhalt filternde Hauptlegende die Hilfslayer ausblenden würde.
Wrapper um die nötigen QGIS-/Qt-Symbole mit Mock ergänzt (eigener Block in
qgiscore_wrapper; QgsRectangle hatte bisher keinen Mock).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
remove_toolbar()/remove_menu() nahmen Toolbar und Menü bisher nur aus der sichtbaren Leiste,
das Qt-Objekt blieb als Kind von main_window bestehen. Beim Neuladen mit dem Plugin Reloader
meldete QGIS deshalb "removing duplicated widget(s) not cleaned up by the plugin during
unload: LnoSachsenToolbar" - der defensive Workaround in init_ui() (Suche nach übrig
gebliebenen Toolbars) kaschierte das nur beim nächsten Laden, nicht beim Unload selbst.
remove_all() ruft jetzt deleteLater() auf beide Objekte, bevor die Referenzen verworfen
werden - dieselbe Behandlung, die init_ui() schon für Altlasten nutzt. deleteLater() ist in
PyQt5 und PyQt6 identisch, keine QGIS3/4-Fallunterscheidung nötig.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
43 als "vernachlässigbar" eingestufte Funktionen (dialog_wrapper.py,
message_wrapper.py, os_wrapper.py, qgisui_wrapper.py, qt_wrapper.py,
DataGrabber.py, LayerLoader.py, Pruefmanager.py, navigation.py,
print_tab.py) tragen jetzt den Vermerk "von Test abgesehen, weil
vernachlässigbar; HD 18.09.2026". Fehlalarme der Testkatalog-Heuristik
(Dateipruefer._ist_leer/_handle_leere_eingabe, linkpruefer.py komplett,
Pruefmanager._handle_datei_existiert) und der als Bug erfasste tote Code
(Pruefmanager._ask_use_or_replace_pufferlayer, #60) bleiben unangetastet.
41 Funktionen im zur Grundüberarbeitung anstehenden Print-Bereich
(print_logic.py, print_layout.py, print_layout_baufreigabe.py) tragen den
Vermerk "Test ausgesetzt, zunächst Refactor".
Reine Dokumentationsänderung, kein Verhalten geändert.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
70 neue Testfälle für Datenabruf.py, Datenschreiber.py, LayerLoader.py und
excel_importer.py - die einzigen Module ohne jede Testdatei laut
Testkatalog-Abschnitt "Ungetestete Funktionen". Schwerpunkt: Provider-URL-
Bau (WFS/REST/OGR), Raumfilter, CRS-Transformation, GPKG-Schreib-/Ladepfad
und Excel-Import-Fehlerzweige.
qgiscore_wrapper._MockQgsProject um transformContext() und addMapLayer()
ergänzt - beide fehlten im Mock und ließen die betroffenen Funktionen im
Mock-Modus für jeden gültigen Layer scheitern (siehe fallstricke.md).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ursache für "QML-Dateien greifen nicht" (Verfahrensgebiet #50): get_plugin_root()
nutzte Path(__file__).resolve(), was Junctions zum echten Zielverzeichnis
auflöst. link_qgis_profile.py verknüpft die Klone im QGIS-Profil per Junction
unter ihrem Paketnamen (sn_verfahrensgebiet, sn_plan41, ...) - .resolve()
sprang dabei zurück zum Workspace-Root, wo die Klone unter ihrem Repo-Namen
(Plugin_SN_*) liegen. Alle Aufrufer von get_plugin_root() (Stilpruefer,
ly_style_wrapper.apply_style, LayerLoader.apply_style, Datenschreiber,
sn_plan41 vln_api_logic/tab_a_logic) suchten dadurch am falschen Ort.
.absolute() statt .resolve(): __file__ liefert beim Import über die Junction
bereits den korrekten, unaufgelösten Pfad - nichts, was aufgelöst werden
müsste. Für echte ZIP-/Repository-Installationen (kein Symlink im Plugin-
Ordner) ändert sich nichts, da dort nichts aufzulösen ist.
Test test_get_plugin_root_folgt_keiner_verzeichnisverknuepfung legt eine
echte Verzeichnisverknüpfung an (Symlink, unter Windows via Junction wie
link_qgis_profile.py) und zeigt den Fehler vor dem Fix rot, danach grün.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Regex zur Bezeichner-Bereinigung aus Datenschreiber.py in
functions/text_wrapper.py (sanitize_bezeichner) ausgelagert und um
Bindestrich ergänzt, der bisher fehlte. Neue Tests decken Umlaute, ß,
Unterstrich, Bindestrich, eigenes Ersatzzeichen und Leerfälle ab.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MneDjzrjmbpQt8udFYxN9e
Portiert aus origin/unstable: sn_basis/functions/laenderkennung.py bildet
Plugin-Präfix -> zweistellige ALKIS-Länderkennung ab (aktuell nur Sachsen).
Wird von der neuen Beteiligungsprüfung in sn_verfahrensgebiet für die
Flurstückskennzeichen-Bildung genutzt.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Landkreisliste liegt jetzt in data/landkreise.json statt hartcodiert in
landkreise.py, damit sie ohne Codeänderung pflegbar und auch aus anderen
Modulen nutzbar ist (Sentinel ALLE_LANDKREISE für "Alle Landkreise").
- ask_bror_kombinationen, ask_landkreis_objekte und ask_landkreis_auswahl aus
dialog_wrapper.py entfernt: sie sind sn_verfahrensgebiet-spezifisches
Vokabular (BROR/VKZ/Landkreis-Fallback) und gehören nicht in den
domänenfreien sn_basis-Hub. Sie leben jetzt in
sn_verfahrensgebiet/functions/verfahrensgebiet_dialoge.py.
- qt_wrapper.py: QTableWidget/QTableWidgetItem/QTableWidgetSelectionRange,
SelectRows, NoEditTriggers, AscendingOrder ergänzt (für die neue
Tabellen-Auswahl im Landkreis-Objektdialog).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Landkreis-Feld in den Projekteigenschaften als Dropdown statt Freitext,
Landkreiskennzahl zusätzlich als eigene Projektvariable verfügbar.
- ask_bror_kombination(en) auf echte Mehrfachauswahl umgestellt, inkl.
Titel, Wappen-Icon, kompakter/anpassbarer Größe und Scrollbar-Fix.
- Neuer Dialog ask_landkreis_objekte für die landkreisweite Objektsuche
(Mehrfachauswahl, "Alle auswählen", "Nur laden ohne weiteren Ablauf").
- qt_wrapper um QDialog/QDialogButtonBox/QListWidget/QListWidgetItem/
QAbstractItemView/QIcon sowie QComboBox-userData/currentData erweitert.