From c17275ef66ecc6164a2dadaaa9ecdec9a4c5ecb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Sp=C3=A1=C4=8Dil?= Date: Mon, 16 Mar 2026 14:00:37 +0100 Subject: [PATCH] changed from three 1:N relations to a polymorphic relation --- amcr_viewer/amcr_tools.py | 76 ++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 29 deletions(-) diff --git a/amcr_viewer/amcr_tools.py b/amcr_viewer/amcr_tools.py index 1b1e26c..f5bf1d6 100644 --- a/amcr_viewer/amcr_tools.py +++ b/amcr_viewer/amcr_tools.py @@ -2,7 +2,7 @@ from qgis.gui import QgsMapToolIdentifyFeature from qgis.core import (QgsProject, QgsVectorLayer, QgsFeature, QgsGeometry, QgsField, QgsCoordinateReferenceSystem, QgsCoordinateTransform, - QgsWkbTypes, QgsRelation, QgsEditorWidgetSetup, Qgis) + QgsWkbTypes, QgsRelation, QgsPolymorphicRelation, QgsEditorWidgetSetup, Qgis) from qgis.utils import iface from qgis.PyQt.QtCore import Qt, QMetaType from qgis.PyQt.QtWidgets import QMessageBox, QApplication @@ -149,6 +149,7 @@ 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 = {} + komponenty_lookup = {} target_pian_ids = set() actions_with_geom = 0 @@ -258,15 +259,15 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false") if komponenty == "true": komps = dj.get('dj_komponenta', []) for komp in komps: - feat = QgsFeature() - atributy = [ + komp_temp = [ komp.get('ident_cely', ""), - dj_id, komp.get('komponenta_areal', {}).get('value', ""), komp.get('komponenta_obdobi', {}).get('value', "") ] - feat.setAttributes(atributy) - feats_k.append(feat) + if dj_id not in komponenty_lookup: + komponenty_lookup[dj_id] = [] + komponenty_lookup[dj_id].append(komp_temp) + if not target_pian_ids: iface.messageBar().pushMessage("AMCR", f"Nalezeno {len(docs)} záznamů, ale žádný nemá geometrii.", level=Qgis.MessageLevel.Warning) @@ -374,14 +375,14 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false") QgsField("komponenta", QMetaType.Type.QString), QgsField("dj_id", 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_dj_id = vl_komponenty.fields().indexOf("dj_id") - text_setup = QgsEditorWidgetSetup("TextEdit", {}) - vl_komponenty.setEditorWidgetSetup(idx_dj_id, text_setup) + idx_vrstva = vl_komponenty.fields().indexOf("vrstva") + vl_komponenty.setEditorWidgetSetup(idx_vrstva, QgsEditorWidgetSetup("Hidden", {})) for vl in layers: vl.dataProvider().addAttributes(cols) @@ -429,11 +430,14 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false") target_list = None if t == QgsWkbTypes.PolygonGeometry: target_list = feats_p + referenced_layer = vl_poly elif t == QgsWkbTypes.LineGeometry: target_list = feats_l + referenced_layer = vl_line elif t == QgsWkbTypes.PointGeometry: target_list = feats_pt - + referenced_layer = vl_point + if target_list is None: continue @@ -463,7 +467,12 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false") meta['lokalita_typ'], meta['lokalita_druh'], 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']) feat.setAttributes(atributy) target_list.append(feat) @@ -471,6 +480,17 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false") except Exception as ex: print(f"Chyba při tvorbě feature: {ex}") pass + + if komponenty == "true": + 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() @@ -499,24 +519,22 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false") # --- RELATIONSHIP MANAGEMENT --- # Set up automatic links between spatial layers and the component table if komponenty == "true": - parent_layers = [ - (vl_poly, "Polygony"), - (vl_line, "Linie"), - (vl_point, "Body") - ] + parent_layers_ids = [vl_poly.id(), vl_line.id(), vl_point.id()] rel_manager = proj.relationManager() - for parent_layer, label in parent_layers: - rel = QgsRelation() - rel_name = f"Komponenty pro {label}" - rel.setName(rel_name) - rel.setReferencingLayer(vl_komponenty.id()) - rel.setReferencedLayer(parent_layer.id()) - rel.addFieldPair("dj_id", "Dokumentační jednotka") - rel.generateId() - if rel.isValid(): - rel_manager.addRelation(rel) - else: - print(f"Relace pro {label} není validní!") + + 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") + + if rel.isValid(): + rel_manager.addPolymorphicRelation(rel) + else: + print("Relace Komponenty není validní!") else: iface.messageBar().pushMessage("AMCR", "Žádná data k zobrazení.", level=Qgis.MessageLevel.Info)