From 0c316b961a7d6e32eb2146abc04f0120cf4189a6 Mon Sep 17 00:00:00 2001 From: wwelch <57472892+ww2406@users.noreply.github.com> Date: Sat, 12 Oct 2024 21:44:38 -0700 Subject: [PATCH 1/5] Add fix for #648 with error message during import This fixes #648 by adding a command tracker queue. When the queue is not empty, closing the dialog is prevented to ensure the completion callback can still access UI elements. --- gui/wxpython/modules/import_export.py | 43 +++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/gui/wxpython/modules/import_export.py b/gui/wxpython/modules/import_export.py index f2f70e47831..ded580e754f 100644 --- a/gui/wxpython/modules/import_export.py +++ b/gui/wxpython/modules/import_export.py @@ -21,6 +21,7 @@ """ import os +from collections import deque from pathlib import Path @@ -60,6 +61,8 @@ def __init__( self.commandId = -1 # id of running command + self._commands_running = deque() + wx.Dialog.__init__( self, parent, id, title, style=style, name="MultiImportDialog" ) @@ -122,8 +125,9 @@ def __init__( # buttons # # cancel + self._DEFAULT_CLOSE_BTN_TEXT = "Close dialog" self.btn_close = CloseButton(parent=self.panel) - self.btn_close.SetToolTip(_("Close dialog")) + self.btn_close.SetToolTip(_(self._DEFAULT_CLOSE_BTN_TEXT)) self.btn_close.Bind(wx.EVT_BUTTON, self.OnClose) # run self.btn_run = Button(parent=self.panel, id=wx.ID_OK, label=_("&Import")) @@ -131,7 +135,7 @@ def __init__( self.btn_run.SetDefault() self.btn_run.Bind(wx.EVT_BUTTON, self.OnRun) - self.Bind(wx.EVT_CLOSE, lambda evt: self.Destroy()) + self.Bind(wx.EVT_CLOSE, self._handleCloseEvent) self.notebook = GNotebook(parent=self, style=globalvar.FNPageDStyle) @@ -270,6 +274,30 @@ def _validateOutputMapName(self): return False return True + def _handleCloseEvent(self, *args, **kwargs): + if len(self._commands_running) > 0: + # prevent dialog close while async commands are running + return + self.Destroy() + + def _addToCommandQueue(self): + self._commands_running.append(True) + + # disable the dialog close button + self.btn_close.SetToolTip(_("Dialog cannot be closed while command is running.")) + self.btn_close.Disable() + + def _removeFromCommandQueue(self): + try: + self._commands_running.pop() + except IndexError: + pass + finally: + if len(self._commands_running) == 0: + # enable the dialog close button + self.btn_close.Enable() + self.btn_close.SetToolTip(self._DEFAULT_CLOSE_BTN_TEXT) + def OnClose(self, event=None): """Close dialog""" self.Close() @@ -519,6 +547,7 @@ def OnRun(self, event): ): cmd.append("--overwrite") + self._addToCommandQueue() # run in Layer Manager self._giface.RunCmd( cmd, onDone=self.OnCmdDone, userData=userData, addLayer=False @@ -527,9 +556,11 @@ def OnRun(self, event): def OnCmdDone(self, event): """Load layers and close if required""" if not hasattr(self, "AddLayers"): + self._removeFromCommandQueue() return self.AddLayers(event.returncode, event.cmd, event.userData) + self._removeFromCommandQueue() if event.returncode == 0 and self.closeOnFinish.IsChecked(): self.Close() @@ -670,6 +701,7 @@ def OnRun(self, event): ): cmd.append("--overwrite") + self._addToCommandQueue() # run in Layer Manager self._giface.RunCmd( cmd, onDone=self.OnCmdDone, userData=userData, addLayer=False @@ -678,10 +710,13 @@ def OnRun(self, event): def OnCmdDone(self, event): """Load layers and close if required""" if not hasattr(self, "AddLayers"): + self._removeFromCommandQueue() return self.AddLayers(event.returncode, event.cmd, event.userData) + self._removeFromCommandQueue() + if self.popOGR: os.environ.pop("GRASS_VECTOR_OGR") @@ -880,16 +915,20 @@ def OnRun(self, event): ): cmd.append("--overwrite") + self._commands_running.append(True) # run in Layer Manager self._giface.RunCmd(cmd, onDone=self.OnCmdDone, addLayer=False) def OnCmdDone(self, event): """Load layers and close if required""" if not hasattr(self, "AddLayers"): + self._removeFromCommandQueue() return self.AddLayers(event.returncode, event.cmd) + self._removeFromCommandQueue() + if self.closeOnFinish.IsChecked(): self.Close() From efbb3c0ba5b3e9dd125c5d07edea3cb4dad05256 Mon Sep 17 00:00:00 2001 From: ww2406 <57472892+ww2406@users.noreply.github.com> Date: Mon, 14 Oct 2024 10:23:49 -0700 Subject: [PATCH 2/5] Update formatting Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- gui/wxpython/modules/import_export.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gui/wxpython/modules/import_export.py b/gui/wxpython/modules/import_export.py index ded580e754f..48f83ba41e5 100644 --- a/gui/wxpython/modules/import_export.py +++ b/gui/wxpython/modules/import_export.py @@ -284,7 +284,9 @@ def _addToCommandQueue(self): self._commands_running.append(True) # disable the dialog close button - self.btn_close.SetToolTip(_("Dialog cannot be closed while command is running.")) + self.btn_close.SetToolTip( + _("Dialog cannot be closed while command is running.") + ) self.btn_close.Disable() def _removeFromCommandQueue(self): From f475b00c747f47b0388ce174c9febf261dac56fb Mon Sep 17 00:00:00 2001 From: ww2406 <57472892+ww2406@users.noreply.github.com> Date: Mon, 14 Oct 2024 10:25:02 -0700 Subject: [PATCH 3/5] Make default close button text translatable --- gui/wxpython/modules/import_export.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/wxpython/modules/import_export.py b/gui/wxpython/modules/import_export.py index 48f83ba41e5..5a98a59cd02 100644 --- a/gui/wxpython/modules/import_export.py +++ b/gui/wxpython/modules/import_export.py @@ -125,7 +125,7 @@ def __init__( # buttons # # cancel - self._DEFAULT_CLOSE_BTN_TEXT = "Close dialog" + self._DEFAULT_CLOSE_BTN_TEXT = _("Close dialog") self.btn_close = CloseButton(parent=self.panel) self.btn_close.SetToolTip(_(self._DEFAULT_CLOSE_BTN_TEXT)) self.btn_close.Bind(wx.EVT_BUTTON, self.OnClose) From f92b7d53dd14debc9587548fdb6d6b545a222c7b Mon Sep 17 00:00:00 2001 From: wwelch <57472892+ww2406@users.noreply.github.com> Date: Thu, 17 Oct 2024 21:10:14 -0700 Subject: [PATCH 4/5] Add event.Veto check and call --- gui/wxpython/modules/import_export.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gui/wxpython/modules/import_export.py b/gui/wxpython/modules/import_export.py index 5a98a59cd02..a1db923cf9e 100644 --- a/gui/wxpython/modules/import_export.py +++ b/gui/wxpython/modules/import_export.py @@ -274,9 +274,10 @@ def _validateOutputMapName(self): return False return True - def _handleCloseEvent(self, *args, **kwargs): - if len(self._commands_running) > 0: + def _handleCloseEvent(self, event: wx.CloseEvent): + if event.CanVeto() and len(self._commands_running) > 0: # prevent dialog close while async commands are running + event.Veto() return self.Destroy() From 60b1a380c7fef6610822052cce3edb41f1e91ff8 Mon Sep 17 00:00:00 2001 From: wwelch <57472892+ww2406@users.noreply.github.com> Date: Thu, 17 Oct 2024 21:27:17 -0700 Subject: [PATCH 5/5] Add author note --- gui/wxpython/modules/import_export.py | 1 + 1 file changed, 1 insertion(+) diff --git a/gui/wxpython/modules/import_export.py b/gui/wxpython/modules/import_export.py index dd2de5d08d4..c3106d0467b 100644 --- a/gui/wxpython/modules/import_export.py +++ b/gui/wxpython/modules/import_export.py @@ -18,6 +18,7 @@ @author Martin Landa @author Anna Kratochvilova (GroupDialog, SymbolDialog) +@author William Welch (commands running queue) """ import os