Skip to content

Commit

Permalink
gui: Add fix for wxGUI Data import Python error (#4504)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ww2406 authored Oct 18, 2024
1 parent 6fd21a8 commit 62b001b
Showing 1 changed file with 45 additions and 2 deletions.
47 changes: 45 additions & 2 deletions gui/wxpython/modules/import_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@
@author Martin Landa <landa.martin gmail.com>
@author Anna Kratochvilova <kratochanna gmail.com> (GroupDialog, SymbolDialog)
@author William Welch <ww.dev icloud.com> (commands running queue)
"""

import os
from collections import deque

from pathlib import Path

Expand Down Expand Up @@ -60,6 +62,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"
)
Expand Down Expand Up @@ -122,16 +126,17 @@ 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"))
self.btn_run.SetToolTip(_("Import selected layers"))
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)

Expand Down Expand Up @@ -270,6 +275,33 @@ def _validateOutputMapName(self):
return False
return True

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()

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()
Expand Down Expand Up @@ -518,6 +550,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
Expand All @@ -526,9 +559,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()
Expand Down Expand Up @@ -663,6 +698,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
Expand All @@ -671,10 +707,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")

Expand Down Expand Up @@ -873,16 +912,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()

Expand Down

0 comments on commit 62b001b

Please sign in to comment.