Einklappbarer Bereich „Basemap“: Auswertebereich (Verfahrensgebiet/Druckbereich), Basemap-Legende beim Erstellen an/aus, „Basemap-Legende aktualisieren“ für bestehende Vorlagen und Stilvorlagen des Basemap-Layers. Stilvorlagen liegen lokal im QGIS-Profil (QML plus Begleitdatei mit Legendenauswahl), mehrere Varianten, eine als Standard markierbar; geladen wird nur auf Knopfdruck nach Rückfrage, fremde Varianten (andere Style-Namen) erst nach zweiter Bestätigung. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
129 lines
5.7 KiB
Python
129 lines
5.7 KiB
Python
"""
|
||
Tests für modules/basemap_stilvorlagen.py – lokale Stilvorlagen des Basemap-Layers (Basis #88).
|
||
|
||
Gespeichert wird in einem temporären Ordner; der Layer schreibt statt einer echten QML-Datei
|
||
eine kleine Textdatei. Laden und Speichern am echten Vektorkachel-Layer ist im QGIS-Test geprüft.
|
||
"""
|
||
import os
|
||
import shutil
|
||
import tempfile
|
||
import unittest
|
||
|
||
from sn_basis.modules.basemap_stilvorlagen import STANDARD_SCHLUESSEL, BasemapStilvorlagen
|
||
|
||
|
||
class _Einstellungen:
|
||
"""Ersatz für QSettings – die Tests dürfen keine echten Benutzereinstellungen verändern."""
|
||
|
||
def __init__(self): self.daten = {}
|
||
def value(self, k, standard=""): return self.daten.get(k, standard)
|
||
def setValue(self, k, v): self.daten[k] = v
|
||
def remove(self, k): self.daten.pop(k, None)
|
||
|
||
|
||
class _Stil:
|
||
def __init__(self, name): self._name = name
|
||
def styleName(self): return self._name
|
||
|
||
|
||
class _Layer:
|
||
def __init__(self, stile=("Kontur_Kreisstr", "Decker_Kreisstr"), speichern_ok=True):
|
||
self.stile = list(stile)
|
||
self.geladen = None
|
||
self.neu_gezeichnet = False
|
||
self._speichern_ok = speichern_ok
|
||
|
||
def name(self): return "Basemap.de - Farbe"
|
||
def renderer(self): return type("R", (), {"styles": lambda s: [_Stil(n) for n in self.stile]})()
|
||
|
||
def saveNamedStyle(self, pfad, kategorien):
|
||
if not self._speichern_ok:
|
||
return "kein Schreibrecht", False
|
||
with open(pfad, "w", encoding="utf-8") as datei:
|
||
datei.write("<qgis/>")
|
||
return "", True
|
||
|
||
def loadNamedStyle(self, pfad, kategorien):
|
||
self.geladen = pfad
|
||
return "", True
|
||
|
||
def triggerRepaint(self): self.neu_gezeichnet = True
|
||
|
||
|
||
class TestStilvorlagen(unittest.TestCase):
|
||
|
||
def setUp(self):
|
||
self.ordner = tempfile.mkdtemp()
|
||
self.einstellungen = _Einstellungen()
|
||
self.vorlagen = BasemapStilvorlagen(os.path.join(self.ordner, "stile"), self.einstellungen)
|
||
|
||
def tearDown(self):
|
||
shutil.rmtree(self.ordner, ignore_errors=True)
|
||
|
||
def test_speichern_und_auflisten(self):
|
||
"""Prüft, dass eine gespeicherte Vorlage mit Anzeigenamen, QML-Datei und Begleitdatei aufgelistet wird."""
|
||
self.vorlagen.speichern(_Layer(), "Ohne Hausnummern", {"ausgeblendet": ["wald"], "eingeblendet": []})
|
||
liste = self.vorlagen.liste()
|
||
self.assertEqual([v.anzeigename for v in liste], ["Ohne Hausnummern"])
|
||
self.assertEqual(liste[0].name, "Ohne_Hausnummern")
|
||
self.assertTrue(os.path.exists(liste[0].pfad))
|
||
self.assertEqual(self.vorlagen.legendenauswahl("Ohne_Hausnummern")["ausgeblendet"], ["wald"])
|
||
|
||
def test_mehrere_varianten_alphabetisch(self):
|
||
"""Prüft, dass mehrere Varianten nebeneinander bestehen und alphabetisch nach Anzeigename sortiert werden."""
|
||
for name in ("Zeichnung", "Abstimmung", "mit Gebäuden"):
|
||
self.vorlagen.speichern(_Layer(), name)
|
||
self.assertEqual([v.anzeigename for v in self.vorlagen.liste()], ["Abstimmung", "mit Gebäuden", "Zeichnung"])
|
||
|
||
def test_leerer_name_oder_fehler_beim_schreiben(self):
|
||
"""Prüft, dass ein leerer Name und ein Schreibfehler von QGIS als ValueError gemeldet werden."""
|
||
with self.assertRaises(ValueError):
|
||
self.vorlagen.speichern(_Layer(), " ")
|
||
with self.assertRaises(ValueError):
|
||
self.vorlagen.speichern(_Layer(speichern_ok=False), "Test")
|
||
|
||
def test_laden_setzt_stil_und_zeichnet_neu(self):
|
||
"""Prüft, dass das Laden die QML-Datei der Vorlage in den Layer lädt und neu zeichnen lässt."""
|
||
self.vorlagen.speichern(_Layer(), "Standard LNO")
|
||
layer = _Layer()
|
||
self.vorlagen.laden(layer, "Standard_LNO")
|
||
self.assertTrue(layer.geladen.endswith("Standard_LNO.qml"))
|
||
self.assertTrue(layer.neu_gezeichnet)
|
||
with self.assertRaises(ValueError):
|
||
self.vorlagen.laden(layer, "gibt_es_nicht")
|
||
|
||
def test_passung_meldet_fremde_styles(self):
|
||
"""Prüft, dass Style-Namen der Vorlage gemeldet werden, die der Ziel-Layer nicht kennt."""
|
||
self.vorlagen.speichern(_Layer(stile=("A", "B", "C")), "Grau")
|
||
self.assertEqual(self.vorlagen.pruefe_passung(_Layer(stile=("A",)), "Grau"), ["B", "C"])
|
||
self.assertEqual(self.vorlagen.pruefe_passung(_Layer(stile=("A", "B", "C")), "Grau"), [])
|
||
|
||
def test_standard_setzen_und_beim_loeschen_entfernen(self):
|
||
"""Prüft, dass eine Vorlage als Standard markiert wird und die Markierung beim Löschen der Vorlage entfällt."""
|
||
self.vorlagen.speichern(_Layer(), "Standard LNO")
|
||
self.vorlagen.setze_standard("Standard_LNO")
|
||
self.assertTrue(self.vorlagen.liste()[0].standard)
|
||
self.vorlagen.loeschen("Standard_LNO")
|
||
self.assertEqual(self.vorlagen.liste(), [])
|
||
self.assertEqual(self.vorlagen.standard(), "")
|
||
self.assertNotIn(STANDARD_SCHLUESSEL, self.einstellungen.daten)
|
||
with self.assertRaises(ValueError):
|
||
self.vorlagen.setze_standard("Standard_LNO")
|
||
|
||
def test_fehlende_begleitdatei_wird_toleriert(self):
|
||
"""Prüft, dass eine QML-Datei ohne Begleitdatei mit ihrem Dateinamen aufgelistet wird."""
|
||
os.makedirs(self.vorlagen.ordner, exist_ok=True)
|
||
with open(os.path.join(self.vorlagen.ordner, "Alt.qml"), "w", encoding="utf-8") as datei:
|
||
datei.write("<qgis/>")
|
||
self.assertEqual([v.anzeigename for v in self.vorlagen.liste()], ["Alt"])
|
||
self.assertIsNone(self.vorlagen.legendenauswahl("Alt"))
|
||
self.assertEqual(self.vorlagen.pruefe_passung(_Layer(), "Alt"), [])
|
||
|
||
def test_ohne_ordner_leere_liste(self):
|
||
"""Prüft, dass ohne angelegten Vorlagenordner eine leere Liste zurückkommt."""
|
||
self.assertEqual(self.vorlagen.liste(), [])
|
||
|
||
|
||
if __name__ == "__main__":
|
||
unittest.main()
|