Skip to content

Commit

Permalink
wxGUI/datalog: fix crashing due to accessing GUI from other thread (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
petrasovaa committed Oct 17, 2020
1 parent b44377c commit 1962602
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 30 deletions.
17 changes: 2 additions & 15 deletions gui/wxpython/datacatalog/catalog.py
Expand Up @@ -18,7 +18,6 @@
import wx
import os

from core.gthread import gThread
from core.debug import Debug
from datacatalog.tree import DataCatalogTree
from datacatalog.toolbars import DataCatalogToolbar
Expand All @@ -45,8 +44,6 @@ def __init__(self, parent, giface=None, id=wx.ID_ANY,

# tree with layers
self.tree = DataCatalogTree(self, giface=giface)
self.thread = gThread()
self._loaded = False
self.tree.showNotification.connect(self.showNotification)

# some layout
Expand All @@ -68,21 +65,11 @@ def _layout(self):
self.Layout()

def LoadItems(self):
if self._loaded:
return

self.thread.Run(callable=self.tree.ReloadTreeItems,
ondone=lambda event: self.LoadItemsDone())

def LoadItemsDone(self):
self._loaded = True
self.tree.UpdateCurrentDbLocationMapsetNode()
self.tree.ExpandCurrentMapset()
self.tree.ReloadTreeItems()

def OnReloadTree(self, event):
"""Reload whole tree"""
self.tree.ReloadTreeItems()
self.tree.ExpandCurrentMapset()
self.LoadItems()

def OnReloadCurrentMapset(self, event):
"""Reload current mapset tree only"""
Expand Down
3 changes: 0 additions & 3 deletions gui/wxpython/datacatalog/frame.py
Expand Up @@ -53,8 +53,6 @@ def __init__(self, parent, giface=None):
# tree
self.tree = DataCatalogTree(parent=self.panel, giface=self._giface)
self.tree.ReloadTreeItems()
self.tree.UpdateCurrentDbLocationMapsetNode()
self.tree.ExpandCurrentMapset()

# buttons
self.btnClose = Button(parent=self.panel, id=wx.ID_CLOSE)
Expand Down Expand Up @@ -94,7 +92,6 @@ def OnCloseWindow(self, event):
def OnReloadTree(self, event):
"""Reload whole tree"""
self.tree.ReloadTreeItems()
self.tree.ExpandCurrentMapset()

def OnReloadCurrentMapset(self, event):
"""Reload current mapset tree only"""
Expand Down
32 changes: 20 additions & 12 deletions gui/wxpython/datacatalog/tree.py
Expand Up @@ -28,6 +28,7 @@
from core.gcmd import RunCommand, GError, GMessage, GWarning
from core.utils import GetListOfLocations
from core.debug import Debug
from core.gthread import gThread
from gui_core.dialogs import TextEntryDialog
from core.giface import StandaloneGrassInterface
from core.treemodel import TreeModel, DictNode
Expand Down Expand Up @@ -278,6 +279,7 @@ def __init__(
self._iconTypes = ['grassdb', 'location', 'mapset', 'raster',
'vector', 'raster_3d']
self._initImages()
self.thread = gThread()

self._resetSelectVariables()
self._resetCopyVariables()
Expand Down Expand Up @@ -478,8 +480,6 @@ def _reloadGrassDBNode(self, grassdb_node):
queue_list = []
loc_list = []
location_nodes = []
# refresh after each chunk to make GUI more responsive
self.RefreshItems()

for node in all_location_nodes:
self._model.SortChildren(node)
Expand All @@ -489,7 +489,10 @@ def _reloadGrassDBNode(self, grassdb_node):

def _reloadTreeItems(self):
"""Updates grass databases, locations, mapsets and layers in the tree.
Saves resulting data and error."""
It runs in thread, so it should not directly interact with GUI.
In case of any errors it returns the errors as a list of strings, otherwise None.
"""
errors = []
for grassdatabase in self.grassdatabases:
grassdb_nodes = self._model.SearchNodes(name=grassdatabase,
Expand All @@ -505,12 +508,8 @@ def _reloadTreeItems(self):
errors += error

if errors:
# WriteWarning/Error results in crash
self._giface.WriteLog('\n'.join(errors))
Debug.msg(1, "Tree filled")

self.UpdateCurrentDbLocationMapsetNode()
self.RefreshItems()
return errors
return None

def _renameNode(self, node, name):
"""Rename node (map, mapset, location), sort and refresh.
Expand Down Expand Up @@ -543,9 +542,18 @@ def is_current_mapset_node_locked():

def ReloadTreeItems(self):
"""Reload dbs, locations, mapsets and layers in the tree."""
busy = wx.BusyCursor()
self._reloadTreeItems()
del busy
self.busy = wx.BusyCursor()
self.thread.Run(callable=self._reloadTreeItems,
ondone=self._loadItemsDone)

def _loadItemsDone(self, event):
Debug.msg(1, "Tree filled")
del self.busy
if event.ret is not None:
self._giface.WriteWarning('\n'.join(event.ret))
self.UpdateCurrentDbLocationMapsetNode()
self.RefreshItems()
self.ExpandCurrentMapset()

def ReloadCurrentMapset(self):
"""Reload current mapset tree only."""
Expand Down

0 comments on commit 1962602

Please sign in to comment.