Parcourir la source

wxGUI: save database, location and mapset to workspace and switch it when opening it (closes https://trac.osgeo.org/grass/ticket/3575)

It is no longer possible to just open workspace in a different mapset
than the one where it was saved. However, when session element is not
present (deleted or older gxw file) no mapset switching is performed.
Older versions of GRASS GIS simply ignore the session element.

An error message is given when mapset does not exist and options to
proceed or not are given with some details (can be improved by
diagnostics from grass.py if moved to library).


git-svn-id: https://svn.osgeo.org/grass/grass/trunk@73348 15284696-431f-4ddb-bdfa-cd5b030d7da7
Vaclav Petras il y a 6 ans
Parent
commit
053eaa89d5
3 fichiers modifiés avec 82 ajouts et 2 suppressions
  1. 35 0
      gui/wxpython/core/workspace.py
  2. 41 1
      gui/wxpython/lmgr/frame.py
  3. 6 1
      gui/wxpython/xml/grass-gxw.dtd

+ 35 - 0
gui/wxpython/core/workspace.py

@@ -29,6 +29,14 @@ from nviz.main import NvizSettings
 from grass.script import core as gcore
 
 
+def get_database_location_mapset():
+    """Returns GRASS database, location, and mapset as a tuple"""
+    gisenv = gcore.gisenv()
+    return (gisenv['GISDBASE'],
+            gisenv['LOCATION_NAME'],
+            gisenv['MAPSET'])
+
+
 class ProcessWorkspaceFile:
 
     def __init__(self, tree):
@@ -95,6 +103,9 @@ class ProcessWorkspaceFile:
 
     def __processFile(self):
         """Process workspace file"""
+
+        self.__processSession()
+        
         #
         # layer manager
         #
@@ -177,6 +188,17 @@ class ProcessWorkspaceFile:
             # process nviz_state
             self.__processNvizState(display)
 
+    def __processSession(self):
+        session = self.root.find('session')
+        if session is None:
+            self.database = None
+            self.location = None
+            self.mapset = None
+            return
+        self.database = self.__filterValue(self.__getNodeText(session, 'database'))
+        self.location = self.__filterValue(self.__getNodeText(session, 'location'))
+        self.mapset = self.__filterValue(self.__getNodeText(session, 'mapset'))
+
     def __processLayers(self, node, inGroup=-1):
         """Process layers/groups of selected display
 
@@ -813,6 +835,19 @@ class WriteWorkspaceFile(object):
 
         self.indent = + 4
 
+        database, location, mapset = get_database_location_mapset()
+
+        file.write('{indent}<session>\n'.format(indent=' ' * self.indent))
+        self.indent += 4
+        file.write('{indent}<database>{database}</database>\n'.format(
+            indent=' ' * self.indent, database=database))
+        file.write('{indent}<location>{location}</location>\n'.format(
+            indent=' ' * self.indent, location=location))
+        file.write('{indent}<mapset>{mapset}</mapset>\n'.format(
+            indent=' ' * self.indent, mapset=mapset))
+        self.indent -= 4
+        file.write('{indent}</session>\n'.format(indent=' ' * self.indent))
+
         # layer manager
         windowPos = self.lmgr.GetPosition()
         windowSize = self.lmgr.GetSize()

+ 41 - 1
gui/wxpython/lmgr/frame.py

@@ -1375,6 +1375,41 @@ class GMFrame(wx.Frame):
         self.workspaceFile = filename
         self._setTitle()
 
+    def _tryToSwitchMapsetFromWorkspaceFile(self, gxwXml):
+        returncode, errors = RunCommand('g.mapset',
+                      dbase=gxwXml.database,
+                      location=gxwXml.location,
+                      mapset=gxwXml.mapset,
+                      getErrorMsg=True,
+                      )
+        if returncode != 0:
+            # TODO: use the function from grass.py
+            reason = _("Most likely the database, location or mapset"
+                       " does not exist")
+            details = errors
+            message = _("Unable to change to location and mapset"
+                        " specified in the workspace.\n"
+                        "Reason: {reason}\nDetails: {details}\n\n"
+                        "Do you want to proceed with opening"
+                        " the workspace anyway?"
+                        ).format(**locals())
+            dlg = wx.MessageDialog(
+                parent=self, message=message, caption=_(
+                    "Proceed with opening of the workspace?"),
+                style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
+            dlg.CenterOnParent()
+            if dlg.ShowModal() in [wx.ID_NO, wx.ID_CANCEL]:
+                return False
+        else:
+            # TODO: copy from ChangeLocation function
+            GMessage(
+                parent=self,
+                message=_("Current location is <%(loc)s>.\n"
+                          "Current mapset is <%(mapset)s>.") %
+                          {'loc': gxwXml.location,
+                           'mapset': gxwXml.mapset})
+        return True
+
     def LoadWorkspaceFile(self, filename):
         """Load layer tree definition stored in GRASS Workspace XML file (gxw)
 
@@ -1393,8 +1428,13 @@ class GMFrame(wx.Frame):
                     "Reading workspace file <%s> failed.\n"
                     "Invalid file, unable to parse XML document.") %
                 filename)
-            return
+            return False
+
+        if gxwXml.database and gxwXml.location and gxwXml.mapset:
+            if not self._tryToSwitchMapsetFromWorkspaceFile(gxwXml):
+                return False
 
+        # the really busy part starts here (mapset change is fast)
         busy = wx.BusyInfo(_("Please wait, loading workspace..."),
                            parent=self)
         wx.Yield()

+ 6 - 1
gui/wxpython/xml/grass-gxw.dtd

@@ -14,7 +14,12 @@
 
 <!ELEMENT grass-gxw (gxw)>
 
-<!ELEMENT gxw (layer_manager?, display*)>
+<!ELEMENT gxw (session?, layer_manager?, display*)>
+
+<!ELEMENT session (database, location, mapset)>
+<!ELEMENT database (#PCDATA)>
+<!ELEMENT location (#PCDATA)>
+<!ELEMENT mapset (#PCDATA)>
 
 <!--    a layer_manager defines properties of Layer Manager
 	GUI component