Browse Source

wxGUI/psmap: properly isolate region setting from the rest of GUI (#1127)

fixes #1047
Anna Petrasova 4 năm trước cách đây
mục cha
commit
8d784d192c

+ 133 - 102
gui/wxpython/psmap/dialogs.py

@@ -208,12 +208,13 @@ class CheckListCtrl(ListCtrl, CheckListCtrlMixin, ListCtrlAutoWidthMixin):
 
 class PsmapDialog(Dialog):
 
-    def __init__(self, parent, id, title, settings, apply=True):
+    def __init__(self, parent, id, title, settings, env, apply=True):
         Dialog.__init__(self, parent=parent, id=wx.ID_ANY,
                            title=title, size=wx.DefaultSize,
                            style=wx.CAPTION | wx.MINIMIZE_BOX | wx.CLOSE_BOX)
         self.apply = apply
         self.id = id
+        self.env = env
         self.parent = parent
         self.instruction = settings
         self.objectType = None
@@ -347,7 +348,8 @@ class PsmapDialog(Dialog):
             mapInstr=self.instruction[self.mapId],
             x=dialogDict['where'][0],
             y=dialogDict['where'][1],
-            paperToMap=True)
+            paperToMap=True,
+            env=self.env)
         panel.position['eCtrl'].SetValue(str(east))
         panel.position['nCtrl'].SetValue(str(north))
 
@@ -499,13 +501,14 @@ class PsmapDialog(Dialog):
 
 class PageSetupDialog(PsmapDialog):
 
-    def __init__(self, parent, id, settings):
+    def __init__(self, parent, id, settings, env):
         PsmapDialog.__init__(
             self,
             parent=parent,
             id=id,
             title="Page setup",
-            settings=settings)
+            settings=settings,
+            env=env)
 
         self.cat = [
             'Units',
@@ -725,13 +728,14 @@ class PageSetupDialog(PsmapDialog):
 class MapDialog(PsmapDialog):
     """Dialog for map frame settings and optionally  raster and vector map selection"""
 
-    def __init__(self, parent, id, settings, rect=None, notebook=False):
+    def __init__(self, parent, id, settings, env, rect=None, notebook=False):
         PsmapDialog.__init__(
             self,
             parent=parent,
             id=id,
             title="",
-            settings=settings)
+            settings=settings,
+            env=env)
 
         self.isNotebook = notebook
         if self.isNotebook:
@@ -747,16 +751,17 @@ class MapDialog(PsmapDialog):
                 parent=self.notebook,
                 id=self.id[0],
                 settings=self.instruction,
+                env=env,
                 rect=rect,
                 notebook=True)
             self.id[0] = self.mPanel.getId()
             self.rPanel = RasterPanel(
                 parent=self.notebook, id=self.id[1],
-                settings=self.instruction, notebook=True)
+                settings=self.instruction, env=env, notebook=True)
             self.id[1] = self.rPanel.getId()
             self.vPanel = VectorPanel(
                 parent=self.notebook, id=self.id[2],
-                settings=self.instruction, notebook=True)
+                settings=self.instruction, env=env, notebook=True)
             self.id[2] = self.vPanel.getId()
             self._layout(self.notebook)
             self.SetTitle(_("Map settings"))
@@ -765,6 +770,7 @@ class MapDialog(PsmapDialog):
                 parent=self,
                 id=self.id[0],
                 settings=self.instruction,
+                env=env,
                 rect=rect,
                 notebook=False)
             self.id[0] = self.mPanel.getId()
@@ -819,11 +825,12 @@ class MapDialog(PsmapDialog):
 class MapFramePanel(Panel):
     """Panel with map (scale, region, border) settings"""
 
-    def __init__(self, parent, id, settings, rect, notebook=True):
+    def __init__(self, parent, id, settings, env, rect, notebook=True):
         Panel.__init__(self, parent, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL)
 
         self.id = id
         self.instruction = settings
+        self.env = env
 
         if notebook:
             self.book = parent
@@ -836,7 +843,7 @@ class MapFramePanel(Panel):
             self.mapFrameDict = self.instruction[self.id].GetInstruction()
         else:
             self.id = NewId()
-            mapFrame = MapFrame(self.id)
+            mapFrame = MapFrame(self.id, env=self.env)
             self.mapFrameDict = mapFrame.GetInstruction()
             self.mapFrameDict['rect'] = rect
 
@@ -1182,18 +1189,18 @@ class MapFramePanel(Panel):
 
             self.scale[0], self.center[0], foo = AutoAdjust(
                 self, scaleType=0, map=self.selected, mapType=mapType,
-                rect=self.mapFrameDict['rect'])
+                rect=self.mapFrameDict['rect'], env=self.env)
             #self.center[0] = self.RegionCenter(self.RegionDict(scaleType = 0))
 
         elif self.scaleChoice.GetSelection() == 1:
             self.selectedRegion = self.selected
             self.scale[1], self.center[1], foo = AutoAdjust(
                 self, scaleType=1, region=self.selected,
-                rect=self.mapFrameDict['rect'])
+                rect=self.mapFrameDict['rect'], env=self.env)
             #self.center[1] = self.RegionCenter(self.RegionDict(scaleType = 1))
         elif self.scaleChoice.GetSelection() == 2:
             self.scale[2], self.center[2], foo = AutoAdjust(
-                self, scaleType=2, rect=self.mapFrameDict['rect'])
+                self, scaleType=2, rect=self.mapFrameDict['rect'], env=self.env)
             #self.center[2] = self.RegionCenter(self.RegionDict(scaleType = 2))
 
         else:
@@ -1330,7 +1337,7 @@ class MapFramePanel(Panel):
                         if raster:
                             raster['raster'] = mapFrameDict['map']
                         else:
-                            raster = Raster(NewId())
+                            raster = Raster(NewId(), env=self.env)
                             raster['raster'] = mapFrameDict['map']
                             raster['isRaster'] = True
                             self.instruction.AddInstruction(raster)
@@ -1367,13 +1374,13 @@ class MapFramePanel(Panel):
                                     mapFrameDict['map'].split('@')) + ')'
 
                                 if not vector:
-                                    vector = Vector(NewId())
+                                    vector = Vector(NewId(), env=self.env)
                                     vector['list'] = []
                                     self.instruction.AddInstruction(vector)
                                 id = NewId()
                                 vector['list'].insert(
                                     0, [mapFrameDict['map'], topoType, id, 1, label])
-                                vProp = VProperties(id, topoType)
+                                vProp = VProperties(id, topoType, env=self.env)
                                 vProp['name'], vProp['label'], vProp[
                                     'lpos'] = mapFrameDict['map'], label, 1
                                 self.instruction.AddInstruction(vProp)
@@ -1381,7 +1388,7 @@ class MapFramePanel(Panel):
                                 return False
 
                 self.scale[0], self.center[0], self.rectAdjusted = AutoAdjust(
-                    self, scaleType=0, map=mapFrameDict['map'],
+                    self, scaleType=0, map=mapFrameDict['map'], env=self.env,
                     mapType=self.mapType, rect=self.mapFrameDict['rect'])
 
                 if self.rectAdjusted:
@@ -1394,7 +1401,8 @@ class MapFramePanel(Panel):
                 mapFrameDict['center'] = self.center[0]
                 # set region
                 if self.mapType == 'raster':
-                    RunCommand('g.region', raster=mapFrameDict['map'])
+                    self.env['GRASS_REGION'] = grass.region_env(raster=mapFrameDict['map'],
+                                                                env=self.env)
                 if self.mapType == 'vector':
                     raster = self.instruction.FindInstructionByType('raster')
                     if raster:
@@ -1403,13 +1411,12 @@ class MapFramePanel(Panel):
                         rasterId = None
 
                     if rasterId:
-
-                        RunCommand(
-                            'g.region',
-                            vector=mapFrameDict['map'],
-                            raster=self.instruction[rasterId]['raster'])
+                        self.env['GRASS_REGION'] = grass.region_env(vector=mapFrameDict['map'],
+                                                                    raster=self.instruction[rasterId]['raster'],
+                                                                    env=self.env)
                     else:
-                        RunCommand('g.region', vector=mapFrameDict['map'])
+                        self.env['GRASS_REGION'] = grass.region_env(vector=mapFrameDict['map'],
+                                                                    env=self.env)
 
             else:
                 wx.MessageBox(
@@ -1425,7 +1432,8 @@ class MapFramePanel(Panel):
                 mapFrameDict['mapType'] = None
                 mapFrameDict['region'] = self.select.GetValue()
                 self.scale[1], self.center[1], self.rectAdjusted = AutoAdjust(
-                    self, scaleType=1, region=mapFrameDict['region'], rect=self.mapFrameDict['rect'])
+                    self, scaleType=1, region=mapFrameDict['region'],
+                    rect=self.mapFrameDict['rect'], env=self.env)
                 if self.rectAdjusted:
                     mapFrameDict['rect'] = self.rectAdjusted
                 else:
@@ -1434,7 +1442,8 @@ class MapFramePanel(Panel):
                 mapFrameDict['scale'] = self.scale[1]
                 mapFrameDict['center'] = self.center[1]
                 # set region
-                RunCommand('g.region', region=mapFrameDict['region'])
+                self.env['GRASS_REGION'] = grass.region_env(region=mapFrameDict['region'],
+                                                            env=self.env)
             else:
                 wx.MessageBox(
                     message=_("No region selected!"),
@@ -1448,7 +1457,7 @@ class MapFramePanel(Panel):
             mapFrameDict['mapType'] = None
             mapFrameDict['region'] = None
             self.scale[2], self.center[2], self.rectAdjusted = AutoAdjust(
-                self, scaleType=2, rect=self.mapFrameDict['rect'])
+                self, scaleType=2, rect=self.mapFrameDict['rect'], env=self.env)
             if self.rectAdjusted:
                 mapFrameDict['rect'] = self.rectAdjusted
             else:
@@ -1456,7 +1465,7 @@ class MapFramePanel(Panel):
 
             mapFrameDict['scale'] = self.scale[2]
             mapFrameDict['center'] = self.center[2]
-            region = grass.region()
+            region = grass.region(env=None)
 
             raster = self.instruction.FindInstructionByType('raster')
             if raster:
@@ -1465,16 +1474,14 @@ class MapFramePanel(Panel):
                 rasterId = None
 
             if rasterId:  # because of resolution
-                RunCommand(
-                    'g.region',
-                    n=region['n'],
-                    s=region['s'],
-                    e=region['e'],
-                    w=region['w'],
-                    rast=self.instruction[rasterId]['raster'])
+                self.env['GRASS_REGION'] = grass.region_env(n=region['n'], s=region['s'],
+                                                            e=region['e'], w=region['w'],
+                                                            raster=self.instruction[rasterId]['raster'],
+                                                            env=self.env)
             else:
-                RunCommand('g.region', n=region['n'], s=region['s'],
-                           e=region['e'], w=region['w'])
+                self.env['GRASS_REGION'] = grass.region_env(n=region['n'], s=region['s'],
+                                                            e=region['e'], w=region['w'],
+                                                            env=self.env)
 
         elif scaleType == 3:
             mapFrameDict['drawMap'] = False
@@ -1495,13 +1502,14 @@ class MapFramePanel(Panel):
             mapFrameDict['scale'] = 1 / scaleNumber
             mapFrameDict['center'] = centerE, centerN
 
-            ComputeSetRegion(self, mapDict=mapFrameDict)
+            ComputeSetRegion(self, mapDict=mapFrameDict, env=self.env)
 
         # check resolution
         SetResolution(
             dpi=mapFrameDict['resolution'],
             width=mapFrameDict['rect'].width,
-            height=mapFrameDict['rect'].height)
+            height=mapFrameDict['rect'].height,
+            env=self.env)
         # border
         if self.borderCheck.GetValue():
             mapFrameDict['border'] = 'y'
@@ -1514,7 +1522,7 @@ class MapFramePanel(Panel):
                 self.borderColourPicker.GetColour())
 
         if self.id not in self.instruction:
-            mapFrame = MapFrame(self.id)
+            mapFrame = MapFrame(self.id, env=self.env)
             self.instruction.AddInstruction(mapFrame)
         self.instruction[self.id].SetInstruction(mapFrameDict)
 
@@ -1527,9 +1535,10 @@ class MapFramePanel(Panel):
 class RasterPanel(Panel):
     """Panel for raster map settings"""
 
-    def __init__(self, parent, id, settings, notebook=True):
+    def __init__(self, parent, id, settings, env, notebook=True):
         Panel.__init__(self, parent, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL)
         self.instruction = settings
+        self.env = env
 
         if notebook:
             self.book = parent
@@ -1542,7 +1551,7 @@ class RasterPanel(Panel):
             self.rasterDict = self.instruction[self.id].GetInstruction()
         else:
             self.id = NewId()
-            raster = Raster(self.id)
+            raster = Raster(self.id, env=self.env)
             self.rasterDict = raster.GetInstruction()
 
         self._layout()
@@ -1646,7 +1655,7 @@ class RasterPanel(Panel):
 
             raster = self.instruction.FindInstructionByType('raster')
             if not raster:
-                raster = Raster(self.id)
+                raster = Raster(self.id, env=self.env)
                 self.instruction.AddInstruction(raster)
                 self.instruction[self.id].SetInstruction(self.rasterDict)
             else:
@@ -1663,10 +1672,11 @@ class RasterPanel(Panel):
 class VectorPanel(Panel):
     """Panel for vector maps settings"""
 
-    def __init__(self, parent, id, settings, notebook=True):
+    def __init__(self, parent, id, settings, env, notebook=True):
         Panel.__init__(self, parent, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL)
 
         self.parent = parent
+        self.env = env
         self.instruction = settings
         self.tmpDialogDict = {}
         vectors = self.instruction.FindInstructionByType(
@@ -1865,7 +1875,7 @@ class VectorPanel(Panel):
             self.reposition()
             self.listbox.InsertItems([record], 0)
 
-            vector = VProperties(id, ttype)
+            vector = VProperties(id, ttype, env=self.env)
             self.tmpDialogDict[id] = vector.GetInstruction()
             self.tmpDialogDict[id]['name'] = vmap
 
@@ -1931,6 +1941,7 @@ class VectorPanel(Panel):
                 self,
                 id=id,
                 settings=self.instruction,
+                env=self.env,
                 vectors=self.vectorList,
                 tmpSettings=self.tmpDialogDict[id])
             dlg.ShowModal()
@@ -1974,7 +1985,7 @@ class VectorPanel(Panel):
             del self.instruction[self.id]
 
         if len(self.vectorList) > 0:
-            vector = Vector(self.id)
+            vector = Vector(self.id, env=self.env)
             self.instruction.AddInstruction(vector)
 
             vector.SetInstruction({'list': deepcopy(self.vectorList)})
@@ -1983,7 +1994,7 @@ class VectorPanel(Panel):
             for item in self.vectorList:
                 id = item[2]
 
-                vLayer = VProperties(id, item[1])
+                vLayer = VProperties(id, item[1], env=self.env)
                 self.instruction.AddInstruction(vLayer)
                 vLayer.SetInstruction(self.tmpDialogDict[id])
                 vLayer['name'] = item[0]
@@ -2002,20 +2013,22 @@ class VectorPanel(Panel):
 
 class RasterDialog(PsmapDialog):
 
-    def __init__(self, parent, id, settings):
+    def __init__(self, parent, id, settings, env):
         PsmapDialog.__init__(
             self,
             parent=parent,
             id=id,
             title=_("Raster map settings"),
-            settings=settings)
+            settings=settings,
+            env=env)
         self.objectType = ('raster',)
 
         self.rPanel = RasterPanel(
             parent=self,
             id=self.id,
             settings=self.instruction,
-            notebook=False)
+            notebook=False,
+            env=self.env)
 
         self.id = self.rPanel.getId()
         self._layout(self.rPanel)
@@ -2050,18 +2063,20 @@ class RasterDialog(PsmapDialog):
 
 class MainVectorDialog(PsmapDialog):
 
-    def __init__(self, parent, id, settings):
+    def __init__(self, parent, id, settings, env):
         PsmapDialog.__init__(
             self,
             parent=parent,
             id=id,
             title=_("Vector maps settings"),
-            settings=settings)
+            settings=settings,
+            env=env)
         self.objectType = ('vector',)
         self.vPanel = VectorPanel(
             parent=self,
             id=self.id,
             settings=self.instruction,
+            env=env,
             notebook=False)
 
         self.id = self.vPanel.getId()
@@ -2086,13 +2101,14 @@ class MainVectorDialog(PsmapDialog):
 
 class VPropertiesDialog(PsmapDialog):
 
-    def __init__(self, parent, id, settings, vectors, tmpSettings):
+    def __init__(self, parent, id, settings, vectors, tmpSettings, env):
         PsmapDialog.__init__(
             self,
             parent=parent,
             id=id,
             title="",
             settings=settings,
+            env=env,
             apply=False)
 
         vectorList = vectors
@@ -3292,13 +3308,14 @@ class VPropertiesDialog(PsmapDialog):
 
 class LegendDialog(PsmapDialog):
 
-    def __init__(self, parent, id, settings, page):
+    def __init__(self, parent, id, settings, page, env):
         PsmapDialog.__init__(
             self,
             parent=parent,
             id=id,
             title="Legend settings",
-            settings=settings)
+            settings=settings,
+            env=env)
         self.objectType = ('rasterLegend', 'vectorLegend')
         self.instruction = settings
         map = self.instruction.FindInstructionByType('map')
@@ -3327,7 +3344,7 @@ class LegendDialog(PsmapDialog):
             self.rLegendDict = self.rasterLegend.GetInstruction()
         else:
             self.id[0] = NewId()
-            self.rasterLegend = RasterLegend(self.id[0])
+            self.rasterLegend = RasterLegend(self.id[0], env=self.env)
             self.rLegendDict = self.rasterLegend.GetInstruction()
             self.rLegendDict['where'] = currPage['Left'], currPage['Top']
 
@@ -3336,7 +3353,7 @@ class LegendDialog(PsmapDialog):
             self.vLegendDict = self.instruction[self.id[1]].GetInstruction()
         else:
             self.id[1] = NewId()
-            vectorLegend = VectorLegend(self.id[1])
+            vectorLegend = VectorLegend(self.id[1], env=self.env)
             self.vLegendDict = vectorLegend.GetInstruction()
             self.vLegendDict['where'] = currPage['Left'], currPage['Top']
 
@@ -4268,7 +4285,7 @@ class LegendDialog(PsmapDialog):
                     self.rLegendDict['range'] = False
 
         if not self.id[0] in self.instruction:
-            rasterLegend = RasterLegend(self.id[0])
+            rasterLegend = RasterLegend(self.id[0], env=self.env)
             self.instruction.AddInstruction(rasterLegend)
         self.instruction[self.id[0]].SetInstruction(self.rLegendDict)
 
@@ -4378,7 +4395,7 @@ class LegendDialog(PsmapDialog):
                     self.vLegendDict['border'] = 'none'
 
         if not self.id[1] in self.instruction:
-            vectorLegend = VectorLegend(self.id[1])
+            vectorLegend = VectorLegend(self.id[1], env=self.env)
             self.instruction.AddInstruction(vectorLegend)
         self.instruction[self.id[1]].SetInstruction(self.vLegendDict)
         if self.id[1] not in self.parent.objectId:
@@ -4459,13 +4476,14 @@ class LegendDialog(PsmapDialog):
 
 class MapinfoDialog(PsmapDialog):
 
-    def __init__(self, parent, id, settings):
+    def __init__(self, parent, id, settings, env):
         PsmapDialog.__init__(
             self,
             parent=parent,
             id=id,
             title=_("Mapinfo settings"),
-            settings=settings)
+            settings=settings,
+            env=env)
 
         self.objectType = ('mapinfo',)
         if self.id is not None:
@@ -4473,7 +4491,7 @@ class MapinfoDialog(PsmapDialog):
             self.mapinfoDict = self.mapinfo.GetInstruction()
         else:
             self.id = NewId()
-            self.mapinfo = Mapinfo(self.id)
+            self.mapinfo = Mapinfo(self.id, env=self.env)
             self.mapinfoDict = self.mapinfo.GetInstruction()
             page = self.instruction.FindInstructionByType(
                 'page').GetInstruction()
@@ -4710,7 +4728,7 @@ class MapinfoDialog(PsmapDialog):
         self.mapinfoDict['rect'] = self.mapinfo.EstimateRect(self.mapinfoDict)
 
         if self.id not in self.instruction:
-            mapinfo = Mapinfo(self.id)
+            mapinfo = Mapinfo(self.id, env=self.env)
             self.instruction.AddInstruction(mapinfo)
 
         self.instruction[self.id].SetInstruction(self.mapinfoDict)
@@ -4736,20 +4754,21 @@ class MapinfoDialog(PsmapDialog):
 class ScalebarDialog(PsmapDialog):
     """Dialog for scale bar"""
 
-    def __init__(self, parent, id, settings):
+    def __init__(self, parent, id, settings, env):
         PsmapDialog.__init__(
             self,
             parent=parent,
             id=id,
             title="Scale bar settings",
-            settings=settings)
+            settings=settings,
+            env=env)
         self.objectType = ('scalebar',)
         if self.id is not None:
             self.scalebar = self.instruction[id]
             self.scalebarDict = self.scalebar.GetInstruction()
         else:
             self.id = NewId()
-            self.scalebar = Scalebar(self.id)
+            self.scalebar = Scalebar(self.id, env=self.env)
             self.scalebarDict = self.scalebar.GetInstruction()
             page = self.instruction.FindInstructionByType(
                 'page').GetInstruction()
@@ -4869,7 +4888,7 @@ class ScalebarDialog(PsmapDialog):
         if self.scalebarDict['length']:
             self.lengthTextCtrl.SetValue(str(self.scalebarDict['length']))
         else:  # estimate default
-            reg = grass.region()
+            reg = grass.region(env=self.env)
             w = int((reg['e'] - reg['w']) / 3)
             w = round(w, -len(str(w)) + 2)  # 12345 -> 12000
             self.lengthTextCtrl.SetValue(str(w))
@@ -5101,7 +5120,7 @@ class ScalebarDialog(PsmapDialog):
         self.scalebarDict['where'] = self.scalebarDict['rect'].GetCentre()
 
         if self.id not in self.instruction:
-            scalebar = Scalebar(self.id)
+            scalebar = Scalebar(self.id, env=self.env)
             self.instruction.AddInstruction(scalebar)
         self.instruction[self.id].SetInstruction(self.scalebarDict)
         if self.id not in self.parent.objectId:
@@ -5122,19 +5141,20 @@ class ScalebarDialog(PsmapDialog):
 
 class TextDialog(PsmapDialog):
 
-    def __init__(self, parent, id, settings):
+    def __init__(self, parent, id, settings, env):
         PsmapDialog.__init__(
             self,
             parent=parent,
             id=id,
             title="Text settings",
-            settings=settings)
+            settings=settings,
+            env=env)
         self.objectType = ('text',)
         if self.id is not None:
             self.textDict = self.instruction[id].GetInstruction()
         else:
             self.id = NewId()
-            text = Text(self.id)
+            text = Text(self.id, env=self.env)
             self.textDict = text.GetInstruction()
             page = self.instruction.FindInstructionByType(
                 'page').GetInstruction()
@@ -5148,7 +5168,8 @@ class TextDialog(PsmapDialog):
         self.textDict['east'], self.textDict['north'] = PaperMapCoordinates(
             mapInstr=map, x=self.textDict['where'][0],
             y=self.textDict['where'][1],
-            paperToMap=True)
+            paperToMap=True,
+            env=self.env)
 
         notebook = Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
         self.textPanel = self._textPanel(notebook)
@@ -5632,7 +5653,7 @@ class TextDialog(PsmapDialog):
                 value=float(y), fromUnit=currUnit, toUnit='inch')
             self.textDict['where'] = x, y
             self.textDict['east'], self.textDict['north'] = PaperMapCoordinates(
-                self.instruction[self.mapId], x, y, paperToMap=True)
+                self.instruction[self.mapId], x, y, paperToMap=True, env=self.env)
         else:
             self.textDict['XY'] = False
             if self.positionPanel.position['eCtrl'].GetValue():
@@ -5651,7 +5672,8 @@ class TextDialog(PsmapDialog):
                 mapInstr=self.instruction[
                     self.mapId], x=float(
                     self.textDict['east']), y=float(
-                    self.textDict['north']), paperToMap=False)
+                    self.textDict['north']), paperToMap=False,
+                    env=self.env)
         # rotation
         if self.rotCtrl.GetValue():
             self.textDict['rotate'] = self.rotValue.GetValue()
@@ -5663,7 +5685,7 @@ class TextDialog(PsmapDialog):
                 self.textDict['ref'] = radio.GetName()
 
         if self.id not in self.instruction:
-            text = Text(self.id)
+            text = Text(self.id, env=self.env)
             self.instruction.AddInstruction(text)
         self.instruction[self.id].SetInstruction(self.textDict)
 
@@ -5698,13 +5720,14 @@ class ImageDialog(PsmapDialog):
     It's base dialog for North Arrow dialog.
     """
 
-    def __init__(self, parent, id, settings, imagePanelName=_("Image")):
+    def __init__(self, parent, id, settings, env, imagePanelName=_("Image")):
         PsmapDialog.__init__(
             self,
             parent=parent,
             id=id,
             title="Image settings",
-            settings=settings)
+            settings=settings,
+            env=env)
 
         self.objectType = ('image',)
         if self.id is not None:
@@ -5726,7 +5749,7 @@ class ImageDialog(PsmapDialog):
         self.imageDict['east'], self.imageDict['north'] = PaperMapCoordinates(
             mapInstr=map, x=self.imageDict['where'][0],
             y=self.imageDict['where'][1],
-            paperToMap=True)
+            paperToMap=True, env=self.env)
 
         notebook = Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
         self.imagePanelName = imagePanelName
@@ -5745,7 +5768,7 @@ class ImageDialog(PsmapDialog):
 
     def _newObject(self):
         """Create corresponding instruction object"""
-        return Image(self.id, self.instruction)
+        return Image(self.id, self.instruction, env=self.env)
 
     def _imagePanel(self, notebook):
         panel = Panel(
@@ -6144,7 +6167,8 @@ class ImageDialog(PsmapDialog):
                 mapInstr=self.instruction[
                     self.mapId], x=float(
                     self.imageDict['east']), y=float(
-                    self.imageDict['north']), paperToMap=False)
+                    self.imageDict['north']), paperToMap=False,
+                    env=self.env)
 
         # rotation
         rot = self.imagePanel.image['rotate'].GetValue()
@@ -6203,15 +6227,15 @@ class ImageDialog(PsmapDialog):
 
 class NorthArrowDialog(ImageDialog):
 
-    def __init__(self, parent, id, settings):
+    def __init__(self, parent, id, settings, env):
         ImageDialog.__init__(self, parent=parent, id=id, settings=settings,
-                             imagePanelName=_("North Arrow"))
+                             imagePanelName=_("North Arrow"), env=env)
 
         self.objectType = ('northArrow',)
         self.SetTitle(_("North Arrow settings"))
 
     def _newObject(self):
-        return NorthArrow(self.id, self.instruction)
+        return NorthArrow(self.id, self.instruction, env=self.env)
 
     def _getImageDirectory(self):
         gisbase = os.getenv("GISBASE")
@@ -6226,7 +6250,7 @@ class NorthArrowDialog(ImageDialog):
         panel.image['convergence'] = convergence
 
     def OnConvergence(self, event):
-        ret = RunCommand('g.region', read=True, flags='ng')
+        ret = RunCommand('g.region', read=True, flags='nug', env=self.env)
         if ret:
             convergence = float(ret.strip().split('=')[1])
             if convergence < 0:
@@ -6239,14 +6263,15 @@ class PointDialog(PsmapDialog):
     """Dialog for setting point properties."""
 
     def __init__(
-            self, parent, id, settings, coordinates=None,
+            self, parent, id, settings, env, coordinates=None,
             pointPanelName=_("Point")):
         PsmapDialog.__init__(
             self,
             parent=parent,
             id=id,
             title="Point settings",
-            settings=settings)
+            settings=settings,
+            env=env)
 
         self.objectType = ('point',)
         if self.id is not None:
@@ -6254,7 +6279,7 @@ class PointDialog(PsmapDialog):
             self.pointDict = self.instruction[id].GetInstruction()
         else:
             self.id = NewId()
-            self.pointObj = Point(self.id)
+            self.pointObj = Point(self.id, env=self.env)
             self.pointDict = self.pointObj.GetInstruction()
             self.pointDict['where'] = coordinates
         self.defaultDict = self.pointObj.defaultInstruction
@@ -6267,7 +6292,8 @@ class PointDialog(PsmapDialog):
         self.pointDict['east'], self.pointDict['north'] = PaperMapCoordinates(
             mapInstr=mapObj, x=self.pointDict['where'][0],
             y=self.pointDict['where'][1],
-            paperToMap=True)
+            paperToMap=True,
+            env=self.env)
 
         notebook = Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
         self.pointPanelName = pointPanelName
@@ -6586,7 +6612,8 @@ class PointDialog(PsmapDialog):
                 mapInstr=self.instruction[
                     self.mapId], x=float(
                     self.pointDict['east']), y=float(
-                    self.pointDict['north']), paperToMap=False)
+                    self.pointDict['north']), paperToMap=False,
+                    env=self.env)
 
         # rotation
         self.pointDict['rotate'] = self.rotCtrl.GetValue()
@@ -6615,7 +6642,7 @@ class PointDialog(PsmapDialog):
             x=x - w / 2, y=y - h / 2, width=w, height=h)
 
         if self.id not in self.instruction:
-            point = Point(self.id)
+            point = Point(self.id, env=self.env)
             self.instruction.AddInstruction(point)
         self.instruction[self.id].SetInstruction(self.pointDict)
 
@@ -6644,7 +6671,7 @@ class PointDialog(PsmapDialog):
 
 class RectangleDialog(PsmapDialog):
 
-    def __init__(self, parent, id, settings,
+    def __init__(self, parent, id, settings, env,
                  type='rectangle', coordinates=None):
         """
 
@@ -6659,7 +6686,8 @@ class RectangleDialog(PsmapDialog):
             parent=parent,
             id=id,
             title=title,
-            settings=settings)
+            settings=settings,
+            env=env)
 
         self.objectType = (type,)
 
@@ -6669,9 +6697,9 @@ class RectangleDialog(PsmapDialog):
         else:
             self.id = NewId()
             if type == 'rectangle':
-                self.rectObj = Rectangle(self.id)
+                self.rectObj = Rectangle(self.id, env=self.env)
             else:
-                self.rectObj = Line(self.id)
+                self.rectObj = Line(self.id, env=self.env)
             self.rectDict = self.rectObj.GetInstruction()
 
             self.rectDict['rect'] = Rect2DPP(coordinates[0], coordinates[1])
@@ -6804,9 +6832,11 @@ class RectangleDialog(PsmapDialog):
         point1 = self.rectDict['where'][0]
         point2 = self.rectDict['where'][1]
         self.rectDict['east1'], self.rectDict['north1'] = PaperMapCoordinates(
-            mapInstr=mapInstr, x=point1[0], y=point1[1], paperToMap=True)
+            mapInstr=mapInstr, x=point1[0], y=point1[1], paperToMap=True,
+            env=self.env)
         self.rectDict['east2'], self.rectDict['north2'] = PaperMapCoordinates(
-            mapInstr=mapInstr, x=point2[0], y=point2[1], paperToMap=True)
+            mapInstr=mapInstr, x=point2[0], y=point2[1], paperToMap=True,
+            env=self.env)
         # width
         self.rectDict['width'] = self.widthCtrl.GetValue()
 
@@ -6827,9 +6857,9 @@ class RectangleDialog(PsmapDialog):
 
         if self.id not in self.instruction:
             if self.objectType == ('rectangle',):
-                rect = Rectangle(self.id)
+                rect = Rectangle(self.id, env=self.env)
             else:
-                rect = Line(self.id)
+                rect = Line(self.id, env=self.env)
             self.instruction.AddInstruction(rect)
 
         self.instruction[self.id].SetInstruction(self.rectDict)
@@ -6848,19 +6878,20 @@ class RectangleDialog(PsmapDialog):
 
 class LabelsDialog(PsmapDialog):
 
-    def __init__(self, parent, id, settings):
+    def __init__(self, parent, id, settings, env):
         PsmapDialog.__init__(
             self,
             parent=parent,
             id=id,
             title=_("Vector labels"),
-            settings=settings)
+            settings=settings,
+            env=env)
         self.objectType = ('labels',)
         if self.id is not None:
             self.labels = self.instruction[self.id]
         else:
             self.id = NewId()
-            self.labels = Labels(self.id)
+            self.labels = Labels(self.id, env=self.env)
         self.labelsDict = self.labels.GetInstruction()
         self.panel = self._labelPanel()
 
@@ -6912,7 +6943,7 @@ class LabelsDialog(PsmapDialog):
         else:
             self.labelsDict['labels'] = value.split(',')
         if self.id not in self.instruction:
-            labels = Labels(self.id)
+            labels = Labels(self.id, env=self.env)
             self.instruction.AddInstruction(labels)
 
         self.instruction[self.id].SetInstruction(self.labelsDict)

+ 67 - 46
gui/wxpython/psmap/frame.py

@@ -148,9 +148,12 @@ class PsMapFrame(wx.Frame):
         # list of objects to draw
         self.objectId = []
 
+        # we need isolated environment to handle region
+        self.env = os.environ.copy()
+
         # instructions
         self.instruction = Instruction(
-            parent=self, objectsToDraw=self.objectId)
+            parent=self, objectsToDraw=self.objectId, env=self.env)
         # open dialogs
         self.openDialogs = dict()
 
@@ -168,7 +171,8 @@ class PsMapFrame(wx.Frame):
             openDialogs=self.openDialogs,
             pageId=self.pageId,
             objectId=self.objectId,
-            preview=False)
+            preview=False,
+            env=self.env)
 
         self.canvas.SetCursor(self.cursors["default"])
         self.getInitMap()
@@ -184,10 +188,8 @@ class PsMapFrame(wx.Frame):
             cursors=self.cursors,
             pen=self.pen,
             brush=self.brush,
-            preview=True)
-
-        # set WIND_OVERRIDE
-        grass.use_temp_region()
+            preview=True,
+            env=self.env)
 
         self.toolbar.SelectDefault()
 
@@ -334,7 +336,7 @@ class PsMapFrame(wx.Frame):
         instrFileFd.close()
 
         temp = False
-        regOld = grass.region()
+        regOld = grass.region(env=self.env)
 
         if pdf:
             pdfname = filename
@@ -348,7 +350,8 @@ class PsMapFrame(wx.Frame):
                 if self.instruction.FindInstructionByType('map'):
                     mapId = self.instruction.FindInstructionByType('map').id
                     SetResolution(dpi=100, width=self.instruction[mapId]['rect'][
-                                  2], height=self.instruction[mapId]['rect'][3])
+                                  2], height=self.instruction[mapId]['rect'][3],
+                                  env=self.env)
 
         cmd = ['ps.map', '--overwrite']
         if os.path.splitext(filename)[1] == '.eps':
@@ -366,6 +369,7 @@ class PsMapFrame(wx.Frame):
 
         self.cmdThread.RunCmd(
             cmd,
+            env=self.env,
             userData={
                 'instrFile': instrFile,
                 'filename': filename,
@@ -430,8 +434,9 @@ class PsMapFrame(wx.Frame):
         # show preview only when user doesn't want to create ps or pdf
         if havePILImage and event.userData[
                 'temp'] and not event.userData['pdfname']:
-            RunCommand('g.region', cols=event.userData['regionOld'][
-                       'cols'], rows=event.userData['regionOld']['rows'])
+            self.env['GRASS_REGION'] = grass.region_env(cols=event.userData['regionOld']['cols'],
+                                                        rows=event.userData['regionOld']['rows'],
+                                                        env=self.env)
             # wx.BusyInfo does not display the message
             busy = wx.BusyInfo(
                 _("Generating preview, wait please"),
@@ -547,7 +552,7 @@ class PsMapFrame(wx.Frame):
     def LoadFile(self, filename):
         """Load file and read instructions"""
         readObjectId = []
-        readInstruction = Instruction(parent=self, objectsToDraw=readObjectId)
+        readInstruction = Instruction(parent=self, objectsToDraw=readObjectId, env=self.env)
         ok = readInstruction.Read(filename)
         if not ok:
             GMessage(_("Failed to read file %s.") % filename)
@@ -567,7 +572,7 @@ class PsMapFrame(wx.Frame):
     def OnPageSetup(self, event=None):
         """Specify paper size, margins and orientation"""
         id = self.instruction.FindInstructionByType('page').id
-        dlg = PageSetupDialog(self, id=id, settings=self.instruction)
+        dlg = PageSetupDialog(self, id=id, settings=self.instruction, env=self.env)
         dlg.CenterOnParent()
         val = dlg.ShowModal()
         if val == wx.ID_OK:
@@ -651,6 +656,7 @@ class PsMapFrame(wx.Frame):
                         parent=self,
                         id=id,
                         settings=self.instruction,
+                        env=self.env,
                         notebook=notebook)
                     self.openDialogs['mapNotebook'] = dlg
                 self.openDialogs['mapNotebook'].Show()
@@ -663,6 +669,7 @@ class PsMapFrame(wx.Frame):
                             parent=self,
                             id=id,
                             settings=self.instruction,
+                            env=self.env,
                             notebook=notebook)
                         self.openDialogs['map'] = dlg
                     self.openDialogs['map'].Show()
@@ -690,7 +697,7 @@ class PsMapFrame(wx.Frame):
             self.openDialogs['mapNotebook'].notebook.ChangeSelection(1)
         else:
             if 'raster' not in self.openDialogs:
-                dlg = RasterDialog(self, id=id, settings=self.instruction)
+                dlg = RasterDialog(self, id=id, settings=self.instruction, env=self.env)
                 self.openDialogs['raster'] = dlg
             self.openDialogs['raster'].Show()
 
@@ -710,7 +717,7 @@ class PsMapFrame(wx.Frame):
             self.openDialogs['mapNotebook'].notebook.ChangeSelection(2)
         else:
             if 'vector' not in self.openDialogs:
-                dlg = MainVectorDialog(self, id=id, settings=self.instruction)
+                dlg = MainVectorDialog(self, id=id, settings=self.instruction, env=self.env)
                 self.openDialogs['vector'] = dlg
             self.openDialogs['vector'].Show()
 
@@ -726,7 +733,7 @@ class PsMapFrame(wx.Frame):
             id = None
 
         if 'scalebar' not in self.openDialogs:
-            dlg = ScalebarDialog(self, id=id, settings=self.instruction)
+            dlg = ScalebarDialog(self, id=id, settings=self.instruction, env=self.env)
             self.openDialogs['scalebar'] = dlg
         self.openDialogs['scalebar'].Show()
 
@@ -744,7 +751,7 @@ class PsMapFrame(wx.Frame):
         if 'rasterLegend' not in self.openDialogs:
             dlg = LegendDialog(
                 self, id=[idR, idV],
-                settings=self.instruction, page=page)
+                settings=self.instruction, env=self.env, page=page)
             self.openDialogs['rasterLegend'] = dlg
             self.openDialogs['vectorLegend'] = dlg
         self.openDialogs['rasterLegend'].notebook.ChangeSelection(page)
@@ -757,7 +764,7 @@ class PsMapFrame(wx.Frame):
             id = None
 
         if 'mapinfo' not in self.openDialogs:
-            dlg = MapinfoDialog(self, id=id, settings=self.instruction)
+            dlg = MapinfoDialog(self, id=id, settings=self.instruction, env=self.env)
             self.openDialogs['mapinfo'] = dlg
         self.openDialogs['mapinfo'].Show()
 
@@ -768,7 +775,7 @@ class PsMapFrame(wx.Frame):
             position = self.openDialogs['image'].GetPosition()
             self.openDialogs['image'].OnApply(event=None)
             self.openDialogs['image'].Destroy()
-        dlg = ImageDialog(self, id=id, settings=self.instruction)
+        dlg = ImageDialog(self, id=id, settings=self.instruction, env=self.env)
         self.openDialogs['image'] = dlg
         if position:
             dlg.SetPosition(position)
@@ -782,7 +789,7 @@ class PsMapFrame(wx.Frame):
             id = None
 
         if 'northArrow' not in self.openDialogs:
-            dlg = NorthArrowDialog(self, id=id, settings=self.instruction)
+            dlg = NorthArrowDialog(self, id=id, settings=self.instruction, env=self.env)
             self.openDialogs['northArrow'] = dlg
         self.openDialogs['northArrow'].Show()
 
@@ -793,7 +800,7 @@ class PsMapFrame(wx.Frame):
             position = self.openDialogs['text'].GetPosition()
             self.openDialogs['text'].OnApply(event=None)
             self.openDialogs['text'].Destroy()
-        dlg = TextDialog(self, id=id, settings=self.instruction)
+        dlg = TextDialog(self, id=id, settings=self.instruction, env=self.env)
         self.openDialogs['text'] = dlg
         if position:
             dlg.SetPosition(position)
@@ -817,7 +824,7 @@ class PsMapFrame(wx.Frame):
             self.openDialogs['point'].OnApply(event=None)
             self.openDialogs['point'].Destroy()
         dlg = PointDialog(self, id=id, settings=self.instruction,
-                          coordinates=coordinates)
+                          coordinates=coordinates, env=self.env)
         self.openDialogs['point'] = dlg
         if position:
             dlg.SetPosition(position)
@@ -843,7 +850,8 @@ class PsMapFrame(wx.Frame):
             self.openDialogs['line'].OnApply(event=None)
             self.openDialogs['line'].Destroy()
         dlg = RectangleDialog(self, id=id, settings=self.instruction,
-                              type='line', coordinates=coordinates)
+                              type='line', coordinates=coordinates,
+                              env=self.env)
         self.openDialogs['line'] = dlg
         if position:
             dlg.SetPosition(position)
@@ -869,7 +877,8 @@ class PsMapFrame(wx.Frame):
             self.openDialogs['rectangle'].OnApply(event=None)
             self.openDialogs['rectangle'].Destroy()
         dlg = RectangleDialog(self, id=id, settings=self.instruction,
-                              type='rectangle', coordinates=coordinates)
+                              type='rectangle', coordinates=coordinates,
+                              env=self.env)
         self.openDialogs['rectangle'] = dlg
         if position:
             dlg.SetPosition(position)
@@ -888,7 +897,7 @@ class PsMapFrame(wx.Frame):
             return
 
         if 'labels' not in self.openDialogs:
-            dlg = LabelsDialog(self, id=id, settings=self.instruction)
+            dlg = LabelsDialog(self, id=id, settings=self.instruction, env=self.env)
             self.openDialogs['labels'] = dlg
         self.openDialogs['labels'].Show()
 
@@ -985,10 +994,11 @@ class PsMapFrame(wx.Frame):
         page = self.instruction.FindInstructionByType('page')
         mapInitRect = GetMapBounds(
             instrFile, portrait=(
-                page['Orientation'] == 'Portrait'))
+                page['Orientation'] == 'Portrait'),
+            env=self.env)
         grass.try_remove(instrFile)
 
-        region = grass.region()
+        region = grass.region(env=self.env)
         units = UnitConversion(self)
         realWidth = units.convert(
             value=abs(region['w'] - region['e']),
@@ -1003,7 +1013,7 @@ class PsMapFrame(wx.Frame):
 
         if not id:
             id = NewId()
-            initMap = InitMap(id)
+            initMap = InitMap(id, env=self.env)
             self.instruction.AddInstruction(initMap)
         self.instruction[id].SetInstruction(
             dict(rect=mapInitRect, scale=scale))
@@ -1142,11 +1152,13 @@ class PsMapFrame(wx.Frame):
             if itype in ('map', 'vector', 'raster', 'labels'):
 
                 if itype == 'raster':  # set resolution
-                    info = grass.raster_info(self.instruction[id]['raster'])
-                    RunCommand(
-                        'g.region',
-                        nsres=info['nsres'],
-                        ewres=info['ewres'])
+                    try:
+                        info = grass.raster_info(self.instruction[id]['raster'])
+                        self.env['GRASS_REGION'] = grass.region_env(nsres=info['nsres'],
+                                                                    ewres=info['ewres'],
+                                                                    env=self.env)
+                    except grass.CalledModuleError:  # fails after switching location
+                        pass
                     # change current raster in raster legend
 
                 if 'rasterLegend' in self.openDialogs:
@@ -1157,7 +1169,8 @@ class PsMapFrame(wx.Frame):
                 if itype == 'raster':
                     SetResolution(dpi=self.instruction[id]['resolution'],
                                   width=self.instruction[id]['rect'].width,
-                                  height=self.instruction[id]['rect'].height)
+                                  height=self.instruction[id]['rect'].height,
+                                  env=self.env)
                 rectCanvas = self.canvas.CanvasPaperCoordinates(
                     rect=self.instruction[id]['rect'], canvasToPaper=False)
                 self.canvas.RecalculateEN()
@@ -1283,7 +1296,8 @@ class PsMapBufferedWindow(wx.Window):
             self.pageId = kwargs['pageId']
         if 'objectId' in kwargs:
             self.objectId = kwargs['objectId']
-
+        if 'env' in kwargs:
+            self.env = kwargs['env']
         # labels
         self.itemLabelsDict = {'map': _("MAP FRAME"),
                                'rasterLegend': _("RASTER LEGEND"),
@@ -1395,7 +1409,7 @@ class PsMapBufferedWindow(wx.Window):
 
         page = self.instruction[self.pageId]
         if not page:
-            page = PageSetup(id=self.pageId)
+            page = PageSetup(id=self.pageId, env=self.env)
             self.instruction.AddInstruction(page)
 
         ppi = wx.ClientDC(self).GetPPI()
@@ -1439,23 +1453,27 @@ class PsMapBufferedWindow(wx.Window):
                             mapInstr=self.instruction[mapId],
                             x=instr['where'][0][0],
                             y=instr['where'][0][1],
-                            paperToMap=True)
+                            paperToMap=True,
+                            env=self.env)
                         e2, n2 = PaperMapCoordinates(
                             mapInstr=self.instruction[mapId],
                             x=instr['where'][1][0],
                             y=instr['where'][1][1],
-                            paperToMap=True)
+                            paperToMap=True,
+                            env=self.env)
                     else:
                         e1, n1 = PaperMapCoordinates(
                             mapInstr=self.instruction[mapId],
                             x=instr['rect'].GetLeft(),
                             y=instr['rect'].GetTop(),
-                            paperToMap=True)
+                            paperToMap=True,
+                            env=self.env)
                         e2, n2 = PaperMapCoordinates(
                             mapInstr=self.instruction[mapId],
                             x=instr['rect'].GetRight(),
                             y=instr['rect'].GetBottom(),
-                            paperToMap=True)
+                            paperToMap=True,
+                            env=self.env)
                     instr['east1'] = e1
                     instr['north1'] = n1
                     instr['east2'] = e2
@@ -1465,7 +1483,8 @@ class PsMapBufferedWindow(wx.Window):
                         mapInstr=self.instruction[mapId],
                         x=instr['where'][0],
                         y=instr['where'][1],
-                        paperToMap=True)
+                        paperToMap=True,
+                        env=self.env)
                     instr['east'], instr['north'] = e, n
 
     def OnPaint(self, event):
@@ -1658,7 +1677,7 @@ class PsMapBufferedWindow(wx.Window):
 
             dlg = MapDialog(
                 parent=self.parent, id=[None, None, None],
-                settings=self.instruction, rect=rectPaper)
+                settings=self.instruction, env=self.env, rect=rectPaper)
             self.openDialogs['map'] = dlg
             self.openDialogs['map'].Show()
 
@@ -1685,18 +1704,19 @@ class PsMapBufferedWindow(wx.Window):
 
                         scale, foo, rect = AutoAdjust(
                             self, scaleType=0, map=self.instruction[mapId]
-                            ['map'],
+                            ['map'], env=self.env,
                             mapType=self.instruction[mapId]['mapType'],
                             rect=self.instruction[mapId]['rect'])
 
                     elif self.instruction[mapId]['scaleType'] == 1:
                         scale, foo, rect = AutoAdjust(
-                            self, scaleType=1,
+                            self, scaleType=1, env=self.env,
                             region=self.instruction[mapId]['region'],
                             rect=self.instruction[mapId]['rect'])
                     else:
                         scale, foo, rect = AutoAdjust(
-                            self, scaleType=2, rect=self.instruction[mapId]['rect'])
+                            self, scaleType=2, rect=self.instruction[mapId]['rect'],
+                            env=self.env)
                     self.instruction[mapId]['rect'] = rect
                     self.instruction[mapId]['scale'] = scale
 
@@ -1712,11 +1732,12 @@ class PsMapBufferedWindow(wx.Window):
 
                 elif self.instruction[mapId]['scaleType'] == 3:
                     ComputeSetRegion(
-                        self, mapDict=self.instruction[mapId].GetInstruction())
+                        self, mapDict=self.instruction[mapId].GetInstruction(), env=self.env)
                 # check resolution
                 SetResolution(dpi=self.instruction[mapId]['resolution'],
                               width=self.instruction[mapId]['rect'].width,
-                              height=self.instruction[mapId]['rect'].height)
+                              height=self.instruction[mapId]['rect'].height,
+                              env=self.env)
 
                 self.RedrawSelectBox(mapId)
                 self.Zoom(zoomFactor=1, view=(0, 0))

+ 74 - 60
gui/wxpython/psmap/instructions.py

@@ -57,12 +57,13 @@ def NewId():
 class Instruction:
     """Class which represents instruction file"""
 
-    def __init__(self, parent, objectsToDraw):
+    def __init__(self, parent, objectsToDraw, env):
 
         self.parent = parent
         self.objectsToDraw = objectsToDraw
         # here are kept objects like mapinfo, rasterlegend, etc.
         self.instruction = list()
+        self.env = env
 
     def __str__(self):
         """Returns text for instruction file"""
@@ -164,12 +165,13 @@ class Instruction:
         # then run ps.map -b to get information for maploc
         # compute scale and center
         map = self.FindInstructionByType('map')
-        region = grass.region()
+        region = grass.region(env=self.env)
         map['center'] = (region['n'] + region['s']
                          ) / 2, (region['w'] + region['e']) / 2
         mapRect = GetMapBounds(
             self.filename, portrait=(
-                orientation == 'Portrait'))
+                orientation == 'Portrait'),
+            env=self.env)
         map['rect'] = mapRect
         proj = projInfo()
         toM = 1.0
@@ -185,7 +187,8 @@ class Instruction:
         SetResolution(
             dpi=300,
             width=map['rect'].width,
-            height=map['rect'].height)
+            height=map['rect'].height,
+            env=self.env)
 
         # read file again, now with information about map bounds
         isBuffer = False
@@ -392,7 +395,7 @@ class Instruction:
 
         page = self.FindInstructionByType('page')
         if not page:
-            page = PageSetup(NewId())
+            page = PageSetup(NewId(), env=self.env)
             self.AddInstruction(page)
         else:
             page['Orientation'] = orientation
@@ -449,7 +452,9 @@ class Instruction:
                 id = NewId()  # !vProperties expect subtype
                 if i == 'vProperties':
                     id = kwargs['id']
-                    newInstr = myInstrDict[i](id, subType=instruction[1:])
+                    newInstr = myInstrDict[i](
+                        id, subType=instruction[1:], env=self.env,
+                    )
                 elif i in ('image', 'northArrow'):
                     commentFound = False
                     for line in text:
@@ -458,9 +463,9 @@ class Instruction:
                     if i == 'image' and commentFound or \
                        i == 'northArrow' and not commentFound:
                         continue
-                    newInstr = myInstrDict[i](id, settings=self)
+                    newInstr = myInstrDict[i](id, settings=self, env=self.env)
                 else:
-                    newInstr = myInstrDict[i](id)
+                    newInstr = myInstrDict[i](id, env=self.env)
                 ok = newInstr.Read(instruction, text, **kwargs)
                 if ok:
                     self.AddInstruction(newInstr)
@@ -476,7 +481,7 @@ class Instruction:
 
     def SetRegion(self, regionInstruction):
         """Sets region from file comment or sets current region in case of no comment"""
-        map = MapFrame(NewId())
+        map = MapFrame(NewId(), env=self.env)
         self.AddInstruction(map)
         if regionInstruction:
             cmd = cmdlist_to_tuple(regionInstruction.strip('# ').split())
@@ -499,16 +504,14 @@ class Instruction:
                 map['scaleType'] = 2
         else:
             map['scaleType'] = 2
-            grass.del_temp_region()
-            region = grass.region()
-            grass.use_temp_region()
+            region = grass.region(env=None)
             cmd = ['g.region', region]
         cmdString = GetCmdString(cmd).replace('g.region', '')
         GMessage(
             _("Instruction file will be loaded with following region: %s\n") %
             cmdString)
         try:
-            RunCommand(cmd[0], **cmd[1])
+            self.env['GRASS_REGION'] = grass.region_env(env=self.env, **cmd[1])
 
         except grass.ScriptError as e:
             GError(_("Region cannot be set\n%s") % e)
@@ -518,8 +521,9 @@ class Instruction:
 class InstructionObject:
     """Abtract class representing single instruction"""
 
-    def __init__(self, id):
+    def __init__(self, id, env):
         self.id = id
+        self.env = env
 
         # default values
         self.defaultInstruction = dict()
@@ -556,7 +560,7 @@ class InstructionObject:
     def PercentToReal(self, e, n):
         """Converts text coordinates from percent of region to map coordinates"""
         e, n = float(e.strip('%')), float(n.strip('%'))
-        region = grass.region()
+        region = grass.region(env=self.env)
         N = region['s'] + (region['n'] - region['s']) / 100 * n
         E = region['w'] + (region['e'] - region['w']) / 100 * e
         return E, N
@@ -565,8 +569,8 @@ class InstructionObject:
 class InitMap(InstructionObject):
     """Class representing virtual map"""
 
-    def __init__(self, id):
-        InstructionObject.__init__(self, id=id)
+    def __init__(self, id, env):
+        InstructionObject.__init__(self, id=id, env=env)
         self.type = 'initMap'
 
         # default values
@@ -578,8 +582,8 @@ class InitMap(InstructionObject):
 class MapFrame(InstructionObject):
     """Class representing map (instructions maploc, scale, border)"""
 
-    def __init__(self, id):
-        InstructionObject.__init__(self, id=id)
+    def __init__(self, id, env):
+        InstructionObject.__init__(self, id=id, env=env)
         self.type = 'map'
         # default values
         self.defaultInstruction = dict(
@@ -603,7 +607,7 @@ class MapFrame(InstructionObject):
         comment = ''
 
         # region settings
-        region = grass.region()
+        region = grass.region(env=self.env)
         if self.instruction['scaleType'] == 0:  # match map
             map = self.instruction['map']
             if self.instruction['mapType'] == 'raster':
@@ -724,8 +728,8 @@ class MapFrame(InstructionObject):
 class PageSetup(InstructionObject):
     """Class representing page instruction"""
 
-    def __init__(self, id):
-        InstructionObject.__init__(self, id=id)
+    def __init__(self, id, env):
+        InstructionObject.__init__(self, id=id, env=env)
         self.type = 'page'
         # default values
         self.defaultInstruction = dict(
@@ -818,8 +822,8 @@ class PageSetup(InstructionObject):
 class Mapinfo(InstructionObject):
     """Class representing mapinfo instruction"""
 
-    def __init__(self, id):
-        InstructionObject.__init__(self, id=id)
+    def __init__(self, id, env):
+        InstructionObject.__init__(self, id=id, env=env)
         self.type = 'mapinfo'
         # default values
         self.defaultInstruction = dict(
@@ -891,8 +895,8 @@ class Mapinfo(InstructionObject):
 class Text(InstructionObject):
     """Class representing text instruction"""
 
-    def __init__(self, id):
-        InstructionObject.__init__(self, id=id)
+    def __init__(self, id, env):
+        InstructionObject.__init__(self, id=id, env=env)
         self.type = 'text'
         # default values
         self.defaultInstruction = dict(
@@ -990,7 +994,8 @@ class Text(InstructionObject):
         instr['where'] = PaperMapCoordinates(
             mapInstr=map, x=instr['east'],
             y=instr['north'],
-            paperToMap=False)
+            paperToMap=False,
+            env=self.env)
         self.instruction.update(instr)
 
         return True
@@ -999,8 +1004,8 @@ class Text(InstructionObject):
 class Image(InstructionObject):
     """Class representing eps instruction - image"""
 
-    def __init__(self, id, settings):
-        InstructionObject.__init__(self, id=id)
+    def __init__(self, id, settings, env):
+        InstructionObject.__init__(self, id=id, env=env)
         self.settings = settings
         self.type = 'image'
         # default values
@@ -1082,7 +1087,8 @@ class Image(InstructionObject):
             mapInstr=mapInstr,
             x=self.instruction['east'],
             y=self.instruction['north'],
-            paperToMap=False)
+            paperToMap=False,
+            env=self.env)
         w = self.unitConv.convert(
             value=instr['size'][0],
             fromUnit='point', toUnit='inch')
@@ -1110,7 +1116,8 @@ class Image(InstructionObject):
                 mapInstr=self.settings[mapId],
                 x=center[0],
                 y=center[1],
-                paperToMap=True)
+                paperToMap=True,
+                env=self.env)
 
             self.instruction['east'], self.instruction['north'] = ENCenter
         else:
@@ -1118,7 +1125,8 @@ class Image(InstructionObject):
                 mapInstr=self.settings[mapId],
                 x=self.instruction['east'],
                 y=self.instruction['north'],
-                paperToMap=False)
+                paperToMap=False,
+                env=self.env)
             w = self.unitConv.convert(
                 value=self.instruction['size'][0],
                 fromUnit='point', toUnit='inch')
@@ -1129,7 +1137,8 @@ class Image(InstructionObject):
             y -= h * self.instruction['scale'] / 2
             e, n = PaperMapCoordinates(
                 mapInstr=self.settings[mapId],
-                x=x, y=y, paperToMap=True)
+                x=x, y=y, paperToMap=True,
+                env=self.env)
             self.instruction['east'], self.instruction['north'] = e, n
 
     def GetImageOrigSize(self, imagePath):
@@ -1158,8 +1167,8 @@ class Image(InstructionObject):
 class NorthArrow(Image):
     """Class representing eps instruction -- North Arrow"""
 
-    def __init__(self, id, settings):
-        Image.__init__(self, id=id, settings=settings)
+    def __init__(self, id, settings, env):
+        Image.__init__(self, id=id, settings=settings, env=env)
         self.type = 'northArrow'
 
     def __str__(self):
@@ -1185,8 +1194,8 @@ class NorthArrow(Image):
 class Point(InstructionObject):
     """Class representing point instruction"""
 
-    def __init__(self, id):
-        InstructionObject.__init__(self, id=id)
+    def __init__(self, id, env):
+        InstructionObject.__init__(self, id=id, env=env)
         self.type = 'point'
         # default values
         self.defaultInstruction = dict(symbol=os.path.join('basic', 'x'),
@@ -1245,7 +1254,8 @@ class Point(InstructionObject):
             mapInstr=mapInstr,
             x=self.instruction['east'],
             y=self.instruction['north'],
-            paperToMap=False)
+            paperToMap=False,
+            env=self.env)
         w = h = self.unitConv.convert(
             value=instr['size'],
             fromUnit='point', toUnit='inch')
@@ -1261,8 +1271,8 @@ class Point(InstructionObject):
 class Line(InstructionObject):
     """Class representing line instruction"""
 
-    def __init__(self, id):
-        InstructionObject.__init__(self, id=id)
+    def __init__(self, id, env):
+        InstructionObject.__init__(self, id=id, env=env)
         self.type = 'line'
         # default values
         self.defaultInstruction = dict(color='0:0:0', width=2,
@@ -1311,11 +1321,13 @@ class Line(InstructionObject):
         e1, n1 = PaperMapCoordinates(
             mapInstr=mapInstr, x=self.instruction['east1'],
             y=self.instruction['north1'],
-            paperToMap=False)
+            paperToMap=False,
+            env=self.env)
         e2, n2 = PaperMapCoordinates(
             mapInstr=mapInstr, x=self.instruction['east2'],
             y=self.instruction['north2'],
-            paperToMap=False)
+            paperToMap=False,
+            env=self.env)
         instr['where'] = [wx.Point2D(e1, n1), wx.Point2D(e2, n2)]
         instr['rect'] = Rect2DPP(instr['where'][0], instr['where'][1])
         self.instruction.update(instr)
@@ -1326,8 +1338,8 @@ class Line(InstructionObject):
 class Rectangle(InstructionObject):
     """Class representing rectangle instruction"""
 
-    def __init__(self, id):
-        InstructionObject.__init__(self, id=id)
+    def __init__(self, id, env):
+        InstructionObject.__init__(self, id=id, env=env)
         self.type = 'rectangle'
         # default values
         self.defaultInstruction = dict(color='0:0:0', fcolor='none', width=2,
@@ -1378,11 +1390,13 @@ class Rectangle(InstructionObject):
         e1, n1 = PaperMapCoordinates(
             mapInstr=mapInstr, x=self.instruction['east1'],
             y=self.instruction['north1'],
-            paperToMap=False)
+            paperToMap=False,
+            env=self.env)
         e2, n2 = PaperMapCoordinates(
             mapInstr=mapInstr, x=self.instruction['east2'],
             y=self.instruction['north2'],
-            paperToMap=False)
+            paperToMap=False,
+            env=self.env)
         instr['rect'] = Rect2DPP(wx.Point2D(e1, n1), wx.Point2D(e2, n2))
         self.instruction.update(instr)
 
@@ -1392,8 +1406,8 @@ class Rectangle(InstructionObject):
 class Scalebar(InstructionObject):
     """Class representing scalebar instruction"""
 
-    def __init__(self, id):
-        InstructionObject.__init__(self, id=id)
+    def __init__(self, id, env):
+        InstructionObject.__init__(self, id=id, env=env)
         self.type = 'scalebar'
         # default values
         self.defaultInstruction = dict(unit='inch', where=(1, 1),
@@ -1490,8 +1504,8 @@ class Scalebar(InstructionObject):
 class RasterLegend(InstructionObject):
     """Class representing colortable instruction"""
 
-    def __init__(self, id):
-        InstructionObject.__init__(self, id=id)
+    def __init__(self, id, env):
+        InstructionObject.__init__(self, id=id, env=env)
         self.type = 'rasterLegend'
         # default values
         self.defaultInstruction = dict(rLegend=False, unit='inch', rasterDefault=True, raster=None,
@@ -1665,8 +1679,8 @@ class RasterLegend(InstructionObject):
 class VectorLegend(InstructionObject):
     """Class representing colortable instruction"""
 
-    def __init__(self, id):
-        InstructionObject.__init__(self, id=id)
+    def __init__(self, id, env):
+        InstructionObject.__init__(self, id=id, env=env)
         self.type = 'vectorLegend'
         # default values
         self.defaultInstruction = dict(
@@ -1757,8 +1771,8 @@ class VectorLegend(InstructionObject):
 class Raster(InstructionObject):
     """Class representing raster instruction"""
 
-    def __init__(self, id):
-        InstructionObject.__init__(self, id=id)
+    def __init__(self, id, env):
+        InstructionObject.__init__(self, id=id, env=env)
         self.type = 'raster'
         # default values
         self.defaultInstruction = dict(isRaster=False, raster=None)
@@ -1792,8 +1806,8 @@ class Raster(InstructionObject):
 class Vector(InstructionObject):
     """Class keeps vector layers"""
 
-    def __init__(self, id):
-        InstructionObject.__init__(self, id=id)
+    def __init__(self, id, env):
+        InstructionObject.__init__(self, id=id, env=env)
         self.type = 'vector'
         # default values
         self.defaultInstruction = dict(
@@ -1844,8 +1858,8 @@ class Vector(InstructionObject):
 class VProperties(InstructionObject):
     """Class represents instructions vareas, vlines, vpoints"""
 
-    def __init__(self, id, subType):
-        InstructionObject.__init__(self, id=id)
+    def __init__(self, id, subType, env):
+        InstructionObject.__init__(self, id=id, env=env)
         self.type = 'vProperties'
         self.subType = subType
         # default values
@@ -2107,8 +2121,8 @@ class VProperties(InstructionObject):
 class Labels(InstructionObject):
     """Class representing labels instruction"""
 
-    def __init__(self, id):
-        InstructionObject.__init__(self, id=id)
+    def __init__(self, id, env):
+        InstructionObject.__init__(self, id=id, env=env)
         self.type = 'labels'
         # default values
         self.defaultInstruction = dict(labels=[])

+ 42 - 35
gui/wxpython/psmap/utils.py

@@ -184,14 +184,14 @@ def convertRGB(rgb):
             return None
 
 
-def PaperMapCoordinates(mapInstr, x, y, paperToMap=True):
+def PaperMapCoordinates(mapInstr, x, y, paperToMap=True, env=None):
     """Converts paper (inch) coordinates <-> map coordinates.
 
     :param mapInstr: map frame instruction
     :param x,y: paper coords in inches or mapcoords in map units
     :param paperToMap: specify conversion direction
     """
-    region = grass.region()
+    region = grass.region(env=env)
     mapWidthPaper = mapInstr['rect'].GetWidth()
     mapHeightPaper = mapInstr['rect'].GetHeight()
     mapWidthEN = region['e'] - region['w']
@@ -221,29 +221,33 @@ def PaperMapCoordinates(mapInstr, x, y, paperToMap=True):
         return xPaper, yPaper
 
 
-def AutoAdjust(self, scaleType, rect, map=None, mapType=None, region=None):
+def AutoAdjust(self, scaleType, rect, env, map=None, mapType=None, region=None):
     """Computes map scale, center and map frame rectangle to fit region
     (scale is not fixed)
     """
     currRegionDict = {}
-    if scaleType == 0 and map:  # automatic, region from raster or vector
-        res = ''
-        if mapType == 'raster':
-            try:
-                res = grass.read_command("g.region", flags='gu', raster=map)
-            except grass.ScriptError:
-                pass
-        elif mapType == 'vector':
-            res = grass.read_command("g.region", flags='gu', vector=map)
-        currRegionDict = grass.parse_key_val(res, val_type=float)
-    elif scaleType == 1 and region:  # saved region
-        res = grass.read_command("g.region", flags='gu', region=region)
-        currRegionDict = grass.parse_key_val(res, val_type=float)
-    elif scaleType == 2:  # current region
-        currRegionDict = grass.region()
+    try:
+        if scaleType == 0 and map:  # automatic, region from raster or vector
+            res = ''
+            if mapType == 'raster':
+                try:
+                    res = grass.read_command("g.region", flags='gu', raster=map, env=env)
+                except grass.ScriptError:
+                    pass
+            elif mapType == 'vector':
+                res = grass.read_command("g.region", flags='gu', vector=map, env=env)
+            currRegionDict = grass.parse_key_val(res, val_type=float)
+        elif scaleType == 1 and region:  # saved region
+            res = grass.read_command("g.region", flags='gu', region=region, env=env)
+            currRegionDict = grass.parse_key_val(res, val_type=float)
+        elif scaleType == 2:  # current region
+            currRegionDict = grass.region(env=None)
 
-    else:
-        return None, None, None
+        else:
+            return None, None, None
+    # fails after switching location
+    except (grass.ScriptError, grass.CalledModuleError):
+        pass
 
     if not currRegionDict:
         return None, None, None
@@ -290,21 +294,21 @@ def AutoAdjust(self, scaleType, rect, map=None, mapType=None, region=None):
     return scale, (cE, cN), Rect2D(x, y, rWNew, rHNew)  # inch
 
 
-def SetResolution(dpi, width, height):
+def SetResolution(dpi, width, height, env):
     """If resolution is too high, lower it
 
     :param dpi: max DPI
     :param width: map frame width
     :param height: map frame height
     """
-    region = grass.region()
+    region = grass.region(env=env)
     if region['cols'] > width * dpi or region['rows'] > height * dpi:
         rows = height * dpi
         cols = width * dpi
-        RunCommand('g.region', rows=rows, cols=cols)
+        env['GRASS_REGION'] = grass.region_env(rows=rows, cols=cols, env=env)
 
 
-def ComputeSetRegion(self, mapDict):
+def ComputeSetRegion(self, mapDict, env):
     """Computes and sets region from current scale, map center
     coordinates and map rectangle
     """
@@ -339,16 +343,18 @@ def ComputeSetRegion(self, mapDict):
             rasterId = None
 
         if rasterId:
-            RunCommand('g.region', n=ceil(centerN + rectHalfMeter[1]),
-                       s=floor(centerN - rectHalfMeter[1]),
-                       e=ceil(centerE + rectHalfMeter[0]),
-                       w=floor(centerE - rectHalfMeter[0]),
-                       rast=self.instruction[rasterId]['raster'])
+            env['GRASS_REGION'] = grass.region_env(n=ceil(centerN + rectHalfMeter[1]),
+                                                   s=floor(centerN - rectHalfMeter[1]),
+                                                   e=ceil(centerE + rectHalfMeter[0]),
+                                                   w=floor(centerE - rectHalfMeter[0]),
+                                                   rast=self.instruction[rasterId]['raster'],
+                                                   env=env)
         else:
-            RunCommand('g.region', n=ceil(centerN + rectHalfMeter[1]),
-                       s=floor(centerN - rectHalfMeter[1]),
-                       e=ceil(centerE + rectHalfMeter[0]),
-                       w=floor(centerE - rectHalfMeter[0]))
+            env['GRASS_REGION'] = grass.region_env(n=ceil(centerN + rectHalfMeter[1]),
+                                                   s=floor(centerN - rectHalfMeter[1]),
+                                                   e=ceil(centerE + rectHalfMeter[0]),
+                                                   w=floor(centerE - rectHalfMeter[0]),
+                                                   env=env)
 
 
 def projInfo():
@@ -375,10 +381,11 @@ def projInfo():
     return projinfo
 
 
-def GetMapBounds(filename, portrait=True):
+def GetMapBounds(filename, env, portrait=True):
     """Run ps.map -b to get information about map bounding box
 
     :param filename: psmap input file
+    :param env: enironment with GRASS_REGION defined
     :param portrait: page orientation"""
     orient = ''
     if not portrait:
@@ -390,7 +397,7 @@ def GetMapBounds(filename, portrait=True):
                     flags='b' +
                     orient,
                     quiet=True,
-                    input=filename).strip().split('=')[1].split(',')))
+                    input=filename, env=env).strip().split('=')[1].split(',')))
     except (grass.ScriptError, IndexError):
         GError(message=_("Unable to run `ps.map -b`"))
         return None