mirror of
https://github.com/ARUP-CAS/aiscr-qgis-amcr-viewer.git
synced 2026-06-17 11:22:53 +02:00
Feature/login (#36)
* přidáno nové tlačítko do toolbaru * přihlašovací dialog * funkce pro přihlašování * aplikace získávání dat z API přes session * zastřešující akce v main skriptu * ošetření prodlužování session/opětovné přihlášení * přidání přístupnosti do hesláře * aktualizace přibaleného hesláře * oprava stahování hesláře (pristupnost vyžaduje písmeno [A/B/C/D], ne heslo; aktualizace hesláře * aplikace přístupnosti do filtračního dialogu * úpravy přihlašovacího dialogu
This commit is contained in:
@@ -25,7 +25,8 @@ slovnicek = {
|
|||||||
'typ_lokality' : 'heslo:lokalita_typ',
|
'typ_lokality' : 'heslo:lokalita_typ',
|
||||||
'druh_lokality' : 'heslo:lokalita_druh',
|
'druh_lokality' : 'heslo:lokalita_druh',
|
||||||
'jistota' : 'heslo:jistota_urceni',
|
'jistota' : 'heslo:jistota_urceni',
|
||||||
'lokalita_zachovalost' : 'heslo:stav_dochovani'
|
'lokalita_zachovalost' : 'heslo:stav_dochovani',
|
||||||
|
'pristupnost' : 'heslo:pristupnost'
|
||||||
}
|
}
|
||||||
|
|
||||||
NS = {
|
NS = {
|
||||||
@@ -78,7 +79,7 @@ def parse_codelist_file(filename, target_dict=None):
|
|||||||
return target_dict
|
return target_dict
|
||||||
|
|
||||||
def load_all_data():
|
def load_all_data():
|
||||||
"""Loads all static and dynamic codelists during plugin startup."""
|
"""Loads the codelist during plugin startup."""
|
||||||
ensure_codelists_dir()
|
ensure_codelists_dir()
|
||||||
categorized_data = {k: {} for k in slovnicek.keys()}
|
categorized_data = {k: {} for k in slovnicek.keys()}
|
||||||
parse_codelist_file('heslar.csv', categorized_data)
|
parse_codelist_file('heslar.csv', categorized_data)
|
||||||
@@ -125,6 +126,9 @@ def fetch_set(internal_name, api_set, task=None):
|
|||||||
if internal_name in specialni_pripady:
|
if internal_name in specialni_pripady:
|
||||||
kod = nazev
|
kod = nazev
|
||||||
|
|
||||||
|
if internal_name == 'pristupnost':
|
||||||
|
kod = next((t.text for t in titles if t.text and len(t.text) == 1 and t.text.isalpha()), None)
|
||||||
|
|
||||||
dataset.append({
|
dataset.append({
|
||||||
'Název': nazev,
|
'Název': nazev,
|
||||||
'Kód': kod,
|
'Kód': kod,
|
||||||
@@ -186,7 +190,7 @@ def download_heslare(task=None):
|
|||||||
def refresh_globals():
|
def refresh_globals():
|
||||||
"""Znovu načte data ze souborů do globálních proměnných."""
|
"""Znovu načte data ze souborů do globálních proměnných."""
|
||||||
global OBDOBI, TYP_AKCE, AREAL, KRAJE, ORGANIZACE, OKRESY, KATASTRY
|
global OBDOBI, TYP_AKCE, AREAL, KRAJE, ORGANIZACE, OKRESY, KATASTRY
|
||||||
global VEDOUCI, PIAN_PRESNOST, TYP_LOKALITY, DRUH_LOKALITY, JISTOTA, LOKALITA_ZACHOVALOST
|
global VEDOUCI, PIAN_PRESNOST, TYP_LOKALITY, DRUH_LOKALITY, JISTOTA, LOKALITA_ZACHOVALOST, PRISTUPNOST
|
||||||
|
|
||||||
data = load_all_data()
|
data = load_all_data()
|
||||||
|
|
||||||
@@ -216,6 +220,9 @@ def refresh_globals():
|
|||||||
JISTOTA.update(data.get('jistota', {}))
|
JISTOTA.update(data.get('jistota', {}))
|
||||||
LOKALITA_ZACHOVALOST.clear()
|
LOKALITA_ZACHOVALOST.clear()
|
||||||
LOKALITA_ZACHOVALOST.update(data.get('lokalita_zachovalost', {}))
|
LOKALITA_ZACHOVALOST.update(data.get('lokalita_zachovalost', {}))
|
||||||
|
PRISTUPNOST.clear()
|
||||||
|
PRISTUPNOST.update(data.get('pristupnost', {}))
|
||||||
|
|
||||||
|
|
||||||
# Inicializace prázdných diktů, které se naplní hned pod tím
|
# Inicializace prázdných diktů, které se naplní hned pod tím
|
||||||
OBDOBI = {}
|
OBDOBI = {}
|
||||||
@@ -231,5 +238,6 @@ TYP_LOKALITY = {}
|
|||||||
DRUH_LOKALITY = {}
|
DRUH_LOKALITY = {}
|
||||||
JISTOTA = {}
|
JISTOTA = {}
|
||||||
LOKALITA_ZACHOVALOST = {}
|
LOKALITA_ZACHOVALOST = {}
|
||||||
|
PRISTUPNOST = {}
|
||||||
|
|
||||||
refresh_globals()
|
refresh_globals()
|
||||||
+105
-5
@@ -1,14 +1,15 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
import base64
|
||||||
from qgis.PyQt.QtWidgets import (QDialog, QVBoxLayout,
|
from qgis.PyQt.QtWidgets import (QDialog, QVBoxLayout,
|
||||||
QLineEdit, QDialogButtonBox,
|
QLineEdit, QDialogButtonBox,
|
||||||
QCheckBox, QGroupBox, QPushButton,
|
QCheckBox, QGroupBox, QPushButton,
|
||||||
QListWidget, QListWidgetItem, QHBoxLayout,
|
QListWidget, QListWidgetItem, QHBoxLayout,
|
||||||
QMessageBox)
|
QMessageBox, QLabel, QFormLayout)
|
||||||
from qgis.PyQt.QtCore import Qt
|
from qgis.PyQt.QtCore import Qt, QSettings
|
||||||
from qgis.core import QgsTask, QgsApplication, QgsMessageLog, Qgis
|
from qgis.core import QgsTask, QgsApplication, QgsMessageLog, Qgis
|
||||||
from .amcr_codelists import (OBDOBI, TYP_AKCE, KRAJE, AREAL, ORGANIZACE,
|
from .amcr_codelists import (OBDOBI, TYP_AKCE, KRAJE, AREAL, ORGANIZACE,
|
||||||
OKRESY, KATASTRY, VEDOUCI, PIAN_PRESNOST, TYP_LOKALITY,
|
OKRESY, KATASTRY, VEDOUCI, PIAN_PRESNOST, TYP_LOKALITY,
|
||||||
DRUH_LOKALITY, JISTOTA, LOKALITA_ZACHOVALOST,
|
DRUH_LOKALITY, JISTOTA, LOKALITA_ZACHOVALOST, PRISTUPNOST,
|
||||||
download_heslare, refresh_globals)
|
download_heslare, refresh_globals)
|
||||||
|
|
||||||
class UpdateCodelistsTask(QgsTask):
|
class UpdateCodelistsTask(QgsTask):
|
||||||
@@ -133,7 +134,7 @@ class AmcrFilterDialog(QDialog):
|
|||||||
# Cache dictionary to store selected codes for each category
|
# Cache dictionary to store selected codes for each category
|
||||||
self.selection_cache = {
|
self.selection_cache = {
|
||||||
'organizace': [], 'kraj': [], 'obdobi': [], 'areal': [],
|
'organizace': [], 'kraj': [], 'obdobi': [], 'areal': [],
|
||||||
'typ_akce': [], 'okres': [], 'katastr': [], 'vedouci': [], 'pian_presnost': [],
|
'typ_akce': [], 'okres': [], 'katastr': [], 'vedouci': [], 'pian_presnost': [], 'pristupnost': [],
|
||||||
'typ_lokality': [], 'druh_lokality': [], 'jistota': [], 'lokalita_zachovalost': []
|
'typ_lokality': [], 'druh_lokality': [], 'jistota': [], 'lokalita_zachovalost': []
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,6 +166,9 @@ class AmcrFilterDialog(QDialog):
|
|||||||
|
|
||||||
self.picker_presnost = self.setup_picker("PIAN – přesnost", 'pian_presnost', PIAN_PRESNOST)
|
self.picker_presnost = self.setup_picker("PIAN – přesnost", 'pian_presnost', PIAN_PRESNOST)
|
||||||
layout.addWidget(self.picker_presnost)
|
layout.addWidget(self.picker_presnost)
|
||||||
|
|
||||||
|
self.picker_pristupnost = self.setup_picker("Přístupnost", 'pristupnost', PRISTUPNOST)
|
||||||
|
layout.addWidget(self.picker_pristupnost)
|
||||||
|
|
||||||
# Filters valid for Akce
|
# Filters valid for Akce
|
||||||
|
|
||||||
@@ -321,6 +325,8 @@ class AmcrFilterDialog(QDialog):
|
|||||||
filters['f_areal'] = self.selection_cache['areal']
|
filters['f_areal'] = self.selection_cache['areal']
|
||||||
if self.selection_cache['pian_presnost']:
|
if self.selection_cache['pian_presnost']:
|
||||||
filters['f_pian_presnost'] = self.selection_cache['pian_presnost']
|
filters['f_pian_presnost'] = self.selection_cache['pian_presnost']
|
||||||
|
if self.selection_cache['pristupnost']:
|
||||||
|
filters['pristupnost'] = self.selection_cache['pristupnost']
|
||||||
|
|
||||||
if self.typ_dat == "akce":
|
if self.typ_dat == "akce":
|
||||||
if self.chk_posevidence.isChecked():
|
if self.chk_posevidence.isChecked():
|
||||||
@@ -342,4 +348,98 @@ class AmcrFilterDialog(QDialog):
|
|||||||
if self.selection_cache['lokalita_zachovalost']:
|
if self.selection_cache['lokalita_zachovalost']:
|
||||||
filters['f_lokalita_zachovalost'] = self.selection_cache['lokalita_zachovalost']
|
filters['f_lokalita_zachovalost'] = self.selection_cache['lokalita_zachovalost']
|
||||||
|
|
||||||
return filters
|
return filters
|
||||||
|
|
||||||
|
class LoginDialog(QDialog):
|
||||||
|
"""
|
||||||
|
Dialog pro uložení přihlašovacích údajů do AMČR.
|
||||||
|
Ukládá do QSettings (username plaintext, heslo base64).
|
||||||
|
"""
|
||||||
|
|
||||||
|
KEY_USER = "amcr_viewer/username"
|
||||||
|
KEY_PASS = "amcr_viewer/password"
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.setWindowTitle("Přihlášení do AMČR")
|
||||||
|
self.setMinimumWidth(360)
|
||||||
|
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
|
||||||
|
settings = QSettings()
|
||||||
|
has_saved = bool(settings.value(self.KEY_USER, ""))
|
||||||
|
|
||||||
|
if has_saved:
|
||||||
|
info = QLabel("✔ Přihlašovací údaje jsou uloženy. Vyplňte pole níže pro jejich změnu.")
|
||||||
|
info.setStyleSheet("color: green; font-style: italic;")
|
||||||
|
else:
|
||||||
|
info = QLabel("Zadejte přihlašovací údaje k Digitálnímu archivu AMČR.\nVarování: přihlašovací údaje budou nezašifrovaně uloženy v registrech systému.")
|
||||||
|
info.setWordWrap(True)
|
||||||
|
layout.addWidget(info)
|
||||||
|
layout.addSpacing(8)
|
||||||
|
|
||||||
|
form = QFormLayout()
|
||||||
|
|
||||||
|
self.txt_user = QLineEdit()
|
||||||
|
self.txt_user.setPlaceholderText("např. jan.novak@email.cz")
|
||||||
|
# Předvyplnit uložené jméno pro pohodlí
|
||||||
|
self.txt_user.setText(settings.value(self.KEY_USER, ""))
|
||||||
|
form.addRow("E-mail:", self.txt_user)
|
||||||
|
|
||||||
|
self.txt_pass = QLineEdit()
|
||||||
|
self.txt_pass.setEchoMode(QLineEdit.EchoMode.Password)
|
||||||
|
self.txt_pass.setPlaceholderText("heslo")
|
||||||
|
form.addRow("Heslo:", self.txt_pass)
|
||||||
|
|
||||||
|
layout.addLayout(form)
|
||||||
|
layout.addSpacing(8)
|
||||||
|
|
||||||
|
if has_saved:
|
||||||
|
btn_forget = QPushButton("Zapomenout uložené přihlašovací údaje")
|
||||||
|
btn_forget.setStyleSheet("color: #c0392b;")
|
||||||
|
btn_forget.clicked.connect(self._forget_credentials)
|
||||||
|
layout.addWidget(btn_forget)
|
||||||
|
|
||||||
|
layout.addStretch(1)
|
||||||
|
|
||||||
|
buttons = QDialogButtonBox(
|
||||||
|
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
|
||||||
|
)
|
||||||
|
buttons.accepted.connect(self._save_and_accept)
|
||||||
|
buttons.rejected.connect(self.reject)
|
||||||
|
layout.addWidget(buttons)
|
||||||
|
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
def _save_and_accept(self):
|
||||||
|
username = self.txt_user.text().strip()
|
||||||
|
password = self.txt_pass.text()
|
||||||
|
|
||||||
|
if not username or not password:
|
||||||
|
QMessageBox.warning(self, "Chybí údaje", "Vyplňte prosím uživatelské jméno i heslo.")
|
||||||
|
return
|
||||||
|
|
||||||
|
settings = QSettings()
|
||||||
|
settings.setValue(self.KEY_USER, username)
|
||||||
|
# base64 není šifrování, ale heslo aspoň neleží v plaintextu v registru
|
||||||
|
settings.setValue(self.KEY_PASS, base64.b64encode(password.encode()).decode())
|
||||||
|
self.accept()
|
||||||
|
|
||||||
|
def _forget_credentials(self):
|
||||||
|
settings = QSettings()
|
||||||
|
settings.remove(self.KEY_USER)
|
||||||
|
settings.remove(self.KEY_PASS)
|
||||||
|
QMessageBox.information(self, "Hotovo", "Přihlašovací údaje byly odstraněny.")
|
||||||
|
self.reject()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_credentials() -> tuple[str, str]:
|
||||||
|
"""Vrátí (username, password) z QSettings, nebo ('', '') pokud nejsou uloženy."""
|
||||||
|
settings = QSettings()
|
||||||
|
username = settings.value(LoginDialog.KEY_USER, "")
|
||||||
|
encoded = settings.value(LoginDialog.KEY_PASS, "")
|
||||||
|
try:
|
||||||
|
password = base64.b64decode(encoded.encode()).decode() if encoded else ""
|
||||||
|
except Exception:
|
||||||
|
password = ""
|
||||||
|
return username, password
|
||||||
+113
-3
@@ -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, Qgis)
|
QgsWkbTypes, Qgis, QgsApplication, QgsAuthMethodConfig, QgsMessageLog)
|
||||||
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
|
||||||
@@ -12,6 +12,116 @@ import json
|
|||||||
# Global cache to store translated terms from the Digital Archive
|
# Global cache to store translated terms from the Digital Archive
|
||||||
TRANSLATIONS = {}
|
TRANSLATIONS = {}
|
||||||
|
|
||||||
|
# Session s autentizační cookie po přihlášení; None = nepřihlášen (anonymní přístup)
|
||||||
|
AMCR_SESSION: requests.Session | None = None
|
||||||
|
|
||||||
|
def _log(msg: str, level=Qgis.MessageLevel.Info):
|
||||||
|
"""Shortcut: zapíše zprávu do QGIS logu (panel Zprávy → záložka AMČR)."""
|
||||||
|
QgsMessageLog.logMessage(msg, "AMČR login", level)
|
||||||
|
|
||||||
|
|
||||||
|
def login_to_api(username: str, password: str):
|
||||||
|
"""
|
||||||
|
Přihlásí se do Digiarchiv API pomocí username a hesla.
|
||||||
|
Vrátí requests.Session s nastavenou session cookie, nebo None při chybě.
|
||||||
|
"""
|
||||||
|
login_url = "https://digiarchiv.aiscr.cz/api/user/login"
|
||||||
|
|
||||||
|
_log(f"Přihlašuji uživatele: '{username}'")
|
||||||
|
|
||||||
|
if not username or not password:
|
||||||
|
_log("CHYBA: username nebo heslo je prázdné.", Qgis.MessageLevel.Critical)
|
||||||
|
return None
|
||||||
|
|
||||||
|
session = requests.Session()
|
||||||
|
session.headers.update({
|
||||||
|
"Accept": "application/json, text/plain, */*",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"User-Agent": "QGIS-Plugin/1.0 (AISCR Data Fetcher)"
|
||||||
|
})
|
||||||
|
|
||||||
|
try:
|
||||||
|
_log(f"Odesílám POST na {login_url} ...")
|
||||||
|
response = session.post(login_url, json={"user": username, "pwd": password}, timeout=10)
|
||||||
|
_log(f"HTTP status: {response.status_code}")
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
# API vrací chyby se status kódem 200 – je nutné zkontrolovat tělo odpovědi
|
||||||
|
body = response.json()
|
||||||
|
if "error" in body:
|
||||||
|
_log(f"CHYBA přihlášení (API): {body['error']}", Qgis.MessageLevel.Critical)
|
||||||
|
return None
|
||||||
|
|
||||||
|
_log("Přihlášení proběhlo úspěšně.")
|
||||||
|
global AMCR_SESSION
|
||||||
|
AMCR_SESSION = session
|
||||||
|
return session
|
||||||
|
|
||||||
|
except requests.exceptions.HTTPError as e:
|
||||||
|
_log(f"CHYBA HTTP {e.response.status_code if e.response else '?'}: "
|
||||||
|
f"{e.response.text[:300] if e.response else 'žádná odpověď'}", Qgis.MessageLevel.Critical)
|
||||||
|
return None
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
_log(f"CHYBA sítě: {e}", Qgis.MessageLevel.Critical)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _get_session() -> requests.Session | None:
|
||||||
|
"""
|
||||||
|
Vrátí aktivní session. Pokud žádná není (restart QGIS), pokusí se
|
||||||
|
automaticky přihlásit pomocí uložených přihlašovacích údajů.
|
||||||
|
Vrátí None pokud přihlašovací údaje nejsou uloženy.
|
||||||
|
"""
|
||||||
|
global AMCR_SESSION
|
||||||
|
if AMCR_SESSION is not None:
|
||||||
|
return AMCR_SESSION
|
||||||
|
|
||||||
|
# Zkusit auto-login pomocí uložených údajů
|
||||||
|
from .amcr_dialog import LoginDialog
|
||||||
|
username, password = LoginDialog.get_credentials()
|
||||||
|
if username and password:
|
||||||
|
_log("Session vypršela nebo chybí – automatické přihlášení...")
|
||||||
|
AMCR_SESSION = login_to_api(username, password)
|
||||||
|
|
||||||
|
return AMCR_SESSION
|
||||||
|
|
||||||
|
|
||||||
|
def _api_get(url, params, timeout=30) -> requests.Response:
|
||||||
|
"""
|
||||||
|
Provede GET request. Pokud API signalizuje vypršení přihlášení,
|
||||||
|
provede jedno opakované přihlášení a zkusí znovu.
|
||||||
|
"""
|
||||||
|
global AMCR_SESSION
|
||||||
|
|
||||||
|
def _is_auth_error(resp: requests.Response) -> bool:
|
||||||
|
"""API vrací auth chyby se status 200 – je nutné zkontrolovat tělo."""
|
||||||
|
if resp.status_code == 401:
|
||||||
|
return True
|
||||||
|
try:
|
||||||
|
body = resp.json()
|
||||||
|
err = str(body.get("error", "")).lower()
|
||||||
|
return "unauthorized" in err or "not logged" in err or "session" in err
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
session = _get_session()
|
||||||
|
resp = (session or requests).get(url, params=params, timeout=timeout)
|
||||||
|
|
||||||
|
if _is_auth_error(resp):
|
||||||
|
_log("Session vypršela během stahování – obnovuji přihlášení...", Qgis.MessageLevel.Warning)
|
||||||
|
AMCR_SESSION = None # Zrušit starou session
|
||||||
|
from .amcr_dialog import LoginDialog
|
||||||
|
username, password = LoginDialog.get_credentials()
|
||||||
|
if username and password:
|
||||||
|
AMCR_SESSION = login_to_api(username, password)
|
||||||
|
if AMCR_SESSION:
|
||||||
|
resp = AMCR_SESSION.get(url, params=params, timeout=timeout)
|
||||||
|
else:
|
||||||
|
_log("Opakované přihlášení selhalo.", Qgis.MessageLevel.Critical)
|
||||||
|
else:
|
||||||
|
_log("Přihlašovací údaje nejsou uloženy – pokračuji anonymně.", Qgis.MessageLevel.Warning)
|
||||||
|
|
||||||
|
return resp
|
||||||
|
|
||||||
def load_translations():
|
def load_translations():
|
||||||
"""Fetches the official Czech translation dictionary from the AISCR API."""
|
"""Fetches the official Czech translation dictionary from the AISCR API."""
|
||||||
global TRANSLATIONS
|
global TRANSLATIONS
|
||||||
@@ -103,7 +213,7 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false")
|
|||||||
del base_params['page']
|
del base_params['page']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
resp_docs = requests.get(url, params=base_params, timeout=30)
|
resp_docs = _api_get(url, params=base_params, timeout=30)
|
||||||
resp_json = resp_docs.json()
|
resp_json = resp_docs.json()
|
||||||
data = resp_json.get('response', {})
|
data = resp_json.get('response', {})
|
||||||
batch_docs = data.get('docs', [])
|
batch_docs = data.get('docs', [])
|
||||||
@@ -308,7 +418,7 @@ def load_amcr_data(canvas, bb, filters=None, typ_dat="akce", komponenty="false")
|
|||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
QApplication.processEvents()
|
QApplication.processEvents()
|
||||||
r_pian = requests.get(url, params=params_pian, timeout=15)
|
r_pian = _api_get(url, params=params_pian, timeout=15)
|
||||||
batch_docs = r_pian.json().get('response', {}).get('docs', [])
|
batch_docs = r_pian.json().get('response', {}).get('docs', [])
|
||||||
docs_pian.extend(batch_docs)
|
docs_pian.extend(batch_docs)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -2,9 +2,11 @@
|
|||||||
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, QDialog
|
from qgis.PyQt.QtWidgets import QMenu, QAction, QToolButton, QDialog
|
||||||
|
from qgis.core import Qgis
|
||||||
|
from qgis.utils import iface
|
||||||
|
|
||||||
from .amcr_tools import load_amcr_data
|
from .amcr_tools import load_amcr_data, login_to_api
|
||||||
from .amcr_dialog import AmcrFilterDialog
|
from .amcr_dialog import AmcrFilterDialog, LoginDialog
|
||||||
from .resources import *
|
from .resources import *
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
@@ -109,6 +111,16 @@ class AmcrViewer:
|
|||||||
)
|
)
|
||||||
self.plugin_menu.addAction(self.action_download_lokality)
|
self.plugin_menu.addAction(self.action_download_lokality)
|
||||||
|
|
||||||
|
self.action_login_dialog = self.add_action(
|
||||||
|
icon_path=icon_akce_path,
|
||||||
|
text=self.tr(u'Přihlásit se | AMČR Viewer'),
|
||||||
|
callback=lambda checked=False: self.login(),
|
||||||
|
parent=self.iface.mainWindow(),
|
||||||
|
add_to_menu=False,
|
||||||
|
add_to_toolbar=False
|
||||||
|
)
|
||||||
|
self.plugin_menu.addAction(self.action_login_dialog)
|
||||||
|
|
||||||
# 3. Create the main project action and attach the menu to it
|
# 3. Create the main project action and attach the menu to it
|
||||||
main_icon = QIcon(icon_akce_path)
|
main_icon = QIcon(icon_akce_path)
|
||||||
self.main_action = QAction(main_icon, 'AMČR Viewer', self.iface.mainWindow())
|
self.main_action = QAction(main_icon, 'AMČR Viewer', self.iface.mainWindow())
|
||||||
@@ -168,4 +180,19 @@ class AmcrViewer:
|
|||||||
|
|
||||||
# Access the map canvas and start the fetch/render process from amcr_tools
|
# Access the map canvas and start the fetch/render process from amcr_tools
|
||||||
canvas = self.iface.mapCanvas()
|
canvas = self.iface.mapCanvas()
|
||||||
load_amcr_data(canvas, bbox, filters, typ_dat, komponenty)
|
load_amcr_data(canvas, bbox, filters, typ_dat, komponenty)
|
||||||
|
|
||||||
|
def login(self):
|
||||||
|
dlg = LoginDialog(parent=self.iface.mainWindow())
|
||||||
|
result = dlg.exec()
|
||||||
|
if result == QDialog.DialogCode.Accepted:
|
||||||
|
username, password = LoginDialog.get_credentials()
|
||||||
|
session = login_to_api(username, password)
|
||||||
|
if session:
|
||||||
|
self.iface.messageBar().pushMessage(
|
||||||
|
"AMČR", "Přihlášení proběhlo úspěšně.", level=Qgis.MessageLevel.Success
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.iface.messageBar().pushMessage(
|
||||||
|
"AMČR", "Přihlášení se nezdařilo – viz záložka AMČR login v panelu Zprávy.", level=Qgis.MessageLevel.Critical
|
||||||
|
)
|
||||||
@@ -523,6 +523,9 @@ Děčín;Děčín;okres
|
|||||||
Česká Lípa;Česká Lípa;okres
|
Česká Lípa;Česká Lípa;okres
|
||||||
Beroun;Beroun;okres
|
Beroun;Beroun;okres
|
||||||
Benešov;Benešov;okres
|
Benešov;Benešov;okres
|
||||||
|
Kohoutovice;Kohoutovice;katastr
|
||||||
|
Nový Lískovec;Nový Lískovec;katastr
|
||||||
|
Bohunice;Bohunice;katastr
|
||||||
Starý Lískovec;Starý Lískovec;katastr
|
Starý Lískovec;Starý Lískovec;katastr
|
||||||
Horní Heršpice;Horní Heršpice;katastr
|
Horní Heršpice;Horní Heršpice;katastr
|
||||||
Královo Pole;Královo Pole;katastr
|
Královo Pole;Královo Pole;katastr
|
||||||
@@ -9952,7 +9955,6 @@ Jestřabice;Jestřabice;katastr
|
|||||||
Jeníkovec;Jeníkovec;katastr
|
Jeníkovec;Jeníkovec;katastr
|
||||||
Týnec nad Labem;Týnec nad Labem;katastr
|
Týnec nad Labem;Týnec nad Labem;katastr
|
||||||
Horní Čepí;Horní Čepí;katastr
|
Horní Čepí;Horní Čepí;katastr
|
||||||
Kohoutovice;Kohoutovice;katastr
|
|
||||||
Pikárec;Pikárec;katastr
|
Pikárec;Pikárec;katastr
|
||||||
Horní Slověnice;Horní Slověnice;katastr
|
Horní Slověnice;Horní Slověnice;katastr
|
||||||
Porešín;Porešín;katastr
|
Porešín;Porešín;katastr
|
||||||
@@ -10586,7 +10588,6 @@ Němčice nad Labem;Němčice nad Labem;katastr
|
|||||||
Kozojídky;Kozojídky;katastr
|
Kozojídky;Kozojídky;katastr
|
||||||
Šemanovice;Šemanovice;katastr
|
Šemanovice;Šemanovice;katastr
|
||||||
Smolov;Smolov;katastr
|
Smolov;Smolov;katastr
|
||||||
Bohunice;Bohunice;katastr
|
|
||||||
Podolí u Mohelnice;Podolí u Mohelnice;katastr
|
Podolí u Mohelnice;Podolí u Mohelnice;katastr
|
||||||
Běšiny;Běšiny;katastr
|
Běšiny;Běšiny;katastr
|
||||||
Bělice;Bělice;katastr
|
Bělice;Bělice;katastr
|
||||||
@@ -11885,7 +11886,6 @@ Hřivínův Újezd;Hřivínův Újezd;katastr
|
|||||||
Radonice u Hradiště;Radonice u Hradiště;katastr
|
Radonice u Hradiště;Radonice u Hradiště;katastr
|
||||||
Chabičovice;Chabičovice;katastr
|
Chabičovice;Chabičovice;katastr
|
||||||
Košín;Košín;katastr
|
Košín;Košín;katastr
|
||||||
Nový Lískovec;Nový Lískovec;katastr
|
|
||||||
Pavlovice;Pavlovice;katastr
|
Pavlovice;Pavlovice;katastr
|
||||||
Kněžičky;Kněžičky;katastr
|
Kněžičky;Kněžičky;katastr
|
||||||
Občov;Občov;katastr
|
Občov;Občov;katastr
|
||||||
@@ -13614,6 +13614,8 @@ Kameničná;Kameničná;katastr
|
|||||||
Hrušová;Hrušová;katastr
|
Hrušová;Hrušová;katastr
|
||||||
Javornice u Dubu;Javornice u Dubu;katastr
|
Javornice u Dubu;Javornice u Dubu;katastr
|
||||||
Veleslavín;Veleslavín;katastr
|
Veleslavín;Veleslavín;katastr
|
||||||
|
Tolar, Jan;OS-008490;vedouci
|
||||||
|
Šimurda, Petr;OS-008489;vedouci
|
||||||
Mrázek, Michal;OS-008488;vedouci
|
Mrázek, Michal;OS-008488;vedouci
|
||||||
Hendrych, Marek;OS-008487;vedouci
|
Hendrych, Marek;OS-008487;vedouci
|
||||||
Haydamakha, Ruslan;OS-008486;vedouci
|
Haydamakha, Ruslan;OS-008486;vedouci
|
||||||
@@ -21865,3 +21867,7 @@ ruina;HES-001456;lokalita_zachovalost
|
|||||||
nadzemní relikty;HES-001455;lokalita_zachovalost
|
nadzemní relikty;HES-001455;lokalita_zachovalost
|
||||||
lokalita pod zástavbou;HES-001454;lokalita_zachovalost
|
lokalita pod zástavbou;HES-001454;lokalita_zachovalost
|
||||||
zaniklá lokalita;HES-001453;lokalita_zachovalost
|
zaniklá lokalita;HES-001453;lokalita_zachovalost
|
||||||
|
archivář;D;pristupnost
|
||||||
|
archeolog;C;pristupnost
|
||||||
|
badatel;B;pristupnost
|
||||||
|
anonym;A;pristupnost
|
||||||
|
|||||||
|
Can't render this file because it is too large.
|
Reference in New Issue
Block a user