mirror of
https://github.com/ARUP-CAS/aiscr-qgis-amcr-viewer.git
synced 2026-06-17 11:22:53 +02:00
Oprava pádů: chybějící locale při startu a životní cyklus úlohy aktualizace heslářů
- amcr_viewer.py: QSettings().value('locale/userLocale') může být None na
čisté instalaci QGIS – ošetřen fallback na 'en', jinak plugin spadne
na TypeError hned při načtení.
- amcr_viewer.py: odstraněn nepoužívaný hvězdičkový import resources.
- amcr_dialog.py: úloha aktualizace heslářů se drží v modulové referenci,
aby GC neuklidil Python wrapper QgsTask před dokončením (známá příčina
pádů QGIS).
- amcr_dialog.py: tlačítko aktualizace se po spuštění zakáže – nelze už
spustit několik stahování paralelně přepisujících heslar.csv.
- amcr_dialog.py: závěrečné QMessageBoxy se parentují na hlavní okno QGIS
místo dialogu, který může být v době dokončení úlohy už zavřený
(smazaný C++ objekt → pád).
This commit is contained in:
+35
-10
@@ -7,6 +7,7 @@ from qgis.PyQt.QtWidgets import (QDialog, QVBoxLayout,
|
|||||||
from qgis.PyQt.QtCore import Qt, QSettings
|
from qgis.PyQt.QtCore import Qt, QSettings
|
||||||
from qgis.core import (QgsTask, QgsApplication,
|
from qgis.core import (QgsTask, QgsApplication,
|
||||||
QgsMessageLog, Qgis, QgsAuthMethodConfig)
|
QgsMessageLog, Qgis, QgsAuthMethodConfig)
|
||||||
|
from qgis.utils import iface
|
||||||
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,
|
OKRESY, KATASTRY, VEDOUCI, PIAN_PRESNOST,
|
||||||
TYP_LOKALITY, DRUH_LOKALITY, JISTOTA,
|
TYP_LOKALITY, DRUH_LOKALITY, JISTOTA,
|
||||||
@@ -14,6 +15,12 @@ from .amcr_codelists import (OBDOBI, TYP_AKCE, KRAJE, AREAL, ORGANIZACE,
|
|||||||
download_heslare, refresh_globals)
|
download_heslare, refresh_globals)
|
||||||
|
|
||||||
|
|
||||||
|
# Keep Python references to running tasks. QgsTaskManager only holds the
|
||||||
|
# C++ object; without a Python-side reference the wrapper can be garbage
|
||||||
|
# collected before the task finishes, which crashes QGIS.
|
||||||
|
_ACTIVE_TASKS = []
|
||||||
|
|
||||||
|
|
||||||
class UpdateCodelistsTask(QgsTask):
|
class UpdateCodelistsTask(QgsTask):
|
||||||
def __init__(self, description):
|
def __init__(self, description):
|
||||||
super().__init__(description, QgsTask.CanCancel)
|
super().__init__(description, QgsTask.CanCancel)
|
||||||
@@ -370,21 +377,38 @@ class AmcrFilterDialog(QDialog):
|
|||||||
return row_widget
|
return row_widget
|
||||||
|
|
||||||
def action_update_heslare(self):
|
def action_update_heslare(self):
|
||||||
# Create the task instance
|
# Create the task instance and keep a reference so the Python
|
||||||
|
# wrapper survives until the task finishes
|
||||||
task = UpdateCodelistsTask("Aktualizace heslářů AMČR")
|
task = UpdateCodelistsTask("Aktualizace heslářů AMČR")
|
||||||
|
_ACTIVE_TASKS.append(task)
|
||||||
|
|
||||||
# Re-enable the button regardless of the outcome
|
# Prevent parallel downloads overwriting heslar.csv
|
||||||
task.taskCompleted.connect(lambda: self.btn_update.setEnabled(True))
|
self.btn_update.setEnabled(False)
|
||||||
task.taskTerminated.connect(lambda: self.btn_update.setEnabled(True))
|
|
||||||
|
|
||||||
task.taskCompleted.connect(lambda: QMessageBox.information(
|
# Message boxes are parented to the main window, not to this dialog –
|
||||||
self,
|
# the dialog may already be closed (and its C++ object deleted)
|
||||||
"Hotovo",
|
# by the time the minute-long task finishes.
|
||||||
"Hesláře byly úspěšně aktualizovány."
|
parent_win = iface.mainWindow() if iface else None
|
||||||
))
|
|
||||||
|
def _cleanup():
|
||||||
|
if task in _ACTIVE_TASKS:
|
||||||
|
_ACTIVE_TASKS.remove(task)
|
||||||
|
try:
|
||||||
|
self.btn_update.setEnabled(True)
|
||||||
|
except RuntimeError:
|
||||||
|
pass # dialog already closed
|
||||||
|
|
||||||
|
def on_completed():
|
||||||
|
_cleanup()
|
||||||
|
QMessageBox.information(
|
||||||
|
parent_win,
|
||||||
|
"Hotovo",
|
||||||
|
"Hesláře byly úspěšně aktualizovány."
|
||||||
|
)
|
||||||
|
|
||||||
# Show the exact error if the task fails
|
# Show the exact error if the task fails
|
||||||
def on_error():
|
def on_error():
|
||||||
|
_cleanup()
|
||||||
if task.exception:
|
if task.exception:
|
||||||
# This will show exactly what went wrong (e.g. PermissionError)
|
# This will show exactly what went wrong (e.g. PermissionError)
|
||||||
msg = (
|
msg = (
|
||||||
@@ -393,8 +417,9 @@ class AmcrFilterDialog(QDialog):
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
msg = "Aktualizace byla zrušena uživatelem."
|
msg = "Aktualizace byla zrušena uživatelem."
|
||||||
QMessageBox.warning(self, "Chyba / Zrušeno", msg)
|
QMessageBox.warning(parent_win, "Chyba / Zrušeno", msg)
|
||||||
|
|
||||||
|
task.taskCompleted.connect(on_completed)
|
||||||
task.taskTerminated.connect(on_error)
|
task.taskTerminated.connect(on_error)
|
||||||
|
|
||||||
QgsApplication.taskManager().addTask(task)
|
QgsApplication.taskManager().addTask(task)
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ from qgis.core import Qgis
|
|||||||
|
|
||||||
from .amcr_tools import load_amcr_data, login_to_api
|
from .amcr_tools import load_amcr_data, login_to_api
|
||||||
from .amcr_dialog import AmcrFilterDialog, LoginDialog
|
from .amcr_dialog import AmcrFilterDialog, LoginDialog
|
||||||
from .resources import *
|
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
|
|
||||||
@@ -24,8 +23,9 @@ class AmcrViewer:
|
|||||||
self.iface = iface
|
self.iface = iface
|
||||||
self.plugin_dir = os.path.dirname(__file__)
|
self.plugin_dir = os.path.dirname(__file__)
|
||||||
|
|
||||||
# Determine the user's locale to load appropriate translation files
|
# Determine the user's locale to load appropriate translation files.
|
||||||
locale = QSettings().value('locale/userLocale')[0:2]
|
# The setting may be missing (None) on a fresh QGIS install.
|
||||||
|
locale = str(QSettings().value('locale/userLocale') or 'en')[0:2]
|
||||||
locale_path = os.path.join(
|
locale_path = os.path.join(
|
||||||
self.plugin_dir,
|
self.plugin_dir,
|
||||||
'i18n',
|
'i18n',
|
||||||
|
|||||||
Reference in New Issue
Block a user