12 Commits

Author SHA1 Message Date
David Spáčil a696872b0c Update README.md 2026-02-19 07:28:44 +01:00
David Spáčil bcde600433 Update metadata.txt 2026-02-19 07:22:23 +01:00
David Spáčil 8b71d75701 Merge pull request #16 from ARUP-CAS/pian-downloading-logic-fix
Fixed PIAN counting and downloading logic
2026-02-19 07:20:14 +01:00
David Spáčil 6131c7ff9d Fixed PIAN counting and downloading logic 2026-02-19 07:17:13 +01:00
David Spáčil 396f4fbb4e Merge pull request #15 from ARUP-CAS/filter-presnost
Added logic for filtering based on PIAN accuracy; features with a "location by cadastral area" attribute are disabled by default.
2026-02-18 22:16:45 +01:00
David Spáčil 0f07a40bb0 Added logic for filtering based on PIAN accuracy
Features with a "location by cadastral area" attribute are disabled by default.
2026-02-18 22:13:30 +01:00
David Spáčil 0d3bd0a696 Merge pull request #11 from ARUP-CAS/restructuring-amcr_tools
amcr_tools.py was restructured to better match the Digital archive API structure.
2026-02-18 16:12:44 +01:00
David Spáčil 777b1900d5 Update amcr_tools.py 2026-02-18 11:04:26 +01:00
David Spáčil 27303fdf53 Update amcr_tools.py
Further polishing; removed obsolete bits
2026-02-17 18:51:27 +01:00
David Spáčil fbe5c6a113 Fixed DJs handling logic and filtering negative DJs 2026-02-17 18:43:36 +01:00
David Spáčil 8693179fa9 Tidying up
removed unused bits of code
2026-02-17 18:11:06 +01:00
David Spáčil a314dd3758 Update amcr_tools.py
Logic is restructured: event → doc unit → pian.
Logic for filtering negative DJs still needs to be reimplemented.
2026-02-17 08:33:56 +01:00
7 changed files with 141 additions and 194 deletions
+4 -10
View File
@@ -51,7 +51,7 @@ To initiate a search query, click the **Load AMCR Data** icon. The filter dialog
* **Attribute Filters:**
* The dialog utilizes "Picker" widgets for controlled vocabularies (Region, District, Cadastral area, Organisation, Period, Activity Area).
* The dialog utilizes "Picker" widgets for controlled vocabularies (Region, District, Cadastral area, Organisation, Period, Activity Area, PIAN accuracy.
* Click **Select...** to open a searchable selection window. Multiple values can be selected simultaneously (Logic: OR).
@@ -70,13 +70,7 @@ Upon successful retrieval, the plugin generates three temporary memory layers:
2. **AMČR Linie (Lines)**
3. **AMČR Body (Points)**
The Attribute Table includes standardized fields such as:
* **Identification:** `Identifikátor` (Fieldwork event ID), `PIAN` (PIAN ID).
* **Classification:** `Hlavní typ` (Main Fieldwork event Type), `Vedlejší typ` (Secondary Fieldwork event Type), `PIAN typ` (PIAN Type).
* **Administration:** `Vedoucí akce` (Fieldwork Manager), `Organizace` (Organization), `Datum zahájeni`/`Datum ukončení` (Dates of start and end of the Fieldwork event).
* **Location:** `Katastr` (Main Cadastral area), `Další katastry` (Other Cadastral areas), `Okres` (District), `Definiční bod(y)` (PIAN point localization).
* **Links:** `Odkaz do Digiarchivu` (Direct URL to the DigiArchive record).
The Attribute Table includes standardized fields with important metadata.
---
@@ -98,7 +92,7 @@ The plugin interacts with three primary endpoints of the AIS CR infrastructure:
1. **Search API (Solr):**
* Endpoint: `https://digiarchiv.aiscr.cz/api/search/query`
* Method: `GET`
* Parameters: `entity=akce`, `fl` (field list), `q` (query), `rows/page` (pagination).
* Parameters: `entity=akce`, `rows/page` (pagination).
* Logic: The plugin implements a `while True` loop to handle pagination, processing data in batches of 500 records to ensure stability.
@@ -115,7 +109,7 @@ The plugin interacts with three primary endpoints of the AIS CR infrastructure:
### 4.4 Constraints
* **Record Limit:** A safety cap of 20,000 records is enforced to prevent memory overflow in QGIS.
* **Record Limit:** A safety cap of 20,000 records is enforced.
* **Batch Processing:** Geometry fetching is batched (50 IDs per request) to comply with URL length limitations and server load balancing.
## 6. Links and resources
+2 -1
View File
@@ -62,7 +62,7 @@ def load_all_data():
categorized_data = {
'obdobi': {}, 'typ_akce': {}, 'areal': {},
'kraj': {}, 'organizace': {}, 'okres': {}, 'katastr': {},
'vedouci': {}
'vedouci': {}, 'pian_presnost': {}
}
# Funkce pro roztřídění načteného slovníku (tohle je trochu redundance, ale pro zachování logiky)
@@ -157,6 +157,7 @@ ORGANIZACE = _DATA['organizace']
OKRESY = _DATA['okres']
KATASTRY = _DATA['katastr']
VEDOUCI = _DATA['vedouci'] # Tady to bude zpočátku prázdné, pokud soubor neexistuje
PIAN_PRESNOST = _DATA['pian_presnost']
def refresh_vedouci_cache():
"""
+41 -17
View File
@@ -6,7 +6,7 @@ from qgis.PyQt.QtWidgets import (QDialog, QVBoxLayout, QFormLayout,
QLabel, QMessageBox, QApplication, QWidget)
from qgis.PyQt.QtCore import Qt
from .amcr_codelists import (OBDOBI, TYP_AKCE, KRAJE, AREAL, ORGANIZACE,
OKRESY, KATASTRY, VEDOUCI,
OKRESY, KATASTRY, VEDOUCI, PIAN_PRESNOST,
download_vedouci, refresh_vedouci_cache)
class FilterableSelectionDialog(QDialog):
@@ -37,16 +37,20 @@ class FilterableSelectionDialog(QDialog):
item = QListWidgetItem(name)
item.setData(Qt.UserRole, code)
item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
if code in self.preselected: item.setCheckState(Qt.Checked)
else: item.setCheckState(Qt.Unchecked)
if code in self.preselected:
item.setCheckState(Qt.Checked)
else:
item.setCheckState(Qt.Unchecked)
self.list_widget.addItem(item)
def filter_list(self, text):
search_text = text.lower()
for i in range(self.list_widget.count()):
item = self.list_widget.item(i)
if search_text not in item.text().lower(): item.setHidden(True)
else: item.setHidden(False)
if search_text not in item.text().lower():
item.setHidden(True)
else:
item.setHidden(False)
def get_selected_codes(self):
codes = []
@@ -69,7 +73,7 @@ class AmcrFilterDialog(QDialog):
# Cache for filtering
self.selection_cache = {
'organizace': [], 'kraj': [], 'obdobi': [], 'areal': [],
'typ_akce': [], 'okres': [], 'katastr': [], 'vedouci': []
'typ_akce': [], 'okres': [], 'katastr': [], 'vedouci': [], 'pian_presnost': []
}
layout = QVBoxLayout()
@@ -103,9 +107,15 @@ class AmcrFilterDialog(QDialog):
if dlg.exec_() == QDialog.Accepted:
codes, labels = dlg.get_selected_codes()
self.selection_cache[cache_key] = codes
if labels: display_field.setText(", ".join(labels))
else: display_field.clear()
if labels:
display_field.setText(", ".join(labels))
else:
display_field.clear()
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)
row_layout.addWidget(display_field)
@@ -146,6 +156,9 @@ class AmcrFilterDialog(QDialog):
self.picker_typ = setup_picker("Typ výzkumu", 'typ_akce', TYP_AKCE)
layout.addWidget(self.picker_typ)
self.picker_presnost = setup_picker("PIAN přesnost", 'pian_presnost', PIAN_PRESNOST)
layout.addWidget(self.picker_presnost)
layout.addStretch(1)
buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
@@ -175,16 +188,27 @@ class AmcrFilterDialog(QDialog):
def get_filters(self):
filters = {}
if self.chk_posevidence.isChecked(): filters['posevidence'] = 'true'
if self.chk_posevidence.isChecked():
filters['posevidence'] = 'true'
# Loading from cache
if self.selection_cache['organizace']: filters['f_organizace'] = self.selection_cache['organizace']
if self.selection_cache['kraj']: filters['f_kraj'] = self.selection_cache['kraj']
if self.selection_cache['okres']: filters['f_okres'] = self.selection_cache['okres']
if self.selection_cache['katastr']: filters['f_katastr'] = self.selection_cache['katastr']
if self.selection_cache['obdobi']: filters['f_obdobi'] = self.selection_cache['obdobi']
if self.selection_cache['areal']: filters['f_areal'] = self.selection_cache['areal']
if self.selection_cache['typ_akce']: filters['f_typ_vyzkumu'] = self.selection_cache['typ_akce']
if self.selection_cache['vedouci']: filters['f_vedouci'] = self.selection_cache['vedouci']
if self.selection_cache['organizace']:
filters['f_organizace'] = self.selection_cache['organizace']
if self.selection_cache['kraj']:
filters['f_kraj'] = self.selection_cache['kraj']
if self.selection_cache['okres']:
filters['f_okres'] = self.selection_cache['okres']
if self.selection_cache['katastr']:
filters['f_katastr'] = self.selection_cache['katastr']
if self.selection_cache['obdobi']:
filters['f_obdobi'] = self.selection_cache['obdobi']
if self.selection_cache['areal']:
filters['f_areal'] = self.selection_cache['areal']
if self.selection_cache['typ_akce']:
filters['f_typ_vyzkumu'] = self.selection_cache['typ_akce']
if self.selection_cache['vedouci']:
filters['f_vedouci'] = self.selection_cache['vedouci']
if self.selection_cache['pian_presnost']:
filters['f_pian_presnost'] = self.selection_cache['pian_presnost']
return filters
+88 -138
View File
@@ -17,7 +17,8 @@ TRANSLATIONS = {}
# Download Digiarchive's vocabulary
def load_translations():
global TRANSLATIONS
if TRANSLATIONS: return
if TRANSLATIONS:
return
url = "https://digiarchiv.aiscr.cz/api/assets/i18n/cs.json"
try:
@@ -28,7 +29,8 @@ def load_translations():
print(f"Chyba při stahování hesláře: {e}")
def tr_code(code):
if not code: return ""
if not code:
return ""
return TRANSLATIONS.get(code, code)
def load_amcr_data(canvas, bb, filters=None):
@@ -54,7 +56,6 @@ def load_amcr_data(canvas, bb, filters=None):
base_params = {
"mapa": "true",
#"isExport": "true",
"entity": "akce",
"sort": "ident_cely asc"
}
@@ -65,7 +66,8 @@ def load_amcr_data(canvas, bb, filters=None):
# Apply filters
if filters:
for key, value in filters.items():
if not value: continue
if not value:
continue
if isinstance(value, list):
base_params[key] = [f"{v}:or" for v in value]
else:
@@ -77,6 +79,7 @@ def load_amcr_data(canvas, bb, filters=None):
MAX_LIMIT = 20000
seen_ids = set()
target_pian_ids_count = 0
while True:
base_params['rows'] = BATCH_AKCE
@@ -128,43 +131,24 @@ def load_amcr_data(canvas, bb, filters=None):
pian_lookup = {}
target_pian_ids = set()
actions_with_geom = 0
negative_dj_pian_ids = set()
for akce in docs_akce:
piani = akce.get('az_dj_pian', [])
if not piani: continue
negative_pians = set()
# Pokud je aktivní filtr 'posevidence', projdeme dokumentační jednotky
if filters and filters.get('posevidence') == 'true':
djs = akce.get('az_dokumentacni_jednotka', [])
for dj in djs:
# Pokud je jednotka negativní
if dj.get('dj_negativni_jednotka') is True:
# Získáme ID pianu z objektu (např. {"id": "P-...", "value": "..."})
pian_obj = dj.get('dj_pian')
if pian_obj and isinstance(pian_obj, dict):
negative_pians.add(pian_obj.get('id'))
djs = akce.get('az_dokumentacni_jednotka', [])
for dj in djs:
is_negative = dj.get('dj_negativni_jednotka')
if is_negative is True or str(is_negative).lower() == 'true':
# Získáme ID pianu z objektu (např. {"id": "P-...", "value": "..."})
pian_obj = dj.get('dj_pian')
if pian_obj and isinstance(pian_obj, dict):
negative_dj_pian_ids.add(pian_obj.get('id'))
if not piani:
continue
actions_with_geom += 1
def g(key, default=""):
val = akce.get(key)
if isinstance(val, list): return str(val[0]) if val else default
if isinstance(val, list):
return str(val[0]) if val else default
return str(val) if val is not None else default
def g_list(key, translate=False):
val = akce.get(key, [])
if not isinstance(val, list): val = [val] if val else []
if not isinstance(val, list):
val = [val] if val else []
if translate:
return ", ".join([tr_code(str(x)) for x in val if x])
return ", ".join([str(x) for x in val if x])
@@ -199,15 +183,31 @@ def load_amcr_data(canvas, bb, filters=None):
"loc": g_list('loc')
}
for pid in piani:
if pid in negative_pians:
djs = akce.get('az_dokumentacni_jednotka', [])
for dj in djs:
if filters and filters.get('posevidence') == 'true' and dj.get('dj_negativni_jednotka') is True:
continue
pian_lookup[pid] = meta
target_pian_ids.add(pid)
dj_meta = meta.copy()
dj_meta['dj_id'] = dj.get('ident_cely')
dj_typ = dj.get('dj_typ')
dj_meta['dj_typ_value'] = dj_typ.get('value') if dj_typ else ""
dj_meta['dj_negativni'] = "Negativní" if dj.get('dj_negativni_jednotka') is True else "Pozitivní"
dj_pian = dj.get('dj_pian')
if dj_pian:
dj_pian_value = dj_pian.get('id')
if dj_pian_value:
target_pian_ids.add(dj_pian_value)
target_pian_ids_count = target_pian_ids_count+1
if dj_pian_value not in pian_lookup:
pian_lookup[dj_pian_value] = []
pian_lookup[dj_pian_value].append(dj_meta)
if not target_pian_ids:
iface.messageBar().pushMessage("AMCR", f"Nalezeno {len(docs_akce)} akcí, ale žádná nemá geometrii.", level=1)
return
return
# ==========================================
# B) Geometry (PIAN)
@@ -217,7 +217,7 @@ def load_amcr_data(canvas, bb, filters=None):
docs_pian = []
BATCH_PIAN = 50
iface.messageBar().pushMessage("AMCR", f"Akcí: {len(docs_akce)} (z toho {actions_with_geom} s mapou). Stahuji {total_pians} geometrií...", level=1)
iface.messageBar().pushMessage("AMCR", f"Akcí: {len(docs_akce)} (z toho {actions_with_geom} s mapou). Stahuji {total_pians} unikátních geometrií, vykresluji {target_pian_ids_count} geometrií...", level=1)
# Seznam polí pro PIAN
fl_pian = ["ident_cely", "pian_typ", "pian_chranene_udaje", "pian_presnost"]
@@ -255,9 +255,11 @@ def load_amcr_data(canvas, bb, filters=None):
QgsField("PIAN", QVariant.String),
QgsField("Přesnost", QVariant.String),
QgsField("PIAN typ", QVariant.String),
QgsField("Dokumentační jednotka", QVariant.String),
QgsField("Typ dokumentační jednotky", QVariant.String),
QgsField("Definiční bod(y) (WGS-84)", QVariant.String),
QgsField("Identifikátor", QVariant.String),
QgsField("Odkaz do Digiarchivu", QVariant.String),
QgsField("Akce", QVariant.String),
QgsField("Odkaz do Digitálního archivu AMČR", QVariant.String),
QgsField("Okres", QVariant.String),
QgsField("Katastr", QVariant.String),
QgsField("Další katastry", QVariant.String),
@@ -270,7 +272,7 @@ def load_amcr_data(canvas, bb, filters=None):
QgsField("Vedlejší typ", QVariant.String),
QgsField("Zjištění", QVariant.String),
QgsField("Akce lokalizace", QVariant.String),
QgsField("Akce - nahrazuje NZ", QVariant.String),
QgsField("Akce nahrazuje NZ", QVariant.String),
QgsField("Přístupnost", QVariant.String)
]
@@ -283,55 +285,68 @@ def load_amcr_data(canvas, bb, filters=None):
for doc in docs_pian:
try:
pid = doc.get('ident_cely', '')
if pid not in pian_lookup: continue
meta = pian_lookup[pid]
if pid not in pian_lookup:
continue
metas = pian_lookup[pid]
# Geometry processing
raw = doc.get('pian_chranene_udaje')
if isinstance(raw, list) and raw: raw = raw[0]
if isinstance(raw, list) and raw:
raw = raw[0]
jdata = json.loads(raw) if isinstance(raw, str) else (raw if isinstance(raw, dict) else {})
wkt = None
if jdata.get('geom_sjtsk_wkt'): wkt = jdata['geom_sjtsk_wkt'].get('value')
elif jdata.get('geom_wkt'): wkt = jdata['geom_wkt'].get('value')
if jdata.get('geom_sjtsk_wkt'):
wkt = jdata['geom_sjtsk_wkt'].get('value')
elif jdata.get('geom_wkt'):
wkt = jdata['geom_wkt'].get('value')
# PIAN attributes
pian_presnost = tr_code(str(doc.get('pian_presnost', '')))
pian_typ = tr_code(str(doc.get('pian_typ', '')))
dj_negativni = "Negativní" if pid in negative_dj_pian_ids else "Pozitivní"
if filters and filters.get('f_pian_presnost') and doc.get('pian_presnost') not in filters.get('f_pian_presnost'):
continue
if wkt:
geom = QgsGeometry.fromWkt(wkt)
if geom.isGeosValid():
feat = QgsFeature()
feat.setGeometry(geom)
feat.setAttributes([
pid,
pian_presnost,
pian_typ,
meta['loc'],
meta['ident_cely'],
"https://digiarchiv.aiscr.cz/id/" + meta['ident_cely'],
meta['az_okres'],
meta['katastr'],
meta['dalsi_katastr'],
meta['akce_hlavni_vedouci'],
meta['akce_organizace'],
meta['akce_specifikace_data'],
meta['akce_datum_zahajeni'],
meta['akce_datum_ukonceni'],
meta['akce_hlavni_typ'],
meta['akce_vedlejsi_typ'],
dj_negativni,
meta['lokalizace_okolnosti'],
meta['akce_je_nz'],
meta['pristupnost']
])
t = geom.type()
if t == QgsWkbTypes.PolygonGeometry: feats_p.append(feat)
elif t == QgsWkbTypes.LineGeometry: feats_l.append(feat)
elif t == QgsWkbTypes.PointGeometry: feats_pt.append(feat)
for meta in metas:
feat = QgsFeature()
feat.setGeometry(geom)
feat.setAttributes([
pid,
pian_presnost,
pian_typ,
meta['dj_id'],
meta['dj_typ_value'],
meta['loc'],
meta['ident_cely'],
"https://digiarchiv.aiscr.cz/id/" + meta['ident_cely'],
meta['az_okres'],
meta['katastr'],
meta['dalsi_katastr'],
meta['akce_hlavni_vedouci'],
meta['akce_organizace'],
meta['akce_specifikace_data'],
meta['akce_datum_zahajeni'],
meta['akce_datum_ukonceni'],
meta['akce_hlavni_typ'],
meta['akce_vedlejsi_typ'],
meta['dj_negativni'],
meta['lokalizace_okolnosti'],
meta['akce_je_nz'],
meta['pristupnost']
])
t = geom.type()
if t == QgsWkbTypes.PolygonGeometry:
feats_p.append(feat)
elif t == QgsWkbTypes.LineGeometry:
feats_l.append(feat)
elif t == QgsWkbTypes.PointGeometry:
feats_pt.append(feat)
except Exception as ex:
print(f"Chyba při tvorbě feature: {ex}")
pass
@@ -355,68 +370,3 @@ def load_amcr_data(canvas, bb, filters=None):
iface.messageBar().pushMessage("Chyba", str(e), level=2)
finally:
QApplication.restoreOverrideCursor()
# class AmcrIdentifyTool(QgsMapToolIdentifyFeature):
# def __init__(self, canvas):
# super().__init__(canvas)
# self.canvas = canvas
# self.setCursor(Qt.CrossCursor)
# def canvasReleaseEvent(self, event):
# results = self.identify(event.x(), event.y(), self.IdentifyMode.TopDownStopAtFirst, self.VectorLayer)
# if not results: return
# feature = results[0].mFeature
# akce_id = None
# # Změna: hledáme 'ident_cely' (ID akce)
# idx = feature.fieldNameIndex('ident_cely')
# if idx != -1:
# akce_id = feature.attributes()[idx]
# # Fallback na starší názvy polí, kdyby něco
# if not akce_id:
# for col in ['akce_id', 'ident_cely', 'pian_id']:
# if col in feature.fields().names():
# akce_id = feature[col]
# break
# if not akce_id: return
# full_id = akce_id if "api.aiscr.cz" in str(akce_id) else f"https://api.aiscr.cz/id/{akce_id}"
# url = f"https://api.aiscr.cz/2.2/oai?verb=GetRecord&metadataPrefix=oai_amcr&identifier={full_id}"
# iface.messageBar().pushMessage("AMCR", f"Detail: {akce_id}...", level=1)
# QApplication.setOverrideCursor(Qt.WaitCursor)
# try:
# r = requests.get(url, timeout=5)
# if r.status_code == 200: self.show_detail(akce_id, r.text)
# except Exception as e:
# iface.messageBar().pushMessage("Chyba", str(e), level=2)
# finally:
# QApplication.restoreOverrideCursor()
# def show_detail(self, title, raw_xml):
# xml = re.sub(r'\sxmlns="[^"]+"', '', raw_xml, count=1)
# xml = re.sub(r'<(/?)[a-zA-Z0-9]+:', r'<\1', xml)
# info = ""
# try:
# root = ET.fromstring(xml)
# rec = root.find('.//archeologicky_zaznam')
# if not rec: info = "Zadna data."
# else:
# kat = rec.find('.//hlavni_katastr')
# info += f"<h3>{kat.text if kat is not None else '?'}</h3>"
# for dj in rec.findall('.//dokumentacni_jednotka'):
# pn = dj.find('pian')
# p_txt = pn.text if pn is not None else ""
# info += f"<hr><b>PIAN: {p_txt}</b><ul>"
# for k in dj.findall('komponenta'):
# ob = k.find('obdobi').text or "?"
# ar = k.find('areal').text or "?"
# info += f"<li>{ob} ({ar})</li>"
# info += "</ul>"
# dlg = QMessageBox()
# dlg.setWindowTitle(str(title))
# dlg.setText(info)
# dlg.setTextFormat(Qt.RichText)
# dlg.exec_()
# except: pass
+1 -27
View File
@@ -3,7 +3,7 @@ from qgis.PyQt.QtCore import QSettings, QTranslator, QCoreApplication
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import QAction
from .amcr_tools import load_amcr_data#, AmcrIdentifyTool
from .amcr_tools import load_amcr_data
from .amcr_dialog import AmcrFilterDialog
from .resources import *
import os.path
@@ -61,7 +61,6 @@ class AmcrViewer:
icon = QIcon(os.path.join(plugin_dir, 'download.png'))
# icon_info = QIcon(os.path.join(plugin_dir, 'info.png'))
# Download data button
self.action_download = self.add_action(
@@ -70,14 +69,6 @@ class AmcrViewer:
callback=self.run_download,
parent=self.iface.mainWindow())
# # Info button (Checkable / Toggle)
# self.action_tool = self.add_action(
# icon_info,
# text=self.tr(u'Výpis údajů záznamu'),
# callback=self.run_tool,
# parent=self.iface.mainWindow())
# self.action_tool.setCheckable(True) # Toto tlačítko se zamačkává
self.first_start = True
def unload(self):
@@ -100,20 +91,3 @@ class AmcrViewer:
canvas = self.iface.mapCanvas()
load_amcr_data(canvas, bbox, filters)
# --- Info button toggle ---
# def run_tool(self):
# if self.action_tool.isChecked():
# canvas = self.iface.mapCanvas()
# if not hasattr(self, 'tool'):
# self.tool = AmcrIdentifyTool(canvas)
# self.tool.deactivated.connect(lambda: self.action_tool.setChecked(False))
# canvas.setMapTool(self.tool)
# self.iface.messageBar().pushMessage("AMČR", "Info nástroj aktivní.", level=0)
# else:
# if self.iface.mapCanvas().mapTool() == getattr(self, 'tool', None):
# self.iface.mapCanvas().unsetMapTool(self.tool)
+4
View File
@@ -13614,3 +13614,7 @@ Zvotoky;Zvotoky;katastr
Žumberk u Nových Hradů;Žumberk u Nových Hradů;katastr
Županovice;Županovice;katastr
Županovice u Dešné;Županovice u Dešné;katastr
odchylka jednotky metrů;HES-000861;pian_presnost
odchylka desítky metrů;HES-000862;pian_presnost
odchylka stovky metrů;HES-000863;pian_presnost
poloha podle katastru;HES-000864;pian_presnost
1 Název Kód Kategorie
13614 Žumberk u Nových Hradů Žumberk u Nových Hradů katastr
13615 Županovice Županovice katastr
13616 Županovice u Dešné Županovice u Dešné katastr
13617 odchylka jednotky metrů HES-000861 pian_presnost
13618 odchylka desítky metrů HES-000862 pian_presnost
13619 odchylka stovky metrů HES-000863 pian_presnost
13620 poloha podle katastru HES-000864 pian_presnost
+1 -1
View File
@@ -6,7 +6,7 @@
name=AMČR Viewer
qgisMinimumVersion=3.4
description=Viewing and downloading the AMČR data.
version=1.0.2
version=1.1.0
author=David Spáčil
email=spacil@arub.cz