Fix/komponenta jako zaklad (#35)

* čištění amcr_tools.py od zbytečných prvků souvisejících se standalone tabulkou komponent

* aplikace nové logiky přípravy dat v případě požadavku na komponenty

* nové aliasy + přidání dat komponent do finálních tabulek

* oprava pořadí polí v tabulce
This commit is contained in:
2026-05-16 14:18:17 +02:00
committed by GitHub
parent 54f154b264
commit 499b3b3f0a
+42 -79
View File
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from qgis.core import (QgsProject, QgsVectorLayer, QgsFeature, QgsGeometry, from qgis.core import (QgsProject, QgsVectorLayer, QgsFeature, QgsGeometry,
QgsField, QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsField, QgsCoordinateReferenceSystem, QgsCoordinateTransform,
QgsWkbTypes, QgsPolymorphicRelation, QgsEditorWidgetSetup, Qgis) QgsWkbTypes, Qgis)
from qgis.utils import iface from qgis.utils import iface
from qgis.PyQt.QtCore import Qt, QMetaType from qgis.PyQt.QtCore import Qt, QMetaType
from qgis.PyQt.QtWidgets import QApplication from qgis.PyQt.QtWidgets import QApplication
@@ -86,7 +86,7 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false")
current_page = 0 current_page = 0
BATCH_DOCS = 500 # Records per API request BATCH_DOCS = 500 # Records per API request
MAX_LIMIT = 20000 # Safety limit to prevent QGIS from freezing MAX_LIMIT = 20000 # Safety limit to prevent QGIS from freezing
feats_k = [] # List for component features (non-spatial)
seen_ids = set() seen_ids = set()
target_pian_ids_count = 0 target_pian_ids_count = 0
@@ -146,7 +146,6 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false")
# pian_lookup maps a Geometry ID (PIAN) to a list of its associated metadata # pian_lookup maps a Geometry ID (PIAN) to a list of its associated metadata
pian_lookup = {} pian_lookup = {}
komponenty_lookup = {}
target_pian_ids = set() target_pian_ids = set()
actions_with_geom = 0 actions_with_geom = 0
@@ -247,23 +246,35 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false")
dj_pian_value = dj_pian.get('id') dj_pian_value = dj_pian.get('id')
if dj_pian_value: if dj_pian_value:
target_pian_ids.add(dj_pian_value) target_pian_ids.add(dj_pian_value)
target_pian_ids_count += 1
if dj_pian_value not in pian_lookup: if dj_pian_value not in pian_lookup:
pian_lookup[dj_pian_value] = [] pian_lookup[dj_pian_value] = []
pian_lookup[dj_pian_value].append(dj_meta)
# Parse non-spatial components if requested (for relational tables)
if komponenty == "true": if komponenty == "true":
# One feature per component — all data on a single row, no relations needed
komps = dj.get('dj_komponenta', []) komps = dj.get('dj_komponenta', [])
for komp in komps: if komps:
komp_temp = [ for komp in komps:
komp.get('ident_cely', ""), komp_meta = {
komp.get('komponenta_areal', {}).get('value', ""), **dj_meta,
komp.get('komponenta_obdobi', {}).get('value', "") 'komponenta_id': komp.get('ident_cely', ""),
] 'komponenta_areal': komp.get('komponenta_areal', {}).get('value', ""),
if dj_id not in komponenty_lookup: 'komponenta_obdobi': komp.get('komponenta_obdobi', {}).get('value', ""),
komponenty_lookup[dj_id] = [] }
komponenty_lookup[dj_id].append(komp_temp) pian_lookup[dj_pian_value].append(komp_meta)
target_pian_ids_count += 1
else:
# DJ without components — still include with empty component fields
empty_meta = {
**dj_meta,
'komponenta_id': "",
'komponenta_areal': "",
'komponenta_obdobi': "",
}
pian_lookup[dj_pian_value].append(empty_meta)
target_pian_ids_count += 1
else:
target_pian_ids_count += 1
pian_lookup[dj_pian_value].append(dj_meta)
if not target_pian_ids: if not target_pian_ids:
@@ -382,25 +393,18 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false")
"popis_lokality": "Popis lokality", "popis_lokality": "Popis lokality",
"typ_lokality": "Typ lokality", "typ_lokality": "Typ lokality",
"druh_lokality": "Druh lokality", "druh_lokality": "Druh lokality",
"zachovalost": "Zachovalost" "zachovalost": "Zachovalost",
"komponenta": "Komponenta",
"komponenta_areal": "Areál",
"komponenta_obdobi": "Období",
} }
# Create a non-spatial table for components if requested
if komponenty == "true": if komponenty == "true":
vl_komponenty = QgsVectorLayer("None", "AMCR Komponenty", "memory") cols += [
pr = vl_komponenty.dataProvider()
komponenty_cols = [
QgsField("komponenta", QMetaType.Type.QString), QgsField("komponenta", QMetaType.Type.QString),
QgsField("dj_id", QMetaType.Type.QString),
QgsField("komponenta_areal", QMetaType.Type.QString), QgsField("komponenta_areal", QMetaType.Type.QString),
QgsField("komponenta_obdobi", QMetaType.Type.QString), QgsField("komponenta_obdobi", QMetaType.Type.QString),
QgsField("vrstva", QMetaType.Type.QString)
] ]
pr.addAttributes(komponenty_cols)
vl_komponenty.updateFields()
idx_vrstva = vl_komponenty.fields().indexOf("vrstva")
vl_komponenty.setEditorWidgetSetup(idx_vrstva, QgsEditorWidgetSetup("Hidden", {}))
for vl in layers: for vl in layers:
vl.dataProvider().addAttributes(cols) vl.dataProvider().addAttributes(cols)
@@ -485,13 +489,16 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false")
meta['lokalita_typ'], meta['lokalita_druh'], meta['lokalita_typ'], meta['lokalita_druh'],
meta['lokalita_zachovalost'] meta['lokalita_zachovalost']
]) ])
if komponenty == "true" and meta['dj_id'] in komponenty_lookup:
for k in komponenty_lookup[meta['dj_id']]:
if len(k) == 3:
k.append(referenced_layer.id())
atributy.append(meta['pristupnost']) atributy.append(meta['pristupnost'])
if komponenty == "true":
atributy.extend([
meta.get('komponenta_id', ""),
meta.get('komponenta_areal', ""),
meta.get('komponenta_obdobi', ""),
])
feat.setAttributes(atributy) feat.setAttributes(atributy)
target_list.append(feat) target_list.append(feat)
@@ -499,18 +506,7 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false")
print(f"Chyba při tvorbě feature: {ex}") print(f"Chyba při tvorbě feature: {ex}")
pass pass
if komponenty == "true": # --- ADDING TO QGIS INTERFACE ---
for k in komponenty_lookup:
for komp in komponenty_lookup[k]:
if len(komp) == 4:
feat = QgsFeature()
atributy = [
komp[0], k, komp[1], komp[2], komp[3]
]
feat.setAttributes(atributy)
feats_k.append(feat)
# --- ADDING TO QGIS INTERFACE ---
proj = QgsProject.instance() proj = QgsProject.instance()
added = 0 added = 0
layers_to_process = [ layers_to_process = [
@@ -519,49 +515,16 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false")
(feats_pt, vl_point, "Body"), (feats_pt, vl_point, "Body"),
] ]
if komponenty == "true":
layers_to_process.append((feats_k, vl_komponenty, "Komponenty"))
for f, l, n in layers_to_process: for f, l, n in layers_to_process:
if f: if f:
l.dataProvider().addFeatures(f) l.dataProvider().addFeatures(f)
l.updateExtents() l.updateExtents()
l.setName(f"AMCR_{archeologicky_zaznam}_{n}") l.setName(f"AMCR_{archeologicky_zaznam}_{n}")
proj.addMapLayer(l) proj.addMapLayer(l)
if n != "Komponenty": added += len(f)
added += len(f)
if added > 0: if added > 0:
iface.messageBar().pushMessage("AMCR", f"Hotovo. Záznamů: {len(docs)} (s geom: {actions_with_geom}). Vykresleno: {added} prvků.", level=Qgis.MessageLevel.Success) iface.messageBar().pushMessage("AMCR", f"Hotovo. Záznamů: {len(docs)} (s geom: {actions_with_geom}). Vykresleno: {added} prvků.", level=Qgis.MessageLevel.Success)
# --- RELATIONSHIP MANAGEMENT ---
# Set up automatic links between spatial layers and the component table
if komponenty == "true":
parent_layers_ids = []
if feats_p:
parent_layers_ids.append(vl_poly.id())
if feats_l:
parent_layers_ids.append(vl_line.id())
if feats_pt:
parent_layers_ids.append(vl_point.id())
rel_manager = proj.relationManager()
rel = QgsPolymorphicRelation()
# rel.setId(f"rel_komponenty_{archeologicky_zaznam}")
rel.setName("Komponenty")
rel.setReferencingLayer(vl_komponenty.id())
rel.setReferencedLayerExpression("@layer_id")
rel.setReferencedLayerField("vrstva")
rel.setReferencedLayerIds(parent_layers_ids)
rel.addFieldPair("dj_id", "Dokumentační jednotka")
rel.generateId()
if rel.isValid():
rel_manager.addPolymorphicRelation(rel)
else:
print("Relace Komponenty není validní!")
else: else:
iface.messageBar().pushMessage("AMCR", "Žádná data k zobrazení.", level=Qgis.MessageLevel.Info) iface.messageBar().pushMessage("AMCR", "Žádná data k zobrazení.", level=Qgis.MessageLevel.Info)