Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
272bad3866 | ||
|
|
72844cd257 | ||
|
|
a754fcfe34 | ||
|
|
7755e3e8cb | ||
|
|
bc9bb20597 |
@@ -1,3 +1,4 @@
|
||||
- Bezeichner-Bereinigung (Layernamen) um Bindestrich ergänzt und in eine zentrale Funktion `sanitize_bezeichner` (`functions/text_wrapper.py`) ausgelagert, damit Umlaute/Sonderzeichen nicht mehr pro Aufrufstelle vergessen werden (#42)
|
||||
- Landkreis-Dropdown (statt Freitext) in den Projekteigenschaften ergänzt, inkl. Landkreiskennzahl als eigene Projektvariable
|
||||
- Landkreisliste liegt jetzt als JSON (sn_basis/data/landkreise.json) statt hartcodiert vor, damit auch andere Module und Nicht-Entwickler sie pflegen können
|
||||
- Auswahldialog für mehrere BauRaumOderBodenordnungsrecht-Treffer auf Mehrfachauswahl umgestellt (mehrere Objekte gemeinsam laden/verschmelzen)
|
||||
|
||||
@@ -22,6 +22,7 @@ from .ly_metadata_wrapper import (
|
||||
from .ly_style_wrapper import apply_style
|
||||
from .dialog_wrapper import ask_yes_no, ask_overwrite_append_cancel_custom, ask_ergaenzen_entfernen_ersetzen_abbrechen, ask_detailpruefung_oder_vg_laden
|
||||
from .laenderkennung import get_laenderkennung, LAENDERKENNUNGEN
|
||||
from .text_wrapper import sanitize_bezeichner
|
||||
|
||||
from .message_wrapper import (
|
||||
_get_message_bar,
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
"""
|
||||
sn_basis/functions/text_wrapper.py – Bezeichner-Hilfsfunktionen.
|
||||
|
||||
Zentrale Stelle, um Freitext (z. B. ein Thema oder ein Schriftfeldinhalt) in einen
|
||||
technischen Bezeichner (Layername, Dateiname) umzuwandeln. Nicht pro Aufrufstelle
|
||||
ein eigenes Regex schreiben – Umlaute, Unterstrich und Bindestrich werden hier an
|
||||
einer Stelle gepflegt (siehe docs/wissen/fallstricke.md, Issue Plugin_SN_Basis #42).
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
# Buchstaben, Ziffern, deutsche Umlaute/ß, Unterstrich und Bindestrich gelten immer
|
||||
# als zulässig. Wurde in der Vergangenheit wiederholt vergessen, wenn ein neues
|
||||
# Regex direkt im Aufrufer entstand statt diese Funktion zu nutzen.
|
||||
_BEZEICHNER_ERLAUBT = r"A-Za-z0-9_\-ÄäÖöÜüß"
|
||||
|
||||
|
||||
def sanitize_bezeichner(text: str, ersatz: str = "_") -> str:
|
||||
"""Wandelt `text` in einen technischen Bezeichner um.
|
||||
|
||||
Alle Zeichen außerhalb von Buchstaben/Ziffern/Umlauten/ß/Unterstrich/Bindestrich
|
||||
werden durch `ersatz` ersetzt, anschließend werden führende und folgende
|
||||
Vorkommen von `ersatz` entfernt. Gedacht für Layer- und Dateinamen – nicht für
|
||||
Freitext in Schriftfeldern oder der Legende, wo auch andere Zeichen sichtbar
|
||||
bleiben sollen.
|
||||
"""
|
||||
bereinigt = re.sub(rf"[^{_BEZEICHNER_ERLAUBT}]+", ersatz, text)
|
||||
return bereinigt.strip(ersatz)
|
||||
+13
-2
@@ -30,7 +30,6 @@ from sn_basis.modules.linkpruefer import Linkpruefer
|
||||
from sn_basis.modules.layerpruefer import Layerpruefer
|
||||
from sn_basis.modules.stilpruefer import Stilpruefer
|
||||
from sn_basis.modules.excel_importer import ExcelImporter
|
||||
from sn_plan41.modules.listenauswerter import Listenauswerter
|
||||
|
||||
|
||||
SourceType = Literal["service", "database", "excel", "unknown"]
|
||||
@@ -286,7 +285,19 @@ class DataGrabber:
|
||||
}
|
||||
source_dict["rows"].append(result_row)
|
||||
|
||||
# Validierung über Listenauswerter
|
||||
# Validierung über Listenauswerter – Import erst hier (statt am Modul-
|
||||
# anfang), da DataGrabber generisch für alle sn_*-Plugins nutzbar sein
|
||||
# soll und nicht bei jedem Aufruf zwingend sn_plan41 installiert ist;
|
||||
# nur die Excel-Quellenverarbeitung braucht Listenauswerter.
|
||||
try:
|
||||
from sn_plan41.modules.listenauswerter import Listenauswerter
|
||||
except ImportError as exc:
|
||||
raise ImportError(
|
||||
"Die Verarbeitung von Excel-Quellen benötigt das Plugin "
|
||||
"sn_plan41 (sn_plan41.modules.listenauswerter.Listenauswerter), "
|
||||
"das hier nicht installiert ist."
|
||||
) from exc
|
||||
|
||||
listenauswerter = Listenauswerter(self.pruefmanager, self.stil_pruefer or Stilpruefer())
|
||||
validated, validation_results = listenauswerter.validate_rows(source_dict)
|
||||
results.extend(validation_results)
|
||||
|
||||
@@ -30,13 +30,13 @@ from __future__ import annotations
|
||||
from typing import Any, Dict, List, Optional
|
||||
import os
|
||||
import json
|
||||
import re
|
||||
import datetime
|
||||
import sqlite3
|
||||
|
||||
from sn_basis.functions import qgiscore_wrapper as qgiscore
|
||||
from sn_basis.functions.os_wrapper import normalize_path, is_absolute_path
|
||||
from sn_basis.functions.sys_wrapper import get_plugin_root, join_path, file_exists
|
||||
from sn_basis.functions.text_wrapper import sanitize_bezeichner
|
||||
from sn_basis.modules.pruef_ergebnis import pruef_ergebnis
|
||||
|
||||
|
||||
@@ -209,7 +209,7 @@ class Datenschreiber:
|
||||
continue
|
||||
|
||||
layer_name_raw = thema or str(ident)
|
||||
layer_name = re.sub(r"[^A-Za-z0-9_ÄäÖöÜüß]+", "_", layer_name_raw).strip("_")
|
||||
layer_name = sanitize_bezeichner(layer_name_raw)
|
||||
if not layer_name:
|
||||
layer_name = f"layer_{ident}"
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ MM = QgsUnitTypes.LayoutMillimeters
|
||||
|
||||
|
||||
class PrintLayout:
|
||||
"""Erzeugt ein QGIS-Einzelblatt-Layout fuer den Druck."""
|
||||
"""Erzeugt ein QGIS-Einzelblatt-Layout für den Druck."""
|
||||
|
||||
_FRAME_STROKE_WIDTH_MM = 0.5
|
||||
_LEGEND_WIDTH_MM = 180.0
|
||||
@@ -340,7 +340,7 @@ class PrintLayout:
|
||||
("[% @sn_landkreise_proj %]", 16.0, -48.0, 171.0, 4.0, "Format_1", "Landkreis"),
|
||||
("[% @sn_kartenname %]", 16.0, -32.0, 137.0, 12.0, "Format_3", "Kartenname"),
|
||||
("Gefertigt: ", 16.0, -23.0, 81.0, 4.0, "Format_1", "Gefertigt"),
|
||||
("Geprueft: ", 101.0, -23.0, 81.0, 4.0, "Format_1", "Geprüft"),
|
||||
("Geprüft: ", 101.0, -23.0, 81.0, 4.0, "Format_1", "Geprüft"),
|
||||
(
|
||||
"Maßstab: 1 : [%round(map_get(item_variables('Hauptkarte'),'map_scale'),0)%]",
|
||||
16.0,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
"""
|
||||
sn_basis/modules/print_layout_baufreigabe.py - Layout-Erstellung fuer Baufreigabe-Vorlagen.
|
||||
sn_basis/modules/print_layout_baufreigabe.py - Layout-Erstellung für Baufreigabe-Vorlagen.
|
||||
|
||||
Baufreigabe-Layouts verwenden immer feste DIN A3/A4 Seitengroessen im Querformat,
|
||||
ein 120 mm breites Kartenschild (statt 180 mm) und erbenerben die Standard-Logik
|
||||
fuer Hauptkarte, Quellenangabe und Legende vom PrintLayout.
|
||||
Baufreigabe-Layouts verwenden immer feste DIN A3/A4 Seitengrößen im Querformat,
|
||||
ein 120 mm breites Kartenschild (statt 180 mm) und erben die Standard-Logik
|
||||
für Hauptkarte, Quellenangabe und Legende vom PrintLayout.
|
||||
|
||||
Atlas-Integration erfolgt nach Layouterstellung durch externe Konfiguration
|
||||
in der PrintLogic.
|
||||
@@ -32,7 +32,7 @@ MM = QgsUnitTypes.LayoutMillimeters
|
||||
|
||||
|
||||
class PrintLayoutBaufreigabe(PrintLayout):
|
||||
"""Erzeugt QGIS-Einzelblatt-Layouts mit fester DIN A3/A4 Querformat-Groesse und 80mm Kartenschild."""
|
||||
"""Erzeugt QGIS-Einzelblatt-Layouts mit fester DIN A3/A4 Querformat-Größe und 80mm Kartenschild."""
|
||||
|
||||
_FRAME_STROKE_WIDTH_MM = 0.5
|
||||
_KARTENSCHILD_WIDTH_MM = 80.0
|
||||
@@ -41,7 +41,7 @@ class PrintLayoutBaufreigabe(PrintLayout):
|
||||
_GRID_INTERVAL_MAP_UNITS = 500.0
|
||||
|
||||
# DIN-Formate: nur A3 und A4 im Querformat
|
||||
_DIN_A3_LANDSCAPE = (420, 297) # Breite x Hoehe (Querformat)
|
||||
_DIN_A3_LANDSCAPE = (420, 297) # Breite x Höhe (Querformat)
|
||||
_DIN_A4_LANDSCAPE = (297, 210) # Querformat
|
||||
|
||||
_TEXT_FORMAT_TEMPLATES = {
|
||||
@@ -99,25 +99,25 @@ class PrintLayoutBaufreigabe(PrintLayout):
|
||||
fit_extent_to_map: bool = True,
|
||||
atlas_driven: bool = True,
|
||||
) -> Any:
|
||||
"""Erstellt ein Baufreigabe-Layout mit fester DIN A3/A4 Querformat-Groesse.
|
||||
"""Erstellt ein Baufreigabe-Layout mit fester DIN A3/A4 Querformat-Größe.
|
||||
|
||||
Args:
|
||||
name: Name des Layouts
|
||||
din_format: "DIN A3" oder "DIN A4"
|
||||
map_width_mm: Breite der Hauptkarte
|
||||
map_height_mm: Hoehe der Hauptkarte
|
||||
map_height_mm: Höhe der Hauptkarte
|
||||
extent: QgsRectangle der Kartenausdehnung
|
||||
plotmassstab: Plotmassstab (z.B. 5000 fuer 1:5000)
|
||||
plotmassstab: Plotmaßstab (z.B. 5000 für 1:5000)
|
||||
thema: Name des Visibility-Presets (optional)
|
||||
fit_extent_to_map: Extent bei Bedarf auf das Karten-Seitenverhaeltnis erweitern
|
||||
fit_extent_to_map: Extent bei Bedarf auf das Karten-Seitenverhältnis erweitern
|
||||
|
||||
Returns:
|
||||
QgsPrintLayout objektInstance (wird im Layout-Dialog geoeffnet)
|
||||
QgsPrintLayout objektInstance (wird im Layout-Dialog geöffnet)
|
||||
|
||||
Raises:
|
||||
ValueError: Falls Name bereits existiert oder Format ungueltig ist
|
||||
ValueError: Falls Name bereits existiert oder Format ungültig ist
|
||||
"""
|
||||
# Seitenformat auswaehlen (nur A3/A4 im Querformat)
|
||||
# Seitenformat auswählen (nur A3/A4 im Querformat)
|
||||
if din_format == "DIN A3":
|
||||
page_width_mm, page_height_mm = self._DIN_A3_LANDSCAPE
|
||||
elif din_format == "DIN A4":
|
||||
@@ -266,9 +266,9 @@ class PrintLayoutBaufreigabe(PrintLayout):
|
||||
map_top_mm: float,
|
||||
map_height_mm: float,
|
||||
) -> None:
|
||||
"""Erstellt Legende, Quellenangabe und Kartenschild fuer Baufreigabe-Layout.
|
||||
"""Erstellt Legende, Quellenangabe und Kartenschild für Baufreigabe-Layout.
|
||||
|
||||
Angepasst fuer 80mm Kartenschild statt 180mm.
|
||||
Angepasst für 80mm Kartenschild statt 180mm.
|
||||
"""
|
||||
if self._current_layout is None:
|
||||
raise RuntimeError("Kein Layout aktiv.")
|
||||
@@ -279,7 +279,7 @@ class PrintLayoutBaufreigabe(PrintLayout):
|
||||
kartenfenster_untere_rechte_ecke_mm[1] + rel_y_mm,
|
||||
)
|
||||
|
||||
# Legende: 80mm Breite, hoehe adaptive wie Standard
|
||||
# Legende: 80mm Breite, Höhe adaptiv wie Standard
|
||||
legende_x = kartenfenster_untere_rechte_ecke_mm[0] + 10.0
|
||||
legende_height_mm = max(map_height_mm - 122.0, 20.0)
|
||||
legende_y = map_top_mm
|
||||
|
||||
+33
-33
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
sn_basis/modules/print_logic.py - Fachlogik fuer den Druck-Tab (nur Einzelblatt).
|
||||
sn_basis/modules/print_logic.py - Fachlogik für den Druck-Tab (nur Einzelblatt).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -16,7 +16,7 @@ from sn_basis.modules.print_layout_baufreigabe import PrintLayoutBaufreigabe
|
||||
|
||||
|
||||
class AtlasConfig(TypedDict, total=False):
|
||||
"""Strukturierte Konfiguration fuer Atlas-Optionen.
|
||||
"""Strukturierte Konfiguration für Atlas-Optionen.
|
||||
|
||||
Alle Felder sind optional (total=False) und haben vordefinierte Standartwerte.
|
||||
"""
|
||||
@@ -113,7 +113,7 @@ STANDARD_A4_LANDSCAPE_H_MM = 210.0
|
||||
|
||||
|
||||
class PrintLogic:
|
||||
"""Kapselt die Fachlogik fuer den Druck-Tab (ohne Atlas)."""
|
||||
"""Kapselt die Fachlogik für den Druck-Tab (ohne Atlas)."""
|
||||
|
||||
def __init__(self, pruefmanager: Pruefmanager) -> None:
|
||||
self.pruefmanager = pruefmanager
|
||||
@@ -125,8 +125,8 @@ class PrintLogic:
|
||||
|
||||
def _show_target_size_too_small(self) -> dict:
|
||||
self.pruefmanager.zeige_hinweis(
|
||||
"Zielgroesse zu klein",
|
||||
"Die gewaehlte Zielgroesse reicht fuer den Einzelblatt-Druck nicht aus.",
|
||||
"Zielgröße zu klein",
|
||||
"Die gewählte Zielgröße reicht für den Einzelblatt-Druck nicht aus.",
|
||||
)
|
||||
return self._failed_result()
|
||||
|
||||
@@ -348,13 +348,13 @@ class PrintLogic:
|
||||
if int(cast(Any, selected_count())) == 0:
|
||||
self.pruefmanager.zeige_hinweis(
|
||||
"Atlas Layer erstellen",
|
||||
"Auf dem Layer sind keine Features ausgewaehlt.",
|
||||
"Auf dem Layer sind keine Features ausgewählt.",
|
||||
)
|
||||
return None, ""
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Bestehenden Atlaslayer loeschen (optional Wiederverwedung)
|
||||
# Bestehenden Atlaslayer löschen (optional Wiederverwendung)
|
||||
existing_atlas = self._get_existing_layer_by_name("Atlaslayer")
|
||||
if existing_atlas is not None:
|
||||
try:
|
||||
@@ -367,7 +367,7 @@ class PrintLogic:
|
||||
if qgs_vector_layer is None:
|
||||
self.pruefmanager.zeige_hinweis(
|
||||
"Atlas Layer erstellen",
|
||||
"QgsVectorLayer ist nicht verfuegbar.",
|
||||
"QgsVectorLayer ist nicht verfügbar.",
|
||||
)
|
||||
return None, ""
|
||||
|
||||
@@ -392,7 +392,7 @@ class PrintLogic:
|
||||
)
|
||||
return None, ""
|
||||
|
||||
# Ausgewaehlte Features kopieren
|
||||
# Ausgewählte Features kopieren
|
||||
try:
|
||||
get_selected = getattr(source_layer, "selectedFeatures", None)
|
||||
if not callable(get_selected):
|
||||
@@ -400,15 +400,15 @@ class PrintLogic:
|
||||
|
||||
selected_features = list(cast(Any, get_selected()))
|
||||
if not selected_features:
|
||||
raise Exception("Keine Features ausgewaehlt")
|
||||
raise Exception("Keine Features ausgewählt")
|
||||
|
||||
qgs_feature = self._import_qgis_symbol("qgis.core", "QgsFeature")
|
||||
if qgs_feature is None:
|
||||
raise Exception("QgsFeature Symbol nicht verfuegbar")
|
||||
raise Exception("QgsFeature Symbol nicht verfügbar")
|
||||
|
||||
data_provider = getattr(atlas_layer, "dataProvider", lambda: None)()
|
||||
if data_provider is None:
|
||||
raise Exception("dataProvider nicht verfuegbar")
|
||||
raise Exception("dataProvider nicht verfügbar")
|
||||
|
||||
new_features = []
|
||||
for source_feature in selected_features:
|
||||
@@ -470,7 +470,7 @@ class PrintLogic:
|
||||
layout_name: str = "",
|
||||
atlas_config: AtlasConfig | None = None,
|
||||
) -> bool:
|
||||
"""Konfiguriert den Atlas fuer ein Baufreigabe-Layout mit erweiterten Optionen.
|
||||
"""Konfiguriert den Atlas für ein Baufreigabe-Layout mit erweiterten Optionen.
|
||||
|
||||
Wird nach erfolgreicher Baufreigabe-Layout-Erstellung aufgerufen.
|
||||
Setzt den Coverage-Layer (aus sn_abdeckungslayer Variable) und konfiguriert den Atlas
|
||||
@@ -483,7 +483,7 @@ class PrintLogic:
|
||||
project = QgsProject.instance()
|
||||
layout_manager = getattr(project, "layoutManager", lambda: None)()
|
||||
if layout_manager is None:
|
||||
self.pruefmanager.zeige_hinweis("Atlas konfigurieren", "Layout Manager nicht verfuegbar.")
|
||||
self.pruefmanager.zeige_hinweis("Atlas konfigurieren", "Layout Manager nicht verfügbar.")
|
||||
return False
|
||||
|
||||
if not layout_name:
|
||||
@@ -672,7 +672,7 @@ class PrintLogic:
|
||||
if map_canvas is None:
|
||||
self.pruefmanager.zeige_hinweis(
|
||||
"Druckrechteck",
|
||||
"Das Kartenfenster ist nicht verfuegbar.",
|
||||
"Das Kartenfenster ist nicht verfügbar.",
|
||||
)
|
||||
return False
|
||||
|
||||
@@ -684,7 +684,7 @@ class PrintLogic:
|
||||
if None in (qgs_geometry, qgs_rectangle, qgs_wkb_types, qgs_map_tool_emit_point, qgs_rubber_band):
|
||||
self.pruefmanager.zeige_hinweis(
|
||||
"Druckrechteck",
|
||||
"Die Rechteck-Erfassung ist in dieser QGIS-Umgebung nicht verfuegbar.",
|
||||
"Die Rechteck-Erfassung ist in dieser QGIS-Umgebung nicht verfügbar.",
|
||||
)
|
||||
return False
|
||||
|
||||
@@ -736,13 +736,13 @@ class PrintLogic:
|
||||
if width <= 0 or height <= 0:
|
||||
logic.pruefmanager.zeige_hinweis(
|
||||
"Druckrechteck",
|
||||
"Das gezeichnete Rechteck ist ungueltig.",
|
||||
"Das gezeichnete Rechteck ist ungültig.",
|
||||
)
|
||||
else:
|
||||
if logic._store_druckrechteck(layer, rectangle):
|
||||
logic.pruefmanager.zeige_hinweis(
|
||||
"Druckrechteck",
|
||||
"Das Druckrechteck wurde uebernommen.",
|
||||
"Das Druckrechteck wurde übernommen.",
|
||||
)
|
||||
try:
|
||||
self.rubber_band.reset(polygon_geometry)
|
||||
@@ -920,7 +920,7 @@ class PrintLogic:
|
||||
if extent is None:
|
||||
self.pruefmanager.zeige_hinweis(
|
||||
"Druckbereich",
|
||||
"Das aktuelle Kartenfenster liefert keine gueltige Ausdehnung.",
|
||||
"Das aktuelle Kartenfenster liefert keine gültige Ausdehnung.",
|
||||
)
|
||||
return None, None
|
||||
return extent, None
|
||||
@@ -931,7 +931,7 @@ class PrintLogic:
|
||||
if extent is None:
|
||||
self.pruefmanager.zeige_hinweis(
|
||||
"Druckbereich",
|
||||
"Auf dem aktuellen Layer sind keine gueltigen Objekte ausgewaehlt.",
|
||||
"Auf dem aktuellen Layer sind keine gültigen Objekte ausgewählt.",
|
||||
)
|
||||
return None, None
|
||||
return self._buffer_extent(extent, plotmassstab), None
|
||||
@@ -948,7 +948,7 @@ class PrintLogic:
|
||||
if not ergebnis.ok:
|
||||
self.pruefmanager.zeige_hinweis(
|
||||
"Verfahrensgebiets-Layer angeben",
|
||||
"Kein gueltiger Verfahrensgebiets-Layer gefunden. Bitte Layerauswahl im jeweiligen Plugin setzen.",
|
||||
"Kein gültiger Verfahrensgebiets-Layer gefunden. Bitte Layerauswahl im jeweiligen Plugin setzen.",
|
||||
)
|
||||
return None, None
|
||||
|
||||
@@ -1001,12 +1001,12 @@ class PrintLogic:
|
||||
required_map_height_mm: float,
|
||||
max_format: str = "DIN A3",
|
||||
) -> tuple[str, float, float, float, float, bool]:
|
||||
"""Waehlt fuer Baufreigabe ein Blatt im Querformat.
|
||||
"""Wählt für Baufreigabe ein Blatt im Querformat.
|
||||
|
||||
Args:
|
||||
required_map_width_mm: benoetigte Breite der Hauptkarte in mm
|
||||
required_map_height_mm: benoetigte Hoehe der Hauptkarte in mm
|
||||
max_format: maximale Blattgroesse, standardmaessig DIN A3
|
||||
required_map_width_mm: benötigte Breite der Hauptkarte in mm
|
||||
required_map_height_mm: benötigte Höhe der Hauptkarte in mm
|
||||
max_format: maximale Blattgröße, standardmäßig DIN A3
|
||||
|
||||
Returns:
|
||||
(din_format, page_width_mm, page_height_mm, map_w_mm, map_h_mm, fallback_applied)
|
||||
@@ -1029,8 +1029,8 @@ class PrintLogic:
|
||||
if map_w >= required_map_width_mm and map_h >= required_map_height_mm:
|
||||
return din_format, page_w, page_h, map_w, map_h, False
|
||||
|
||||
# Wenn der gewuenschte Ausschnitt nicht passt, verwende das maximal erlaubte Blatt
|
||||
# und erweitere die Hauptkarte auf die verfuegbare Kartenflaeche (zentriert per fit_extent_to_map).
|
||||
# Wenn der gewünschte Ausschnitt nicht passt, verwende das maximal erlaubte Blatt
|
||||
# und erweitere die Hauptkarte auf die verfügbare Kartenfläche (zentriert per fit_extent_to_map).
|
||||
din_format, page_w, page_h = limited_candidates[-1]
|
||||
map_w = max(page_w - BAUFREIGABE_LAYOUT_FIXBREITE_MM, 50.0)
|
||||
map_h = max(page_h - BAUFREIGABE_LAYOUT_FIXHOEHE_MM, 50.0)
|
||||
@@ -1059,7 +1059,7 @@ class PrintLogic:
|
||||
return map_width_mm + fixed_width_mm, map_height_mm + fixed_height_mm
|
||||
|
||||
def _get_required_map_dimensions_mm(self, extent: Any, plotmassstab: float) -> tuple[float, float]:
|
||||
"""Berechnet die benoetigte Kartenfenstergroesse in mm fuer Extent und Massstab."""
|
||||
"""Berechnet die benötigte Kartenfenstergröße in mm für Extent und Maßstab."""
|
||||
if extent is None or not isinstance(plotmassstab, (int, float)) or plotmassstab <= 0:
|
||||
return 0.0, 0.0
|
||||
|
||||
@@ -1077,7 +1077,7 @@ class PrintLogic:
|
||||
required_map_height_mm: float,
|
||||
max_format: str,
|
||||
) -> tuple[float, float, float, float] | None:
|
||||
"""Waehlt das kleinste passende DIN-Blatt fuer das Standardlayout."""
|
||||
"""Wählt das kleinste passende DIN-Blatt für das Standardlayout."""
|
||||
try:
|
||||
max_index = DIN_AUTO_REIHENFOLGE.index(max_format)
|
||||
except ValueError:
|
||||
@@ -1170,7 +1170,7 @@ class PrintLogic:
|
||||
resolved_layer = layer or self._resolve_layer_from_project()
|
||||
|
||||
if kartenname_auswahl not in (KARTENNAME_38, KARTENNAME_41, KARTENNAME_BAUFREIGABE):
|
||||
self.pruefmanager.zeige_hinweis("Kartennamen waehlen", "Kartennamen waehlen")
|
||||
self.pruefmanager.zeige_hinweis("Kartennamen wählen", "Kartennamen wählen")
|
||||
return self._failed_result()
|
||||
|
||||
if massstab_auswahl == MASSSTAB_WIE_KARTENFENSTER:
|
||||
@@ -1191,7 +1191,7 @@ class PrintLogic:
|
||||
massstab_zahl = float(PLOTMASSSTAB_BY_AUSWAHL.get(massstab_auswahl, 0))
|
||||
|
||||
if massstab_zahl <= 0:
|
||||
self.pruefmanager.zeige_hinweis("Massstab fehlt", "Kein gueltiger Massstab angegeben.")
|
||||
self.pruefmanager.zeige_hinweis("Maßstab fehlt", "Kein gültiger Maßstab angegeben.")
|
||||
return self._failed_result()
|
||||
|
||||
extent, layer_for_extent = self._resolve_extent(resolved_layer, druckbereich_auswahl, massstab_zahl)
|
||||
@@ -1262,7 +1262,7 @@ class PrintLogic:
|
||||
|
||||
vorlage_name = (vorlage_name or "").strip() or kartenname
|
||||
|
||||
# Atlas-Status vorab bestimmen, damit er sowohl an create_ als auch configure_ uebergeben wird.
|
||||
# Atlas-Status vorab bestimmen, damit er sowohl an create_ als auch configure_ übergeben wird.
|
||||
atlas_raw_bf = get_variable(ATLAS_ERZEUGEN_UI_VAR, scope="project")
|
||||
atlas_erzeugen_bf = self._is_enabled_flag(atlas_raw_bf)
|
||||
|
||||
@@ -1283,7 +1283,7 @@ class PrintLogic:
|
||||
atlas_driven=atlas_erzeugen_bf,
|
||||
)
|
||||
else:
|
||||
# Standard-Layout: dynamische Groessenanpassung
|
||||
# Standard-Layout: dynamische Größenanpassung
|
||||
PrintLayout().create_single_page_layout(
|
||||
name=vorlage_name,
|
||||
page_width_mm=auto_page_w,
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
"""sn_basis/tests/test_text_wrapper.py
|
||||
|
||||
Unit-Tests für :mod:`sn_basis.functions.text_wrapper`.
|
||||
"""
|
||||
|
||||
import unittest
|
||||
|
||||
from sn_basis.functions.text_wrapper import sanitize_bezeichner
|
||||
|
||||
|
||||
class TestSanitizeBezeichner(unittest.TestCase):
|
||||
def test_umlaute_bleiben_erhalten(self):
|
||||
"""Prüft, dass Umlaute und ß nicht durch den Ersatz entfernt werden."""
|
||||
self.assertEqual(sanitize_bezeichner("Grünfläche"), "Grünfläche")
|
||||
self.assertEqual(sanitize_bezeichner("Straße"), "Straße")
|
||||
|
||||
def test_bindestrich_bleibt_erhalten(self):
|
||||
"""Prüft, dass ein Bindestrich im Bezeichner erhalten bleibt (Issue #42)."""
|
||||
self.assertEqual(sanitize_bezeichner("Wege-Plan"), "Wege-Plan")
|
||||
|
||||
def test_unterstrich_bleibt_erhalten(self):
|
||||
"""Prüft, dass ein Unterstrich im Bezeichner erhalten bleibt."""
|
||||
self.assertEqual(sanitize_bezeichner("thema_flur_1"), "thema_flur_1")
|
||||
|
||||
def test_leerzeichen_wird_durch_ersatz_zusammengefasst(self):
|
||||
"""Prüft, dass Leerzeichen (kein zulässiges Zeichen) zu einem Ersatzzeichen werden."""
|
||||
self.assertEqual(sanitize_bezeichner("Flurstücke Gemarkung"), "Flurstücke_Gemarkung")
|
||||
|
||||
def test_fuehrender_und_folgender_ersatz_wird_entfernt(self):
|
||||
"""Prüft, dass ein Ersatzzeichen am Anfang oder Ende des Ergebnisses entfernt wird."""
|
||||
self.assertEqual(sanitize_bezeichner("!Thema!"), "Thema")
|
||||
|
||||
def test_eigenes_ersatzzeichen_wird_verwendet(self):
|
||||
"""Prüft, dass ein abweichendes Ersatzzeichen anstelle von Unterstrich genutzt wird."""
|
||||
self.assertEqual(sanitize_bezeichner("a b", ersatz="-"), "a-b")
|
||||
|
||||
def test_nur_unzulaessige_zeichen_ergibt_leeren_string(self):
|
||||
"""Prüft, dass ein Bezeichner ganz aus unzulässigen Zeichen zu einem leeren String wird."""
|
||||
self.assertEqual(sanitize_bezeichner("!!!"), "")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
+11
-11
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
sn_basis/ui/tabs/print_tab.py - Zentraler Druck-Tab fuer sn-Plugins.
|
||||
sn_basis/ui/tabs/print_tab.py - Zentraler Druck-Tab für sn-Plugins.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -41,7 +41,7 @@ from sn_basis.modules.print_logic import (
|
||||
|
||||
|
||||
KARTENNAME_VAR = "tab_b_kartenname"
|
||||
KARTENNAME_PLACEHOLDER = "Kartenname waehlen"
|
||||
KARTENNAME_PLACEHOLDER = "Kartenname wählen"
|
||||
KARTENNAME_38 = "§38"
|
||||
KARTENNAME_41 = "§41"
|
||||
KARTENNAME_BAUFREIGABE = "Anlage zur Baufreigabe"
|
||||
@@ -59,7 +59,7 @@ DRUCKBEREICH_OPTIONEN = [
|
||||
|
||||
|
||||
class PrintTab(QWidget):
|
||||
"""UI-Klasse fuer den zentralen Druck-Tab."""
|
||||
"""UI-Klasse für den zentralen Druck-Tab."""
|
||||
|
||||
tab_title = "Druck"
|
||||
|
||||
@@ -130,7 +130,7 @@ class PrintTab(QWidget):
|
||||
self._kartenname_combo = kartenname_combo
|
||||
main_layout.addWidget(kartenname_combo)
|
||||
|
||||
massstab_label = QLabel("Massstab")
|
||||
massstab_label = QLabel("Maßstab")
|
||||
massstab_label.setStyleSheet("font-weight: bold; margin-top: 6px;")
|
||||
main_layout.addWidget(massstab_label)
|
||||
|
||||
@@ -152,7 +152,7 @@ class PrintTab(QWidget):
|
||||
self._thema_combo = thema_combo
|
||||
main_layout.addWidget(thema_combo)
|
||||
|
||||
zielgroesse_label = QLabel("max. Blattgroesse")
|
||||
zielgroesse_label = QLabel("max. Blattgröße")
|
||||
zielgroesse_label.setStyleSheet("font-weight: bold; margin-top: 6px;")
|
||||
main_layout.addWidget(zielgroesse_label)
|
||||
|
||||
@@ -610,7 +610,7 @@ class PrintTab(QWidget):
|
||||
return None
|
||||
|
||||
def _on_atlas_layer_changed(self, layer_or_name: Any) -> None:
|
||||
"""Speichert den ausgewaehlten Atlas-Layer als Layer-ID in Projektvariablen."""
|
||||
"""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
|
||||
@@ -639,10 +639,10 @@ class PrintTab(QWidget):
|
||||
pass
|
||||
|
||||
def _on_auswahl_as_atlas_clicked(self) -> None:
|
||||
"""Handler fuer Button 'Auswahl als Atlas anlegen'.
|
||||
|
||||
"""Handler für Button 'Auswahl als Atlas anlegen'.
|
||||
|
||||
Erstellt einen neuen Layer 'Atlaslayer' aus der aktuellen Feature-Auswahl
|
||||
und traegt ihn ins Atlas-Dropdown ein.
|
||||
und trägt ihn ins Atlas-Dropdown ein.
|
||||
"""
|
||||
if not self.logic or not self.pruefmanager:
|
||||
return
|
||||
@@ -673,11 +673,11 @@ class PrintTab(QWidget):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Fallback nur fuer Mock/klassische ComboBox
|
||||
# Fallback nur für Mock/klassische ComboBox
|
||||
self._populate_atlas_layer_combo()
|
||||
|
||||
def _populate_atlas_layer_combo(self) -> None:
|
||||
"""Fallback-Befuellung, falls kein echtes QgsMapLayerComboBox Verhalten verfuegbar ist."""
|
||||
"""Fallback-Befüllung, falls kein echtes QgsMapLayerComboBox Verhalten verfügbar ist."""
|
||||
if not self._atlas_layer_combo:
|
||||
return
|
||||
|
||||
|
||||
Reference in New Issue
Block a user