From 1459a0017f5a47f1bf0f08348ecde76a68bb6a2c Mon Sep 17 00:00:00 2001 From: Tomas Zigo Date: Mon, 4 Dec 2023 19:16:28 +0100 Subject: [PATCH 1/7] wxGUI/locdownload: show progress of downloading new location as Data Catalog info bar message And hide Download Location dialog during progress of downloading. --- gui/wxpython/datacatalog/catalog.py | 16 +++++ gui/wxpython/datacatalog/infomanager.py | 9 +++ gui/wxpython/datacatalog/tree.py | 32 +++++++-- gui/wxpython/startup/guiutils.py | 18 ++--- gui/wxpython/startup/locdownload.py | 93 +++++++++++++++++++------ 5 files changed, 128 insertions(+), 40 deletions(-) diff --git a/gui/wxpython/datacatalog/catalog.py b/gui/wxpython/datacatalog/catalog.py index 4835061d968..4488048d030 100644 --- a/gui/wxpython/datacatalog/catalog.py +++ b/gui/wxpython/datacatalog/catalog.py @@ -74,6 +74,10 @@ def __init__( # tree with layers self.tree = DataCatalogTree(self, giface=giface) self.tree.showNotification.connect(self.showNotification) + self.tree.showDownloadingNewLocationInfoMessage.connect( + self.showDownloadingNewLocationInfoMessage + ) + self.tree.dismissShowInfoBarMessage.connect(self.dismissInfobar) # infobar for data catalog delay = 2000 @@ -140,6 +144,18 @@ def showImportDataInfo(self): self.OnImportOgrLayers, self.OnImportGdalLayers ) + def showDownloadingNewLocationInfoMessage(self, message, buttons): + """Show progress of downloading new location info message + + :param str message: text message + :param list buttons: list of info bar widget buttons + [(button_label, button_click_event_handler),...] + """ + self.infoManager.ShowDownloadingNewLocationInfo( + message=message, + buttons=buttons, + ) + def LoadItems(self): """Reload tree - full or lazy - based on user settings""" self._startLoadingTime = clock() diff --git a/gui/wxpython/datacatalog/infomanager.py b/gui/wxpython/datacatalog/infomanager.py index d3daf4d38fa..1d2e681478e 100644 --- a/gui/wxpython/datacatalog/infomanager.py +++ b/gui/wxpython/datacatalog/infomanager.py @@ -100,6 +100,15 @@ def ShowLockedMapsetInfo(self, OnSwitchMapsetHandler): ).format(mapsetpath=last_used_mapset_path) self.infoBar.ShowMessage(message, wx.ICON_INFORMATION, buttons) + def ShowDownloadingNewLocationInfo(self, message, buttons): + """Show progress of downloading new location info message + + :param str message: message text + :param list buttons: list of info bar widget buttons + [(buton_label, button_click_event_handler),...] + """ + self.infoBar.ShowMessage(message, wx.ICON_INFORMATION, buttons) + def _text_from_reason_id(self, reason_id): """Get string for infobar message based on the reason.""" last_used_mapset_path = gisenv()["LAST_MAPSET_PATH"] diff --git a/gui/wxpython/datacatalog/tree.py b/gui/wxpython/datacatalog/tree.py index bf06fd11ab8..e1393a44344 100644 --- a/gui/wxpython/datacatalog/tree.py +++ b/gui/wxpython/datacatalog/tree.py @@ -232,6 +232,10 @@ def __init__( self.showNotification = Signal("Tree.showNotification") self.showImportDataInfo = Signal("Tree.showImportDataInfo") self.loadingDone = Signal("Tree.loadingDone") + self.showDownloadingNewLocationInfoMessage = Signal( + "Tree.showDownloadingNewLocationInfoMessage" + ) + self.dismissShowInfoBarMessage = Signal("Tree.dismissShowInfoBarMessage") self.parent = parent self.contextMenu.connect(self.OnRightClick) self.itemActivated.connect(self.OnDoubleClick) @@ -1612,17 +1616,35 @@ def OnDeleteLocation(self, event): for change in changes: self._giface.grassdbChanged.emit(**change) + def AddDownloadedNewLocation(self): + """ + Add downloaded new location into tree + """ + location = self.loc_download.GetLocation() + if location: + self._reloadGrassDBNode(self.selected_grassdb[0]) + self.UpdateCurrentDbLocationMapsetNode() + self.RefreshItems() + self.showNotification.emit( + message=_( + "The new location <{}> has been downloaded successfully" + ).format(location) + ) + def DownloadLocation(self, grassdb_node): """ Download new location interactively. """ - grassdatabase, location, mapset = download_location_interactively( + self.loc_download = download_location_interactively( self, grassdb_node.data["name"] ) - if location: - self._reloadGrassDBNode(grassdb_node) - self.UpdateCurrentDbLocationMapsetNode() - self.RefreshItems() + self.loc_download.newLocationIsDownloaded.connect(self.AddDownloadedNewLocation) + self.loc_download.showInfoBarMessage.connect( + self.showDownloadingNewLocationInfoMessage + ) + self.loc_download.dismissShowInfoBarMessage.connect( + self.dismissShowInfoBarMessage + ) def OnDownloadLocation(self, event): """ diff --git a/gui/wxpython/startup/guiutils.py b/gui/wxpython/startup/guiutils.py index fa4d0a8760a..09b17068a3c 100644 --- a/gui/wxpython/startup/guiutils.py +++ b/gui/wxpython/startup/guiutils.py @@ -319,23 +319,17 @@ def download_location_interactively(guiparent, grassdb): """ Download new location using Location Wizard. - Returns tuple (database, location, mapset) where mapset is "PERMANENT" - by default or in future it could be the mapset the user may want to - switch to. + :param guiparent object: gui parent object + :param str grassdb: GRASS GIS database path string + + :return object loc_download: Download location dialog instance object """ from startup.locdownload import LocationDownloadDialog - result = (None, None, None) loc_download = LocationDownloadDialog(parent=guiparent, database=grassdb) loc_download.Centre() - loc_download.ShowModal() - - if loc_download.GetLocation() is not None: - # Returns database and location created by user - # and a mapset user may want to switch to - result = (grassdb, loc_download.GetLocation(), "PERMANENT") - loc_download.Destroy() - return result + loc_download.Show() + return loc_download def delete_mapset_interactively(guiparent, grassdb, location, mapset): diff --git a/gui/wxpython/startup/locdownload.py b/gui/wxpython/startup/locdownload.py index ccbeaa8fb0c..635aeed00eb 100644 --- a/gui/wxpython/startup/locdownload.py +++ b/gui/wxpython/startup/locdownload.py @@ -25,6 +25,7 @@ import wx from wx.lib.newevent import NewEvent +from grass.pydispatch.signal import Signal from grass.script.utils import try_rmdir, legalize_vector_name from grass.utils.download import download_and_extract, name_from_url, DownloadError from grass.grassdb.checks import is_location_valid @@ -84,14 +85,16 @@ class RedirectText: def __init__(self, window): - self.out = window + self.window = window def write(self, string): try: - if self.out: + if self.window.message: string = self._wrap_string(string) heigth = self._get_heigth(string) - wx.CallAfter(self.out.SetLabel, string) + wx.CallAfter(self.window.message.SetLabel, string) + # Show Data Catalog info bar messsage + wx.CallAfter(self.window.ShowInfoBarMessage, string) self._resize(heigth) except: # window closed -> PyDeadObjectError @@ -119,7 +122,7 @@ def _get_heigth(self, string): :return int: widget heigth """ n_lines = string.count("\n") - attr = self.out.GetClassDefaultAttributes() + attr = self.window.message.GetClassDefaultAttributes() font_size = attr.font.GetPointSize() return int((n_lines + 2) * font_size // 0.75) # 1 px = 0.75 pt @@ -128,11 +131,11 @@ def _resize(self, heigth=-1): :param int heigth: widget heigth """ - wx.CallAfter(self.out.GetParent().SetMinSize, (-1, -1)) - wx.CallAfter(self.out.SetMinSize, (-1, heigth)) + wx.CallAfter(self.window.meesage.GetParent().SetMinSize, (-1, -1)) + wx.CallAfter(self.window.message.SetMinSize, (-1, heigth)) wx.CallAfter( - self.out.GetParent().parent.sizer.Fit, - self.out.GetParent().parent, + self.window.message.GetParent().parent.sizer.Fit, + self.window.message.GetParent().parent, ) @@ -240,7 +243,7 @@ def __init__(self, parent, database, locations=LOCATIONS): # TODO: messages copied from gis_set.py, need this as API? self.message = StaticText(parent=self, size=(-1, 50)) - sys.stdout = RedirectText(self.message) + sys.stdout = RedirectText(window=self) # It is not clear if all wx versions supports color, so try-except. # The color itself may not be correct for all platforms/system settings @@ -298,6 +301,31 @@ def _change_download_btn_label( self.parent.download_button.SetLabel(label) self.parent.download_button.SetToolTip(tooltip) + def _terminateDownloadCallback(self, event): + """Terminate download callback + + :param object event: event object + """ + if self._download_in_progress: + self.thread.Terminate() + # Clean up after urllib urlretrieve which is used internally + # in grass.utils. + from urllib import request # pylint: disable=import-outside-toplevel + + self._download_in_progress = False + request.urlcleanup() + sys.stdout.write("Download aborted") + self.thread = gThread() + self._change_download_btn_label() + self.parent.Show(True) + + def OnAbort(self, event): + """Info bar widget abort button event handler + + :param object event: event object + """ + self._terminateDownloadCallback(event) + def OnDownload(self, event): """Handle user-initiated action of download""" button_label = self.parent.download_button.GetLabel() @@ -314,6 +342,21 @@ def OnDownload(self, event): else: self.parent.OnCancel() + def ShowInfoBarMessage(self, message, buttons=None): + """Show progress of downloading new location Data Catalog info + message + + :param str message: text message + :param list buttons: list of info bar widget buttons + [(button_label, button_click_event_handler),...] + """ + self.parent.showInfoBarMessage.emit( + message=message, + buttons=[(self._abort_btn_label, self.OnAbort)] + if buttons is None + else buttons, + ) + def DownloadItem(self, item): """Download the selected item""" Debug.msg(1, "DownloadItem: %s" % item) @@ -343,18 +386,9 @@ def download_complete_callback(event): "now in the data tree" ) ) + self.parent.newLocationIsDownloaded.emit() self._change_download_btn_label() - - def terminate_download_callback(event): - # Clean up after urllib urlretrieve which is used internally - # in grass.utils. - from urllib import request # pylint: disable=import-outside-toplevel - - self._download_in_progress = False - request.urlcleanup() - sys.stdout.write("Download aborted") - self.thread = gThread() - self._change_download_btn_label() + self.parent.Show(True) self._download_in_progress = True self._warning(_("Download in progress, wait until it is finished")) @@ -364,8 +398,9 @@ def terminate_download_callback(event): name=dirname, database=self.database, ondone=download_complete_callback, - onterminate=terminate_download_callback, + onterminate=self._terminateDownloadCallback, ) + wx.CallLater(1000, self.parent.Show, False) def OnChangeChoice(self, event): """React to user changing the selection""" @@ -386,7 +421,9 @@ def CheckItem(self, item): ) self.parent.download_button.SetLabel(label=_("Download")) return - self._clearMessage() + else: + self.parent.dismissShowInfoBarMessage.emit() + self._clearMessage() def GetLocation(self): """Get the name of the last location downloaded by the user""" @@ -440,6 +477,15 @@ def __init__(self, parent, database, title=_("Dataset Download")): :param title: window title if the default is not appropriate """ wx.Dialog.__init__(self, parent=parent, title=title) + + self.newLocationIsDownloaded = Signal( + "LocationDownloadDialog.newLocationIsDownloaded" + ) + self.showInfoBarMessage = Signal("LocationDownloadDialog.showInfoBarMessage") + self.dismissShowInfoBarMessage = Signal( + "LocationDownloadDialog.dismissShowInfoBarMessage" + ) + cancel_button = Button(self, id=wx.ID_CANCEL) self.download_button = Button(parent=self, id=wx.ID_ANY, label=_("Do&wnload")) self.download_button.SetToolTip(_("Download selected dataset")) @@ -499,7 +545,8 @@ def OnCancel(self, event=None): self.panel._change_download_btn_label() if event: - self.EndModal(wx.ID_CANCEL) + self.dismissShowInfoBarMessage.emit() + self.Destroy() def main(): From 1c4346786d088ac95ff7a2f8a2fe4186818a88e8 Mon Sep 17 00:00:00 2001 From: Tomas Zigo Date: Tue, 5 Dec 2023 09:06:01 +0100 Subject: [PATCH 2/7] Fix tests --- gui/wxpython/startup/locdownload.py | 32 +++++++++++++++++------------ 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/gui/wxpython/startup/locdownload.py b/gui/wxpython/startup/locdownload.py index 635aeed00eb..df445c48b19 100644 --- a/gui/wxpython/startup/locdownload.py +++ b/gui/wxpython/startup/locdownload.py @@ -237,7 +237,8 @@ def __init__(self, parent, database, locations=LOCATIONS): self.choice = wx.Choice(parent=self, choices=choices) self.choice.Bind(wx.EVT_CHOICE, self.OnChangeChoice) - self.parent.download_button.Bind(wx.EVT_BUTTON, self.OnDownload) + if hasattr(self.parent, "download_button"): + self.parent.download_button.Bind(wx.EVT_BUTTON, self.OnDownload) # TODO: add button for a link to an associated website? # TODO: add thumbnail for each location? @@ -317,7 +318,8 @@ def _terminateDownloadCallback(self, event): sys.stdout.write("Download aborted") self.thread = gThread() self._change_download_btn_label() - self.parent.Show(True) + if not self.parent: + self.parent.Show(True) def OnAbort(self, event): """Info bar widget abort button event handler @@ -350,12 +352,13 @@ def ShowInfoBarMessage(self, message, buttons=None): :param list buttons: list of info bar widget buttons [(button_label, button_click_event_handler),...] """ - self.parent.showInfoBarMessage.emit( - message=message, - buttons=[(self._abort_btn_label, self.OnAbort)] - if buttons is None - else buttons, - ) + if not self.parent: + self.parent.showInfoBarMessage.emit( + message=message, + buttons=[(self._abort_btn_label, self.OnAbort)] + if buttons is None + else buttons, + ) def DownloadItem(self, item): """Download the selected item""" @@ -388,7 +391,8 @@ def download_complete_callback(event): ) self.parent.newLocationIsDownloaded.emit() self._change_download_btn_label() - self.parent.Show(True) + if not self.parent: + self.parent.Show(True) self._download_in_progress = True self._warning(_("Download in progress, wait until it is finished")) @@ -400,7 +404,8 @@ def download_complete_callback(event): ondone=download_complete_callback, onterminate=self._terminateDownloadCallback, ) - wx.CallLater(1000, self.parent.Show, False) + if not self.parent: + wx.CallLater(1000, self.parent.Show, False) def OnChangeChoice(self, event): """React to user changing the selection""" @@ -419,10 +424,12 @@ def CheckItem(self, item): name=dirname ) ) - self.parent.download_button.SetLabel(label=_("Download")) + if not self.parent: + self.parent.download_button.SetLabel(label=_("Download")) return else: - self.parent.dismissShowInfoBarMessage.emit() + if not self.parent: + self.parent.dismissShowInfoBarMessage.emit() self._clearMessage() def GetLocation(self): @@ -563,7 +570,6 @@ def main(): location = window.GetLocation() if location: print(location) - window.Destroy() elif sys.argv[2] == "panel": window = wx.Dialog(parent=None) panel = LocationDownloadPanel(parent=window, database=database) From 8801867f04e75fb31c3bb031d41a7a39c1270437 Mon Sep 17 00:00:00 2001 From: Tomas Zigo Date: Tue, 5 Dec 2023 09:16:41 +0100 Subject: [PATCH 3/7] Revert "Fix tests" This reverts commit 995143654a2bd946323943e9500882e69cccead9. --- gui/wxpython/startup/locdownload.py | 32 ++++++++++++----------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/gui/wxpython/startup/locdownload.py b/gui/wxpython/startup/locdownload.py index df445c48b19..635aeed00eb 100644 --- a/gui/wxpython/startup/locdownload.py +++ b/gui/wxpython/startup/locdownload.py @@ -237,8 +237,7 @@ def __init__(self, parent, database, locations=LOCATIONS): self.choice = wx.Choice(parent=self, choices=choices) self.choice.Bind(wx.EVT_CHOICE, self.OnChangeChoice) - if hasattr(self.parent, "download_button"): - self.parent.download_button.Bind(wx.EVT_BUTTON, self.OnDownload) + self.parent.download_button.Bind(wx.EVT_BUTTON, self.OnDownload) # TODO: add button for a link to an associated website? # TODO: add thumbnail for each location? @@ -318,8 +317,7 @@ def _terminateDownloadCallback(self, event): sys.stdout.write("Download aborted") self.thread = gThread() self._change_download_btn_label() - if not self.parent: - self.parent.Show(True) + self.parent.Show(True) def OnAbort(self, event): """Info bar widget abort button event handler @@ -352,13 +350,12 @@ def ShowInfoBarMessage(self, message, buttons=None): :param list buttons: list of info bar widget buttons [(button_label, button_click_event_handler),...] """ - if not self.parent: - self.parent.showInfoBarMessage.emit( - message=message, - buttons=[(self._abort_btn_label, self.OnAbort)] - if buttons is None - else buttons, - ) + self.parent.showInfoBarMessage.emit( + message=message, + buttons=[(self._abort_btn_label, self.OnAbort)] + if buttons is None + else buttons, + ) def DownloadItem(self, item): """Download the selected item""" @@ -391,8 +388,7 @@ def download_complete_callback(event): ) self.parent.newLocationIsDownloaded.emit() self._change_download_btn_label() - if not self.parent: - self.parent.Show(True) + self.parent.Show(True) self._download_in_progress = True self._warning(_("Download in progress, wait until it is finished")) @@ -404,8 +400,7 @@ def download_complete_callback(event): ondone=download_complete_callback, onterminate=self._terminateDownloadCallback, ) - if not self.parent: - wx.CallLater(1000, self.parent.Show, False) + wx.CallLater(1000, self.parent.Show, False) def OnChangeChoice(self, event): """React to user changing the selection""" @@ -424,12 +419,10 @@ def CheckItem(self, item): name=dirname ) ) - if not self.parent: - self.parent.download_button.SetLabel(label=_("Download")) + self.parent.download_button.SetLabel(label=_("Download")) return else: - if not self.parent: - self.parent.dismissShowInfoBarMessage.emit() + self.parent.dismissShowInfoBarMessage.emit() self._clearMessage() def GetLocation(self): @@ -570,6 +563,7 @@ def main(): location = window.GetLocation() if location: print(location) + window.Destroy() elif sys.argv[2] == "panel": window = wx.Dialog(parent=None) panel = LocationDownloadPanel(parent=window, database=database) From 727592182f120d779d9a633fc4292bacfe59007f Mon Sep 17 00:00:00 2001 From: Tomas Zigo Date: Tue, 5 Dec 2023 13:15:35 +0100 Subject: [PATCH 4/7] Refactor tests --- gui/wxpython/startup/locdownload.py | 49 ++++++++++++++++++----------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/gui/wxpython/startup/locdownload.py b/gui/wxpython/startup/locdownload.py index 635aeed00eb..8c8a1ac4f51 100644 --- a/gui/wxpython/startup/locdownload.py +++ b/gui/wxpython/startup/locdownload.py @@ -237,7 +237,8 @@ def __init__(self, parent, database, locations=LOCATIONS): self.choice = wx.Choice(parent=self, choices=choices) self.choice.Bind(wx.EVT_CHOICE, self.OnChangeChoice) - self.parent.download_button.Bind(wx.EVT_BUTTON, self.OnDownload) + if hasattr(self.parent, "download_button"): + self.parent.download_button.Bind(wx.EVT_BUTTON, self.OnDownload) # TODO: add button for a link to an associated website? # TODO: add thumbnail for each location? @@ -350,12 +351,13 @@ def ShowInfoBarMessage(self, message, buttons=None): :param list buttons: list of info bar widget buttons [(button_label, button_click_event_handler),...] """ - self.parent.showInfoBarMessage.emit( - message=message, - buttons=[(self._abort_btn_label, self.OnAbort)] - if buttons is None - else buttons, - ) + if hasattr(self.parent, "showInfoBarMessage"): + self.parent.showInfoBarMessage.emit( + message=message, + buttons=[(self._abort_btn_label, self.OnAbort)] + if buttons is None + else buttons, + ) def DownloadItem(self, item): """Download the selected item""" @@ -419,10 +421,12 @@ def CheckItem(self, item): name=dirname ) ) - self.parent.download_button.SetLabel(label=_("Download")) + if hasattr(self.parent, "download_button"): + self.parent.download_button.SetLabel(label=_("Download")) return else: - self.parent.dismissShowInfoBarMessage.emit() + if hasattr(self.parent, "dismissShowInfoBarMessage"): + self.parent.dismissShowInfoBarMessage.emit() self._clearMessage() def GetLocation(self): @@ -486,11 +490,11 @@ def __init__(self, parent, database, title=_("Dataset Download")): "LocationDownloadDialog.dismissShowInfoBarMessage" ) - cancel_button = Button(self, id=wx.ID_CANCEL) + self.cancel_button = Button(self, id=wx.ID_CANCEL) self.download_button = Button(parent=self, id=wx.ID_ANY, label=_("Do&wnload")) self.download_button.SetToolTip(_("Download selected dataset")) self.panel = LocationDownloadPanel(parent=self, database=database) - cancel_button.Bind(wx.EVT_BUTTON, self.OnCancel) + self.cancel_button.Bind(wx.EVT_BUTTON, self.OnCancel) self.Bind(wx.EVT_CLOSE, self.OnCancel) self.sizer = wx.BoxSizer(wx.VERTICAL) @@ -498,7 +502,7 @@ def __init__(self, parent, database, title=_("Dataset Download")): button_sizer = wx.StdDialogButtonSizer() button_sizer.Add( - cancel_button, + self.cancel_button, proportion=0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=5, @@ -558,12 +562,21 @@ def main(): app = wx.App() if len(sys.argv) == 2 or sys.argv[2] == "dialog": - window = LocationDownloadDialog(parent=None, database=database) - window.ShowModal() - location = window.GetLocation() - if location: - print(location) - window.Destroy() + + def new_location_is_downloaded(): + # Reset stdout + sys.stdout = sys.__stdout__ + print(window.GetLocation()) + + def on_close(event): + parent_window.Destroy() + + parent_window = wx.Dialog(parent=None) + window = LocationDownloadDialog(parent=parent_window, database=database) + window.Bind(wx.EVT_CLOSE, on_close) + window.cancel_button.Bind(wx.EVT_BUTTON, on_close) + window.newLocationIsDownloaded.connect(new_location_is_downloaded) + window.Show() elif sys.argv[2] == "panel": window = wx.Dialog(parent=None) panel = LocationDownloadPanel(parent=window, database=database) From 0724c9d38f40faf7104dc6c5dab624011da1c28a Mon Sep 17 00:00:00 2001 From: Tomas Zigo Date: Fri, 9 Feb 2024 18:56:43 +0100 Subject: [PATCH 5/7] Fix showing info bar message Abort button widget --- gui/wxpython/datacatalog/infomanager.py | 10 +++++++- gui/wxpython/gui_core/infobar.py | 6 +++-- gui/wxpython/startup/locdownload.py | 33 +++++++++++++++++++++++-- 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/gui/wxpython/datacatalog/infomanager.py b/gui/wxpython/datacatalog/infomanager.py index 1d2e681478e..19a1abebf5b 100644 --- a/gui/wxpython/datacatalog/infomanager.py +++ b/gui/wxpython/datacatalog/infomanager.py @@ -107,7 +107,15 @@ def ShowDownloadingNewLocationInfo(self, message, buttons): :param list buttons: list of info bar widget buttons [(buton_label, button_click_event_handler),...] """ - self.infoBar.ShowMessage(message, wx.ICON_INFORMATION, buttons) + self.infoBar.ShowMessage(message, wx.ICON_INFORMATION, remove_buttons=False) + if buttons: + for btn in buttons: + if btn["btnsAction"]["addBtn"]: + # Add btn widget here, to prevent blinking widget + self.infoBar.AddButton(btnid=btn["id"], label=btn["label"]) + self.infoBar.Bind(wx.EVT_BUTTON, btn["handler"], id=btn["id"]) + if btn["btnsAction"]["removeBtn"]: + self.infoBar.RemoveButtons() def _text_from_reason_id(self, reason_id): """Get string for infobar message based on the reason.""" diff --git a/gui/wxpython/gui_core/infobar.py b/gui/wxpython/gui_core/infobar.py index e9bd8b848a5..1353ea1a015 100644 --- a/gui/wxpython/gui_core/infobar.py +++ b/gui/wxpython/gui_core/infobar.py @@ -99,11 +99,12 @@ def _unInitLayout(self): else: sizer.Detach(i) - def ShowMessage(self, message, icon, buttons=None): + def ShowMessage(self, message, icon, buttons=None, remove_buttons=True): """Show message with buttons (optional). Buttons are list of tuples (label, handler)""" self.Hide() - self.RemoveButtons() + if remove_buttons: + self.RemoveButtons() if buttons: self.SetButtons(buttons) super().ShowMessage(message, icon) @@ -122,6 +123,7 @@ def AddButton(self, btnid, label): self._button.Hide() button = wx.Button(self, btnid, label) + self.button_ids.append(btnid) button.SetBackgroundColour(self._background_color) button.SetForegroundColour(self._foreground_color) diff --git a/gui/wxpython/startup/locdownload.py b/gui/wxpython/startup/locdownload.py index 8c8a1ac4f51..f5e80319081 100644 --- a/gui/wxpython/startup/locdownload.py +++ b/gui/wxpython/startup/locdownload.py @@ -225,7 +225,12 @@ def __init__(self, parent, database, locations=LOCATIONS): self.database = database self.locations = locations self._abort_btn_label = _("Abort") - self._abort_btn_tooltip = _("Abort download") + self._abort_btn_tooltip = _("Abort download location") + self._infobar_message_btn_id = wx.NewIdRef() + self._infobar_message_btns = { + "addBtn": None, + "removeBtn": None, + } self.label = StaticText( parent=self, label=_("Select sample project to download:") @@ -307,6 +312,7 @@ def _terminateDownloadCallback(self, event): :param object event: event object """ + self._infobar_message_btns["addBtn"] = True if self._download_in_progress: self.thread.Terminate() # Clean up after urllib urlretrieve which is used internally @@ -319,6 +325,9 @@ def _terminateDownloadCallback(self, event): self.thread = gThread() self._change_download_btn_label() self.parent.Show(True) + self._infobar_message_btns.update( + dict(zip(("addBtn", "removeBtn"), (False, True))), + ) def OnAbort(self, event): """Info bar widget abort button event handler @@ -329,6 +338,9 @@ def OnAbort(self, event): def OnDownload(self, event): """Handle user-initiated action of download""" + self._infobar_message_btns.update( + dict(zip(("addBtn", "removeBtn"), (True, False))), + ) button_label = self.parent.download_button.GetLabel() if button_label in {_("Download"), _("Do&wnload")}: self._change_download_btn_label( @@ -354,10 +366,18 @@ def ShowInfoBarMessage(self, message, buttons=None): if hasattr(self.parent, "showInfoBarMessage"): self.parent.showInfoBarMessage.emit( message=message, - buttons=[(self._abort_btn_label, self.OnAbort)] + buttons=[ + { + "id": self._infobar_message_btn_id, + "label": self._abort_btn_label, + "handler": self.OnAbort, + "btnsAction": self._infobar_message_btns, + } + ] if buttons is None else buttons, ) + self._infobar_message_btns["addBtn"] = False def DownloadItem(self, item): """Download the selected item""" @@ -372,11 +392,15 @@ def DownloadItem(self, item): "Project name {name} already exists in {path}, download canceled" ).format(name=dirname, path=self.database) ) + self._infobar_message_btns.update( + dict(zip(("addBtn", "removeBtn"), (False, True))), + ) self._change_download_btn_label() return def download_complete_callback(event): self._download_in_progress = False + self._infobar_message_btns["addBtn"] = True errors = event.ret if errors: self._error(_("Download failed: %s") % errors) @@ -389,6 +413,9 @@ def download_complete_callback(event): ) ) self.parent.newLocationIsDownloaded.emit() + self._infobar_message_btns.update( + dict(zip(("addBtn", "removeBtn"), (False, True))), + ) self._change_download_btn_label() self.parent.Show(True) @@ -412,6 +439,7 @@ def OnChangeChoice(self, event): def CheckItem(self, item): """Check what user selected and report potential issues""" # similar code as in DownloadItem + self._infobar_message_btns["addBtn"] = True url = item["url"] dirname = location_name_from_url(url) destination = os.path.join(self.database, dirname) @@ -421,6 +449,7 @@ def CheckItem(self, item): name=dirname ) ) + self._infobar_message_btns["addBtn"] = False if hasattr(self.parent, "download_button"): self.parent.download_button.SetLabel(label=_("Download")) return From 1b9482caefe4fb48c8cba388550b2b8d11c45281 Mon Sep 17 00:00:00 2001 From: Tomas Zigo Date: Mon, 26 Feb 2024 14:58:30 +0100 Subject: [PATCH 6/7] Incorporate suggestion --- gui/wxpython/startup/locdownload.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/gui/wxpython/startup/locdownload.py b/gui/wxpython/startup/locdownload.py index f5e80319081..675b1eb0e3b 100644 --- a/gui/wxpython/startup/locdownload.py +++ b/gui/wxpython/startup/locdownload.py @@ -408,8 +408,8 @@ def download_complete_callback(event): self._last_downloaded_location_name = dirname self._warning( _( - "Download completed. The downloaded sample data is available " - "now in the data tree" + "Download completed. The downloaded sample data is listed " + "in the location/mapset tree." ) ) self.parent.newLocationIsDownloaded.emit() @@ -417,7 +417,8 @@ def download_complete_callback(event): dict(zip(("addBtn", "removeBtn"), (False, True))), ) self._change_download_btn_label() - self.parent.Show(True) + if errors: + self.parent.Show(True) self._download_in_progress = True self._warning(_("Download in progress, wait until it is finished")) From c0dbb5a776c6189b80f23084fb13cb6e5079e1ce Mon Sep 17 00:00:00 2001 From: Tomas Zigo Date: Tue, 5 Nov 2024 07:33:09 +0100 Subject: [PATCH 7/7] Fix Ruff RET505 [*] Unnecessary after statement error --- gui/wxpython/startup/locdownload.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/gui/wxpython/startup/locdownload.py b/gui/wxpython/startup/locdownload.py index 675b1eb0e3b..e0f83cd41f3 100644 --- a/gui/wxpython/startup/locdownload.py +++ b/gui/wxpython/startup/locdownload.py @@ -366,16 +366,18 @@ def ShowInfoBarMessage(self, message, buttons=None): if hasattr(self.parent, "showInfoBarMessage"): self.parent.showInfoBarMessage.emit( message=message, - buttons=[ - { - "id": self._infobar_message_btn_id, - "label": self._abort_btn_label, - "handler": self.OnAbort, - "btnsAction": self._infobar_message_btns, - } - ] - if buttons is None - else buttons, + buttons=( + [ + { + "id": self._infobar_message_btn_id, + "label": self._abort_btn_label, + "handler": self.OnAbort, + "btnsAction": self._infobar_message_btns, + } + ] + if buttons is None + else buttons + ), ) self._infobar_message_btns["addBtn"] = False @@ -454,10 +456,9 @@ def CheckItem(self, item): if hasattr(self.parent, "download_button"): self.parent.download_button.SetLabel(label=_("Download")) return - else: - if hasattr(self.parent, "dismissShowInfoBarMessage"): - self.parent.dismissShowInfoBarMessage.emit() - self._clearMessage() + if hasattr(self.parent, "dismissShowInfoBarMessage"): + self.parent.dismissShowInfoBarMessage.emit() + self._clearMessage() def GetLocation(self): """Get the name of the last location downloaded by the user"""