Gefunden ueber das neue Skript scripts/pruefe_umlaute.py, das genau dieses Muster (ASCII-Ersatzschreibweise statt Umlaut in String-Inhalten und Kommentaren mit Leerzeichen) erkennt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MneDjzrjmbpQt8udFYxN9e
709 lines
27 KiB
Python
709 lines
27 KiB
Python
"""
|
|
sn_basis/ui/tabs/print_tab.py - Zentraler Druck-Tab für sn-Plugins.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from typing import Any, Optional
|
|
|
|
from sn_basis.functions.qt_wrapper import (
|
|
QWidget,
|
|
QVBoxLayout,
|
|
QLabel,
|
|
QComboBox,
|
|
QCheckBox,
|
|
QHBoxLayout,
|
|
QPushButton,
|
|
QToolButton,
|
|
ToolButtonTextBesideIcon,
|
|
ArrowDown,
|
|
ArrowRight,
|
|
)
|
|
from sn_basis.functions.qgiscore_wrapper import QgsProject, QgsMapLayerProxyModel
|
|
from sn_basis.functions.qgisui_wrapper import iface, QgsMapLayerComboBox
|
|
from sn_basis.functions.variable_wrapper import get_variable, set_variable
|
|
from sn_basis.modules.Pruefmanager import Pruefmanager
|
|
from sn_basis.modules.DataGrabber import DataGrabber
|
|
from sn_basis.modules.print_logic import (
|
|
PrintLogic,
|
|
MASSSTAB_WIE_KARTENFENSTER,
|
|
PLOTMASSSTAB_BY_AUSWAHL,
|
|
THEMA_WIE_KARTENFENSTER,
|
|
DIN_GROESSEN,
|
|
DIN_STANDARD,
|
|
DRUCKBEREICH_VAR,
|
|
DRUCKPUFFER_VAR,
|
|
DRUCKPUFFER_STANDARD_CM,
|
|
DRUCKBEREICH_VERFAHRENSGEBIET,
|
|
DRUCKBEREICH_WIE_KARTENFENSTER,
|
|
DRUCKBEREICH_AKTUELLE_AUSWAHL,
|
|
DRUCKBEREICH_RECHTECK,
|
|
)
|
|
|
|
|
|
KARTENNAME_VAR = "tab_b_kartenname"
|
|
KARTENNAME_PLACEHOLDER = "Kartenname wählen"
|
|
KARTENNAME_38 = "§38"
|
|
KARTENNAME_41 = "§41"
|
|
KARTENNAME_BAUFREIGABE = "Anlage zur Baufreigabe"
|
|
MASSSTAB_VAR = "tab_b_massstab"
|
|
THEMA_VAR = "tab_b_thema"
|
|
ZIELGROESSE_UI_VAR = "tab_b_zielgroesse"
|
|
FORMFAKTOR_UI_VAR = "tab_b_formfaktor"
|
|
ATLAS_ERZEUGEN_VAR = "tab_b_atlas_erzeugen"
|
|
DRUCKBEREICH_OPTIONEN = [
|
|
DRUCKBEREICH_VERFAHRENSGEBIET,
|
|
DRUCKBEREICH_WIE_KARTENFENSTER,
|
|
DRUCKBEREICH_AKTUELLE_AUSWAHL,
|
|
DRUCKBEREICH_RECHTECK,
|
|
]
|
|
|
|
|
|
class PrintTab(QWidget):
|
|
"""UI-Klasse für den zentralen Druck-Tab."""
|
|
|
|
tab_title = "Druck"
|
|
|
|
def __init__(self, parent: Optional[Any] = None):
|
|
super().__init__(parent)
|
|
self.pruefmanager: Optional[Pruefmanager] = None
|
|
self.logic = PrintLogic(self.pruefmanager)
|
|
|
|
|
|
#self.logic: Optional[PrintLogic] = None
|
|
self._kartenname_combo: Optional[Any] = None
|
|
self._massstab_combo: Optional[Any] = None
|
|
self._thema_combo: Optional[Any] = None
|
|
self._theme_signal_connected = False
|
|
self._connected_theme_collection: object = None
|
|
self._zielgroesse_combo: Optional[Any] = None
|
|
self._druckbereich_combo: Optional[Any] = None
|
|
self._endlosrolle_cb: Optional[Any] = None
|
|
self._druckpuffer_button: Optional[Any] = None
|
|
self._btn_vorlage_erstellen: Optional[Any] = None
|
|
self._atlas_layer_combo: Optional[Any] = None
|
|
self._btn_auswahl_as_atlas: Optional[Any] = None
|
|
self._atlas_erzeugen_cb: Optional[Any] = None
|
|
self._atlas_button: Optional[Any] = None
|
|
self._atlas_content: Optional[Any] = None
|
|
|
|
self._build_ui()
|
|
self._restore_state()
|
|
self._connect_theme_collection_signals()
|
|
self._connect_project_signals()
|
|
|
|
def set_services(self, pruefmanager: Pruefmanager, data_grabber: DataGrabber) -> None:
|
|
_ = data_grabber
|
|
self.pruefmanager = pruefmanager
|
|
self.logic = PrintLogic(pruefmanager=self.pruefmanager)
|
|
|
|
if self._kartenname_combo:
|
|
self.logic.set_kartenname_for_auswahl(self._kartenname_combo.currentText())
|
|
if self._massstab_combo:
|
|
self.logic.set_plotmassstab_for_auswahl(
|
|
self._massstab_combo.currentText(),
|
|
self._get_current_canvas_scale(),
|
|
)
|
|
if self._thema_combo:
|
|
self.logic.set_view_for_auswahl(self._thema_combo.currentText())
|
|
if self._zielgroesse_combo:
|
|
self.logic.set_zielgroesse_for_auswahl(self._zielgroesse_combo.currentText())
|
|
if self._druckbereich_combo:
|
|
self.logic.set_druckbereich_for_auswahl(self._druckbereich_combo.currentText())
|
|
if self._endlosrolle_cb:
|
|
self.logic.set_formfaktor(self._endlosrolle_cb.isChecked())
|
|
|
|
def _build_ui(self) -> None:
|
|
main_layout = QVBoxLayout()
|
|
main_layout.setSpacing(4)
|
|
main_layout.setContentsMargins(4, 4, 4, 4)
|
|
|
|
kartenname_label = QLabel("Kartenname")
|
|
kartenname_label.setStyleSheet("font-weight: bold; margin-top: 6px;")
|
|
main_layout.addWidget(kartenname_label)
|
|
|
|
kartenname_combo = QComboBox(self)
|
|
kartenname_combo.addItem(KARTENNAME_PLACEHOLDER)
|
|
kartenname_combo.addItem(KARTENNAME_38)
|
|
kartenname_combo.addItem(KARTENNAME_41)
|
|
kartenname_combo.addItem(KARTENNAME_BAUFREIGABE)
|
|
kartenname_combo.currentTextChanged.connect(self._on_kartenname_changed)
|
|
self._kartenname_combo = kartenname_combo
|
|
main_layout.addWidget(kartenname_combo)
|
|
|
|
massstab_label = QLabel("Maßstab")
|
|
massstab_label.setStyleSheet("font-weight: bold; margin-top: 6px;")
|
|
main_layout.addWidget(massstab_label)
|
|
|
|
massstab_combo = QComboBox(self)
|
|
massstab_combo.addItem(MASSSTAB_WIE_KARTENFENSTER)
|
|
massstab_combo.addItems(list(PLOTMASSSTAB_BY_AUSWAHL.keys()))
|
|
massstab_combo.currentTextChanged.connect(self._on_massstab_changed)
|
|
self._massstab_combo = massstab_combo
|
|
main_layout.addWidget(massstab_combo)
|
|
|
|
thema_label = QLabel("Thema")
|
|
thema_label.setStyleSheet("font-weight: bold; margin-top: 6px;")
|
|
main_layout.addWidget(thema_label)
|
|
|
|
thema_combo = QComboBox(self)
|
|
thema_combo.addItem(THEMA_WIE_KARTENFENSTER)
|
|
thema_combo.addItems(self._get_gespeicherte_themen())
|
|
thema_combo.currentTextChanged.connect(self._on_thema_changed)
|
|
self._thema_combo = thema_combo
|
|
main_layout.addWidget(thema_combo)
|
|
|
|
zielgroesse_label = QLabel("max. Blattgröße")
|
|
zielgroesse_label.setStyleSheet("font-weight: bold; margin-top: 6px;")
|
|
main_layout.addWidget(zielgroesse_label)
|
|
|
|
zielgroesse_row = QHBoxLayout()
|
|
zielgroesse_row.setSpacing(6)
|
|
zielgroesse_combo = QComboBox(self)
|
|
zielgroesse_combo.addItems(list(DIN_GROESSEN.keys()))
|
|
zielgroesse_combo.setCurrentText(DIN_STANDARD)
|
|
zielgroesse_combo.currentTextChanged.connect(self._on_zielgroesse_changed)
|
|
self._zielgroesse_combo = zielgroesse_combo
|
|
zielgroesse_row.addWidget(zielgroesse_combo)
|
|
|
|
endlosrolle_cb = QCheckBox("Endlosrolle", self)
|
|
endlosrolle_cb.setChecked(False)
|
|
endlosrolle_cb.stateChanged.connect(self._on_formfaktor_changed)
|
|
self._endlosrolle_cb = endlosrolle_cb
|
|
zielgroesse_row.addWidget(endlosrolle_cb)
|
|
main_layout.addLayout(zielgroesse_row)
|
|
|
|
druckbereich_row = QHBoxLayout()
|
|
druckbereich_row.setSpacing(6)
|
|
|
|
druckbereich_column = QVBoxLayout()
|
|
druckbereich_column.setSpacing(4)
|
|
druckbereich_column.setContentsMargins(0, 0, 0, 0)
|
|
|
|
druckbereich_label = QLabel("Druckbereich")
|
|
druckbereich_label.setStyleSheet("font-weight: bold; margin-top: 6px;")
|
|
druckbereich_column.addWidget(druckbereich_label)
|
|
|
|
druckbereich_combo = QComboBox(self)
|
|
druckbereich_combo.addItems(DRUCKBEREICH_OPTIONEN)
|
|
druckbereich_combo.currentTextChanged.connect(self._on_druckbereich_changed)
|
|
self._druckbereich_combo = druckbereich_combo
|
|
druckbereich_column.addWidget(druckbereich_combo)
|
|
druckbereich_row.addLayout(druckbereich_column, 1)
|
|
|
|
druckpuffer_column = QVBoxLayout()
|
|
druckpuffer_column.setSpacing(4)
|
|
druckpuffer_column.setContentsMargins(0, 0, 0, 0)
|
|
|
|
druckpuffer_label = QLabel("Kartenpuffer")
|
|
druckpuffer_label.setStyleSheet("font-weight: bold; margin-top: 6px;")
|
|
druckpuffer_column.addWidget(druckpuffer_label)
|
|
|
|
druckpuffer_button = QPushButton(self._format_druckpuffer_label(DRUCKPUFFER_STANDARD_CM), self)
|
|
druckpuffer_button.setToolTip("Puffer")
|
|
druckpuffer_button.clicked.connect(self._on_druckpuffer_clicked)
|
|
self._druckpuffer_button = druckpuffer_button
|
|
druckpuffer_column.addWidget(druckpuffer_button)
|
|
druckbereich_row.addLayout(druckpuffer_column)
|
|
|
|
main_layout.addLayout(druckbereich_row)
|
|
|
|
# Atlas-Bereich (einklappbar, analog Tab A)
|
|
atlas_button = QToolButton()
|
|
atlas_button.setText("Atlas")
|
|
atlas_button.setCheckable(True)
|
|
atlas_button.setChecked(False)
|
|
atlas_button.setToolButtonStyle(ToolButtonTextBesideIcon)
|
|
atlas_button.setArrowType(ArrowRight)
|
|
atlas_button.setStyleSheet("font-weight: bold; margin-top: 6px;")
|
|
atlas_button.toggled.connect(self._toggle_atlas)
|
|
self._atlas_button = atlas_button
|
|
main_layout.addWidget(atlas_button)
|
|
|
|
atlas_content = QWidget()
|
|
atlas_layout = QVBoxLayout()
|
|
atlas_layout.setSpacing(4)
|
|
atlas_layout.setContentsMargins(10, 4, 4, 4)
|
|
|
|
atlas_erzeugen_cb = QCheckBox("Atlas erzeugen", self)
|
|
atlas_erzeugen_cb.setChecked(True)
|
|
atlas_erzeugen_cb.stateChanged.connect(self._on_atlas_erzeugen_changed)
|
|
self._atlas_erzeugen_cb = atlas_erzeugen_cb
|
|
atlas_layout.addWidget(atlas_erzeugen_cb)
|
|
|
|
atlas_layer_label = QLabel("Abdeckungslayer", self)
|
|
atlas_layout.addWidget(atlas_layer_label)
|
|
|
|
atlas_layer_combo = QgsMapLayerComboBox(self)
|
|
set_filters = getattr(atlas_layer_combo, "setFilters", None)
|
|
if callable(set_filters):
|
|
set_filters(QgsMapLayerProxyModel.VectorLayer)
|
|
layer_changed = getattr(atlas_layer_combo, "layerChanged", None)
|
|
if layer_changed is not None:
|
|
try:
|
|
layer_changed.connect(self._on_atlas_layer_changed)
|
|
except Exception:
|
|
pass
|
|
self._atlas_layer_combo = atlas_layer_combo
|
|
atlas_layout.addWidget(atlas_layer_combo)
|
|
|
|
btn_auswahl_as_atlas = QPushButton("Auswahl als Atlas anlegen", self)
|
|
btn_auswahl_as_atlas.clicked.connect(self._on_auswahl_as_atlas_clicked)
|
|
self._btn_auswahl_as_atlas = btn_auswahl_as_atlas
|
|
atlas_layout.addWidget(btn_auswahl_as_atlas)
|
|
|
|
atlas_content.setLayout(atlas_layout)
|
|
atlas_content.setVisible(False)
|
|
self._atlas_content = atlas_content
|
|
main_layout.addWidget(atlas_content)
|
|
|
|
btn_vorlage_erstellen = QPushButton("Vorlage erstellen", self)
|
|
btn_vorlage_erstellen.clicked.connect(self._on_vorlage_erstellen)
|
|
self._btn_vorlage_erstellen = btn_vorlage_erstellen
|
|
main_layout.addWidget(btn_vorlage_erstellen)
|
|
|
|
main_layout.addStretch(1)
|
|
self.setLayout(main_layout)
|
|
|
|
def _restore_state(self) -> None:
|
|
if not self._kartenname_combo or not self._massstab_combo or not self._thema_combo:
|
|
return
|
|
if not self._zielgroesse_combo or not self._endlosrolle_cb:
|
|
return
|
|
if not self._druckbereich_combo or not self._druckpuffer_button:
|
|
return
|
|
|
|
saved_kartenname = get_variable(KARTENNAME_VAR, scope="project")
|
|
if saved_kartenname in (KARTENNAME_38, KARTENNAME_41, KARTENNAME_BAUFREIGABE):
|
|
self._kartenname_combo.setCurrentText(saved_kartenname)
|
|
else:
|
|
self._kartenname_combo.setCurrentText(KARTENNAME_PLACEHOLDER)
|
|
|
|
saved_massstab = get_variable(MASSSTAB_VAR, scope="project")
|
|
valid_massstaebe = [MASSSTAB_WIE_KARTENFENSTER, *PLOTMASSSTAB_BY_AUSWAHL.keys()]
|
|
if saved_massstab in valid_massstaebe:
|
|
self._massstab_combo.setCurrentText(saved_massstab)
|
|
else:
|
|
self._massstab_combo.setCurrentText(MASSSTAB_WIE_KARTENFENSTER)
|
|
|
|
aktuelle_themen = [THEMA_WIE_KARTENFENSTER, *self._get_gespeicherte_themen()]
|
|
self._thema_combo.clear()
|
|
self._thema_combo.addItems(aktuelle_themen)
|
|
|
|
saved_thema = get_variable(THEMA_VAR, scope="project")
|
|
if saved_thema in aktuelle_themen:
|
|
self._thema_combo.setCurrentText(saved_thema)
|
|
else:
|
|
self._thema_combo.setCurrentText(THEMA_WIE_KARTENFENSTER)
|
|
|
|
saved_zielgroesse = get_variable(ZIELGROESSE_UI_VAR, scope="project")
|
|
if saved_zielgroesse in DIN_GROESSEN:
|
|
self._zielgroesse_combo.setCurrentText(saved_zielgroesse)
|
|
else:
|
|
self._zielgroesse_combo.setCurrentText(DIN_STANDARD)
|
|
|
|
saved_formfaktor = get_variable(FORMFAKTOR_UI_VAR, scope="project")
|
|
self._endlosrolle_cb.setChecked(saved_formfaktor == "Endlosrolle")
|
|
|
|
saved_druckbereich = get_variable(DRUCKBEREICH_VAR, scope="project")
|
|
if saved_druckbereich in DRUCKBEREICH_OPTIONEN:
|
|
self._druckbereich_combo.setCurrentText(saved_druckbereich)
|
|
else:
|
|
self._druckbereich_combo.setCurrentText(DRUCKBEREICH_VERFAHRENSGEBIET)
|
|
|
|
saved_druckpuffer = get_variable(DRUCKPUFFER_VAR, scope="project")
|
|
try:
|
|
druckpuffer_cm = int(str(saved_druckpuffer).strip())
|
|
except (TypeError, ValueError):
|
|
druckpuffer_cm = DRUCKPUFFER_STANDARD_CM
|
|
self._druckpuffer_button.setText(self._format_druckpuffer_label(max(0, druckpuffer_cm)))
|
|
|
|
if self._atlas_erzeugen_cb:
|
|
atlas_raw = get_variable(ATLAS_ERZEUGEN_VAR, scope="project")
|
|
atlas_checked = True if atlas_raw in (None, "") else str(atlas_raw).strip().lower() in {
|
|
"1",
|
|
"true",
|
|
"ja",
|
|
"yes",
|
|
"on",
|
|
}
|
|
self._atlas_erzeugen_cb.setChecked(atlas_checked)
|
|
self._on_atlas_erzeugen_changed(1 if atlas_checked else 0)
|
|
|
|
self._restore_atlas_layer_selection()
|
|
|
|
def _on_kartenname_changed(self, value: str) -> None:
|
|
if value in (KARTENNAME_38, KARTENNAME_41, KARTENNAME_BAUFREIGABE):
|
|
set_variable(KARTENNAME_VAR, value, scope="project")
|
|
else:
|
|
set_variable(KARTENNAME_VAR, "", scope="project")
|
|
|
|
# Atlas-Bereich automatisch ein-/ausklappen je nach Kartenname.
|
|
if self._atlas_button:
|
|
self._atlas_button.setChecked(value == KARTENNAME_BAUFREIGABE)
|
|
|
|
if self.logic:
|
|
self.logic.set_kartenname_for_auswahl(value)
|
|
|
|
def _on_massstab_changed(self, value: str) -> None:
|
|
set_variable(MASSSTAB_VAR, value, scope="project")
|
|
if self.logic:
|
|
self.logic.set_plotmassstab_for_auswahl(value, self._get_current_canvas_scale())
|
|
|
|
def _on_thema_changed(self, value: str) -> None:
|
|
set_variable(THEMA_VAR, value, scope="project")
|
|
if self.logic:
|
|
self.logic.set_view_for_auswahl(value)
|
|
|
|
def _on_zielgroesse_changed(self, value: str) -> None:
|
|
set_variable(ZIELGROESSE_UI_VAR, value, scope="project")
|
|
if self.logic:
|
|
self.logic.set_zielgroesse_for_auswahl(value)
|
|
|
|
def _on_formfaktor_changed(self, state: int) -> None:
|
|
checked = bool(state)
|
|
set_variable(FORMFAKTOR_UI_VAR, "Endlosrolle" if checked else "Blatt", scope="project")
|
|
if self.logic:
|
|
self.logic.set_formfaktor(checked)
|
|
|
|
def _on_druckbereich_changed(self, value: str) -> None:
|
|
if value not in DRUCKBEREICH_OPTIONEN:
|
|
value = DRUCKBEREICH_VERFAHRENSGEBIET
|
|
set_variable(DRUCKBEREICH_VAR, value, scope="project")
|
|
if self.logic:
|
|
self.logic.set_druckbereich_for_auswahl(value)
|
|
if value == DRUCKBEREICH_RECHTECK:
|
|
self.logic.activate_druckrechteck_capture()
|
|
|
|
def _on_atlas_erzeugen_changed(self, state: int) -> None:
|
|
enabled = bool(state)
|
|
set_variable(ATLAS_ERZEUGEN_VAR, "1" if enabled else "0", scope="project")
|
|
|
|
if self._atlas_layer_combo:
|
|
set_enabled = getattr(self._atlas_layer_combo, "setEnabled", None)
|
|
if callable(set_enabled):
|
|
try:
|
|
set_enabled(enabled)
|
|
except Exception:
|
|
pass
|
|
|
|
if self._btn_auswahl_as_atlas:
|
|
self._btn_auswahl_as_atlas.setEnabled(enabled)
|
|
|
|
def _on_druckpuffer_clicked(self) -> None:
|
|
if not self.pruefmanager:
|
|
return
|
|
|
|
current_value = get_variable(DRUCKPUFFER_VAR, scope="project") or str(DRUCKPUFFER_STANDARD_CM)
|
|
text_value, bestaetigt = self.pruefmanager.frage_text(
|
|
"Puffer um den Druckbereich",
|
|
"Puffer um den Druckbereich",
|
|
default_text=str(current_value),
|
|
)
|
|
if not bestaetigt:
|
|
return
|
|
|
|
try:
|
|
puffer_value = int(str(text_value).strip())
|
|
except (TypeError, ValueError):
|
|
self.pruefmanager.zeige_hinweis(
|
|
"Puffer um den Druckbereich",
|
|
"Der Puffer muss als ganze Zahl eingegeben werden.",
|
|
)
|
|
return
|
|
|
|
if puffer_value < 0:
|
|
self.pruefmanager.zeige_hinweis(
|
|
"Puffer um den Druckbereich",
|
|
"Der Puffer darf nicht negativ sein.",
|
|
)
|
|
return
|
|
|
|
set_variable(DRUCKPUFFER_VAR, str(puffer_value), scope="project")
|
|
if self._druckpuffer_button:
|
|
self._druckpuffer_button.setText(self._format_druckpuffer_label(puffer_value))
|
|
|
|
def _format_druckpuffer_label(self, value_cm: int) -> str:
|
|
return f"{value_cm} cm"
|
|
|
|
def _on_vorlage_erstellen(self) -> None:
|
|
if not self.logic or not self.pruefmanager:
|
|
return
|
|
|
|
self.logic.druckvorlage_anlegen(
|
|
layer=None,
|
|
kartenname_auswahl=self._kartenname_combo.currentText() if self._kartenname_combo else "",
|
|
massstab_auswahl=self._massstab_combo.currentText() if self._massstab_combo else "",
|
|
zielgroesse=self._zielgroesse_combo.currentText() if self._zielgroesse_combo else DIN_STANDARD,
|
|
formfaktor=self._endlosrolle_cb.isChecked() if self._endlosrolle_cb else False,
|
|
druckbereich_auswahl=self._druckbereich_combo.currentText() if self._druckbereich_combo else DRUCKBEREICH_VERFAHRENSGEBIET,
|
|
)
|
|
|
|
def _disconnect_project_signals(self) -> None:
|
|
try:
|
|
project = QgsProject.instance()
|
|
except Exception:
|
|
return
|
|
|
|
if project is None:
|
|
return
|
|
|
|
for signal_name in ("readProject", "newProjectCreated", "cleared"):
|
|
signal = getattr(project, signal_name, None)
|
|
if signal is None:
|
|
continue
|
|
try:
|
|
signal.disconnect(self._on_project_changed)
|
|
except Exception:
|
|
pass
|
|
|
|
def cleanup(self) -> None:
|
|
"""Trennt Signalverbindungen vor dem Schliessen des Tabs."""
|
|
self._disconnect_theme_collection_signals()
|
|
self._disconnect_project_signals()
|
|
|
|
def _connect_project_signals(self) -> None:
|
|
try:
|
|
project = QgsProject.instance()
|
|
except Exception:
|
|
return
|
|
|
|
if project is None:
|
|
return
|
|
|
|
for signal_name in ("readProject", "newProjectCreated", "cleared"):
|
|
signal = getattr(project, signal_name, None)
|
|
if signal is None:
|
|
continue
|
|
try:
|
|
signal.connect(self._on_project_changed)
|
|
except Exception:
|
|
pass
|
|
|
|
def _on_project_changed(self, *args) -> None:
|
|
_ = args
|
|
self._disconnect_theme_collection_signals()
|
|
self._theme_signal_connected = False
|
|
self._connect_theme_collection_signals()
|
|
self._restore_state()
|
|
|
|
def _toggle_atlas(self, checked: bool) -> None:
|
|
if self._atlas_button:
|
|
self._atlas_button.setArrowType(ArrowDown if checked else ArrowRight)
|
|
if self._atlas_content:
|
|
self._atlas_content.setVisible(checked)
|
|
|
|
def _restore_atlas_layer_selection(self) -> None:
|
|
if not self._atlas_layer_combo:
|
|
return
|
|
|
|
layer_id = (get_variable("sn_abdeckungslayer", scope="project") or "").strip()
|
|
if not layer_id:
|
|
return
|
|
|
|
try:
|
|
layer = QgsProject.instance().mapLayer(layer_id)
|
|
if layer is None:
|
|
return
|
|
|
|
set_current_layer = getattr(self._atlas_layer_combo, "setLayer", None)
|
|
if callable(set_current_layer):
|
|
set_current_layer(layer)
|
|
return
|
|
|
|
set_current_layer = getattr(self._atlas_layer_combo, "setCurrentLayer", None)
|
|
if callable(set_current_layer):
|
|
set_current_layer(layer)
|
|
except Exception:
|
|
pass
|
|
|
|
def _disconnect_theme_collection_signals(self) -> None:
|
|
collection = self._connected_theme_collection
|
|
if collection is not None:
|
|
for signal_name in ("mapThemesChanged", "changed", "themeChanged"):
|
|
try:
|
|
signal = getattr(collection, signal_name, None)
|
|
except RuntimeError:
|
|
break
|
|
except Exception:
|
|
continue
|
|
if signal is None:
|
|
continue
|
|
try:
|
|
signal.disconnect(self._refresh_thema_combo_live)
|
|
except Exception:
|
|
pass
|
|
self._connected_theme_collection = None
|
|
self._theme_signal_connected = False
|
|
|
|
def _connect_theme_collection_signals(self) -> None:
|
|
if self._theme_signal_connected:
|
|
return
|
|
|
|
try:
|
|
theme_collection = QgsProject.instance().mapThemeCollection()
|
|
except Exception:
|
|
return
|
|
|
|
if theme_collection is None:
|
|
return
|
|
|
|
connected_any = False
|
|
for signal_name in ("mapThemesChanged", "changed", "themeChanged"):
|
|
signal = getattr(theme_collection, signal_name, None)
|
|
if signal is None:
|
|
continue
|
|
try:
|
|
signal.connect(self._refresh_thema_combo_live)
|
|
connected_any = True
|
|
except Exception:
|
|
pass
|
|
|
|
if connected_any:
|
|
self._connected_theme_collection = theme_collection
|
|
self._theme_signal_connected = connected_any
|
|
|
|
def _refresh_thema_combo_live(self, *args) -> None:
|
|
_ = args
|
|
if not self._thema_combo:
|
|
return
|
|
|
|
vorherige_auswahl = self._thema_combo.currentText() or THEMA_WIE_KARTENFENSTER
|
|
eintraege = [THEMA_WIE_KARTENFENSTER, *self._get_gespeicherte_themen()]
|
|
|
|
self._thema_combo.blockSignals(True)
|
|
self._thema_combo.clear()
|
|
self._thema_combo.addItems(eintraege)
|
|
|
|
if vorherige_auswahl in eintraege:
|
|
self._thema_combo.setCurrentText(vorherige_auswahl)
|
|
else:
|
|
self._thema_combo.setCurrentText(THEMA_WIE_KARTENFENSTER)
|
|
self._thema_combo.blockSignals(False)
|
|
|
|
self._on_thema_changed(self._thema_combo.currentText())
|
|
|
|
def _get_gespeicherte_themen(self) -> list[str]:
|
|
try:
|
|
theme_collection = QgsProject.instance().mapThemeCollection()
|
|
if theme_collection is None:
|
|
return []
|
|
themes = theme_collection.mapThemes()
|
|
except Exception:
|
|
return []
|
|
|
|
namen: list[str] = []
|
|
for theme_name in themes:
|
|
name = str(theme_name or "").strip()
|
|
if name and name not in namen:
|
|
namen.append(name)
|
|
|
|
return namen
|
|
|
|
def _get_current_canvas_scale(self) -> float | None:
|
|
try:
|
|
canvas = iface.mapCanvas()
|
|
if canvas is None:
|
|
return None
|
|
scale = canvas.scale()
|
|
return float(scale) if scale else None
|
|
except Exception:
|
|
return None
|
|
|
|
def _on_atlas_layer_changed(self, layer_or_name: Any) -> None:
|
|
"""Speichert den ausgewählten Atlas-Layer als Layer-ID in Projektvariablen."""
|
|
if layer_or_name is None or layer_or_name == "":
|
|
set_variable("sn_abdeckungslayer", "", scope="project")
|
|
return
|
|
|
|
# Standardfall QgsMapLayerComboBox: echtes Layer-Objekt
|
|
layer_id_getter = getattr(layer_or_name, "id", None)
|
|
if callable(layer_id_getter):
|
|
layer_id = layer_id_getter() or ""
|
|
set_variable("sn_abdeckungslayer", layer_id, scope="project")
|
|
return
|
|
|
|
# Fallback: ggf. Name aus Mock/anderen Widgets
|
|
value = str(layer_or_name).strip()
|
|
if not value:
|
|
set_variable("sn_abdeckungslayer", "", scope="project")
|
|
return
|
|
|
|
try:
|
|
project = QgsProject.instance()
|
|
map_layers = project.mapLayers()
|
|
for layer_id, layer in map_layers.items():
|
|
if getattr(layer, "name", lambda: "")() == value:
|
|
set_variable("sn_abdeckungslayer", layer_id, scope="project")
|
|
return
|
|
except Exception:
|
|
pass
|
|
|
|
def _on_auswahl_as_atlas_clicked(self) -> None:
|
|
"""Handler für Button 'Auswahl als Atlas anlegen'.
|
|
|
|
Erstellt einen neuen Layer 'Atlaslayer' aus der aktuellen Feature-Auswahl
|
|
und trägt ihn ins Atlas-Dropdown ein.
|
|
"""
|
|
if not self.logic or not self.pruefmanager:
|
|
return
|
|
|
|
atlas_layer, layer_id = self.logic.create_atlas_layer_from_selection()
|
|
if atlas_layer is None or not layer_id:
|
|
return
|
|
|
|
if self._atlas_button and self._atlas_content:
|
|
self._atlas_button.setChecked(True)
|
|
self._toggle_atlas(True)
|
|
|
|
# Neu erstellten Layer im Layer-Combo setzen
|
|
if self._atlas_layer_combo:
|
|
set_current_layer = getattr(self._atlas_layer_combo, "setLayer", None)
|
|
if callable(set_current_layer):
|
|
try:
|
|
set_current_layer(atlas_layer)
|
|
return
|
|
except Exception:
|
|
pass
|
|
|
|
set_current_layer = getattr(self._atlas_layer_combo, "setCurrentLayer", None)
|
|
if callable(set_current_layer):
|
|
try:
|
|
set_current_layer(atlas_layer)
|
|
return
|
|
except Exception:
|
|
pass
|
|
|
|
# Fallback nur für Mock/klassische ComboBox
|
|
self._populate_atlas_layer_combo()
|
|
|
|
def _populate_atlas_layer_combo(self) -> None:
|
|
"""Fallback-Befüllung, falls kein echtes QgsMapLayerComboBox Verhalten verfügbar ist."""
|
|
if not self._atlas_layer_combo:
|
|
return
|
|
|
|
clear_fn = getattr(self._atlas_layer_combo, "clear", None)
|
|
add_item_fn = getattr(self._atlas_layer_combo, "addItem", None)
|
|
if not callable(clear_fn) or not callable(add_item_fn):
|
|
return
|
|
|
|
self._atlas_layer_combo.blockSignals(True)
|
|
clear_fn()
|
|
add_item_fn("")
|
|
|
|
try:
|
|
project = QgsProject.instance()
|
|
map_layers = getattr(project, "mapLayers", None)
|
|
if not callable(map_layers):
|
|
self._atlas_layer_combo.blockSignals(False)
|
|
return
|
|
|
|
layers = map_layers().values() if hasattr(map_layers(), "values") else map_layers()
|
|
for layer in layers:
|
|
layer_name = getattr(layer, "name", lambda: None)()
|
|
if layer_name and layer_name not in ("", "Druckrechteck"):
|
|
add_item_fn(layer_name)
|
|
except Exception:
|
|
pass
|
|
|
|
self._atlas_layer_combo.blockSignals(False)
|