2026-10-02 11:57:10 +02:00
|
|
|
|
"""
|
|
|
|
|
|
sn_basis/ui/widgets/basemap_bereich.py – einklappbarer Bereich „Basemap“ im Druck-Tab
|
|
|
|
|
|
|
2026-10-05 21:27:35 +02:00
|
|
|
|
Basemap-Layer hinzufügen und sein Thema wechseln (Basis #100), Einstellungen der
|
|
|
|
|
|
Basemap-Legende (Auswertebereich, Erzeugen beim Anlegen der Vorlage),
|
2026-10-02 12:33:00 +02:00
|
|
|
|
„Basemap-Legende aktualisieren“ für bestehende Vorlagen, lokale Stilvorlagen des
|
|
|
|
|
|
Basemap-Layers (laden, speichern, als Standard markieren, löschen) und „Punktlinien
|
|
|
|
|
|
korrigieren“ (Basis #90). Basis #88.
|
2026-10-02 11:57:10 +02:00
|
|
|
|
|
|
|
|
|
|
Die Handler enthalten nur Ablauf und Rückfragen; die Logik liegt in
|
2026-10-05 21:27:35 +02:00
|
|
|
|
``modules/basemap_themen``, ``modules/basemap_legende`` und ``modules/basemap_stilvorlagen``.
|
2026-10-02 11:57:10 +02:00
|
|
|
|
"""
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
|
|
from typing import Any, Optional
|
|
|
|
|
|
|
2026-10-05 21:27:35 +02:00
|
|
|
|
from sn_basis.functions.dialog_wrapper import ask_auswahl, ask_text, ask_yes_no
|
2026-10-02 11:57:10 +02:00
|
|
|
|
from sn_basis.functions.message_wrapper import info, success, warning
|
|
|
|
|
|
from sn_basis.functions.qgiscore_wrapper import QgsProject
|
2026-10-05 21:27:35 +02:00
|
|
|
|
from sn_basis.functions.qgisui_wrapper import get_active_layer
|
2026-10-02 11:57:10 +02:00
|
|
|
|
from sn_basis.functions.qt_wrapper import (
|
|
|
|
|
|
ArrowDown,
|
|
|
|
|
|
ArrowRight,
|
|
|
|
|
|
QCheckBox,
|
|
|
|
|
|
QComboBox,
|
|
|
|
|
|
QHBoxLayout,
|
|
|
|
|
|
QLabel,
|
|
|
|
|
|
QPushButton,
|
|
|
|
|
|
QToolButton,
|
|
|
|
|
|
QVBoxLayout,
|
|
|
|
|
|
QWidget,
|
|
|
|
|
|
ToolButtonTextBesideIcon,
|
|
|
|
|
|
)
|
|
|
|
|
|
from sn_basis.modules import basemap_legende as legende
|
2026-10-05 21:27:35 +02:00
|
|
|
|
from sn_basis.modules import basemap_themen as themen
|
2026-10-02 11:57:10 +02:00
|
|
|
|
from sn_basis.modules.basemap_legende_layout import layouts_mit_basemap_legende
|
2026-10-02 12:33:00 +02:00
|
|
|
|
from sn_basis.modules.basemap_stilkorrektur import korrigiere_punktlinien
|
2026-10-02 11:57:10 +02:00
|
|
|
|
from sn_basis.modules.basemap_stilvorlagen import BasemapStilvorlagen
|
|
|
|
|
|
|
|
|
|
|
|
TITEL = "Basemap"
|
|
|
|
|
|
KEIN_LAYER_TEXT = "Kein Basemap-Layer im Projekt"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class BasemapBereich(QWidget):
|
|
|
|
|
|
"""Einklappbarer Basemap-Bereich; standardmäßig eingeklappt."""
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, parent: Optional[Any] = None, project: Any | None = None,
|
2026-10-05 21:27:35 +02:00
|
|
|
|
stilvorlagen: BasemapStilvorlagen | None = None,
|
|
|
|
|
|
layer_fabrik: Any | None = None) -> None:
|
2026-10-02 11:57:10 +02:00
|
|
|
|
super().__init__(parent)
|
|
|
|
|
|
self._project = project
|
|
|
|
|
|
self._stilvorlagen = stilvorlagen
|
2026-10-05 21:27:35 +02:00
|
|
|
|
self._layer_fabrik = layer_fabrik
|
2026-10-02 11:57:10 +02:00
|
|
|
|
self._build_ui()
|
|
|
|
|
|
self.aktualisieren()
|
|
|
|
|
|
|
|
|
|
|
|
# --- Aufbau ---------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
def _build_ui(self) -> None:
|
|
|
|
|
|
"""von Test abgesehen, weil reiner Widget-Aufbau; im QGIS-Test geprüft"""
|
|
|
|
|
|
haupt = QVBoxLayout()
|
|
|
|
|
|
haupt.setSpacing(4)
|
|
|
|
|
|
haupt.setContentsMargins(0, 0, 0, 0)
|
|
|
|
|
|
|
|
|
|
|
|
knopf = QToolButton()
|
|
|
|
|
|
knopf.setText(TITEL)
|
|
|
|
|
|
knopf.setCheckable(True)
|
|
|
|
|
|
knopf.setChecked(False)
|
|
|
|
|
|
knopf.setToolButtonStyle(ToolButtonTextBesideIcon)
|
|
|
|
|
|
knopf.setArrowType(ArrowRight)
|
|
|
|
|
|
knopf.setStyleSheet("font-weight: bold; margin-top: 6px;")
|
|
|
|
|
|
knopf.toggled.connect(self._umschalten)
|
|
|
|
|
|
self._knopf = knopf
|
|
|
|
|
|
haupt.addWidget(knopf)
|
|
|
|
|
|
|
|
|
|
|
|
inhalt = QWidget()
|
|
|
|
|
|
spalte = QVBoxLayout()
|
|
|
|
|
|
spalte.setSpacing(4)
|
|
|
|
|
|
spalte.setContentsMargins(10, 4, 4, 4)
|
|
|
|
|
|
|
|
|
|
|
|
self._status = QLabel(KEIN_LAYER_TEXT)
|
|
|
|
|
|
self._status.setWordWrap(True)
|
|
|
|
|
|
spalte.addWidget(self._status)
|
|
|
|
|
|
|
2026-10-05 21:27:35 +02:00
|
|
|
|
spalte.addWidget(self._ueberschrift("Basemap-Layer"))
|
|
|
|
|
|
self._hinzufuegen_btn = QPushButton("Basemap hinzufügen", self)
|
|
|
|
|
|
self._hinzufuegen_btn.setToolTip(
|
|
|
|
|
|
"Lädt basemap.de (Vektorkacheln) im gewählten Thema ganz unten in den Layerbaum."
|
|
|
|
|
|
)
|
|
|
|
|
|
self._hinzufuegen_btn.clicked.connect(lambda *_: self._on_basemap_hinzufuegen())
|
|
|
|
|
|
spalte.addWidget(self._hinzufuegen_btn)
|
|
|
|
|
|
spalte.addWidget(QLabel("Thema"))
|
|
|
|
|
|
self._thema_combo = QComboBox(self)
|
|
|
|
|
|
self._thema_combo.setToolTip(
|
|
|
|
|
|
"Darstellung des Dienstes für den ausgewählten Basemap-Layer. "
|
|
|
|
|
|
"Ohne Basemap-Layer gilt die Wahl für „Basemap hinzufügen“."
|
|
|
|
|
|
)
|
|
|
|
|
|
for schluessel, eintrag in themen.THEMEN.items():
|
|
|
|
|
|
self._thema_combo.addItem(eintrag.bezeichnung, schluessel)
|
|
|
|
|
|
self._thema_combo.setCurrentIndex(max(0, self._thema_combo.findData(themen.STANDARD_THEMA)))
|
|
|
|
|
|
self._thema_combo.currentIndexChanged.connect(self._on_thema_gewaehlt)
|
|
|
|
|
|
spalte.addWidget(self._thema_combo)
|
|
|
|
|
|
|
2026-10-02 11:57:10 +02:00
|
|
|
|
spalte.addWidget(self._ueberschrift("Legende"))
|
|
|
|
|
|
spalte.addWidget(QLabel("Auswertebereich"))
|
|
|
|
|
|
self._bereich_combo = QComboBox(self)
|
|
|
|
|
|
for schluessel, text in legende.AUSWERTEBEREICHE.items():
|
|
|
|
|
|
self._bereich_combo.addItem(text, schluessel)
|
|
|
|
|
|
self._bereich_combo.currentIndexChanged.connect(self._on_bereich_geaendert)
|
|
|
|
|
|
spalte.addWidget(self._bereich_combo)
|
|
|
|
|
|
|
|
|
|
|
|
self._erzeugen_cb = QCheckBox("Basemap-Legende beim Erstellen der Vorlage erzeugen (§ 38, § 41)", self)
|
|
|
|
|
|
self._erzeugen_cb.toggled.connect(self._on_erzeugen_geaendert)
|
|
|
|
|
|
spalte.addWidget(self._erzeugen_cb)
|
|
|
|
|
|
|
|
|
|
|
|
spalte.addWidget(QLabel("Vorlage"))
|
|
|
|
|
|
self._layout_combo = QComboBox(self)
|
|
|
|
|
|
spalte.addWidget(self._layout_combo)
|
|
|
|
|
|
self._aktualisieren_btn = QPushButton("Basemap-Legende aktualisieren", self)
|
|
|
|
|
|
self._aktualisieren_btn.clicked.connect(self._on_legende_aktualisieren)
|
|
|
|
|
|
spalte.addWidget(self._aktualisieren_btn)
|
|
|
|
|
|
|
|
|
|
|
|
spalte.addWidget(self._ueberschrift("Stilvorlage"))
|
|
|
|
|
|
self._stil_combo = QComboBox(self)
|
|
|
|
|
|
spalte.addWidget(self._stil_combo)
|
|
|
|
|
|
zeile = QHBoxLayout()
|
|
|
|
|
|
for text, handler in (
|
|
|
|
|
|
("Laden", self._on_stil_laden),
|
|
|
|
|
|
("Speichern unter …", self._on_stil_speichern),
|
|
|
|
|
|
("Als Standard", self._on_stil_standard),
|
|
|
|
|
|
("Löschen", self._on_stil_loeschen),
|
|
|
|
|
|
):
|
|
|
|
|
|
knopf_stil = QPushButton(text, self)
|
|
|
|
|
|
knopf_stil.clicked.connect(lambda *_, h=handler: h())
|
|
|
|
|
|
zeile.addWidget(knopf_stil)
|
|
|
|
|
|
spalte.addLayout(zeile)
|
|
|
|
|
|
|
2026-10-02 12:33:00 +02:00
|
|
|
|
self._punktlinien_btn = QPushButton("Punktlinien korrigieren", self)
|
|
|
|
|
|
self._punktlinien_btn.setToolTip(
|
|
|
|
|
|
"Baumreihen, Hecken, Durchlässe u. a. zeichnet QGIS aus dem Basemap-Stil nicht (Strichlänge 0). "
|
|
|
|
|
|
"Korrigiert die Darstellung im Projekt; mit „Speichern unter …“ als Stilvorlage sichern."
|
|
|
|
|
|
)
|
|
|
|
|
|
self._punktlinien_btn.clicked.connect(lambda *_: self._on_punktlinien_korrigieren())
|
|
|
|
|
|
spalte.addWidget(self._punktlinien_btn)
|
|
|
|
|
|
|
2026-10-02 11:57:10 +02:00
|
|
|
|
inhalt.setLayout(spalte)
|
|
|
|
|
|
inhalt.setVisible(False)
|
|
|
|
|
|
self._inhalt = inhalt
|
|
|
|
|
|
haupt.addWidget(inhalt)
|
|
|
|
|
|
self.setLayout(haupt)
|
|
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
|
def _ueberschrift(text: str) -> Any:
|
|
|
|
|
|
beschriftung = QLabel(text)
|
|
|
|
|
|
beschriftung.setStyleSheet("font-weight: bold; margin-top: 4px;")
|
|
|
|
|
|
return beschriftung
|
|
|
|
|
|
|
|
|
|
|
|
# --- Zustand --------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
def _projekt(self) -> Any:
|
|
|
|
|
|
return getattr(self, "_project", None) or QgsProject.instance()
|
|
|
|
|
|
|
|
|
|
|
|
def _vorlagen(self) -> BasemapStilvorlagen:
|
|
|
|
|
|
if getattr(self, "_stilvorlagen", None) is None:
|
|
|
|
|
|
self._stilvorlagen = BasemapStilvorlagen()
|
|
|
|
|
|
return self._stilvorlagen
|
|
|
|
|
|
|
|
|
|
|
|
def basemap_layer(self) -> Any | None:
|
|
|
|
|
|
"""Erster Basemap-Layer des Projekts (sichtbar oder nicht)."""
|
|
|
|
|
|
try:
|
|
|
|
|
|
layer = list(self._projekt().mapLayers().values())
|
|
|
|
|
|
except Exception:
|
|
|
|
|
|
return None
|
|
|
|
|
|
gefunden = legende.finde_basemap_layer(layer)
|
|
|
|
|
|
return gefunden[0] if gefunden else None
|
|
|
|
|
|
|
2026-10-05 21:27:35 +02:00
|
|
|
|
def _ziel_layer(self) -> Any | None:
|
|
|
|
|
|
"""Der im Layerbaum ausgewählte Basemap-Layer, sonst der erste des Projekts."""
|
|
|
|
|
|
aktiv = get_active_layer()
|
|
|
|
|
|
if aktiv is not None and legende.ist_basemap_layer(aktiv):
|
|
|
|
|
|
return aktiv
|
|
|
|
|
|
return self.basemap_layer()
|
|
|
|
|
|
|
|
|
|
|
|
def _gewaehltes_thema(self) -> str:
|
|
|
|
|
|
return str(self._thema_combo.currentData() or themen.STANDARD_THEMA)
|
|
|
|
|
|
|
|
|
|
|
|
def _zeige_thema(self, layer: Any | None) -> None:
|
|
|
|
|
|
"""Stellt das Thema-Dropdown ohne Themenwechsel auf das Thema des Layers."""
|
|
|
|
|
|
schluessel = themen.thema_des_layers(layer) if layer is not None else None
|
|
|
|
|
|
if schluessel is None:
|
|
|
|
|
|
return
|
|
|
|
|
|
self._thema_combo.blockSignals(True)
|
|
|
|
|
|
self._thema_combo.setCurrentIndex(max(0, self._thema_combo.findData(schluessel)))
|
|
|
|
|
|
self._thema_combo.blockSignals(False)
|
|
|
|
|
|
|
2026-10-02 11:57:10 +02:00
|
|
|
|
def _umschalten(self, offen: bool) -> None:
|
|
|
|
|
|
self._knopf.setArrowType(ArrowDown if offen else ArrowRight)
|
|
|
|
|
|
self._inhalt.setVisible(offen)
|
|
|
|
|
|
if offen:
|
|
|
|
|
|
self.aktualisieren()
|
|
|
|
|
|
|
|
|
|
|
|
def aktualisieren(self) -> None:
|
|
|
|
|
|
"""Liest Projektvariablen, Layouts und Stilvorlagen neu ein (z. B. nach Projektwechsel)."""
|
2026-10-05 21:27:35 +02:00
|
|
|
|
layer = self._ziel_layer()
|
2026-10-02 11:57:10 +02:00
|
|
|
|
self._status.setText(f"Basemap-Layer: {layer.name()}" if layer is not None else KEIN_LAYER_TEXT)
|
2026-10-05 21:27:35 +02:00
|
|
|
|
self._zeige_thema(layer)
|
2026-10-02 11:57:10 +02:00
|
|
|
|
|
|
|
|
|
|
bereich = legende.lies_auswertebereich()
|
|
|
|
|
|
self._bereich_combo.blockSignals(True)
|
|
|
|
|
|
self._bereich_combo.setCurrentIndex(max(0, self._bereich_combo.findData(bereich)))
|
|
|
|
|
|
self._bereich_combo.blockSignals(False)
|
|
|
|
|
|
self._erzeugen_cb.blockSignals(True)
|
|
|
|
|
|
self._erzeugen_cb.setChecked(legende.legende_erzeugen_aktiv())
|
|
|
|
|
|
self._erzeugen_cb.blockSignals(False)
|
|
|
|
|
|
|
|
|
|
|
|
self._layout_combo.clear()
|
|
|
|
|
|
self._layout_combo.addItems(layouts_mit_basemap_legende(self._projekt()))
|
|
|
|
|
|
self._aktualisieren_btn.setEnabled(layer is not None and self._layout_combo.count() > 0)
|
2026-10-02 12:33:00 +02:00
|
|
|
|
self._punktlinien_btn.setEnabled(layer is not None)
|
2026-10-02 11:57:10 +02:00
|
|
|
|
|
|
|
|
|
|
self._stil_combo.clear()
|
|
|
|
|
|
for vorlage in self._vorlagen().liste():
|
|
|
|
|
|
self._stil_combo.addItem(f"{vorlage.anzeigename}{' ★' if vorlage.standard else ''}", vorlage.name)
|
|
|
|
|
|
standard = self._vorlagen().standard()
|
|
|
|
|
|
if standard:
|
|
|
|
|
|
self._stil_combo.setCurrentIndex(max(0, self._stil_combo.findData(standard)))
|
|
|
|
|
|
|
2026-10-05 21:27:35 +02:00
|
|
|
|
# --- Handler: Basemap-Layer und Thema ------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
def _aenderungen_klaeren(self, layer: Any) -> bool:
|
|
|
|
|
|
"""Fragt vor dem Überschreiben der Darstellung nach, ob Änderungen als Stil gesichert werden sollen.
|
|
|
|
|
|
|
|
|
|
|
|
``True``: weitermachen (gespeichert, verworfen oder nichts geändert); ``False``: abbrechen.
|
|
|
|
|
|
"""
|
|
|
|
|
|
stand = themen.aenderungsstand(layer)
|
|
|
|
|
|
if stand == themen.UNVERAENDERT:
|
|
|
|
|
|
return True
|
|
|
|
|
|
if stand == themen.GEAENDERT:
|
|
|
|
|
|
grund = f"Die Darstellung von „{layer.name()}“ wurde seit dem Laden des Themas oder Stils verändert."
|
|
|
|
|
|
else:
|
|
|
|
|
|
grund = (f"Für „{layer.name()}“ ist nicht bekannt, ob die Darstellung verändert wurde "
|
|
|
|
|
|
"(Layer wurde ohne diese Funktion geladen).")
|
|
|
|
|
|
wahl = ask_auswahl(
|
|
|
|
|
|
TITEL,
|
|
|
|
|
|
f"{grund} Beim Themenwechsel gehen Änderungen verloren.\n\nVorher als Stil speichern?",
|
|
|
|
|
|
[("speichern", "Als Stil speichern …"), ("verwerfen", "Verwerfen"), ("abbrechen", "Abbrechen")],
|
|
|
|
|
|
default="speichern",
|
|
|
|
|
|
abbrechen="abbrechen",
|
|
|
|
|
|
)
|
|
|
|
|
|
if wahl == "abbrechen":
|
|
|
|
|
|
return False
|
|
|
|
|
|
if wahl == "speichern":
|
|
|
|
|
|
return self._on_stil_speichern(layer)
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
def _on_basemap_hinzufuegen(self) -> None:
|
|
|
|
|
|
schluessel = self._gewaehltes_thema()
|
|
|
|
|
|
try:
|
|
|
|
|
|
vorhanden = themen.layer_mit_quelle(list(self._projekt().mapLayers().values()))
|
|
|
|
|
|
except Exception:
|
|
|
|
|
|
vorhanden = []
|
|
|
|
|
|
if vorhanden:
|
|
|
|
|
|
namen = ", ".join(f"„{l.name()}“" for l in vorhanden)
|
|
|
|
|
|
wahl = ask_auswahl(
|
|
|
|
|
|
TITEL,
|
|
|
|
|
|
f"Im Projekt gibt es schon einen Basemap-Layer mit derselben Quelle: {namen}.\n\n"
|
|
|
|
|
|
"Einen weiteren Basemap-Layer zusätzlich laden, den vorhandenen ersetzen oder abbrechen?",
|
|
|
|
|
|
[("zusaetzlich", "Zusätzlich laden"), ("ersetzen", "Ersetzen"), ("abbrechen", "Abbrechen")],
|
|
|
|
|
|
default="abbrechen",
|
|
|
|
|
|
abbrechen="abbrechen",
|
|
|
|
|
|
)
|
|
|
|
|
|
if wahl == "abbrechen":
|
|
|
|
|
|
return
|
|
|
|
|
|
if wahl == "ersetzen":
|
|
|
|
|
|
ziel = self._ziel_layer()
|
|
|
|
|
|
self._ersetzen(ziel if ziel in vorhanden else vorhanden[0], schluessel)
|
|
|
|
|
|
return
|
|
|
|
|
|
try:
|
|
|
|
|
|
layer = themen.erzeuge_layer(schluessel, getattr(self, "_layer_fabrik", None))
|
|
|
|
|
|
except ValueError as fehler:
|
|
|
|
|
|
warning(TITEL, str(fehler))
|
|
|
|
|
|
return
|
|
|
|
|
|
themen.fuege_hinzu(self._projekt(), layer)
|
|
|
|
|
|
self.aktualisieren()
|
|
|
|
|
|
success(TITEL, f"„{layer.name()}“ hinzugefügt.")
|
|
|
|
|
|
|
|
|
|
|
|
def _ersetzen(self, layer: Any, schluessel: str) -> None:
|
|
|
|
|
|
"""Lädt den vorhandenen Layer im gewählten Thema neu; Position und Bezüge in Layouts bleiben."""
|
|
|
|
|
|
if not self._aenderungen_klaeren(layer):
|
|
|
|
|
|
return
|
|
|
|
|
|
try:
|
|
|
|
|
|
themen.wechsle_thema(layer, schluessel)
|
|
|
|
|
|
except ValueError as fehler:
|
|
|
|
|
|
warning(TITEL, str(fehler))
|
|
|
|
|
|
return
|
|
|
|
|
|
self.aktualisieren()
|
|
|
|
|
|
success(TITEL, f"„{layer.name()}“ im Thema {themen.thema(schluessel).bezeichnung} neu geladen.")
|
|
|
|
|
|
|
|
|
|
|
|
def _on_thema_gewaehlt(self, *_: Any) -> None:
|
|
|
|
|
|
layer = self._ziel_layer()
|
|
|
|
|
|
if layer is None:
|
|
|
|
|
|
return # Wahl gilt für „Basemap hinzufügen“
|
|
|
|
|
|
schluessel = self._gewaehltes_thema()
|
|
|
|
|
|
if themen.thema_des_layers(layer) == schluessel:
|
|
|
|
|
|
return
|
|
|
|
|
|
if not self._aenderungen_klaeren(layer):
|
|
|
|
|
|
self._zeige_thema(layer)
|
|
|
|
|
|
return
|
|
|
|
|
|
try:
|
|
|
|
|
|
themen.wechsle_thema(layer, schluessel)
|
|
|
|
|
|
except ValueError as fehler:
|
|
|
|
|
|
warning(TITEL, str(fehler))
|
|
|
|
|
|
self._zeige_thema(layer)
|
|
|
|
|
|
return
|
|
|
|
|
|
self.aktualisieren()
|
|
|
|
|
|
success(TITEL, f"Thema von „{layer.name()}“: {themen.thema(schluessel).bezeichnung}.")
|
|
|
|
|
|
|
2026-10-02 11:57:10 +02:00
|
|
|
|
# --- Handler: Legende -----------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
def _on_bereich_geaendert(self, *_: Any) -> None:
|
|
|
|
|
|
bereich = self._bereich_combo.currentData()
|
|
|
|
|
|
if bereich in legende.AUSWERTEBEREICHE:
|
|
|
|
|
|
legende.setze_auswertebereich(bereich)
|
|
|
|
|
|
|
|
|
|
|
|
def _on_erzeugen_geaendert(self, aktiv: bool) -> None:
|
|
|
|
|
|
legende.setze_legende_erzeugen(bool(aktiv))
|
|
|
|
|
|
|
|
|
|
|
|
def _on_legende_aktualisieren(self) -> None:
|
|
|
|
|
|
name = self._layout_combo.currentText()
|
|
|
|
|
|
layout = self._projekt().layoutManager().layoutByName(name) if name else None
|
|
|
|
|
|
if layout is None:
|
|
|
|
|
|
warning(TITEL, "Bitte eine Vorlage mit Basemap-Legende wählen.")
|
|
|
|
|
|
return
|
|
|
|
|
|
try:
|
|
|
|
|
|
ergebnis = legende.BasemapLegende(self._projekt()).aktualisiere(layout)
|
|
|
|
|
|
except Exception as fehler:
|
|
|
|
|
|
warning(TITEL, f"Die Basemap-Legende konnte nicht aktualisiert werden: {fehler}")
|
|
|
|
|
|
return
|
|
|
|
|
|
if ergebnis["status"] == "ok":
|
|
|
|
|
|
success(TITEL, ergebnis["meldung"])
|
|
|
|
|
|
elif ergebnis["status"] != "abgebrochen":
|
|
|
|
|
|
info(TITEL, ergebnis["meldung"])
|
|
|
|
|
|
|
2026-10-02 12:33:00 +02:00
|
|
|
|
# --- Handler: Darstellung korrigieren ------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
def _on_punktlinien_korrigieren(self) -> None:
|
2026-10-05 21:27:35 +02:00
|
|
|
|
layer = self._ziel_layer()
|
2026-10-02 12:33:00 +02:00
|
|
|
|
if layer is None:
|
|
|
|
|
|
warning(TITEL, KEIN_LAYER_TEXT)
|
|
|
|
|
|
return
|
|
|
|
|
|
anzahl = korrigiere_punktlinien(layer)
|
|
|
|
|
|
if anzahl:
|
|
|
|
|
|
success(TITEL, f"{anzahl} Punktlinien-Styles korrigiert. Basemap-Legende ggf. aktualisieren.")
|
|
|
|
|
|
else:
|
|
|
|
|
|
info(TITEL, "Keine Punktlinien zu korrigieren.")
|
|
|
|
|
|
|
2026-10-02 11:57:10 +02:00
|
|
|
|
# --- Handler: Stilvorlagen ------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
def _gewaehlte_vorlage(self) -> str:
|
|
|
|
|
|
return str(self._stil_combo.currentData() or "")
|
|
|
|
|
|
|
|
|
|
|
|
def _on_stil_laden(self) -> None:
|
2026-10-05 21:27:35 +02:00
|
|
|
|
layer = self._ziel_layer()
|
2026-10-02 11:57:10 +02:00
|
|
|
|
name = self._gewaehlte_vorlage()
|
|
|
|
|
|
if layer is None or not name:
|
|
|
|
|
|
warning(TITEL, "Kein Basemap-Layer oder keine Stilvorlage gewählt.")
|
|
|
|
|
|
return
|
|
|
|
|
|
if not ask_yes_no("Stilvorlage laden",
|
|
|
|
|
|
f"Darstellung von „{layer.name()}“ durch die Stilvorlage ersetzen?", default=False):
|
|
|
|
|
|
return
|
|
|
|
|
|
unbekannt = self._vorlagen().pruefe_passung(layer, name)
|
|
|
|
|
|
if unbekannt and not ask_yes_no(
|
|
|
|
|
|
"Stilvorlage laden",
|
|
|
|
|
|
f"{len(unbekannt)} Styles der Vorlage gibt es in diesem Layer nicht – die Vorlage stammt "
|
|
|
|
|
|
"vermutlich von einer anderen Basemap-Variante. Trotzdem laden?",
|
|
|
|
|
|
default=False,
|
|
|
|
|
|
):
|
|
|
|
|
|
return
|
|
|
|
|
|
try:
|
|
|
|
|
|
self._vorlagen().laden(layer, name)
|
|
|
|
|
|
except ValueError as fehler:
|
|
|
|
|
|
warning(TITEL, str(fehler))
|
|
|
|
|
|
return
|
|
|
|
|
|
auswahl = self._vorlagen().legendenauswahl(name)
|
|
|
|
|
|
if auswahl is not None:
|
|
|
|
|
|
import json
|
|
|
|
|
|
from sn_basis.functions.variable_wrapper import set_variable
|
|
|
|
|
|
set_variable(legende.AUSWAHL_VAR, json.dumps(auswahl), scope="project")
|
2026-10-05 21:27:35 +02:00
|
|
|
|
themen.merke_stand(layer)
|
2026-10-02 11:57:10 +02:00
|
|
|
|
success(TITEL, "Stilvorlage geladen.")
|
|
|
|
|
|
|
2026-10-05 21:27:35 +02:00
|
|
|
|
def _on_stil_speichern(self, layer: Any | None = None) -> bool:
|
|
|
|
|
|
"""Speichert die Darstellung als Stilvorlage; ``True``, wenn gespeichert wurde."""
|
|
|
|
|
|
layer = layer if layer is not None else self._ziel_layer()
|
2026-10-02 11:57:10 +02:00
|
|
|
|
if layer is None:
|
|
|
|
|
|
warning(TITEL, KEIN_LAYER_TEXT)
|
2026-10-05 21:27:35 +02:00
|
|
|
|
return False
|
2026-10-02 11:57:10 +02:00
|
|
|
|
anzeigename, ok = ask_text("Stilvorlage speichern", "Name der Stilvorlage:",
|
|
|
|
|
|
default_text=self._stil_combo.currentText().replace(" ★", ""))
|
|
|
|
|
|
if not ok or not anzeigename.strip():
|
2026-10-05 21:27:35 +02:00
|
|
|
|
return False
|
2026-10-02 11:57:10 +02:00
|
|
|
|
if self._vorlagen().vorhanden(anzeigename) and not ask_yes_no(
|
|
|
|
|
|
"Stilvorlage speichern", f"Die Stilvorlage „{anzeigename}“ gibt es schon. Ersetzen?", default=False
|
|
|
|
|
|
):
|
2026-10-05 21:27:35 +02:00
|
|
|
|
return False
|
2026-10-02 11:57:10 +02:00
|
|
|
|
try:
|
|
|
|
|
|
self._vorlagen().speichern(layer, anzeigename, legende.lies_auswahl())
|
|
|
|
|
|
except ValueError as fehler:
|
|
|
|
|
|
warning(TITEL, str(fehler))
|
2026-10-05 21:27:35 +02:00
|
|
|
|
return False
|
|
|
|
|
|
themen.merke_stand(layer)
|
2026-10-02 11:57:10 +02:00
|
|
|
|
self.aktualisieren()
|
|
|
|
|
|
success(TITEL, f"Stilvorlage „{anzeigename.strip()}“ gespeichert.")
|
2026-10-05 21:27:35 +02:00
|
|
|
|
return True
|
2026-10-02 11:57:10 +02:00
|
|
|
|
|
|
|
|
|
|
def _on_stil_standard(self) -> None:
|
|
|
|
|
|
name = self._gewaehlte_vorlage()
|
|
|
|
|
|
if not name:
|
|
|
|
|
|
return
|
|
|
|
|
|
try:
|
|
|
|
|
|
self._vorlagen().setze_standard(name)
|
|
|
|
|
|
except ValueError as fehler:
|
|
|
|
|
|
warning(TITEL, str(fehler))
|
|
|
|
|
|
return
|
|
|
|
|
|
self.aktualisieren()
|
|
|
|
|
|
|
|
|
|
|
|
def _on_stil_loeschen(self) -> None:
|
|
|
|
|
|
name = self._gewaehlte_vorlage()
|
|
|
|
|
|
if not name or not ask_yes_no("Stilvorlage löschen",
|
|
|
|
|
|
f"Stilvorlage „{self._stil_combo.currentText()}“ löschen?", default=False):
|
|
|
|
|
|
return
|
|
|
|
|
|
self._vorlagen().loeschen(name)
|
|
|
|
|
|
self.aktualisieren()
|