Objekte als Templates angelegt

This commit is contained in:
2026-03-23 10:43:37 +01:00
parent 800488fb15
commit 5d7bababd1
+138 -78
View File
@@ -26,9 +26,109 @@ MM = QgsUnitTypes.LayoutMillimeters
class Layout:
"""Erzeugt ein QGIS-Layout für den Druck."""
_OBJECT_TEMPLATES = {
"hauptkarte": {
"id": "Hauptkarte",
},
"quellenangabe": {
"id": "Quellenangabe",
"size_mm": (180.0, 100.0),
"font": ("Arial", 12),
},
"seitenzahl": {
"id": "Seitenzahl",
"size_mm": (60.0, 8.0),
"font": ("Arial", 12),
},
}
_QUELLENANGABE_TEXT = (
"Quelle Geobasisdaten: GeoSN, "
"<a href=\"https://www.govdata.de/dl-de/by-2-0\">dl-de/by-2-0</a><br><br>"
"Quelle Fachdaten: Darstellung auf der Grundlage von Daten und mit Erlaubnis des "
"Sächsischen Landesamtes für Umwelt, Landwirtschaft und Geologie<br><br>"
"Basemap:<br><br>"
"© GeoBasis-DE / <a href=\"https://www.bkg.bund.de\">BKG</a> ([%year($now)%]) "
"<a href=\"https://creativecommons.org/licences/by/4.0/\">CC BY 4.0</a> "
"mit teilweise angepasster Signatur<br>"
)
_SEITENZAHL_TEXT = "Seite [% attribute(@atlas_feature, 'Seitenzahl') %] von [% @atlas_totalfeatures %]"
def __init__(self, project: Any | None = None) -> None:
self.project = project or QgsProject.instance()
def _create_map_item(
self,
layout: Any,
template_name: str,
x_mm: float,
y_mm: float,
width_mm: float,
height_mm: float,
) -> Any:
template = self._OBJECT_TEMPLATES[template_name]
map_item = QgsLayoutItemMap(layout)
map_item.setId(template["id"])
layout.addLayoutItem(map_item)
map_item.attemptMove(QgsLayoutPoint(x_mm, y_mm, MM))
map_item.attemptResize(QgsLayoutSize(width_mm, height_mm, MM))
return map_item
def _create_label_item(
self,
layout: Any,
template_name: str,
text: str,
x_mm: float,
y_mm: float,
*,
font_name: str | None = None,
font_size: int | None = None,
width_mm: float | None = None,
height_mm: float | None = None,
html_mode: bool = False,
expression_enabled: bool = False,
) -> Any:
template = self._OBJECT_TEMPLATES[template_name]
label = QgsLayoutItemLabel(layout)
label.setId(template["id"])
label.setText(text)
if html_mode:
set_mode = getattr(label, "setMode", None)
mode_html = getattr(QgsLayoutItemLabel, "ModeHtml", None)
if callable(set_mode) and mode_html is not None:
set_mode(mode_html)
if expression_enabled:
set_expr_enabled = getattr(label, "setExpressionEnabled", None)
if callable(set_expr_enabled):
try:
set_expr_enabled(True)
except Exception:
pass
template_font_name, template_font_size = template.get("font", ("Arial", 12))
label.setFont(QFont(font_name or template_font_name, font_size or template_font_size))
set_reference_point = getattr(label, "setReferencePoint", None)
lower_left = getattr(getattr(QgsLayoutItem, "ReferencePoint", object), "LowerLeft", None)
if callable(set_reference_point) and lower_left is not None:
set_reference_point(lower_left)
template_width, template_height = template.get("size_mm", (0.0, 0.0))
label.attemptMove(QgsLayoutPoint(x_mm, y_mm, MM))
label.attemptResize(
QgsLayoutSize(
width_mm if width_mm is not None else template_width,
height_mm if height_mm is not None else template_height,
MM,
)
)
layout.addLayoutItem(label)
return label
def create_single_page_layout(
self,
name: str,
@@ -67,17 +167,16 @@ class Layout:
f"[Layout] Kartenbild-Kanten: rechts={map_right_mm:.1f} mm, unten={map_bottom_mm:.1f} mm"
)
hauptkarte = QgsLayoutItemMap(layout)
hauptkarte.setId("Hauptkarte")
hauptkarte = self._create_map_item(
layout,
"hauptkarte",
map_left_mm,
map_top_mm,
map_width_mm,
map_height_mm,
)
print(f"[Layout] QgsLayoutItemMap erstellt")
# Zum Layout hinzufügen, BEVOR Eigenschaften gesetzt werden
layout.addLayoutItem(hauptkarte)
print("[Layout] Hauptkarte zum Layout hinzugefügt")
# Position und Größe setzen
hauptkarte.attemptMove(QgsLayoutPoint(map_left_mm, map_top_mm, MM))
hauptkarte.attemptResize(QgsLayoutSize(map_width_mm, map_height_mm, MM))
print(f"[Layout] Position und Größe gesetzt: pos=({map_left_mm}, {map_top_mm}), size=({map_width_mm:.1f}x{map_height_mm:.1f})")
# Extent und Maßstab setzen
@@ -164,34 +263,20 @@ class Layout:
print(f"[Layout] Hauptkarte vollständig konfiguriert")
quellenangabe = QgsLayoutItemLabel(layout)
quellenangabe.setId("Quellenangabe")
quellenangabe.setText(
"Quelle Geobasisdaten: GeoSN, "
"<a href=\"https://www.govdata.de/dl-de/by-2-0\">dl-de/by-2-0</a><br><br>"
"Quelle Fachdaten: Darstellung auf der Grundlage von Daten und mit Erlaubnis des "
"Sächsischen Landesamtes für Umwelt, Landwirtschaft und Geologie<br><br>"
"Basemap:<br><br>"
"© GeoBasis-DE / <a href=\"https://www.bkg.bund.de\">BKG</a> ([%year($now)%]) "
"<a href=\"https://creativecommons.org/licences/by/4.0/\">CC BY 4.0</a> "
"mit teilweise angepasster Signatur<br>"
)
set_mode = getattr(quellenangabe, "setMode", None)
mode_html = getattr(QgsLayoutItemLabel, "ModeHtml", None)
print(f"[Layout] QgsLayoutItemLabel.ModeHtml={mode_html!r}")
if callable(set_mode) and mode_html is not None:
set_mode(mode_html)
quellenangabe.setFont(QFont("Arial", 12))
set_reference_point = getattr(quellenangabe, "setReferencePoint", None)
lower_left = getattr(getattr(QgsLayoutItem, "ReferencePoint", object), "LowerLeft", None)
print(f"[Layout] QgsLayoutItem.ReferencePoint.LowerLeft={lower_left!r}")
if callable(set_reference_point) and lower_left is not None:
set_reference_point(lower_left)
quellenangabe_x_mm = map_right_mm + 20.0
quellenangabe_y_mm = map_bottom_mm - 120.0
quellenangabe.attemptMove(QgsLayoutPoint(quellenangabe_x_mm, quellenangabe_y_mm, MM))
quellenangabe.attemptResize(QgsLayoutSize(180.0, 100.0, MM))
layout.addLayoutItem(quellenangabe)
self._create_label_item(
layout,
"quellenangabe",
self._QUELLENANGABE_TEXT,
quellenangabe_x_mm,
quellenangabe_y_mm,
html_mode=True,
)
print("[Layout] Quellenangabe zum Layout hinzugefügt")
layout_manager.addLayout(layout)
@@ -238,11 +323,14 @@ class Layout:
map_right_mm = map_left_mm + map_width_mm
map_bottom_mm = map_top_mm + map_height_mm
hauptkarte = QgsLayoutItemMap(layout)
hauptkarte.setId("Hauptkarte")
layout.addLayoutItem(hauptkarte)
hauptkarte.attemptMove(QgsLayoutPoint(map_left_mm, map_top_mm, MM))
hauptkarte.attemptResize(QgsLayoutSize(map_width_mm, map_height_mm, MM))
hauptkarte = self._create_map_item(
layout,
"hauptkarte",
map_left_mm,
map_top_mm,
map_width_mm,
map_height_mm,
)
# Verifiziere mit Units-bewussten Methoden (rect() kann andere Units verwenden).
actual_w = None
@@ -361,51 +449,23 @@ class Layout:
hauptkarte.attemptResize(QgsLayoutSize(map_width_mm, map_height_mm, MM))
print(f"[Layout] Atlas Hauptkarte Größe nach Atlas-Konfiguration erneut gesetzt: {map_width_mm:.1f}mm × {map_height_mm:.1f}mm")
quellenangabe = QgsLayoutItemLabel(layout)
quellenangabe.setId("Quellenangabe")
quellenangabe.setText(
"Quelle Geobasisdaten: GeoSN, "
"<a href=\"https://www.govdata.de/dl-de/by-2-0\">dl-de/by-2-0</a><br><br>"
"Quelle Fachdaten: Darstellung auf der Grundlage von Daten und mit Erlaubnis des "
"Sächsischen Landesamtes für Umwelt, Landwirtschaft und Geologie<br><br>"
"Basemap:<br><br>"
"© GeoBasis-DE / <a href=\"https://www.bkg.bund.de\">BKG</a> ([%year($now)%]) "
"<a href=\"https://creativecommons.org/licences/by/4.0/\">CC BY 4.0</a> "
"mit teilweise angepasster Signatur<br>"
self._create_label_item(
layout,
"quellenangabe",
self._QUELLENANGABE_TEXT,
map_right_mm + 5.0,
map_bottom_mm,
html_mode=True,
)
set_mode = getattr(quellenangabe, "setMode", None)
mode_html = getattr(QgsLayoutItemLabel, "ModeHtml", None)
if callable(set_mode) and mode_html is not None:
set_mode(mode_html)
quellenangabe.setFont(QFont("Arial", 12))
set_reference_point = getattr(quellenangabe, "setReferencePoint", None)
lower_left = getattr(getattr(QgsLayoutItem, "ReferencePoint", object), "LowerLeft", None)
if callable(set_reference_point) and lower_left is not None:
set_reference_point(lower_left)
quellenangabe.attemptMove(QgsLayoutPoint(map_right_mm + 5.0, map_bottom_mm, MM))
quellenangabe.attemptResize(QgsLayoutSize(180.0, 100.0, MM))
layout.addLayoutItem(quellenangabe)
seitenzahl_label = QgsLayoutItemLabel(layout)
seitenzahl_label.setId("Seitenzahl")
seitenzahl_label.setFont(QFont("Arial", 12))
set_expr_enabled = getattr(seitenzahl_label, "setExpressionEnabled", None)
if callable(set_expr_enabled):
try:
set_expr_enabled(True)
except Exception:
pass
# Ausdrucksauswertung robust über [% ... %]-Platzhalter.
seitenzahl_label.setText(
"Seite [% attribute(@atlas_feature, 'Seitenzahl') %] von [% @atlas_totalfeatures %]"
self._create_label_item(
layout,
"seitenzahl",
self._SEITENZAHL_TEXT,
map_right_mm + 5.0,
map_bottom_mm - 2.0,
expression_enabled=True,
)
set_reference_point = getattr(seitenzahl_label, "setReferencePoint", None)
lower_left = getattr(getattr(QgsLayoutItem, "ReferencePoint", object), "LowerLeft", None)
if callable(set_reference_point) and lower_left is not None:
set_reference_point(lower_left)
seitenzahl_label.attemptMove(QgsLayoutPoint(map_right_mm + 5.0, map_bottom_mm - 2.0, MM))
seitenzahl_label.attemptResize(QgsLayoutSize(60.0, 8.0, MM))
layout.addLayoutItem(seitenzahl_label)
atlas = layout.atlas()
if atlas is not None: