9 Commits

Author SHA1 Message Date
david 11f44d025b Update metadata.txt 2026-03-19 09:38:32 +01:00
david 7f3b2b46fb Merge pull request #28 from ARUP-CAS/relation-fix
Fix polymorphic relations not creating in some cases
2026-03-19 09:36:37 +01:00
david be53edefa5 relation fix 2026-03-19 09:30:13 +01:00
david 3be7832b40 Update metadata.txt 2026-03-16 14:30:12 +01:00
david 8c0c540fa4 Merge pull request #26 from ARUP-CAS/polymorphic-relation
Polymorphic relation instead of the standard ones; code cleanup
2026-03-16 14:13:50 +01:00
David Spáčil 8088b32661 removed unnecessary imports 2026-03-16 14:01:32 +01:00
David Spáčil c17275ef66 changed from three 1:N relations to a polymorphic relation 2026-03-16 14:00:37 +01:00
david 9ec866f1d2 Update metadata.txt 2026-03-13 10:56:09 +01:00
david 5a951edec7 Fixed compatibility issues with QGIS 4 (#24)
* used PyQt6 compatible objects

* metadata update
2026-03-13 10:48:12 +01:00
6 changed files with 165 additions and 141 deletions
+1
View File
@@ -210,3 +210,4 @@ __marimo__/
README_files/ README_files/
README.html README.html
amcr_viewer.zip
+60 -62
View File
@@ -13,6 +13,7 @@ from .amcr_codelists import (OBDOBI, TYP_AKCE, KRAJE, AREAL, ORGANIZACE,
class FilterableSelectionDialog(QDialog): class FilterableSelectionDialog(QDialog):
""" """
A custom dialog for selecting multiple items from a list with a search filter. A custom dialog for selecting multiple items from a list with a search filter.
Updated for PyQt6/Qt6 compatibility.
""" """
def __init__(self, title, data_dict, preselected_codes, parent=None): def __init__(self, title, data_dict, preselected_codes, parent=None):
super().__init__(parent) super().__init__(parent)
@@ -37,7 +38,9 @@ class FilterableSelectionDialog(QDialog):
layout.addWidget(self.list_widget) layout.addWidget(self.list_widget)
# Standard OK/Cancel dialog buttons # Standard OK/Cancel dialog buttons
buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttons = QDialogButtonBox(
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
)
buttons.accepted.connect(self.accept) buttons.accepted.connect(self.accept)
buttons.rejected.connect(self.reject) buttons.rejected.connect(self.reject)
layout.addWidget(buttons) layout.addWidget(buttons)
@@ -52,16 +55,16 @@ class FilterableSelectionDialog(QDialog):
item = QListWidgetItem(name) item = QListWidgetItem(name)
# Store the actual code (ID) hidden in the UserRole # Store the actual code (ID) hidden in the UserRole
item.setData(Qt.UserRole, code) item.setData(Qt.ItemDataRole.UserRole, code)
# Make the item checkable (adds a checkbox) # Make the item checkable (adds a checkbox)
item.setFlags(item.flags() | Qt.ItemIsUserCheckable) item.setFlags(item.flags() | Qt.ItemFlag.ItemIsUserCheckable)
# Restore previous selection state # Restore previous selection state
if code in self.preselected: if code in self.preselected:
item.setCheckState(Qt.Checked) item.setCheckState(Qt.CheckState.Checked)
else: else:
item.setCheckState(Qt.Unchecked) item.setCheckState(Qt.CheckState.Unchecked)
self.list_widget.addItem(item) self.list_widget.addItem(item)
@@ -70,10 +73,7 @@ class FilterableSelectionDialog(QDialog):
search_text = text.lower() search_text = text.lower()
for i in range(self.list_widget.count()): for i in range(self.list_widget.count()):
item = self.list_widget.item(i) item = self.list_widget.item(i)
if search_text not in item.text().lower(): item.setHidden(search_text not in item.text().lower())
item.setHidden(True)
else:
item.setHidden(False)
def get_selected_codes(self): def get_selected_codes(self):
"""Returns the hidden codes and display labels of all checked items.""" """Returns the hidden codes and display labels of all checked items."""
@@ -81,8 +81,8 @@ class FilterableSelectionDialog(QDialog):
labels = [] labels = []
for i in range(self.list_widget.count()): for i in range(self.list_widget.count()):
item = self.list_widget.item(i) item = self.list_widget.item(i)
if item.checkState() == Qt.Checked: if item.checkState() == Qt.CheckState.Checked:
codes.append(item.data(Qt.UserRole)) codes.append(item.data(Qt.ItemDataRole.UserRole))
labels.append(item.text()) labels.append(item.text())
return codes, labels return codes, labels
@@ -93,7 +93,7 @@ class AmcrFilterDialog(QDialog):
The main filtering UI where users set criteria before downloading data. The main filtering UI where users set criteria before downloading data.
""" """
def __init__(self, typ_dat, parent=None): def __init__(self, typ_dat, parent=None):
super(AmcrFilterDialog, self).__init__(parent) super().__init__(parent)
self.setWindowTitle("Filtr AMČR") self.setWindowTitle("Filtr AMČR")
self.resize(500, 750) self.resize(500, 750)
@@ -189,7 +189,9 @@ class AmcrFilterDialog(QDialog):
layout.addStretch(1) layout.addStretch(1)
# Main dialog OK/Cancel buttons # Main dialog OK/Cancel buttons
buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttons = QDialogButtonBox(
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
)
buttons.accepted.connect(self.accept) buttons.accepted.connect(self.accept)
buttons.rejected.connect(self.reject) buttons.rejected.connect(self.reject)
layout.addWidget(buttons) layout.addWidget(buttons)
@@ -197,60 +199,56 @@ class AmcrFilterDialog(QDialog):
self.setLayout(layout) self.setLayout(layout)
def setup_picker(self, label_text, cache_key, data_source, extra_btn=None): def setup_picker(self, label_text, cache_key, data_source, extra_btn=None):
""" """
Creates a reusable UI component consisting of a label, a read-only Creates a reusable UI component consisting of a label, a read-only
text field showing selected items, and a button to open the selection dialog. text field showing selected items, and a button to open the selection dialog.
""" """
row_widget = QGroupBox(label_text) row_widget = QGroupBox(label_text)
# row_widget.setFlat(True) row_layout = QHBoxLayout()
row_layout.setContentsMargins(5, 5, 5, 5)
row_layout = QHBoxLayout()
row_layout.setContentsMargins(5, 5, 5, 5) # Read-only field displaying the names of selected items
display_field = QLineEdit()
# Read-only field displaying the names of selected items display_field.setReadOnly(True)
display_field = QLineEdit() display_field.setPlaceholderText("Nic nevybráno (vše)")
display_field.setReadOnly(True) display_field.setStyleSheet("background-color: #f0f0f0; color: #333;")
display_field.setPlaceholderText("Nic nevybráno (vše)")
display_field.setStyleSheet("background-color: #f0f0f0; color: #333;") btn = QPushButton("Vybrat...")
btn.setFixedWidth(80)
btn = QPushButton("Vybrat...")
btn.setFixedWidth(80) # Nested function that handles opening the dialog and saving results
def open_dialog():
# Nested function that handles opening the dialog and saving results dlg = FilterableSelectionDialog(label_text, data_source, self.selection_cache[cache_key], self)
def open_dialog(): if dlg.exec() == QDialog.DialogCode.Accepted: # PyQt6: DialogCode
dlg = FilterableSelectionDialog(label_text, data_source, self.selection_cache[cache_key], self) codes, labels = dlg.get_selected_codes()
if dlg.exec() == QDialog.Accepted: # Update local cache with selected IDs
codes, labels = dlg.get_selected_codes() self.selection_cache[cache_key] = codes
# Update the UI text field with selected names
# Update local cache with selected IDs if labels:
self.selection_cache[cache_key] = codes display_field.setText(", ".join(labels))
else:
# Update the UI text field with selected names display_field.clear()
if labels:
display_field.setText(", ".join(labels)) # Special case: Pre-fill specific accuracy levels by default
else: if cache_key == 'pian_presnost':
display_field.clear() display_field.setText("odchylka jednotky metrů, odchylka desítky metrů, odchylka stovky metrů")
self.selection_cache[cache_key] = ['HES-000861', 'HES-000862', 'HES-000863']
# Special case: Pre-fill specific accuracy levels by default
if cache_key == 'pian_presnost':
display_field.setText("odchylka jednotky metrů, odchylka desítky metrů, odchylka stovky metrů")
self.selection_cache[cache_key] = ['HES-000861', 'HES-000862', 'HES-000863']
btn.clicked.connect(open_dialog) btn.clicked.connect(open_dialog)
row_layout.addWidget(display_field)
row_layout.addWidget(btn)
# Add an optional extra button (e.g., the refresh button for leaders)
if extra_btn:
row_layout.addWidget(extra_btn)
row_layout.addWidget(display_field) row_widget.setLayout(row_layout)
row_layout.addWidget(btn) return row_widget
# Add an optional extra button (e.g., the refresh button for leaders)
if extra_btn:
row_layout.addWidget(extra_btn)
row_widget.setLayout(row_layout)
return row_widget
def action_update_vedouci(self): def action_update_vedouci(self):
# Change cursor to loading state to indicate background task # Change cursor to loading state to indicate background task
QApplication.setOverrideCursor(Qt.WaitCursor) QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor)
try: try:
success, msg = download_vedouci() success, msg = download_vedouci()
if success: if success:
+97 -73
View File
@@ -1,15 +1,13 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from qgis.gui import QgsMapToolIdentifyFeature
from qgis.core import (QgsProject, QgsVectorLayer, QgsFeature, QgsGeometry, from qgis.core import (QgsProject, QgsVectorLayer, QgsFeature, QgsGeometry,
QgsField, QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsField, QgsCoordinateReferenceSystem, QgsCoordinateTransform,
QgsWkbTypes, QgsRelation, QgsEditorWidgetSetup) QgsWkbTypes, QgsPolymorphicRelation, QgsEditorWidgetSetup, Qgis)
from qgis.utils import iface from qgis.utils import iface
from qgis.PyQt.QtCore import QVariant, Qt from qgis.PyQt.QtCore import Qt, QMetaType
from qgis.PyQt.QtWidgets import QMessageBox, QApplication from qgis.PyQt.QtWidgets import QApplication
from qgis.PyQt.QtGui import QCursor
import requests import requests
import json import json
import xml.etree.ElementTree as ET
import re
# Global cache to store translated terms from the Digital Archive # Global cache to store translated terms from the Digital Archive
TRANSLATIONS = {} TRANSLATIONS = {}
@@ -56,8 +54,8 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false")
url = "https://digiarchiv.aiscr.cz/api/search/query" url = "https://digiarchiv.aiscr.cz/api/search/query"
iface.messageBar().pushMessage("AMCR", "Hledám záznamy...", level=1) iface.messageBar().pushMessage("AMCR", "Hledám záznamy...", level=Qgis.MessageLevel.Info)
QApplication.setOverrideCursor(Qt.WaitCursor) QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
try: try:
# ========================================== # ==========================================
@@ -128,7 +126,7 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false")
if len(docs) >= num_found: if len(docs) >= num_found:
break break
if len(docs) >= MAX_LIMIT: if len(docs) >= MAX_LIMIT:
iface.messageBar().pushMessage("AMCR", f"Limit {MAX_LIMIT} záznamů dosažen.", level=1) iface.messageBar().pushMessage("AMCR", f"Limit {MAX_LIMIT} záznamů dosažen.", level=Qgis.MessageLevel.Warning)
break break
current_page += 1 current_page += 1
@@ -139,7 +137,7 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false")
break break
if not docs: if not docs:
iface.messageBar().pushMessage("AMCR", "Žádné záznamy nenalezeny.", level=1) iface.messageBar().pushMessage("AMCR", "Žádné záznamy nenalezeny.", level=Qgis.MessageLevel.Warning)
return return
# ========================================== # ==========================================
@@ -148,6 +146,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 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
@@ -257,18 +256,18 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false")
if komponenty == "true": if komponenty == "true":
komps = dj.get('dj_komponenta', []) komps = dj.get('dj_komponenta', [])
for komp in komps: for komp in komps:
feat = QgsFeature() komp_temp = [
atributy = [
komp.get('ident_cely', ""), komp.get('ident_cely', ""),
dj_id,
komp.get('komponenta_areal', {}).get('value', ""), komp.get('komponenta_areal', {}).get('value', ""),
komp.get('komponenta_obdobi', {}).get('value', "") komp.get('komponenta_obdobi', {}).get('value', "")
] ]
feat.setAttributes(atributy) if dj_id not in komponenty_lookup:
feats_k.append(feat) komponenty_lookup[dj_id] = []
komponenty_lookup[dj_id].append(komp_temp)
if not target_pian_ids: if not target_pian_ids:
iface.messageBar().pushMessage("AMCR", f"Nalezeno {len(docs)} záznamů, ale žádný nemá geometrii.", level=1) iface.messageBar().pushMessage("AMCR", f"Nalezeno {len(docs)} záznamů, ale žádný nemá geometrii.", level=Qgis.MessageLevel.Warning)
return return
@@ -280,7 +279,7 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false")
docs_pian = [] docs_pian = []
BATCH_PIAN = 200 # Geometry requests are batch-processed to stay under URL length limits BATCH_PIAN = 200 # Geometry requests are batch-processed to stay under URL length limits
iface.messageBar().pushMessage("AMCR", f"Záznamů: {len(docs)} (z toho {actions_with_geom} s mapou). Stahuji {total_pians} unikátních geometrií, vykresluji {target_pian_ids_count} geometrií...", level=1) iface.messageBar().pushMessage("AMCR", f"Záznamů: {len(docs)} (z toho {actions_with_geom} s mapou). Stahuji {total_pians} unikátních geometrií, vykresluji {target_pian_ids_count} geometrií...", level=Qgis.MessageLevel.Info)
fl_pian = ["ident_cely", "pian_typ", "pian_chranene_udaje", "pian_presnost"] fl_pian = ["ident_cely", "pian_typ", "pian_chranene_udaje", "pian_presnost"]
@@ -318,43 +317,43 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false")
# Define attribute table structure # Define attribute table structure
cols = [ cols = [
QgsField("PIAN", QVariant.String), QgsField("PIAN", QMetaType.Type.QString),
QgsField("Přesnost", QVariant.String), QgsField("Přesnost", QMetaType.Type.QString),
QgsField("PIAN typ", QVariant.String), QgsField("PIAN typ", QMetaType.Type.QString),
QgsField("Dokumentační jednotka", QVariant.String), QgsField("Dokumentační jednotka", QMetaType.Type.QString),
QgsField("Typ dokumentační jednotky", QVariant.String), QgsField("Typ dokumentační jednotky", QMetaType.Type.QString),
QgsField("Definiční bod(y) (WGS-84)", QVariant.String), QgsField("Definiční bod(y) (WGS-84)", QMetaType.Type.QString),
QgsField(archeologicky_zaznam, QVariant.String), QgsField(archeologicky_zaznam, QMetaType.Type.QString),
QgsField("Odkaz do Digitálního archivu AMČR", QVariant.String), QgsField("Odkaz do Digitálního archivu AMČR", QMetaType.Type.QString),
QgsField("Okres", QVariant.String), QgsField("Okres", QMetaType.Type.QString),
QgsField("Katastr", QVariant.String), QgsField("Katastr", QMetaType.Type.QString),
QgsField("Další katastry", QVariant.String) QgsField("Další katastry", QMetaType.Type.QString)
] ]
# Extend table based on data type # Extend table based on data type
if typ_dat == "akce": if typ_dat == "akce":
cols += [ cols += [
QgsField("Akce lokalizace", QVariant.String), QgsField("Akce lokalizace", QMetaType.Type.QString),
QgsField("Vedoucí akce", QVariant.String), QgsField("Vedoucí akce", QMetaType.Type.QString),
QgsField("Organizace", QVariant.String), QgsField("Organizace", QMetaType.Type.QString),
QgsField("Specifikace data", QVariant.String), QgsField("Specifikace data", QMetaType.Type.QString),
QgsField("Datum zahájeni", QVariant.String), QgsField("Datum zahájeni", QMetaType.Type.QString),
QgsField("Datum ukončení", QVariant.String), QgsField("Datum ukončení", QMetaType.Type.QString),
QgsField("Hlavní typ", QVariant.String), QgsField("Hlavní typ", QMetaType.Type.QString),
QgsField("Vedlejší typ", QVariant.String), QgsField("Vedlejší typ", QMetaType.Type.QString),
QgsField("Zjištění", QVariant.String), QgsField("Zjištění", QMetaType.Type.QString),
QgsField("Akce nahrazuje NZ", QVariant.String), QgsField("Akce nahrazuje NZ", QMetaType.Type.QString),
] ]
elif typ_dat == "lokalita": elif typ_dat == "lokalita":
cols += [ cols += [
QgsField("nazev_lokality", QVariant.String), QgsField("nazev_lokality", QMetaType.Type.QString),
QgsField("popis_lokality", QVariant.String), QgsField("popis_lokality", QMetaType.Type.QString),
QgsField("typ_lokality", QVariant.String), QgsField("typ_lokality", QMetaType.Type.QString),
QgsField("druh_lokality", QVariant.String), QgsField("druh_lokality", QMetaType.Type.QString),
QgsField("zachovalost", QVariant.String) QgsField("zachovalost", QMetaType.Type.QString)
] ]
cols.append(QgsField("Přístupnost", QVariant.String)) cols.append(QgsField("Přístupnost", QMetaType.Type.QString))
# Use aliases for technical field names # Use aliases for technical field names
alias_map = { alias_map = {
@@ -370,17 +369,17 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false")
vl_komponenty = QgsVectorLayer("None", "AMCR Komponenty", "memory") vl_komponenty = QgsVectorLayer("None", "AMCR Komponenty", "memory")
pr = vl_komponenty.dataProvider() pr = vl_komponenty.dataProvider()
komponenty_cols = [ komponenty_cols = [
QgsField("komponenta", QVariant.String), QgsField("komponenta", QMetaType.Type.QString),
QgsField("dj_id", QVariant.String), QgsField("dj_id", QMetaType.Type.QString),
QgsField("komponenta_areal", QVariant.String), QgsField("komponenta_areal", QMetaType.Type.QString),
QgsField("komponenta_obdobi", QVariant.String) QgsField("komponenta_obdobi", QMetaType.Type.QString),
QgsField("vrstva", QMetaType.Type.QString)
] ]
pr.addAttributes(komponenty_cols) pr.addAttributes(komponenty_cols)
vl_komponenty.updateFields() vl_komponenty.updateFields()
idx_dj_id = vl_komponenty.fields().indexOf("dj_id") idx_vrstva = vl_komponenty.fields().indexOf("vrstva")
text_setup = QgsEditorWidgetSetup("TextEdit", {}) vl_komponenty.setEditorWidgetSetup(idx_vrstva, QgsEditorWidgetSetup("Hidden", {}))
vl_komponenty.setEditorWidgetSetup(idx_dj_id, text_setup)
for vl in layers: for vl in layers:
vl.dataProvider().addAttributes(cols) vl.dataProvider().addAttributes(cols)
@@ -428,11 +427,14 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false")
target_list = None target_list = None
if t == QgsWkbTypes.PolygonGeometry: if t == QgsWkbTypes.PolygonGeometry:
target_list = feats_p target_list = feats_p
referenced_layer = vl_poly
elif t == QgsWkbTypes.LineGeometry: elif t == QgsWkbTypes.LineGeometry:
target_list = feats_l target_list = feats_l
referenced_layer = vl_line
elif t == QgsWkbTypes.PointGeometry: elif t == QgsWkbTypes.PointGeometry:
target_list = feats_pt target_list = feats_pt
referenced_layer = vl_point
if target_list is None: if target_list is None:
continue continue
@@ -462,7 +464,12 @@ 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'])
feat.setAttributes(atributy) feat.setAttributes(atributy)
target_list.append(feat) target_list.append(feat)
@@ -470,6 +477,17 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false")
except Exception as ex: except Exception as ex:
print(f"Chyba při tvorbě feature: {ex}") print(f"Chyba při tvorbě feature: {ex}")
pass 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 --- # --- ADDING TO QGIS INTERFACE ---
proj = QgsProject.instance() proj = QgsProject.instance()
@@ -493,35 +511,41 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false")
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=0) iface.messageBar().pushMessage("AMCR", f"Hotovo. Záznamů: {len(docs)} (s geom: {actions_with_geom}). Vykresleno: {added} prvků.", level=Qgis.MessageLevel.Success)
# --- RELATIONSHIP MANAGEMENT --- # --- RELATIONSHIP MANAGEMENT ---
# Set up automatic links between spatial layers and the component table # Set up automatic links between spatial layers and the component table
if komponenty == "true": if komponenty == "true":
parent_layers = [ parent_layers_ids = []
(vl_poly, "Polygony"), if feats_p:
(vl_line, "Linie"), parent_layers_ids.append(vl_poly.id())
(vl_point, "Body") 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_manager = proj.relationManager()
for parent_layer, label in parent_layers:
rel = QgsRelation() rel = QgsPolymorphicRelation()
rel_name = f"Komponenty pro {label}" # rel.setId(f"rel_komponenty_{archeologicky_zaznam}")
rel.setName(rel_name) rel.setName("Komponenty")
rel.setReferencingLayer(vl_komponenty.id()) rel.setReferencingLayer(vl_komponenty.id())
rel.setReferencedLayer(parent_layer.id()) rel.setReferencedLayerExpression("@layer_id")
rel.addFieldPair("dj_id", "Dokumentační jednotka") rel.setReferencedLayerField("vrstva")
rel.generateId() rel.setReferencedLayerIds(parent_layers_ids)
if rel.isValid(): rel.addFieldPair("dj_id", "Dokumentační jednotka")
rel_manager.addRelation(rel) rel.generateId()
else:
print(f"Relace pro {label} není validní!") if rel.isValid():
rel_manager.addPolymorphicRelation(rel)
else:
print("Relace Komponenty není validní!")
else: else:
iface.messageBar().pushMessage("AMCR", "Žádná data k zobrazení.", level=1) iface.messageBar().pushMessage("AMCR", "Žádná data k zobrazení.", level=Qgis.MessageLevel.Info)
except Exception as e: except Exception as e:
iface.messageBar().pushMessage("Chyba", str(e), level=2) iface.messageBar().pushMessage("Chyba", str(e), level=Qgis.MessageLevel.Critical)
finally: finally:
# Always restore cursor, even after failure # Always restore cursor, even after failure
QApplication.restoreOverrideCursor() QApplication.restoreOverrideCursor()
+3 -3
View File
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from qgis.PyQt.QtCore import QSettings, QTranslator, QCoreApplication from qgis.PyQt.QtCore import QSettings, QTranslator, QCoreApplication
from qgis.PyQt.QtGui import QIcon from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import QMenu, QAction, QToolButton from qgis.PyQt.QtWidgets import QMenu, QAction, QToolButton, QDialog
from .amcr_tools import load_amcr_data from .amcr_tools import load_amcr_data
from .amcr_dialog import AmcrFilterDialog from .amcr_dialog import AmcrFilterDialog
@@ -120,7 +120,7 @@ class AmcrViewer:
self.tool_button = QToolButton() self.tool_button = QToolButton()
self.tool_button.setMenu(self.plugin_menu) self.tool_button.setMenu(self.plugin_menu)
self.tool_button.setDefaultAction(self.action_download_akce) self.tool_button.setDefaultAction(self.action_download_akce)
self.tool_button.setPopupMode(QToolButton.MenuButtonPopup) self.tool_button.setPopupMode(QToolButton.ToolButtonPopupMode.MenuButtonPopup)
# Add the widget directly to the toolbar and store the reference for cleanup # Add the widget directly to the toolbar and store the reference for cleanup
self.toolbar_action = self.iface.addToolBarWidget(self.tool_button) self.toolbar_action = self.iface.addToolBarWidget(self.tool_button)
@@ -161,7 +161,7 @@ class AmcrViewer:
result = dlg.exec() result = dlg.exec()
# If user confirmed the dialog (OK button), gather filters and load data # If user confirmed the dialog (OK button), gather filters and load data
if result == 1: if result == QDialog.DialogCode.Accepted:
filters = dlg.get_filters() filters = dlg.get_filters()
bbox = dlg.get_bbox() bbox = dlg.get_bbox()
komponenty = dlg.get_komponenty() komponenty = dlg.get_komponenty()
+3 -2
View File
@@ -5,9 +5,10 @@
[general] [general]
name=AMČR Viewer name=AMČR Viewer
qgisMinimumVersion=3.4 qgisMinimumVersion=3.4.0
qgisMaximumVersion=4.99.0
description=Viewing and downloading the AMČR data. description=Viewing and downloading the AMČR data.
version=1.2.0 version=1.3.2
author=David Spáčil author=David Spáčil
email=spacil@arub.cz email=spacil@arub.cz
+1 -1
View File
@@ -6,7 +6,7 @@
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore from qgis.PyQt import QtCore
qt_resource_data = b"\ qt_resource_data = b"\
\x00\x00\x04\x0a\ \x00\x00\x04\x0a\