[GRASS-SVN] r71309 - in grass/trunk: gui/wxpython/core gui/wxpython/datacatalog lib/python/script

svn_grass at osgeo.org svn_grass at osgeo.org
Sat Jul 22 19:21:32 PDT 2017


Author: annakrat
Date: 2017-07-22 19:21:32 -0700 (Sat, 22 Jul 2017)
New Revision: 71309

Modified:
   grass/trunk/gui/wxpython/core/giface.py
   grass/trunk/gui/wxpython/datacatalog/dialogs.py
   grass/trunk/gui/wxpython/datacatalog/tree.py
   grass/trunk/lib/python/script/core.py
Log:
wxGUI/catalog: implement moving maps between mapsets and locations including reprojection

Modified: grass/trunk/gui/wxpython/core/giface.py
===================================================================
--- grass/trunk/gui/wxpython/core/giface.py	2017-07-22 19:35:06 UTC (rev 71308)
+++ grass/trunk/gui/wxpython/core/giface.py	2017-07-23 02:21:32 UTC (rev 71309)
@@ -247,7 +247,7 @@
         event.Skip()
 
     def RunCmd(self, command, compReg=True, env=None, skipInterface=False,
-               onDone=None, onPrepare=None, userData=None,
+               onDone=None, onPrepare=None, userData=None, addLayer=None,
                notification=Notification.MAKE_VISIBLE):
         self._gconsole.RunCmd(
             command=command,
@@ -257,6 +257,7 @@
             onDone=onDone,
             onPrepare=onPrepare,
             userData=userData,
+            addLayer=addLayer,
             notification=notification)
 
     def Help(self, entry):

Modified: grass/trunk/gui/wxpython/datacatalog/dialogs.py
===================================================================
--- grass/trunk/gui/wxpython/datacatalog/dialogs.py	2017-07-22 19:35:06 UTC (rev 71308)
+++ grass/trunk/gui/wxpython/datacatalog/dialogs.py	2017-07-23 02:21:32 UTC (rev 71309)
@@ -7,7 +7,7 @@
 Classes:
  - dialogs::CatalogReprojectionDialog
 
-(C) 2016 by the GRASS Development Team
+(C) 2017 by the GRASS Development Team
 
 This program is free software under the GNU General Public License
 (>=v2). Read the file COPYING that comes with GRASS for details.
@@ -17,63 +17,66 @@
 
 
 import wx
-import grass.script as gscript
-from grass.script import task as gtask
-from gui_core.forms import CmdPanel
+from gui_core.widgets import FloatValidator, IntegerValidator
 from core.giface import Notification
+from core.gcmd import RunCommand
 
+from grass.script import parse_key_val, region_env
 
+
 class CatalogReprojectionDialog(wx.Dialog):
-    """ """
-    def __init__(self, parent, giface, inputGisdbase, inputLocation, inputMapset, inputLayer,
-                 outputGisdbase, outputLocation, outputMapset, etype,
+    def __init__(self, parent, giface, inputGisdbase, inputLocation,
+                 inputMapset, inputLayer, inputEnv,
+                 outputGisdbase, outputLocation, outputMapset, outputLayer,
+                 etype, outputEnv, callback,
                  id=wx.ID_ANY, title=_("Reprojection"),
                  style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
-        self.parent = parent    # GMFrame
-        self._giface = giface  # used to add layers
 
+        self.parent = parent
+        self._giface = giface
+
         wx.Dialog.__init__(self, parent, id, title, style=style,
                            name="ReprojectionDialog")
 
-        self.panel = wx.Panel(parent=self, id=wx.ID_ANY)
+        self.panel = wx.Panel(parent=self)
         self.iGisdbase = inputGisdbase
         self.iLocation = inputLocation
         self.iMapset = inputMapset
         self.iLayer = inputLayer
+        self.iEnv = inputEnv
         self.oGisdbase = outputGisdbase
         self.oLocation = outputLocation
         self.oMapset = outputMapset
+        self.oLayer = outputLayer
         self.etype = etype
+        self.oEnv = outputEnv
+        self.callback = callback
 
-        self._blackList = {
-            'enabled': True,
-            'items': {
-                'r.proj': {
-                    'params': ['location', 'mapset', 'input', 'dbase'],
-                    'flags': ['l']},
-                'v.proj': {
-                    'params': ['location', 'mapset', 'input', 'dbase'],
-                    'flags': ['l']}}}
+        self._widgets()
+        self._doLayout()
 
         if self.etype == 'raster':
-            grass_task = gtask.parse_interface('r.proj', blackList=self._blackList)
-        elif self.etype == 'vector':
-            grass_task = gtask.parse_interface('v.proj', blackList=self._blackList)
+            self._estimateResampling()
+            self._estimateResolution()
 
-        self.settingsPanel = CmdPanel(parent=self, giface=self._giface, task=grass_task, frame=None)
-        self.closeOnFinished = wx.CheckBox(self.panel, label=_("Close dialog on finish"))
+    def _widgets(self):
+        if self.etype == 'raster':
+            self.resolution = wx.TextCtrl(self.panel, validator=FloatValidator())
+            self.resampling = wx.Choice(self.panel, size=(200, -1),
+                                        choices=['nearest', 'bilinear', 'bicubic', 'lanczos',
+                                                 'bilinear_f', 'bicubic_f', 'lanczos_f'])
+        else:
+            self.vsplit = wx.TextCtrl(self.panel, validator=IntegerValidator())
+            self.vsplit.SetValue('10000')
+
         #
         # buttons
         #
-        # cancel
         self.btn_close = wx.Button(parent=self.panel, id=wx.ID_CLOSE)
-        self.btn_close.Bind(wx.EVT_BUTTON, lambda evt: self.Close())
+        self.SetEscapeId(self.btn_close.GetId())
 
         # run
-        self.btn_run = wx.Button(
-            parent=self.panel,
-            id=wx.ID_OK,
-            label=_("Reproject"))
+        self.btn_run = wx.Button(parent=self.panel, id=wx.ID_OK, label=_("Reproject"))
         if self.etype == 'raster':
             self.btn_run.SetToolTipString(_("Reproject raster"))
         elif self.etype == 'vector':
@@ -81,62 +84,98 @@
         self.btn_run.SetDefault()
         self.btn_run.Bind(wx.EVT_BUTTON, self.OnReproject)
 
-        self.doLayout()
-
-    def doLayout(self):
+    def _doLayout(self):
         """Do layout"""
         dialogSizer = wx.BoxSizer(wx.VERTICAL)
+        optionsSizer = wx.GridBagSizer(5, 5)
 
-        dialogSizer.Add(wx.StaticText(self.panel, label=_("The copied layer needs to be reprojected:")),
-                        flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, border=5)
-        dialogSizer.Add(self.settingsPanel, proportion=1,
-                        flag=wx.ALL | wx.EXPAND, border=5)
-        dialogSizer.Add(self.closeOnFinished, flag=wx.ALL | wx.EXPAND, border=5)
-
+        label = _("Map layer <{ml}> needs to be reprojected.\n"
+                  "Please review and modify reprojection parameters:").format(ml=self.iLayer)
+        dialogSizer.Add(wx.StaticText(self.panel, label=label),
+                        flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, border=10)
+        if self.etype == 'raster':
+            optionsSizer.Add(wx.StaticText(self.panel, label=_("Estimated resolution:")),
+                             pos=(0, 0), flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)
+            optionsSizer.Add(self.resolution, pos=(0, 1), flag=wx.EXPAND)
+            optionsSizer.Add(wx.StaticText(self.panel, label=_("Resampling method:")),
+                             pos=(1, 0), flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)
+            optionsSizer.Add(self.resampling, pos=(1, 1), flag=wx.EXPAND)
+        else:
+            optionsSizer.Add(wx.StaticText(self.panel, label=_("Maximum segment length:")),
+                             pos=(1, 0), flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)
+            optionsSizer.Add(self.vsplit, pos=(1, 1), flag=wx.EXPAND)
+        optionsSizer.AddGrowableCol(1)
+        dialogSizer.Add(optionsSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=10)
+        helptext = wx.StaticText(self.panel,
+                                 label="For more reprojection options,"
+                                       " please see {module}".format(module='r.proj' if self.etype == 'raster'
+                                                                     else 'v.proj'))
+        dialogSizer.Add(helptext, proportion=0, flag=wx.ALL | wx.EXPAND, border=10)
         #
         # buttons
         #
-        btnsizer = wx.BoxSizer(orient=wx.HORIZONTAL)
+        btnStdSizer = wx.StdDialogButtonSizer()
+        btnStdSizer.AddButton(self.btn_run)
+        btnStdSizer.AddButton(self.btn_close)
+        btnStdSizer.Realize()
+        dialogSizer.Add(btnStdSizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
 
-        btnsizer.Add(self.btn_close, proportion=0,
-                     flag=wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER,
-                     border=10)
-
-        btnsizer.Add(self.btn_run, proportion=0,
-                     flag=wx.RIGHT | wx.ALIGN_CENTER,
-                     border=10)
-
-        dialogSizer.Add(
-            btnsizer,
-            proportion=0,
-            flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT,
-            border=5)
-
         self.panel.SetSizer(dialogSizer)
         dialogSizer.Fit(self.panel)
 
         self.Layout()
-        # sizing not working properly
-        self.SetMinSize(self.GetBestSize())
+        self.SetSize(self.GetBestSize())
 
-    def getSettingsPageCmd(self):
-        return self.settingsPanel.createCmd(
-            ignoreErrors=True, ignoreRequired=True)
+    def _estimateResolution(self):
+        output = RunCommand('r.proj', flags='g', quiet=False, read=True, input=self.iLayer,
+                            dbase=self.iGisdbase, location=self.iLocation, mapset=self.iMapset,
+                            env=self.oEnv).strip()
+        params = parse_key_val(output, vsep=' ')
+        output = RunCommand('g.region', flags='ug', quiet=False, read=True, env=self.oEnv,
+                            parse=lambda x: parse_key_val(x, val_type=float), **params)
+        cell_ns = (output['n'] - output['s']) / output['rows']
+        cell_ew = (output['e'] - output['w']) / output['cols']
+        estimate = (cell_ew + cell_ns) / 2.
+        self.resolution.SetValue(str(estimate))
+        self.params = params
 
+    def _estimateResampling(self):
+        output = RunCommand('r.info', flags='g', quiet=False, read=True, map=self.iLayer,
+                            env=self.iEnv, parse=parse_key_val)
+        if output['datatype'] == 'CELL':
+            self.resampling.SetStringSelection('nearest')
+        else:
+            self.resampling.SetStringSelection('bilinear')
+
     def OnReproject(self, event):
-        cmd = self.getSettingsPageCmd()
-        cmd.append('dbase=' + self.iGisdbase)
-        cmd.append('location=' + self.iLocation)
-        cmd.append('mapset=' + self.iMapset)
-        cmd.append('input=' + self.iLayer)
+        cmd = []
+        if self.etype == 'raster':
+            cmd.append('r.proj')
+            cmd.append('dbase=' + self.iGisdbase)
+            cmd.append('location=' + self.iLocation)
+            cmd.append('mapset=' + self.iMapset)
+            cmd.append('input=' + self.iLayer)
+            cmd.append('output=' + self.oLayer)
+            cmd.append('method=' + self.resampling.GetStringSelection())
 
-        self.tmpfile, env = gscript.create_environment(self.oGisdbase, self.oLocation, self.oMapset)
+            self.oEnv['GRASS_REGION'] = region_env(n=self.params['n'], s=self.params['s'],
+                                                   e=self.params['e'], w=self.params['w'],
+                                                   flags='a', res=float(self.resolution.GetValue()),
+                                                   env=self.oEnv)
+        else:
+            cmd.append('v.proj')
+            cmd.append('dbase=' + self.iGisdbase)
+            cmd.append('location=' + self.iLocation)
+            cmd.append('mapset=' + self.iMapset)
+            cmd.append('input=' + self.iLayer)
+            cmd.append('output=' + self.oLayer)
+            cmd.append('smax=' + self.vsplit.GetValue())
 
-        self._giface.RunCmd(cmd, env=env,
-               onDone=self.OnDone, userData=None,
-               notification=Notification.MAKE_VISIBLE)
+        self._giface.RunCmd(cmd, env=self.oEnv, compReg=False, addLayer=False,
+                            onDone=self._onDone, userData=None,
+                            notification=Notification.MAKE_VISIBLE)
 
-    def OnDone(self, event):
-        gscript.try_remove(self.tmpfile)
-        if self.closeOnFinished.IsChecked() and event.returncode == 0:
-            self.Close()
+        event.Skip()
+
+    def _onDone(self, event):
+        self.callback()

Modified: grass/trunk/gui/wxpython/datacatalog/tree.py
===================================================================
--- grass/trunk/gui/wxpython/datacatalog/tree.py	2017-07-22 19:35:06 UTC (rev 71308)
+++ grass/trunk/gui/wxpython/datacatalog/tree.py	2017-07-23 02:21:32 UTC (rev 71309)
@@ -541,6 +541,7 @@
 
     def _initVariablesCatalog(self):
         """Init variables."""
+        self.copy_mode = False
         self.copy_layer = None
         self.copy_type = None
         self.copy_mapset = None
@@ -559,18 +560,24 @@
         """Add locations, mapsets and layers to the tree."""
         self._initTreeItems()
 
+    def OnMoveMap(self, event):
+        """Move layer or mapset (just save it temporarily, copying is done by paste)"""
+        self.copy_mode = False
+        self.copy_layer = self.selected_layer
+        self.copy_type = self.selected_type
+        self.copy_mapset = self.selected_mapset
+        self.copy_location = self.selected_location
+        label = _("Map <{layer}> marked for moving.").format(layer=self.copy_layer)
+        self.showNotification.emit(message=label)
+
     def OnCopyMap(self, event):
         """Copy layer or mapset (just save it temporarily, copying is done by paste)"""
+        self.copy_mode = True
         self.copy_layer = self.selected_layer
         self.copy_type = self.selected_type
         self.copy_mapset = self.selected_mapset
         self.copy_location = self.selected_location
-        label = _(
-            "Map <{layer}> marked for copying. "
-            "You can paste it to the current mapset "
-            "<{mapset}>.".format(
-                layer=self.copy_layer.label,
-                mapset=gisenv()['MAPSET']))
+        label = _("Map <{layer}> marked for copying.").format(layer=self.copy_layer)
         self.showNotification.emit(message=label)
 
     def OnRenameMap(self, event):
@@ -631,98 +638,115 @@
         gscript.try_remove(gisrc)
 
     def OnPasteMap(self, event):
-        """Paste layer"""
         # copying between mapsets of one location
         if not self.copy_layer:
-            GMessage(_("No map selected for copying."), parent=self)
+            if self.copy_mode:
+                GMessage(_("No map selected for copying."), parent=self)
+            else:
+                GMessage(_("No map selected for moving."), parent=self)
             return
+
+        gisrc, env = gscript.create_environment(
+                        gisenv()['GISDBASE'], self.selected_location.label, mapset=self.selected_mapset.label)
+        gisrc2, env2 = gscript.create_environment(
+                        gisenv()['GISDBASE'], self.copy_location.label, mapset=self.copy_mapset.label)
+        new_name = self.copy_layer.label
         if self.selected_location == self.copy_location:
-            gisrc, env = gscript.create_environment(
-                gisenv()['GISDBASE'], self.selected_location.label, mapset=self.selected_mapset.label)
-            new_name = self._getNewMapName(
-                _('New name'),
-                _('Copy map'),
-                self.copy_layer.label,
-                env=env,
-                mapset=self.selected_mapset.label,
-                element=self.copy_type.label)
-            if not new_name:
-                return
-            if map_exists(
-                    new_name, element=self.copy_type.label, env=env,
-                    mapset=self.selected_mapset.label):
-                GMessage(
-                    _("Failed to copy map: new map has the same name"),
-                    parent=self)
-                return
+            # within one mapset
+            if self.selected_mapset == self.copy_mapset:
+                # ignore when just moves map
+                if self.copy_mode is False:
+                    return
+                new_name = self._getNewMapName(_('New name'), _('Select new name'),
+                                               self.copy_layer.label, env=env,
+                                               mapset=self.selected_mapset.label,
+                                               element=self.copy_type.label)
+                if not new_name:
+                    return
+            # within one location, different mapsets
+            else:
+                if map_exists(new_name, element=self.copy_type.label, env=env,
+                              mapset=self.selected_mapset.label):
+                    new_name = self._getNewMapName(_('New name'), _('Select new name'),
+                                                   self.copy_layer.label, env=env,
+                                                   mapset=self.selected_mapset.label,
+                                                   element=self.copy_type.label)
+                    if not new_name:
+                        return
 
-            if not self.selected_type:
-                found = self._model.SearchNodes(
-                    parent=self.selected_mapset, type='element',
-                    name=self.copy_type.label)
-                self.selected_type = found[0] if found else None
-
-            overwrite = False
-            if self.selected_type:
-                found = self._model.SearchNodes(
-                    parent=self.selected_type,
-                    type=self.copy_type.label,
-                    name=new_name)
-                if found and found[0]:
-                    dlg = wx.MessageDialog(
-                        parent=self,
-                        message=_(
-                            "Map <{map}> already exists "
-                            "in the current mapset. "
-                            "Do you want to overwrite it?").format(
-                            map=new_name),
-                        caption=_("Overwrite?"),
-                        style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
-                    ret = dlg.ShowModal()
-                    dlg.Destroy()
-                    if ret == wx.ID_YES:
-                        overwrite = True
-
             string = self.copy_layer.label + '@' + self.copy_mapset.label + ',' + new_name
-
             pasted = 0
-            label = _("Copying <{name}>...").format(name=string)
+            if self.copy_mode:
+                label = _("Copying <{name}>...").format(name=string)
+            else:
+                label = _("Moving <{name}>...").format(name=string)
             self.showNotification.emit(message=label)
             if self.copy_type.label == 'vector':
-                pasted, cmd = self._runCommand(
-                    'g.copy', vector=string, overwrite=overwrite, env=env)
+                pasted, cmd = self._runCommand('g.copy', vector=string, env=env)
                 node = 'vector'
             elif self.copy_type.label == 'raster':
-                pasted, cmd = self._runCommand(
-                    'g.copy', raster=string, overwrite=overwrite, env=env)
+                pasted, cmd = self._runCommand('g.copy', raster=string, env=env)
                 node = 'raster'
             else:
-                pasted, cmd = self._runCommand(
-                    'g.copy', raster_3d=string, overwrite=overwrite, env=env)
+                pasted, cmd = self._runCommand('g.copy', raster_3d=string, env=env)
                 node = 'raster_3d'
             if pasted == 0:
-                self.InsertLayer(
-                    name=new_name,
-                    mapset_node=self.selected_mapset,
-                    element_name=node)
+                self.InsertLayer(name=new_name, mapset_node=self.selected_mapset,
+                                 element_name=node)
                 Debug.msg(1, "COPIED TO: " + new_name)
-                self.showNotification.emit(
-                    message=_("g.copy completed").format(cmd=cmd))
+                if self.copy_mode:
+                    self.showNotification.emit(message=_("g.copy completed").format(cmd=cmd))
+                else:
+                    self.showNotification.emit(message=_("g.copy completed").format(cmd=cmd))
+
+                # remove old
+                if not self.copy_mode:
+                    self._removeMapAfterCopy(env2)
+
             gscript.try_remove(gisrc)
+            gscript.try_remove(gisrc2)
+            # expand selected mapset
+            self.ExpandNode(self.selected_mapset, recursive=True)
+            self._initVariablesCatalog()
         else:
             if self.copy_type.label == 'raster_3d':
-                 GError(_("Reprojection is not implemented for 3D rasters"), parent=self)
-                 return
+                GError(_("Reprojection is not implemented for 3D rasters"), parent=self)
+                return
+            if map_exists(new_name, element=self.copy_type.label, env=env,
+                          mapset=self.selected_mapset.label):
+                new_name = self._getNewMapName(_('New name'), _('Select new name'),
+                                               self.copy_layer.label, env=env,
+                                               mapset=self.selected_mapset.label,
+                                               element=self.copy_type.label)
+                if not new_name:
+                    return
             gisdbase = gisenv()['GISDBASE']
+            callback = lambda: self._onDoneReprojection(iEnv=env2, iGisrc=gisrc2, oGisrc=gisrc)
             dlg = CatalogReprojectionDialog(self, self._giface, gisdbase, self.copy_location.label,
-                                            self.copy_mapset.label, self.copy_layer.label,
+                                            self.copy_mapset.label, self.copy_layer.label, env2,
                                             gisdbase, self.selected_location.label, self.selected_mapset.label,
-                                            etype=self.copy_type.label)
-            dlg.Show()
+                                            new_name, self.copy_type.label, env, callback)
+            dlg.ShowModal()
 
-        # expand selected mapset
+    def _onDoneReprojection(self, iEnv, iGisrc, oGisrc):
+        self.InsertLayer(name=self.copy_layer.label, mapset_node=self.selected_mapset,
+                         element_name=self.copy_type.label)
+        if not self.copy_mode:
+            self._removeMapAfterCopy(iEnv)
+        gscript.try_remove(iGisrc)
+        gscript.try_remove(oGisrc)
         self.ExpandNode(self.selected_mapset, recursive=True)
+        self._initVariablesCatalog()
 
+    def _removeMapAfterCopy(self, env):
+        removed, cmd = self._runCommand('g.remove', type=self.copy_type.label,
+                                        name=self.copy_layer.label, flags='f', env=env)
+        if removed == 0:
+            self._model.RemoveNode(self.copy_layer)
+            self.RefreshNode(self.copy_type, recursive=True)
+            Debug.msg(1, "LAYER " + self.copy_layer.label + " DELETED")
+            self.showNotification.emit(message=_("g.remove completed").format(cmd=cmd))
+
     def InsertLayer(self, name, mapset_node, element_name):
         """Insert layer into model and refresh tree"""
         found_element = self._model.SearchNodes(
@@ -813,27 +837,19 @@
 
     def OnEndDrag(self, node, event):
         """Copy layer into target"""
-
-        if not wx.GetMouseState().ControlDown():
-            GMessage(_("Moving maps not implemented"), parent=self)
-            event.Veto()
-            return
+        self.copy_mode = wx.GetMouseState().ControlDown()
         if node:
             self.DefineItems(node)
-            if self._restricted and gisenv(
-            )['MAPSET'] != self.selected_mapset.label:
-                GMessage(
-                    _("Maps can be copied only to current mapset"),
-                    parent=self)
+            if self._restricted and gisenv()['MAPSET'] != self.selected_mapset.label:
+                GMessage(_("To move or copy maps to other mapsets, unlock editing of other mapsets"),
+                         parent=self)
                 event.Veto()
                 return
-            if self.selected_location == self.copy_location and self.selected_mapset:
-                event.Allow()
-                self.OnPasteMap(event)
-                Debug.msg(1, "DROP DONE")
-            else:
-                event.Veto()
 
+            event.Allow()
+            Debug.msg(1, "DROP DONE")
+            self.OnPasteMap(event)
+
     def OnSwitchLocationMapset(self, event):
         genv = gisenv()
         if self.selected_location.label == genv['LOCATION_NAME']:
@@ -929,6 +945,12 @@
         genv = gisenv()
         currentLocation, currentMapset = self._isCurrent(genv)
 
+        item = wx.MenuItem(menu, wx.NewId(), _("&Cut"))
+        menu.AppendItem(item)
+        self.Bind(wx.EVT_MENU, self.OnMoveMap, item)
+        if not currentMapset:
+            item.Enable(False)
+
         item = wx.MenuItem(menu, wx.NewId(), _("&Copy"))
         menu.AppendItem(item)
         self.Bind(wx.EVT_MENU, self.OnCopyMap, item)
@@ -940,7 +962,7 @@
         item = wx.MenuItem(menu, wx.NewId(), _("&Paste"))
         menu.AppendItem(item)
         self.Bind(wx.EVT_MENU, self.OnPasteMap, item)
-        if not(currentLocation and self.copy_layer):
+        if not(currentMapset and self.copy_layer):
             item.Enable(False)
 
         item = wx.MenuItem(menu, wx.NewId(), _("&Delete"))
@@ -977,7 +999,7 @@
         item = wx.MenuItem(menu, wx.NewId(), _("&Paste"))
         menu.AppendItem(item)
         self.Bind(wx.EVT_MENU, self.OnPasteMap, item)
-        if not(currentLocation and self.copy_layer):
+        if not(currentMapset and self.copy_layer):
             item.Enable(False)
 
         item = wx.MenuItem(menu, wx.NewId(), _("&Switch mapset"))
@@ -997,7 +1019,7 @@
         self.Bind(wx.EVT_MENU, self.OnPasteMap, item)
         genv = gisenv()
         currentLocation, currentMapset = self._isCurrent(genv)
-        if not(currentLocation and self.copy_layer):
+        if not(currentMapset and self.copy_layer):
             item.Enable(False)
 
         self.PopupMenu(menu)

Modified: grass/trunk/lib/python/script/core.py
===================================================================
--- grass/trunk/lib/python/script/core.py	2017-07-22 19:35:06 UTC (rev 71308)
+++ grass/trunk/lib/python/script/core.py	2017-07-23 02:21:32 UTC (rev 71309)
@@ -999,7 +999,7 @@
 # interface to g.gisenv
 
 
-def gisenv():
+def gisenv(env=None):
     """Returns the output from running g.gisenv (with no arguments), as a
     dictionary. Example:
 
@@ -1007,9 +1007,10 @@
     >>> print(env['GISDBASE'])  # doctest: +SKIP
     /opt/grass-data
 
+    :param env run with different environment
     :return: list of GRASS variables
     """
-    s = read_command("g.gisenv", flags='n')
+    s = read_command("g.gisenv", flags='n', env=env)
     return parse_key_val(s)
 
 # interface to g.region
@@ -1029,12 +1030,13 @@
         return False
 
 
-def region(region3d=False, complete=False):
+def region(region3d=False, complete=False, env=None):
     """Returns the output from running "g.region -gu", as a
     dictionary. Example:
 
     :param bool region3d: True to get 3D region
     :param bool complete:
+    :param env env
 
     >>> curent_region = region()
     >>> # obtain n, s, e and w values
@@ -1052,7 +1054,7 @@
     if complete:
         flgs += 'cep'
 
-    s = read_command("g.region", flags=flgs)
+    s = read_command("g.region", flags=flgs, env=env)
     reg = parse_key_val(s, val_type=float)
     for k in ['projection', 'zone', 'rows',  'cols',  'cells',
               'rows3', 'cols3', 'cells3', 'depths']:
@@ -1063,7 +1065,7 @@
     return reg
 
 
-def region_env(region3d=False, **kwargs):
+def region_env(region3d=False, flags=None, env=None, **kwargs):
     """Returns region settings as a string which can used as
     GRASS_REGION environmental variable.
 
@@ -1074,6 +1076,8 @@
     temporary region used for raster-based computation.
 
     :param bool region3d: True to get 3D region
+    :param string flags: for example 'a'
+    :param env: different environment than current
     :param kwargs: g.region's parameters like 'raster', 'vector' or 'region'
 
     ::
@@ -1086,9 +1090,9 @@
     :return: empty string on error
     """
     # read proj/zone from WIND file
-    env = gisenv()
-    windfile = os.path.join(env['GISDBASE'], env['LOCATION_NAME'],
-                            env['MAPSET'], "WIND")
+    gis_env = gisenv(env)
+    windfile = os.path.join(gis_env['GISDBASE'], gis_env['LOCATION_NAME'],
+                            gis_env['MAPSET'], "WIND")
     fd = open(windfile, "r")
     grass_region = ''
     for line in fd.readlines():
@@ -1109,8 +1113,10 @@
     flgs = 'ug'
     if region3d:
         flgs += '3'
+    if flags:
+        flgs += flags
 
-    s = read_command('g.region', flags=flgs, **kwargs)
+    s = read_command('g.region', flags=flgs, env=env, **kwargs)
     if not s:
         return ''
     reg = parse_key_val(s)



More information about the grass-commit mailing list