Jelajahi Sumber

wxGUI: apply pep8
(autopep8 --in-place --aggressive --recursive --experimental --jobs 4)


git-svn-id: https://svn.osgeo.org/grass/grass/trunk@68374 15284696-431f-4ddb-bdfa-cd5b030d7da7

Martin Landa 9 tahun lalu
induk
melakukan
87e5b1d9b8
100 mengubah file dengan 20923 tambahan dan 15259 penghapusan
  1. 17 15
      gui/scripts/d.wms.py
  2. 12 5
      gui/wxpython/animation/anim.py
  3. 108 45
      gui/wxpython/animation/controller.py
  4. 29 12
      gui/wxpython/animation/data.py
  5. 697 260
      gui/wxpython/animation/dialogs.py
  6. 58 26
      gui/wxpython/animation/frame.py
  7. 3 2
      gui/wxpython/animation/g.gui.animation.py
  8. 18 9
      gui/wxpython/animation/mapwindow.py
  9. 69 35
      gui/wxpython/animation/nviztask.py
  10. 174 82
      gui/wxpython/animation/provider.py
  11. 142 44
      gui/wxpython/animation/temporal_manager.py
  12. 69 48
      gui/wxpython/animation/toolbars.py
  13. 17 5
      gui/wxpython/animation/utils.py
  14. 1 1
      gui/wxpython/core/__init__.py
  15. 17 12
      gui/wxpython/core/debug.py
  16. 189 159
      gui/wxpython/core/gcmd.py
  17. 65 41
      gui/wxpython/core/gconsole.py
  18. 20 8
      gui/wxpython/core/giface.py
  19. 27 18
      gui/wxpython/core/globalvar.py
  20. 5 4
      gui/wxpython/core/gthread.py
  21. 20 7
      gui/wxpython/core/layerlist.py
  22. 37 24
      gui/wxpython/core/menutree.py
  23. 276 230
      gui/wxpython/core/render.py
  24. 753 701
      gui/wxpython/core/settings.py
  25. 53 27
      gui/wxpython/core/toolboxes.py
  26. 22 19
      gui/wxpython/core/treemodel.py
  27. 92 90
      gui/wxpython/core/units.py
  28. 337 268
      gui/wxpython/core/utils.py
  29. 519 333
      gui/wxpython/core/workspace.py
  30. 87 58
      gui/wxpython/core/ws.py
  31. 13 11
      gui/wxpython/datacatalog/catalog.py
  32. 7 1
      gui/wxpython/datacatalog/frame.py
  33. 3 2
      gui/wxpython/datacatalog/g.gui.datacatalog.py
  34. 14 5
      gui/wxpython/datacatalog/toolbars.py
  35. 196 85
      gui/wxpython/datacatalog/tree.py
  36. 1 1
      gui/wxpython/dbmgr/__init__.py
  37. 1703 1359
      gui/wxpython/dbmgr/base.py
  38. 313 272
      gui/wxpython/dbmgr/dialogs.py
  39. 8 6
      gui/wxpython/dbmgr/g.gui.dbmgr.py
  40. 87 69
      gui/wxpython/dbmgr/manager.py
  41. 396 306
      gui/wxpython/dbmgr/sqlbuilder.py
  42. 70 53
      gui/wxpython/dbmgr/vinfo.py
  43. 29 18
      gui/wxpython/docs/wxgui_sphinx/conf.py
  44. 1 1
      gui/wxpython/gcp/__init__.py
  45. 2 2
      gui/wxpython/gcp/g.gui.gcp.py
  46. 1016 669
      gui/wxpython/gcp/manager.py
  47. 102 85
      gui/wxpython/gcp/mapdisplay.py
  48. 2 0
      gui/wxpython/gcp/statusbar.py
  49. 47 37
      gui/wxpython/gcp/toolbars.py
  50. 449 364
      gui/wxpython/gis_set.py
  51. 9 8
      gui/wxpython/gis_set_error.py
  52. 1 1
      gui/wxpython/gmodeler/__init__.py
  53. 440 358
      gui/wxpython/gmodeler/dialogs.py
  54. 845 648
      gui/wxpython/gmodeler/frame.py
  55. 3 2
      gui/wxpython/gmodeler/g.gui.gmodeler.py
  56. 5 3
      gui/wxpython/gmodeler/giface.py
  57. 7 5
      gui/wxpython/gmodeler/menudata.py
  58. 903 690
      gui/wxpython/gmodeler/model.py
  59. 528 386
      gui/wxpython/gmodeler/preferences.py
  60. 40 38
      gui/wxpython/gmodeler/toolbars.py
  61. 1 1
      gui/wxpython/gui_core/__init__.py
  62. 981 760
      gui/wxpython/gui_core/dialogs.py
  63. 1289 968
      gui/wxpython/gui_core/forms.py
  64. 394 317
      gui/wxpython/gui_core/ghelp.py
  65. 286 209
      gui/wxpython/gui_core/goutput.py
  66. 597 406
      gui/wxpython/gui_core/gselect.py
  67. 181 154
      gui/wxpython/gui_core/mapdisp.py
  68. 78 67
      gui/wxpython/gui_core/menu.py
  69. 1425 913
      gui/wxpython/gui_core/preferences.py
  70. 139 114
      gui/wxpython/gui_core/prompt.py
  71. 10 7
      gui/wxpython/gui_core/pyedit.py
  72. 181 86
      gui/wxpython/gui_core/pystc.py
  73. 90 43
      gui/wxpython/gui_core/query.py
  74. 56 36
      gui/wxpython/gui_core/simplelmgr.py
  75. 107 101
      gui/wxpython/gui_core/toolbars.py
  76. 31 18
      gui/wxpython/gui_core/treeview.py
  77. 67 45
      gui/wxpython/gui_core/vselect.py
  78. 202 107
      gui/wxpython/gui_core/widgets.py
  79. 1 1
      gui/wxpython/iclass/__init__.py
  80. 348 276
      gui/wxpython/iclass/dialogs.py
  81. 64 47
      gui/wxpython/iclass/digit.py
  82. 583 454
      gui/wxpython/iclass/frame.py
  83. 4 2
      gui/wxpython/iclass/g.gui.iclass.py
  84. 126 94
      gui/wxpython/iclass/plots.py
  85. 42 36
      gui/wxpython/iclass/statistics.py
  86. 131 104
      gui/wxpython/iclass/toolbars.py
  87. 1 1
      gui/wxpython/icons/__init__.py
  88. 38 27
      gui/wxpython/icons/icon.py
  89. 1 1
      gui/wxpython/iscatt/__init__.py
  90. 271 233
      gui/wxpython/iscatt/controllers.py
  91. 96 57
      gui/wxpython/iscatt/core_c.py
  92. 216 155
      gui/wxpython/iscatt/dialogs.py
  93. 176 129
      gui/wxpython/iscatt/frame.py
  94. 181 139
      gui/wxpython/iscatt/iscatt_core.py
  95. 307 228
      gui/wxpython/iscatt/plots.py
  96. 144 131
      gui/wxpython/iscatt/toolbars.py
  97. 1 1
      gui/wxpython/lmgr/__init__.py
  98. 892 712
      gui/wxpython/lmgr/frame.py
  99. 12 6
      gui/wxpython/lmgr/giface.py
  100. 0 0
      gui/wxpython/lmgr/layertree.py

+ 17 - 15
gui/scripts/d.wms.py

@@ -20,7 +20,7 @@
 #% keyword: raster
 #% keyword: import
 #% keyword: WMS
-#% keyword: WMTS 
+#% keyword: WMTS
 #% keyword: OnEarth
 #%end
 
@@ -66,8 +66,8 @@
 #%option
 #% key: srs
 #% type: integer
-#% description: EPSG code of requested source projection 
-#% answer:4326 
+#% description: EPSG code of requested source projection
+#% answer:4326
 #% guisection: Request
 #%end
 
@@ -161,19 +161,20 @@ import sys
 from grass.script import core as grass
 
 sys.path.append(os.path.join(os.getenv("GISBASE"), "etc", "r.in.wms"))
-                
+
+
 def GetRegion():
     """!Parse region from GRASS_REGION env var.
     """
     region = os.environ["GRASS_REGION"]
-    conv_reg_vals = {'east' : 'e',
-                     'north' : 'n',
-                     'west' : 'w',
-                     'south' : 's',
-                     'rows' : 'rows',
-                     'cols' : 'cols',
-                     'e-w resol' : 'ewres',
-                     'n-s resol' : 'nsres'}
+    conv_reg_vals = {'east': 'e',
+                     'north': 'n',
+                     'west': 'w',
+                     'south': 's',
+                     'rows': 'rows',
+                     'cols': 'cols',
+                     'e-w resol': 'ewres',
+                     'n-s resol': 'nsres'}
 
     keys_to_convert = conv_reg_vals.keys()
 
@@ -183,12 +184,13 @@ def GetRegion():
     for r in region:
         r = r.split(':')
         r[0] = r[0].strip()
-        
+
         if r[0] in keys_to_convert:
             conv_region[conv_reg_vals[r[0]]] = float(r[1])
 
     return conv_region
 
+
 def main():
     options['region'] = GetRegion()
 
@@ -200,8 +202,8 @@ def main():
         grass.debug("Using GDAL WMS driver")
         from wms_gdal_drv import WMSGdalDrv
         wms = WMSGdalDrv()
-    
-    temp_map = wms.GetMap(options, flags) 
+
+    temp_map = wms.GetMap(options, flags)
     os.rename(temp_map, os.environ["GRASS_RENDER_FILE"])
 
     return 0

+ 12 - 5
gui/wxpython/animation/anim.py

@@ -21,6 +21,7 @@ from core.utils import _
 
 class Animation(wx.EvtHandler):
     """Animation class specifies which frame to show at which instance."""
+
     def __init__(self):
         wx.EvtHandler.__init__(self)
 
@@ -103,7 +104,9 @@ class Animation(wx.EvtHandler):
         if not self.IsActive():
             return
         self.currentIndex = 0
-        self.callbackEndAnimation(self.currentIndex, self.GetFrame(self.currentIndex))
+        self.callbackEndAnimation(
+            self.currentIndex, self.GetFrame(
+                self.currentIndex))
 
     def _arrivedToEnd(self):
         """Decides which action to do after animation end (stop, repeat)."""
@@ -132,7 +135,9 @@ class Animation(wx.EvtHandler):
         if not self.IsActive():
             return
 
-        self.callbackUpdateFrame(self.currentIndex, self.GetFrame(self.currentIndex))
+        self.callbackUpdateFrame(
+            self.currentIndex, self.GetFrame(
+                self.currentIndex))
         if self.orientation == Orientation.FORWARD:
             self.currentIndex += 1
             if self.currentIndex == self.count:
@@ -147,7 +152,9 @@ class Animation(wx.EvtHandler):
         if not self.IsActive():
             return
         self.currentIndex = index
-        self.callbackUpdateFrame(self.currentIndex, self.GetFrame(self.currentIndex))
+        self.callbackUpdateFrame(
+            self.currentIndex, self.GetFrame(
+                self.currentIndex))
 
     def PreviousFrameIndex(self):
         if not self.IsActive():
@@ -173,7 +180,7 @@ class Animation(wx.EvtHandler):
             if self.currentIndex == -1:
                 self.currentIndex = 0
 
-#def test():
+# def test():
 #    import wx
 #    app = wx.PySimpleApp()
 #    a = Animation()
@@ -187,5 +194,5 @@ class Animation(wx.EvtHandler):
 #    app.MainLoop()
 #
 #
-#if __name__ == '__main__':
+# if __name__ == '__main__':
 #    test()

+ 108 - 45
gui/wxpython/animation/controller.py

@@ -29,7 +29,9 @@ from animation.data import AnimationData
 
 
 class AnimationController(wx.EvtHandler):
-    def __init__(self, frame, sliders, animations, mapwindows, provider, bitmapPool, mapFilesPool):
+
+    def __init__(self, frame, sliders, animations, mapwindows,
+                 provider, bitmapPool, mapFilesPool):
         wx.EvtHandler.__init__(self)
 
         self.mapwindows = mapwindows
@@ -50,10 +52,13 @@ class AnimationController(wx.EvtHandler):
         self.bitmapProvider = provider
         for anim, win in zip(self.animations, self.mapwindows):
             anim.SetCallbackUpdateFrame(
-                lambda index, dataId, win=win: self.UpdateFrame(index, win, dataId))
+                lambda index, dataId, win=win: self.UpdateFrame(
+                    index, win, dataId))
             anim.SetCallbackEndAnimation(
-                lambda index, dataId, win=win: self.UpdateFrameEnd(index, win, dataId))
-            anim.SetCallbackOrientationChanged(self.OrientationChangedInReverseMode)
+                lambda index, dataId, win=win: self.UpdateFrameEnd(
+                    index, win, dataId))
+            anim.SetCallbackOrientationChanged(
+                self.OrientationChangedInReverseMode)
 
         for slider in self.sliders.values():
             slider.SetCallbackSliderChanging(self.SliderChanging)
@@ -199,8 +204,12 @@ class AnimationController(wx.EvtHandler):
         # if self.timer.IsRunning():
         #     running = True
         self.EndAnimation()
-        dlg = EditDialog(parent=self.frame, evalFunction=self.EvaluateInput,
-                         animationData=self.animationData, maxAnimations=len(self.animations))
+        dlg = EditDialog(
+            parent=self.frame,
+            evalFunction=self.EvaluateInput,
+            animationData=self.animationData,
+            maxAnimations=len(
+                self.animations))
         dlg.CenterOnParent()
         if dlg.ShowModal() == wx.ID_CANCEL:
             dlg.Destroy()
@@ -220,8 +229,10 @@ class AnimationController(wx.EvtHandler):
                 break
 
         if not found:
-            GMessage(parent=self.frame,
-                     message=_("Maximum number of animations is %s.") % len(self.animations))
+            GMessage(
+                parent=self.frame,
+                message=_("Maximum number of animations is %s.") %
+                len(self.animations))
             return
 
         # running = False
@@ -232,9 +243,13 @@ class AnimationController(wx.EvtHandler):
 
         animData = AnimationData()
         # number of active animations
-        animationIndex = len([anim for anim in self.animations if anim.IsActive()])
+        animationIndex = len(
+            [anim for anim in self.animations if anim.IsActive()])
         animData.SetDefaultValues(windowIndex, animationIndex)
-        dlg = InputDialog(parent=self.frame, mode='add', animationData=animData)
+        dlg = InputDialog(
+            parent=self.frame,
+            mode='add',
+            animationData=animData)
         dlg.CenterOnParent()
         if dlg.ShowModal() == wx.ID_CANCEL:
             dlg.Destroy()
@@ -242,11 +257,14 @@ class AnimationController(wx.EvtHandler):
         dlg.Destroy()
         # check compatibility
         if animData.windowIndex in indices:
-            GMessage(parent=self.frame, message=_("More animations are using one window."
-                                                  " Please select different window for each animation."))
+            GMessage(
+                parent=self.frame, message=_(
+                    "More animations are using one window."
+                    " Please select different window for each animation."))
             return
         try:
-            temporalMode, tempManager = self.EvaluateInput(self.animationData + [animData])
+            temporalMode, tempManager = self.EvaluateInput(
+                self.animationData + [animData])
         except GException as e:
             GError(parent=self.frame, message=e.value, showTraceback=False)
             return
@@ -299,9 +317,13 @@ class AnimationController(wx.EvtHandler):
             if anim.viewMode == '2d':
                 anim.cmdMatrix = layerListToCmdsMatrix(anim.layerList)
             else:
-                anim.cmdMatrix = [(cmd,) for cmd in anim.GetNvizCommands()['commands']]
+                anim.cmdMatrix = [(cmd,)
+                                  for cmd in anim.GetNvizCommands()
+                                  ['commands']]
         self._updateSlider(timeLabels=timeLabels)
-        self._updateAnimations(activeIndices=indices, mapNamesDict=mapNamesDict)
+        self._updateAnimations(
+            activeIndices=indices,
+            mapNamesDict=mapNamesDict)
         wx.Yield()
         self._updateBitmapData()
         # if running:
@@ -331,30 +353,34 @@ class AnimationController(wx.EvtHandler):
                 if i not in activeIndices:
                     self.animations[i].SetActive(False)
                     continue
-                anim = [anim for anim in self.animationData if anim.windowIndex == i][0]
+                anim = [anim for anim in self.animationData
+                        if anim.windowIndex == i][0]
                 w, h = self.mapwindows[i].GetClientSize()
                 regions = anim.GetRegions(w, h)
-                self.animations[i].SetFrames([HashCmds(cmdList, region)
-                                              for cmdList, region in zip(anim.cmdMatrix, regions)])
+                self.animations[i].SetFrames(
+                    [HashCmds(cmdList, region) for cmdList,
+                     region in zip(anim.cmdMatrix, regions)])
                 self.animations[i].SetActive(True)
         else:
             for i in range(len(self.animations)):
                 if i not in activeIndices:
                     self.animations[i].SetActive(False)
                     continue
-                anim = [anim for anim in self.animationData if anim.windowIndex == i][0]
+                anim = [anim for anim in self.animationData
+                        if anim.windowIndex == i][0]
                 w, h = self.mapwindows[i].GetClientSize()
                 regions = anim.GetRegions(w, h)
-                identifiers = sampleCmdMatrixAndCreateNames(anim.cmdMatrix,
-                                                            mapNamesDict[anim.firstStdsNameType[0]],
-                                                            regions)
+                identifiers = sampleCmdMatrixAndCreateNames(
+                    anim.cmdMatrix, mapNamesDict[
+                        anim.firstStdsNameType[0]], regions)
                 self.animations[i].SetFrames(identifiers)
                 self.animations[i].SetActive(True)
 
     def _updateWindows(self, activeIndices):
         # add or remove window
         for windowIndex in range(len(self.animations)):
-            if not self.frame.IsWindowShown(windowIndex) and windowIndex in activeIndices:
+            if not self.frame.IsWindowShown(
+                    windowIndex) and windowIndex in activeIndices:
                 self.frame.AddWindow(windowIndex)
             elif self.frame.IsWindowShown(windowIndex) and windowIndex not in activeIndices:
                 self.frame.RemoveWindow(windowIndex)
@@ -370,18 +396,27 @@ class AnimationController(wx.EvtHandler):
             else:
                 self._load3DData(animData)
             self._loadLegend(animData)
-        color = UserSettings.Get(group='animation', key='bgcolor', subkey='color')
-        cpus = UserSettings.Get(group='animation', key='nprocs', subkey='value')
+        color = UserSettings.Get(
+            group='animation',
+            key='bgcolor',
+            subkey='color')
+        cpus = UserSettings.Get(
+            group='animation',
+            key='nprocs',
+            subkey='value')
         self.bitmapProvider.Load(nprocs=cpus, bgcolor=color)
         # clear pools
         self.bitmapPool.Clear()
         self.mapFilesPool.Clear()
 
     def _set2DData(self, animationData):
-        opacities = [layer.opacity for layer in animationData.layerList if layer.active]
+        opacities = [
+            layer.opacity for layer in animationData.layerList
+            if layer.active]
         w, h = self.mapwindows[animationData.GetWindowIndex()].GetClientSize()
         regions = animationData.GetRegions(w, h)
-        self.bitmapProvider.SetCmds(animationData.cmdMatrix, opacities, regions)
+        self.bitmapProvider.SetCmds(
+            animationData.cmdMatrix, opacities, regions)
 
     def _load3DData(self, animationData):
         nviz = animationData.GetNvizCommands()
@@ -390,7 +425,8 @@ class AnimationController(wx.EvtHandler):
     def _loadLegend(self, animationData):
         if animationData.legendCmd:
             try:
-                bitmap = self.bitmapProvider.LoadOverlay(animationData.legendCmd)
+                bitmap = self.bitmapProvider.LoadOverlay(
+                    animationData.legendCmd)
                 try:
                     from PIL import Image
                     for param in animationData.legendCmd:
@@ -400,7 +436,9 @@ class AnimationController(wx.EvtHandler):
                             break
                 except ImportError:
                     x, y = 0, 0
-                self.mapwindows[animationData.windowIndex].SetOverlay(bitmap, x, y)
+                self.mapwindows[
+                    animationData.windowIndex].SetOverlay(
+                    bitmap, x, y)
             except GException:
                 GError(message=_("Failed to display legend."))
         else:
@@ -433,7 +471,8 @@ class AnimationController(wx.EvtHandler):
 
         if temporalMode == TemporalMode.NONTEMPORAL:
             if len(mapCount) > 1:
-                raise GException(_("Inconsistent number of maps, please check input data."))
+                raise GException(
+                    _("Inconsistent number of maps, please check input data."))
         elif temporalMode == TemporalMode.TEMPORAL:
             tempManager = TemporalManager()
             # these raise GException:
@@ -449,8 +488,14 @@ class AnimationController(wx.EvtHandler):
     def Reload(self):
         self.EndAnimation()
 
-        color = UserSettings.Get(group='animation', key='bgcolor', subkey='color')
-        cpus = UserSettings.Get(group='animation', key='nprocs', subkey='value')
+        color = UserSettings.Get(
+            group='animation',
+            key='bgcolor',
+            subkey='color')
+        cpus = UserSettings.Get(
+            group='animation',
+            key='nprocs',
+            subkey='value')
         self.bitmapProvider.Load(nprocs=cpus, bgcolor=color, force=True)
 
         self.EndAnimation()
@@ -477,7 +522,8 @@ class AnimationController(wx.EvtHandler):
             timeLabels, mapNamesDict = self.temporalManager.GetLabelsAndMaps()
             frameCount = len(timeLabels)
         else:
-            frameCount = self.animationData[0].mapCount  # should be the same for all
+            frameCount = self.animationData[
+                0].mapCount  # should be the same for all
 
         animWinSize = []
         animWinPos = []
@@ -492,11 +538,19 @@ class AnimationController(wx.EvtHandler):
                 animWinIndex.append(i)
 
         images = []
-        busy = wx.BusyInfo(message=_("Preparing export, please wait..."), parent=self.frame)
+        busy = wx.BusyInfo(
+            message=_("Preparing export, please wait..."),
+            parent=self.frame)
         wx.Yield()
         lastBitmaps = {}
-        fgcolor = UserSettings.Get(group='animation', key='font', subkey='fgcolor')
-        bgcolor = UserSettings.Get(group='animation', key='font', subkey='bgcolor')
+        fgcolor = UserSettings.Get(
+            group='animation',
+            key='font',
+            subkey='fgcolor')
+        bgcolor = UserSettings.Get(
+            group='animation',
+            key='font',
+            subkey='bgcolor')
         for frameIndex in range(frameCount):
             image = wx.EmptyImage(*size)
             image.Replace(0, 0, 0, 255, 255, 255)
@@ -514,7 +568,7 @@ class AnimationController(wx.EvtHandler):
                 else:
                     bitmap = self.bitmapProvider.GetBitmap(frameId)
                     lastBitmaps[i] = bitmap
-                
+
                 im = wx.ImageFromBitmap(lastBitmaps[i])
 
                 # add legend if used
@@ -523,7 +577,8 @@ class AnimationController(wx.EvtHandler):
                     legendBitmap = self.bitmapProvider.LoadOverlay(legend)
                     x, y = self.mapwindows[i].GetOverlayPos()
                     legImage = wx.ImageFromBitmap(legendBitmap)
-                    # not so nice result, can we handle the transparency otherwise?
+                    # not so nice result, can we handle the transparency
+                    # otherwise?
                     legImage.ConvertAlphaToMask()
                     im.Paste(legImage, x, y)
 
@@ -540,19 +595,24 @@ class AnimationController(wx.EvtHandler):
                 elif decoration['name'] == 'time':
                     timeLabel = timeLabels[frameIndex]
                     if timeLabel[1]:  # interval
-                        text = _("%(from)s %(dash)s %(to)s") % \
-                                {'from': timeLabel[0], 'dash': u"\u2013", 'to': timeLabel[1]}
+                        text = _("%(from)s %(dash)s %(to)s") % {
+                            'from': timeLabel[0],
+                            'dash': u"\u2013", 'to': timeLabel[1]}
                     else:
                         if self.temporalManager.GetTemporalType() == TemporalType.ABSOLUTE:
                             text = timeLabel[0]
                         else:
                             text = _("%(start)s %(unit)s") % \
-                                    {'start': timeLabel[0], 'unit': timeLabel[2]}
+                                {'start': timeLabel[0], 'unit': timeLabel[2]}
 
-                    decImage = RenderText(text, decoration['font'], bgcolor, fgcolor).ConvertToImage()
+                    decImage = RenderText(
+                        text, decoration['font'],
+                        bgcolor, fgcolor).ConvertToImage()
                 elif decoration['name'] == 'text':
                     text = decoration['text']
-                    decImage = RenderText(text, decoration['font'], bgcolor, fgcolor).ConvertToImage()
+                    decImage = RenderText(
+                        text, decoration['font'],
+                        bgcolor, fgcolor).ConvertToImage()
 
                 image.Paste(decImage, x, y)
 
@@ -566,8 +626,11 @@ class AnimationController(wx.EvtHandler):
         wx.Yield()
         try:
             if exportInfo['method'] == 'sequence':
-                filename = os.path.join(exportInfo['directory'],
-                                        exportInfo['prefix'] + '.' + exportInfo['format'].lower())
+                filename = os.path.join(
+                    exportInfo['directory'],
+                    exportInfo['prefix'] +
+                    '.' +
+                    exportInfo['format'].lower())
                 writeIms(filename=filename, images=pilImages)
             elif exportInfo['method'] == 'gif':
                 writeGif(filename=exportInfo['file'], images=pilImages,

+ 29 - 12
gui/wxpython/animation/data.py

@@ -32,6 +32,7 @@ import grass.temporal as tgis
 
 
 class AnimationData(object):
+
     def __init__(self):
         self._name = None
         self._windowIndex = 0
@@ -209,17 +210,22 @@ class AnimationData(object):
     def GetZoomRegionValue(self):
         return self._zoomRegionValue
 
-    zoomRegionValue = property(fset=SetZoomRegionValue, fget=GetZoomRegionValue)
+    zoomRegionValue = property(
+        fset=SetZoomRegionValue,
+        fget=GetZoomRegionValue)
 
     def GetRegions(self, width, height):
         self._computeRegions(width, height, self._mapCount, self._startRegion,
                              self._endRegion, self._zoomRegionValue)
         return self._regions
 
-    def _computeRegions(self, width, height, count, startRegion, endRegion=None, zoomValue=None):
+    def _computeRegions(
+            self, width, height, count, startRegion, endRegion=None,
+            zoomValue=None):
         """Computes regions based on start region and end region or zoom value
         for each of the animation frames."""
-        currRegion = dict(gcore.region())  # cast to dict, otherwise deepcopy error
+        currRegion = dict(
+            gcore.region())  # cast to dict, otherwise deepcopy error
         del currRegion['cells']
         del currRegion['cols']
         del currRegion['rows']
@@ -237,15 +243,24 @@ class AnimationData(object):
             self._regions = regions
             return
 
-        startRegionDict = parse_key_val(gcore.read_command('g.region', flags='gu',
-                                                                 region=startRegion),
-                                              val_type=float)
+        startRegionDict = parse_key_val(
+            gcore.read_command(
+                'g.region',
+                flags='gu',
+                region=startRegion),
+            val_type=float)
         if endRegion:
-            endRegionDict = parse_key_val(gcore.read_command('g.region', flags='gu',
-                                                                   region=endRegion),
-                                                val_type=float)
+            endRegionDict = parse_key_val(
+                gcore.read_command(
+                    'g.region',
+                    flags='gu',
+                    region=endRegion),
+                val_type=float)
             for key in ('n', 's', 'e', 'w'):
-                values = interpolate(startRegionDict[key], endRegionDict[key], self._mapCount)
+                values = interpolate(
+                    startRegionDict[key],
+                    endRegionDict[key],
+                    self._mapCount)
                 for value, region in zip(values, regions):
                     region[key] = value
 
@@ -259,7 +274,7 @@ class AnimationData(object):
                 # handle cases when north < south and similarly EW
                 if regions[i]['n'] < regions[i]['s'] or \
                    regions[i]['e'] < regions[i]['w']:
-                        regions[i] = regions[i - 1]
+                    regions[i] = regions[i - 1]
 
         for region in regions:
             mapwidth = abs(region['e'] - region['w'])
@@ -276,6 +291,7 @@ class AnimationData(object):
 class AnimLayer(Layer):
     """Animation layer allows adding either space-time dataset
     or series of maps."""
+
     def __init__(self):
         Layer.__init__(self)
         self._mapTypes.extend(['strds', 'stvds', 'str3ds'])
@@ -284,7 +300,8 @@ class AnimLayer(Layer):
     def SetName(self, name):
         if not self.hidden:
             if self._mapType is None:
-                raise ValueError("To set layer name, the type of layer must be specified.")
+                raise ValueError(
+                    "To set layer name, the type of layer must be specified.")
             if self._mapType in ('strds', 'stvds', 'str3ds'):
                 try:
                     name = validateTimeseriesName(name, self._mapType)

File diff ditekan karena terlalu besar
+ 697 - 260
gui/wxpython/animation/dialogs.py


+ 58 - 26
gui/wxpython/animation/frame.py

@@ -47,6 +47,7 @@ gcore.set_raise_on_error(True)
 
 
 class AnimationFrame(wx.Frame):
+
     def __init__(self, parent, giface, title=_("GRASS GIS Animation tool"),
                  rasters=None, timeseries=None):
         wx.Frame.__init__(self, parent, title=title,
@@ -55,26 +56,35 @@ class AnimationFrame(wx.Frame):
         self.SetClientSize(self.GetSize())
         self.iconsize = (16, 16)
 
-        self.SetIcon(wx.Icon(os.path.join(globalvar.ICONDIR, 'grass_map.ico'), wx.BITMAP_TYPE_ICO))
+        self.SetIcon(
+            wx.Icon(
+                os.path.join(
+                    globalvar.ICONDIR,
+                    'grass_map.ico'),
+                wx.BITMAP_TYPE_ICO))
 
         # Make sure the temporal database exists
         tgis.init()
 
-        # create temporal directory and ensure it's deleted after programs ends (stored in MAPSET/.tmp/)
+        # create temporal directory and ensure it's deleted after programs ends
+        # (stored in MAPSET/.tmp/)
         global TMP_DIR
         TMP_DIR = gcore.tempdir()
 
         self.animations = [Animation() for i in range(MAX_COUNT)]
         self.windows = []
-        self.animationPanel = AnimationsPanel(self, self.windows, initialCount=MAX_COUNT)
+        self.animationPanel = AnimationsPanel(
+            self, self.windows, initialCount=MAX_COUNT)
         bitmapPool = BitmapPool()
         mapFilesPool = MapFilesPool()
 
         self._progressDlg = None
         self._progressDlgMax = None
 
-        self.provider = BitmapProvider(bitmapPool=bitmapPool,
-                                       mapFilesPool=mapFilesPool, tempDir=TMP_DIR)
+        self.provider = BitmapProvider(
+            bitmapPool=bitmapPool,
+            mapFilesPool=mapFilesPool,
+            tempDir=TMP_DIR)
         self.animationSliders = {}
         self.animationSliders['nontemporal'] = SimpleAnimationSlider(self)
         self.animationSliders['temporal'] = TimeAnimationSlider(self)
@@ -91,7 +101,8 @@ class AnimationFrame(wx.Frame):
             self.provider.renderingStarted.connect(self._showRenderingProgress)
             self.provider.renderingContinues.connect(self._updateProgress)
             self.provider.renderingFinished.connect(self._closeProgress)
-            self.provider.compositionStarted.connect(self._showRenderingProgress)
+            self.provider.compositionStarted.connect(
+                self._showRenderingProgress)
             self.provider.compositionContinues.connect(self._updateProgress)
             self.provider.compositionFinished.connect(self._closeProgress)
 
@@ -126,9 +137,12 @@ class AnimationFrame(wx.Frame):
                           Floatable(False).BestSize((-1, -1)).
                           CloseButton(False).DestroyOnClose(True).Layer(0))
         for name, slider in self.animationSliders.iteritems():
-            self._mgr.AddPane(slider, wx.aui.AuiPaneInfo().PaneBorder(False).Name('slider_' + name).
-                              Layer(1).CaptionVisible(False).BestSize(slider.GetBestSize()).
-                              DestroyOnClose(True).CloseButton(False).Bottom())
+            self._mgr.AddPane(
+                slider,
+                wx.aui.AuiPaneInfo().PaneBorder(False).Name(
+                    'slider_' +
+                    name). Layer(1).CaptionVisible(False).BestSize(
+                    slider.GetBestSize()). DestroyOnClose(True).CloseButton(False).Bottom())
             self._mgr.GetPane('slider_' + name).Hide()
 
     def _addToolbar(self, name):
@@ -159,7 +173,8 @@ class AnimationFrame(wx.Frame):
                               BottomDockable(True).TopDockable(True).
                               CloseButton(False).Layer(2).Row(1).
                               BestSize((self.toolbars['animationToolbar'].GetBestSize())))
-            self.controller.SetAnimationToolbar(self.toolbars['animationToolbar'])
+            self.controller.SetAnimationToolbar(
+                self.toolbars['animationToolbar'])
         elif name == 'miscToolbar':
             self.toolbars[name] = MiscToolbar(self)
             self._mgr.AddPane(self.toolbars[name],
@@ -245,9 +260,10 @@ class AnimationFrame(wx.Frame):
             else:
                 win.Show()
         else:  # start
-            win = SpeedDialog(self, temporalMode=self.controller.GetTemporalMode(),
-                              timeGranularity=self.controller.GetTimeGranularity(),
-                              initialSpeed=self.controller.timeTick)
+            win = SpeedDialog(
+                self, temporalMode=self.controller.GetTemporalMode(),
+                timeGranularity=self.controller.GetTimeGranularity(),
+                initialSpeed=self.controller.timeTick)
             win.CenterOnParent()
             self.dialogs['speed'] = win
             win.speedChanged.connect(self.ChangeSpeed)
@@ -260,13 +276,14 @@ class AnimationFrame(wx.Frame):
         self.controller.Reload()
 
     def _showRenderingProgress(self, count):
-        # the message is not really visible, it's there for the initial dlg size
-        self._progressDlg = wx.ProgressDialog(title=_("Loading data"),
-                                              message="Loading data started, please be patient.",
-                                              maximum=count,
-                                              parent=self,
-                                              style=wx.PD_CAN_ABORT | wx.PD_APP_MODAL |
-                                              wx.PD_AUTO_HIDE | wx.PD_SMOOTH)
+        # the message is not really visible, it's there for the initial dlg
+        # size
+        self._progressDlg = wx.ProgressDialog(
+            title=_("Loading data"),
+            message="Loading data started, please be patient.",
+            maximum=count,
+            parent=self,
+            style=wx.PD_CAN_ABORT | wx.PD_APP_MODAL | wx.PD_AUTO_HIDE | wx.PD_SMOOTH)
         self._progressDlgMax = count
 
     def _updateProgress(self, current, text):
@@ -296,7 +313,8 @@ class AnimationFrame(wx.Frame):
         if not self.dialogs['preferences']:
             dlg = PreferencesDialog(parent=self, giface=self._giface)
             self.dialogs['preferences'] = dlg
-            dlg.formatChanged.connect(lambda: self.controller.UpdateAnimations())
+            dlg.formatChanged.connect(
+                lambda: self.controller.UpdateAnimations())
             dlg.CenterOnParent()
 
         self.dialogs['preferences'].ShowModal()
@@ -308,7 +326,7 @@ class AnimationFrame(wx.Frame):
 
     def OnCloseWindow(self, event):
         if self.controller.timer.IsRunning():
-                self.controller.timer.Stop()
+            self.controller.timer.Stop()
         CleanUp(TMP_DIR)()
         self.Destroy()
 
@@ -321,6 +339,7 @@ class AnimationFrame(wx.Frame):
 
 
 class AnimationsPanel(wx.Panel):
+
     def __init__(self, parent, windows, initialCount=4):
         wx.Panel.__init__(self, parent, id=wx.ID_ANY, style=wx.NO_BORDER)
         self.shown = []
@@ -361,6 +380,7 @@ class AnimationsPanel(wx.Panel):
 
 
 class AnimationSliderBase(wx.Panel):
+
     def __init__(self, parent):
         wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY)
         self.label1 = wx.StaticText(self, id=wx.ID_ANY)
@@ -449,6 +469,7 @@ class AnimationSliderBase(wx.Panel):
 
 
 class SimpleAnimationSlider(AnimationSliderBase):
+
     def __init__(self, parent):
         AnimationSliderBase.__init__(self, parent)
 
@@ -461,7 +482,11 @@ class SimpleAnimationSlider(AnimationSliderBase):
                  flag=wx.ALIGN_CENTER | wx.LEFT, border=5)
         hbox.Add(item=self.label1, proportion=0,
                  flag=wx.ALIGN_CENTER | wx.LEFT | wx.RIGHT, border=5)
-        hbox.Add(item=self.slider, proportion=1, flag=wx.ALIGN_CENTER | wx.EXPAND, border=0)
+        hbox.Add(
+            item=self.slider,
+            proportion=1,
+            flag=wx.ALIGN_CENTER | wx.EXPAND,
+            border=0)
         self.SetSizerAndFit(hbox)
 
     def _setFrames(self, count):
@@ -483,6 +508,7 @@ class SimpleAnimationSlider(AnimationSliderBase):
 
 
 class TimeAnimationSlider(AnimationSliderBase):
+
     def __init__(self, parent):
         AnimationSliderBase.__init__(self, parent)
         self.timeLabels = []
@@ -510,7 +536,11 @@ class TimeAnimationSlider(AnimationSliderBase):
         vbox.Add(item=hbox, proportion=0, flag=wx.EXPAND, border=0)
 
         hbox = wx.BoxSizer(wx.HORIZONTAL)
-        hbox.Add(item=self.slider, proportion=1, flag=wx.ALIGN_CENTER | wx.EXPAND, border=0)
+        hbox.Add(
+            item=self.slider,
+            proportion=1,
+            flag=wx.ALIGN_CENTER | wx.EXPAND,
+            border=0)
         vbox.Add(item=hbox, proportion=0, flag=wx.EXPAND, border=0)
 
         self._setTemporalType()
@@ -572,8 +602,10 @@ class TimeAnimationSlider(AnimationSliderBase):
         start = self.timeLabels[index][0]
         if self.timeLabels[index][1]:  # interval
             if self.temporalType == TemporalType.ABSOLUTE:
-                label = _("%(from)s %(dash)s %(to)s") % \
-                    {'from': start, 'dash': u"\u2013", 'to': self.timeLabels[index][1]}
+                label = _("%(from)s %(dash)s %(to)s") % {
+                    'from': start,
+                    'dash': u"\u2013",
+                    'to': self.timeLabels[index][1]}
             else:
                 label = _("to %(to)s") % {'to': self.timeLabels[index][1]}
         else:

+ 3 - 2
gui/wxpython/animation/g.gui.animation.py

@@ -64,7 +64,7 @@ def main():
 
     from grass.script.setup import set_gui_path
     set_gui_path()
-    
+
     from core.globalvar import CheckWxVersion
     from core.utils import _
     from core.giface import StandaloneGrassInterface
@@ -133,7 +133,8 @@ def main():
     frame.Show()
     if len(layerList) >= 1:
         # CallAfter added since it was crashing with wxPython 3 gtk
-        wx.CallAfter(frame.SetAnimations, [layerList] + [None] * (MAX_COUNT - 1))
+        wx.CallAfter(frame.SetAnimations,
+                     [layerList] + [None] * (MAX_COUNT - 1))
     app.MainLoop()
 
 if __name__ == '__main__':

+ 18 - 9
gui/wxpython/animation/mapwindow.py

@@ -35,10 +35,11 @@ class BufferedWindow(wx.Window):
     SaveToFile(self, file_name, file_type) method.
 
     """
+
     def __init__(self, *args, **kwargs):
         # make sure the NO_FULL_REPAINT_ON_RESIZE style flag is set.
-        kwargs['style'] = kwargs.setdefault('style', wx.NO_FULL_REPAINT_ON_RESIZE) | \
-            wx.NO_FULL_REPAINT_ON_RESIZE
+        kwargs['style'] = kwargs.setdefault(
+            'style', wx.NO_FULL_REPAINT_ON_RESIZE) | wx.NO_FULL_REPAINT_ON_RESIZE
         wx.Window.__init__(self, *args, **kwargs)
 
         Debug.msg(2, "BufferedWindow.__init__()")
@@ -50,8 +51,8 @@ class BufferedWindow(wx.Window):
         self.OnSize(None)
 
     def Draw(self, dc):
-        ## just here as a place holder.
-        ## This method should be over-ridden when subclassed
+        # just here as a place holder.
+        # This method should be over-ridden when subclassed
         pass
 
     def OnPaint(self, event):
@@ -74,9 +75,9 @@ class BufferedWindow(wx.Window):
         # event.Skip()
 
     def SaveToFile(self, FileName, FileType=wx.BITMAP_TYPE_PNG):
-        ## This will save the contents of the buffer
-        ## to the specified file. See the wxWindows docs for
-        ## wx.Bitmap::SaveFile for the details
+        # This will save the contents of the buffer
+        # to the specified file. See the wxWindows docs for
+        # wx.Bitmap::SaveFile for the details
         self._Buffer.SaveFile(FileName, FileType)
 
     def UpdateDrawing(self):
@@ -98,6 +99,7 @@ class BufferedWindow(wx.Window):
 
 
 class AnimationWindow(BufferedWindow):
+
     def __init__(self, parent, id=wx.ID_ANY,
                  style=wx.DEFAULT_FRAME_STYLE | wx.FULL_REPAINT_ON_RESIZE |
                  wx.BORDER_RAISED):
@@ -145,8 +147,15 @@ class AnimationWindow(BufferedWindow):
             bitmap = wx.BitmapFromImage(im)
             if self._overlay:
                 im = wx.ImageFromBitmap(self.bitmap_overlay)
-                im.Rescale(im.GetWidth() * params['scale'], im.GetHeight() * params['scale'])
-                self._setOverlay(wx.BitmapFromImage(im), xperc=self.perc[0], yperc=self.perc[1])
+                im.Rescale(
+                    im.GetWidth() *
+                    params['scale'],
+                    im.GetHeight() *
+                    params['scale'])
+                self._setOverlay(
+                    wx.BitmapFromImage(im),
+                    xperc=self.perc[0],
+                    yperc=self.perc[1])
         else:
             self.x = 0
             self.y = 0

+ 69 - 35
gui/wxpython/animation/nviztask.py

@@ -28,6 +28,7 @@ from core.settings import UserSettings
 
 
 class NvizTask:
+
     def __init__(self):
         self.task = None
         self.filename = None
@@ -48,7 +49,9 @@ class NvizTask:
         # pprint(gxwXml.nviz_state)
 
         if not gxwXml.nviz_state:
-            raise GException(_("No 3d view information in workspace file <%s>.") % self.filename)
+            raise GException(
+                _("No 3d view information in workspace file <%s>.") %
+                self.filename)
 
         self._getExtent(gxwXml)
         self._processState(gxwXml.nviz_state)
@@ -58,8 +61,8 @@ class NvizTask:
         for display in root.displays:
             if display['viewMode'] == '3d':
                 self.region['w'], self.region['s'],\
-                self.region['e'], self.region['n'],\
-                self.region['b'], self.region['t'] = display['extent']
+                    self.region['e'], self.region['n'],\
+                    self.region['b'], self.region['t'] = display['extent']
                 self.region['tbres'] = display['tbres']
 
     def _processLayers(self, layers):
@@ -69,18 +72,22 @@ class NvizTask:
 
             if not layer['nviz']:
                 continue
-            layerName, found = GetLayerNameFromCmd(layer['cmd'], fullyQualified=False,
-                                                   param='map')
+            layerName, found = GetLayerNameFromCmd(
+                layer['cmd'], fullyQualified=False, param='map')
             if not found:
                 continue
 
             if 'surface' in layer['nviz']:
-                self._processSurface(layer['nviz']['surface'], mapName=layerName)
+                self._processSurface(
+                    layer['nviz']['surface'],
+                    mapName=layerName)
             if 'volume' in layer['nviz']:
                 self._processVolume(layer['nviz']['volume'], mapName=layerName)
             if 'vector' in layer['nviz']:
                 if 'points' in layer['nviz']['vector']:
-                    self._processPoints(layer['nviz']['vector']['points'], mapName=layerName)
+                    self._processPoints(
+                        layer['nviz']['vector']['points'],
+                        mapName=layerName)
 
     def _processSurface(self, surface, mapName):
         self._setMultiTaskParam('elevation_map', mapName)
@@ -88,8 +95,8 @@ class NvizTask:
         # attributes like color, shine, transparency
         attributes = ('color', 'shine', 'transp')  # mask missing
         parameters = (('color_map', 'color'),
-                     ('shininess_map', 'shininess_value'),
-                     ('transparency_map', 'transparency_value'))
+                      ('shininess_map', 'shininess_value'),
+                      ('transparency_map', 'transparency_value'))
         for attr, params in zip(attributes, parameters):
             mapname = None
             const = None
@@ -117,7 +124,9 @@ class NvizTask:
         value = surface['draw']['wire-color']['value']
         self._setMultiTaskParam('wire_color', value)
         # resolution
-        for mode1, mode2 in zip(('coarse', 'fine'), ('resolution_coarse', 'resolution_fine')):
+        for mode1, mode2 in zip(
+                ('coarse', 'fine'),
+                ('resolution_coarse', 'resolution_fine')):
             value = surface['draw']['resolution'][mode1]
             self._setMultiTaskParam(mode2, value)
 
@@ -135,11 +144,16 @@ class NvizTask:
                 self._setMultiTaskParam('vpoint_' + attrib, str(val))
         if 'height' in points:
             height = points['height']['value']
-            self._setMultiTaskParam('vpoint_position', '0,0,{h}'.format(h=height))
+            self._setMultiTaskParam(
+                'vpoint_position',
+                '0,0,{h}'.format(
+                    h=height))
         if 'marker' in points:
-            marker = list(UserSettings.Get(group='nviz', key='vector',
-                                           subkey=['points', 'marker'],
-                                           settings_type='internal'))[points['marker']['value']]
+            marker = list(
+                UserSettings.Get(
+                    group='nviz', key='vector', subkey=[
+                        'points', 'marker'], settings_type='internal'))[
+                points['marker']['value']]
             self._setMultiTaskParam('vpoint_marker', marker)
         if 'mode' in points:
             if points['mode']['type'] == '3d':
@@ -160,10 +174,11 @@ class NvizTask:
             self._setMultiTaskParam('volume_resolution', res_value)
             for isosurface in isosurfaces:
                 attributes = ('topo', 'color', 'shine', 'transp')
-                parameters = ((None, 'isosurf_level'),
-                              ('isosurf_color_map', 'isosurf_color_value'),
-                              ('isosurf_shininess_map', 'isosurf_shininess_value'),
-                              ('isosurf_transparency_map', 'isosurf_transparency_value'))
+                parameters = (
+                    (None, 'isosurf_level'),
+                    ('isosurf_color_map', 'isosurf_color_value'),
+                    ('isosurf_shininess_map', 'isosurf_shininess_value'),
+                    ('isosurf_transparency_map', 'isosurf_transparency_value'))
                 for attr, params in zip(attributes, parameters):
                     mapname = None
                     const = None
@@ -182,8 +197,10 @@ class NvizTask:
                         self._setMultiTaskParam(params[0], mapname)
                     else:
                         if attr == 'topo':
-                            # TODO: we just assume it's the first volume, what to do else?
-                            self._setMultiTaskParam(params[1], '1:' + str(const))
+                            # TODO: we just assume it's the first volume, what
+                            # to do else?
+                            self._setMultiTaskParam(
+                                params[1], '1:' + str(const))
                         else:
                             self._setMultiTaskParam(params[1], const)
                 if isosurface['inout']['value']:
@@ -194,12 +211,15 @@ class NvizTask:
             res_value = volume['draw']['resolution']['slice']['value']
             self._setMultiTaskParam('volume_resolution', res_value)
             for slice_ in slices:
-                self._setMultiTaskParam('slice_transparency', slice_['transp']['value'])
+                self._setMultiTaskParam(
+                    'slice_transparency', slice_['transp']['value'])
                 axis = slice_['position']['axis']
                 self._setMultiTaskParam('slice', '1:' + 'xyz'[axis])
                 pos = slice_['position']
-                coords = pos['x1'], pos['x2'], pos['y1'], pos['y2'], pos['z1'], pos['z2']
-                self._setMultiTaskParam('slice_position', ','.join([str(c) for c in coords]))
+                coords = pos['x1'], pos['x2'], pos[
+                    'y1'], pos['y2'], pos['z1'], pos['z2']
+                self._setMultiTaskParam('slice_position', ','.join(
+                    [str(c) for c in coords]))
 
         # position
         pos = []
@@ -212,19 +232,25 @@ class NvizTask:
     def _processState(self, state):
         color = state['view']['background']['color']
         self.task.set_param('bgcolor', self._join(color, delim=':'))
-        self.task.set_param('position', self._join((state['view']['position']['x'],
-                                                    state['view']['position']['y'])))
+        self.task.set_param(
+            'position', self._join(
+                (state['view']['position']['x'],
+                 state['view']['position']['y'])))
         self.task.set_param('height', state['iview']['height']['value'])
         self.task.set_param('perspective', state['view']['persp']['value'])
         self.task.set_param('twist', state['view']['twist']['value'])
         # TODO: fix zexag
         self.task.set_param('zexag', state['view']['z-exag']['value'])
-        self.task.set_param('focus', self._join((state['iview']['focus']['x'],
-                                                 state['iview']['focus']['y'],
-                                                 state['iview']['focus']['z'])))
-        self.task.set_param('light_position', self._join((state['light']['position']['x'],
-                                                          state['light']['position']['y'],
-                                                          state['light']['position']['z'] / 100.)))
+        self.task.set_param(
+            'focus', self._join(
+                (state['iview']['focus']['x'],
+                 state['iview']['focus']['y'],
+                 state['iview']['focus']['z'])))
+        self.task.set_param(
+            'light_position', self._join(
+                (state['light']['position']['x'],
+                 state['light']['position']['y'],
+                 state['light']['position']['z'] / 100.)))
         color = state['light']['color'][:3]
         self.task.set_param('light_color', self._join(color, delim=':'))
         self.task.set_param('light_brightness', int(state['light']['bright']))
@@ -262,7 +288,8 @@ class NvizTask:
         if hasattr(layer, 'maps'):
             series = layer.maps
         else:
-            raise GException(_("No map series nor space-time dataset is added."))
+            raise GException(
+                _("No map series nor space-time dataset is added."))
 
         for value in series:
             self.task.set_param(paramName, value)
@@ -273,7 +300,10 @@ class NvizTask:
                 self.task.set_param('isosurf_color_map', '')
             self.task.set_flag('overwrite', True)
             self.task.set_param('output', 'tobechanged')
-            cmd = self.task.get_cmd(ignoreErrors=False, ignoreRequired=False, ignoreDefault=True)
+            cmd = self.task.get_cmd(
+                ignoreErrors=False,
+                ignoreRequired=False,
+                ignoreDefault=True)
             commands.append(cmd)
 
         return commands
@@ -283,7 +313,10 @@ class NvizTask:
             return None
         self.task.set_flag('overwrite', True)
         self.task.set_param('output', 'tobechanged')
-        cmd = self.task.get_cmd(ignoreErrors=False, ignoreRequired=False, ignoreDefault=True)
+        cmd = self.task.get_cmd(
+            ignoreErrors=False,
+            ignoreRequired=False,
+            ignoreDefault=True)
         return gtask.cmdlist_to_tuple(cmd)
 
     def GetRegion(self):
@@ -298,7 +331,8 @@ def test():
     cmds = nviz.GetCommandSeries(['aspect', 'elevation'], 'color_map')
     for cmd in cmds:
         print cmd
-        returncode, message = RunCommand(getErrorMsg=True, prog=cmd[0], **cmd[1])
+        returncode, message = RunCommand(
+            getErrorMsg=True, prog=cmd[0], **cmd[1])
         print returncode, message
 
 

+ 174 - 82
gui/wxpython/animation/provider.py

@@ -44,13 +44,15 @@ class BitmapProvider:
     There is one instance of this class in the application.
     It handles both 2D and 3D animations.
     """
+
     def __init__(self, bitmapPool, mapFilesPool, tempDir,
                  imageWidth=640, imageHeight=480):
 
         self._bitmapPool = bitmapPool
         self._mapFilesPool = mapFilesPool
         self.imageWidth = imageWidth  # width of the image to render with d.rast or d.vect
-        self.imageHeight = imageHeight  # height of the image to render with d.rast or d.vect
+        # height of the image to render with d.rast or d.vect
+        self.imageHeight = imageHeight
         self._tempDir = tempDir
 
         self._uniqueCmds = []
@@ -70,7 +72,8 @@ class BitmapProvider:
         self.renderingStarted = Signal('BitmapProvider.renderingStarted')
         self.compositionStarted = Signal('BitmapProvider.compositionStarted')
         self.renderingContinues = Signal('BitmapProvider.renderingContinues')
-        self.compositionContinues = Signal('BitmapProvider.compositionContinues')
+        self.compositionContinues = Signal(
+            'BitmapProvider.compositionContinues')
         self.renderingFinished = Signal('BitmapProvider.renderingFinished')
         self.compositionFinished = Signal('BitmapProvider.compositionFinished')
         self.mapsLoaded = Signal('BitmapProvider.mapsLoaded')
@@ -89,7 +92,9 @@ class BitmapProvider:
         :param opacities: list of opacity values
         :param regions: list of regions
         """
-        Debug.msg(2, "BitmapProvider.SetCmds: {n} lists".format(n=len(cmdsForComposition)))
+        Debug.msg(
+            2, "BitmapProvider.SetCmds: {n} lists".format(
+                n=len(cmdsForComposition)))
         self._cmdsForComposition.extend(cmdsForComposition)
         self._opacities.extend(opacities)
         self._regions.extend(regions)
@@ -102,7 +107,9 @@ class BitmapProvider:
         :param cmds: list of commands m.nviz.image (cmd as a list)
         :param region: for 3D rendering
         """
-        Debug.msg(2, "BitmapProvider.SetCmds3D: {c} commands".format(c=len(cmds)))
+        Debug.msg(
+            2, "BitmapProvider.SetCmds3D: {c} commands".format(
+                c=len(cmds)))
         self._cmds3D = cmds
         self._regionFor3D = region
 
@@ -118,8 +125,8 @@ class BitmapProvider:
                     unique.append((tuple(cmd), None))
         unique = list(set(unique))
         self._uniqueCmds = [cmdAndRegion[0] for cmdAndRegion in unique]
-        self._regionsForUniqueCmds.extend([dict(cmdAndRegion[1]) if cmdAndRegion[1] else None
-                                           for cmdAndRegion in unique])
+        self._regionsForUniqueCmds.extend([dict(cmdAndRegion[1]) if cmdAndRegion[
+                                          1] else None for cmdAndRegion in unique])
 
     def Unload(self):
         """Unloads currently loaded data.
@@ -127,10 +134,12 @@ class BitmapProvider:
         """
         Debug.msg(2, "BitmapProvider.Unload")
         if self._cmdsForComposition:
-            for cmd, region in zip(self._uniqueCmds, self._regionsForUniqueCmds):
+            for cmd, region in zip(self._uniqueCmds,
+                                   self._regionsForUniqueCmds):
                 del self._mapFilesPool[HashCmd(cmd, region)]
 
-            for cmdList, region in zip(self._cmdsForComposition, self._regions):
+            for cmdList, region in zip(
+                    self._cmdsForComposition, self._regions):
                 del self._bitmapPool[HashCmds(cmdList, region)]
             self._uniqueCmds = []
             self._cmdsForComposition = []
@@ -151,12 +160,15 @@ class BitmapProvider:
         count = 0
         for cmd, region in zip(uniqueCmds, regions):
             filename = GetFileFromCmd(self._tempDir, cmd, region)
-            if not force and os.path.exists(filename) and \
-               self._mapFilesPool.GetSize(HashCmd(cmd, region)) == (self.imageWidth, self.imageHeight):
+            if not force and os.path.exists(filename) and self._mapFilesPool.GetSize(
+                    HashCmd(cmd, region)) == (self.imageWidth, self.imageHeight):
                 continue
             count += 1
 
-        Debug.msg(3, "BitmapProvider._dryRender: {c} files to be rendered".format(c=count))
+        Debug.msg(
+            3,
+            "BitmapProvider._dryRender: {c} files to be rendered".format(
+                c=count))
 
         return count
 
@@ -170,13 +182,17 @@ class BitmapProvider:
         """
         count = 0
         for cmdList, region in zip(cmdLists, regions):
-            if not force and HashCmds(cmdList, region) in self._bitmapPool and \
-                self._bitmapPool[HashCmds(cmdList, region)].GetSize() == (self.imageWidth,
-                                                                          self.imageHeight):
+            if not force and HashCmds(
+                    cmdList, region) in self._bitmapPool and self._bitmapPool[
+                    HashCmds(cmdList, region)].GetSize() == (
+                    self.imageWidth, self.imageHeight):
                 continue
             count += 1
 
-        Debug.msg(2, "BitmapProvider._dryCompose: {c} files to be composed".format(c=count))
+        Debug.msg(
+            2,
+            "BitmapProvider._dryCompose: {c} files to be composed".format(
+                c=count))
 
         return count
 
@@ -206,19 +222,33 @@ class BitmapProvider:
 
         # create no data bitmap
         if None not in self._bitmapPool or force:
-            self._bitmapPool[None] = createNoDataBitmap(self.imageWidth, self.imageHeight)
-
-        ok = self._renderer.Render(cmds, regions, regionFor3D=self._regionFor3D,
-                                   bgcolor=bgcolor, force=force, nprocs=nprocs)
+            self._bitmapPool[None] = createNoDataBitmap(
+                self.imageWidth, self.imageHeight)
+
+        ok = self._renderer.Render(
+            cmds,
+            regions,
+            regionFor3D=self._regionFor3D,
+            bgcolor=bgcolor,
+            force=force,
+            nprocs=nprocs)
         self.renderingFinished.emit()
         if not ok:
             self.mapsLoaded.emit()  # what to do here?
             return
         if self._cmdsForComposition:
-            count = self._dryCompose(self._cmdsForComposition, self._regions, force=force)
+            count = self._dryCompose(
+                self._cmdsForComposition,
+                self._regions,
+                force=force)
             self.compositionStarted.emit(count=count)
-            self._composer.Compose(self._cmdsForComposition, self._regions, self._opacities,
-                                   bgcolor=bgcolor, force=force, nprocs=nprocs)
+            self._composer.Compose(
+                self._cmdsForComposition,
+                self._regions,
+                self._opacities,
+                bgcolor=bgcolor,
+                force=force,
+                nprocs=nprocs)
             self.compositionFinished.emit()
         if self._cmds3D:
             for cmd in self._cmds3D:
@@ -247,7 +277,9 @@ class BitmapProvider:
 
     def WindowSizeChanged(self, width, height):
         """Sets size when size of related window changes."""
-        Debug.msg(5, "BitmapProvider.WindowSizeChanged: w={w}, h={h}".format(w=width, h=height))
+        Debug.msg(
+            5, "BitmapProvider.WindowSizeChanged: w={w}, h={h}".format(
+                w=width, h=height))
 
         self.imageWidth, self.imageHeight = width, height
 
@@ -271,7 +303,8 @@ class BitmapProvider:
 
         Debug.msg(1, "Render raster legend " + str(filename))
         cmdTuple = cmdlist_to_tuple(cmd)
-        returncode, stdout, messages = read2_command(cmdTuple[0], **cmdTuple[1])
+        returncode, stdout, messages = read2_command(
+            cmdTuple[0], **cmdTuple[1])
 
         if returncode == 0:
             return wx.BitmapFromImage(autoCropImageFromFile(filename))
@@ -282,6 +315,7 @@ class BitmapProvider:
 
 class BitmapRenderer:
     """Class which renderes 2D and 3D images to files."""
+
     def __init__(self, mapFilesPool, tempDir,
                  imageWidth, imageHeight):
         self._mapFilesPool = mapFilesPool
@@ -315,8 +349,8 @@ class BitmapRenderer:
         filteredCmdList = []
         for cmd, region in zip(cmdList, regions):
             filename = GetFileFromCmd(self._tempDir, cmd, region)
-            if not force and os.path.exists(filename) and \
-               self._mapFilesPool.GetSize(HashCmd(cmd, region)) == (self.imageWidth, self.imageHeight):
+            if not force and os.path.exists(filename) and self._mapFilesPool.GetSize(
+                    HashCmd(cmd, region)) == (self.imageWidth, self.imageHeight):
                 # for reference counting
                 self._mapFilesPool[HashCmd(cmd, region)] = filename
                 continue
@@ -332,13 +366,27 @@ class BitmapRenderer:
             q = Queue()
             # The separate render process
             if cmd[0] == 'm.nviz.image':
-                p = Process(target=RenderProcess3D,
-                            args=(self.imageWidth, self.imageHeight, self._tempDir,
-                                  cmd, regionFor3D, bgcolor, q))
+                p = Process(
+                    target=RenderProcess3D,
+                    args=(
+                        self.imageWidth,
+                        self.imageHeight,
+                        self._tempDir,
+                        cmd,
+                        regionFor3D,
+                        bgcolor,
+                        q))
             else:
-                p = Process(target=RenderProcess2D,
-                            args=(self.imageWidth, self.imageHeight, self._tempDir,
-                                  cmd, region, bgcolor, q))
+                p = Process(
+                    target=RenderProcess2D,
+                    args=(
+                        self.imageWidth,
+                        self.imageHeight,
+                        self._tempDir,
+                        cmd,
+                        region,
+                        bgcolor,
+                        q))
             p.start()
 
             queue_list.append(q)
@@ -351,16 +399,22 @@ class BitmapRenderer:
                 for i in range(len(cmd_list)):
                     proc_list[i].join()
                     filename = queue_list[i].get()
-                    self._mapFilesPool[HashCmd(cmd_list[i][0], cmd_list[i][1])] = filename
-                    self._mapFilesPool.SetSize(HashCmd(cmd_list[i][0], cmd_list[i][1]),
-                                               (self.imageWidth, self.imageHeight))
+                    self._mapFilesPool[
+                        HashCmd(
+                            cmd_list[i][0],
+                            cmd_list[i][1])] = filename
+                    self._mapFilesPool.SetSize(
+                        HashCmd(cmd_list[i][0],
+                                cmd_list[i][1]),
+                        (self.imageWidth, self.imageHeight))
 
                 proc_count = 0
                 proc_list = []
                 queue_list = []
                 cmd_list = []
 
-            self.renderingContinues.emit(current=count, text=_("Rendering map layers"))
+            self.renderingContinues.emit(
+                current=count, text=_("Rendering map layers"))
             if self._stopRendering:
                 self._stopRendering = False
                 stopped = True
@@ -377,6 +431,7 @@ class BitmapRenderer:
 
 class BitmapComposer:
     """Class which handles the composition of image files with g.pnmcomp."""
+
     def __init__(self, tempDir, mapFilesPool, bitmapPool,
                  imageWidth, imageHeight):
         self._mapFilesPool = mapFilesPool
@@ -411,11 +466,19 @@ class BitmapComposer:
 
         filteredCmdLists = []
         for cmdList, region in zip(cmdLists, regions):
-            if not force and HashCmds(cmdList, region) in self._bitmapPool and \
-                self._bitmapPool[HashCmds(cmdList, region)].GetSize() == (self.imageWidth,
-                                                                          self.imageHeight):
-                # TODO: find a better way than to assign the same to increase the reference
-                self._bitmapPool[HashCmds(cmdList, region)] = self._bitmapPool[HashCmds(cmdList, region)]
+            if not force and HashCmds(
+                    cmdList, region) in self._bitmapPool and self._bitmapPool[
+                    HashCmds(cmdList, region)].GetSize() == (
+                    self.imageWidth, self.imageHeight):
+                # TODO: find a better way than to assign the same to increase
+                # the reference
+                self._bitmapPool[
+                    HashCmds(
+                        cmdList,
+                        region)] = self._bitmapPool[
+                    HashCmds(
+                        cmdList,
+                        region)]
                 continue
             filteredCmdLists.append((cmdList, region))
 
@@ -444,19 +507,27 @@ class BitmapComposer:
                     proc_list[i].join()
                     filename = queue_list[i].get()
                     if filename is None:
-                        self._bitmapPool[HashCmds(cmd_lists[i][0], cmd_lists[i][1])] = \
-                            createNoDataBitmap(self.imageWidth, self.imageHeight,
-                                               text="Failed to render")
+                        self._bitmapPool[
+                            HashCmds(
+                                cmd_lists[i][0],
+                                cmd_lists[i][1])] = createNoDataBitmap(
+                            self.imageWidth,
+                            self.imageHeight,
+                            text="Failed to render")
                     else:
-                        self._bitmapPool[HashCmds(cmd_lists[i][0], cmd_lists[i][1])] = \
-                            wx.BitmapFromImage(wx.Image(filename))
+                        self._bitmapPool[
+                            HashCmds(
+                                cmd_lists[i][0],
+                                cmd_lists[i][1])] = wx.BitmapFromImage(
+                            wx.Image(filename))
                         os.remove(filename)
                 proc_count = 0
                 proc_list = []
                 queue_list = []
                 cmd_lists = []
 
-            self.compositionContinues.emit(current=count, text=_("Overlaying map layers"))
+            self.compositionContinues.emit(
+                current=count, text=_("Overlaying map layers"))
             if self._stopComposing:
                 self._stopComposing = False
                 break
@@ -469,7 +540,8 @@ class BitmapComposer:
             self._stopComposing = True
 
 
-def RenderProcess2D(imageWidth, imageHeight, tempDir, cmd, region, bgcolor, fileQueue):
+def RenderProcess2D(imageWidth, imageHeight, tempDir,
+                    cmd, region, bgcolor, fileQueue):
     """Render raster or vector files as ppm image and write the
        resulting ppm filename in the provided file queue
 
@@ -506,7 +578,8 @@ def RenderProcess2D(imageWidth, imageHeight, tempDir, cmd, region, bgcolor, file
     fileQueue.put(filename)
 
 
-def RenderProcess3D(imageWidth, imageHeight, tempDir, cmd, region, bgcolor, fileQueue):
+def RenderProcess3D(imageWidth, imageHeight, tempDir,
+                    cmd, region, bgcolor, fileQueue):
     """Renders image with m.nviz.image and writes the
        resulting ppm filename in the provided file queue
 
@@ -530,7 +603,8 @@ def RenderProcess3D(imageWidth, imageHeight, tempDir, cmd, region, bgcolor, file
     cmdTuple[1]['size'] = '%d,%d' % (imageWidth, imageHeight)
     # set format
     cmdTuple[1]['format'] = 'ppm'
-    cmdTuple[1]['bgcolor'] = bgcolor = ':'.join([str(part) for part in bgcolor])
+    cmdTuple[1]['bgcolor'] = bgcolor = ':'.join(
+        [str(part) for part in bgcolor])
     returncode, stdout, messages = read2_command(cmdTuple[0], **cmdTuple[1])
     if returncode != 0:
         gcore.warning("Rendering failed:\n" + messages)
@@ -542,7 +616,8 @@ def RenderProcess3D(imageWidth, imageHeight, tempDir, cmd, region, bgcolor, file
     fileQueue.put(filename)
 
 
-def CompositeProcess(imageWidth, imageHeight, tempDir, cmdList, region, opacities, bgcolor, fileQueue):
+def CompositeProcess(imageWidth, imageHeight, tempDir,
+                     cmdList, region, opacities, bgcolor, fileQueue):
     """Performs the composition of image ppm files and writes the
        resulting ppm filename in the provided file queue
 
@@ -569,15 +644,11 @@ def CompositeProcess(imageWidth, imageHeight, tempDir, cmdList, region, opacitie
 
     opacities = [str(op) for op in opacities]
     bgcolor = ':'.join([str(part) for part in bgcolor])
-    returncode, stdout, messages = read2_command('g.pnmcomp',
-                                                 overwrite=True,
-                                                 input='%s' % ",".join(reversed(maps)),
-                                                 mask='%s' % ",".join(reversed(masks)),
-                                                 opacity='%s' % ",".join(reversed(opacities)),
-                                                 bgcolor=bgcolor,
-                                                 width=imageWidth,
-                                                 height=imageHeight,
-                                                 output=filename)
+    returncode, stdout, messages = read2_command(
+        'g.pnmcomp', overwrite=True, input='%s' % ",".join(reversed(maps)),
+        mask='%s' % ",".join(reversed(masks)),
+        opacity='%s' % ",".join(reversed(opacities)),
+        bgcolor=bgcolor, width=imageWidth, height=imageHeight, output=filename)
 
     if returncode != 0:
         gcore.warning("Rendering composite failed:\n" + messages)
@@ -592,6 +663,7 @@ class DictRefCounter:
     """Base class storing map files/bitmaps (emulates dictionary).
     Counts the references to know which files/bitmaps to delete.
     """
+
     def __init__(self):
         self.dictionary = {}
         self.referenceCount = {}
@@ -605,14 +677,16 @@ class DictRefCounter:
             self.referenceCount[key] = 1
         else:
             self.referenceCount[key] += 1
-        Debug.msg(5, 'DictRefCounter.__setitem__: +1 for key {k}'.format(k=key))
+        Debug.msg(
+            5, 'DictRefCounter.__setitem__: +1 for key {k}'.format(k=key))
 
     def __contains__(self, key):
         return key in self.dictionary
 
     def __delitem__(self, key):
         self.referenceCount[key] -= 1
-        Debug.msg(5, 'DictRefCounter.__delitem__: -1 for key {k}'.format(k=key))
+        Debug.msg(
+            5, 'DictRefCounter.__delitem__: -1 for key {k}'.format(k=key))
 
     def keys(self):
         return self.dictionary.keys()
@@ -629,6 +703,7 @@ class DictRefCounter:
 
 class MapFilesPool(DictRefCounter):
     """Stores rendered images as files."""
+
     def __init__(self):
         DictRefCounter.__init__(self)
         self.size = {}
@@ -658,12 +733,14 @@ class MapFilesPool(DictRefCounter):
 
 class BitmapPool(DictRefCounter):
     """Class storing bitmaps (emulates dictionary)"""
+
     def __init__(self):
         DictRefCounter.__init__(self)
 
 
 class CleanUp:
     """Responsible for cleaning up the files."""
+
     def __init__(self, tempDir):
         self._tempDir = tempDir
 
@@ -672,9 +749,13 @@ class CleanUp:
         if os.path.exists(self._tempDir):
             try:
                 shutil.rmtree(self._tempDir)
-                Debug.msg(5, 'CleanUp: removed directory {t}'.format(t=self._tempDir))
+                Debug.msg(
+                    5, 'CleanUp: removed directory {t}'.format(
+                        t=self._tempDir))
             except OSError:
-                gcore.warning(_("Directory {t} not removed.").format(t=self._tempDir))
+                gcore.warning(
+                    _("Directory {t} not removed.").format(
+                        t=self._tempDir))
 
 
 def _setEnvironment(width, height, filename, transparent, bgcolor):
@@ -686,20 +767,22 @@ def _setEnvironment(width, height, filename, transparent, bgcolor):
     :param transparent: use transparency
     :param bgcolor: background color as a tuple of 3 values 0 to 255
     """
-    Debug.msg(5, "_setEnvironment: width={w}, height={h}, "
-                 "filename={f}, transparent={t}, bgcolor={b}".format(w=width,
-                                                                     h=height,
-                                                                     f=filename,
-                                                                     t=transparent,
-                                                                     b=bgcolor))
+    Debug.msg(
+        5,
+        "_setEnvironment: width={w}, height={h}, "
+        "filename={f}, transparent={t}, bgcolor={b}".format(
+            w=width,
+            h=height,
+            f=filename,
+            t=transparent,
+            b=bgcolor))
 
     os.environ['GRASS_RENDER_WIDTH'] = str(width)
     os.environ['GRASS_RENDER_HEIGHT'] = str(height)
     driver = UserSettings.Get(group='display', key='driver', subkey='type')
     os.environ['GRASS_RENDER_IMMEDIATE'] = driver
-    os.environ['GRASS_RENDER_BACKGROUNDCOLOR'] = '{r:02x}{g:02x}{b:02x}'.format(r=bgcolor[0],
-                                                                         g=bgcolor[1],
-                                                                         b=bgcolor[2])
+    os.environ['GRASS_RENDER_BACKGROUNDCOLOR'] = '{r:02x}{g:02x}{b:02x}'.format(
+        r=bgcolor[0], g=bgcolor[1], b=bgcolor[2])
     os.environ['GRASS_RENDER_TRUECOLOR'] = "TRUE"
     if transparent:
         os.environ['GRASS_RENDER_TRANSPARENT'] = "TRUE"
@@ -717,9 +800,8 @@ def createNoDataBitmap(imageWidth, imageHeight, text="No data"):
     :param imageWidth: image width
     :param imageHeight: image height
     """
-    Debug.msg(4, "createNoDataBitmap: w={w}, h={h}, text={t}".format(w=imageWidth,
-                                                                     h=imageHeight,
-                                                                     t=text))
+    Debug.msg(4, "createNoDataBitmap: w={w}, h={h}, text={t}".format(
+        w=imageWidth, h=imageHeight, t=text))
     bitmap = wx.EmptyBitmap(imageWidth, imageHeight)
     dc = wx.MemoryDC()
     dc.SelectObject(bitmap)
@@ -780,13 +862,19 @@ def test():
     prov = BitmapProvider(bPool, mapFilesPool, tempDir,
                           imageWidth=640, imageHeight=480)
     prov.renderingStarted.connect(
-        lambda count: sys.stdout.write("Total number of maps: {c}\n".format(c=count)))
+        lambda count: sys.stdout.write(
+            "Total number of maps: {c}\n".format(
+                c=count)))
     prov.renderingContinues.connect(
-        lambda current, text: sys.stdout.write("Current number: {c}\n".format(c=current)))
-    prov.compositionStarted.connect(
-        lambda count: sys.stdout.write("Composition: total number of maps: {c}\n".format(c=count)))
+        lambda current, text: sys.stdout.write(
+            "Current number: {c}\n".format(
+                c=current)))
+    prov.compositionStarted.connect(lambda count: sys.stdout.write(
+        "Composition: total number of maps: {c}\n".format(c=count)))
     prov.compositionContinues.connect(
-        lambda current, text: sys.stdout.write("Composition: Current number: {c}\n".format(c=current)))
+        lambda current, text: sys.stdout.write(
+            "Composition: Current number: {c}\n".format(
+                c=current)))
     prov.mapsLoaded.connect(
         lambda: sys.stdout.write("Maps loading finished\n"))
     cmdMatrix = layerListToCmdsMatrix(layerList)
@@ -797,7 +885,11 @@ def test():
 
     for key in bPool.keys():
         if key is not None:
-            bPool[key].SaveFile(os.path.join(tempDir, key + '.png'), wx.BITMAP_TYPE_PNG)
+            bPool[key].SaveFile(
+                os.path.join(
+                    tempDir,
+                    key + '.png'),
+                wx.BITMAP_TYPE_PNG)
 #    prov.Unload()
 #    prov.SetCmds(cmdMatrix, [l.opacity for l in layerList])
 #    prov.Load(bgcolor=(13, 156, 230))

+ 142 - 44
gui/wxpython/animation/temporal_manager.py

@@ -40,6 +40,7 @@ class GranularityMode:
 
 class TemporalManager(object):
     """Class for temporal data processing."""
+
     def __init__(self):
         self.timeseriesList = []
         self.timeseriesInfo = {}
@@ -69,7 +70,11 @@ class TemporalManager(object):
         :param timeseries: name of timeseries (with or without mapset)
         :param etype: element type (strds, stvds)
         """
-        self._gatherInformation(timeseries, etype, self.timeseriesList, self.timeseriesInfo)
+        self._gatherInformation(
+            timeseries,
+            etype,
+            self.timeseriesList,
+            self.timeseriesInfo)
 
     def EvaluateInputData(self):
         """Checks if all timeseries are compatible (raises GException).
@@ -116,7 +121,8 @@ class TemporalManager(object):
             for infoDict in self.timeseriesInfo.values():
                 units.add(infoDict['unit'])
             if len(units) > 1:
-                message = _("It is not allowed to display data with different units (%s).") % ','.join(units)
+                message = _(
+                    "It is not allowed to display data with different units (%s).") % ','.join(units)
                 return False, message
 
         # check for interval x point
@@ -127,9 +133,10 @@ class TemporalManager(object):
             else:
                 point += 1
         if bool(interval) == bool(point):
-            message = _("You are going to display data with different "
-                        "temporal types of maps (interval and point)."
-                        " It is recommended to use data of one temporal type to avoid confusion.")
+            message = _(
+                "You are going to display data with different "
+                "temporal types of maps (interval and point)."
+                " It is recommended to use data of one temporal type to avoid confusion.")
             return True, message  # warning
 
         return True, None
@@ -139,7 +146,8 @@ class TemporalManager(object):
         """
         if self.dataMode == DataMode.SIMPLE:
             gran = self.timeseriesInfo[self.timeseriesList[0]]['granularity']
-            if 'unit' in self.timeseriesInfo[self.timeseriesList[0]]:  # relative:
+            if 'unit' in self.timeseriesInfo[
+                    self.timeseriesList[0]]:  # relative:
                 granNum = gran
                 unit = self.timeseriesInfo[self.timeseriesList[0]]['unit']
                 if self.granularityMode == GranularityMode.ONE_UNIT:
@@ -187,13 +195,13 @@ class TemporalManager(object):
         # combine all timeLabels and fill missing maps with None
         # BUT this does not work properly if the datasets have
         # no temporal overlap! We would need to sample all datasets
-        # by a temporary dataset, I don't know how it would work with point data
+        # by a temporary dataset, I don't know how it would work with point
+        # data
         if self.temporalType == TemporalType.ABSOLUTE:
             timestamps = sorted(list(labelListSet), key=lambda x: x[0])
         else:
             timestamps = sorted(list(labelListSet), key=lambda x: x[0])
 
-
         newMapLists = []
         for mapList, labelList in zip(mapLists, labelLists):
             newMapList = [None] * len(timestamps)
@@ -210,22 +218,29 @@ class TemporalManager(object):
 
         if self.temporalType == TemporalType.ABSOLUTE:
             # ('1996-01-01 00:00:00', '1997-01-01 00:00:00', 'year'),
-            formatString = UserSettings.Get(group='animation', key='temporal', subkey='format')
-            timestamps = [(datetime.datetime.strftime(st, formatString),
-                          datetime.datetime.strftime(end, formatString)
-                          if end is not None else None, unit) for (st, end, unit) in timestamps]
+            formatString = UserSettings.Get(
+                group='animation', key='temporal', subkey='format')
+            timestamps = [
+                (datetime.datetime.strftime(
+                    st, formatString), datetime.datetime.strftime(
+                    end, formatString) if end is not None else None, unit) for (
+                    st, end, unit) in timestamps]
         else:
             # ('15', '16', u'years'),
-            timestamps = [(str(st), end if end is None else str(end), unit) for st, end, unit in timestamps]
+            timestamps = [(str(st), end if end is None else str(end), unit)
+                          for st, end, unit in timestamps]
         return timestamps, mapDict
 
     def _getLabelsAndMaps(self, timeseries):
         """Returns time labels and map names (done by sampling)
         for both interval and point data.
         """
-        sp = tgis.dataset_factory(self.timeseriesInfo[timeseries]['etype'], timeseries)
+        sp = tgis.dataset_factory(
+            self.timeseriesInfo[timeseries]['etype'], timeseries)
         if sp.is_in_db() is False:
-            raise GException(_("Space time dataset <%s> not found.") % timeseries)
+            raise GException(
+                _("Space time dataset <%s> not found.") %
+                timeseries)
         sp.select()
 
         listOfMaps = []
@@ -307,7 +322,8 @@ class TemporalManager(object):
                 end = tgis.string_to_datetime(end)
                 end = tgis.datetime_to_grass_datetime_string(end)
             grassLabels.append((start, end, unit))
-            if '00:00:00' not in start or (end is not None and '00:00:00' not in end):
+            if '00:00:00' not in start or (
+                    end is not None and '00:00:00' not in end):
                 isTime = True
         if not isTime:
             for i, (start, end, unit) in enumerate(grassLabels):
@@ -327,7 +343,8 @@ class TemporalManager(object):
         maps = sp.get_registered_maps_as_objects()
 
         if not sp.check_temporal_topology(maps):
-            raise GException(_("Topology of Space time dataset %s is invalid." % id))
+            raise GException(
+                _("Topology of Space time dataset %s is invalid." % id))
 
         timeseriesList.append(id)
         infoDict[id] = {}
@@ -364,12 +381,22 @@ def test():
     print '///////////////////////////'
     gran = temp.GetGranularity()
     print "granularity: " + str(gran)
-    pprint (temp.GetLabelsAndMaps())
+    pprint(temp.GetLabelsAndMaps())
 
 
 def createAbsoluteInterval():
-    grass.run_command('g.region', s=0, n=80, w=0, e=120, b=0, t=50, res=10, res3=10,
-                      flags='p3', quiet=True)
+    grass.run_command(
+        'g.region',
+        s=0,
+        n=80,
+        w=0,
+        e=120,
+        b=0,
+        t=50,
+        res=10,
+        res3=10,
+        flags='p3',
+        quiet=True)
 
     grass.mapcalc(exp="prec_1 = rand(0, 550)", overwrite=True)
     grass.mapcalc(exp="prec_2 = rand(0, 450)", overwrite=True)
@@ -414,17 +441,37 @@ def createAbsoluteInterval():
                       maps='prec_1,prec_2,prec_3,prec_4,prec_5,prec_6,'
                       'temp_1,temp_2,temp_3,temp_4,temp_5,temp_6')
     for name, fname in zip((name1, name2), (n1, n2)):
-        grass.run_command('t.create', overwrite=True, type='strds',
-                          temporaltype='absolute', output=name,
-                          title="A test with input files", descr="A test with input files")
-        grass.run_command('t.register', flags='i', input=name, file=fname, overwrite=True)
+        grass.run_command(
+            't.create',
+            overwrite=True,
+            type='strds',
+            temporaltype='absolute',
+            output=name,
+            title="A test with input files",
+            descr="A test with input files")
+        grass.run_command(
+            't.register',
+            flags='i',
+            input=name,
+            file=fname,
+            overwrite=True)
 
     return name1, name2
 
 
 def createRelativeInterval():
-    grass.run_command('g.region', s=0, n=80, w=0, e=120, b=0, t=50, res=10, res3=10,
-                      flags='p3', quiet=True)
+    grass.run_command(
+        'g.region',
+        s=0,
+        n=80,
+        w=0,
+        e=120,
+        b=0,
+        t=50,
+        res=10,
+        res3=10,
+        flags='p3',
+        quiet=True)
 
     grass.mapcalc(exp="prec_1 = rand(0, 550)", overwrite=True)
     grass.mapcalc(exp="prec_2 = rand(0, 450)", overwrite=True)
@@ -469,16 +516,37 @@ def createRelativeInterval():
                       maps='prec_1,prec_2,prec_3,prec_4,prec_5,prec_6,'
                       'temp_1,temp_2,temp_3,temp_4,temp_5,temp_6')
     for name, fname in zip((name1, name2), (n1, n2)):
-        grass.run_command('t.create', overwrite=True, type='strds',
-                          temporaltype='relative', output=name,
-                          title="A test with input files", descr="A test with input files")
-        grass.run_command('t.register', flags='i', input=name, file=fname, unit="years", overwrite=True)
+        grass.run_command(
+            't.create',
+            overwrite=True,
+            type='strds',
+            temporaltype='relative',
+            output=name,
+            title="A test with input files",
+            descr="A test with input files")
+        grass.run_command(
+            't.register',
+            flags='i',
+            input=name,
+            file=fname,
+            unit="years",
+            overwrite=True)
     return name1, name2
 
 
 def createAbsolutePoint():
-    grass.run_command('g.region', s=0, n=80, w=0, e=120, b=0, t=50, res=10, res3=10,
-                      flags='p3', quiet=True)
+    grass.run_command(
+        'g.region',
+        s=0,
+        n=80,
+        w=0,
+        e=120,
+        b=0,
+        t=50,
+        res=10,
+        res3=10,
+        flags='p3',
+        quiet=True)
 
     grass.mapcalc(exp="prec_1 = rand(0, 550)", overwrite=True)
     grass.mapcalc(exp="prec_2 = rand(0, 450)", overwrite=True)
@@ -499,17 +567,37 @@ def createAbsolutePoint():
     )
     fd.close()
     name = 'abspoint'
-    grass.run_command('t.create', overwrite=True, type='strds',
-                      temporaltype='absolute', output=name,
-                      title="A test with input files", descr="A test with input files")
-
-    grass.run_command('t.register', flags='i', input=name, file=n1, overwrite=True)
+    grass.run_command(
+        't.create',
+        overwrite=True,
+        type='strds',
+        temporaltype='absolute',
+        output=name,
+        title="A test with input files",
+        descr="A test with input files")
+
+    grass.run_command(
+        't.register',
+        flags='i',
+        input=name,
+        file=n1,
+        overwrite=True)
     return name
 
 
 def createRelativePoint():
-    grass.run_command('g.region', s=0, n=80, w=0, e=120, b=0, t=50, res=10, res3=10,
-                      flags='p3', quiet=True)
+    grass.run_command(
+        'g.region',
+        s=0,
+        n=80,
+        w=0,
+        e=120,
+        b=0,
+        t=50,
+        res=10,
+        res3=10,
+        flags='p3',
+        quiet=True)
 
     grass.mapcalc(exp="prec_1 = rand(0, 550)", overwrite=True)
     grass.mapcalc(exp="prec_2 = rand(0, 450)", overwrite=True)
@@ -530,11 +618,21 @@ def createRelativePoint():
     )
     fd.close()
     name = 'relpoint'
-    grass.run_command('t.create', overwrite=True, type='strds',
-                      temporaltype='relative', output=name,
-                      title="A test with input files", descr="A test with input files")
-
-    grass.run_command('t.register', unit="day", input=name, file=n1, overwrite=True)
+    grass.run_command(
+        't.create',
+        overwrite=True,
+        type='strds',
+        temporaltype='relative',
+        output=name,
+        title="A test with input files",
+        descr="A test with input files")
+
+    grass.run_command(
+        't.register',
+        unit="day",
+        input=name,
+        file=n1,
+        overwrite=True)
     return name
 
 if __name__ == '__main__':

+ 69 - 48
gui/wxpython/animation/toolbars.py

@@ -25,35 +25,55 @@ from gui_core.simplelmgr import SimpleLmgrToolbar
 from animation.anim import ReplayMode
 
 ganimIcons = {
-    'speed': MetaIcon(img='move', label=_("Change animation speed")),
-    'playForward': MetaIcon(img='execute', label=_("Play forward")),
-    'playBack': MetaIcon(img='player-back', label=_("Play back")),
-    'stop': MetaIcon(img='player-stop', label=_("Stop")),
-    'pause': MetaIcon(img='player-pause', label=_("Pause")),
-    'oneDirectionReplay': MetaIcon(img='redraw', label=_("Repeat")),
-    'bothDirectionReplay': MetaIcon(img='player-repeat-back-forward',
-                                    label=_("Play back and forward")),
-    'addAnimation': MetaIcon(img='layer-add', label=_("Add new animation"),
-                             desc=_("Add new animation")),
-    'editAnimation': MetaIcon(img='layer-more', label=_("Add, edit or remove animation"),
-                              desc=_("Add, edit or remove animation")),
-    'exportAnimation': MetaIcon(img='layer-export', label=_("Export animation"),
-                                desc=_("Export animation"))
-}
+    'speed': MetaIcon(
+        img='move',
+        label=_("Change animation speed")),
+    'playForward': MetaIcon(
+        img='execute',
+        label=_("Play forward")),
+    'playBack': MetaIcon(
+        img='player-back',
+        label=_("Play back")),
+    'stop': MetaIcon(
+        img='player-stop',
+        label=_("Stop")),
+    'pause': MetaIcon(
+        img='player-pause',
+        label=_("Pause")),
+    'oneDirectionReplay': MetaIcon(
+        img='redraw',
+        label=_("Repeat")),
+    'bothDirectionReplay': MetaIcon(
+        img='player-repeat-back-forward',
+        label=_("Play back and forward")),
+    'addAnimation': MetaIcon(
+        img='layer-add',
+        label=_("Add new animation"),
+        desc=_("Add new animation")),
+    'editAnimation': MetaIcon(
+        img='layer-more',
+        label=_("Add, edit or remove animation"),
+        desc=_("Add, edit or remove animation")),
+    'exportAnimation': MetaIcon(
+        img='layer-export',
+        label=_("Export animation"),
+        desc=_("Export animation"))}
 
 SIMPLE_LMGR_STDS = 256
 
 
 simpleLmgrIcons = {
-    'addSeries': MetaIcon(img='mapset-add',
-                          label=_("Add space-time dataset or series of map layers"),
-                          desc=_("Add space-time dataset or series of map layers for animation")),
+    'addSeries': MetaIcon(
+        img='mapset-add',
+        label=_("Add space-time dataset or series of map layers"),
+        desc=_("Add space-time dataset or series of map layers for animation")),
 }
 
 
 class MainToolbar(BaseToolbar):
     """Main toolbar (data management)
     """
+
     def __init__(self, parent):
         """Main toolbar constructor
         """
@@ -69,20 +89,21 @@ class MainToolbar(BaseToolbar):
         # BaseIcons are a set of often used icons. It is possible
         # to reuse icons in ./trunk/gui/icons/grass or add new ones there.
         icons = ganimIcons
-        return self._getToolbarData((("addAnimation", icons["addAnimation"],
-                                      self.parent.OnAddAnimation),
-                                     ("editAnimation", icons["editAnimation"],
-                                      self.parent.OnEditAnimation),
-                                     ("reload", BaseIcons["render"],
-                                      self.parent.Reload),
-                                     ("exportAnimation", icons["exportAnimation"],
-                                      self.parent.OnExportAnimation)
-                                     ))
+        return self._getToolbarData(
+            (("addAnimation", icons["addAnimation"],
+              self.parent.OnAddAnimation),
+             ("editAnimation", icons["editAnimation"],
+              self.parent.OnEditAnimation),
+             ("reload", BaseIcons["render"],
+              self.parent.Reload),
+             ("exportAnimation", icons["exportAnimation"],
+              self.parent.OnExportAnimation)))
 
 
 class AnimationToolbar(BaseToolbar):
     """Animation toolbar (to control animation)
     """
+
     def __init__(self, parent):
         """Animation toolbar constructor
         """
@@ -101,26 +122,23 @@ class AnimationToolbar(BaseToolbar):
         # BaseIcons are a set of often used icons. It is possible
         # to reuse icons in ./trunk/gui/icons/grass or add new ones there.
         icons = ganimIcons
-        return self._getToolbarData((("playBack", icons["playBack"],
-                                      self.OnPlayBack),
-                                     ("playForward", icons["playForward"],
-                                      self.OnPlayForward),
-                                     ("pause", icons["pause"],
-                                      self.OnPause,
-                                      wx.ITEM_CHECK),
-                                     ("stop", icons["stop"],
-                                      self.OnStop),
-                                     (None, ),
-                                     ("oneDirectionReplay", icons["oneDirectionReplay"],
-                                      self.OnOneDirectionReplay,
-                                      wx.ITEM_CHECK),
-                                     ("bothDirectionReplay", icons["bothDirectionReplay"],
-                                      self.OnBothDirectionReplay,
-                                      wx.ITEM_CHECK),
-                                     (None, ),
-                                     ("adjustSpeed", icons['speed'],
-                                      self.parent.OnAdjustSpeed)
-                                     ))
+        return self._getToolbarData(
+            (("playBack", icons["playBack"],
+              self.OnPlayBack),
+             ("playForward", icons["playForward"],
+              self.OnPlayForward),
+             ("pause", icons["pause"],
+              self.OnPause, wx.ITEM_CHECK),
+             ("stop", icons["stop"],
+              self.OnStop),
+             (None,),
+             ("oneDirectionReplay", icons["oneDirectionReplay"],
+              self.OnOneDirectionReplay, wx.ITEM_CHECK),
+             ("bothDirectionReplay", icons["bothDirectionReplay"],
+              self.OnBothDirectionReplay, wx.ITEM_CHECK),
+             (None,),
+             ("adjustSpeed", icons['speed'],
+              self.parent.OnAdjustSpeed)))
 
     def OnPlayForward(self, event):
         self.PlayForward()
@@ -171,7 +189,8 @@ class AnimationToolbar(BaseToolbar):
 
         # if not self.GetToolState(self.oneDirectionReplay) and \
         #    not self.GetToolState(self.bothDirectionReplay):
-        #     self.EnableTool(self.playBack, False) # assuming that stop rewinds to the beginning
+        # self.EnableTool(self.playBack, False) # assuming that stop rewinds to
+        # the beginning
 
     def OnOneDirectionReplay(self, event):
         if event.IsChecked():
@@ -204,6 +223,7 @@ class AnimationToolbar(BaseToolbar):
 class MiscToolbar(BaseToolbar):
     """Toolbar with miscellaneous tools related to app
     """
+
     def __init__(self, parent):
         """Toolbar constructor
         """
@@ -228,6 +248,7 @@ class AnimSimpleLmgrToolbar(SimpleLmgrToolbar):
     """Simple layer manager toolbar for animation tool.
     Allows adding space-time dataset or series of maps.
     """
+
     def __init__(self, parent, lmgrStyle):
         SimpleLmgrToolbar.__init__(self, parent, lmgrStyle)
 

+ 17 - 5
gui/wxpython/animation/utils.py

@@ -66,7 +66,9 @@ def validateTimeseriesName(timeseries, etype='strds'):
         if nameShort in trastDict[mapset]:
             return timeseries
         else:
-            raise GException(_("Space time dataset <%s> not found.") % timeseries)
+            raise GException(
+                _("Space time dataset <%s> not found.") %
+                timeseries)
 
     mapsets = tgis.get_tgis_c_library_interface().available_mapsets()
     for mapset in mapsets:
@@ -200,7 +202,8 @@ def checkSeriesCompatibility(mapSeriesList=None, timeseriesList=None):
             raise GException(_("The number of maps to animate has to be "
                                "the same for each map series."))
 
-        if timeseriesList and list(count)[0] != list(timeseriesInfo['count'])[0]:
+        if timeseriesList and list(count)[0] != list(
+                timeseriesInfo['count'])[0]:
             raise GException(_("The number of maps to animate has to be "
                                "the same as the number of maps in temporal dataset."))
 
@@ -260,7 +263,13 @@ def RenderText(text, font, bgcolor, fgcolor):
 def WxImageToPil(image):
     """Converts wx.Image to PIL image"""
     pilImage = Image.new('RGB', (image.GetWidth(), image.GetHeight()))
-    getattr(pilImage, "frombytes", getattr(pilImage, "fromstring"))(image.GetData())
+    getattr(
+        pilImage,
+        "frombytes",
+        getattr(
+            pilImage,
+            "fromstring"))(
+        image.GetData())
     return pilImage
 
 
@@ -318,9 +327,12 @@ def layerListToCmdsMatrix(layerList):
                         if mapLayer:
                             try:
                                 idx = cmd.index('layer')
-                                cmd[idx] = 'layer={layer}'.format(layer=mapLayer)
+                                cmd[idx] = 'layer={layer}'.format(
+                                    layer=mapLayer)
                             except ValueError:
-                                cmd.append('layer={layer}'.format(layer=mapLayer))
+                                cmd.append(
+                                    'layer={layer}'.format(
+                                        layer=mapLayer))
                         cmds.append(cmd[:])
                     cmdsForComposition.append(cmds)
         else:

+ 1 - 1
gui/wxpython/core/__init__.py

@@ -13,4 +13,4 @@ all = [
     'utils',
     'globalvar',
     'giface',
-    ]
+]

+ 17 - 12
gui/wxpython/core/debug.py

@@ -10,7 +10,7 @@ Classes:
 from core.debug import Debug
 Debug.msg (3, 'debug message')
 @endcode
-         
+
 (C) 2007-2009, 2011 by the GRASS Development Team
 
 This program is free software under the GNU General Public License
@@ -24,16 +24,18 @@ import sys
 
 import grass.script as grass
 
+
 class DebugMsg:
     """wxGUI debugging
-    
+
         g.gisenv set=WX_DEBUG=[0-5]
 
     """
+
     def __init__(self):
         # default level
         self.debuglevel = 0
-        
+
         self.SetLevel()
 
     def SetLevel(self):
@@ -42,11 +44,14 @@ class DebugMsg:
         try:
             self.debuglevel = int(grass.gisenv().get('WX_DEBUG', 0))
             if self.debuglevel < 0 or self.debuglevel > 5:
-                raise ValueError(_("Wx debug level {}.").format(self.debuglevel))
+                raise ValueError(
+                    _("Wx debug level {}.").format(
+                        self.debuglevel))
         except ValueError as e:
             self.debuglevel = 0
-            sys.stderr.write(_("WARNING: Ignoring unsupported wx debug level (must be >=0 and <=5). {}\n").format(e))
-        
+            sys.stderr.write(
+                _("WARNING: Ignoring unsupported wx debug level (must be >=0 and <=5). {}\n").format(e))
+
     def msg(self, level, message, *args):
         """Print debug message
 
@@ -57,13 +62,13 @@ class DebugMsg:
         # self.SetLevel()
         if self.debuglevel > 0 and level > 0 and level <= self.debuglevel:
             if args:
-                sys.stderr.write("GUI D%d/%d: " % (level, self.debuglevel) + \
-                    message % args + os.linesep)
+                sys.stderr.write("GUI D%d/%d: " % (level, self.debuglevel) +
+                                 message % args + os.linesep)
             else:
-                sys.stderr.write("GUI D%d/%d: " % (level, self.debuglevel) + \
-                                     message + os.linesep)
-            sys.stderr.flush() # force flush (required for MS Windows)
-        
+                sys.stderr.write("GUI D%d/%d: " % (level, self.debuglevel) +
+                                 message + os.linesep)
+            sys.stderr.flush()  # force flush (required for MS Windows)
+
     def GetLevel(self):
         """Return current GUI debug level"""
         return self.debuglevel

+ 189 - 159
gui/wxpython/core/gcmd.py

@@ -46,14 +46,18 @@ import wx
 
 from grass.script import core as grass
 
-from core       import globalvar
+from core import globalvar
 from core.debug import Debug
 
 # cannot import from the core.utils module to avoid cross dependencies
 try:
     # intended to be used also outside this module
     import gettext
-    _ = gettext.translation('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale')).ugettext
+    _ = gettext.translation(
+        'grasswxpy',
+        os.path.join(
+            os.getenv("GISBASE"),
+            'locale')).ugettext
 except IOError:
     # using no translation silently
     def null_gettext(string):
@@ -63,38 +67,41 @@ except IOError:
 
 def DecodeString(string):
     """Decode string using system encoding
-    
+
     :param string: string to be decoded
-    
+
     :return: decoded string
     """
     if not string:
         return string
-    
+
     if _enc:
         Debug.msg(5, "DecodeString(): enc=%s" % _enc)
         return string.decode(_enc)
-    
+
     return string
 
+
 def EncodeString(string):
     """Return encoded string using system locales
-    
+
     :param string: string to be encoded
-    
+
     :return: encoded string
     """
     if not string:
         return string
-    
+
     if _enc:
         Debug.msg(5, "EncodeString(): enc=%s" % _enc)
         return string.encode(_enc)
-    
+
     return string
 
+
 class GError:
-    def __init__(self, message, parent = None, caption = None, showTraceback = True):
+
+    def __init__(self, message, parent=None, caption=None, showTraceback=True):
         """Show error message window
 
         :param message: error message
@@ -109,43 +116,49 @@ class GError:
         if exc_traceback:
             exception = traceback.format_exc()
             reason = exception.splitlines()[-1].split(':', 1)[-1].strip()
-        
+
         if Debug.GetLevel() > 0 and exc_traceback:
             sys.stderr.write(exception)
-        
+
         if showTraceback and exc_traceback:
-            wx.MessageBox(parent = parent,
-                          message = message + '\n\n%s: %s\n\n%s' % \
-                              (_('Reason'),
-                               reason, exception),
-                          caption = caption,
-                          style = style)
+            wx.MessageBox(parent=parent,
+                          message=message + '\n\n%s: %s\n\n%s' %
+                          (_('Reason'),
+                           reason, exception),
+                          caption=caption,
+                          style=style)
         else:
-            wx.MessageBox(parent = parent,
-                          message = message,
-                          caption = caption,
-                          style = style)
+            wx.MessageBox(parent=parent,
+                          message=message,
+                          caption=caption,
+                          style=style)
+
 
 class GWarning:
-    def __init__(self, message, parent = None):
+
+    def __init__(self, message, parent=None):
         caption = _('Warning')
         style = wx.OK | wx.ICON_WARNING | wx.CENTRE
-        wx.MessageBox(parent = parent,
-                      message = message,
-                      caption = caption,
-                      style = style)
-        
+        wx.MessageBox(parent=parent,
+                      message=message,
+                      caption=caption,
+                      style=style)
+
+
 class GMessage:
-    def __init__(self, message, parent = None):
+
+    def __init__(self, message, parent=None):
         caption = _('Message')
         style = wx.OK | wx.ICON_INFORMATION | wx.CENTRE
-        wx.MessageBox(parent = parent,
-                      message = message,
-                      caption = caption,
-                      style = style)
+        wx.MessageBox(parent=parent,
+                      message=message,
+                      caption=caption,
+                      style=style)
+
 
 class GException(Exception):
-    def __init__(self, value = ''):
+
+    def __init__(self, value=''):
         self.value = value
 
     def __str__(self):
@@ -154,8 +167,10 @@ class GException(Exception):
     def __unicode__(self):
         return self.value
 
+
 class Popen(subprocess.Popen):
     """Subclass subprocess.Popen"""
+
     def __init__(self, args, **kwargs):
         if subprocess.mswindows:
             args = map(EncodeString, args)
@@ -190,14 +205,14 @@ class Popen(subprocess.Popen):
                             args[i] = k + v
 
         subprocess.Popen.__init__(self, args, **kwargs)
-        
-    def recv(self, maxsize = None):
+
+    def recv(self, maxsize=None):
         return self._recv('stdout', maxsize)
-    
-    def recv_err(self, maxsize = None):
+
+    def recv_err(self, maxsize=None):
         return self._recv('stderr', maxsize)
 
-    def send_recv(self, input = '', maxsize = None):
+    def send_recv(self, input='', maxsize=None):
         return self.send(input), self.recv(maxsize), self.recv_err(maxsize)
 
     def get_conn_maxsize(self, which, maxsize):
@@ -206,7 +221,7 @@ class Popen(subprocess.Popen):
         elif maxsize < 1:
             maxsize = 1
         return getattr(self, which), maxsize
-    
+
     def _close(self, which):
         getattr(self, which).close()
         setattr(self, which, None)
@@ -219,7 +234,7 @@ class Popen(subprocess.Popen):
             return (0 != win32api.TerminateProcess(handle, 0))
         else:
             try:
-                os.kill(-self.pid, signal.SIGTERM) # kill whole group
+                os.kill(-self.pid, signal.SIGTERM)  # kill whole group
             except OSError:
                 pass
 
@@ -244,7 +259,7 @@ class Popen(subprocess.Popen):
             conn, maxsize = self.get_conn_maxsize(which, maxsize)
             if conn is None:
                 return None
-            
+
             try:
                 x = msvcrt.get_osfhandle(conn.fileno())
                 (read, nAvail, nMessage) = PeekNamedPipe(x, 0)
@@ -258,7 +273,7 @@ class Popen(subprocess.Popen):
                 if why[0] in (109, errno.ESHUTDOWN):
                     return self._close(which)
                 raise
-            
+
             if self.universal_newlines:
                 read = self._translate_newlines(read)
             return read
@@ -274,7 +289,7 @@ class Popen(subprocess.Popen):
             try:
                 written = os.write(self.stdin.fileno(), input)
             except OSError as why:
-                if why[0] == errno.EPIPE: #broken pipe
+                if why[0] == errno.EPIPE:  # broken pipe
                     return self._close('stdin')
                 raise
 
@@ -284,20 +299,20 @@ class Popen(subprocess.Popen):
             conn, maxsize = self.get_conn_maxsize(which, maxsize)
             if conn is None:
                 return None
-            
+
             flags = fcntl.fcntl(conn, fcntl.F_GETFL)
             if not conn.closed:
-                fcntl.fcntl(conn, fcntl.F_SETFL, flags| os.O_NONBLOCK)
-            
+                fcntl.fcntl(conn, fcntl.F_SETFL, flags | os.O_NONBLOCK)
+
             try:
                 if not select.select([conn], [], [], 0)[0]:
                     return ''
-                
+
                 r = conn.read(maxsize)
-                
+
                 if not r:
                     return self._close(which)
-    
+
                 if self.universal_newlines:
                     r = self._translate_newlines(r)
                 return r
@@ -307,10 +322,11 @@ class Popen(subprocess.Popen):
 
 message = "Other end disconnected!"
 
-def recv_some(p, t = .1, e = 1, tr = 5, stderr = 0):
+
+def recv_some(p, t=.1, e=1, tr=5, stderr=0):
     if tr < 1:
         tr = 1
-    x = time.time()+t
+    x = time.time() + t
     y = []
     r = ''
     pr = p.recv
@@ -326,9 +342,10 @@ def recv_some(p, t = .1, e = 1, tr = 5, stderr = 0):
         elif r:
             y.append(r)
         else:
-            time.sleep(max((x-time.time())/tr, 0))
+            time.sleep(max((x - time.time()) / tr, 0))
     return ''.join(y)
-    
+
+
 def send_all(p, data):
     while len(data):
         sent = p.send(data)
@@ -336,6 +353,7 @@ def send_all(p, data):
             raise Exception(message)
         data = buffer(data, sent)
 
+
 class Command:
     """Run command in separate thread. Used for commands launched
     on the background.
@@ -352,9 +370,10 @@ class Command:
         else:
             print 'FAILURE (%d)' % cmd.returncode
     """
-    def __init__ (self, cmd, stdin = None,
-                  verbose = None, wait = True, rerr = False,
-                  stdout = None, stderr = None):
+
+    def __init__(self, cmd, stdin=None,
+                 verbose=None, wait=True, rerr=False,
+                 stdout=None, stderr=None):
         """
         :param cmd: command given as list
         :param stdin: standard input stream
@@ -391,7 +410,7 @@ class Command:
         self.cmdThread = CommandThread(cmd, stdin,
                                        stdout, stderr)
         self.cmdThread.start()
-        
+
         if wait:
             self.cmdThread.join()
             if self.cmdThread.module:
@@ -404,33 +423,39 @@ class Command:
             self.returncode = None
 
         if self.returncode is not None:
-            Debug.msg (3, "Command(): cmd='%s', wait=%s, returncode=%d, alive=%s" % \
-                           (' '.join(cmd), wait, self.returncode, self.cmdThread.isAlive()))
+            Debug.msg(
+                3, "Command(): cmd='%s', wait=%s, returncode=%d, alive=%s" %
+                (' '.join(cmd), wait, self.returncode, self.cmdThread.isAlive()))
             if rerr is not None and self.returncode != 0:
-                if rerr is False: # GUI dialog
-                    raise GException("%s '%s'%s%s%s %s%s" % \
-                                         (_("Execution failed:"),
-                                          ' '.join(self.cmd),
-                                          os.linesep, os.linesep,
-                                          _("Details:"),
-                                          os.linesep,
-                                          _("Error: ") + self.__GetError()))
-                elif rerr == sys.stderr: # redirect message to sys
-                    stderr.write("Execution failed: '%s'" % (' '.join(self.cmd)))
-                    stderr.write("%sDetails:%s%s" % (os.linesep,
-                                                     _("Error: ") + self.__GetError(),
-                                                     os.linesep))
+                if rerr is False:  # GUI dialog
+                    raise GException("%s '%s'%s%s%s %s%s" %
+                                     (_("Execution failed:"),
+                                      ' '.join(self.cmd),
+                                      os.linesep, os.linesep,
+                                      _("Details:"),
+                                      os.linesep,
+                                      _("Error: ") + self.__GetError()))
+                elif rerr == sys.stderr:  # redirect message to sys
+                    stderr.write("Execution failed: '%s'" %
+                                 (' '.join(self.cmd)))
+                    stderr.write(
+                        "%sDetails:%s%s" %
+                        (os.linesep,
+                         _("Error: ") +
+                            self.__GetError(),
+                            os.linesep))
             else:
-                pass # nop
+                pass  # nop
         else:
-            Debug.msg (3, "Command(): cmd='%s', wait=%s, returncode=?, alive=%s" % \
-                           (' '.join(cmd), wait, self.cmdThread.isAlive()))
+            Debug.msg(
+                3, "Command(): cmd='%s', wait=%s, returncode=?, alive=%s" %
+                (' '.join(cmd), wait, self.cmdThread.isAlive()))
 
         if verbose_orig:
             os.environ["GRASS_VERBOSE"] = verbose_orig
         elif "GRASS_VERBOSE" in os.environ:
             del os.environ["GRASS_VERBOSE"]
-            
+
     def __ReadOutput(self, stream):
         """Read stream and return list of lines
 
@@ -449,7 +474,7 @@ class Command:
             lineList.append(line)
 
         return lineList
-                    
+
     def __ReadErrOutput(self):
         """Read standard error output and return list of lines"""
         return self.__ReadOutput(self.cmdThread.module.stderr)
@@ -465,27 +490,27 @@ class Command:
         else:
             lines = self.cmdThread.error.strip('%s' % os.linesep). \
                 split('%s' % os.linesep)
-        
+
         msg = []
 
-        type    = None
+        type = None
         content = ""
         for line in lines:
             if len(line) == 0:
                 continue
-            if 'GRASS_' in line: # error or warning
-                if 'GRASS_INFO_WARNING' in line: # warning
+            if 'GRASS_' in line:  # error or warning
+                if 'GRASS_INFO_WARNING' in line:  # warning
                     type = "WARNING"
-                elif 'GRASS_INFO_ERROR' in line: # error
+                elif 'GRASS_INFO_ERROR' in line:  # error
                     type = "ERROR"
-                elif 'GRASS_INFO_END': # end of message
+                elif 'GRASS_INFO_END':  # end of message
                     msg.append((type, content))
                     type = None
                     content = ""
-                
+
                 if type:
                     content += line.split(':', 1)[1].strip()
-            else: # stderr
+            else:  # stderr
                 msg.append((None, line.strip()))
 
         return msg
@@ -494,53 +519,55 @@ class Command:
         """Get error message or ''"""
         if not self.cmdThread.module:
             return _("Unable to exectute command: '%s'") % ' '.join(self.cmd)
-        
+
         for type, msg in self.__ProcessStdErr():
             if type == 'ERROR':
                 if _enc:
                     return unicode(msg, _enc)
                 return msg
-        
+
         return ''
-    
+
+
 class CommandThread(Thread):
     """Create separate thread for command. Used for commands launched
     on the background."""
-    def __init__ (self, cmd, env = None, stdin = None,
-                  stdout = sys.stdout, stderr = sys.stderr):
+
+    def __init__(self, cmd, env=None, stdin=None,
+                 stdout=sys.stdout, stderr=sys.stderr):
         """
         :param cmd: command (given as list)
         :param env: environmental variables
-        :param stdin: standard input stream 
+        :param stdin: standard input stream
         :param stdout: redirect standard output or None
         :param stderr: redirect standard error output or None
         """
         Thread.__init__(self)
-        
-        self.cmd    = cmd
-        self.stdin  = stdin
+
+        self.cmd = cmd
+        self.stdin = stdin
         self.stdout = stdout
         self.stderr = stderr
-        self.env    = env
-        
+        self.env = env
+
         self.module = None
-        self.error  = ''
-        
+        self.error = ''
+
         self._want_abort = False
         self.aborted = False
-        
+
         self.setDaemon(True)
-        
+
         # set message formatting
         self.message_format = os.getenv("GRASS_MESSAGE_FORMAT")
         os.environ["GRASS_MESSAGE_FORMAT"] = "gui"
-        
+
     def __del__(self):
         if self.message_format:
             os.environ["GRASS_MESSAGE_FORMAT"] = self.message_format
         else:
             del os.environ["GRASS_MESSAGE_FORMAT"]
-        
+
     def run(self):
         """Run command"""
         if len(self.cmd) == 0:
@@ -565,27 +592,27 @@ class CommandThread(Thread):
             args[0] = grass.get_real_command(args[0])
             if args[0].endswith('.py'):
                 args.insert(0, sys.executable)
- 
+
         try:
             self.module = Popen(args,
-                                stdin = subprocess.PIPE,
-                                stdout = subprocess.PIPE,
-                                stderr = subprocess.PIPE,
-                                shell = sys.platform == "win32",
-                                env = self.env)
-            
+                                stdin=subprocess.PIPE,
+                                stdout=subprocess.PIPE,
+                                stderr=subprocess.PIPE,
+                                shell=sys.platform == "win32",
+                                env=self.env)
+
         except OSError as e:
             self.error = str(e)
             print >> sys.stderr, e
             return 1
-        
-        if self.stdin: # read stdin if requested ...
+
+        if self.stdin:  # read stdin if requested ...
             self.module.stdin.write(self.stdin)
             self.module.stdin.close()
-            
+
         # redirect standard outputs...
         self._redirect_stream()
-        
+
     def _redirect_stream(self):
         """Redirect stream"""
         if self.stdout:
@@ -593,44 +620,45 @@ class CommandThread(Thread):
             out_fileno = self.module.stdout.fileno()
             if not subprocess.mswindows:
                 flags = fcntl.fcntl(out_fileno, fcntl.F_GETFL)
-                fcntl.fcntl(out_fileno, fcntl.F_SETFL, flags| os.O_NONBLOCK)
-                
+                fcntl.fcntl(out_fileno, fcntl.F_SETFL, flags | os.O_NONBLOCK)
+
         if self.stderr:
             # make module stdout/stderr non-blocking
             out_fileno = self.module.stderr.fileno()
             if not subprocess.mswindows:
                 flags = fcntl.fcntl(out_fileno, fcntl.F_GETFL)
-                fcntl.fcntl(out_fileno, fcntl.F_SETFL, flags| os.O_NONBLOCK)
-        
+                fcntl.fcntl(out_fileno, fcntl.F_SETFL, flags | os.O_NONBLOCK)
+
         # wait for the process to end, sucking in stuff until it does end
         while self.module.poll() is None:
-            if self._want_abort: # abort running process
+            if self._want_abort:  # abort running process
                 self.module.terminate()
                 self.aborted = True
-                return 
+                return
             if self.stdout:
-                line = recv_some(self.module, e = 0, stderr = 0)
+                line = recv_some(self.module, e=0, stderr=0)
                 self.stdout.write(line)
             if self.stderr:
-                line = recv_some(self.module, e = 0, stderr = 1)
+                line = recv_some(self.module, e=0, stderr=1)
                 self.stderr.write(line)
                 if len(line) > 0:
                     self.error = line
 
         # get the last output
         if self.stdout:
-            line = recv_some(self.module, e = 0, stderr = 0)
+            line = recv_some(self.module, e=0, stderr=0)
             self.stdout.write(line)
         if self.stderr:
-            line = recv_some(self.module, e = 0, stderr = 1)
+            line = recv_some(self.module, e=0, stderr=1)
             self.stderr.write(line)
             if len(line) > 0:
                 self.error = line
-            
+
     def abort(self):
         """Abort running process, used by main thread to signal an abort"""
         self._want_abort = True
-    
+
+
 def _formatMsg(text):
     """Format error messages for dialogs
     """
@@ -648,12 +676,13 @@ def _formatMsg(text):
             return message
         else:
             message += line.strip() + '\n'
-    
+
     return message
 
-def RunCommand(prog, flags = "", overwrite = False, quiet = False,
-               verbose = False, parent = None, read = False,
-               parse = None, stdin = None, getErrorMsg = False, **kwargs):
+
+def RunCommand(prog, flags="", overwrite=False, quiet=False,
+               verbose=False, parent=None, read=False,
+               parse=None, stdin=None, getErrorMsg=False, **kwargs):
     """Run GRASS command
 
     :param prog: program to run
@@ -665,7 +694,7 @@ def RunCommand(prog, flags = "", overwrite = False, quiet = False,
     :param stdin: stdin or None
     :param getErrorMsg: get error messages on failure
     :param kwargs: program parameters
-    
+
     :return: returncode (read == False and getErrorMsg == False)
     :return: returncode, messages (read == False and getErrorMsg == True)
     :return: stdout (read == True and getErrorMsg == False)
@@ -674,50 +703,50 @@ def RunCommand(prog, flags = "", overwrite = False, quiet = False,
     """
     cmdString = ' '.join(grass.make_command(prog, flags, overwrite,
                                             quiet, verbose, **kwargs))
-    
+
     Debug.msg(1, "gcmd.RunCommand(): %s" % cmdString)
-    
+
     kwargs['stderr'] = subprocess.PIPE
-    
+
     if read:
         kwargs['stdout'] = subprocess.PIPE
-    
+
     if stdin:
         kwargs['stdin'] = subprocess.PIPE
 
     if parent:
         messageFormat = os.getenv('GRASS_MESSAGE_FORMAT', 'gui')
         os.environ['GRASS_MESSAGE_FORMAT'] = 'standard'
-    
+
     start = time.time()
-    
+
     ps = grass.start_command(prog, flags, overwrite, quiet, verbose, **kwargs)
-    
+
     if stdin:
         ps.stdin.write(stdin)
         ps.stdin.close()
         ps.stdin = None
-    
+
     stdout, stderr = map(DecodeString, ps.communicate())
-    
-    if parent: # restore previous settings
+
+    if parent:  # restore previous settings
         os.environ['GRASS_MESSAGE_FORMAT'] = messageFormat
-    
+
     ret = ps.returncode
-    Debug.msg(1, "gcmd.RunCommand(): get return code %d (%.6f sec)" % \
-                  (ret, (time.time() - start)))
-    
+    Debug.msg(1, "gcmd.RunCommand(): get return code %d (%.6f sec)" %
+              (ret, (time.time() - start)))
+
     if ret != 0:
         if stderr:
             Debug.msg(2, "gcmd.RunCommand(): error %s" % stderr)
         else:
             Debug.msg(2, "gcmd.RunCommand(): nothing to print ???")
-        
+
         if parent:
-            GError(parent = parent,
-                   caption = _("Error in %s") % prog,
-                   message = stderr)
-    
+            GError(parent=parent,
+                   caption=_("Error in %s") % prog,
+                   message=stderr)
+
     if not read:
         if not getErrorMsg:
             return ret
@@ -728,21 +757,22 @@ def RunCommand(prog, flags = "", overwrite = False, quiet = False,
         Debug.msg(3, "gcmd.RunCommand(): return stdout\n'%s'" % stdout)
     else:
         Debug.msg(3, "gcmd.RunCommand(): return stdout = None")
-    
+
     if parse:
         stdout = parse(stdout)
-    
+
     if not getErrorMsg:
         return stdout
-    
+
     if read and getErrorMsg:
         return ret, stdout, _formatMsg(stderr)
-    
+
     return stdout, _formatMsg(stderr)
 
-def GetDefaultEncoding(forceUTF8 = False):
+
+def GetDefaultEncoding(forceUTF8=False):
     """Get default system encoding
-    
+
     :param bool forceUTF8: force 'UTF-8' if encoding is not defined
 
     :return: system encoding (can be None)
@@ -750,8 +780,8 @@ def GetDefaultEncoding(forceUTF8 = False):
     enc = locale.getdefaultlocale()[1]
     if forceUTF8 and (enc is None or enc == 'UTF8'):
         return 'UTF-8'
-    
+
     Debug.msg(1, "GetSystemEncoding(): %s" % enc)
     return enc
 
-_enc = GetDefaultEncoding() # define as global variable
+_enc = GetDefaultEncoding()  # define as global variable

+ 65 - 41
gui/wxpython/core/gconsole.py

@@ -33,7 +33,7 @@ import wx
 from wx.lib.newevent import NewEvent
 
 import grass.script as grass
-from   grass.script import task as gtask
+from grass.script import task as gtask
 
 from grass.pydispatch.signal import Signal
 
@@ -116,7 +116,8 @@ class CmdThread(threading.Thread):
         os.environ['GRASS_MESSAGE_FORMAT'] = 'gui'
         while True:
             requestId, args, kwds = self.requestQ.get()
-            for key in ('callable', 'onDone', 'onPrepare', 'userData', 'addLayer', 'notification'):
+            for key in ('callable', 'onDone', 'onPrepare',
+                        'userData', 'addLayer', 'notification'):
                 if key in kwds:
                     vars()[key] = kwds[key]
                     del kwds[key]
@@ -191,7 +192,8 @@ class CmdThread(threading.Thread):
                     argsColor[0] = ['r.colors',
                                     'map=%s' % mapName,
                                     'color=%s' % colorTable]
-                    self.requestCmdColor = vars()['callable'](*argsColor, **kwds)
+                    self.requestCmdColor = vars()['callable'](
+                        *argsColor, **kwds)
                     self.resultQ.put((requestId, self.requestCmdColor.run()))
 
             if self.receiver:
@@ -217,6 +219,7 @@ class CmdThread(threading.Thread):
         if self.requestQ.empty():
             self._want_abort_all = False
 
+
 class GStdout:
     """GConsole standard output
 
@@ -228,6 +231,7 @@ class GStdout:
     Copyright: (c) 2005-2007 Jean-Michel Fauth
     Licence:   GPL
     """
+
     def __init__(self, receiver):
         """
         :param receiver: event receiver (used in PostEvent)
@@ -261,6 +265,7 @@ class GStderr:
     Copyright: (c) 2005-2007 Jean-Michel Fauth
     Licence:   GPL
     """
+
     def __init__(self, receiver):
         """
         :param receiver: event receiver (used in PostEvent)
@@ -334,6 +339,7 @@ gIgnoredCmdRun, EVT_IGNORED_CMD_RUN = NewEvent()
 class GConsole(wx.EvtHandler):
     """
     """
+
     def __init__(self, guiparent=None, giface=None, ignoredCmdPattern=None):
         """
         :param guiparent: parent window for created GUI objects
@@ -404,9 +410,10 @@ class GConsole(wx.EvtHandler):
         :param notification: form of notification
         """
         self.writeLog.emit(text=text, wrap=wrap,
-                          notification=notification)
+                           notification=notification)
 
-    def WriteCmdLog(self, text, pid=None, notification=Notification.MAKE_VISIBLE):
+    def WriteCmdLog(self, text, pid=None,
+                    notification=Notification.MAKE_VISIBLE):
         """Write message in selected style
 
         :param text: message to be printed
@@ -456,17 +463,17 @@ class GConsole(wx.EvtHandler):
 
         # update history file
         self.UpdateHistoryFile(' '.join(command))
-        
+
         if command[0] in globalvar.grassCmd:
             # send GRASS command without arguments to GUI command interface
             # except ignored commands (event is emitted)
             if self._ignoredCmdPattern and \
-              re.compile(self._ignoredCmdPattern).search(' '.join(command)) and \
-              '--help' not in command and '--ui' not in command:
+                    re.compile(self._ignoredCmdPattern).search(' '.join(command)) and \
+                    '--help' not in command and '--ui' not in command:
                 event = gIgnoredCmdRun(cmd=command)
                 wx.PostEvent(self, event)
                 return
-            
+
             else:
                 # other GRASS commands (r|v|g|...)
                 try:
@@ -487,11 +494,16 @@ class GConsole(wx.EvtHandler):
                                 p.get('element', '') == 'file' and \
                                 p.get('age', 'new') == 'old' and \
                                 p.get('value', '') == '-':
-                            GError(parent=self._guiparent,
-                                   message=_("Unable to run command:\n%(cmd)s\n\n"
-                                             "Option <%(opt)s>: read from standard input is not "
-                                             "supported by wxGUI") % {'cmd': ' '.join(command),
-                                                                      'opt': p.get('name', '')})
+                            GError(
+                                parent=self._guiparent,
+                                message=_(
+                                    "Unable to run command:\n%(cmd)s\n\n"
+                                    "Option <%(opt)s>: read from standard input is not "
+                                    "supported by wxGUI") % {
+                                    'cmd': ' '.join(command),
+                                    'opt': p.get(
+                                        'name',
+                                        '')})
                             return
 
                 if len(command) == 1:
@@ -501,27 +513,33 @@ class GConsole(wx.EvtHandler):
                         pyFile = command[0]
                         if sys.platform == 'win32':
                             pyFile += '.py'
-                        pyPath = os.path.join(os.environ['GISBASE'], 'scripts', pyFile)
+                        pyPath = os.path.join(
+                            os.environ['GISBASE'], 'scripts', pyFile)
                         if not os.path.exists(pyPath):
-                            pyPath = os.path.join(os.environ['GRASS_ADDON_BASE'], 'scripts', pyFile)
+                            pyPath = os.path.join(
+                                os.environ['GRASS_ADDON_BASE'], 'scripts', pyFile)
                         if not os.path.exists(pyPath):
-                            GError(parent=self._guiparent,
-                                   message=_("Module <%s> not found.") % command[0])
-                        pymodule = imp.load_source(command[0].replace('.', '_'), pyPath)
+                            GError(
+                                parent=self._guiparent,
+                                message=_("Module <%s> not found.") %
+                                command[0])
+                        pymodule = imp.load_source(
+                            command[0].replace('.', '_'), pyPath)
                         pymain = inspect.getargspec(pymodule.main)
                         if pymain and 'giface' in pymain.args:
                             pymodule.main(self._giface)
                             return
-                    
+
                     if hasParams and command[0] != 'v.krige':
                         # no arguments given
                         try:
-                            GUI(parent=self._guiparent, giface=self._giface).ParseCommand(command)
+                            GUI(parent=self._guiparent,
+                                giface=self._giface).ParseCommand(command)
                         except GException as e:
                             print >> sys.stderr, e
-                        
+
                         return
-                
+
                 # activate computational region (set with g.region)
                 # for all non-display commands.
                 if compReg:
@@ -539,7 +557,8 @@ class GConsole(wx.EvtHandler):
                                       notification=notification)
                 self.cmdOutputTimer.Start(50)
 
-                # deactivate computational region and return to display settings
+                # deactivate computational region and return to display
+                # settings
                 if compReg and tmpreg:
                     os.environ["GRASS_REGION"] = tmpreg
         else:
@@ -569,7 +588,7 @@ class GConsole(wx.EvtHandler):
                     sfile.close()
                 except IOError:
                     pass
-            
+
             if len(command) == 1 and not skipInterface:
                 try:
                     task = gtask.parse_interface(command[0])
@@ -580,7 +599,8 @@ class GConsole(wx.EvtHandler):
 
             if task:
                 # process GRASS command without argument
-                GUI(parent=self._guiparent, giface=self._giface).ParseCommand(command)
+                GUI(parent=self._guiparent,
+                    giface=self._giface).ParseCommand(command)
             else:
                 self.cmdThread.RunCmd(command,
                                       stdout=self.cmdStdOut,
@@ -631,8 +651,8 @@ class GConsole(wx.EvtHandler):
                 stime = _("%d sec") % int(ctime)
             else:
                 mtime = int(ctime / 60)
-                stime = _("%(min)d min %(sec)d sec") % {'min': mtime,
-                                                        'sec': int(ctime - (mtime * 60))}
+                stime = _("%(min)d min %(sec)d sec") % {
+                    'min': mtime, 'sec': int(ctime - (mtime * 60))}
         except KeyError:
             # stopped deamon
             stime = _("unknown")
@@ -676,14 +696,17 @@ class GConsole(wx.EvtHandler):
         name = task.get_name()
         for p in task.get_options()['params']:
             prompt = p.get('prompt', '')
-            if prompt in ('raster', 'vector', 'raster_3d') and p.get('value', None):
-                if p.get('age', 'old') == 'new' or \
-                        name in ('r.colors', 'r3.colors', 'v.colors', 'v.proj', 'r.proj'):
+            if prompt in (
+                    'raster', 'vector', 'raster_3d') and p.get(
+                    'value', None):
+                if p.get('age', 'old') == 'new' or name in (
+                        'r.colors', 'r3.colors', 'v.colors', 'v.proj', 'r.proj'):
                     # if multiple maps (e.g. r.series.interp), we need add each
                     if p.get('multiple', False):
                         lnames = p.get('value').split(',')
                         # in case multiple input (old) maps in r.colors
-                        # we don't want to rerender it multiple times! just once
+                        # we don't want to rerender it multiple times! just
+                        # once
                         if p.get('age', 'old') == 'old':
                             lnames = lnames[0:1]
                     else:
@@ -691,11 +714,13 @@ class GConsole(wx.EvtHandler):
                     for lname in lnames:
                         if '@' not in lname:
                             lname += '@' + grass.gisenv()['MAPSET']
-                        if grass.find_file(lname, element=p.get('element'))['fullname']:
-                            self.mapCreated.emit(name=lname, ltype=prompt, add=event.addLayer)
+                        if grass.find_file(lname, element=p.get('element'))[
+                                'fullname']:
+                            self.mapCreated.emit(
+                                name=lname, ltype=prompt, add=event.addLayer)
         if name == 'r.mask':
             self.updateMap.emit()
-        
+
         event.Skip()
 
     def OnProcessPendingOutputWindowEvents(self, event):
@@ -703,7 +728,7 @@ class GConsole(wx.EvtHandler):
 
     def UpdateHistoryFile(self, command):
         """Update history file
-        
+
         :param command: the command given as a string
         """
         env = grass.gisenv()
@@ -714,17 +739,16 @@ class GConsole(wx.EvtHandler):
                                     '.bash_history')
             fileHistory = codecs.open(filePath, encoding='utf-8', mode='a')
         except IOError as e:
-            GError(_("Unable to write file '%(filePath)s'.\n\nDetails: %(error)s") % 
-                    {'filePath': filePath, 'error': e},
+            GError(_("Unable to write file '%(filePath)s'.\n\nDetails: %(error)s") %
+                   {'filePath': filePath, 'error': e},
                    parent=self._guiparent)
             return
-        
+
         try:
             fileHistory.write(command + os.linesep)
         finally:
             fileHistory.close()
-        
+
         # update wxGUI prompt
         if self._giface:
             self._giface.UpdateCmdHistory(command)
-        

+ 20 - 8
gui/wxpython/core/giface.py

@@ -23,7 +23,7 @@ import grass.script as grass
 from grass.pydispatch.signal import Signal
 
 # to disable Abstract class not referenced
-#pylint: disable=R0921
+# pylint: disable=R0921
 
 
 class Notification:
@@ -51,6 +51,7 @@ class Layer(object):
 
 
 class LayerList(object):
+
     def GetSelectedLayers(self, checkedOnly=True):
         """Returns list of selected layers.
 
@@ -116,6 +117,7 @@ class GrassInterface:
 
         The GrassInterface process is not finished.
     """
+
     def RunCmd(self, *args, **kwargs):
         """Executes a command.
         """
@@ -131,7 +133,8 @@ class GrassInterface:
         """
         raise NotImplementedError()
 
-    def WriteCmdLog(self, text, pid=None, notification=Notification.MAKE_VISIBLE):
+    def WriteCmdLog(self, text, pid=None,
+                    notification=Notification.MAKE_VISIBLE):
         """Writes message related to start or end of the command.
         """
         raise NotImplementedError()
@@ -202,6 +205,7 @@ class GrassInterface:
 
 class StandaloneGrassInterface():
     """@implements GrassInterface"""
+
     def __init__(self):
 
         # Signal when some map is created or updated by a module.
@@ -242,11 +246,18 @@ class StandaloneGrassInterface():
         grass.percent(event.value, 100, 1)
         event.Skip()
 
-    def RunCmd(self, command, compReg=True, skipInterface=False,
-               onDone=None, onPrepare=None, userData=None, notification=Notification.MAKE_VISIBLE):
-        self._gconsole.RunCmd(command=command, compReg=compReg,
-                              skipInterface=skipInterface, onDone=onDone,
-                              onPrepare=onPrepare, userData=userData, notification=notification)
+    def RunCmd(
+            self, command, compReg=True, skipInterface=False, onDone=None,
+            onPrepare=None, userData=None,
+            notification=Notification.MAKE_VISIBLE):
+        self._gconsole.RunCmd(
+            command=command,
+            compReg=compReg,
+            skipInterface=skipInterface,
+            onDone=onDone,
+            onPrepare=onPrepare,
+            userData=userData,
+            notification=notification)
 
     def Help(self, entry):
         self._gconsole.RunCmd(['g.manual', 'entry=%s' % entry])
@@ -255,7 +266,8 @@ class StandaloneGrassInterface():
                  notification=Notification.HIGHLIGHT):
         self._write(grass.message, text)
 
-    def WriteCmdLog(self, text, pid=None, notification=Notification.MAKE_VISIBLE):
+    def WriteCmdLog(self, text, pid=None,
+                    notification=Notification.MAKE_VISIBLE):
         if pid:
             text = '(' + str(pid) + ') ' + text
         self._write(grass.message, text)

+ 27 - 18
gui/wxpython/core/globalvar.py

@@ -19,12 +19,12 @@ if not os.getenv("GISBASE"):
     sys.exit("GRASS is not running. Exiting...")
 
 # path to python scripts
-ETCDIR   = os.path.join(os.getenv("GISBASE"), "etc")
-GUIDIR   = os.path.join(os.getenv("GISBASE"), "gui")
+ETCDIR = os.path.join(os.getenv("GISBASE"), "etc")
+GUIDIR = os.path.join(os.getenv("GISBASE"), "gui")
 WXGUIDIR = os.path.join(GUIDIR, "wxpython")
-ICONDIR  = os.path.join(GUIDIR, "icons")
-IMGDIR   = os.path.join(GUIDIR, "images")
-SYMBDIR  = os.path.join(IMGDIR, "symbols")
+ICONDIR = os.path.join(GUIDIR, "icons")
+IMGDIR = os.path.join(GUIDIR, "images")
+SYMBDIR = os.path.join(IMGDIR, "symbols")
 
 from core.debug import Debug
 
@@ -32,7 +32,11 @@ from core.debug import Debug
 try:
     # intended to be used also outside this module
     import gettext
-    _ = gettext.translation('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale')).ugettext
+    _ = gettext.translation(
+        'grasswxpy',
+        os.path.join(
+            os.getenv("GISBASE"),
+            'locale')).ugettext
 except IOError:
     # using no translation silently
     def null_gettext(string):
@@ -41,6 +45,7 @@ except IOError:
 
 from grass.script.core import get_commands
 
+
 def CheckWxVersion(version):
     """Check wx version"""
     ver = wx.__version__
@@ -49,7 +54,8 @@ def CheckWxVersion(version):
 
     return True
 
-def CheckForWx(forceVersion = os.getenv('GRASS_WXVERSION', None)):
+
+def CheckForWx(forceVersion=os.getenv('GRASS_WXVERSION', None)):
     """Try to import wx module and check its version
 
     :param forceVersion: force wxPython version, eg. '2.8'
@@ -70,14 +76,16 @@ def CheckForWx(forceVersion = os.getenv('GRASS_WXVERSION', None)):
         version = wx.__version__
 
         if map(int, version.split('.')) < minVersion:
-            raise ValueError('Your wxPython version is %s.%s.%s.%s' % tuple(version.split('.')))
+            raise ValueError(
+                'Your wxPython version is %s.%s.%s.%s' %
+                tuple(version.split('.')))
 
     except ImportError as e:
         print >> sys.stderr, 'ERROR: wxGUI requires wxPython. %s' % str(e)
         sys.exit(1)
     except (ValueError, wxversion.VersionError) as e:
-        print >> sys.stderr, 'ERROR: wxGUI requires wxPython >= %d.%d.%d.%d. ' % tuple(minVersion) + \
-            '%s.' % (str(e))
+        print >> sys.stderr, 'ERROR: wxGUI requires wxPython >= %d.%d.%d.%d. ' % tuple(
+            minVersion) + '%s.' % (str(e))
         sys.exit(1)
     except locale.Error as e:
         print >> sys.stderr, "Unable to set locale:", e
@@ -106,7 +114,7 @@ FNPageDStyle = FN.FNB_FANCY_TABS | \
     FN.FNB_NO_NAV_BUTTONS | \
     FN.FNB_NO_X_BUTTON
 
-FNPageColor = wx.Colour(125,200,175)
+FNPageColor = wx.Colour(125, 200, 175)
 
 """Dialog widget dimension"""
 DIALOG_SPIN_SIZE = (150, -1)
@@ -140,7 +148,7 @@ else:
     BIN_EXT = SCT_EXT = ''
 
 
-def UpdateGRASSAddOnCommands(eList = None):
+def UpdateGRASSAddOnCommands(eList=None):
     """Update list of available GRASS AddOns commands to use when
     parsing string from the command line
 
@@ -155,7 +163,7 @@ def UpdateGRASSAddOnCommands(eList = None):
         addonPath += os.pathsep + os.path.join(addonBase, 'bin')
         if sys.platform != 'win32':
             addonPath += os.pathsep + os.path.join(addonBase, 'scripts')
-    
+
     # remove commands first
     if eList:
         for ext in eList:
@@ -168,15 +176,15 @@ def UpdateGRASSAddOnCommands(eList = None):
     for path in addonPath.split(os.pathsep):
         if not os.path.exists(path) or not os.path.isdir(path):
             continue
-        
+
         # check if addon is in the path
         if pathList and path not in pathList:
             os.environ['PATH'] = path + os.pathsep + os.environ['PATH']
-        
+
         for fname in os.listdir(path):
             if fname in ['docs', 'modules.xml']:
                 continue
-            if grassScripts: # win32
+            if grassScripts:  # win32
                 name, ext = os.path.splitext(fname)
                 if name not in grassCmd:
                     if ext not in [BIN_EXT, SCT_EXT]:
@@ -194,7 +202,7 @@ def UpdateGRASSAddOnCommands(eList = None):
                     grassCmd.add(fname)
                     Debug.msg(3, "AddOn commands: %s", fname)
                     nCmd += 1
-    
+
     Debug.msg(1, "Number of GRASS AddOn commands: %d", nCmd)
 
 """@brief Collected GRASS-relared binaries/scripts"""
@@ -210,4 +218,5 @@ hasAgw = CheckWxVersion([2, 8, 11, 0])
 wxPython3 = CheckWxVersion([3, 0, 0, 0])
 
 """@Add GUIDIR/scripts into path"""
-os.environ['PATH'] = os.path.join(GUIDIR, 'scripts') + os.pathsep + os.environ['PATH']
+os.environ['PATH'] = os.path.join(
+    GUIDIR, 'scripts') + os.pathsep + os.environ['PATH']

+ 5 - 4
gui/wxpython/core/gthread.py

@@ -23,6 +23,7 @@ import Queue
 
 from core.gconsole import EVT_CMD_DONE, wxCmdDone
 
+
 class gThread(threading.Thread, wx.EvtHandler):
     """Thread for various backends"""
     requestId = 0
@@ -65,8 +66,8 @@ class gThread(threading.Thread, wx.EvtHandler):
         return gThread.requestId
 
     def GetId(self):
-         """Get id for next command"""
-         return gThread.requestId + 1
+        """Get id for next command"""
+        return gThread.requestId + 1
 
     def SetId(self, id):
         """Set starting id"""
@@ -95,14 +96,14 @@ class gThread(threading.Thread, wx.EvtHandler):
 
             if self.terminate:
                 return
-            #except Exception as e:
+            # except Exception as e:
             #    exception  = e;
 
             self.resultQ.put((requestId, ret))
 
             event = wxCmdDone(ondone=vars()['ondone'],
                               kwds=kwds,
-                              args=args, #TODO expand args to kwds
+                              args=args,  # TODO expand args to kwds
                               ret=ret,
                               exception=exception,
                               userdata=vars()['userdata'],

+ 20 - 7
gui/wxpython/core/layerlist.py

@@ -27,6 +27,7 @@ class LayerList(object):
     a non GUI class (e.g. named LayerTree) which includes this API,
     should be used for Layer Manager.
     """
+
     def __init__(self):
         self._list = []
 
@@ -179,6 +180,7 @@ class Layer(object):
         ...
         ValueError: Map <blablabla> not found.
     """
+
     def __init__(self):
         self._mapType = None
         self._name = None
@@ -209,14 +211,20 @@ class Layer(object):
         """
         if not self.hidden:
             fullName = name.split('@')
-            if len(fullName) == 1 and self._mapType != 'rgb':  # skip checking rgb maps for now
+            if len(
+                    fullName) == 1 and self._mapType != 'rgb':  # skip checking rgb maps for now
                 if self._mapType is None:
-                    raise ValueError("To set layer name, the type of layer must be specified.")
+                    raise ValueError(
+                        "To set layer name, the type of layer must be specified.")
 
-                res = gcore.find_file(name=fullName,
-                                      element=self._internalTypes[self._mapType])
+                res = gcore.find_file(
+                    name=fullName,
+                    element=self._internalTypes[
+                        self._mapType])
                 if not res['mapset']:
-                    raise ValueError("Map <{name}> not found.".format(name=name))
+                    raise ValueError(
+                        "Map <{name}> not found.".format(
+                            name=name))
                 self._name = name + '@' + res['mapset']
             else:
                 self._name = name
@@ -249,7 +257,9 @@ class Layer(object):
         :param mapType: can be 'raster', 'vector', 'raster_3d'
         """
         if mapType not in self._mapTypes:
-            raise ValueError("Wrong map type used: {mtype}".format(mtype=mapType))
+            raise ValueError(
+                "Wrong map type used: {mtype}".format(
+                    mtype=mapType))
 
         self._mapType = mapType
 
@@ -268,7 +278,9 @@ class Layer(object):
         :param float opacity: value between 0 and 1
         """
         if not (0 <= opacity <= 1):
-            raise ValueError("Opacity value must be between 0 and 1, not {op}.".format(op=opacity))
+            raise ValueError(
+                "Opacity value must be between 0 and 1, not {op}.".format(
+                    op=opacity))
         self._opacity = opacity
 
     opacity = property(fget=GetOpacity, fset=SetOpacity)
@@ -302,6 +314,7 @@ class Layer(object):
 
 class LayerListToRendererConverter:
     """Help class for converting LayerList layers into renderer list (Map)"""
+
     def __init__(self, renderer):
         """
 

+ 37 - 24
gui/wxpython/core/menutree.py

@@ -37,9 +37,9 @@ import os
 import sys
 import copy
 try:
-    import xml.etree.ElementTree   as etree
+    import xml.etree.ElementTree as etree
 except ImportError:
-    import elementtree.ElementTree as etree # Python <= 2.4
+    import elementtree.ElementTree as etree  # Python <= 2.4
 
 import wx
 
@@ -55,11 +55,12 @@ if not os.getenv("GISBASE"):
 # TODO: change the system to remove strange derived classes
 class MenuTreeModelBuilder:
     """Abstract menu data class"""
+
     def __init__(self, filename, expandAddons=True):
 
-        self.menustyle = UserSettings.Get(group = 'appearance',
-                                          key = 'menustyle',
-                                          subkey = 'selection')
+        self.menustyle = UserSettings.Get(group='appearance',
+                                          key='menustyle',
+                                          subkey='selection')
 
         xmlTree = etree.parse(filename)
         if expandAddons:
@@ -89,14 +90,14 @@ class MenuTreeModelBuilder:
             self.model.AppendNode(parent=node, label='', data=data)
         elif item.tag == 'menuitem':
             origLabel = _(item.find('label').text)
-            handler  = item.find('handler').text
-            desc     = item.find('help')  # optional
-            gcmd     = item.find('command')  # optional
-            keywords = item.find('keywords') # optional
-            shortcut = item.find('shortcut') # optional
-            wxId     = item.find('id')       # optional
-            icon     = item.find('icon')     # optional
-            if gcmd != None:
+            handler = item.find('handler').text
+            desc = item.find('help')  # optional
+            gcmd = item.find('command')  # optional
+            keywords = item.find('keywords')  # optional
+            shortcut = item.find('shortcut')  # optional
+            wxId = item.find('id')       # optional
+            icon = item.find('icon')     # optional
+            if gcmd is not None:
                 gcmd = gcmd.text
             else:
                 gcmd = ""
@@ -106,17 +107,17 @@ class MenuTreeModelBuilder:
                 desc = ""
             if keywords is None or keywords.text is None:
                 keywords = ""
-            else:            
+            else:
                 keywords = keywords.text
-            if shortcut != None:
+            if shortcut is not None:
                 shortcut = shortcut.text
             else:
                 shortcut = ""
-            if wxId != None:
+            if wxId is not None:
                 wxId = eval('wx.' + wxId.text)
             else:
                 wxId = wx.ID_ANY
-            if icon != None:
+            if icon is not None:
                 icon = icon.text
             else:
                 icon = ''
@@ -126,8 +127,15 @@ class MenuTreeModelBuilder:
                     label += '   [' + gcmd + ']'
                 elif self.menustyle == 2:
                     label = '      [' + gcmd + ']'
-            data = dict(label=origLabel, description=desc, handler=handler,
-                        command=gcmd, keywords=keywords, shortcut=shortcut, wxId=wxId, icon=icon)
+            data = dict(
+                label=origLabel,
+                description=desc,
+                handler=handler,
+                command=gcmd,
+                keywords=keywords,
+                shortcut=shortcut,
+                wxId=wxId,
+                icon=icon)
             self.model.AppendNode(parent=node, label=label, data=data)
         elif item.tag == 'menu':
             self._createMenu(item, node)
@@ -163,6 +171,7 @@ class MenuTreeModelBuilder:
     def PrintCommands(self, fh):
         printCommands(self.model.root, fh, itemSep=' | ', menuSep=' > ')
 
+
 def removeSeparators(model, node=None):
     if not node:
         node = model.root
@@ -172,6 +181,7 @@ def removeSeparators(model, node=None):
     else:
         model.RemoveNode(node)
 
+
 def printTree(node, fh, indent=0):
     if not node.label:
         return
@@ -180,6 +190,7 @@ def printTree(node, fh, indent=0):
     for child in node.children:
         printTree(node=child, fh=fh, indent=indent + 2)
 
+
 def printStrings(node, fh):
     # node.label  - with module in brackets
     # node.data['label'] - without module in brackets
@@ -193,6 +204,7 @@ def printStrings(node, fh):
     for child in node.children:
         printStrings(node=child, fh=fh)
 
+
 def printCommands(node, fh, itemSep, menuSep):
 
     def collectParents(node, parents):
@@ -217,21 +229,22 @@ def printCommands(node, fh, itemSep, menuSep):
 if __name__ == "__main__":
 
     action = 'strings'
-    menu   = 'manager'
+    menu = 'manager'
 
     for arg in sys.argv:
         if arg in ('strings', 'tree', 'commands', 'dump'):
-            action =  arg
+            action = arg
         elif arg in ('manager', 'module_tree', 'modeler', 'psmap'):
             menu = arg
 
     # FIXME: cross-dependencies
     if menu == 'manager':
-        from lmgr.menudata     import LayerManagerMenuData
-        from core.globalvar    import WXGUIDIR
+        from lmgr.menudata import LayerManagerMenuData
+        from core.globalvar import WXGUIDIR
         filename = os.path.join(WXGUIDIR, 'xml', 'menudata.xml')
         menudata = LayerManagerMenuData(filename)
-    # FIXME: since module descriptions are used again we have now the third copy of the same string (one is in modules)
+    # FIXME: since module descriptions are used again we have now the third
+    # copy of the same string (one is in modules)
     elif menu == 'module_tree':
         from lmgr.menudata import LayerManagerModuleTree
         from core.globalvar import WXGUIDIR

File diff ditekan karena terlalu besar
+ 276 - 230
gui/wxpython/core/render.py


File diff ditekan karena terlalu besar
+ 753 - 701
gui/wxpython/core/settings.py


+ 53 - 27
gui/wxpython/core/toolboxes.py

@@ -44,9 +44,9 @@ WXGUIDIR = os.path.join(os.getenv("GISBASE"), "gui", "wxpython")
 
 
 # this could be placed to functions
-mainMenuFile    = os.path.join(WXGUIDIR, 'xml', 'main_menu.xml')
-toolboxesFile   = os.path.join(WXGUIDIR, 'xml', 'toolboxes.xml')
-wxguiItemsFile  = os.path.join(WXGUIDIR, 'xml', 'wxgui_items.xml')
+mainMenuFile = os.path.join(WXGUIDIR, 'xml', 'main_menu.xml')
+toolboxesFile = os.path.join(WXGUIDIR, 'xml', 'toolboxes.xml')
+wxguiItemsFile = os.path.join(WXGUIDIR, 'xml', 'wxgui_items.xml')
 moduleItemsFile = os.path.join(WXGUIDIR, 'xml', 'module_items.xml')
 
 
@@ -62,15 +62,20 @@ def GetSettingsPath():
         # (these files are always check for existence here)
         return ""
 
+
 def _getUserToolboxesFile():
-    userToolboxesFile = os.path.join(GetSettingsPath(), 'toolboxes', 'toolboxes.xml')
+    userToolboxesFile = os.path.join(
+        GetSettingsPath(),
+        'toolboxes', 'toolboxes.xml')
     if not os.path.exists(userToolboxesFile):
         userToolboxesFile = None
     return userToolboxesFile
 
 
 def _getUserMainMenuFile():
-    userMainMenuFile = os.path.join(GetSettingsPath(), 'toolboxes', 'main_menu.xml')
+    userMainMenuFile = os.path.join(
+        GetSettingsPath(),
+        'toolboxes', 'main_menu.xml')
     if not os.path.exists(userMainMenuFile):
         userMainMenuFile = None
     return userMainMenuFile
@@ -144,7 +149,10 @@ def getMenudataFile(userRootFile, newFile, fallback):
     If something goes wrong during building or user doesn't modify menu,
     default file (from distribution) is returned.
     """
-    _debug(1, "toolboxes.getMenudataFile: {userRootFile}, {newFile}, {fallback}".format(**locals()))
+    _debug(
+        1,
+        "toolboxes.getMenudataFile: {userRootFile}, {newFile}, {fallback}".format(
+            **locals()))
 
     distributionRootFile = os.path.join(WXGUIDIR, 'xml', userRootFile)
     userRootFile = os.path.join(GetSettingsPath(), 'toolboxes', userRootFile)
@@ -164,23 +172,29 @@ def getMenudataFile(userRootFile, newFile, fallback):
             # remove menu file when there is no main_menu and toolboxes
             if not _getUserToolboxesFile() and not userRootFile:
                 os.remove(menudataFile)
-                _debug(2, "toolboxes.getMenudataFile: no user defined files, menudata deleted")
+                _debug(
+                    2, "toolboxes.getMenudataFile: no user defined files, menudata deleted")
                 return fallback
 
             if bool(_getUserToolboxesFile()) != bool(userRootFile):
-                # always generate new because we don't know if there has been any change
+                # always generate new because we don't know if there has been
+                # any change
                 generateNew = True
-                _debug(2, "toolboxes.getMenudataFile: only one of the user defined files")
+                _debug(
+                    2, "toolboxes.getMenudataFile: only one of the user defined files")
             else:
                 # if newer files -> generate new
                 menudataTime = os.path.getmtime(menudataFile)
                 if _getUserToolboxesFile():
-                    if os.path.getmtime(_getUserToolboxesFile()) > menudataTime:
-                        _debug(2, "toolboxes.getMenudataFile: user toolboxes is newer than menudata")
+                    if os.path.getmtime(
+                            _getUserToolboxesFile()) > menudataTime:
+                        _debug(
+                            2, "toolboxes.getMenudataFile: user toolboxes is newer than menudata")
                         generateNew = True
                 if userRootFile:
                     if os.path.getmtime(userRootFile) > menudataTime:
-                        _debug(2, "toolboxes.getMenudataFile: user root file is newer than menudata")
+                        _debug(
+                            2, "toolboxes.getMenudataFile: user root file is newer than menudata")
                         generateNew = True
         elif _getUserToolboxesFile() or userRootFile:
             _debug(2, "toolboxes.getMenudataFile: no menudata")
@@ -196,7 +210,9 @@ def getMenudataFile(userRootFile, newFile, fallback):
                 # Unfortunately, this is the case can be often: defined
                 # toolboxes but undefined module tree file.
                 _debug(2, "toolboxes.getMenudataFile: creating a tree")
-                tree = createTree(distributionRootFile=distributionRootFile, userRootFile=userRootFile)
+                tree = createTree(
+                    distributionRootFile=distributionRootFile,
+                    userRootFile=userRootFile)
             except ETREE_EXCEPTIONS:
                 _warning(_("Unable to parse user toolboxes XML files. "
                            "Default files will be loaded."))
@@ -209,7 +225,9 @@ def getMenudataFile(userRootFile, newFile, fallback):
                 fh.close()
                 return menudataFile
             except:
-                _debug(2, "toolboxes.getMenudataFile: writing menudata failed, returning fallback file")
+                _debug(
+                    2,
+                    "toolboxes.getMenudataFile: writing menudata failed, returning fallback file")
                 return fallback
         else:
             return menudataFile
@@ -236,10 +254,12 @@ def _createPath(path):
         try:
             os.mkdir(path)
         except OSError as e:
-            # we cannot use GError or similar because the gui doesn't start at all
-            gcore.warning('%(reason)s\n%(detail)s' % 
-                    ({'reason':_('Unable to create toolboxes directory.'),
-                      'detail': str(e)}))
+            # we cannot use GError or similar because the gui doesn't start at
+            # all
+            gcore.warning(
+                '%(reason)s\n%(detail)s' % ({
+                    'reason': _('Unable to create toolboxes directory.'),
+                    'detail': str(e)}))
             return False
     return True
 
@@ -422,7 +442,9 @@ def _expandToolboxes(node, toolboxes):
             idx = items.getchildren().index(subtoolbox)
 
             if has_xpath:
-                toolbox = toolboxes.find('.//toolbox[@name="%s"]' % subtoolbox.get('name'))
+                toolbox = toolboxes.find(
+                    './/toolbox[@name="%s"]' %
+                    subtoolbox.get('name'))
             else:
                 toolbox = None
                 potentialToolboxes = toolboxes.findall('.//toolbox')
@@ -455,7 +477,9 @@ def _expandUserToolboxesItem(node, toolboxes):
     for n in node.findall('./items/user-toolboxes-list'):
         items = node.find('./items')
         idx = items.getchildren().index(n)
-        el = etree.Element('toolbox', attrib={'name': 'GeneratedUserToolboxesList'})
+        el = etree.Element(
+            'toolbox', attrib={
+                'name': 'GeneratedUserToolboxesList'})
         items.insert(idx, el)
         label = etree.SubElement(el, tag='label')
         label.text = _("Custom toolboxes")
@@ -485,14 +509,14 @@ def _getAddons():
         _warning(_("List of addons cannot be obtained"
                    " because g.extension failed."))
         return []
-    
+
     flist = []
     for line in output.splitlines():
         if not line.startswith('executables'):
             continue
         for fexe in line.split('=', 1)[1].split(','):
             flist.append(fexe)
-    
+
     return sorted(flist)
 
 
@@ -616,12 +640,14 @@ def _expandRuntimeModules(node, loadMetadata=True):
             n.text = _escapeXML(','.join(keywords))
             if loadMetadata and not desc:
                 hasErrors = True
-    
+
     if hasErrors:
         # not translatable until toolboxes compilation on Mac is fixed
         # translating causes importing globalvar, where sys.exit is called
-        sys.stderr.write("WARNING: Some addons failed when loading. "
-                         "Please consider to update your addons by running 'g.extension.all -f'.\n")
+        sys.stderr.write(
+            "WARNING: Some addons failed when loading. "
+            "Please consider to update your addons by running 'g.extension.all -f'.\n")
+
 
 def _escapeXML(text):
     """Helper function for correct escaping characters for XML.
@@ -786,10 +812,10 @@ def module_test():
     """Tests the module using test files included in the current
     directory and in files from distribution.
     """
-    toolboxesFile   = os.path.join(WXGUIDIR, 'xml', 'toolboxes.xml')
+    toolboxesFile = os.path.join(WXGUIDIR, 'xml', 'toolboxes.xml')
     userToolboxesFile = 'data/test_toolboxes_user_toolboxes.xml'
     menuFile = 'data/test_toolboxes_menu.xml'
-    wxguiItemsFile  = os.path.join(WXGUIDIR, 'xml', 'wxgui_items.xml')
+    wxguiItemsFile = os.path.join(WXGUIDIR, 'xml', 'wxgui_items.xml')
     moduleItemsFile = os.path.join(WXGUIDIR, 'xml', 'module_items.xml')
 
     toolboxes = etree.parse(toolboxesFile)

+ 22 - 19
gui/wxpython/core/treemodel.py

@@ -19,11 +19,11 @@ This program is free software under the GNU General Public License
 
 class TreeModel(object):
     """Class represents a tree structure with hidden root.
-    
+
     TreeModel is used together with TreeView class to display results in GUI.
     The functionality is not complete, only needed methods are implemented.
     If needed, the functionality can be extended.
-    
+
     >>> tree = TreeModel(DictNode)
     >>> root = tree.root
     >>> n1 = tree.AppendNode(parent=root, label='node1')
@@ -52,6 +52,7 @@ class TreeModel(object):
       node21
         * xxx : 1
     """
+
     def __init__(self, nodeClass):
         """Constructor creates root node.
 
@@ -66,11 +67,11 @@ class TreeModel(object):
 
     def AppendNode(self, parent, label, data=None):
         """Create node and append it to parent node.
-        
+
         :param parent: parent node of the new node
         :param label: node label
         :param data: optional node data
-        
+
         :return: new node
         """
         node = self.nodeClass(label=label, data=data)
@@ -84,7 +85,7 @@ class TreeModel(object):
         parent = parent if parent else self.root
         self._searchNodes(node=parent, foundNodes=nodes, **kwargs)
         return nodes
-        
+
     def _searchNodes(self, node, foundNodes, **kwargs):
         """Helper method for searching nodes."""
         if node.match(**kwargs):
@@ -101,27 +102,25 @@ class TreeModel(object):
         if len(index) == 0:
             return self.root
         return self._getNode(self.root, index)
-        
+
     def GetIndexOfNode(self, node):
         """Method used for communication between view (VirtualTree) and model."""
         index = []
         return self._getIndex(node, index)
-        
-        
+
     def _getIndex(self, node, index):
         if node.parent:
             index.insert(0, node.parent.children.index(node))
             return self._getIndex(node.parent, index)
         return index
-        
-        
+
     def GetChildrenByIndex(self, index):
         """Method used for communication between view (VirtualTree) and model."""
         if len(index) == 0:
             return self.root.children
         node = self._getNode(self.root, index)
         return node.children
-        
+
     def _getNode(self, node, index):
         if len(index) == 1:
             return node.children[index[0]]
@@ -152,6 +151,7 @@ class TreeModel(object):
 
 class DictNode(object):
     """Node which has data in a form of dictionary."""
+
     def __init__(self, label, data=None):
         """Create node.
 
@@ -160,7 +160,7 @@ class DictNode(object):
         """
 
         self.label = label
-        if data == None:
+        if data is None:
             self.data = dict()
         else:
             self.data = data
@@ -175,9 +175,9 @@ class DictNode(object):
         text.append(indent * ' ' + self.label)
         if self.data:
             for key, value in self.data.iteritems():
-                text.append("%(indent)s* %(key)s : %(value)s" % {'indent': (indent + 2) * ' ',
-                                                                 'key': key,
-                                                                 'value': value})
+                text.append(
+                    "%(indent)s* %(key)s : %(value)s" %
+                    {'indent': (indent + 2) * ' ', 'key': key, 'value': value})
 
         if self.children:
             for child in self.children:
@@ -196,6 +196,7 @@ class DictNode(object):
 
 class ModuleNode(DictNode):
     """Node representing module."""
+
     def __init__(self, label, data=None):
         super(ModuleNode, self).__init__(label=label, data=data)
 
@@ -206,13 +207,15 @@ class ModuleNode(DictNode):
             return False
         if key in ('command', 'keywords', 'description'):
             try:
-                return len(self.data[key]) and (value in self.data[key] or value == '*')
+                return len(
+                    self.data[key]) and(
+                    value in self.data[key] or value == '*')
             except KeyError:
                 return False
-        
+
         return False
-            
-        
+
+
 def main():
     import doctest
     doctest.testmod()

+ 92 - 90
gui/wxpython/core/units.py

@@ -29,42 +29,43 @@ if __name__ == '__main__':
 
 from core.utils import _
 
+
 class BaseUnits:
+
     def __init__(self):
         self._units = dict()
-        self._units['length'] = { 0 : { 'key' : 'mu', 'label' : _('map units') },
-                             1 : { 'key' : 'me', 'label' : _('meters') },
-                             2 : { 'key' : 'km', 'label' : _('kilometers') },
-                             3 : { 'key' : 'mi', 'label' : _('miles') },
-                             4 : { 'key' : 'ft', 'label' : _('feet') } }
-        
-        self._units['area']   = { 0 : { 'key' : 'mu', 'label' : _('sq map units') },
-                             1 : { 'key' : 'me', 'label' : _('sq meters') },
-                             2 : { 'key' : 'km', 'label' : _('sq kilometers') },
-                             3 : { 'key' : 'ar', 'label' : _('acres') },
-                             4 : { 'key' : 'ht', 'label' : _('hectares') } }
+        self._units['length'] = {0: {'key': 'mu', 'label': _('map units')},
+                                 1: {'key': 'me', 'label': _('meters')},
+                                 2: {'key': 'km', 'label': _('kilometers')},
+                                 3: {'key': 'mi', 'label': _('miles')},
+                                 4: {'key': 'ft', 'label': _('feet')}}
+
+        self._units['area'] = {0: {'key': 'mu', 'label': _('sq map units')},
+                               1: {'key': 'me', 'label': _('sq meters')},
+                               2: {'key': 'km', 'label': _('sq kilometers')},
+                               3: {'key': 'ar', 'label': _('acres')},
+                               4: {'key': 'ht', 'label': _('hectares')}}
 
     def GetUnitsList(self, type):
         """Get list of units (their labels)
-        
+
         :param type: units type ('length' or 'area')
-        
+
         :return: list of units labels
         """
         result = list()
         try:
-            keys = self._units[type].keys()
-            keys.sort()
+            keys = sorted(self._units[type].keys())
             for idx in keys:
                 result.append(self._units[type][idx]['label'])
         except KeyError:
             pass
-        
+
         return result
 
     def GetUnitsKey(self, type, index):
         """Get units key based on index
-        
+
         :param type: units type ('length' or 'area')
         :param index: units index
         """
@@ -72,7 +73,7 @@ class BaseUnits:
 
     def GetUnitsIndex(self, type, key):
         """Get units index based on key
-        
+
         :param type: units type ('length' or 'area')
         :param key: units key, e.g. 'me' for meters
 
@@ -85,6 +86,7 @@ class BaseUnits:
 
 Units = BaseUnits()
 
+
 def ConvertValue(value, type, units):
     """Convert value from map units to given units
 
@@ -96,7 +98,7 @@ def ConvertValue(value, type, units):
     """
     # get map units
     # TODO
-    
+
     f = 1
     if type == 'length':
         if units == 'me':
@@ -107,7 +109,7 @@ def ConvertValue(value, type, units):
             f = 6.21371192237334e-4
         elif units == 'ft':
             f = 3.28083989501312
-    else: # -> area
+    else:  # -> area
         if units == 'me':
             f = 1.0
         elif units == 'km':
@@ -125,78 +127,78 @@ def ConvertValue(value, type, units):
 
 
 def formatDist(distance, mapunits):
-        """Formats length numbers and units in a nice way.
-
-        Formats length numbers and units as a function of length.
-
-        >>> formatDist(20.56915, 'metres')
-        (20.57, 'm')
-        >>> formatDist(6983.4591, 'metres')
-        (6.983, 'km')
-        >>> formatDist(0.59, 'feet')
-        (0.59, 'ft')
-        >>> formatDist(8562, 'feet')
-        (1.622, 'miles')
-        >>> formatDist(0.48963, 'degrees')
-        (29.38, 'min')
-        >>> formatDist(20.2546, 'degrees')
-        (20.25, 'deg')
-        >>> formatDist(82.146, 'unknown')
-        (82.15, 'units')
-
-        Accepted map units are 'meters', 'metres', 'feet', 'degree'.
-        Returns 'units' instead of unrecognized units.
-
-        :param distance: map units
-        :param mapunits: map units
-
-        From code by Hamish Bowman Grass Development Team 2006.
-        """
-        if mapunits == 'metres':
-            mapunits = 'meters'
-        outunits = mapunits
-        distance = float(distance)
-        divisor = 1.0
-
-        # figure out which units to use
-        if mapunits == 'meters':
-            if distance > 2500.0:
-                outunits = 'km'
-                divisor = 1000.0
-            else:
-                outunits = 'm'
-        elif mapunits == 'feet':
-            # nano-bug: we match any "feet", but US Survey feet is really
-            #  5279.9894 per statute mile, or 10.6' per 1000 miles. As >1000
-            #  miles the tick markers are rounded to the nearest 10th of a
-            #  mile (528'), the difference in foot flavours is ignored.
-            if distance > 5280.0:
-                outunits = 'miles'
-                divisor = 5280.0
-            else:
-                outunits = 'ft'
-        elif 'degree' in mapunits:
-            # was: 'degree' in mapunits and not haveCtypes (for unknown reason)
-            if distance < 1:
-                outunits = 'min'
-                divisor = (1 / 60.0)
-            else:
-                outunits = 'deg'
+    """Formats length numbers and units in a nice way.
+
+    Formats length numbers and units as a function of length.
+
+    >>> formatDist(20.56915, 'metres')
+    (20.57, 'm')
+    >>> formatDist(6983.4591, 'metres')
+    (6.983, 'km')
+    >>> formatDist(0.59, 'feet')
+    (0.59, 'ft')
+    >>> formatDist(8562, 'feet')
+    (1.622, 'miles')
+    >>> formatDist(0.48963, 'degrees')
+    (29.38, 'min')
+    >>> formatDist(20.2546, 'degrees')
+    (20.25, 'deg')
+    >>> formatDist(82.146, 'unknown')
+    (82.15, 'units')
+
+    Accepted map units are 'meters', 'metres', 'feet', 'degree'.
+    Returns 'units' instead of unrecognized units.
+
+    :param distance: map units
+    :param mapunits: map units
+
+    From code by Hamish Bowman Grass Development Team 2006.
+    """
+    if mapunits == 'metres':
+        mapunits = 'meters'
+    outunits = mapunits
+    distance = float(distance)
+    divisor = 1.0
+
+    # figure out which units to use
+    if mapunits == 'meters':
+        if distance > 2500.0:
+            outunits = 'km'
+            divisor = 1000.0
         else:
-            return (distance, 'units')
-
-        # format numbers in a nice way
-        if (distance / divisor) >= 2500.0:
-            outdistance = round(distance / divisor)
-        elif (distance / divisor) >= 1000.0:
-            outdistance = round(distance / divisor, 1)
-        elif (distance / divisor) > 0.0:
-            outdistance = round(distance / divisor,
-                                int(math.ceil(3 - math.log10(distance / divisor))))
+            outunits = 'm'
+    elif mapunits == 'feet':
+        # nano-bug: we match any "feet", but US Survey feet is really
+        #  5279.9894 per statute mile, or 10.6' per 1000 miles. As >1000
+        #  miles the tick markers are rounded to the nearest 10th of a
+        #  mile (528'), the difference in foot flavours is ignored.
+        if distance > 5280.0:
+            outunits = 'miles'
+            divisor = 5280.0
         else:
-            outdistance = float(distance / divisor)
-
-        return (outdistance, outunits)
+            outunits = 'ft'
+    elif 'degree' in mapunits:
+        # was: 'degree' in mapunits and not haveCtypes (for unknown reason)
+        if distance < 1:
+            outunits = 'min'
+            divisor = (1 / 60.0)
+        else:
+            outunits = 'deg'
+    else:
+        return (distance, 'units')
+
+    # format numbers in a nice way
+    if (distance / divisor) >= 2500.0:
+        outdistance = round(distance / divisor)
+    elif (distance / divisor) >= 1000.0:
+        outdistance = round(distance / divisor, 1)
+    elif (distance / divisor) > 0.0:
+        outdistance = round(distance / divisor,
+                            int(math.ceil(3 - math.log10(distance / divisor))))
+    else:
+        outdistance = float(distance / divisor)
+
+    return (outdistance, outunits)
 
 
 def doc_test():

File diff ditekan karena terlalu besar
+ 337 - 268
gui/wxpython/core/utils.py


File diff ditekan karena terlalu besar
+ 519 - 333
gui/wxpython/core/workspace.py


+ 87 - 58
gui/wxpython/core/ws.py

@@ -27,15 +27,15 @@ from grass.script.utils import try_remove
 from grass.script import core as grass
 from grass.exceptions import CalledModuleError
 
-from core          import utils
-from core.debug    import Debug
-from core.gthread import  gThread
+from core import utils
+from core.debug import Debug
+from core.gthread import gThread
 from core.utils import _
 
 try:
     haveGdal = True
     from osgeo import gdal
-    from osgeo import gdalconst 
+    from osgeo import gdalconst
 except ImportError:
     haveGdal = False
 
@@ -45,13 +45,14 @@ from grass.pydispatch.signal import Signal
 class RenderWMSMgr(wx.EvtHandler):
     """Fetch and prepare WMS data for rendering.
     """
+
     def __init__(self, layer, env):
         if not haveGdal:
-            sys.stderr.write(_("Unable to load GDAL Python bindings.\n"\
+            sys.stderr.write(_("Unable to load GDAL Python bindings.\n"
                                "WMS layers can not be displayed without the bindings.\n"))
 
         self.layer = layer
-        
+
         wx.EvtHandler.__init__(self)
 
         # thread for d.wms commands
@@ -65,7 +66,7 @@ class RenderWMSMgr(wx.EvtHandler):
 
         self.tempMap = grass.tempfile()
         self.dstSize = {}
- 
+
         self.dataFetched = Signal('RenderWMSMgr.dataFetched')
         self.updateProgress = Signal('RenderWMSMgr.updateProgress')
 
@@ -82,7 +83,7 @@ class RenderWMSMgr(wx.EvtHandler):
         if not haveGdal:
             return
 
-        Debug.msg(1, "RenderWMSMgr.Render(%s): force=%d img=%s" % \
+        Debug.msg(1, "RenderWMSMgr.Render(%s): force=%d img=%s" %
                   (self.layer, self.layer.forceRender, self.layer.mapfile))
 
         env = copy.copy(env)
@@ -93,7 +94,7 @@ class RenderWMSMgr(wx.EvtHandler):
         self._fitAspect(region, self.dstSize)
 
         self.updateMap = True
-        fetchData = True # changed to True when calling Render()
+        fetchData = True  # changed to True when calling Render()
         zoomChanged = False
 
         if self.renderedRegion is None or \
@@ -108,7 +109,7 @@ class RenderWMSMgr(wx.EvtHandler):
 
             for c in ['e-w resol', 'n-s resol']:
                 if self.renderedRegion and \
-                    region[c] != self.renderedRegion[c]:
+                        region[c] != self.renderedRegion[c]:
                     zoomChanged = True
                     break
 
@@ -120,7 +121,7 @@ class RenderWMSMgr(wx.EvtHandler):
             try_remove(self.tempMap)
 
             self.currentPid = self.thread.GetId()
-            ### self.thread.Terminate()
+            # self.thread.Terminate()
             self.downloading = True
 
             self.fetching_cmd = cmd
@@ -129,15 +130,15 @@ class RenderWMSMgr(wx.EvtHandler):
             env["GRASS_REGION"] = self._createRegionStr(region)
 
             cmd_render = copy.deepcopy(cmd)
-            cmd_render[1]['quiet'] = True # be quiet
-        
+            cmd_render[1]['quiet'] = True  # be quiet
+
             self._startTime = time.time()
             self.thread.Run(callable=self._render, cmd=cmd_render, env=env,
                             ondone=self.OnRenderDone)
             self.layer.forceRender = False
-            
+
         self.updateProgress.emit(layer=self.layer)
-        
+
     def _render(self, cmd, env):
         try:
             return grass.run_command(cmd[0], env=env, **cmd[1])
@@ -157,23 +158,30 @@ class RenderWMSMgr(wx.EvtHandler):
             self.fetched_data_cmd = None
             return
 
-        self.mapMerger = GDALRasterMerger(targetFile = self.layer.mapfile,
-                                          region = self.renderedRegion,
-                                          bandsNum = 3, gdalDriver = 'PNM', fillValue = 0)
-        self.mapMerger.AddRasterBands(self.tempMap, {1 : 1, 2 : 2, 3 : 3})
+        self.mapMerger = GDALRasterMerger(
+            targetFile=self.layer.mapfile,
+            region=self.renderedRegion,
+            bandsNum=3,
+            gdalDriver='PNM',
+            fillValue=0)
+        self.mapMerger.AddRasterBands(self.tempMap, {1: 1, 2: 2, 3: 3})
         del self.mapMerger
 
-        self.maskMerger = GDALRasterMerger(targetFile = self.layer.maskfile, region = self.renderedRegion,
-                                           bandsNum = 1, gdalDriver = 'PNM', fillValue = 0)
+        self.maskMerger = GDALRasterMerger(
+            targetFile=self.layer.maskfile,
+            region=self.renderedRegion,
+            bandsNum=1,
+            gdalDriver='PNM',
+            fillValue=0)
         #{4 : 1} alpha channel (4) to first and only channel (1) in mask
-        self.maskMerger.AddRasterBands(self.tempMap, {4 : 1}) 
+        self.maskMerger.AddRasterBands(self.tempMap, {4: 1})
         del self.maskMerger
 
         self.fetched_data_cmd = self.fetching_cmd
 
-        Debug.msg(1, "RenderWMSMgr.OnRenderDone(%s): ret=%d time=%f" % \
-                      (self.layer, event.ret, time.time() - self._startTime))
-        
+        Debug.msg(1, "RenderWMSMgr.OnRenderDone(%s): ret=%d time=%f" %
+                  (self.layer, event.ret, time.time() - self._startTime))
+
         self.dataFetched.emit(layer=self.layer)
 
     def _getRegionDict(self, env):
@@ -209,7 +217,7 @@ class RenderWMSMgr(wx.EvtHandler):
         return regionStr
 
     def IsDownloading(self):
-        """Is it downloading any data from WMS server? 
+        """Is it downloading any data from WMS server?
         """
         return self.downloading
 
@@ -219,7 +227,7 @@ class RenderWMSMgr(wx.EvtHandler):
         if region['n-s resol'] > region['e-w resol']:
             delta = region['n-s resol'] * size['cols'] / 2
 
-            center = (region['east'] - region['west'])/2
+            center = (region['east'] - region['west']) / 2
 
             region['east'] = center + delta + region['west']
             region['west'] = center - delta + region['west']
@@ -228,7 +236,7 @@ class RenderWMSMgr(wx.EvtHandler):
         else:
             delta = region['e-w resol'] * size['rows'] / 2
 
-            center = (region['north'] - region['south'])/2 
+            center = (region['north'] - region['south']) / 2
 
             region['north'] = center + delta + region['south']
             region['south'] = center - delta + region['south']
@@ -238,18 +246,21 @@ class RenderWMSMgr(wx.EvtHandler):
         """Abort rendering process"""
         Debug.msg(1, "RenderWMSMgr({}).Abort()".format(self.layer))
         self.thread.Terminate()
-        
+
         # force rendering layer next time
         self.layer.forceRender = True
         self.updateMap = False
         self.thread.Terminate(False)
 
+
 class GDALRasterMerger:
     """Merge rasters.
 
         Based on gdal_merge.py utility.
     """
-    def __init__(self, targetFile, region, bandsNum, gdalDriver, fillValue = None):
+
+    def __init__(self, targetFile, region, bandsNum,
+                 gdalDriver, fillValue=None):
         """Create raster for merging.
         """
         self.gdalDrvType = gdalDriver
@@ -257,12 +268,19 @@ class GDALRasterMerger:
         nsRes = (region['south'] - region['north']) / region['rows']
         ewRes = (region['east'] - region['west']) / region['cols']
 
-        self.tGeotransform = [region['west'], ewRes, 0, region['north'], 0, nsRes]
+        self.tGeotransform = [
+            region['west'],
+            ewRes, 0, region['north'],
+            0, nsRes]
 
-        self.tUlx, self.tUly, self.tLrx, self.tLry = self._getCorners(self.tGeotransform, region)
+        self.tUlx, self.tUly, self.tLrx, self.tLry = self._getCorners(
+            self.tGeotransform, region)
 
         driver = gdal.GetDriverByName(self.gdalDrvType)
-        self.tDataset = driver.Create(targetFile, region['cols'], region['rows'], bandsNum,  gdal.GDT_Byte)
+        self.tDataset = driver.Create(
+            targetFile, region['cols'],
+            region['rows'],
+            bandsNum, gdal.GDT_Byte)
 
         if fillValue is not None:
             # fill raster bands with a constant value
@@ -272,29 +290,29 @@ class GDALRasterMerger:
     def AddRasterBands(self, sourceFile, sTBands):
         """Add raster bands from sourceFile into the merging raster.
         """
-        sDataset = gdal.Open(sourceFile, gdal.GA_ReadOnly) 
+        sDataset = gdal.Open(sourceFile, gdal.GA_ReadOnly)
         if sDataset is None:
             return
 
         sGeotransform = sDataset.GetGeoTransform()
 
         sSize = {
-                    'rows' :  sDataset.RasterYSize,
-                    'cols' :  sDataset.RasterXSize
-                 }
+            'rows': sDataset.RasterYSize,
+            'cols': sDataset.RasterXSize
+        }
 
         sUlx, sUly, sLrx, sLry = self._getCorners(sGeotransform, sSize)
 
         # figure out intersection region
-        tIntsctUlx = max(self.tUlx,sUlx)
-        tIntsctLrx = min(self.tLrx,sLrx)
+        tIntsctUlx = max(self.tUlx, sUlx)
+        tIntsctLrx = min(self.tLrx, sLrx)
         if self.tGeotransform[5] < 0:
-            tIntsctUly = min(self.tUly,sUly)
-            tIntsctLry = max(self.tLry,sLry)
+            tIntsctUly = min(self.tUly, sUly)
+            tIntsctLry = max(self.tLry, sLry)
         else:
-            tIntsctUly = max(self.tUly,sUly)
-            tIntsctLry = min(self.tLry,sLry)
-        
+            tIntsctUly = max(self.tUly, sUly)
+            tIntsctLry = min(self.tLry, sLry)
+
         # do they even intersect?
         if tIntsctUlx >= tIntsctLrx:
             return
@@ -303,12 +321,21 @@ class GDALRasterMerger:
         if self.tGeotransform[5] > 0 and tIntsctUly >= tIntsctLry:
             return
 
-
         # compute target window in pixel coordinates.
-        tXoff = int((tIntsctUlx - self.tGeotransform[0]) / self.tGeotransform[1] + 0.1)
-        tYoff = int((tIntsctUly - self.tGeotransform[3]) / self.tGeotransform[5] + 0.1)
-        tXsize = int((tIntsctLrx - self.tGeotransform[0])/self.tGeotransform[1] + 0.5) - tXoff
-        tYsize = int((tIntsctLry - self.tGeotransform[3])/self.tGeotransform[5] + 0.5) - tYoff
+        tXoff = int(
+            (tIntsctUlx -
+             self.tGeotransform[0]) /
+            self.tGeotransform[1] +
+            0.1)
+        tYoff = int(
+            (tIntsctUly -
+             self.tGeotransform[3]) /
+            self.tGeotransform[5] +
+            0.1)
+        tXsize = int(
+            (tIntsctLrx - self.tGeotransform[0]) / self.tGeotransform[1] + 0.5) - tXoff
+        tYsize = int(
+            (tIntsctLry - self.tGeotransform[3]) / self.tGeotransform[5] + 0.5) - tYoff
 
         if tXsize < 1 or tYsize < 1:
             return
@@ -316,17 +343,19 @@ class GDALRasterMerger:
         # Compute source window in pixel coordinates.
         sXoff = int((tIntsctUlx - sGeotransform[0]) / sGeotransform[1])
         sYoff = int((tIntsctUly - sGeotransform[3]) / sGeotransform[5])
-        sXsize = int((tIntsctLrx - sGeotransform[0]) / sGeotransform[1] + 0.5) - sXoff
-        sYsize = int((tIntsctLry - sGeotransform[3]) / sGeotransform[5] + 0.5) - sYoff
+        sXsize = int(
+            (tIntsctLrx - sGeotransform[0]) / sGeotransform[1] + 0.5) - sXoff
+        sYsize = int(
+            (tIntsctLry - sGeotransform[3]) / sGeotransform[5] + 0.5) - sYoff
 
         if sXsize < 1 or sYsize < 1:
             return
 
         for sBandNnum, tBandNum in sTBands.iteritems():
-            bandData = sDataset.GetRasterBand(sBandNnum).ReadRaster(sXoff, sYoff, sXsize,
-                                                                    sYsize, tXsize, tYsize, gdal.GDT_Byte)
-            self.tDataset.GetRasterBand(tBandNum).WriteRaster(tXoff, tYoff, tXsize, tYsize, bandData, 
-                                                              tXsize, tYsize, gdal.GDT_Byte)
+            bandData = sDataset.GetRasterBand(sBandNnum).ReadRaster(
+                sXoff, sYoff, sXsize, sYsize, tXsize, tYsize, gdal.GDT_Byte)
+            self.tDataset.GetRasterBand(tBandNum).WriteRaster(
+                tXoff, tYoff, tXsize, tYsize, bandData, tXsize, tYsize, gdal.GDT_Byte)
 
     def _getCorners(self, geoTrans, size):
 
@@ -335,13 +364,13 @@ class GDALRasterMerger:
         lrx = geoTrans[0] + size['cols'] * geoTrans[1]
         lry = geoTrans[3] + size['rows'] * geoTrans[5]
 
-        return ulx, uly, lrx, lry 
+        return ulx, uly, lrx, lry
 
     def SetGeorefAndProj(self):
         """Set georeference and projection to target file
         """
-        projection = grass.read_command('g.proj', 
-                                        flags = 'wf')
+        projection = grass.read_command('g.proj',
+                                        flags='wf')
         self.tDataset.SetProjection(projection)
 
         self.tDataset.SetGeoTransform(self.tGeotransform)

+ 13 - 11
gui/wxpython/datacatalog/catalog.py

@@ -25,21 +25,23 @@ from datacatalog.toolbars import DataCatalogToolbar
 
 from grass.pydispatch.signal import Signal
 
+
 class DataCatalog(wx.Panel):
     """Data catalog panel"""
-    def __init__(self, parent, giface=None, id = wx.ID_ANY, title=_("Data catalog"),
-                 name='catalog', **kwargs):
+
+    def __init__(self, parent, giface=None, id=wx.ID_ANY,
+                 title=_("Data catalog"), name='catalog', **kwargs):
         """Panel constructor  """
         self.showNotification = Signal('DataCatalog.showNotification')
         self.parent = parent
         self.baseTitle = title
-        wx.Panel.__init__(self, parent = parent, id = id, **kwargs)
+        wx.Panel.__init__(self, parent=parent, id=id, **kwargs)
         self.SetName("DataCatalog")
-        
+
         Debug.msg(1, "DataCatalog.__init__()")
 
         # toolbar
-        self.toolbar = DataCatalogToolbar(parent = self)
+        self.toolbar = DataCatalogToolbar(parent=self)
 
         # tree with layers
         self.tree = DataCatalogTree(self, giface=giface)
@@ -54,15 +56,15 @@ class DataCatalog(wx.Panel):
         """Do layout"""
         sizer = wx.BoxSizer(wx.VERTICAL)
 
-        sizer.Add(item = self.toolbar, proportion = 0,
-                  flag = wx.EXPAND)          
+        sizer.Add(item=self.toolbar, proportion=0,
+                  flag=wx.EXPAND)
+
+        sizer.Add(item=self.tree.GetControl(), proportion=1,
+                  flag=wx.EXPAND)
 
-        sizer.Add(item = self.tree.GetControl(), proportion = 1,
-                  flag = wx.EXPAND)          
-        
         self.SetAutoLayout(True)
         self.SetSizer(sizer)
-        
+
         self.Layout()
 
     def LoadItems(self):

+ 7 - 1
gui/wxpython/datacatalog/frame.py

@@ -29,11 +29,17 @@ from datacatalog.toolbars import DataCatalogToolbar
 
 class DataCatalogFrame(wx.Frame):
     """Frame for testing purposes only."""
+
     def __init__(self, parent, giface=None):
         wx.Frame.__init__(self, parent=parent,
                           title=_('GRASS GIS Data Catalog'))
         self.SetName("DataCatalog")
-        self.SetIcon(wx.Icon(os.path.join(ICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
+        self.SetIcon(
+            wx.Icon(
+                os.path.join(
+                    ICONDIR,
+                    'grass.ico'),
+                wx.BITMAP_TYPE_ICO))
 
         self._giface = giface
         self.panel = wx.Panel(self)

+ 3 - 2
gui/wxpython/datacatalog/g.gui.datacatalog.py

@@ -27,16 +27,17 @@
 
 import grass.script as gscript
 
+
 def main():
     options, flags = gscript.parser()
 
     # import wx only after running parser
     # to avoid issues when only interface is needed
     import wx
-    
+
     from grass.script.setup import set_gui_path
     set_gui_path()
-    
+
     from core.giface import StandaloneGrassInterface
     from datacatalog.frame import DataCatalogFrame
 

+ 14 - 5
gui/wxpython/datacatalog/toolbars.py

@@ -20,16 +20,25 @@ from icons.icon import MetaIcon
 from core.utils import _
 
 icons = {
-    'reloadTree': MetaIcon(img='redraw', label=_("Reload GRASS locations")),
-    'reloadMapset': MetaIcon(img='reload', label=_("Reload current GRASS mapset only")),
-    'unlocked': MetaIcon(img='unlocked', label=_("Click to restrict editing to current mapset only")),
-    'locked': MetaIcon(img='locked', label=_("Click to allow editing other mapsets")),
-    }
+    'reloadTree': MetaIcon(
+        img='redraw',
+        label=_("Reload GRASS locations")),
+    'reloadMapset': MetaIcon(
+        img='reload',
+        label=_("Reload current GRASS mapset only")),
+    'unlocked': MetaIcon(
+        img='unlocked',
+        label=_("Click to restrict editing to current mapset only")),
+    'locked': MetaIcon(
+        img='locked',
+        label=_("Click to allow editing other mapsets")),
+}
 
 
 class DataCatalogToolbar(BaseToolbar):
     """Main data catalog toolbar
     """
+
     def __init__(self, parent):
         """Main toolbar constructor
         """

+ 196 - 85
gui/wxpython/datacatalog/tree.py

@@ -61,29 +61,46 @@ def getLocationTree(gisdbase, location, queue, mapsets=None):
     elements = ['raster', 'raster_3d', 'vector']
     try:
         if not mapsets:
-            mapsets = gscript.read_command('g.mapsets', flags='l', separator='comma', quiet=True, env=env).strip()
+            mapsets = gscript.read_command(
+                'g.mapsets',
+                flags='l',
+                separator='comma',
+                quiet=True,
+                env=env).strip()
     except CalledModuleError:
-        queue.put((maps_dict, _("Failed to read mapsets from location <{l}>.").format(l=location)))
+        queue.put(
+            (maps_dict,
+             _("Failed to read mapsets from location <{l}>.").format(
+                 l=location)))
         gscript.try_remove(tmp_gisrc_file)
         return
     else:
         listOfMapsets = mapsets.split(',')
-        Debug.msg(4, "Location <{}>: {} mapsets found".format(location, len(listOfMapsets)))
+        Debug.msg(
+            4, "Location <{}>: {} mapsets found".format(
+                location, len(listOfMapsets)))
         for each in listOfMapsets:
             maps_dict[each] = {}
             for elem in elements:
                 maps_dict[each][elem] = []
     try:
-        maplist = gscript.read_command('g.list', flags='mt', type=elements,
-                                       mapset=','.join(listOfMapsets), quiet=True, env=env).strip()
+        maplist = gscript.read_command(
+            'g.list', flags='mt', type=elements,
+            mapset=','.join(listOfMapsets),
+            quiet=True, env=env).strip()
     except CalledModuleError:
-        queue.put((maps_dict, _("Failed to read maps from location <{l}>.").format(l=location)))
+        queue.put(
+            (maps_dict,
+             _("Failed to read maps from location <{l}>.").format(
+                 l=location)))
         gscript.try_remove(tmp_gisrc_file)
         return
     else:
         # fill dictionary
         listOfMaps = maplist.splitlines()
-        Debug.msg(4, "Location <{}>: {} maps found".format(location, len(listOfMaps)))
+        Debug.msg(
+            4, "Location <{}>: {} maps found".format(
+                location, len(listOfMaps)))
         for each in listOfMaps:
             ltype, wholename = each.split('/')
             name, mapset = wholename.split('@')
@@ -109,9 +126,15 @@ def map_exists(name, element, env, mapset=None):
         element = 'grid3'
     # g.findfile returns non-zero when file was not found
     # se we ignore return code and just focus on stdout
-    process = gscript.start_command('g.findfile', flags='n',
-                                    element=element, file=name, mapset=mapset,
-                                    stdout=gscript.PIPE, stderr=gscript.PIPE, env=env)
+    process = gscript.start_command(
+        'g.findfile',
+        flags='n',
+        element=element,
+        file=name,
+        mapset=mapset,
+        stdout=gscript.PIPE,
+        stderr=gscript.PIPE,
+        env=env)
     output, errors = process.communicate()
     info = gscript.parse_key_val(output, sep='=')
     # file is the key questioned in grass.script.core find_file()
@@ -123,6 +146,7 @@ def map_exists(name, element, env, mapset=None):
 
 
 class NameEntryDialog(TextEntryDialog):
+
     def __init__(self, element, mapset, env, **kwargs):
         TextEntryDialog.__init__(self, **kwargs)
         self._element = element
@@ -136,10 +160,16 @@ class NameEntryDialog(TextEntryDialog):
         if not new:
             return
         if map_exists(new, self._element, self._env, self._mapset):
-            dlg = wx.MessageDialog(self, message=_("Map of type {elem} <{name}> already exists in mapset <{mapset}>. "
-                                                   "Do you want to overwrite it?").format(elem=self._element,
-                                   name=new, mapset=self._mapset),
-                                   caption=_("Overwrite?"), style=wx.YES_NO)
+            dlg = wx.MessageDialog(
+                self,
+                message=_(
+                    "Map of type {elem} <{name}> already exists in mapset <{mapset}>. "
+                    "Do you want to overwrite it?").format(
+                    elem=self._element,
+                    name=new,
+                    mapset=self._mapset),
+                caption=_("Overwrite?"),
+                style=wx.YES_NO)
             if dlg.ShowModal() == wx.ID_YES:
                 dlg.Destroy()
                 self._env['GRASS_OVERWRITE'] = '1'
@@ -153,6 +183,7 @@ class NameEntryDialog(TextEntryDialog):
 
 class DataCatalogNode(DictNode):
     """Node representing item in datacatalog."""
+
     def __init__(self, label, data=None):
         super(DataCatalogNode, self).__init__(label=label, data=data)
 
@@ -172,11 +203,20 @@ class DataCatalogNode(DictNode):
 
 
 class LocationMapTree(TreeView):
-    def __init__(self, parent, model=None, style=wx.TR_HIDE_ROOT | wx.TR_EDIT_LABELS | wx.TR_LINES_AT_ROOT |
-                 wx.TR_HAS_BUTTONS | wx.TR_FULL_ROW_HIGHLIGHT | wx.TR_SINGLE):
+
+    def __init__(
+            self, parent, model=None, style=wx.TR_HIDE_ROOT | wx.TR_EDIT_LABELS
+            | wx.TR_LINES_AT_ROOT | wx.TR_HAS_BUTTONS | wx.TR_FULL_ROW_HIGHLIGHT |
+            wx.TR_SINGLE):
         """Location Map Tree constructor."""
         self._model = TreeModel(DataCatalogNode)
-        super(LocationMapTree, self).__init__(parent=parent, model=self._model, id=wx.ID_ANY, style=style)
+        super(
+            LocationMapTree,
+            self).__init__(
+            parent=parent,
+            model=self._model,
+            id=wx.ID_ANY,
+            style=style)
         self.showNotification = Signal('Tree.showNotification')
         self.parent = parent
         self.contextMenu.connect(self.OnRightClick)
@@ -200,23 +240,26 @@ class LocationMapTree(TreeView):
         try:
             nprocs = cpu_count()
         except NotImplementedError:
-                nprocs = 4
+            nprocs = 4
 
         results = dict()
         errors = []
         location_nodes = []
         nlocations = len(locations)
-        grassdata_node = self._model.AppendNode(parent=self._model.root,
-                                                label=_('GRASS locations in {}').format(genv['GISDBASE']),
-                                                data=dict(type='grassdata'))
+        grassdata_node = self._model.AppendNode(
+            parent=self._model.root, label=_('GRASS locations in {}').format(
+                genv['GISDBASE']), data=dict(
+                type='grassdata'))
         for location in locations:
             results[location] = dict()
-            varloc = self._model.AppendNode(parent=grassdata_node, label=location,
-                                            data=dict(type='location', name=location))
+            varloc = self._model.AppendNode(
+                parent=grassdata_node, label=location, data=dict(
+                    type='location', name=location))
             location_nodes.append(varloc)
             loc_count += 1
 
-            Debug.msg(3, "Scanning location <{}> ({}/{})".format(location, loc_count, nlocations))
+            Debug.msg(
+                3, "Scanning location <{}> ({}/{})".format(location, loc_count, nlocations))
 
             q = Queue()
             p = Process(target=getLocationTree,
@@ -238,8 +281,10 @@ class LocationMapTree(TreeView):
                         errors.append(error)
 
                     for key in sorted(maps.keys()):
-                        mapset_node = self._model.AppendNode(parent=location_nodes[i], label=key,
-                                                             data=dict(type='mapset', name=key))
+                        mapset_node = self._model.AppendNode(
+                            parent=location_nodes[i],
+                            label=key, data=dict(
+                                type='mapset', name=key))
                         self._populateMapsetItem(mapset_node, maps[key])
 
                 proc_count = 0
@@ -284,8 +329,13 @@ class LocationMapTree(TreeView):
                 node = get_first_child(mapsetItem)
 
         q = Queue()
-        p = Process(target=getLocationTree,
-                    args=(genv['GISDBASE'], locationItem.data['name'], q, mapsetItem.data['name']))
+        p = Process(
+            target=getLocationTree,
+            args=(
+                genv['GISDBASE'],
+                locationItem.data['name'],
+                q,
+                mapsetItem.data['name']))
         p.start()
         maps, error = q.get()
         if error:
@@ -298,8 +348,9 @@ class LocationMapTree(TreeView):
     def _populateMapsetItem(self, mapset_node, data):
         for elem in data:
             if data[elem]:
-                element_node = self._model.AppendNode(parent=mapset_node, label=elem,
-                                                      data=dict(type='element', name=elem))
+                element_node = self._model.AppendNode(
+                    parent=mapset_node, label=elem,
+                    data=dict(type='element', name=elem))
                 for layer in data[elem]:
                     self._model.AppendNode(parent=element_node, label=layer,
                                            data=dict(type=elem, name=layer))
@@ -392,7 +443,9 @@ class LocationMapTree(TreeView):
         if not locationItem:
             return None, None
 
-        mapsetItem = self._model.SearchNodes(parent=locationItem[0], name=mapset, type='mapset')
+        mapsetItem = self._model.SearchNodes(
+            parent=locationItem[0],
+            name=mapset, type='mapset')
         if not mapsetItem:
             return locationItem[0], None
 
@@ -407,6 +460,7 @@ class LocationMapTree(TreeView):
 
 
 class DataCatalogTree(LocationMapTree):
+
     def __init__(self, parent, giface=None):
         """Data Catalog Tree constructor."""
         super(DataCatalogTree, self).__init__(parent)
@@ -459,17 +513,27 @@ class DataCatalogTree(LocationMapTree):
         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. "
+            "You can paste it to the current mapset "
+            "<{mapset}>.".format(
+                layer=self.copy_layer.label,
+                mapset=gisenv()['MAPSET']))
         self.showNotification.emit(message=label)
 
     def OnRenameMap(self, event):
         """Rename layer with dialog"""
         old_name = self.selected_layer.label
-        gisrc, env = getEnvironment(gisenv()['GISDBASE'], self.selected_location.label, mapset=self.selected_mapset.label)
-        new_name = self._getNewMapName(_('New name'), _('Rename map'),
-                                       old_name, env=env, mapset=self.selected_mapset.label, element=self.selected_type.label)
+        gisrc, env = getEnvironment(
+            gisenv()['GISDBASE'],
+            self.selected_location.label, mapset=self.selected_mapset.label)
+        new_name = self._getNewMapName(
+            _('New name'),
+            _('Rename map'),
+            old_name,
+            env=env,
+            mapset=self.selected_mapset.label,
+            element=self.selected_type.label)
         if new_name:
             self.Rename(old_name, new_name)
 
@@ -493,7 +557,9 @@ class DataCatalogTree(LocationMapTree):
     def Rename(self, old, new):
         """Rename layer"""
         string = old + ',' + new
-        gisrc, env = getEnvironment(gisenv()['GISDBASE'], self.selected_location.label, self.selected_mapset.label)
+        gisrc, env = getEnvironment(
+            gisenv()['GISDBASE'],
+            self.selected_location.label, self.selected_mapset.label)
         label = _("Renaming map <{name}>...").format(name=string)
         self.showNotification.emit(message=label)
         if self.selected_type.label == 'vector':
@@ -501,12 +567,14 @@ class DataCatalogTree(LocationMapTree):
         elif self.selected_type.label == 'raster':
             renamed, cmd = self._runCommand('g.rename', raster=string, env=env)
         else:
-            renamed, cmd = self._runCommand('g.rename', raster3d=string, env=env)
+            renamed, cmd = self._runCommand(
+                'g.rename', raster3d=string, env=env)
         if renamed == 0:
             self.selected_layer.label = new
             self.selected_layer.data['name'] = new
             self.RefreshNode(self.selected_layer)
-            self.showNotification.emit(message=_("{cmd} -- completed").format(cmd=cmd))
+            self.showNotification.emit(
+                message=_("{cmd} -- completed").format(cmd=cmd))
             Debug.msg(1, "LAYER RENAMED TO: " + new)
         gscript.try_remove(gisrc)
 
@@ -517,29 +585,47 @@ class DataCatalogTree(LocationMapTree):
             GMessage(_("No map selected for copying."), parent=self)
             return
         if self.selected_location == self.copy_location:
-            gisrc, env = getEnvironment(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)
+            gisrc, env = getEnvironment(
+                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)
+            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
 
             if not self.selected_type:
-                found = self._model.SearchNodes(parent=self.selected_mapset, type='element', name=self.copy_type.label)
+                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)
+                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)
+                    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:
@@ -551,34 +637,44 @@ class DataCatalogTree(LocationMapTree):
             label = _("Copying <{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, overwrite=overwrite, 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, overwrite=overwrite, 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, overwrite=overwrite, 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))
+                self.showNotification.emit(
+                    message=_("g.copy completed").format(cmd=cmd))
             gscript.try_remove(gisrc)
         else:
-            GError(_("Failed to copy map: action is allowed only within the same location."),
-                   parent=self)
+            GError(
+                _("Failed to copy map: action is allowed only within the same location."),
+                parent=self)
 
         # expand selected mapset
         self.ExpandNode(self.selected_mapset, recursive=True)
 
     def InsertLayer(self, name, mapset_node, element_name):
         """Insert layer into model and refresh tree"""
-        found_element = self._model.SearchNodes(parent=mapset_node, type='element', name=element_name)
+        found_element = self._model.SearchNodes(
+            parent=mapset_node, type='element', name=element_name)
         found_element = found_element[0] if found_element else None
         if not found_element:
             # add type node if not exists
-            found_element = self._model.AppendNode(parent=mapset_node, label=element_name,
-                                                   data=dict(type='element', name=element_name))
+            found_element = self._model.AppendNode(
+                parent=mapset_node, label=element_name,
+                data=dict(type='element', name=element_name))
         found = self._model.SearchNodes(parent=found_element, name=name)
         if len(found) == 0:
             self._model.AppendNode(parent=found_element, label=name,
@@ -589,34 +685,41 @@ class DataCatalogTree(LocationMapTree):
     def OnDeleteMap(self, event):
         """Delete layer or mapset"""
         name = self.selected_layer.label
-        gisrc, env = getEnvironment(gisenv()['GISDBASE'], self.selected_location.label, self.selected_mapset.label)
-        if self._confirmDialog(question=_("Do you really want to delete map <{m}> of type <{etype}> from mapset "
-                               "<{mapset}> in location <{loc}>?").format(m=name, mapset=self.selected_mapset.label,
-                                                                         etype=self.selected_type.label,
-                                                                         loc=self.selected_location.label),
-                               title=_('Delete map')) == wx.ID_YES:
+        gisrc, env = getEnvironment(
+            gisenv()['GISDBASE'],
+            self.selected_location.label, self.selected_mapset.label)
+        if self._confirmDialog(
+                question=_(
+                    "Do you really want to delete map <{m}> of type <{etype}> from mapset "
+                    "<{mapset}> in location <{loc}>?").format(
+                    m=name, mapset=self.selected_mapset.label,
+                    etype=self.selected_type.label,
+                    loc=self.selected_location.label),
+                title=_('Delete map')) == wx.ID_YES:
             label = _("Deleting {name}...").format(name=name)
             self.showNotification.emit(message=label)
             if self.selected_type.label == 'vector':
-                removed, cmd = self._runCommand('g.remove', flags='f', type='vector',
-                                                name=name, env=env)
+                removed, cmd = self._runCommand(
+                    'g.remove', flags='f', type='vector', name=name, env=env)
             elif self.selected_type.label == 'raster':
-                removed, cmd = self._runCommand('g.remove', flags='f', type='raster',
-                                                name=name, env=env)
+                removed, cmd = self._runCommand(
+                    'g.remove', flags='f', type='raster', name=name, env=env)
             else:
-                removed, cmd = self._runCommand('g.remove', flags='f', type='raster_3d',
-                                                name=name, env=env)
+                removed, cmd = self._runCommand(
+                    'g.remove', flags='f', type='raster_3d', name=name, env=env)
             if removed == 0:
                 self._model.RemoveNode(self.selected_layer)
                 self.RefreshNode(self.selected_type, recursive=True)
                 Debug.msg(1, "LAYER " + name + " DELETED")
-                self.showNotification.emit(message=_("g.remove completed").format(cmd=cmd))
+                self.showNotification.emit(
+                    message=_("g.remove completed").format(cmd=cmd))
         gscript.try_remove(gisrc)
 
     def OnDisplayLayer(self, event):
         """Display layer in current graphics view"""
         layerName = []
-        if self.selected_location.label == gisenv()['LOCATION_NAME'] and self.selected_mapset:
+        if self.selected_location.label == gisenv(
+        )['LOCATION_NAME'] and self.selected_mapset:
             string = self.selected_layer.label + '@' + self.selected_mapset.label
             layerName.append(string)
             label = _("Displaying {name}...").format(name=string)
@@ -629,18 +732,21 @@ class DataCatalogTree(LocationMapTree):
                 self._giface.lmgr.AddMaps(layerName, 'raster', True)
             else:
                 self._giface.lmgr.AddMaps(layerName, 'raster_3d', True)
-                label = "d.rast --q map=" + string + _(" -- completed. Go to Layers tab for further operations.")  # generate this message (command) automatically?
+                # generate this message (command) automatically?
+                label = "d.rast --q map=" + string + _(
+                    " -- completed. Go to Layers tab for further operations.")
             self.showNotification.emit(message=label)
             Debug.msg(1, "LAYER " + self.selected_layer.label + " DISPLAYED")
         else:
-            GError(_("Failed to display layer: not in current mapset or invalid layer"),
-                   parent=self)
+            GError(
+                _("Failed to display layer: not in current mapset or invalid layer"),
+                parent=self)
 
     def OnBeginDrag(self, node, event):
         """Just copy necessary data"""
         self.DefineItems(node)
-        if self.selected_layer and \
-           not (self._restricted and gisenv()['LOCATION_NAME'] != self.selected_location.label):
+        if self.selected_layer and not (self._restricted and gisenv()[
+                                        'LOCATION_NAME'] != self.selected_location.label):
             event.Allow()
             self.OnCopyMap(event)
             Debug.msg(1, "DRAG")
@@ -656,8 +762,11 @@ class DataCatalogTree(LocationMapTree):
             return
         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(
+                    _("Maps can be copied only to current mapset"),
+                    parent=self)
                 event.Veto()
                 return
             if self.selected_location == self.copy_location and self.selected_mapset:
@@ -708,7 +817,9 @@ class DataCatalogTree(LocationMapTree):
         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 and self.selected_location == self.copy_location):
+        if not(
+                currentLocation and self.copy_layer and self.selected_location ==
+                self.copy_location):
             item.Enable(False)
 
         item = wx.MenuItem(menu, wx.NewId(), _("&Delete"))

+ 1 - 1
gui/wxpython/dbmgr/__init__.py

@@ -5,4 +5,4 @@ all = [
     'manager',
     'base',
     'dialogs',
-    ]
+]

File diff ditekan karena terlalu besar
+ 1703 - 1359
gui/wxpython/dbmgr/base.py


File diff ditekan karena terlalu besar
+ 313 - 272
gui/wxpython/dbmgr/dialogs.py


+ 8 - 6
gui/wxpython/dbmgr/g.gui.dbmgr.py

@@ -38,7 +38,7 @@ def main():
 
     from grass.script.setup import set_gui_path
     set_gui_path()
-    
+
     from core.utils import _
     from dbmgr.manager import AttributeManager
 
@@ -48,11 +48,13 @@ def main():
         gscript.fatal(_("Vector map <%s> not found") % options['map'])
 
     app = wx.App()
-    gscript.message(_("Loading attribute data for vector map <%s>...") % mapName)
-    f = AttributeManager(parent=None, id=wx.ID_ANY,
-                         title="%s - <%s>" % (_("GRASS GIS Attribute Table Manager"),
-                                              mapName),
-                         size=(900, 600), vectorName=mapName)
+    gscript.message(
+        _("Loading attribute data for vector map <%s>...") %
+        mapName)
+    f = AttributeManager(
+        parent=None, id=wx.ID_ANY, title="%s - <%s>" %
+        (_("GRASS GIS Attribute Table Manager"), mapName), size=(
+            900, 600), vectorName=mapName)
     f.Show()
 
     app.MainLoop()

+ 87 - 69
gui/wxpython/dbmgr/manager.py

@@ -26,21 +26,23 @@ import sys
 import os
 
 import wx
-import wx.lib.flatnotebook    as FN
+import wx.lib.flatnotebook as FN
 
 import grass.script as grass
 
-from core             import globalvar
-from core.gcmd        import GMessage
-from core.debug       import Debug
+from core import globalvar
+from core.gcmd import GMessage
+from core.debug import Debug
 from core.utils import _
-from dbmgr.base       import DbMgrBase
+from dbmgr.base import DbMgrBase
 from gui_core.widgets import GNotebook
-                
+
+
 class AttributeManager(wx.Frame, DbMgrBase):
-    def __init__(self, parent, id = wx.ID_ANY,
-                 title = None, vectorName = None, item = None, log = None,
-                 selection = None, **kwargs):
+
+    def __init__(self, parent, id=wx.ID_ANY,
+                 title=None, vectorName=None, item=None, log=None,
+                 selection=None, **kwargs):
         """GRASS Attribute Table Manager window
 
         :param parent: parent window
@@ -57,12 +59,12 @@ class AttributeManager(wx.Frame, DbMgrBase):
             mapdisplay = self.parent.GetMapDisplay()
         except:
             mapdisplay = None
-        
-        DbMgrBase.__init__(self, id = id, mapdisplay = mapdisplay,
-                           vectorName = vectorName, item = item, 
-                           log = log, statusbar = self, 
+
+        DbMgrBase.__init__(self, id=id, mapdisplay=mapdisplay,
+                           vectorName=vectorName, item=item,
+                           log=log, statusbar=self,
                            **kwargs)
-        
+
         wx.Frame.__init__(self, parent, id, *kwargs)
 
         # title
@@ -72,72 +74,86 @@ class AttributeManager(wx.Frame, DbMgrBase):
                 title += _("READONLY - ")
             title += "<%s>" % (self.dbMgrData['vectName'])
 
-
         self.SetTitle(title)
-        
+
         # icon
-        self.SetIcon(wx.Icon(os.path.join(globalvar.ICONDIR, 'grass_sql.ico'), wx.BITMAP_TYPE_ICO))
+        self.SetIcon(
+            wx.Icon(
+                os.path.join(
+                    globalvar.ICONDIR,
+                    'grass_sql.ico'),
+                wx.BITMAP_TYPE_ICO))
+
+        self.panel = wx.Panel(parent=self, id=wx.ID_ANY)
 
-        self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
-             
         if len(self.dbMgrData['mapDBInfo'].layers.keys()) == 0:
-            GMessage(parent = self.parent,
-                     message = _("Database connection for vector map <%s> "
-                                 "is not defined in DB file. "
-                                 "You can define new connection in "
-                                 "'Manage layers' tab.") % self.dbMgrData['vectName'])
-        
+            GMessage(
+                parent=self.parent, message=_(
+                    "Database connection for vector map <%s> "
+                    "is not defined in DB file. "
+                    "You can define new connection in "
+                    "'Manage layers' tab.") %
+                self.dbMgrData['vectName'])
+
         busy = wx.BusyInfo(message=_("Please wait, loading attribute data..."),
                            parent=self.parent)
         wx.SafeYield()
-        self.CreateStatusBar(number = 1)
+        self.CreateStatusBar(number=1)
+
+        self.notebook = GNotebook(self.panel, style=globalvar.FNPageDStyle)
 
-        self.notebook = GNotebook(self.panel, style = globalvar.FNPageDStyle)
-                
-        self.CreateDbMgrPage(parent = self, pageName = 'browse')
+        self.CreateDbMgrPage(parent=self, pageName='browse')
 
-        self.notebook.AddPage(page = self.pages['browse'], text = _("Browse data"),
-                              name = 'browse')
+        self.notebook.AddPage(page=self.pages['browse'], text=_("Browse data"),
+                              name='browse')
         self.pages['browse'].SetTabAreaColour(globalvar.FNPageColor)
 
-        self.CreateDbMgrPage(parent = self, pageName = 'manageTable')
+        self.CreateDbMgrPage(parent=self, pageName='manageTable')
 
-        self.notebook.AddPage(page = self.pages['manageTable'], text = _("Manage tables"),
-                              name = 'table')
+        self.notebook.AddPage(
+            page=self.pages['manageTable'],
+            text=_("Manage tables"),
+            name='table')
         self.pages['manageTable'].SetTabAreaColour(globalvar.FNPageColor)
 
-        self.CreateDbMgrPage(parent = self, pageName = 'manageLayer')
-        self.notebook.AddPage(page = self.pages['manageLayer'], text = _("Manage layers"),
-                              name = 'layers')
+        self.CreateDbMgrPage(parent=self, pageName='manageLayer')
+        self.notebook.AddPage(
+            page=self.pages['manageLayer'],
+            text=_("Manage layers"),
+            name='layers')
         del busy
 
         if selection:
             wx.CallAfter(self.notebook.SetSelectionByName, selection)
         else:
-            wx.CallAfter(self.notebook.SetSelection, 0) # select browse tab
-        
+            wx.CallAfter(self.notebook.SetSelection, 0)  # select browse tab
+
         # buttons
-        self.btnClose   = wx.Button(parent = self.panel, id = wx.ID_CLOSE)
+        self.btnClose = wx.Button(parent=self.panel, id=wx.ID_CLOSE)
         self.btnClose.SetToolTipString(_("Close Attribute Table Manager"))
-        self.btnReload = wx.Button(parent = self.panel, id = wx.ID_REFRESH)
-        self.btnReload.SetToolTipString(_("Reload currently selected attribute data"))
-        self.btnReset = wx.Button(parent = self.panel, id = wx.ID_CLEAR)
-        self.btnReset.SetToolTipString(_("Reload all attribute data (drop current selection)"))
-        
+        self.btnReload = wx.Button(parent=self.panel, id=wx.ID_REFRESH)
+        self.btnReload.SetToolTipString(
+            _("Reload currently selected attribute data"))
+        self.btnReset = wx.Button(parent=self.panel, id=wx.ID_CLEAR)
+        self.btnReset.SetToolTipString(
+            _("Reload all attribute data (drop current selection)"))
+
         # events
-        self.btnClose.Bind(wx.EVT_BUTTON,   self.OnCloseWindow)
-        self.btnReload.Bind(wx.EVT_BUTTON,  self.OnReloadData)
-        self.btnReset.Bind(wx.EVT_BUTTON,   self.OnReloadDataAll)
-        self.notebook.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
+        self.btnClose.Bind(wx.EVT_BUTTON, self.OnCloseWindow)
+        self.btnReload.Bind(wx.EVT_BUTTON, self.OnReloadData)
+        self.btnReset.Bind(wx.EVT_BUTTON, self.OnReloadDataAll)
+        self.notebook.Bind(
+            FN.EVT_FLATNOTEBOOK_PAGE_CHANGED,
+            self.OnPageChanged)
         self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
 
         # do layout
         self._layout()
 
         # self.SetMinSize(self.GetBestSize())
-        self.SetSize((700, 550)) # FIXME hard-coded size
+        self.SetSize((700, 550))  # FIXME hard-coded size
         self.SetMinSize(self.GetSize())
-    
+
     def _layout(self):
         """Do layout"""
         # frame body
@@ -145,36 +161,36 @@ class AttributeManager(wx.Frame, DbMgrBase):
 
         # buttons
         btnSizer = wx.BoxSizer(wx.HORIZONTAL)
-        btnSizer.Add(item = self.btnReset, proportion = 1,
-                     flag = wx.ALL | wx.ALIGN_RIGHT, border = 5)
-        btnSizer.Add(item = self.btnReload, proportion = 1,
-                     flag = wx.ALL | wx.ALIGN_RIGHT, border = 5)
-        btnSizer.Add(item = self.btnClose, proportion = 1,
-                     flag = wx.ALL | wx.ALIGN_RIGHT, border = 5)
+        btnSizer.Add(item=self.btnReset, proportion=1,
+                     flag=wx.ALL | wx.ALIGN_RIGHT, border=5)
+        btnSizer.Add(item=self.btnReload, proportion=1,
+                     flag=wx.ALL | wx.ALIGN_RIGHT, border=5)
+        btnSizer.Add(item=self.btnClose, proportion=1,
+                     flag=wx.ALL | wx.ALIGN_RIGHT, border=5)
 
-        mainSizer.Add(item = self.notebook, proportion = 1, flag = wx.EXPAND)
-        mainSizer.Add(item = btnSizer, flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
+        mainSizer.Add(item=self.notebook, proportion=1, flag=wx.EXPAND)
+        mainSizer.Add(item=btnSizer, flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
 
         self.panel.SetAutoLayout(True)
         self.panel.SetSizer(mainSizer)
         mainSizer.Fit(self.panel)
         self.Layout()
-  
+
     def OnCloseWindow(self, event):
         """Cancel button pressed"""
         if self.parent and self.parent.GetName() == 'LayerManager':
             # deregister ATM
             self.parent.dialogs['atm'].remove(self)
-                    
+
         if not isinstance(event, wx.CloseEvent):
             self.Destroy()
-        
+
         event.Skip()
 
     def OnReloadData(self, event):
         """Reload data"""
         if self.pages['browse']:
-            self.pages['browse'].OnDataReload(event) # TODO replace by signal
+            self.pages['browse'].OnDataReload(event)  # TODO replace by signal
 
     def OnReloadDataAll(self, event):
         """Reload all data"""
@@ -191,11 +207,13 @@ class AttributeManager(wx.Frame, DbMgrBase):
                 id = None
         except KeyError:
             id = None
-        
+
         if event.GetSelection() == self.notebook.GetPageIndexByName('browse') and id:
             win = self.FindWindowById(id)
             if win:
-                self.log.write(_("Number of loaded records: %d") % win.GetItemCount())
+                self.log.write(
+                    _("Number of loaded records: %d") %
+                    win.GetItemCount())
             else:
                 self.log.write("")
             self.btnReload.Enable()
@@ -204,14 +222,14 @@ class AttributeManager(wx.Frame, DbMgrBase):
             self.log.write("")
             self.btnReload.Enable(False)
             self.btnReset.Enable(False)
-        
-        event.Skip()   
+
+        event.Skip()
 
     def OnTextEnter(self, event):
         pass
 
     def UpdateDialog(self, layer):
         """Updates dialog layout for given layer"""
-        DbMgrBase.UpdateDialog(self, layer = layer)
+        DbMgrBase.UpdateDialog(self, layer=layer)
         # set current page selection
-        self.notebook.SetSelectionByName('layers') 
+        self.notebook.SetSelectionByName('layers')

File diff ditekan karena terlalu besar
+ 396 - 306
gui/wxpython/dbmgr/sqlbuilder.py


+ 70 - 53
gui/wxpython/dbmgr/vinfo.py

@@ -20,11 +20,12 @@ import types
 import wx
 
 from gui_core.gselect import VectorDBInfo as VectorDBInfoBase
-from core.gcmd        import RunCommand, GError
-from core.settings    import UserSettings
+from core.gcmd import RunCommand, GError
+from core.settings import UserSettings
 from core.utils import _
 import grass.script as grass
 
+
 def GetUnicodeValue(value):
     """Get unicode value
 
@@ -32,57 +33,69 @@ def GetUnicodeValue(value):
 
     :return: unicode value
     """
-    if type(value) == types.UnicodeType:
+    if isinstance(value, types.UnicodeType):
         return value
-    
-    enc = UserSettings.Get(group = 'atm', key = 'encoding', subkey = 'value')
+
+    enc = UserSettings.Get(group='atm', key='encoding', subkey='value')
     if not enc and 'GRASS_DB_ENCODING' in os.environ:
         enc = os.environ['GRASS_DB_ENCODING']
     else:
-        enc = 'utf-8' # assuming UTF-8
-    
-    return unicode(str(value), enc, errors = 'replace')
+        enc = 'utf-8'  # assuming UTF-8
+
+    return unicode(str(value), enc, errors='replace')
+
 
 def CreateDbInfoDesc(panel, mapDBInfo, layer):
     """Create database connection information content"""
-    infoFlexSizer = wx.FlexGridSizer (cols = 2, hgap = 1, vgap = 1)
+    infoFlexSizer = wx.FlexGridSizer(cols=2, hgap=1, vgap=1)
     infoFlexSizer.AddGrowableCol(1)
-    
-    infoFlexSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY,
-                                         label = "Driver:"))
-    infoFlexSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY,
-                                         label = mapDBInfo.layers[layer]['driver']))
-    infoFlexSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY,
-                                         label = "Database:"))
-    infoFlexSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY,
-                                         label = mapDBInfo.layers[layer]['database']))
-    infoFlexSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY,
-                                         label = "Table:"))
-    infoFlexSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY,
-                                         label = mapDBInfo.layers[layer]['table']))
-    infoFlexSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY,
-                                         label = "Key:"))
-    infoFlexSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY,
-                                         label = mapDBInfo.layers[layer]['key']))
-    
+
+    infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label="Driver:"))
+    infoFlexSizer.Add(
+        item=wx.StaticText(
+            parent=panel,
+            id=wx.ID_ANY,
+            label=mapDBInfo.layers[layer]['driver']))
+    infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label="Database:"))
+    infoFlexSizer.Add(
+        item=wx.StaticText(
+            parent=panel,
+            id=wx.ID_ANY,
+            label=mapDBInfo.layers[layer]['database']))
+    infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label="Table:"))
+    infoFlexSizer.Add(
+        item=wx.StaticText(
+            parent=panel,
+            id=wx.ID_ANY,
+            label=mapDBInfo.layers[layer]['table']))
+    infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label="Key:"))
+    infoFlexSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
+                                         label=mapDBInfo.layers[layer]['key']))
+
     return infoFlexSizer
-        
+
+
 class VectorDBInfo(VectorDBInfoBase):
     """Class providing information about attribute tables
     linked to the vector map"""
+
     def __init__(self, map):
         VectorDBInfoBase.__init__(self, map)
-        
+
     def GetColumns(self, table):
         """Return list of columns names (based on their index)"""
         try:
             names = [''] * len(self.tables[table].keys())
         except KeyError:
             return []
-        
+
         for name, desc in self.tables[table].iteritems():
             names[desc['index']] = name
-        
+
         return names
 
     def SelectByPoint(self, queryCoords, qdist):
@@ -93,17 +106,21 @@ class VectorDBInfo(VectorDBInfoBase):
         nselected = 0
 
         try:
-            data = grass.vector_what(map=self.map,
-                                     coord=(float(queryCoords[0]), float(queryCoords[1])),
-                                     distance=float(qdist))
+            data = grass.vector_what(
+                map=self.map, coord=(
+                    float(
+                        queryCoords[0]), float(
+                        queryCoords[1])), distance=float(qdist))
         except grass.ScriptError:
-            GError(parent=None,
-                   message=_("Failed to query vector map <{map}>. "
-                             "Check database settings and topology.").format(map=self.map))
+            GError(
+                parent=None, message=_(
+                    "Failed to query vector map <{map}>. "
+                    "Check database settings and topology.").format(
+                    map=self.map))
 
         if len(data) < 1 or all(('Table' not in record) for record in data):
             return None
-        
+
         # process attributes
         ret = dict()
         for key in ['Category', 'Layer', 'Table', 'Id']:
@@ -119,11 +136,11 @@ class VectorDBInfo(VectorDBInfoBase):
                     value = None
                 else:
                     if self.tables[table][key]['ctype'] != types.StringType:
-                        value = self.tables[table][key]['ctype'] (value)
+                        value = self.tables[table][key]['ctype'](value)
                     else:
                         value = GetUnicodeValue(value)
                 self.tables[table][key]['values'].append(value)
-            
+
             for key, value in record.iteritems():
                 if key == 'Attributes':
                     continue
@@ -133,8 +150,8 @@ class VectorDBInfo(VectorDBInfoBase):
                 ret['Id'].append(None)
 
         return ret
-    
-    def SelectFromTable(self, layer, cols = '*', where = None):
+
+    def SelectFromTable(self, layer, cols='*', where=None):
         """Select records from the table
 
         Return number of selected records, -1 on error
@@ -144,29 +161,29 @@ class VectorDBInfo(VectorDBInfoBase):
 
         nselected = 0
 
-        table = self.layers[layer]["table"] # get table desc
+        table = self.layers[layer]["table"]  # get table desc
         # select values (only one record)
         if where is None or where is '':
             sql = "SELECT %s FROM %s" % (cols, table)
         else:
             sql = "SELECT %s FROM %s WHERE %s" % (cols, table, where)
-        
+
         ret = RunCommand('db.select',
-                         read = True,
-                         quiet = True,
-                         flags = 'v',
-                         sql= sql,
-                         database = self.layers[layer]["database"],
-                         driver = self.layers[layer]["driver"])
-        
+                         read=True,
+                         quiet=True,
+                         flags='v',
+                         sql=sql,
+                         database=self.layers[layer]["database"],
+                         driver=self.layers[layer]["driver"])
+
         # self.tables[table][key][1] = str(cat)
         if ret:
             for line in ret.splitlines():
                 name, value = line.split('|')
                 # casting ...
                 if value:
-                    if self.tables[table][name]['ctype'] != type(''):
-                        value = self.tables[table][name]['ctype'] (value)
+                    if not isinstance('', self.tables[table][name]['ctype']):
+                        value = self.tables[table][name]['ctype'](value)
                     else:
                         value = GetUnicodeValue(value)
                 else:

+ 29 - 18
gui/wxpython/docs/wxgui_sphinx/conf.py

@@ -12,7 +12,8 @@
 # All configuration values have a default; values that are commented out
 # serve to show the default.
 
-import sys, os
+import sys
+import os
 from datetime import date
 import string
 from shutil import copy
@@ -22,12 +23,19 @@ from shutil import copy
 # documentation root, use os.path.abspath to make it absolute, like shown here.
 if not os.getenv('GISBASE'):
     sys.exit("GISBASE not defined")
-sys.path.insert(0, os.path.abspath(os.path.join(os.environ['GISBASE'], 'etc', 'python', 'grass')))
+sys.path.insert(
+    0,
+    os.path.abspath(
+        os.path.join(
+            os.environ['GISBASE'],
+            'etc',
+            'python',
+            'grass')))
 
 from grass.script import core
 
-footer_tmpl = string.Template(\
-r"""
+footer_tmpl = string.Template(
+    r"""
 {% block footer %}<hr class="header">
 <p><a href="../index.html">Help Index</a> | <a href="../topics.html">Topics Index</a> | <a href="../keywords.html">Keywords Index</a> | <a href="../full_index.html">Full Index</a></p>
 <p>&copy; 2003-${year} <a href="http://grass.osgeo.org">GRASS Development Team</a>, GRASS GIS ${grass_version} Reference Manual</p>
@@ -39,10 +47,13 @@ today = date.today()
 
 copy("_templates/layout.html.template", "_templates/layout.html")
 with open("_templates/layout.html", "a+b") as f:
-    f.write(footer_tmpl.substitute(grass_version=grass_version, year=today.year))
+    f.write(
+        footer_tmpl.substitute(
+            grass_version=grass_version,
+            year=today.year))
     f.close()
 
-# -- General configuration -----------------------------------------------------
+# -- General configuration -----------------------------------------------
 
 # If your documentation needs a minimal Sphinx version, state it here.
 #needs_sphinx = '1.0'
@@ -174,7 +185,7 @@ html_static_path = ['_static']
 #html_use_smartypants = True
 
 # Custom sidebar templates, maps document names to template names.
-html_sidebars = {"**":["localtoc.html",'relations.html','searchbox.html']}
+html_sidebars = {"**": ["localtoc.html", 'relations.html', 'searchbox.html']}
 
 # Additional templates that should be rendered to pages, maps page names to
 # template names.
@@ -213,22 +224,22 @@ htmlhelp_basename = 'wxGUIdoc'
 # -- Options for LaTeX output ---------------------------------------------
 
 latex_elements = {
-# The paper size ('letterpaper' or 'a4paper').
-'papersize': 'a4paper',
+    # The paper size ('letterpaper' or 'a4paper').
+    'papersize': 'a4paper',
 
-# The font size ('10pt', '11pt' or '12pt').
-'pointsize': '10pt',
+    # The font size ('10pt', '11pt' or '12pt').
+    'pointsize': '10pt',
 
-# Additional stuff for the LaTeX preamble.
-#'preamble': '',
+    # Additional stuff for the LaTeX preamble.
+    #'preamble': '',
 }
 
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title,
 #  author, documentclass [howto, manual, or own class]).
 latex_documents = [
-  ('index', 'wxGUI.tex', u'wxGUI Documentation',
-   u'GRASS Development Team', 'manual'),
+    ('index', 'wxGUI.tex', u'wxGUI Documentation',
+     u'GRASS Development Team', 'manual'),
 ]
 
 # The name of an image file (relative to this directory) to place at the top of
@@ -271,9 +282,9 @@ man_pages = [
 # (source start file, target name, title, author,
 #  dir menu entry, description, category)
 texinfo_documents = [
-  ('index', 'wxGUI', u'wxGUI Documentation',
-   u'GRASS Development Team', 'wxGUI', 'One line description of project.',
-   'Miscellaneous'),
+    ('index', 'wxGUI', u'wxGUI Documentation',
+     u'GRASS Development Team', 'wxGUI', 'One line description of project.',
+     'Miscellaneous'),
 ]
 
 # Documents to append as an appendix to all manuals.

+ 1 - 1
gui/wxpython/gcp/__init__.py

@@ -2,4 +2,4 @@ all = [
     'manager',
     'mapdisplay',
     'toolbars',
-    ]
+]

+ 2 - 2
gui/wxpython/gcp/g.gui.gcp.py

@@ -47,10 +47,10 @@ def main():
     options, flags = gscript.parser()
 
     import wx
-    
+
     from grass.script.setup import set_gui_path
     set_gui_path()
-    
+
     from core.settings import UserSettings
     from core.globalvar import CheckWxVersion
     from core.giface import StandaloneGrassInterface

File diff ditekan karena terlalu besar
+ 1016 - 669
gui/wxpython/gcp/manager.py


+ 102 - 85
gui/wxpython/gcp/mapdisplay.py

@@ -23,14 +23,14 @@ from core import globalvar
 import wx
 import wx.aui
 
-from mapdisp.toolbars  import MapToolbar
-from gcp.toolbars      import GCPDisplayToolbar, GCPManToolbar
-from mapdisp.gprint    import PrintOptions
-from core.gcmd         import GMessage
+from mapdisp.toolbars import MapToolbar
+from gcp.toolbars import GCPDisplayToolbar, GCPManToolbar
+from mapdisp.gprint import PrintOptions
+from core.gcmd import GMessage
 from core.utils import _
-from gui_core.dialogs  import GetImageHandlers, ImageSizeDialog
-from gui_core.mapdisp  import SingleMapFrame
-from core.settings     import UserSettings
+from gui_core.dialogs import GetImageHandlers, ImageSizeDialog
+from gui_core.mapdisp import SingleMapFrame
+from core.settings import UserSettings
 from mapwin.buffered import BufferedMapWindow
 from mapwin.base import MapWindowProperties
 
@@ -40,10 +40,12 @@ import gcp.statusbar as sbgcp
 # for standalone app
 cmdfilename = None
 
+
 class MapFrame(SingleMapFrame):
     """Main frame for map display window. Drawing takes place in
     child double buffered drawing window.
     """
+
     def __init__(self, parent, giface,
                  title=_("GRASS GIS Manage Ground Control Points"),
                  toolbars=["gcpdisp"], Map=None, auimgr=None,
@@ -58,9 +60,16 @@ class MapFrame(SingleMapFrame):
         :param auimgs: AUI manager
         :param kwargs: wx.Frame attribures
         """
-        
-        SingleMapFrame.__init__(self, parent = parent, giface = giface, title = title,
-                              Map = Map, auimgr = auimgr, name = name, **kwargs)
+
+        SingleMapFrame.__init__(
+            self,
+            parent=parent,
+            giface=giface,
+            title=title,
+            Map=Map,
+            auimgr=auimgr,
+            name=name,
+            **kwargs)
 
         self._giface = giface
         # properties are shared in other objects, so defining here
@@ -76,15 +85,15 @@ class MapFrame(SingleMapFrame):
 
         self.activemap = self.toolbars['gcpdisp'].togglemap
         self.activemap.SetSelection(0)
-        
-        self.SrcMap        = self.grwiz.SrcMap       # instance of render.Map
-        self.TgtMap        = self.grwiz.TgtMap       # instance of render.Map
+
+        self.SrcMap = self.grwiz.SrcMap       # instance of render.Map
+        self.TgtMap = self.grwiz.TgtMap       # instance of render.Map
         self._mgr.SetDockSizeConstraint(0.5, 0.5)
 
         #
         # Add statusbar
         #
-        
+
         # items for choice
         self.statusbarItems = [sb.SbCoordinates,
                                sb.SbRegionExtent,
@@ -96,32 +105,35 @@ class MapFrame(SingleMapFrame):
                                sb.SbProjection,
                                sbgcp.SbGoToGCP,
                                sbgcp.SbRMSError]
-                            
-        
+
         # create statusbar and its manager
-        statusbar = self.CreateStatusBar(number = 4, style = 0)
+        statusbar = self.CreateStatusBar(number=4, style=0)
         statusbar.SetStatusWidths([-5, -2, -1, -1])
-        self.statusbarManager = sb.SbManager(mapframe = self, statusbar = statusbar)
-        
+        self.statusbarManager = sb.SbManager(
+            mapframe=self, statusbar=statusbar)
+
         # fill statusbar manager
-        self.statusbarManager.AddStatusbarItemsByClass(self.statusbarItems, mapframe = self, statusbar = statusbar)
-        self.statusbarManager.AddStatusbarItem(sb.SbMask(self, statusbar = statusbar, position = 2))
-        self.statusbarManager.AddStatusbarItem(sb.SbRender(self, statusbar = statusbar, position = 3))
-        
-        self.statusbarManager.SetMode(8) # goto GCP
+        self.statusbarManager.AddStatusbarItemsByClass(
+            self.statusbarItems, mapframe=self, statusbar=statusbar)
+        self.statusbarManager.AddStatusbarItem(
+            sb.SbMask(self, statusbar=statusbar, position=2))
+        self.statusbarManager.AddStatusbarItem(
+            sb.SbRender(self, statusbar=statusbar, position=3))
+
+        self.statusbarManager.SetMode(8)  # goto GCP
 
         #
         # Init map display (buffered DC & set default cursor)
         #
         self.grwiz.SwitchEnv('source')
-        self.SrcMapWindow = BufferedMapWindow(parent=self, giface=self._giface, id=wx.ID_ANY,
-                                              properties=self.mapWindowProperties,
-                                              Map=self.SrcMap)
+        self.SrcMapWindow = BufferedMapWindow(
+            parent=self, giface=self._giface, id=wx.ID_ANY,
+            properties=self.mapWindowProperties, Map=self.SrcMap)
 
         self.grwiz.SwitchEnv('target')
-        self.TgtMapWindow = BufferedMapWindow(parent=self, giface=self._giface, id=wx.ID_ANY,
-                                              properties=self.mapWindowProperties,
-                                              Map=self.TgtMap)
+        self.TgtMapWindow = BufferedMapWindow(
+            parent=self, giface=self._giface, id=wx.ID_ANY,
+            properties=self.mapWindowProperties, Map=self.TgtMap)
         self.MapWindow = self.SrcMapWindow
         self.Map = self.SrcMap
         self._setUpMapWindow(self.SrcMapWindow)
@@ -139,9 +151,9 @@ class MapFrame(SingleMapFrame):
         #
         # initialize region values
         #
-        self._initMap(Map = self.SrcMap) 
-        self._initMap(Map = self.TgtMap) 
-        
+        self._initMap(Map=self.SrcMap)
+        self._initMap(Map=self.TgtMap)
+
         self.GetMapToolbar().SelectDefault()
 
         #
@@ -149,29 +161,30 @@ class MapFrame(SingleMapFrame):
         #
         self.activemap.Bind(wx.EVT_CHOICE, self.OnUpdateActive)
         self.Bind(wx.EVT_SIZE, self.OnSize)
-        
+
         #
         # Update fancy gui style
         #
-        # AuiManager wants a CentrePane, workaround to get two equally sized windows
+        # AuiManager wants a CentrePane, workaround to get two equally sized
+        # windows
         self.list = self.CreateGCPList()
 
         #self.SrcMapWindow.SetSize((300, 300))
         #self.TgtMapWindow.SetSize((300, 300))
         self.list.SetSize((100, 150))
         self._mgr.AddPane(self.list, wx.aui.AuiPaneInfo().
-                  Name("gcplist").Caption(_("GCP List")).LeftDockable(False).
-                  RightDockable(False).PinButton().FloatingSize((600,200)).
-                  CloseButton(False).DestroyOnClose(True).
-                  Top().Layer(1).MinSize((200,100)))
+                          Name("gcplist").Caption(_("GCP List")).LeftDockable(False).
+                          RightDockable(False).PinButton().FloatingSize((600, 200)).
+                          CloseButton(False).DestroyOnClose(True).
+                          Top().Layer(1).MinSize((200, 100)))
         self._mgr.AddPane(self.SrcMapWindow, wx.aui.AuiPaneInfo().
-                  Name("source").Caption(_("Source Display")).Dockable(False).
-                  CloseButton(False).DestroyOnClose(True).Floatable(False).
-                  Centre())
+                          Name("source").Caption(_("Source Display")).Dockable(False).
+                          CloseButton(False).DestroyOnClose(True).Floatable(False).
+                          Centre())
         self._mgr.AddPane(self.TgtMapWindow, wx.aui.AuiPaneInfo().
-                  Name("target").Caption(_("Target Display")).Dockable(False).
-                  CloseButton(False).DestroyOnClose(True).Floatable(False).
-                  Right().Layer(0))
+                          Name("target").Caption(_("Target Display")).Dockable(False).
+                          CloseButton(False).DestroyOnClose(True).Floatable(False).
+                          Right().Layer(0))
 
         srcwidth, srcheight = self.SrcMapWindow.GetSize()
         tgtwidth, tgtheight = self.TgtMapWindow.GetSize()
@@ -192,7 +205,7 @@ class MapFrame(SingleMapFrame):
         # Init print module and classes
         #
         self.printopt = PrintOptions(self, self.MapWindow)
-        
+
         #
         # Initialization of digitization tool
         #
@@ -201,7 +214,7 @@ class MapFrame(SingleMapFrame):
         # set active map
         self.MapWindow = self.SrcMapWindow
         self.Map = self.SrcMap
-        
+
         # do not init zoom history here, that happens when zooming to map(s)
 
         #
@@ -213,7 +226,7 @@ class MapFrame(SingleMapFrame):
         self.dialogs['barscale'] = None
         self.dialogs['legend'] = None
 
-        self.decorationDialog = None # decoration/overlays
+        self.decorationDialog = None  # decoration/overlays
 
         # doing nice things in statusbar when other things are ready
         self.statusbarManager.Update()
@@ -231,7 +244,7 @@ class MapFrame(SingleMapFrame):
 
     def AddToolbar(self, name):
         """Add defined toolbar to the window
-        
+
         Currently known toolbars are:
          - 'map'     - basic map toolbar
          - 'vdigit'  - vector digitizer
@@ -254,7 +267,8 @@ class MapFrame(SingleMapFrame):
 
         # GCP display
         elif name == "gcpdisp":
-            self.toolbars['gcpdisp'] = GCPDisplayToolbar(self, self._toolSwitcher)
+            self.toolbars['gcpdisp'] = GCPDisplayToolbar(
+                self, self._toolSwitcher)
 
             self._mgr.AddPane(self.toolbars['gcpdisp'],
                               wx.aui.AuiPaneInfo().
@@ -265,7 +279,7 @@ class MapFrame(SingleMapFrame):
                               CloseButton(False).Layer(2))
 
             if self.show_target == False:
-                self.toolbars['gcpdisp'].Enable('zoommenu', enable = False)
+                self.toolbars['gcpdisp'].Enable('zoommenu', enable=False)
 
             self.toolbars['gcpman'] = GCPManToolbar(self)
 
@@ -276,7 +290,7 @@ class MapFrame(SingleMapFrame):
                               LeftDockable(False).RightDockable(False).
                               BottomDockable(False).TopDockable(True).
                               CloseButton(False).Layer(2))
-            
+
         self._mgr.Update()
 
     def OnUpdateProgress(self, event):
@@ -284,9 +298,9 @@ class MapFrame(SingleMapFrame):
         Update progress bar info
         """
         self.GetProgressBar().UpdateProgress(event.layer, event.map)
-        
+
         event.Skip()
-        
+
     def OnFocus(self, event):
         """
         Change choicebook page to match display.
@@ -304,8 +318,8 @@ class MapFrame(SingleMapFrame):
     def OnDraw(self, event):
         """Re-display current map composition
         """
-        self.MapWindow.UpdateMap(render = False)
-        
+        self.MapWindow.UpdateMap(render=False)
+
     def OnRender(self, event):
         """Re-render map composition (each map layer)
         """
@@ -318,13 +332,13 @@ class MapFrame(SingleMapFrame):
         self.SrcMapWindow.UpdateMap(render=True)
         if self.show_target:
             self.TgtMapWindow.UpdateMap(render=True)
-        
+
         # update statusbar
         self.StatusbarUpdate()
 
     def OnPointer(self, event):
         """Pointer button clicked
-        """      
+        """
         self.SrcMapWindow.SetModePointer()
         self.TgtMapWindow.SetModePointer()
         # change the default cursor
@@ -364,8 +378,8 @@ class MapFrame(SingleMapFrame):
         """
         img = self.MapWindow.img
         if not img:
-            GMessage(parent = self,
-                     message = _("Nothing to render (empty map). Operation canceled."))
+            GMessage(parent=self, message=_(
+                "Nothing to render (empty map). Operation canceled."))
             return
         filetype, ltype = GetImageHandlers(img)
 
@@ -377,29 +391,29 @@ class MapFrame(SingleMapFrame):
             return
         width, height = dlg.GetValues()
         dlg.Destroy()
-        
+
         # get filename
-        dlg = wx.FileDialog(parent = self,
-                            message = _("Choose a file name to save the image "
-                                        "(no need to add extension)"),
-                            wildcard = filetype,
+        dlg = wx.FileDialog(parent=self,
+                            message=_("Choose a file name to save the image "
+                                      "(no need to add extension)"),
+                            wildcard=filetype,
                             style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
-        
+
         if dlg.ShowModal() == wx.ID_OK:
             path = dlg.GetPath()
             if not path:
                 dlg.Destroy()
                 return
-            
+
             base, ext = os.path.splitext(path)
             fileType = ltype[dlg.GetFilterIndex()]['type']
-            extType  = ltype[dlg.GetFilterIndex()]['ext']
+            extType = ltype[dlg.GetFilterIndex()]['ext']
             if ext != extType:
                 path = base + '.' + extType
-            
+
             self.MapWindow.SaveToFile(path, fileType,
                                       width, height)
-            
+
         dlg.Destroy()
 
     def PrintMenu(self, event):
@@ -430,25 +444,25 @@ class MapFrame(SingleMapFrame):
         """
         Set display extents to match selected raster map (ignore NULLs)
         """
-        self.MapWindow.ZoomToMap(ignoreNulls = True)
-        
+        self.MapWindow.ZoomToMap(ignoreNulls=True)
+
     def OnZoomToSaved(self, event):
         """Set display geometry to match extents in
         saved region file
         """
         self.MapWindow.SetRegion(zoomOnly=True)
-        
+
     def OnDisplayToWind(self, event):
         """Set computational region (WIND file) to match display
         extents
         """
         self.MapWindow.DisplayToWind()
- 
+
     def SaveDisplayRegion(self, event):
         """Save display extents to named region file.
         """
         self.MapWindow.SaveDisplayRegion()
-        
+
     def OnZoomMenu(self, event):
         """Popup Zoom menu
         """
@@ -456,11 +470,13 @@ class MapFrame(SingleMapFrame):
         zoommenu = wx.Menu()
         # Add items to the menu
 
-        zoomwind = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to computational region (set with g.region)'))
+        zoomwind = wx.MenuItem(zoommenu, wx.ID_ANY, _(
+            'Zoom to computational region (set with g.region)'))
         zoommenu.AppendItem(zoomwind)
         self.Bind(wx.EVT_MENU, self.OnZoomToWind, zoomwind)
 
-        zoomdefault = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to default region'))
+        zoomdefault = wx.MenuItem(
+            zoommenu, wx.ID_ANY, _('Zoom to default region'))
         zoommenu.AppendItem(zoomdefault)
         self.Bind(wx.EVT_MENU, self.OnZoomToDefault, zoomdefault)
 
@@ -468,11 +484,13 @@ class MapFrame(SingleMapFrame):
         zoommenu.AppendItem(zoomsaved)
         self.Bind(wx.EVT_MENU, self.OnZoomToSaved, zoomsaved)
 
-        savewind = wx.MenuItem(zoommenu, wx.ID_ANY, _('Set computational region from display'))
+        savewind = wx.MenuItem(zoommenu, wx.ID_ANY, _(
+            'Set computational region from display'))
         zoommenu.AppendItem(savewind)
         self.Bind(wx.EVT_MENU, self.OnDisplayToWind, savewind)
 
-        savezoom = wx.MenuItem(zoommenu, wx.ID_ANY, _('Save display geometry to named region'))
+        savezoom = wx.MenuItem(zoommenu, wx.ID_ANY, _(
+            'Save display geometry to named region'))
         zoommenu.AppendItem(savezoom)
         self.Bind(wx.EVT_MENU, self.SaveDisplayRegion, savezoom)
 
@@ -480,13 +498,12 @@ class MapFrame(SingleMapFrame):
         # will be called before PopupMenu returns.
         self.PopupMenu(zoommenu)
         zoommenu.Destroy()
-        
-        
+
     def IsStandalone(self):
         """Check if Map display is standalone"""
         # we do not know and we do not care, so always False
         return True
-    
+
     def GetLayerManager(self):
         """Get reference to Layer Manager
 
@@ -496,13 +513,13 @@ class MapFrame(SingleMapFrame):
 
     def GetSrcWindow(self):
         return self.SrcMapWindow
-        
+
     def GetTgtWindow(self):
         return self.TgtMapWindow
-    
+
     def GetShowTarget(self):
         return self.show_target
-        
+
     def GetMapToolbar(self):
         """Returns toolbar with zooming tools"""
         return self.toolbars['gcpdisp']

+ 2 - 0
gui/wxpython/gcp/statusbar.py

@@ -30,6 +30,7 @@ class SbGoToGCP(SbItem):
     Requires MapFrame.GetSrcWindow, MapFrame.GetTgtWindow,
     MapFrame.GetListCtrl, MapFrame.GetMapCoordList.
     """
+
     def __init__(self, mapframe, statusbar, position=0):
         SbItem.__init__(self, mapframe, statusbar, position)
         self.name = 'gotoGCP'
@@ -112,6 +113,7 @@ class SbRMSError(SbTextItem):
 
     Requires MapFrame.GetFwdError, MapFrame.GetBkwError.
     """
+
     def __init__(self, mapframe, statusbar, position=0):
         SbTextItem.__init__(self, mapframe, statusbar, position)
         self.name = 'RMSError'

+ 47 - 37
gui/wxpython/gcp/toolbars.py

@@ -20,7 +20,7 @@ import sys
 
 import wx
 
-from core              import globalvar
+from core import globalvar
 from core.utils import _
 from gui_core.toolbars import BaseToolbar, BaseIcons
 from icons.icon import MetaIcon
@@ -31,32 +31,33 @@ class GCPManToolbar(BaseToolbar):
 
     :param parent: reference to GCP widget
     """
+
     def __init__(self, parent):
         BaseToolbar.__init__(self, parent)
-        
+
         self.InitToolbar(self._toolbarData())
-        
+
         # realize the toolbar
         self.Realize()
 
     def _toolbarData(self):
         icons = {
-            'gcpAdd'     : MetaIcon(img = 'gcp-add',
-                                    label = _('Add new GCP to the list')),
-            'gcpDelete'  : MetaIcon(img = 'gcp-delete',
-                                    label = _('Delete selected GCP')),
-            'gcpClear'   : MetaIcon(img = 'gcp-remove',
-                                    label = _('Clear selected GCP')),
-            'gcpRms'     : MetaIcon(img = 'gcp-rms',
-                                    label = _('Recalculate RMS error')),
-            'georectify' : MetaIcon(img = 'georectify',
-                                    label = _('Georectify')),
-            'gcpSave'    : MetaIcon(img = 'gcp-save',
-                                    label = _('Save GCPs to POINTS file')),
-            'gcpReload'  : MetaIcon(img = 'reload',
-                                    label = _('Reload GCPs from POINTS file')),
-            }
-        
+            'gcpAdd': MetaIcon(img='gcp-add',
+                               label=_('Add new GCP to the list')),
+            'gcpDelete': MetaIcon(img='gcp-delete',
+                                  label=_('Delete selected GCP')),
+            'gcpClear': MetaIcon(img='gcp-remove',
+                                 label=_('Clear selected GCP')),
+            'gcpRms': MetaIcon(img='gcp-rms',
+                               label=_('Recalculate RMS error')),
+            'georectify': MetaIcon(img='georectify',
+                                   label=_('Georectify')),
+            'gcpSave': MetaIcon(img='gcp-save',
+                                label=_('Save GCPs to POINTS file')),
+            'gcpReload': MetaIcon(img='reload',
+                                  label=_('Reload GCPs from POINTS file')),
+        }
+
         return self._getToolbarData((('gcpAdd', icons["gcpAdd"],
                                       self.parent.AddGCP),
                                      ('gcpDelete', icons["gcpDelete"],
@@ -74,48 +75,57 @@ class GCPManToolbar(BaseToolbar):
                                      ('gcpReload', icons["gcpReload"],
                                       self.parent.ReloadGCPs))
                                     )
-    
+
+
 class GCPDisplayToolbar(BaseToolbar):
     """GCP Display toolbar
     """
+
     def __init__(self, parent, toolSwitcher):
         """GCP Display toolbar constructor
         """
         BaseToolbar.__init__(self, parent, toolSwitcher)
-        
+
         self.InitToolbar(self._toolbarData())
         self._default = self.gcpset
-        
+
         # add tool to toggle active map window
         self.togglemapid = wx.NewId()
-        self.togglemap = wx.Choice(parent = self, id = self.togglemapid,
-                                   choices = [_('source'), _('target')])
+        self.togglemap = wx.Choice(parent=self, id=self.togglemapid,
+                                   choices=[_('source'), _('target')])
 
         self.InsertControl(10, self.togglemap)
 
-        self.SetToolShortHelp(self.togglemapid, '%s %s %s' % (_('Set map canvas for '),
-                                                              BaseIcons["zoomBack"].GetLabel(),
-                                                              _(' / Zoom to map')))
+        self.SetToolShortHelp(
+            self.togglemapid, '%s %s %s' %
+            (_('Set map canvas for '),
+             BaseIcons["zoomBack"].GetLabel(),
+             _(' / Zoom to map')))
 
         for tool in (self.gcpset, self.pan, self.zoomin, self.zoomout):
-            self.toolSwitcher.AddToolToGroup(group='mouseUse', toolbar=self, tool=tool)
+            self.toolSwitcher.AddToolToGroup(
+                group='mouseUse', toolbar=self, tool=tool)
 
         # realize the toolbar
         self.Realize()
 
         self.EnableTool(self.zoomback, False)
-        
+
     def _toolbarData(self):
         """Toolbar data"""
         icons = {
-            'gcpSet'    : MetaIcon(img = 'gcp-create',
-                                   label = _('Update GCP coordinates'),
-                                   desc = _('Update GCP coordinates)')),
-            'quit'      : BaseIcons['quit'].SetLabel(_('Quit georectification tool')),
-            'settings'  : BaseIcons['settings'].SetLabel( _('Georectifier settings')),
-            'help'      : BaseIcons['help'].SetLabel(_('Georectifier manual')),
-            }
-        
+            'gcpSet': MetaIcon(
+                img='gcp-create',
+                label=_('Update GCP coordinates'),
+                desc=_('Update GCP coordinates)')),
+            'quit': BaseIcons['quit'].SetLabel(
+                _('Quit georectification tool')),
+            'settings': BaseIcons['settings'].SetLabel(
+                _('Georectifier settings')),
+            'help': BaseIcons['help'].SetLabel(
+                _('Georectifier manual')),
+        }
+
         return self._getToolbarData((("displaymap", BaseIcons["display"],
                                       self.parent.OnDraw),
                                      ("rendermap", BaseIcons["render"],

File diff ditekan karena terlalu besar
+ 449 - 364
gui/wxpython/gis_set.py


+ 9 - 8
gui/wxpython/gis_set_error.py

@@ -1,4 +1,4 @@
-""" 
+"""
 @package gis_set_error
 
 GRASS start-up screen error message.
@@ -17,21 +17,22 @@ import sys
 from core import globalvar
 import wx
 
+
 def main():
     app = wx.App()
-    
+
     if len(sys.argv) == 1:
         msg = "Unknown reason"
     else:
         msg = ''
         for m in sys.argv[1:]:
             msg += m
-    
-    wx.MessageBox(caption = "Error",
-                  message = msg,
-                  style = wx.OK | wx.ICON_ERROR)
-    
+
+    wx.MessageBox(caption="Error",
+                  message=msg,
+                  style=wx.OK | wx.ICON_ERROR)
+
     app.MainLoop()
-    
+
 if __name__ == "__main__":
     main()

+ 1 - 1
gui/wxpython/gmodeler/__init__.py

@@ -7,4 +7,4 @@ all = [
     'dialogs',
     'toolbars',
     'frame',
-    ]
+]

File diff ditekan karena terlalu besar
+ 440 - 358
gui/wxpython/gmodeler/dialogs.py


File diff ditekan karena terlalu besar
+ 845 - 648
gui/wxpython/gmodeler/frame.py


+ 3 - 2
gui/wxpython/gmodeler/g.gui.gmodeler.py

@@ -36,14 +36,15 @@
 
 import grass.script as gscript
 
+
 def main():
     options, flags = gscript.parser()
 
     import wx
-    
+
     from grass.script.setup import set_gui_path
     set_gui_path()
-    
+
     from core.giface import StandaloneGrassInterface
     from core.globalvar import CheckWxVersion
     from gmodeler.frame import ModelFrame

+ 5 - 3
gui/wxpython/gmodeler/giface.py

@@ -16,17 +16,19 @@ This program is free software under the GNU General Public License
 
 from grass.pydispatch.signal import Signal
 
+
 class GraphicalModelerGrassInterface():
     """@implements core::giface::GrassInterface"""
+
     def __init__(self, model):
         self._model = model
-    
+
         # Signal emitted to request updating of map (TODO)
         self.updateMap = Signal('GraphicalModelerGrassInterface.updateMap')
-        
+
     def GetLayerTree(self):
         return None
-    
+
     def GetLayerList(self, prompt):
         return self._model.GetMaps(prompt)
 

+ 7 - 5
gui/wxpython/gmodeler/menudata.py

@@ -17,12 +17,14 @@ This program is free software under the GNU General Public License
 import os
 
 from core import globalvar
-from core.menutree  import MenuTreeModelBuilder
+from core.menutree import MenuTreeModelBuilder
+
 
 class ModelerMenuData(MenuTreeModelBuilder):
-    def __init__(self, filename = None):
+
+    def __init__(self, filename=None):
         if not filename:
-            filename = os.path.join(globalvar.WXGUIDIR, 'xml', 'menudata_modeler.xml')
-        
-        MenuTreeModelBuilder.__init__(self, filename)
+            filename = os.path.join(
+                globalvar.WXGUIDIR, 'xml', 'menudata_modeler.xml')
 
+        MenuTreeModelBuilder.__init__(self, filename)

File diff ditekan karena terlalu besar
+ 903 - 690
gui/wxpython/gmodeler/model.py


File diff ditekan karena terlalu besar
+ 528 - 386
gui/wxpython/gmodeler/preferences.py


+ 40 - 38
gui/wxpython/gmodeler/toolbars.py

@@ -19,15 +19,17 @@ import sys
 
 import wx
 
-from core              import globalvar
+from core import globalvar
 from core.utils import _
 from gui_core.toolbars import BaseToolbar, BaseIcons
 
-from icons.icon        import MetaIcon
+from icons.icon import MetaIcon
+
 
 class ModelerToolbar(BaseToolbar):
     """Graphical modeler toolbaro (see gmodeler.py)
     """
+
     def __init__(self, parent):
         BaseToolbar.__init__(self, parent)
 
@@ -36,47 +38,47 @@ class ModelerToolbar(BaseToolbar):
             parent.SetToolBar(self)
 
         self.InitToolbar(self._toolbarData())
-        
+
         # realize the toolbar
         self.Realize()
-        
+
     def _toolbarData(self):
         """Toolbar data"""
         icons = {
-            'new'        : MetaIcon(img = 'create',
-                                    label = _('Create new model (Ctrl+N)')),
-            'open'       : MetaIcon(img = 'open',
-                                    label = _('Load model from file (Ctrl+O)')),
-            'save'       : MetaIcon(img = 'save',
-                                    label = _('Save current model to file (Ctrl+S)')),
-            'toImage'    : MetaIcon(img = 'image-export',
-                                    label = _('Export model to image')),
-            'toPython'   : MetaIcon(img = 'python-export',
-                                    label = _('Export model to Python script')),
-            'actionAdd'  : MetaIcon(img = 'module-add',
-                                    label = _('Add command (GRASS module) to model')),
-            'dataAdd'    : MetaIcon(img = 'data-add',
-                                    label = _('Add data to model')),
-            'relation'   : MetaIcon(img = 'relation-create',
-                                    label = _('Manually define relation between data and commands')),
-            'loop'       : MetaIcon(img = 'loop-add',
-                                    label = _('Add loop/series to model')),
-            'comment'    : MetaIcon(img = 'label-add',
-                                    label = _('Add comment to model')),
-            'run'        : MetaIcon(img = 'execute',
-                                    label = _('Run model')),
-            'validate'   : MetaIcon(img = 'check',
-                                    label = _('Validate model')),
-            'settings'   : BaseIcons['settings'].SetLabel(_('Modeler settings')),
-            'properties' : MetaIcon(img = 'options',
-                                    label = _('Show model properties')),
-            'variables'  : MetaIcon(img = 'modeler-variables',
-                                    label = _('Manage model variables')),
-            'redraw'     : MetaIcon(img = 'redraw',
-                                    label = _('Redraw model canvas')),
-            'quit'       : BaseIcons['quit'].SetLabel(_('Quit Graphical Modeler')),
-            }
-        
+            'new': MetaIcon(img='create',
+                            label=_('Create new model (Ctrl+N)')),
+            'open': MetaIcon(img='open',
+                             label=_('Load model from file (Ctrl+O)')),
+            'save': MetaIcon(img='save',
+                             label=_('Save current model to file (Ctrl+S)')),
+            'toImage': MetaIcon(img='image-export',
+                                label=_('Export model to image')),
+            'toPython': MetaIcon(img='python-export',
+                                 label=_('Export model to Python script')),
+            'actionAdd': MetaIcon(img='module-add',
+                                  label=_('Add command (GRASS module) to model')),
+            'dataAdd': MetaIcon(img='data-add',
+                                label=_('Add data to model')),
+            'relation': MetaIcon(img='relation-create',
+                                 label=_('Manually define relation between data and commands')),
+            'loop': MetaIcon(img='loop-add',
+                             label=_('Add loop/series to model')),
+            'comment': MetaIcon(img='label-add',
+                                label=_('Add comment to model')),
+            'run': MetaIcon(img='execute',
+                            label=_('Run model')),
+            'validate': MetaIcon(img='check',
+                                 label=_('Validate model')),
+            'settings': BaseIcons['settings'].SetLabel(_('Modeler settings')),
+            'properties': MetaIcon(img='options',
+                                   label=_('Show model properties')),
+            'variables': MetaIcon(img='modeler-variables',
+                                  label=_('Manage model variables')),
+            'redraw': MetaIcon(img='redraw',
+                               label=_('Redraw model canvas')),
+            'quit': BaseIcons['quit'].SetLabel(_('Quit Graphical Modeler')),
+        }
+
         return self._getToolbarData((('new', icons['new'],
                                       self.parent.OnModelNew),
                                      ('open', icons['open'],

+ 1 - 1
gui/wxpython/gui_core/__init__.py

@@ -13,4 +13,4 @@ all = [
     'forms',
     'toolbars',
     'treeview',
-    ]
+]

File diff ditekan karena terlalu besar
+ 981 - 760
gui/wxpython/gui_core/dialogs.py


File diff ditekan karena terlalu besar
+ 1289 - 968
gui/wxpython/gui_core/forms.py


File diff ditekan karena terlalu besar
+ 394 - 317
gui/wxpython/gui_core/ghelp.py


+ 286 - 209
gui/wxpython/gui_core/goutput.py

@@ -23,16 +23,16 @@ import os
 import textwrap
 
 import wx
-from   wx import stc
+from wx import stc
 
 from grass.pydispatch.signal import Signal
 
-from core.gcmd       import GError, EncodeString
+from core.gcmd import GError, EncodeString
 from core.gconsole   import GConsole, \
     EVT_CMD_OUTPUT, EVT_CMD_PROGRESS, EVT_CMD_RUN, EVT_CMD_DONE, \
     Notification
 from gui_core.prompt import GPromptSTC
-from core.settings   import UserSettings
+from core.settings import UserSettings
 from core.utils import _
 from gui_core.widgets import SearchModuleWidget
 
@@ -45,9 +45,10 @@ GC_PROMPT = 2
 class GConsoleWindow(wx.SplitterWindow):
     """Create and manage output console for commands run by GUI.
     """
-    def __init__(self, parent, gconsole, menuModel = None, margin = False,
-                 style = wx.TAB_TRAVERSAL | wx.FULL_REPAINT_ON_RESIZE,
-                 gcstyle = GC_EMPTY,
+
+    def __init__(self, parent, gconsole, menuModel=None, margin=False,
+                 style=wx.TAB_TRAVERSAL | wx.FULL_REPAINT_ON_RESIZE,
+                 gcstyle=GC_EMPTY,
                  **kwargs):
         """
         :param parent: gui parent
@@ -59,19 +60,23 @@ class GConsoleWindow(wx.SplitterWindow):
                         (GC_EMPTY, GC_PROMPT to show command prompt,
                         GC_SEARCH to show search widget)
         """
-        wx.SplitterWindow.__init__(self, parent, id = wx.ID_ANY, style = style, **kwargs)
+        wx.SplitterWindow.__init__(
+            self, parent, id=wx.ID_ANY, style=style, **kwargs)
         self.SetName("GConsole")
-        
+
         self.panelOutput = wx.Panel(parent=self, id=wx.ID_ANY)
-        self.panelProgress = wx.Panel(parent=self.panelOutput, id=wx.ID_ANY, name='progressPanel')
+        self.panelProgress = wx.Panel(
+            parent=self.panelOutput,
+            id=wx.ID_ANY,
+            name='progressPanel')
         self.panelPrompt = wx.Panel(parent=self, id=wx.ID_ANY)
         # initialize variables
-        self.parent = parent # GMFrame | CmdPanel | ?
+        self.parent = parent  # GMFrame | CmdPanel | ?
         self._gconsole = gconsole
         self._menuModel = menuModel
 
         self._gcstyle = gcstyle
-        self.lineWidth       = 80
+        self.lineWidth = 80
 
         # signal which requests showing of a notification
         self.showNotification = Signal("GConsoleWindow.showNotification")
@@ -81,9 +86,9 @@ class GConsoleWindow(wx.SplitterWindow):
         self.contentChanged = Signal("GConsoleWindow.contentChanged")
 
         # progress bar
-        self.progressbar = wx.Gauge(parent = self.panelProgress, id = wx.ID_ANY,
-                                    range = 100, pos = (110, 50), size = (-1, 25),
-                                    style = wx.GA_HORIZONTAL)
+        self.progressbar = wx.Gauge(parent=self.panelProgress, id=wx.ID_ANY,
+                                    range=100, pos=(110, 50), size=(-1, 25),
+                                    style=wx.GA_HORIZONTAL)
         self._gconsole.Bind(EVT_CMD_PROGRESS, self.OnCmdProgress)
         self._gconsole.Bind(EVT_CMD_OUTPUT, self.OnCmdOutput)
         self._gconsole.Bind(EVT_CMD_RUN, self.OnCmdRun)
@@ -95,8 +100,11 @@ class GConsoleWindow(wx.SplitterWindow):
         self._gconsole.writeError.connect(self.WriteError)
 
         # text control for command output
-        self.cmdOutput = GStc(parent = self.panelOutput, id = wx.ID_ANY, margin = margin,
-                               wrap = None)
+        self.cmdOutput = GStc(
+            parent=self.panelOutput,
+            id=wx.ID_ANY,
+            margin=margin,
+            wrap=None)
 
         # search & command prompt
         # move to the if below
@@ -109,58 +117,68 @@ class GConsoleWindow(wx.SplitterWindow):
         if not self._gcstyle & GC_PROMPT:
             self.cmdPrompt.Hide()
 
-
         if self._gcstyle & GC_SEARCH:
-            self.infoCollapseLabelExp = _("Click here to show search module engine")
-            self.infoCollapseLabelCol = _("Click here to hide search module engine")
-            self.searchPane = wx.CollapsiblePane(parent = self.panelOutput,
-                                                 label = self.infoCollapseLabelExp,
-                                                 style = wx.CP_DEFAULT_STYLE |
-                                                 wx.CP_NO_TLW_RESIZE | wx.EXPAND)
-            self.MakeSearchPaneContent(self.searchPane.GetPane(), self._menuModel)
+            self.infoCollapseLabelExp = _(
+                "Click here to show search module engine")
+            self.infoCollapseLabelCol = _(
+                "Click here to hide search module engine")
+            self.searchPane = wx.CollapsiblePane(
+                parent=self.panelOutput, label=self.infoCollapseLabelExp,
+                style=wx.CP_DEFAULT_STYLE | wx.CP_NO_TLW_RESIZE | wx.EXPAND)
+            self.MakeSearchPaneContent(
+                self.searchPane.GetPane(), self._menuModel)
             self.searchPane.Collapse(True)
-            self.Bind(wx.EVT_COLLAPSIBLEPANE_CHANGED, self.OnSearchPaneChanged, self.searchPane) 
-            self.search.moduleSelected.connect(lambda name:
-                                               self.cmdPrompt.SetTextAndFocus(name + ' '))
+            self.Bind(
+                wx.EVT_COLLAPSIBLEPANE_CHANGED,
+                self.OnSearchPaneChanged,
+                self.searchPane)
+            self.search.moduleSelected.connect(
+                lambda name: self.cmdPrompt.SetTextAndFocus(name + ' '))
         else:
             self.search = None
 
-
         if self._gcstyle & GC_PROMPT:
             cmdLabel = _("Command prompt")
-            self.outputBox = wx.StaticBox(parent = self.panelOutput, id = wx.ID_ANY,
-                                          label = " %s " % _("Output window"))
+            self.outputBox = wx.StaticBox(
+                parent=self.panelOutput,
+                id=wx.ID_ANY,
+                label=" %s " %
+                _("Output window"))
 
-            self.cmdBox = wx.StaticBox(parent = self.panelOutput, id = wx.ID_ANY,
-                                       label = " %s " % cmdLabel)
+            self.cmdBox = wx.StaticBox(parent=self.panelOutput, id=wx.ID_ANY,
+                                       label=" %s " % cmdLabel)
 
         # buttons
-        self.btnOutputClear = wx.Button(parent = self.panelOutput, id = wx.ID_CLEAR)
+        self.btnOutputClear = wx.Button(
+            parent=self.panelOutput, id=wx.ID_CLEAR)
         self.btnOutputClear.SetToolTipString(_("Clear output window content"))
-        self.btnCmdClear = wx.Button(parent = self.panelOutput, id = wx.ID_CLEAR)
+        self.btnCmdClear = wx.Button(parent=self.panelOutput, id=wx.ID_CLEAR)
         self.btnCmdClear.SetToolTipString(_("Clear command prompt content"))
-        self.btnOutputSave  = wx.Button(parent = self.panelOutput, id = wx.ID_SAVE)
-        self.btnOutputSave.SetToolTipString(_("Save output window content to the file"))
-        self.btnCmdAbort = wx.Button(parent = self.panelProgress, id = wx.ID_STOP)
+        self.btnOutputSave = wx.Button(parent=self.panelOutput, id=wx.ID_SAVE)
+        self.btnOutputSave.SetToolTipString(
+            _("Save output window content to the file"))
+        self.btnCmdAbort = wx.Button(parent=self.panelProgress, id=wx.ID_STOP)
         self.btnCmdAbort.SetToolTipString(_("Abort running command"))
-        self.btnCmdProtocol = wx.ToggleButton(parent = self.panelOutput, id = wx.ID_ANY,
-                                              label = _("&Log file"),
-                                              size = self.btnCmdClear.GetSize())
+        self.btnCmdProtocol = wx.ToggleButton(
+            parent=self.panelOutput,
+            id=wx.ID_ANY,
+            label=_("&Log file"),
+            size=self.btnCmdClear.GetSize())
         self.btnCmdProtocol.SetToolTipString(_("Toggle to save list of executed commands into "
                                                "a file; content saved when switching off."))
-        
+
         if not self._gcstyle & GC_PROMPT:
             self.btnCmdClear.Hide()
             self.btnCmdProtocol.Hide()
-        
-        self.btnCmdClear.Bind(wx.EVT_BUTTON,     self.cmdPrompt.OnCmdErase)
-        self.btnOutputClear.Bind(wx.EVT_BUTTON,  self.OnOutputClear)
-        self.btnOutputSave.Bind(wx.EVT_BUTTON,   self.OnOutputSave)
-        self.btnCmdAbort.Bind(wx.EVT_BUTTON,     self._gconsole.OnCmdAbort)
+
+        self.btnCmdClear.Bind(wx.EVT_BUTTON, self.cmdPrompt.OnCmdErase)
+        self.btnOutputClear.Bind(wx.EVT_BUTTON, self.OnOutputClear)
+        self.btnOutputSave.Bind(wx.EVT_BUTTON, self.OnOutputSave)
+        self.btnCmdAbort.Bind(wx.EVT_BUTTON, self._gconsole.OnCmdAbort)
         self.btnCmdProtocol.Bind(wx.EVT_TOGGLEBUTTON, self.OnCmdProtocol)
-        
+
         self._layout()
-        
+
     def _layout(self):
         """Do layout"""
         self.outputSizer = wx.BoxSizer(wx.VERTICAL)
@@ -172,56 +190,73 @@ class GConsoleWindow(wx.SplitterWindow):
         else:
             outBtnSizer = wx.BoxSizer(wx.HORIZONTAL)
             cmdBtnSizer = wx.BoxSizer(wx.HORIZONTAL)
-            
-        
+
         if self._gcstyle & GC_PROMPT:
             promptSizer = wx.BoxSizer(wx.VERTICAL)
-            promptSizer.Add(item = self.cmdPrompt, proportion = 1,
-                        flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, border = 3)
-            helpText = wx.StaticText(self.panelPrompt, id = wx.ID_ANY,
-                                 label = "Press Tab to display command help, Ctrl+Space to autocomplete")
-            helpText.SetForegroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_GRAYTEXT))
-            promptSizer.Add(item = helpText,
-                            proportion = 0, flag = wx.EXPAND | wx.LEFT, border = 5)
-        
+            promptSizer.Add(
+                item=self.cmdPrompt,
+                proportion=1,
+                flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP,
+                border=3)
+            helpText = wx.StaticText(
+                self.panelPrompt, id=wx.ID_ANY,
+                label="Press Tab to display command help, Ctrl+Space to autocomplete")
+            helpText.SetForegroundColour(
+                wx.SystemSettings_GetColour(
+                    wx.SYS_COLOUR_GRAYTEXT))
+            promptSizer.Add(item=helpText,
+                            proportion=0, flag=wx.EXPAND | wx.LEFT, border=5)
+
         if self._gcstyle & GC_SEARCH:
-            self.outputSizer.Add(item = self.searchPane, proportion = 0,
-                            flag = wx.EXPAND | wx.ALL, border = 3)
-        self.outputSizer.Add(item = self.cmdOutput, proportion = 1,
-                        flag = wx.EXPAND | wx.ALL, border = 3)
+            self.outputSizer.Add(item=self.searchPane, proportion=0,
+                                 flag=wx.EXPAND | wx.ALL, border=3)
+        self.outputSizer.Add(item=self.cmdOutput, proportion=1,
+                             flag=wx.EXPAND | wx.ALL, border=3)
         if self._gcstyle & GC_PROMPT:
             proportion = 1
         else:
             proportion = 0
             outBtnSizer.AddStretchSpacer()
 
-        outBtnSizer.Add(item = self.btnOutputClear, proportion = proportion,
-                        flag = wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
-
-        outBtnSizer.Add(item = self.btnOutputSave, proportion = proportion,
-                        flag = wx.ALIGN_RIGHT | wx.RIGHT | wx.BOTTOM, border = 5)
-
-        cmdBtnSizer.Add(item = self.btnCmdProtocol, proportion = 1,
-                        flag = wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
-        cmdBtnSizer.Add(item = self.btnCmdClear, proportion = 1,
-                        flag = wx.ALIGN_CENTER | wx.RIGHT | wx.BOTTOM, border = 5)
-        progressSizer.Add(item = self.btnCmdAbort, proportion = 0,
-                          flag = wx.ALL|wx.ALIGN_CENTER, border = 5)
-        progressSizer.Add(item = self.progressbar, proportion = 1,
-                          flag = wx.ALIGN_CENTER | wx.RIGHT | wx.TOP | wx.BOTTOM, border = 5)
-                          
+        outBtnSizer.Add(
+            item=self.btnOutputClear,
+            proportion=proportion,
+            flag=wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.BOTTOM,
+            border=5)
+
+        outBtnSizer.Add(item=self.btnOutputSave, proportion=proportion,
+                        flag=wx.ALIGN_RIGHT | wx.RIGHT | wx.BOTTOM, border=5)
+
+        cmdBtnSizer.Add(
+            item=self.btnCmdProtocol,
+            proportion=1,
+            flag=wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT | wx.BOTTOM,
+            border=5)
+        cmdBtnSizer.Add(item=self.btnCmdClear, proportion=1,
+                        flag=wx.ALIGN_CENTER | wx.RIGHT | wx.BOTTOM, border=5)
+        progressSizer.Add(item=self.btnCmdAbort, proportion=0,
+                          flag=wx.ALL | wx.ALIGN_CENTER, border=5)
+        progressSizer.Add(
+            item=self.progressbar,
+            proportion=1,
+            flag=wx.ALIGN_CENTER | wx.RIGHT | wx.TOP | wx.BOTTOM,
+            border=5)
+
         self.panelProgress.SetSizer(progressSizer)
         progressSizer.Fit(self.panelProgress)
-        
-        btnSizer.Add(item = outBtnSizer, proportion = 1,
-                     flag = wx.ALL | wx.ALIGN_CENTER, border = 5)
-        btnSizer.Add(item = cmdBtnSizer, proportion = 1,
-                     flag = wx.ALIGN_CENTER | wx.TOP | wx.BOTTOM | wx.RIGHT, border = 5)
-        self.outputSizer.Add(item = self.panelProgress, proportion = 0,
-                        flag = wx.EXPAND)
-        self.outputSizer.Add(item = btnSizer, proportion = 0,
-                        flag = wx.EXPAND)
-        
+
+        btnSizer.Add(item=outBtnSizer, proportion=1,
+                     flag=wx.ALL | wx.ALIGN_CENTER, border=5)
+        btnSizer.Add(
+            item=cmdBtnSizer,
+            proportion=1,
+            flag=wx.ALIGN_CENTER | wx.TOP | wx.BOTTOM | wx.RIGHT,
+            border=5)
+        self.outputSizer.Add(item=self.panelProgress, proportion=0,
+                             flag=wx.EXPAND)
+        self.outputSizer.Add(item=btnSizer, proportion=0,
+                             flag=wx.EXPAND)
+
         self.outputSizer.Fit(self)
         self.outputSizer.SetSizeHints(self)
         self.panelOutput.SetSizer(self.outputSizer)
@@ -229,12 +264,12 @@ class GConsoleWindow(wx.SplitterWindow):
         # avoid to use a deprecated method in wxPython >= 2.9
         getattr(self.outputSizer, 'FitInside',
                 self.outputSizer.SetVirtualSizeHints)(self.panelOutput)
-        
+
         if self._gcstyle & GC_PROMPT:
             promptSizer.Fit(self)
             promptSizer.SetSizeHints(self)
             self.panelPrompt.SetSizer(promptSizer)
-        
+
         # split window
         if self._gcstyle & GC_PROMPT:
             self.SplitHorizontally(self.panelOutput, self.panelPrompt, -50)
@@ -242,9 +277,9 @@ class GConsoleWindow(wx.SplitterWindow):
             self.SplitHorizontally(self.panelOutput, self.panelPrompt, -45)
             self.Unsplit()
         self.SetMinimumPaneSize(self.btnCmdClear.GetSize()[1] + 25)
-        
+
         self.SetSashGravity(1.0)
-        
+
         self.outputSizer.Hide(self.panelProgress)
         # layout
         self.SetAutoLayout(True)
@@ -253,29 +288,29 @@ class GConsoleWindow(wx.SplitterWindow):
     def MakeSearchPaneContent(self, pane, model):
         """Create search pane"""
         border = wx.BoxSizer(wx.VERTICAL)
-        
-        self.search = SearchModuleWidget(parent = pane,
-                                         model = model)
+
+        self.search = SearchModuleWidget(parent=pane,
+                                         model=model)
 
         self.search.showNotification.connect(self.showNotification)
 
-        border.Add(item = self.search, proportion = 0,
-                   flag = wx.EXPAND | wx.ALL, border = 1)
-        
+        border.Add(item=self.search, proportion=0,
+                   flag=wx.EXPAND | wx.ALL, border=1)
+
         pane.SetSizer(border)
         border.Fit(pane)
-        
+
     def OnSearchPaneChanged(self, event):
         """Collapse search module box"""
         if self.searchPane.IsExpanded():
             self.searchPane.SetLabel(self.infoCollapseLabelCol)
         else:
             self.searchPane.SetLabel(self.infoCollapseLabelExp)
-        
+
         self.panelOutput.Layout()
         self.panelOutput.SendSizeEvent()
-        
-    def GetPanel(self, prompt = True):
+
+    def GetPanel(self, prompt=True):
         """Get panel
 
         :param prompt: get prompt / output panel
@@ -289,8 +324,8 @@ class GConsoleWindow(wx.SplitterWindow):
 
     def WriteLog(self, text, style=None, wrap=None,
                  notification=Notification.HIGHLIGHT):
-        """Generic method for writing log message in 
-        given style. 
+        """Generic method for writing log message in
+        given style.
 
         Emits contentChanged signal.
 
@@ -308,47 +343,53 @@ class GConsoleWindow(wx.SplitterWindow):
 
         if not style:
             style = self.cmdOutput.StyleDefault
-        
+
         # p1 = self.cmdOutput.GetCurrentPos()
         p1 = self.cmdOutput.GetEndStyled()
         # self.cmdOutput.GotoPos(p1)
         self.cmdOutput.DocumentEnd()
-        
+
         for line in text.splitlines():
             # fill space
             if len(line) < self.lineWidth:
-                diff = self.lineWidth - len(line) 
+                diff = self.lineWidth - len(line)
                 line += diff * ' '
-            
-            self.cmdOutput.AddTextWrapped(line, wrap = wrap) # adds '\n'
-            
+
+            self.cmdOutput.AddTextWrapped(line, wrap=wrap)  # adds '\n'
+
             p2 = self.cmdOutput.GetCurrentPos()
-            
+
             self.cmdOutput.StartStyling(p1, 0xff)
             self.cmdOutput.SetStyling(p2 - p1, style)
-        
+
         self.cmdOutput.EnsureCaretVisible()
 
         self.contentChanged.emit(notification=notification)
-        
-    def WriteCmdLog(self, text, pid=None, notification=Notification.MAKE_VISIBLE):
+
+    def WriteCmdLog(self, text, pid=None,
+                    notification=Notification.MAKE_VISIBLE):
         """Write message in selected style
-        
+
         :param text: message to be printed
         :param pid: process pid or None
         :param switchPage: True to switch page
         """
         if pid:
             text = '(' + str(pid) + ') ' + text
-        self.WriteLog(text, style=self.cmdOutput.StyleCommand, notification=notification)
+        self.WriteLog(
+            text,
+            style=self.cmdOutput.StyleCommand,
+            notification=notification)
 
     def WriteWarning(self, text):
         """Write message in warning style"""
-        self.WriteLog(text, style=self.cmdOutput.StyleWarning, notification=Notification.MAKE_VISIBLE)
+        self.WriteLog(text, style=self.cmdOutput.StyleWarning,
+                      notification=Notification.MAKE_VISIBLE)
 
     def WriteError(self, text):
         """Write message in error style"""
-        self.WriteLog(text, style=self.cmdOutput.StyleError, notification=Notification.MAKE_VISIBLE)
+        self.WriteLog(text, style=self.cmdOutput.StyleError,
+                      notification=Notification.MAKE_VISIBLE)
 
     def OnOutputClear(self, event):
         """Clear content of output window"""
@@ -366,43 +407,52 @@ class GConsoleWindow(wx.SplitterWindow):
         text = self.cmdOutput.GetSelectedText()
         if not text:
             text = self.cmdOutput.GetText()
-        
+
         # add newline if needed
         if len(text) > 0 and text[-1] != '\n':
             text += '\n'
-        
-        dlg = wx.FileDialog(self, message = _("Save file as..."),
-                            defaultFile = "grass_cmd_output.txt",
-                            wildcard = _("%(txt)s (*.txt)|*.txt|%(files)s (*)|*") % 
-                            {'txt': _("Text files"), 'files': _("Files")},
-                            style = wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
-        
+
+        dlg = wx.FileDialog(
+            self, message=_("Save file as..."),
+            defaultFile="grass_cmd_output.txt",
+            wildcard=_("%(txt)s (*.txt)|*.txt|%(files)s (*)|*") %
+            {'txt': _("Text files"),
+             'files': _("Files")},
+            style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
+
         # Show the dialog and retrieve the user response. If it is the OK response,
         # process the data.
         if dlg.ShowModal() == wx.ID_OK:
             path = dlg.GetPath()
-            
+
             try:
                 output = open(path, "w")
                 output.write(EncodeString(text))
             except IOError as e:
-                GError(_("Unable to write file '%(path)s'.\n\nDetails: %(error)s") % {'path': path, 'error': e})
+                GError(
+                    _("Unable to write file '%(path)s'.\n\nDetails: %(error)s") % {
+                        'path': path,
+                        'error': e})
             finally:
                 output.close()
             message = _("Command output saved into '%s'") % path
-            self.showNotification.emit(message = message)
-        
+            self.showNotification.emit(message=message)
+
         dlg.Destroy()
 
     def SetCopyingOfSelectedText(self, copy):
         """Enable or disable copying of selected text in to clipboard.
         Effects prompt and output.
-        
+
         :param bool copy: True for enable, False for disable
         """
         if copy:
-            self.cmdPrompt.Bind(stc.EVT_STC_PAINTED, self.cmdPrompt.OnTextSelectionChanged)
-            self.cmdOutput.Bind(stc.EVT_STC_PAINTED, self.cmdOutput.OnTextSelectionChanged)
+            self.cmdPrompt.Bind(
+                stc.EVT_STC_PAINTED,
+                self.cmdPrompt.OnTextSelectionChanged)
+            self.cmdOutput.Bind(
+                stc.EVT_STC_PAINTED,
+                self.cmdOutput.OnTextSelectionChanged)
         else:
             self.cmdPrompt.Unbind(stc.EVT_STC_PAINTED)
             self.cmdOutput.Unbind(stc.EVT_STC_PAINTED)
@@ -413,7 +463,7 @@ class GConsoleWindow(wx.SplitterWindow):
         Emits contentChanged signal.
         """
         message = event.text
-        type  = event.type
+        type = event.type
 
         self.cmdOutput.AddStyledMessage(message, type)
 
@@ -430,8 +480,8 @@ class GConsoleWindow(wx.SplitterWindow):
     def CmdProtocolSave(self):
         """Save list of manually entered commands into a text log file"""
         if not hasattr(self, 'cmdFileProtocol'):
-            return # it should not happen
-        
+            return  # it should not happen
+
         try:
             output = open(self.cmdFileProtocol, "a")
             cmds = self.cmdPrompt.GetCommands()
@@ -439,16 +489,16 @@ class GConsoleWindow(wx.SplitterWindow):
             if len(cmds) > 0:
                 output.write('\n')
         except IOError as e:
-            GError(_("Unable to write file '%(filePath)s'.\n\nDetails: %(error)s") % 
-                    {'filePath': self.cmdFileProtocol, 'error': e})
+            GError(_("Unable to write file '%(filePath)s'.\n\nDetails: %(error)s") %
+                   {'filePath': self.cmdFileProtocol, 'error': e})
         finally:
             output.close()
-        
+
         message = _("Command log saved to '%s'") % self.cmdFileProtocol
-        self.showNotification.emit(message = message)
+        self.showNotification.emit(message=message)
         del self.cmdFileProtocol
-        
-    def OnCmdProtocol(self, event = None):
+
+    def OnCmdProtocol(self, event=None):
         """Save commands into file"""
         if not event.IsChecked():
             # stop capturing commands, save list of commands to the
@@ -458,18 +508,20 @@ class GConsoleWindow(wx.SplitterWindow):
             # start capturing commands
             self.cmdPrompt.ClearCommands()
             # ask for the file
-            dlg = wx.FileDialog(self, message = _("Save file as..."),
-                                defaultFile = "grass_cmd_log.txt",
-                                wildcard = _("%(txt)s (*.txt)|*.txt|%(files)s (*)|*") % 
-                                            {'txt': _("Text files"), 'files': _("Files")},
-                                style = wx.FD_SAVE)
+            dlg = wx.FileDialog(
+                self, message=_("Save file as..."),
+                defaultFile="grass_cmd_log.txt",
+                wildcard=_("%(txt)s (*.txt)|*.txt|%(files)s (*)|*") %
+                {'txt': _("Text files"),
+                 'files': _("Files")},
+                style=wx.FD_SAVE)
             if dlg.ShowModal() == wx.ID_OK:
                 self.cmdFileProtocol = dlg.GetPath()
             else:
                 wx.CallAfter(self.btnCmdProtocol.SetValue, False)
-            
+
             dlg.Destroy()
-            
+
         event.Skip()
 
     def OnCmdRun(self, event):
@@ -481,7 +533,7 @@ class GConsoleWindow(wx.SplitterWindow):
     def OnCmdDone(self, event):
         """Command done (or aborted)
         """
-        self.progressbar.SetValue(0) # reset progress bar on '0%'
+        self.progressbar.SetValue(0)  # reset progress bar on '0%'
         wx.CallLater(100, self._hideProgress)
         event.Skip()
 
@@ -492,7 +544,7 @@ class GConsoleWindow(wx.SplitterWindow):
     def ResetFocus(self):
         """Reset focus"""
         self.cmdPrompt.SetFocus()
-        
+
     def GetPrompt(self):
         """Get prompt"""
         return self.cmdPrompt
@@ -508,21 +560,22 @@ class GStc(stc.StyledTextCtrl):
     Author:    Jean-Michel Fauth, Switzerland
     Copyright: (c) 2005-2007 Jean-Michel Fauth
     Licence:   GPL
-    """  
-    def __init__(self, parent, id, margin = False, wrap = None):
+    """
+
+    def __init__(self, parent, id, margin=False, wrap=None):
         stc.StyledTextCtrl.__init__(self, parent, id)
         self.parent = parent
         self.SetUndoCollection(True)
         self.SetReadOnly(True)
 
         # remember position of line begining (used for '\r')
-        self.linePos         = -1
+        self.linePos = -1
 
         #
         # styles
-        #                
+        #
         self.SetStyle()
-        
+
         #
         # line margins
         #
@@ -549,64 +602,80 @@ class GStc(stc.StyledTextCtrl):
         # bindings
         #
         self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
-        
+
     def OnTextSelectionChanged(self, event):
         """Copy selected text to clipboard and skip event.
         The same function is in TextCtrlAutoComplete class (prompt.py).
         """
         wx.CallAfter(self.Copy)
         event.Skip()
-        
+
     def SetStyle(self):
-        """Set styles for styled text output windows with type face 
+        """Set styles for styled text output windows with type face
         and point size selected by user (Courier New 10 is default)"""
-        
-        typeface = UserSettings.Get(group = 'appearance', key = 'outputfont', subkey = 'type')   
+
+        typeface = UserSettings.Get(
+            group='appearance',
+            key='outputfont',
+            subkey='type')
         if typeface == "":
             typeface = "Courier New"
-        
-        typesize = UserSettings.Get(group = 'appearance', key = 'outputfont', subkey = 'size')
-        if typesize == None or typesize <= 0:
+
+        typesize = UserSettings.Get(
+            group='appearance',
+            key='outputfont',
+            subkey='size')
+        if typesize is None or typesize <= 0:
             typesize = 10
         typesize = float(typesize)
-        
-        self.StyleDefault     = 0
-        self.StyleDefaultSpec = "face:%s,size:%d,fore:#000000,back:#FFFFFF" % (typeface, typesize)
-        self.StyleCommand     = 1
-        self.StyleCommandSpec = "face:%s,size:%d,,fore:#000000,back:#bcbcbc" % (typeface, typesize)
-        self.StyleOutput      = 2
-        self.StyleOutputSpec  = "face:%s,size:%d,,fore:#000000,back:#FFFFFF" % (typeface, typesize)
+
+        self.StyleDefault = 0
+        self.StyleDefaultSpec = "face:%s,size:%d,fore:#000000,back:#FFFFFF" % (
+            typeface,
+            typesize)
+        self.StyleCommand = 1
+        self.StyleCommandSpec = "face:%s,size:%d,,fore:#000000,back:#bcbcbc" % (
+            typeface, typesize)
+        self.StyleOutput = 2
+        self.StyleOutputSpec = "face:%s,size:%d,,fore:#000000,back:#FFFFFF" % (
+            typeface,
+            typesize)
         # fatal error
-        self.StyleError       = 3
-        self.StyleErrorSpec   = "face:%s,size:%d,,fore:#7F0000,back:#FFFFFF" % (typeface, typesize)
+        self.StyleError = 3
+        self.StyleErrorSpec = "face:%s,size:%d,,fore:#7F0000,back:#FFFFFF" % (
+            typeface,
+            typesize)
         # warning
-        self.StyleWarning     = 4
-        self.StyleWarningSpec = "face:%s,size:%d,,fore:#0000FF,back:#FFFFFF" % (typeface, typesize)
+        self.StyleWarning = 4
+        self.StyleWarningSpec = "face:%s,size:%d,,fore:#0000FF,back:#FFFFFF" % (
+            typeface, typesize)
         # message
-        self.StyleMessage     = 5
-        self.StyleMessageSpec = "face:%s,size:%d,,fore:#000000,back:#FFFFFF" % (typeface, typesize)
+        self.StyleMessage = 5
+        self.StyleMessageSpec = "face:%s,size:%d,,fore:#000000,back:#FFFFFF" % (
+            typeface, typesize)
         # unknown
-        self.StyleUnknown     = 6
-        self.StyleUnknownSpec = "face:%s,size:%d,,fore:#000000,back:#FFFFFF" % (typeface, typesize)
-        
+        self.StyleUnknown = 6
+        self.StyleUnknownSpec = "face:%s,size:%d,,fore:#000000,back:#FFFFFF" % (
+            typeface, typesize)
+
         # default and clear => init
         self.StyleSetSpec(stc.STC_STYLE_DEFAULT, self.StyleDefaultSpec)
         self.StyleClearAll()
         self.StyleSetSpec(self.StyleCommand, self.StyleCommandSpec)
-        self.StyleSetSpec(self.StyleOutput,  self.StyleOutputSpec)
-        self.StyleSetSpec(self.StyleError,   self.StyleErrorSpec)
+        self.StyleSetSpec(self.StyleOutput, self.StyleOutputSpec)
+        self.StyleSetSpec(self.StyleError, self.StyleErrorSpec)
         self.StyleSetSpec(self.StyleWarning, self.StyleWarningSpec)
         self.StyleSetSpec(self.StyleMessage, self.StyleMessageSpec)
-        self.StyleSetSpec(self.StyleUnknown, self.StyleUnknownSpec)        
+        self.StyleSetSpec(self.StyleUnknown, self.StyleUnknownSpec)
 
     def OnDestroy(self, evt):
         """The clipboard contents can be preserved after
         the app has exited"""
-        
+
         wx.TheClipboard.Flush()
         evt.Skip()
 
-    def AddTextWrapped(self, txt, wrap = None):
+    def AddTextWrapped(self, txt, wrap=None):
         """Add string to text area.
 
         String is wrapped and linesep is also added to the end
@@ -631,24 +700,27 @@ class GStc(stc.StyledTextCtrl):
                     self.AddText(seg)
         else:
             self.linePos = self.GetCurrentPos()
-            
+
             try:
                 self.AddText(txt)
             except UnicodeDecodeError:
-                enc = UserSettings.Get(group = 'atm', key = 'encoding', subkey = 'value')
+                enc = UserSettings.Get(
+                    group='atm', key='encoding', subkey='value')
                 if enc:
-                    txt = unicode(txt, enc, errors = 'replace')
+                    txt = unicode(txt, enc, errors='replace')
                 elif 'GRASS_DB_ENCODING' in os.environ:
-                    txt = unicode(txt, os.environ['GRASS_DB_ENCODING'], errors = 'replace')
+                    txt = unicode(
+                        txt, os.environ['GRASS_DB_ENCODING'],
+                        errors='replace')
                 else:
                     txt = EncodeString(txt)
-                
+
                 self.AddText(txt)
 
         # reset output window to read only
         self.SetReadOnly(True)
 
-    def AddStyledMessage(self, message, style = None):
+    def AddStyledMessage(self, message, style=None):
         """Add message to text area.
 
         Handles messages with progress percentages.
@@ -662,10 +734,10 @@ class GStc(stc.StyledTextCtrl):
             message = 'WARNING: ' + message
         elif style == 'error':
             message = 'ERROR: ' + message
-        
+
         p1 = self.GetEndStyled()
         self.GotoPos(p1)
-        
+
         # is this still needed?
         if '\b' in message:
             if self.linePos < 0:
@@ -685,48 +757,53 @@ class GStc(stc.StyledTextCtrl):
                     if c != ' ':
                         last_c = c
             if last_c not in ('0123456789'):
-                self.AddTextWrapped('\n', wrap = None)
+                self.AddTextWrapped('\n', wrap=None)
                 self.linePos = -1
         else:
-            self.linePos = -1 # don't force position
+            self.linePos = -1  # don't force position
             if '\n' not in message:
-                self.AddTextWrapped(message, wrap = 60)
+                self.AddTextWrapped(message, wrap=60)
             else:
-                self.AddTextWrapped(message, wrap = None)
+                self.AddTextWrapped(message, wrap=None)
         p2 = self.GetCurrentPos()
-        
+
         if p2 >= p1:
             self.StartStyling(p1, 0xff)
-        
+
             if style == 'error':
                 self.SetStyling(p2 - p1, self.StyleError)
             elif style == 'warning':
                 self.SetStyling(p2 - p1, self.StyleWarning)
             elif style == 'message':
                 self.SetStyling(p2 - p1, self.StyleMessage)
-            else: # unknown
+            else:  # unknown
                 self.SetStyling(p2 - p1, self.StyleUnknown)
-        
+
         self.EnsureCaretVisible()
 
 
 class GConsoleFrame(wx.Frame):
     """Standalone GConsole for testing only"""
-    def __init__(self, parent, id = wx.ID_ANY, title = "GConsole Test Frame",
-                 style = wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL, **kwargs):
-        wx.Frame.__init__(self, parent = parent, id = id, title = title, style = style)
 
-        panel = wx.Panel(self, id = wx.ID_ANY)
-        
+    def __init__(self, parent, id=wx.ID_ANY, title="GConsole Test Frame",
+                 style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL, **kwargs):
+        wx.Frame.__init__(self, parent=parent, id=id, title=title, style=style)
+
+        panel = wx.Panel(self, id=wx.ID_ANY)
+
         from lmgr.menudata import LayerManagerMenuData
         menuTreeBuilder = LayerManagerMenuData()
         self.gconsole = GConsole(guiparent=self)
-        self.goutput = GConsoleWindow(parent = panel, gconsole = self.gconsole,
+        self.goutput = GConsoleWindow(parent=panel, gconsole=self.gconsole,
                                       menuModel=menuTreeBuilder.GetModel(),
-                                      gcstyle = GC_SEARCH | GC_PROMPT)
+                                      gcstyle=GC_SEARCH | GC_PROMPT)
 
         mainSizer = wx.BoxSizer(wx.VERTICAL)
-        mainSizer.Add(item = self.goutput, proportion = 1, flag = wx.EXPAND, border = 0)
+        mainSizer.Add(
+            item=self.goutput,
+            proportion=1,
+            flag=wx.EXPAND,
+            border=0)
 
         panel.SetSizer(mainSizer)
         mainSizer.Fit(panel)
@@ -735,7 +812,7 @@ class GConsoleFrame(wx.Frame):
 
 def testGConsole():
     app = wx.App()
-    frame = GConsoleFrame(parent = None)
+    frame = GConsoleFrame(parent=None)
     frame.Show()
     app.MainLoop()
 

File diff ditekan karena terlalu besar
+ 597 - 406
gui/wxpython/gui_core/gselect.py


+ 181 - 154
gui/wxpython/gui_core/mapdisp.py

@@ -24,8 +24,8 @@ import sys
 
 import wx
 
-from core        import globalvar
-from core.debug  import Debug
+from core import globalvar
+from core.debug import Debug
 from core.utils import _
 from gui_core.toolbars import ToolSwitcher
 
@@ -34,14 +34,14 @@ from grass.script import core as grass
 
 class MapFrameBase(wx.Frame):
     """Base class for map display window
-    
+
     Derived class must use (create and initialize) \c statusbarManager
     or override
     GetProperty(), SetProperty() and HasProperty() methods.
-    
+
     Several methods has to be overriden or
     \c NotImplementedError("MethodName") will be raised.
-    
+
     If derived class enables and disables auto-rendering,
     it should override IsAutoRendered method.
 
@@ -52,17 +52,18 @@ class MapFrameBase(wx.Frame):
     one map will be current.
     Current instances of map window and map renderer should be returned
     by methods GetWindow() and GetMap() respectively.
-    
+
     AUI manager is stored in \c self._mgr.
     """
-    def __init__(self, parent = None, id = wx.ID_ANY, title = '',
-                 style = wx.DEFAULT_FRAME_STYLE,
-                 auimgr = None, name = '', **kwargs):
+
+    def __init__(self, parent=None, id=wx.ID_ANY, title='',
+                 style=wx.DEFAULT_FRAME_STYLE,
+                 auimgr=None, name='', **kwargs):
         """
 
         .. warning::
             Use \a auimgr parameter only if you know what you are doing.
-        
+
         :param parent: gui parent
         :param id: wx id
         :param title: window title
@@ -72,42 +73,57 @@ class MapFrameBase(wx.Frame):
         :param name: frame name
         :param kwargs: arguments passed to \c wx.Frame
         """
-        
-        self.parent     = parent
-        
-        wx.Frame.__init__(self, parent, id, title, style = style, name = name, **kwargs)
-                
+
+        self.parent = parent
+
+        wx.Frame.__init__(
+            self,
+            parent,
+            id,
+            title,
+            style=style,
+            name=name,
+            **kwargs)
+
         #
         # set the size & system icon
         #
         self.SetClientSize(self.GetSize())
         self.iconsize = (16, 16)
 
-        self.SetIcon(wx.Icon(os.path.join(globalvar.ICONDIR, 'grass_map.ico'), wx.BITMAP_TYPE_ICO))
-        
+        self.SetIcon(
+            wx.Icon(
+                os.path.join(
+                    globalvar.ICONDIR,
+                    'grass_map.ico'),
+                wx.BITMAP_TYPE_ICO))
+
         # toolbars
         self.toolbars = {}
-        
+
         #
         # Fancy gui
         #
-        if auimgr == None:
+        if auimgr is None:
             from wx.aui import AuiManager
             self._mgr = AuiManager(self)
         else:
             self._mgr = auimgr
-        
+
         # handles switching between tools in different toolbars
         self._toolSwitcher = ToolSwitcher()
         self._toolSwitcher.toggleToolChanged.connect(self._onToggleTool)
 
         # set accelerator table (fullscreen, close window)
         accelTable = []
-        for wxId, handler, entry, kdb in ((wx.NewId(), self.OnFullScreen, wx.ACCEL_NORMAL, wx.WXK_F11),
-                                          (wx.NewId(), self.OnCloseWindow, wx.ACCEL_CTRL, ord('W'))):
+        for wxId, handler, entry, kdb in (
+            (wx.NewId(),
+             self.OnFullScreen, wx.ACCEL_NORMAL, wx.WXK_F11),
+            (wx.NewId(),
+             self.OnCloseWindow, wx.ACCEL_CTRL, ord('W'))):
             self.Bind(wx.EVT_MENU, handler, id=wxId)
             accelTable.append((entry, kdb, wxId))
-        
+
         self.SetAcceleratorTable(wx.AcceleratorTable(accelTable))
 
     def _initMap(self, Map):
@@ -116,10 +132,10 @@ class MapFrameBase(wx.Frame):
         if not grass.find_program('g.region', '--help'):
             sys.exit(_("GRASS module '%s' not found. Unable to start map "
                        "display window.") % 'g.region')
-        
+
         Debug.msg(2, "MapFrame._initMap():")
         Map.ChangeMapSize(self.GetClientSize())
-        Map.region = Map.GetRegion() # g.region -upgc
+        Map.region = Map.GetRegion()  # g.region -upgc
         # self.Map.SetRegion() # adjust region to match display window
 
     def _resize(self):
@@ -138,7 +154,7 @@ class MapFrameBase(wx.Frame):
         """Adjust statusbar on changing size"""
         # reposition checkbox in statusbar
         self.StatusbarReposition()
-        
+
         # update statusbar
         self.StatusbarUpdate()
 
@@ -152,89 +168,89 @@ class MapFrameBase(wx.Frame):
 
     def OnCloseWindow(self, event):
         self.Destroy()
-        
+
     def GetToolSwitcher(self):
         return self._toolSwitcher
 
     def SetProperty(self, name, value):
         """Sets property"""
         self.statusbarManager.SetProperty(name, value)
-        
+
     def GetProperty(self, name):
         """Returns property"""
         return self.statusbarManager.GetProperty(name)
-        
+
     def HasProperty(self, name):
         """Checks whether object has property"""
         return self.statusbarManager.HasProperty(name)
-    
+
     def GetPPM(self):
         """Get pixel per meter
-        
+
         .. todo::
             now computed every time, is it necessary?
-        
+
         .. todo::
             enable user to specify ppm (and store it in UserSettings)
         """
         # TODO: need to be fixed...
-        ### screen X region problem
-        ### user should specify ppm
+        # screen X region problem
+        # user should specify ppm
         dc = wx.ScreenDC()
         dpSizePx = wx.DisplaySize()   # display size in pixels
-        dpSizeMM = wx.DisplaySizeMM() # display size in mm (system)
-        dpSizeIn = (dpSizeMM[0] / 25.4, dpSizeMM[1] / 25.4) # inches
-        sysPpi  = dc.GetPPI()
+        dpSizeMM = wx.DisplaySizeMM()  # display size in mm (system)
+        dpSizeIn = (dpSizeMM[0] / 25.4, dpSizeMM[1] / 25.4)  # inches
+        sysPpi = dc.GetPPI()
         comPpi = (dpSizePx[0] / dpSizeIn[0],
                   dpSizePx[1] / dpSizeIn[1])
 
         ppi = comPpi                  # pixel per inch
-        ppm = ((ppi[0] / 2.54) * 100, # pixel per meter
-                    (ppi[1] / 2.54) * 100)
-        
+        ppm = ((ppi[0] / 2.54) * 100,  # pixel per meter
+               (ppi[1] / 2.54) * 100)
+
         Debug.msg(4, "MapFrameBase.GetPPM(): size: px=%d,%d mm=%f,%f "
-                  "in=%f,%f ppi: sys=%d,%d com=%d,%d; ppm=%f,%f" % \
+                  "in=%f,%f ppi: sys=%d,%d com=%d,%d; ppm=%f,%f" %
                   (dpSizePx[0], dpSizePx[1], dpSizeMM[0], dpSizeMM[1],
                    dpSizeIn[0], dpSizeIn[1],
                    sysPpi[0], sysPpi[1], comPpi[0], comPpi[1],
                    ppm[0], ppm[1]))
-        
+
         return ppm
-    
-    def SetMapScale(self, value, map = None):
+
+    def SetMapScale(self, value, map=None):
         """Set current map scale
-        
+
         :param value: scale value (n if scale is 1:n)
         :param map: Map instance (if none self.Map is used)
         """
         if not map:
             map = self.Map
-        
+
         region = self.Map.region
         dEW = value * (region['cols'] / self.GetPPM()[0])
         dNS = value * (region['rows'] / self.GetPPM()[1])
         region['n'] = region['center_northing'] + dNS / 2.
         region['s'] = region['center_northing'] - dNS / 2.
-        region['w'] = region['center_easting']  - dEW / 2.
-        region['e'] = region['center_easting']  + dEW / 2.
-        
+        region['w'] = region['center_easting'] - dEW / 2.
+        region['e'] = region['center_easting'] + dEW / 2.
+
         # add to zoom history
         self.GetWindow().ZoomHistory(region['n'], region['s'],
-                                   region['e'], region['w'])
-    
-    def GetMapScale(self, map = None):
+                                     region['e'], region['w'])
+
+    def GetMapScale(self, map=None):
         """Get current map scale
-        
+
         :param map: Map instance (if none self.Map is used)
         """
         if not map:
             map = self.GetMap()
-        
+
         region = map.region
         ppm = self.GetPPM()
 
         heightCm = region['rows'] / ppm[1] * 100
-        widthCm  = region['cols'] / ppm[0] * 100
+        widthCm = region['cols'] / ppm[0] * 100
 
         Debug.msg(4, "MapFrame.GetMapScale(): width_cm=%f, height_cm=%f" %
                   (widthCm, heightCm))
@@ -242,19 +258,20 @@ class MapFrameBase(wx.Frame):
         xscale = (region['e'] - region['w']) / (region['cols'] / ppm[0])
         yscale = (region['n'] - region['s']) / (region['rows'] / ppm[1])
         scale = (xscale + yscale) / 2.
-        
-        Debug.msg(3, "MapFrame.GetMapScale(): xscale=%f, yscale=%f -> scale=%f" % \
-                      (xscale, yscale, scale))
-        
+
+        Debug.msg(
+            3, "MapFrame.GetMapScale(): xscale=%f, yscale=%f -> scale=%f" %
+            (xscale, yscale, scale))
+
         return scale
-        
+
     def GetProgressBar(self):
         """Returns progress bar
-        
+
         Progress bar can be used by other classes.
         """
         return self.statusbarManager.GetProgressBar()
-        
+
     def GetMap(self):
         """Returns current map (renderer) instance"""
         raise NotImplementedError("GetMap")
@@ -266,7 +283,7 @@ class MapFrameBase(wx.Frame):
     def GetWindows(self):
         """Returns list of map windows"""
         raise NotImplementedError("GetWindows")
-        
+
     def GetMapToolbar(self):
         """Returns toolbar with zooming tools"""
         raise NotImplementedError("GetMapToolbar")
@@ -284,7 +301,7 @@ class MapFrameBase(wx.Frame):
         if self.statusbarManager:
             Debug.msg(5, "MapFrameBase.StatusbarUpdate()")
             self.statusbarManager.Update()
-        
+
     def IsAutoRendered(self):
         """Check if auto-rendering is enabled"""
         # TODO: this is now not the right place to access this attribute
@@ -292,7 +309,7 @@ class MapFrameBase(wx.Frame):
         # and pass the right object in the init of derived class?
         # or do not use this method at all, let mapwindow decide
         return self.mapWindowProperties.autoRender
-        
+
     def CoordinatesChanged(self):
         """Shows current coordinates on statusbar.
         """
@@ -301,40 +318,40 @@ class MapFrameBase(wx.Frame):
         if self.statusbarManager:
             if self.statusbarManager.GetMode() == 0:
                 self.statusbarManager.ShowItem('coordinates')
-        
+
     def StatusbarReposition(self):
         """Reposition items in statusbar"""
         if self.statusbarManager:
             self.statusbarManager.Reposition()
-        
-    def StatusbarEnableLongHelp(self, enable = True):
+
+    def StatusbarEnableLongHelp(self, enable=True):
         """Enable/disable toolbars long help"""
         for toolbar in self.toolbars.itervalues():
             toolbar.EnableLongHelp(enable)
-        
+
     def IsStandalone(self):
         """Check if map frame is standalone"""
         raise NotImplementedError("IsStandalone")
-   
+
     def OnRender(self, event):
         """Re-render map composition (each map layer)
         """
         raise NotImplementedError("OnRender")
-        
+
     def OnDraw(self, event):
         """Re-display current map composition
         """
-        self.MapWindow.UpdateMap(render = False)
-        
+        self.MapWindow.UpdateMap(render=False)
+
     def OnErase(self, event):
         """Erase the canvas
         """
         self.MapWindow.EraseMap()
-        
+
     def OnZoomIn(self, event):
         """Zoom in the map."""
         self.MapWindow.SetModeZoomIn()
-        
+
     def OnZoomOut(self, event):
         """Zoom out the map."""
         self.MapWindow.SetModeZoomOut()
@@ -364,20 +381,20 @@ class MapFrameBase(wx.Frame):
         """Zoom last (previously stored position)
         """
         self.MapWindow.ZoomBack()
-        
+
     def OnZoomToMap(self, event):
         """
         Set display extents to match selected raster (including NULLs)
         or vector map.
         """
-        self.MapWindow.ZoomToMap(layers = self.Map.GetListOfLayers())
-    
+        self.MapWindow.ZoomToMap(layers=self.Map.GetListOfLayers())
+
     def OnZoomToWind(self, event):
         """Set display geometry to match computational region
         settings (set with g.region)
         """
         self.MapWindow.ZoomToWind()
-        
+
     def OnZoomToDefault(self, event):
         """Set display geometry to match default region settings
         """
@@ -386,21 +403,22 @@ class MapFrameBase(wx.Frame):
 
 class SingleMapFrame(MapFrameBase):
     """Frame with one map window.
-    
+
     It is base class for frames which needs only one map.
-    
+
     Derived class should have \c self.MapWindow or
     it has to override GetWindow() methods.
-    
+
     @note To access maps use getters only
     (when using class or when writing class itself).
     """
-    def __init__(self, parent = None, giface = None, id = wx.ID_ANY, title = '',
-                 style = wx.DEFAULT_FRAME_STYLE,
-                 Map = None,
-                 auimgr = None, name = '', **kwargs):
+
+    def __init__(self, parent=None, giface=None, id=wx.ID_ANY, title='',
+                 style=wx.DEFAULT_FRAME_STYLE,
+                 Map=None,
+                 auimgr=None, name='', **kwargs):
         """
-        
+
         :param parent: gui parent
         :param id: wx id
         :param title: window title
@@ -410,9 +428,9 @@ class SingleMapFrame(MapFrameBase):
         :param kwargs: arguments passed to MapFrameBase
         """
 
-        MapFrameBase.__init__(self, parent = parent, id = id, title = title,
-                              style = style,
-                              auimgr = auimgr, name = name, **kwargs)
+        MapFrameBase.__init__(self, parent=parent, id=id, title=title,
+                              style=style,
+                              auimgr=auimgr, name=name, **kwargs)
 
         self.Map = Map       # instance of render.Map
 
@@ -420,8 +438,8 @@ class SingleMapFrame(MapFrameBase):
         # initialize region values
         #
         if self.Map:
-            self._initMap(Map = self.Map)
-        
+            self._initMap(Map=self.Map)
+
     def GetMap(self):
         """Returns map (renderer) instance"""
         return self.Map
@@ -429,7 +447,7 @@ class SingleMapFrame(MapFrameBase):
     def GetWindow(self):
         """Returns map window"""
         return self.MapWindow
-        
+
     def GetWindows(self):
         """Returns list of map windows"""
         return [self.MapWindow]
@@ -437,42 +455,43 @@ class SingleMapFrame(MapFrameBase):
     def OnRender(self, event):
         """Re-render map composition (each map layer)
         """
-        self.GetWindow().UpdateMap(render = True, renderVector = True)
-        
+        self.GetWindow().UpdateMap(render=True, renderVector=True)
+
         # update statusbar
         self.StatusbarUpdate()
-        
+
 
 class DoubleMapFrame(MapFrameBase):
     """Frame with two map windows.
-    
+
     It is base class for frames which needs two maps.
     There is no primary and secondary map. Both maps are equal.
     However, one map is current.
-    
+
     It is expected that derived class will call _bindWindowsActivation()
     when both map windows will be initialized.
-    
+
     Drived class should have method GetMapToolbar() returns toolbar
     which has methods SetActiveMap() and Enable().
-    
+
     @note To access maps use getters only
     (when using class or when writing class itself).
-    
+
     .. todo:
         Use it in GCP manager (probably changes to both DoubleMapFrame
         and GCP MapFrame will be neccessary).
     """
-    def __init__(self, parent = None, id = wx.ID_ANY, title = None,
-                 style = wx.DEFAULT_FRAME_STYLE,
-                 firstMap = None, secondMap = None,
-                 auimgr = None, name = None, **kwargs):
+
+    def __init__(self, parent=None, id=wx.ID_ANY, title=None,
+                 style=wx.DEFAULT_FRAME_STYLE,
+                 firstMap=None, secondMap=None,
+                 auimgr=None, name=None, **kwargs):
         """
-        
+
         \a firstMap is set as active (by assign it to \c self.Map).
         Derived class should assging to \c self.MapWindow to make one
         map window current by dafault.
-        
+
         :param parent: gui parent
         :param id: wx id
         :param title: window title
@@ -480,11 +499,11 @@ class DoubleMapFrame(MapFrameBase):
         :param name: frame name
         :param kwargs: arguments passed to MapFrameBase
         """
-        
-        MapFrameBase.__init__(self, parent = parent, id = id, title = title,
-                              style = style,
-                              auimgr = auimgr, name = name, **kwargs)
-        
+
+        MapFrameBase.__init__(self, parent=parent, id=id, title=title,
+                              style=style,
+                              auimgr=auimgr, name=name, **kwargs)
+
         self.firstMap = firstMap
         self.secondMap = secondMap
         self.Map = firstMap
@@ -492,15 +511,15 @@ class DoubleMapFrame(MapFrameBase):
         #
         # initialize region values
         #
-        self._initMap(Map = self.firstMap)
-        self._initMap(Map = self.secondMap)
+        self._initMap(Map=self.firstMap)
+        self._initMap(Map=self.secondMap)
         self._bindRegions = False
-    
+
     def _bindWindowsActivation(self):
         self.GetFirstWindow().Bind(wx.EVT_ENTER_WINDOW, self.ActivateFirstMap)
         self.GetSecondWindow().Bind(wx.EVT_ENTER_WINDOW, self.ActivateSecondMap)
-    
-    def _onToggleTool(self, id): 
+
+    def _onToggleTool(self, id):
         if self._toolSwitcher.IsToolInGroup(id, 'mouseUse'):
             self.GetFirstWindow().UnregisterAllHandlers()
             self.GetSecondWindow().UnregisterAllHandlers()
@@ -509,41 +528,41 @@ class DoubleMapFrame(MapFrameBase):
         """Returns first Map instance
         """
         return self.firstMap
-        
+
     def GetSecondMap(self):
         """Returns second Map instance
         """
         return self.secondMap
-        
+
     def GetFirstWindow(self):
         """Get first map window"""
         return self.firstMapWindow
-    
+
     def GetSecondWindow(self):
         """Get second map window"""
         return self.secondMapWindow
-    
+
     def GetMap(self):
         """Returns current map (renderer) instance
-        
+
         @note Use this method to access current map renderer.
         (It is not guarented that current map will be stored in
         \c self.Map in future versions.)
         """
         return self.Map
-    
+
     def GetWindow(self):
         """Returns current map window
-        
+
         :func:`GetMap()`
         """
         return self.MapWindow
-    
+
     def GetWindows(self):
         """Return list of all windows"""
         return [self.firstMapWindow, self.secondMapWindow]
-    
-    def ActivateFirstMap(self, event = None):
+
+    def ActivateFirstMap(self, event=None):
         """Make first Map and MapWindow active and (un)bind regions of the two Maps."""
         if self.MapWindow == self.firstMapWindow:
             return
@@ -555,20 +574,23 @@ class DoubleMapFrame(MapFrameBase):
         # bind/unbind regions
         if self._bindRegions:
             self.firstMapWindow.zoomChanged.connect(self.OnZoomChangedFirstMap)
-            self.secondMapWindow.zoomChanged.disconnect(self.OnZoomChangedSecondMap)
+            self.secondMapWindow.zoomChanged.disconnect(
+                self.OnZoomChangedSecondMap)
 
-    def ActivateSecondMap(self, event = None):
+    def ActivateSecondMap(self, event=None):
         """Make second Map and MapWindow active and (un)bind regions of the two Maps."""
         if self.MapWindow == self.secondMapWindow:
-            return        
+            return
 
         self.Map = self.secondMap
         self.MapWindow = self.secondMapWindow
         self.GetMapToolbar().SetActiveMap(1)
 
         if self._bindRegions:
-            self.secondMapWindow.zoomChanged.connect(self.OnZoomChangedSecondMap)
-            self.firstMapWindow.zoomChanged.disconnect(self.OnZoomChangedFirstMap)
+            self.secondMapWindow.zoomChanged.connect(
+                self.OnZoomChangedSecondMap)
+            self.firstMapWindow.zoomChanged.disconnect(
+                self.OnZoomChangedFirstMap)
 
     def SetBindRegions(self, on):
         """Set or unset binding display regions."""
@@ -576,14 +598,18 @@ class DoubleMapFrame(MapFrameBase):
 
         if on:
             if self.MapWindow == self.firstMapWindow:
-                self.firstMapWindow.zoomChanged.connect(self.OnZoomChangedFirstMap)
+                self.firstMapWindow.zoomChanged.connect(
+                    self.OnZoomChangedFirstMap)
             else:
-                self.secondMapWindow.zoomChanged.connect(self.OnZoomChangedSecondMap)
+                self.secondMapWindow.zoomChanged.connect(
+                    self.OnZoomChangedSecondMap)
         else:
             if self.MapWindow == self.firstMapWindow:
-                self.firstMapWindow.zoomChanged.disconnect(self.OnZoomChangedFirstMap)
+                self.firstMapWindow.zoomChanged.disconnect(
+                    self.OnZoomChangedFirstMap)
             else:
-                self.secondMapWindow.zoomChanged.disconnect(self.OnZoomChangedSecondMap)
+                self.secondMapWindow.zoomChanged.disconnect(
+                    self.OnZoomChangedSecondMap)
 
     def OnZoomChangedFirstMap(self):
         """Display region of the first window (Map) changed.
@@ -593,7 +619,7 @@ class DoubleMapFrame(MapFrameBase):
         """
         region = self.GetFirstMap().GetCurrentRegion()
         self.GetSecondMap().region.update(region)
-        self.Render(mapToRender = self.GetSecondWindow())
+        self.Render(mapToRender=self.GetSecondWindow())
 
     def OnZoomChangedSecondMap(self):
         """Display region of the second window (Map) changed.
@@ -603,7 +629,7 @@ class DoubleMapFrame(MapFrameBase):
         """
         region = self.GetSecondMap().GetCurrentRegion()
         self.GetFirstMap().region.update(region)
-        self.Render(mapToRender = self.GetFirstWindow())
+        self.Render(mapToRender=self.GetFirstWindow())
 
     def OnZoomIn(self, event):
         """Zoom in the map."""
@@ -614,7 +640,7 @@ class DoubleMapFrame(MapFrameBase):
         """Zoom out the map."""
         self.GetFirstWindow().SetModeZoomOut()
         self.GetSecondWindow().SetModeZoomOut()
-        
+
     def OnPan(self, event):
         """Panning, set mouse to pan"""
         self.GetFirstWindow().SetModePan()
@@ -633,35 +659,36 @@ class DoubleMapFrame(MapFrameBase):
     def OnRender(self, event):
         """Re-render map composition (each map layer)
         """
-        self.Render(mapToRender = self.GetFirstWindow())
-        self.Render(mapToRender = self.GetSecondWindow())
-    
+        self.Render(mapToRender=self.GetFirstWindow())
+        self.Render(mapToRender=self.GetSecondWindow())
+
     def Render(self, mapToRender):
         """Re-render map composition"""
-        mapToRender.UpdateMap(render = True,
-                              renderVector = mapToRender == self.GetFirstWindow())
-        
+        mapToRender.UpdateMap(
+            render=True,
+            renderVector=mapToRender == self.GetFirstWindow())
+
         # update statusbar
         self.StatusbarUpdate()
-        
+
     def OnErase(self, event):
         """Erase the canvas
         """
-        self.Erase(mapToErase = self.GetFirstWindow())
-        self.Erase(mapToErase = self.GetSecondWindow())
-        
+        self.Erase(mapToErase=self.GetFirstWindow())
+        self.Erase(mapToErase=self.GetSecondWindow())
+
     def Erase(self, mapToErase):
         """Erase the canvas
         """
         mapToErase.EraseMap()
-        
+
     def OnDraw(self, event):
         """Re-display current map composition
         """
-        self.Draw(mapToDraw = self.GetFirstWindow())
-        self.Draw(mapToDraw = self.GetSecondWindow())
-        
+        self.Draw(mapToDraw=self.GetFirstWindow())
+        self.Draw(mapToDraw=self.GetSecondWindow())
+
     def Draw(self, mapToDraw):
         """Re-display current map composition
         """
-        mapToDraw.UpdateMap(render = False)
+        mapToDraw.UpdateMap(render=False)

+ 78 - 67
gui/wxpython/gui_core/menu.py

@@ -21,17 +21,19 @@ This program is free software under the GNU General Public License
 import re
 import wx
 
-from core              import globalvar
-from core              import utils
-from core.gcmd         import EncodeString
+from core import globalvar
+from core import utils
+from core.gcmd import EncodeString
 from core.utils import _
-from gui_core.widgets  import SearchModuleWidget
+from gui_core.widgets import SearchModuleWidget
 from gui_core.treeview import CTreeView
 from icons.icon import MetaIcon
 
 from grass.pydispatch.signal import Signal
 
+
 class Menu(wx.MenuBar):
+
     def __init__(self, parent, model):
         """Creates menubar"""
         wx.MenuBar.__init__(self)
@@ -42,7 +44,7 @@ class Menu(wx.MenuBar):
 
         for child in self.model.root.children:
             self.Append(self._createMenu(child), child.label)
-        
+
     def _createMenu(self, node):
         """Creates menu"""
         menu = wx.Menu()
@@ -54,15 +56,16 @@ class Menu(wx.MenuBar):
             else:
                 data = child.data.copy()
                 data.pop('label')
-                
+
                 self._createMenuItem(menu, label=child.label, **data)
-        
+
         self.parent.Bind(wx.EVT_MENU_HIGHLIGHT_ALL, self.OnMenuHighlight)
-        
+
         return menu
 
-    def _createMenuItem(self, menu, label, description, handler, command, keywords,
-                        shortcut = '', icon = '', wxId = wx.ID_ANY, kind = wx.ITEM_NORMAL):
+    def _createMenuItem(
+            self, menu, label, description, handler, command, keywords,
+            shortcut='', icon='', wxId=wx.ID_ANY, kind=wx.ITEM_NORMAL):
         """Creates menu items
         There are three menu styles (menu item text styles).
         1 -- label only, 2 -- label and cmd name, 3 -- cmd name only
@@ -70,51 +73,52 @@ class Menu(wx.MenuBar):
         if not label:
             menu.AppendSeparator()
             return
-        
+
         if command:
             helpString = command + ' -- ' + description
         else:
             helpString = description
-        
+
         if shortcut:
             label += '\t' + shortcut
-        
+
         menuItem = wx.MenuItem(menu, wxId, label, helpString, kind)
         if icon:
-            menuItem.SetBitmap(MetaIcon(img = icon).GetBitmap(self.bmpsize))
+            menuItem.SetBitmap(MetaIcon(img=icon).GetBitmap(self.bmpsize))
         menu.AppendItem(menuItem)
-        
+
         self.menucmd[menuItem.GetId()] = command
-        
-        if command: 
-            try: 
-                cmd = utils.split(str(command)) 
-            except UnicodeError: 
+
+        if command:
+            try:
+                cmd = utils.split(str(command))
+            except UnicodeError:
                 cmd = utils.split(EncodeString((command)))
-            # disable only grass commands which are not present (e.g. r.in.lidar)
+            # disable only grass commands which are not present (e.g.
+            # r.in.lidar)
             if cmd and cmd[0] not in globalvar.grassCmd and \
                re.match('[rvdipmgt][3bs]?\.([a-z0-9\.])+', cmd[0]):
                 menuItem.Enable(False)
 
         rhandler = eval('self.parent.' + handler)
         self.parent.Bind(wx.EVT_MENU, rhandler, menuItem)
-        
+
     def GetData(self):
         """Get menu data"""
         return self.model
-    
+
     def GetCmd(self):
         """Get dictionary of commands (key is id)
 
         :return: dictionary of commands
         """
         return self.menucmd
-        
+
     def OnMenuHighlight(self, event):
         """
         Default menu help handler
         """
-         # Show how to get menu item info from this event handler
+        # Show how to get menu item info from this event handler
         id = event.GetMenuId()
         item = self.FindItemById(id)
         if item:
@@ -124,22 +128,25 @@ class Menu(wx.MenuBar):
         # but in this case just call Skip so the default is done
         event.Skip()
 
+
 class SearchModuleWindow(wx.Panel):
     """Menu tree and search widget for searching modules.
-    
+
     Signal:
         showNotification - attribute 'message'
     """
-    def __init__(self, parent, handlerObj, model, id = wx.ID_ANY, **kwargs):
+
+    def __init__(self, parent, handlerObj, model, id=wx.ID_ANY, **kwargs):
         self.parent = parent
         self.handlerObj = handlerObj
-        
+
         self.showNotification = Signal('SearchModuleWindow.showNotification')
-        wx.Panel.__init__(self, parent = parent, id = id, **kwargs)
-        
+        wx.Panel.__init__(self, parent=parent, id=id, **kwargs)
+
         # tree
         self._tree = CTreeView(model=model, parent=self)
-        self._tree.SetToolTipString(_("Double-click or Ctrl-Enter to run selected module"))
+        self._tree.SetToolTipString(
+            _("Double-click or Ctrl-Enter to run selected module"))
 
 #        self._dataBox = wx.StaticBox(parent = self, id = wx.ID_ANY,
 #                                     label = " %s " % _("Module tree"))
@@ -148,65 +155,69 @@ class SearchModuleWindow(wx.Panel):
         self._search = SearchModuleWidget(parent=self,
                                           model=model,
                                           showChoice=False)
-        self._search.showSearchResult.connect(lambda result: self._tree.Select(result))
+        self._search.showSearchResult.connect(
+            lambda result: self._tree.Select(result))
         self._search.showNotification.connect(self.showNotification)
-        
-        self._helpText = wx.StaticText(parent=self, id=wx.ID_ANY,
-                                       label="Press Enter for next match, Ctrl+Enter to run command")
-        self._helpText.SetForegroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_GRAYTEXT))
-        
+
+        self._helpText = wx.StaticText(
+            parent=self, id=wx.ID_ANY,
+            label="Press Enter for next match, Ctrl+Enter to run command")
+        self._helpText.SetForegroundColour(
+            wx.SystemSettings_GetColour(
+                wx.SYS_COLOUR_GRAYTEXT))
+
         # buttons
         self._btnRun = wx.Button(self, id=wx.ID_OK, label=_("&Run"))
         self._btnRun.SetToolTipString(_("Run selected module from the tree"))
-        
+
         # bindings
         self._btnRun.Bind(wx.EVT_BUTTON, lambda evt: self.Run())
-        self.Bind(wx.EVT_KEY_UP,  self.OnKeyUp)
-        
+        self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
+
         self._tree.selectionChanged.connect(self.OnItemSelected)
         self._tree.itemActivated.connect(lambda node: self.Run(node))
 
         self._layout()
-        
+
         self._search.SetFocus()
-        
+
     def _layout(self):
         """Do dialog layout"""
         sizer = wx.BoxSizer(wx.VERTICAL)
-        
+
         # body
         dataSizer = wx.BoxSizer(wx.HORIZONTAL)
-        dataSizer.Add(item = self._tree, proportion =1,
-                      flag = wx.EXPAND)
-        
+        dataSizer.Add(item=self._tree, proportion=1,
+                      flag=wx.EXPAND)
+
         # buttons
         btnSizer = wx.BoxSizer(wx.HORIZONTAL)
-        btnSizer.Add(item = self._btnRun, proportion = 0)
-        
-        sizer.Add(item = dataSizer, proportion = 1,
-                  flag = wx.EXPAND | wx.ALL, border = 5)
-
-        sizer.Add(item = self._search, proportion = 0,
-                  flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
-        
-        sizer.Add(item = btnSizer, proportion = 0,
-                  flag = wx.ALIGN_RIGHT | wx.BOTTOM | wx.RIGHT, border = 5)
-        
+        btnSizer.Add(item=self._btnRun, proportion=0)
+
+        sizer.Add(item=dataSizer, proportion=1,
+                  flag=wx.EXPAND | wx.ALL, border=5)
+
+        sizer.Add(item=self._search, proportion=0,
+                  flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border=5)
+
+        sizer.Add(item=btnSizer, proportion=0,
+                  flag=wx.ALIGN_RIGHT | wx.BOTTOM | wx.RIGHT, border=5)
+
         sizer.Add(item=self._helpText,
                   proportion=0, flag=wx.EXPAND | wx.LEFT, border=5)
-        
+
         sizer.Fit(self)
         sizer.SetSizeHints(self)
-        
+
         self.SetSizer(sizer)
-        
+
         self.Fit()
-        self.SetAutoLayout(True)        
+        self.SetAutoLayout(True)
         self.Layout()
-        
+
     def Run(self, module=None):
         """Run selected command.
-        
+
         :param module: module (represented by tree node)
         """
         if module is None:
@@ -230,18 +241,18 @@ class SearchModuleWindow(wx.Panel):
         if event.ControlDown() and \
                 event.GetKeyCode() in (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER):
             self.Run()
-        
+
     def OnItemSelected(self, node):
-        """Item selected"""    
+        """Item selected"""
         data = node.data
         if not data or 'command' not in data:
             return
-        
+
         if data['command']:
             label = data['command']
             if data['description']:
                 label += ' -- ' + data['description']
         else:
             label = data['description']
-        
+
         self.showNotification.emit(message=label)

File diff ditekan karena terlalu besar
+ 1425 - 913
gui/wxpython/gui_core/preferences.py


+ 139 - 114
gui/wxpython/gui_core/prompt.py

@@ -30,64 +30,69 @@ from grass.script import task as gtask
 
 from grass.pydispatch.signal import Signal
 
-from core          import globalvar
-from core          import utils
-from core.gcmd     import EncodeString, DecodeString
+from core import globalvar
+from core import utils
+from core.gcmd import EncodeString, DecodeString
 from core.utils import _
 
 
 class GPrompt(object):
     """Abstract class for interactive wxGUI prompt
-    
+
     Signal promptRunCmd - emitted to run command from prompt
                         - attribute 'cmd'
 
     See subclass GPromptPopUp and GPromptSTC.
     """
+
     def __init__(self, parent, menuModel):
         self.parent = parent                 # GConsole
-        self.panel  = self.parent.GetPanel()
+        self.panel = self.parent.GetPanel()
 
         self.promptRunCmd = Signal('GPrompt.promptRunCmd')
 
         # probably only subclasses need this
         self._menuModel = menuModel
 
-        self.mapList    = self._getListOfMaps()
+        self.mapList = self._getListOfMaps()
         self.mapsetList = utils.ListOfMapsets()
-        
+
         # auto complete items
-        self.autoCompList   = list()
+        self.autoCompList = list()
         self.autoCompFilter = None
-        
+
         # command description (gtask.grassTask)
-        self.cmdDesc   = None
-        
+        self.cmdDesc = None
+
         self.cmdbuffer = self._readHistory()
-        self.cmdindex  = len(self.cmdbuffer)
-        
+        self.cmdindex = len(self.cmdbuffer)
+
         # list of traced commands
         self.commands = list()
-        
+
     def _readHistory(self):
         """Get list of commands from history file"""
         hist = list()
         env = grass.gisenv()
         try:
-            fileHistory = codecs.open(os.path.join(env['GISDBASE'],
-                                                   env['LOCATION_NAME'],
-                                                   env['MAPSET'],
-                                                   '.bash_history'),
-                                      encoding = 'utf-8', mode = 'r', errors='replace')
+            fileHistory = codecs.open(
+                os.path.join(
+                    env['GISDBASE'],
+                    env['LOCATION_NAME'],
+                    env['MAPSET'],
+                    '.bash_history'),
+                encoding='utf-8',
+                mode='r',
+                errors='replace')
         except IOError:
             return hist
-        
+
         try:
             for line in fileHistory.readlines():
                 hist.append(line.replace('\n', ''))
         finally:
             fileHistory.close()
-        
+
         return hist
 
     def _getListOfMaps(self):
@@ -95,18 +100,18 @@ class GPrompt(object):
         result = dict()
         result['raster'] = grass.list_strings('raster')
         result['vector'] = grass.list_strings('vector')
-        
+
         return result
-    
+
     def _runCmd(self, cmdString):
         """Run command
-        
+
         :param str cmdString: command to run
         """
         if not cmdString:
             return
 
-        self.commands.append(cmdString) # trace commands
+        self.commands.append(cmdString)  # trace commands
 
         # parse command into list
         try:
@@ -118,36 +123,37 @@ class GPrompt(object):
         self.promptRunCmd.emit(cmd=cmd)
 
         # add command to history & clean prompt
-        ### self.UpdateCmdHistory(cmd)
+        # self.UpdateCmdHistory(cmd)
         self.OnCmdErase(None)
         self.ShowStatusText('')
-        
+
     def GetCommands(self):
         """Get list of launched commands"""
         return self.commands
-    
+
     def ClearCommands(self):
         """Clear list of commands"""
         del self.commands[:]
 
 
 class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
-    """Styled wxGUI prompt with autocomplete and calltips"""  
-    def __init__(self, parent, menuModel, margin = False):
-        GPrompt.__init__(self, parent = parent, menuModel = menuModel)
-        wx.stc.StyledTextCtrl.__init__(self, self.panel, id = wx.ID_ANY)
-        
+    """Styled wxGUI prompt with autocomplete and calltips"""
+
+    def __init__(self, parent, menuModel, margin=False):
+        GPrompt.__init__(self, parent=parent, menuModel=menuModel)
+        wx.stc.StyledTextCtrl.__init__(self, self.panel, id=wx.ID_ANY)
+
         #
         # styles
-        #                
+        #
         self.SetWrapMode(True)
-        self.SetUndoCollection(True)        
-        
+        self.SetUndoCollection(True)
+
         #
         # create command and map lists for autocompletion
         #
-        self.AutoCompSetIgnoreCase(False) 
-                
+        self.AutoCompSetIgnoreCase(False)
+
         #
         # line margins
         #
@@ -159,7 +165,7 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
             self.SetMarginWidth(0, 30)
         else:
             self.SetMarginWidth(0, 0)
-        
+
         #
         # miscellaneous
         #
@@ -168,7 +174,7 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
         self.UsePopUp(True)
         self.SetSelBackground(True, "#FFFF00")
         self.SetUseHorizontalScrollBar(True)
-        
+
         #
         # bindings
         #
@@ -185,20 +191,21 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
 
         # signal to notify selected command
         self.commandSelected = Signal('GPromptSTC.commandSelected')
-        
+
     def OnTextSelectionChanged(self, event):
         """Copy selected text to clipboard and skip event.
         The same function is in GStc class (goutput.py).
         """
         wx.CallAfter(self.Copy)
         event.Skip()
-        
+
     def OnItemChanged(self, event):
-        """Change text in statusbar 
+        """Change text in statusbar
         if the item selection in the auto-completion list is changed"""
         # list of commands
         if self.toComplete['entity'] == 'command':
-            item = self.toComplete['cmd'].rpartition('.')[0] + '.' + self.autoCompList[event.GetIndex()] 
+            item = self.toComplete['cmd'].rpartition(
+                '.')[0] + '.' + self.autoCompList[event.GetIndex()]
             try:
                 nodes = self._menuModel.SearchNodes(key='command', value=item)
                 desc = ''
@@ -206,11 +213,13 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
                     self.commandSelected.emit(command=item)
                     desc = nodes[0].data['description']
             except KeyError:
-                desc = '' 
+                desc = ''
             self.ShowStatusText(desc)
-        # list of flags    
+        # list of flags
         elif self.toComplete['entity'] == 'flags':
-            desc = self.cmdDesc.get_flag(self.autoCompList[event.GetIndex()])['description']
+            desc = self.cmdDesc.get_flag(
+                self.autoCompList[
+                    event.GetIndex()])['description']
             self.ShowStatusText(desc)
         # list of parameters
         elif self.toComplete['entity'] == 'params':
@@ -220,12 +229,15 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
                 desc = '[' + desc + ']'
             desc += ': ' + item['description']
             self.ShowStatusText(desc)
-        # list of flags and commands       
+        # list of flags and commands
         elif self.toComplete['entity'] == 'params+flags':
             if self.autoCompList[event.GetIndex()][0] == '-':
-                desc = self.cmdDesc.get_flag(self.autoCompList[event.GetIndex()].strip('-'))['description']
+                desc = self.cmdDesc.get_flag(
+                    self.autoCompList[
+                        event.GetIndex()].strip('-'))['description']
             else:
-                item = self.cmdDesc.get_param(self.autoCompList[event.GetIndex()])
+                item = self.cmdDesc.get_param(
+                    self.autoCompList[event.GetIndex()])
                 desc = item['name'] + '=' + item['type']
                 if not item['required']:
                     desc = '[' + desc + ']'
@@ -233,31 +245,33 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
             self.ShowStatusText(desc)
         else:
             self.ShowStatusText('')
-            
+
     def OnItemSelected(self, event):
         """Item selected from the list"""
         lastWord = self.GetWordLeft()
-        # to insert selection correctly if selected word partly matches written text
+        # to insert selection correctly if selected word partly matches written
+        # text
         match = difflib.SequenceMatcher(None, event.GetText(), lastWord)
-        matchTuple = match.find_longest_match(0, len(event.GetText()), 0, len(lastWord))
-    
+        matchTuple = match.find_longest_match(
+            0, len(event.GetText()), 0, len(lastWord))
+
         compl = event.GetText()[matchTuple[2]:]
         text = self.GetTextLeft() + compl
         # add space or '=' at the end
         end = '='
-        for char in ('.','-','='):
+        for char in ('.', '-', '='):
             if text.split(' ')[-1].find(char) >= 0:
                 end = ' '
-        
+
         compl += end
         text += end
 
         self.AddText(compl)
         pos = len(text)
         self.SetCurrentPos(pos)
-        
+
         cmd = text.strip().split(' ')[0]
-        
+
         if not self.cmdDesc or cmd != self.cmdDesc.get_name():
             try:
                 self.cmdDesc = gtask.parse_interface(cmd)
@@ -281,17 +295,17 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
 
     def UpdateCmdHistory(self, cmd):
         """Update command history
-        
+
         :param cmd: command given as a string
         """
-        # add command to history    
+        # add command to history
         self.cmdbuffer.append(cmd)
-        
+
         # keep command history to a managable size
         if len(self.cmdbuffer) > 200:
             del self.cmdbuffer[0]
         self.cmdindex = len(self.cmdbuffer)
-        
+
     def EntityToComplete(self):
         """Determines which part of command (flags, parameters) should
         be completed at current cursor position"""
@@ -301,10 +315,10 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
             cmd = entry.split()[0].strip()
         except IndexError:
             return toComplete
-        
+
         try:
             splitted = utils.split(str(entry))
-        except ValueError: # No closing quotation error
+        except ValueError:  # No closing quotation error
             return toComplete
         if len(splitted) > 0 and cmd in globalvar.grassCmd:
             toComplete['cmd'] = cmd
@@ -316,13 +330,14 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
                     toComplete['entity'] = 'params+flags'
             else:
                 # get word left from current position
-                word = self.GetWordLeft(withDelimiter = True)
-                
+                word = self.GetWordLeft(withDelimiter=True)
+
                 if word[0] == '=' and word[-1] == '@':
                     toComplete['entity'] = 'mapsets'
                 elif word[0] == '=':
                     # get name of parameter
-                    paramName = self.GetWordLeft(withDelimiter = False, ignoredDelimiter = '=').strip('=')
+                    paramName = self.GetWordLeft(
+                        withDelimiter=False, ignoredDelimiter='=').strip('=')
                     if paramName:
                         try:
                             param = self.cmdDesc.get_param(paramName)
@@ -330,7 +345,7 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
                             return toComplete
                     else:
                         return toComplete
-                    
+
                     if param['values']:
                         toComplete['entity'] = 'param values'
                     elif param['prompt'] == 'raster' and param['element'] == 'cell':
@@ -344,22 +359,22 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
         else:
             toComplete['entity'] = 'command'
             toComplete['cmd'] = cmd
-        
+
         return toComplete
-    
-    def GetWordLeft(self, withDelimiter = False, ignoredDelimiter = None):
+
+    def GetWordLeft(self, withDelimiter=False, ignoredDelimiter=None):
         """Get word left from current cursor position. The beginning
-        of the word is given by space or chars: .,-= 
-        
+        of the word is given by space or chars: .,-=
+
         :param withDelimiter: returns the word with the initial delimeter
         :param ignoredDelimiter: finds the word ignoring certain delimeter
         """
         textLeft = self.GetTextLeft()
-        
+
         parts = list()
         if ignoredDelimiter is None:
             ignoredDelimiter = ''
-        
+
         for char in set(' .,-=') - set(ignoredDelimiter):
             if not withDelimiter:
                 delimiter = ''
@@ -367,12 +382,14 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
                 delimiter = char
             parts.append(delimiter + textLeft.rpartition(char)[2])
         return min(parts, key=lambda x: len(x))
-         
+
     def ShowList(self):
         """Show sorted auto-completion list if it is not empty"""
         if len(self.autoCompList) > 0:
             self.autoCompList.sort()
-            self.AutoCompShow(lenEntered = 0, itemList = ' '.join(self.autoCompList))    
+            self.AutoCompShow(
+                lenEntered=0, itemList=' '.join(
+                    self.autoCompList))
 
     def OnKeyPressed(self, event):
         """Key pressed capture special treatment for tabulator to show help"""
@@ -438,7 +455,7 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
         .. todo::
             event.ControlDown() for manual autocomplete
         """
-        # keycodes used: "." = 46, "=" = 61, "-" = 45 
+        # keycodes used: "." = 46, "=" = 61, "-" = 45
         pos = self.GetCurrentPos()
         # complete command after pressing '.'
         if event.GetKeyCode() == 46:
@@ -448,15 +465,18 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
             self.CharRight()
             self.toComplete = self.EntityToComplete()
             try:
-                if self.toComplete['entity'] == 'command': 
+                if self.toComplete['entity'] == 'command':
                     for command in globalvar.grassCmd:
                         try:
                             if command.find(self.toComplete['cmd']) == 0:
-                                dotNumber = list(self.toComplete['cmd']).count('.') 
-                                self.autoCompList.append(command.split('.',dotNumber)[-1])
-                        except UnicodeDecodeError as e: # TODO: fix it
-                            sys.stderr.write(DecodeString(command) + ": " + unicode(e))
-                            
+                                dotNumber = list(
+                                    self.toComplete['cmd']).count('.')
+                                self.autoCompList.append(
+                                    command.split('.', dotNumber)[-1])
+                        except UnicodeDecodeError as e:  # TODO: fix it
+                            sys.stderr.write(
+                                DecodeString(command) + ": " + unicode(e))
+
             except (KeyError, TypeError):
                 return
             self.ShowList()
@@ -471,16 +491,16 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
             self.CharRight()
             self.toComplete = self.EntityToComplete()
             if self.toComplete['entity'] == 'flags' and self.cmdDesc:
-                if self.GetTextLeft()[-2:] == ' -': # complete e.g. --quite
+                if self.GetTextLeft()[-2:] == ' -':  # complete e.g. --quite
                     for flag in self.cmdDesc.get_options()['flags']:
                         if len(flag['name']) == 1:
                             self.autoCompList.append(flag['name'])
                 else:
                     for flag in self.cmdDesc.get_options()['flags']:
                         if len(flag['name']) > 1:
-                            self.autoCompList.append(flag['name'])            
+                            self.autoCompList.append(flag['name'])
             self.ShowList()
-            
+
         # complete map or values after parameter
         elif event.GetKeyCode() == 61:
             self.autoCompList = list()
@@ -492,56 +512,59 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
             elif self.toComplete['entity'] == 'vector map':
                 self.autoCompList = self.mapList['vector']
             elif self.toComplete['entity'] == 'param values':
-                param = self.GetWordLeft(withDelimiter = False, ignoredDelimiter='=').strip(' =')
+                param = self.GetWordLeft(
+                    withDelimiter=False,
+                    ignoredDelimiter='=').strip(' =')
                 self.autoCompList = self.cmdDesc.get_param(param)['values']
             self.ShowList()
-        
+
         # complete mapset ('@')
         elif event.GetKeyCode() == 64:
             self.autoCompList = list()
             self.InsertText(pos, '@')
             self.CharRight()
             self.toComplete = self.EntityToComplete()
-            
+
             if self.toComplete['entity'] == 'mapsets':
                 self.autoCompList = self.mapsetList
             self.ShowList()
-            
-        # complete after pressing CTRL + Space          
+
+        # complete after pressing CTRL + Space
         elif event.GetKeyCode() == wx.WXK_SPACE and event.ControlDown():
             self.autoCompList = list()
             self.toComplete = self.EntityToComplete()
 
-            #complete command
+            # complete command
             if self.toComplete['entity'] == 'command':
                 for command in globalvar.grassCmd:
                     if command.find(self.toComplete['cmd']) == 0:
-                        dotNumber = list(self.toComplete['cmd']).count('.') 
-                        self.autoCompList.append(command.split('.',dotNumber)[-1])
-                
-            
+                        dotNumber = list(self.toComplete['cmd']).count('.')
+                        self.autoCompList.append(
+                            command.split('.', dotNumber)[-1])
+
             # complete flags in such situations (| is cursor):
             # r.colors -| ...w, q, l
-            # r.colors -w| ...w, q, l  
+            # r.colors -w| ...w, q, l
             elif self.toComplete['entity'] == 'flags' and self.cmdDesc:
                 for flag in self.cmdDesc.get_options()['flags']:
                     if len(flag['name']) == 1:
                         self.autoCompList.append(flag['name'])
-                    
+
             # complete parameters in such situations (| is cursor):
             # r.colors -w | ...color, map, rast, rules
             # r.colors col| ...color
             elif self.toComplete['entity'] == 'params' and self.cmdDesc:
                 for param in self.cmdDesc.get_options()['params']:
-                    if param['name'].find(self.GetWordLeft(withDelimiter=False)) == 0:
-                        self.autoCompList.append(param['name'])           
-            
+                    if param['name'].find(
+                            self.GetWordLeft(withDelimiter=False)) == 0:
+                        self.autoCompList.append(param['name'])
+
             # complete flags or parameters in such situations (| is cursor):
             # r.colors | ...-w, -q, -l, color, map, rast, rules
             # r.colors color=grey | ...-w, -q, -l, color, map, rast, rules
             elif self.toComplete['entity'] == 'params+flags' and self.cmdDesc:
                 self.autoCompList = list()
-                
+
                 for param in self.cmdDesc.get_options()['params']:
                     self.autoCompList.append(param['name'])
                 for flag in self.cmdDesc.get_options()['flags']:
@@ -549,12 +572,12 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
                         self.autoCompList.append('-' + flag['name'])
                     else:
                         self.autoCompList.append('--' + flag['name'])
-                    
-                self.ShowList() 
-                   
-            # complete map or values after parameter  
+
+                self.ShowList()
+
+            # complete map or values after parameter
             # r.buffer input=| ...list of raster maps
-            # r.buffer units=| ... feet, kilometers, ...   
+            # r.buffer units=| ... feet, kilometers, ...
             elif self.toComplete['entity'] == 'raster map':
                 self.autoCompList = list()
                 self.autoCompList = self.mapList['raster']
@@ -563,9 +586,11 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
                 self.autoCompList = self.mapList['vector']
             elif self.toComplete['entity'] == 'param values':
                 self.autoCompList = list()
-                param = self.GetWordLeft(withDelimiter = False, ignoredDelimiter='=').strip(' =')
+                param = self.GetWordLeft(
+                    withDelimiter=False,
+                    ignoredDelimiter='=').strip(' =')
                 self.autoCompList = self.cmdDesc.get_param(param)['values']
-                
+
             self.ShowList()
 
         elif event.GetKeyCode() == wx.WXK_SPACE:
@@ -579,23 +604,23 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
                     except IOError:
                         self.cmdDesc = None
             event.Skip()
-        
+
         else:
             event.Skip()
 
     def ShowStatusText(self, text):
         """Requests showing of notification, e.g. showing in a statusbar."""
         self.showNotification.emit(message=text)
-        
+
     def GetTextLeft(self):
         """Returns all text left of the caret"""
         pos = self.GetCurrentPos()
         self.HomeExtend()
         entry = self.GetSelectedText()
         self.SetCurrentPos(pos)
-        
+
         return entry
-    
+
     def OnDestroy(self, event):
         """The clipboard contents can be preserved after
         the app has exited"""

+ 10 - 7
gui/wxpython/gui_core/pyedit.py

@@ -88,11 +88,11 @@ def module_template():
 #
 #%s
 """ % ('#' * 72,
-       EncodeString(properties['name']),
-       EncodeString(properties['author']),
-       EncodeString('\n# '.join(properties['description'].splitlines())),
-       time.asctime(),
-       '#' * 72))
+            EncodeString(properties['name']),
+            EncodeString(properties['author']),
+            EncodeString('\n# '.join(properties['description'].splitlines())),
+            time.asctime(),
+            '#' * 72))
 
     # UI
     output.write(
@@ -323,7 +323,8 @@ class PyEditController(object):
         else:
             self.SaveAs()
 
-    # TODO: it should be probably used with replacing, when this gives what we want?
+    # TODO: it should be probably used with replacing, when this gives what we
+    # want?
     def IsModified(self):
         """Check if python script has been modified"""
         return self.body.modified
@@ -432,6 +433,7 @@ class PyEditToolbar(BaseToolbar):
     # pylint: disable=too-many-ancestors
     # pylint: disable=too-many-public-methods
     """PyEdit toolbar"""
+
     def __init__(self, parent):
         BaseToolbar.__init__(self, parent)
 
@@ -465,7 +467,7 @@ class PyEditToolbar(BaseToolbar):
                                      (None, ),
                                      ("help", BaseIcons['help'],
                                       self.parent.OnHelp),
-                                    ))
+                                     ))
 
 
 class PyEditFrame(wx.Frame):
@@ -473,6 +475,7 @@ class PyEditFrame(wx.Frame):
     # pylint: disable=missing-docstring
     # pylint: disable=too-many-public-methods
     # pylint: disable=invalid-name
+
     def __init__(self, parent, giface, id=wx.ID_ANY,
                  title=_("GRASS GIS Simple Python Editor"),
                  **kwargs):

+ 181 - 86
gui/wxpython/gui_core/pystc.py

@@ -27,60 +27,93 @@ class PyStc(stc.StyledTextCtrl):
     usage)
 
     Based on StyledTextCtrl_2 from wxPython demo
-    """  
-    def __init__(self, parent, id = wx.ID_ANY, statusbar = None):
+    """
+
+    def __init__(self, parent, id=wx.ID_ANY, statusbar=None):
         stc.StyledTextCtrl.__init__(self, parent, id)
-        
+
         self.parent = parent
         self.statusbar = statusbar
-        
-        self.modified = False # content modified ?
+
+        self.modified = False  # content modified ?
 
         # this is supposed to get monospace
-        font = wx.Font(9, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
+        font = wx.Font(
+            9,
+            wx.FONTFAMILY_MODERN,
+            wx.FONTSTYLE_NORMAL,
+            wx.FONTWEIGHT_NORMAL)
         face = font.GetFaceName()
         size = font.GetPointSize()
 
         # setting the monospace here to not mess with the rest of the code
         # TODO: review the whole styling
-        self.faces = { 'times': face,
-                       'mono' : face,
-                       'helv' : face,
-                       'other': face,
-                       'size' : 10,
-                       'size2': 8,
-                       }
-        
+        self.faces = {'times': face,
+                      'mono': face,
+                      'helv': face,
+                      'other': face,
+                      'size': 10,
+                      'size2': 8,
+                      }
+
         self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
         self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
-        
+
         self.SetLexer(stc.STC_LEX_PYTHON)
         self.SetKeyWords(0, " ".join(keyword.kwlist))
-        
+
         self.SetProperty("fold", "1")
         self.SetProperty("tab.timmy.whinge.level", "1")
         self.SetMargins(0, 0)
         self.SetTabWidth(4)
         self.SetUseTabs(False)
-        
+
         self.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
         self.SetEdgeColumn(78)
-        
+
         # setup a margin to hold fold markers
         self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
         self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
         self.SetMarginSensitive(2, True)
         self.SetMarginWidth(2, 12)
-        
+
         # like a flattened tree control using square headers
-        self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN,    stc.STC_MARK_BOXMINUS,          "white", "#808080")
-        self.MarkerDefine(stc.STC_MARKNUM_FOLDER,        stc.STC_MARK_BOXPLUS,           "white", "#808080")
-        self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,     stc.STC_MARK_VLINE,             "white", "#808080")
-        self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,    stc.STC_MARK_LCORNER,           "white", "#808080")
-        self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,     stc.STC_MARK_BOXPLUSCONNECTED,  "white", "#808080")
-        self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
-        self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER,           "white", "#808080")
-        
+        self.MarkerDefine(
+            stc.STC_MARKNUM_FOLDEROPEN,
+            stc.STC_MARK_BOXMINUS,
+            "white",
+            "#808080")
+        self.MarkerDefine(
+            stc.STC_MARKNUM_FOLDER,
+            stc.STC_MARK_BOXPLUS,
+            "white",
+            "#808080")
+        self.MarkerDefine(
+            stc.STC_MARKNUM_FOLDERSUB,
+            stc.STC_MARK_VLINE,
+            "white",
+            "#808080")
+        self.MarkerDefine(
+            stc.STC_MARKNUM_FOLDERTAIL,
+            stc.STC_MARK_LCORNER,
+            "white",
+            "#808080")
+        self.MarkerDefine(
+            stc.STC_MARKNUM_FOLDEREND,
+            stc.STC_MARK_BOXPLUSCONNECTED,
+            "white",
+            "#808080")
+        self.MarkerDefine(
+            stc.STC_MARKNUM_FOLDEROPENMID,
+            stc.STC_MARK_BOXMINUSCONNECTED,
+            "white",
+            "#808080")
+        self.MarkerDefine(
+            stc.STC_MARKNUM_FOLDERMIDTAIL,
+            stc.STC_MARK_TCORNER,
+            "white",
+            "#808080")
+
         self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
         self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
         self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
@@ -93,94 +126,155 @@ class PyStc(stc.StyledTextCtrl):
         # Make some styles, the lexer defines what each style is used
         # for, we just have to define what each style looks like.
         # This set is adapted from Scintilla sample property files.
-        
+
         # global default styles for all languages
-        self.StyleSetSpec(stc.STC_STYLE_DEFAULT,     "face:%(helv)s,size:%(size)d" % self.faces)
+        self.StyleSetSpec(
+            stc.STC_STYLE_DEFAULT,
+            "face:%(helv)s,size:%(size)d" %
+            self.faces)
         self.StyleClearAll()  # reset all to be like the default
-        
+
         # global default styles for all languages
-        self.StyleSetSpec(stc.STC_STYLE_DEFAULT,     "face:%(helv)s,size:%(size)d" % self.faces)
-        self.StyleSetSpec(stc.STC_STYLE_LINENUMBER,  "back:#C0C0C0,face:%(helv)s,size:%(size2)d" % self.faces)
-        self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(other)s" % self.faces)
-        self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,  "fore:#FFFFFF,back:#0000FF,bold")
-        self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,    "fore:#000000,back:#FF0000,bold")
-        
+        self.StyleSetSpec(
+            stc.STC_STYLE_DEFAULT,
+            "face:%(helv)s,size:%(size)d" %
+            self.faces)
+        self.StyleSetSpec(
+            stc.STC_STYLE_LINENUMBER,
+            "back:#C0C0C0,face:%(helv)s,size:%(size2)d" %
+            self.faces)
+        self.StyleSetSpec(
+            stc.STC_STYLE_CONTROLCHAR,
+            "face:%(other)s" %
+            self.faces)
+        self.StyleSetSpec(
+            stc.STC_STYLE_BRACELIGHT,
+            "fore:#FFFFFF,back:#0000FF,bold")
+        self.StyleSetSpec(
+            stc.STC_STYLE_BRACEBAD,
+            "fore:#000000,back:#FF0000,bold")
+
         # Python styles
-        # Default 
-        self.StyleSetSpec(stc.STC_P_DEFAULT, "fore:#000000,face:%(helv)s,size:%(size)d" % self.faces)
+        # Default
+        self.StyleSetSpec(
+            stc.STC_P_DEFAULT,
+            "fore:#000000,face:%(helv)s,size:%(size)d" %
+            self.faces)
         # Comments
-        self.StyleSetSpec(stc.STC_P_COMMENTLINE, "fore:#007F00,face:%(other)s,size:%(size)d" % self.faces)
+        self.StyleSetSpec(
+            stc.STC_P_COMMENTLINE,
+            "fore:#007F00,face:%(other)s,size:%(size)d" %
+            self.faces)
         # Number
-        self.StyleSetSpec(stc.STC_P_NUMBER, "fore:#007F7F,size:%(size)d" % self.faces)
+        self.StyleSetSpec(
+            stc.STC_P_NUMBER,
+            "fore:#007F7F,size:%(size)d" %
+            self.faces)
         # String
-        self.StyleSetSpec(stc.STC_P_STRING, "fore:#7F007F,face:%(helv)s,size:%(size)d" % self.faces)
+        self.StyleSetSpec(
+            stc.STC_P_STRING,
+            "fore:#7F007F,face:%(helv)s,size:%(size)d" %
+            self.faces)
         # Single quoted string
-        self.StyleSetSpec(stc.STC_P_CHARACTER, "fore:#7F007F,face:%(helv)s,size:%(size)d" % self.faces)
+        self.StyleSetSpec(
+            stc.STC_P_CHARACTER,
+            "fore:#7F007F,face:%(helv)s,size:%(size)d" %
+            self.faces)
         # Keyword
-        self.StyleSetSpec(stc.STC_P_WORD, "fore:#00007F,bold,size:%(size)d" % self.faces)
+        self.StyleSetSpec(
+            stc.STC_P_WORD,
+            "fore:#00007F,bold,size:%(size)d" %
+            self.faces)
         # Triple quotes
-        self.StyleSetSpec(stc.STC_P_TRIPLE, "fore:#7F0000,size:%(size)d" % self.faces)
+        self.StyleSetSpec(
+            stc.STC_P_TRIPLE,
+            "fore:#7F0000,size:%(size)d" %
+            self.faces)
         # Triple double quotes
-        self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, "fore:#7F0000,size:%(size)d" % self.faces)
+        self.StyleSetSpec(
+            stc.STC_P_TRIPLEDOUBLE,
+            "fore:#7F0000,size:%(size)d" %
+            self.faces)
         # Class name definition
-        self.StyleSetSpec(stc.STC_P_CLASSNAME, "fore:#0000FF,bold,underline,size:%(size)d" % self.faces)
+        self.StyleSetSpec(
+            stc.STC_P_CLASSNAME,
+            "fore:#0000FF,bold,underline,size:%(size)d" %
+            self.faces)
         # Function or method name definition
-        self.StyleSetSpec(stc.STC_P_DEFNAME, "fore:#007F7F,bold,size:%(size)d" % self.faces)
+        self.StyleSetSpec(
+            stc.STC_P_DEFNAME,
+            "fore:#007F7F,bold,size:%(size)d" %
+            self.faces)
         # Operators
-        self.StyleSetSpec(stc.STC_P_OPERATOR, "bold,size:%(size)d" % self.faces)
+        self.StyleSetSpec(
+            stc.STC_P_OPERATOR,
+            "bold,size:%(size)d" %
+            self.faces)
         # Identifiers
-        self.StyleSetSpec(stc.STC_P_IDENTIFIER, "fore:#000000,face:%(helv)s,size:%(size)d" % self.faces)
+        self.StyleSetSpec(
+            stc.STC_P_IDENTIFIER,
+            "fore:#000000,face:%(helv)s,size:%(size)d" %
+            self.faces)
         # Comment-blocks
-        self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, "fore:#7F7F7F,size:%(size)d" % self.faces)
+        self.StyleSetSpec(
+            stc.STC_P_COMMENTBLOCK,
+            "fore:#7F7F7F,size:%(size)d" %
+            self.faces)
         # End of line where string is not closed
-        self.StyleSetSpec(stc.STC_P_STRINGEOL, "fore:#000000,face:%(mono)s,back:#E0C0E0,eol,size:%(size)d" % self.faces)
-        
+        self.StyleSetSpec(
+            stc.STC_P_STRINGEOL,
+            "fore:#000000,face:%(mono)s,back:#E0C0E0,eol,size:%(size)d" %
+            self.faces)
+
         self.SetCaretForeground("BLUE")
-        
+
     def OnKeyPressed(self, event):
         """Key pressed
-        
+
         .. todo::
             implement code completion (see wxPython demo)
         """
         if not self.modified:
             self.modified = True
             if self.statusbar:
-                self.statusbar.SetStatusText(_('Python script contains local modifications'), 0)
-        
+                self.statusbar.SetStatusText(
+                    _('Python script contains local modifications'), 0)
+
         event.Skip()
-        
+
     def OnUpdateUI(self, evt):
         # check for matching braces
         braceAtCaret = -1
         braceOpposite = -1
         charBefore = None
         caretPos = self.GetCurrentPos()
-        
+
         if caretPos > 0:
-            charBefore  = self.GetCharAt(caretPos - 1)
+            charBefore = self.GetCharAt(caretPos - 1)
             styleBefore = self.GetStyleAt(caretPos - 1)
-        
+
         # check before
-        if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
+        if charBefore and chr(
+                charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
             braceAtCaret = caretPos - 1
-        
+
         # check after
         if braceAtCaret < 0:
             charAfter = self.GetCharAt(caretPos)
             styleAfter = self.GetStyleAt(caretPos)
-            
-            if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
+
+            if charAfter and chr(
+                    charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
                 braceAtCaret = caretPos
-        
+
         if braceAtCaret >= 0:
             braceOpposite = self.BraceMatch(braceAtCaret)
-        
-        if braceAtCaret != -1  and braceOpposite == -1:
+
+        if braceAtCaret != -1 and braceOpposite == -1:
             self.BraceBadLight(braceAtCaret)
         else:
             self.BraceHighlight(braceAtCaret, braceOpposite)
-        
+
     def OnMarginClick(self, evt):
         # fold and unfold as needed
         if evt.GetMargin() == 2:
@@ -188,8 +282,9 @@ class PyStc(stc.StyledTextCtrl):
                 self.FoldAll()
             else:
                 lineClicked = self.LineFromPosition(evt.GetPosition())
-                
-                if self.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
+
+                if self.GetFoldLevel(
+                        lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
                     if evt.GetShift():
                         self.SetFoldExpanded(lineClicked, True)
                         self.Expand(lineClicked, True, True, 1)
@@ -202,23 +297,23 @@ class PyStc(stc.StyledTextCtrl):
                             self.Expand(lineClicked, True, True, 100)
                     else:
                         self.ToggleFold(lineClicked)
-        
+
     def FoldAll(self):
         lineCount = self.GetLineCount()
         expanding = True
-        
+
         # find out if we are folding or unfolding
         for lineNum in range(lineCount):
             if self.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG:
                 expanding = not self.GetFoldExpanded(lineNum)
                 break
-        
+
         lineNum = 0
         while lineNum < lineCount:
             level = self.GetFoldLevel(lineNum)
             if level & stc.STC_FOLDLEVELHEADERFLAG and \
                (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
-                
+
                 if expanding:
                     self.SetFoldExpanded(lineNum, True)
                     lineNum = self.Expand(lineNum, True)
@@ -226,16 +321,16 @@ class PyStc(stc.StyledTextCtrl):
                 else:
                     lastChild = self.GetLastChild(lineNum, -1)
                     self.SetFoldExpanded(lineNum, False)
-                    
+
                     if lastChild > lineNum:
-                        self.HideLines(lineNum+1, lastChild)
-            
+                        self.HideLines(lineNum + 1, lastChild)
+
             lineNum = lineNum + 1
-        
+
     def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
         lastChild = self.GetLastChild(line, level)
         line = line + 1
-        
+
         while line <= lastChild:
             if force:
                 if visLevels > 0:
@@ -245,24 +340,24 @@ class PyStc(stc.StyledTextCtrl):
             else:
                 if doExpand:
                     self.ShowLines(line, line)
-            
+
             if level == -1:
                 level = self.GetFoldLevel(line)
-            
+
             if level & stc.STC_FOLDLEVELHEADERFLAG:
                 if force:
                     if visLevels > 1:
                         self.SetFoldExpanded(line, True)
                     else:
                         self.SetFoldExpanded(line, False)
-                    
-                    line = self.Expand(line, doExpand, force, visLevels-1)
+
+                    line = self.Expand(line, doExpand, force, visLevels - 1)
                 else:
                     if doExpand and self.GetFoldExpanded(line):
-                        line = self.Expand(line, True, force, visLevels-1)
+                        line = self.Expand(line, True, force, visLevels - 1)
                     else:
-                        line = self.Expand(line, False, force, visLevels-1)
+                        line = self.Expand(line, False, force, visLevels - 1)
             else:
                 line = line + 1
-        
+
         return line

+ 90 - 43
gui/wxpython/gui_core/query.py

@@ -23,55 +23,76 @@ from core.treemodel import TreeModel, DictNode
 
 from grass.pydispatch.signal import Signal
 
+
 class QueryDialog(wx.Dialog):
-    def __init__(self, parent, data = None):
-        wx.Dialog.__init__(self, parent, id = wx.ID_ANY,
-                           title = _("Query results"),
-                           size = (420, 400),
-                           style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
+
+    def __init__(self, parent, data=None):
+        wx.Dialog.__init__(self, parent, id=wx.ID_ANY,
+                           title=_("Query results"),
+                           size=(420, 400),
+                           style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
         # send query output to console
         self.redirectOutput = Signal('QueryDialog.redirectOutput')
 
         self.data = data
 
-        self.panel = wx.Panel(self, id = wx.ID_ANY)
+        self.panel = wx.Panel(self, id=wx.ID_ANY)
         self.mainSizer = wx.BoxSizer(wx.VERTICAL)
 
-        helpText = wx.StaticText(self.panel, wx.ID_ANY,
-                                 label=_("Right click to copy selected values to clipboard."))
-        helpText.SetForegroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_GRAYTEXT))
+        helpText = wx.StaticText(self.panel, wx.ID_ANY, label=_(
+            "Right click to copy selected values to clipboard."))
+        helpText.SetForegroundColour(
+            wx.SystemSettings_GetColour(
+                wx.SYS_COLOUR_GRAYTEXT))
         self.mainSizer.Add(item=helpText, proportion=0, flag=wx.ALL, border=5)
 
         self._colNames = [_("Feature"), _("Value")]
         self._model = QueryTreeBuilder(self.data, column=self._colNames[1])
         self.tree = TreeListView(model=self._model, parent=self.panel,
                                  columns=self._colNames,
-                                 style=wx.TR_DEFAULT_STYLE | 
+                                 style=wx.TR_DEFAULT_STYLE |
                                  wx.TR_FULL_ROW_HIGHLIGHT | wx.TR_MULTIPLE)
 
         self.tree.SetColumnWidth(0, 220)
         self.tree.SetColumnWidth(1, 1000)
         self.tree.ExpandAll(self._model.root)
         self.tree.contextMenu.connect(self.ShowContextMenu)
-        self.mainSizer.Add(item = self.tree, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 5)
+        self.mainSizer.Add(
+            item=self.tree,
+            proportion=1,
+            flag=wx.EXPAND | wx.ALL,
+            border=5)
 
-        
-        close = wx.Button(self.panel, id = wx.ID_CLOSE)
+        close = wx.Button(self.panel, id=wx.ID_CLOSE)
         close.Bind(wx.EVT_BUTTON, lambda event: self.Close())
-        copy = wx.Button(self.panel, id = wx.ID_ANY, label = _("Copy all to clipboard"))
+        copy = wx.Button(
+            self.panel,
+            id=wx.ID_ANY,
+            label=_("Copy all to clipboard"))
         copy.Bind(wx.EVT_BUTTON, self.Copy)
         self.Bind(wx.EVT_CLOSE, self.OnClose)
         self.redirect = wx.CheckBox(self.panel, label=_("Redirect to console"))
         self.redirect.SetValue(False)
-        self.redirect.Bind(wx.EVT_CHECKBOX, lambda evt: self._onRedirect(evt.IsChecked()))
+        self.redirect.Bind(
+            wx.EVT_CHECKBOX,
+            lambda evt: self._onRedirect(
+                evt.IsChecked()))
 
         hbox = wx.BoxSizer(wx.HORIZONTAL)
-        hbox.Add(item=self.redirect, proportion=0, flag=wx.EXPAND | wx.RIGHT, border=5)
+        hbox.Add(
+            item=self.redirect,
+            proportion=0,
+            flag=wx.EXPAND | wx.RIGHT,
+            border=5)
         hbox.AddStretchSpacer(1)
         hbox.Add(item=copy, proportion=0, flag=wx.EXPAND | wx.RIGHT, border=5)
         hbox.Add(item=close, proportion=0, flag=wx.EXPAND | wx.ALL, border=0)
 
-        self.mainSizer.Add(item=hbox, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
+        self.mainSizer.Add(
+            item=hbox,
+            proportion=0,
+            flag=wx.EXPAND | wx.ALL,
+            border=5)
         self.panel.SetSizer(self.mainSizer)
         self.mainSizer.Fit(self.panel)
         # for Windows
@@ -93,41 +114,55 @@ class QueryDialog(wx.Dialog):
 
     def ShowContextMenu(self, node):
         """Show context menu.
-        
+
         Menu for copying distinguishes single and multiple selection.
         """
         nodes = self.tree.GetSelected()
         if not nodes:
             return
-            
+
         menu = wx.Menu()
         texts = []
         if len(nodes) > 1:
             values = []
             for node in nodes:
-                values.append((node.label, node.data[self._colNames[1]] if node.data else ''))
+                values.append(
+                    (node.label, node.data[
+                        self._colNames[1]] if node.data else ''))
             col1 = '\n'.join([val[1] for val in values if val[1]])
             col2 = '\n'.join([val[0] for val in values if val[0]])
             table = '\n'.join([val[0] + ': ' + val[1] for val in values])
-            texts.append((_("Copy from '%s' column") % self._colNames[1], col1))
-            texts.append((_("Copy from '%s' column") % self._colNames[0], col2))
+            texts.append(
+                (_("Copy from '%s' column") %
+                 self._colNames[1], col1))
+            texts.append(
+                (_("Copy from '%s' column") %
+                 self._colNames[0], col2))
             texts.append((_("Copy selected lines"), table))
         else:
             label1 = nodes[0].label
             texts.append((_("Copy '%s'" % self._cutLabel(label1)), label1))
             if nodes[0].data and nodes[0].data[self._colNames[1]]:
                 label2 = nodes[0].data[self._colNames[1]]
-                texts.insert(0, (_("Copy '%s'" % self._cutLabel(label2)), label2))
+                texts.insert(
+                    0, (_(
+                        "Copy '%s'" %
+                        self._cutLabel(label2)), label2))
                 texts.append((_("Copy line"), label1 + ': ' + label2))
 
         ids = []
         for text in texts:
             id = wx.NewId()
             ids.append(id)
-            self.Bind(wx.EVT_MENU, lambda evt, t=text[1], id=id: self._copyText(t), id=id)
- 
+            self.Bind(
+                wx.EVT_MENU,
+                lambda evt,
+                t=text[1],
+                id=id: self._copyText(t),
+                id=id)
+
             menu.Append(id, text[0])
- 
+
         # show the popup menu
         self.PopupMenu(menu)
         menu.Destroy()
@@ -136,8 +171,8 @@ class QueryDialog(wx.Dialog):
 
     def _onRedirect(self, redirect):
         """Emits instructions to redirect query results.
-        
-        :param redirect: True to start redirecting, False to stop        
+
+        :param redirect: True to start redirecting, False to stop
         """
         if redirect:
             self.redirectOutput.emit(output=_("Query results:"), style='cmd')
@@ -147,14 +182,14 @@ class QueryDialog(wx.Dialog):
 
     def _textToRedirect(self):
         text = printResults(self._model, self._colNames[1])
-        text += '\n' + "-"* 50 + '\n'
+        text += '\n' + "-" * 50 + '\n'
         return text
 
     def _cutLabel(self, label):
         limit = 15
         if len(label) > limit:
             return label[:limit] + '...'
-            
+
         return label
 
     def _copyText(self, text):
@@ -205,17 +240,22 @@ def QueryTreeBuilder(data, column):
 
 def printResults(model, valueCol):
     """Print all results to string.
-    
+
     :param model: results tree model
     :param valueCol: column name with value to be printed
     """
     def printTree(node, textList, valueCol, indent=0):
         if node.data.get(valueCol, '') or node.children:
-            textList.append(indent*' ' + node.label + ': ' + node.data.get(valueCol, ''))
+            textList.append(
+                indent * ' ' + node.label + ': ' + node.data.get(valueCol, ''))
         for child in node.children:
-            printTree(node=child, textList=textList, valueCol=valueCol, indent=indent + 2)
-    
-    textList=[]
+            printTree(
+                node=child,
+                textList=textList,
+                valueCol=valueCol,
+                indent=indent + 2)
+
+    textList = []
     for child in model.root.children:
         printTree(node=child, textList=textList, valueCol=valueCol)
     return '\n'.join(textList)
@@ -248,16 +288,23 @@ def test():
     app = wx.App()
     from grass.script import vector as gvect
     from grass.script import raster as grast
-    testdata1 = grast.raster_what(map = ('elevation_shade@PERMANENT','landclass96'),
-                                  coord = [(638509.051416,224742.348346)],
-                                  localized=True)
+    testdata1 = grast.raster_what(
+        map=('elevation_shade@PERMANENT', 'landclass96'),
+        coord=[(638509.051416, 224742.348346)],
+        localized=True)
+
+    testdata2 = gvect.vector_what(
+        map=(
+            'firestations', 'bridges'), coord=(
+            633177.897487, 221352.921257), distance=10)
 
-    testdata2 = gvect.vector_what(map=('firestations','bridges'),
-                                  coord=(633177.897487,221352.921257), distance=10)
-    
     testdata = testdata1 + testdata2
-    data = PrepareQueryResults(coordinates = (638509.051416,224742.348346), result = testdata)
-    frame = QueryDialog(parent = None, data = data)
+    data = PrepareQueryResults(
+        coordinates=(
+            638509.051416,
+            224742.348346),
+        result=testdata)
+    frame = QueryDialog(parent=None, data=data)
     frame.ShowModal()
     frame.Destroy()
     app.MainLoop()

+ 56 - 36
gui/wxpython/gui_core/simplelmgr.py

@@ -45,9 +45,11 @@ SIMPLE_LMGR_TB_RIGHT = 128
 class SimpleLayerManager(wx.Panel):
     """Simple layer manager class provides similar functionality to
     Layertree, but it's just list, not tree."""
-    def __init__(self, parent, layerList,
-                 lmgrStyle=SIMPLE_LMGR_RASTER | SIMPLE_LMGR_VECTOR | SIMPLE_LMGR_TB_LEFT,
-                 toolbarCls=None, modal=False):
+
+    def __init__(
+            self, parent, layerList, lmgrStyle=SIMPLE_LMGR_RASTER |
+            SIMPLE_LMGR_VECTOR | SIMPLE_LMGR_TB_LEFT, toolbarCls=None,
+            modal=False):
         wx.Panel.__init__(self, parent=parent, name='SimpleLayerManager')
 
         self._style = lmgrStyle
@@ -67,8 +69,12 @@ class SimpleLayerManager(wx.Panel):
         # needed in order not to change selection when moving layers
         self._blockSelectionChanged = False
 
-        self._checkList.Bind(wx.EVT_LISTBOX, lambda evt: self._selectionChanged())
-        self._checkList.Bind(wx.EVT_LISTBOX_DCLICK, self.OnLayerChangeProperties)
+        self._checkList.Bind(
+            wx.EVT_LISTBOX,
+            lambda evt: self._selectionChanged())
+        self._checkList.Bind(
+            wx.EVT_LISTBOX_DCLICK,
+            self.OnLayerChangeProperties)
         self._checkList.Bind(wx.EVT_CHECKLISTBOX, self.OnLayerChecked)
         self._checkList.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)
 
@@ -95,9 +101,9 @@ class SimpleLayerManager(wx.Panel):
                              CloseButton(False).
                              BestSize((self._checkList.GetBestSize())))
         paneInfo = wx.aui.AuiPaneInfo(). \
-                   Name("toolbar").Caption(_("Toolbar")).ToolbarPane(). \
-                   CloseButton(False).Layer(1).Gripper(False). \
-                   BestSize((self._toolbar.GetBestSize()))
+            Name("toolbar").Caption(_("Toolbar")).ToolbarPane(). \
+            CloseButton(False).Layer(1).Gripper(False). \
+            BestSize((self._toolbar.GetBestSize()))
         if self._style & SIMPLE_LMGR_TB_LEFT:
             paneInfo.Left()
         elif self._style & SIMPLE_LMGR_TB_RIGHT:
@@ -135,7 +141,12 @@ class SimpleLayerManager(wx.Panel):
                   _("Copy map names to clipboard (bottom to top)")]
         for label, text in zip(labels, texts):
             id = wx.NewId()
-            self.Bind(wx.EVT_MENU, lambda evt, t=text, id=id: self._copyText(t), id=id)
+            self.Bind(
+                wx.EVT_MENU,
+                lambda evt,
+                t=text,
+                id=id: self._copyText(t),
+                id=id)
 
             menu.Append(id, label)
 
@@ -147,7 +158,7 @@ class SimpleLayerManager(wx.Panel):
     def _copyText(self, text):
         """Helper function for copying
 
-        TODO: move to utils?        
+        TODO: move to utils?
         """
         if wx.TheClipboard.Open():
             do = wx.TextDataObject()
@@ -173,8 +184,8 @@ class SimpleLayerManager(wx.Panel):
         Dummy layer is added first."""
         cmd = ['d.rast']
         layer = self.AddRaster(name='', cmd=cmd, hidden=True, dialog=None)
-        GUI(parent=self, giface=None, modal=self._modal).ParseCommand(cmd=cmd,
-                                                    completed=(self.GetOptData, layer, ''))
+        GUI(parent=self, giface=None, modal=self._modal).ParseCommand(
+            cmd=cmd, completed=(self.GetOptData, layer, ''))
         event.Skip()
 
     def OnAddVector(self, event):
@@ -183,8 +194,8 @@ class SimpleLayerManager(wx.Panel):
         cmd = ['d.vect']
 
         layer = self.AddVector(name='', cmd=cmd, hidden=True, dialog=None)
-        GUI(parent=self, giface=None, modal=self._modal).ParseCommand(cmd=cmd,
-                                                   completed=(self.GetOptData, layer, ''))
+        GUI(parent=self, giface=None, modal=self._modal).ParseCommand(
+            cmd=cmd, completed=(self.GetOptData, layer, ''))
         event.Skip()
 
     def OnAddRast3d(self, event):
@@ -192,8 +203,8 @@ class SimpleLayerManager(wx.Panel):
         Dummy layer is added first."""
         cmd = ['d.rast3d']
         layer = self.AddRast3d(name='', cmd=cmd, hidden=True, dialog=None)
-        GUI(parent=self, giface=None, modal=self._modal).ParseCommand(cmd=cmd,
-                                                   completed=(self.GetOptData, layer, ''))
+        GUI(parent=self, giface=None, modal=self._modal).ParseCommand(
+            cmd=cmd, completed=(self.GetOptData, layer, ''))
         event.Skip()
 
     def OnAddRGB(self, event):
@@ -201,15 +212,16 @@ class SimpleLayerManager(wx.Panel):
         Dummy layer is added first."""
         cmd = ['d.rgb']
         layer = self.AddRGB(name='', cmd=cmd, hidden=True, dialog=None)
-        GUI(parent=self, giface=None, modal=self._modal).ParseCommand(cmd=cmd,
-                                                    completed=(self.GetOptData, layer, ''))
+        GUI(parent=self, giface=None, modal=self._modal).ParseCommand(
+            cmd=cmd, completed=(self.GetOptData, layer, ''))
         event.Skip()
 
     def OnRemove(self, event):
         """Removes selected layers from list."""
         layers = self._layerList.GetSelectedLayers(activeOnly=False)
         for layer in layers:
-            self.layerRemoved.emit(index=self._layerList.GetLayerIndex(layer), layer=layer)
+            self.layerRemoved.emit(
+                index=self._layerList.GetLayerIndex(layer), layer=layer)
             self._layerList.RemoveLayer(layer)
         self._update()
         self.anyChange.emit()
@@ -240,7 +252,8 @@ class SimpleLayerManager(wx.Panel):
         for layer in layers:
             idx = self._layerList.GetLayerIndex(layer)
             if idx < len(self._layerList) - 1:
-                self.layerMovedDown.emit(index=self._layerList.GetLayerIndex(layer), layer=layer)
+                self.layerMovedDown.emit(
+                    index=self._layerList.GetLayerIndex(layer), layer=layer)
                 self._layerList.MoveLayerDown(layer)
         self._update()
         self._blockSelectionChanged = False
@@ -257,9 +270,8 @@ class SimpleLayerManager(wx.Panel):
 
     def _layerChangeProperties(self, layer):
         """Opens new module dialog or recycles it."""
-        GUI(parent=self, giface=None,
-            modal=self._modal).ParseCommand(cmd=layer.cmd,
-                                            completed=(self.GetOptData, layer, ''))
+        GUI(parent=self, giface=None, modal=self._modal).ParseCommand(
+            cmd=layer.cmd, completed=(self.GetOptData, layer, ''))
 
     def OnLayerChangeOpacity(self, event):
         """Opacity of a layer is changing."""
@@ -280,9 +292,11 @@ class SimpleLayerManager(wx.Panel):
 
     def _setLayerOpacity(self, layer, value):
         """Sets layer's opacity.'"""
-        layer.opacity = value 
+        layer.opacity = value
         self._update()
-        self.opacityChanged.emit(index=self._layerList.GetLayerIndex(layer), layer=layer)
+        self.opacityChanged.emit(
+            index=self._layerList.GetLayerIndex(layer),
+            layer=layer)
         self.anyChange.emit()
 
     def _update(self):
@@ -298,8 +312,10 @@ class SimpleLayerManager(wx.Panel):
 
         for layer in self._layerList:
             if layer.opacity < 1:
-                items.append("{name} (opacity {opacity}%)".format(name=layer.name,
-                                                                  opacity=int(layer.opacity * 100)))
+                items.append(
+                    "{name} (opacity {opacity}%)".format(
+                        name=layer.name, opacity=int(
+                            layer.opacity * 100)))
             else:
                 items.append(layer.name)
             active.append(layer.IsActive())
@@ -330,7 +346,9 @@ class SimpleLayerManager(wx.Panel):
                         signal = self.cmdChanged
 
                     layer.name = mapName
-                    signal.emit(index=self._layerList.GetLayerIndex(layer), layer=layer)
+                    signal.emit(
+                        index=self._layerList.GetLayerIndex(layer),
+                        layer=layer)
                 except ValueError as e:
                     self._layerList.RemoveLayer(layer)
                     GError(parent=self,
@@ -388,6 +406,7 @@ class SimpleLmgrToolbar(BaseToolbar):
     Style of the toolbar can be changed (horizontal,
     vertical, which map types to include).
     """
+
     def __init__(self, parent, lmgrStyle):
         """Toolbar constructor
         """
@@ -407,17 +426,17 @@ class SimpleLmgrToolbar(BaseToolbar):
         """Toolbar data"""
         data = [('edit', icons['edit'],
                  self.parent.OnLayerChangeProperties),
-                 ('remove', icons['remove'],
+                ('remove', icons['remove'],
                  self.parent.OnRemove),
-                 (None, ),
-                 ('up', icons['up'],
+                (None, ),
+                ('up', icons['up'],
                  self.parent.OnLayerUp),
-                 ('down', icons['down'],
+                ('down', icons['down'],
                  self.parent.OnLayerDown),
-                 (None, ),
-                 ('opacity', icons['opacity'],
+                (None, ),
+                ('opacity', icons['opacity'],
                  self.parent.OnLayerChangeOpacity),
-                 ]
+                ]
         if self._style & SIMPLE_LMGR_RASTER3D:
             data.insert(0, ('addRaster3d', icons['addRast3d'],
                             self.parent.OnAddRast3d))
@@ -454,10 +473,11 @@ icons = {
                           label=_("Add 3D raster map layer"),
                           desc=_("Add 3D raster map layer")),
     'addRGB': MetaIcon(img='layer-rgb-add', label=_('Add RGB map layer'))
-    }
+}
 
 
 class TestFrame(wx.Frame):
+
     def __init__(self, parent):
         wx.Frame.__init__(self, parent=parent)
         SimpleLayerManager(parent=self, layerList=LayerList())

+ 107 - 101
gui/wxpython/gui_core/toolbars.py

@@ -32,64 +32,65 @@ from grass.pydispatch.signal import Signal
 
 
 BaseIcons = {
-    'display'    : MetaIcon(img = 'show',
-                            label = _('Display map'),
-                            desc  =  _('Re-render modified map layers only')),
-    'render'     : MetaIcon(img = 'layer-redraw',
-                            label = _('Render map'),
-                            desc = _('Force re-rendering all map layers')),
-    'erase'      : MetaIcon(img = 'erase',
-                            label = _('Erase display'),
-                            desc = _('Erase display canvas with given background color')),
-    'pointer'    : MetaIcon(img = 'pointer',
-                            label = _('Pointer')),
-    'zoomIn'     : MetaIcon(img = 'zoom-in',
-                            label = _('Zoom in'),
-                            desc = _('Drag or click mouse to zoom')),
-    'zoomOut'    : MetaIcon(img = 'zoom-out',
-                            label = _('Zoom out'),
-                            desc = _('Drag or click mouse to unzoom')),
-    'zoomBack'   : MetaIcon(img = 'zoom-last',
-                            label = _('Return to previous zoom')),
-    'zoomMenu'   : MetaIcon(img = 'zoom-more',
-                            label = _('Various zoom options'),
-                            desc = _('Zoom to default or saved region, save to named region, ...')),
-    'zoomExtent' : MetaIcon(img = 'zoom-extent',
-                            label = _('Zoom to selected map layer(s)')),
-    'zoomRegion' : MetaIcon(img = 'zoom-region',
-                            label = _('Zoom to computational region extent')),
-    'pan'        : MetaIcon(img = 'pan',
-                            label = _('Pan'),
-                            desc = _('Drag with mouse to pan')),
-    'saveFile'   : MetaIcon(img = 'map-export',
-                            label = _('Save display to file')),
-    'print'      : MetaIcon(img = 'print',
-                            label = _('Print display')),
-    'font'       : MetaIcon(img = 'font',
-                            label = _('Select font')),
-    'help'       : MetaIcon(img = 'help',
-                            label = _('Show manual')),
-    'quit'       : MetaIcon(img = 'quit',
-                            label = _('Quit')),
-    'addRast'    : MetaIcon(img = 'layer-raster-add',
-                            label = _('Add raster map layer')),
-    'addVect'    : MetaIcon(img = 'layer-vector-add',
-                            label = _('Add vector map layer')),
-    'overlay'    : MetaIcon(img = 'overlay-add',
-                            label = _('Add map elements'),
-                            desc = _('Overlay elements like scale and legend onto map')),
-    'histogramD' : MetaIcon(img = 'layer-raster-histogram',
-                            label = _('Create histogram with d.histogram')),
-    'settings'   : MetaIcon(img = 'settings',
-                            label = _("Settings")),
-    }
-    
+    'display': MetaIcon(img='show',
+                        label=_('Display map'),
+                        desc=_('Re-render modified map layers only')),
+    'render': MetaIcon(img='layer-redraw',
+                       label=_('Render map'),
+                       desc=_('Force re-rendering all map layers')),
+    'erase': MetaIcon(img='erase',
+                      label=_('Erase display'),
+                      desc=_('Erase display canvas with given background color')),
+    'pointer': MetaIcon(img='pointer',
+                        label=_('Pointer')),
+    'zoomIn': MetaIcon(img='zoom-in',
+                       label=_('Zoom in'),
+                       desc=_('Drag or click mouse to zoom')),
+    'zoomOut': MetaIcon(img='zoom-out',
+                        label=_('Zoom out'),
+                        desc=_('Drag or click mouse to unzoom')),
+    'zoomBack': MetaIcon(img='zoom-last',
+                         label=_('Return to previous zoom')),
+    'zoomMenu': MetaIcon(img='zoom-more',
+                         label=_('Various zoom options'),
+                         desc=_('Zoom to default or saved region, save to named region, ...')),
+    'zoomExtent': MetaIcon(img='zoom-extent',
+                           label=_('Zoom to selected map layer(s)')),
+    'zoomRegion': MetaIcon(img='zoom-region',
+                           label=_('Zoom to computational region extent')),
+    'pan': MetaIcon(img='pan',
+                    label=_('Pan'),
+                    desc=_('Drag with mouse to pan')),
+    'saveFile': MetaIcon(img='map-export',
+                         label=_('Save display to file')),
+    'print': MetaIcon(img='print',
+                      label=_('Print display')),
+    'font': MetaIcon(img='font',
+                     label=_('Select font')),
+    'help': MetaIcon(img='help',
+                     label=_('Show manual')),
+    'quit': MetaIcon(img='quit',
+                     label=_('Quit')),
+    'addRast': MetaIcon(img='layer-raster-add',
+                        label=_('Add raster map layer')),
+    'addVect': MetaIcon(img='layer-vector-add',
+                        label=_('Add vector map layer')),
+    'overlay': MetaIcon(img='overlay-add',
+                        label=_('Add map elements'),
+                        desc=_('Overlay elements like scale and legend onto map')),
+    'histogramD': MetaIcon(img='layer-raster-histogram',
+                           label=_('Create histogram with d.histogram')),
+    'settings': MetaIcon(img='settings',
+                         label=_("Settings")),
+}
+
+
 class BaseToolbar(wx.ToolBar):
     """Abstract toolbar class.
-    
+
     Following code shows how to create new basic toolbar:
 
-    
+
         class MyToolbar(BaseToolbar):
             def __init__(self, parent):
                 BaseToolbar.__init__(self, parent)
@@ -100,36 +101,37 @@ class BaseToolbar(wx.ToolBar):
                 return self._getToolbarData((("help", Icons["help"],
                                               self.parent.OnHelp),
                                               ))
-    
+
     """
-    def __init__(self, parent, toolSwitcher=None, style=wx.NO_BORDER|wx.TB_HORIZONTAL):
+
+    def __init__(self, parent, toolSwitcher=None,
+                 style=wx.NO_BORDER | wx.TB_HORIZONTAL):
         self.parent = parent
         wx.ToolBar.__init__(self, parent=self.parent, id=wx.ID_ANY,
                             style=style)
-        
 
         self._default = None
         self.SetToolBitmapSize(globalvar.toolbarSize)
-        
+
         self.toolSwitcher = toolSwitcher
         self.handlers = {}
-        
+
     def InitToolbar(self, toolData):
         """Initialize toolbar, add tools to the toolbar
         """
         for tool in toolData:
             self.CreateTool(*tool)
-        
+
         self._data = toolData
-        
+
     def _toolbarData(self):
         """Toolbar data (virtual)"""
         return None
-    
+
     def CreateTool(self, label, bitmap, kind,
-                   shortHelp, longHelp, handler, pos = -1):
+                   shortHelp, longHelp, handler, pos=-1):
         """Add tool to the toolbar
-        
+
         :param pos: if -1 add tool, if > 0 insert at given pos
         :return: id of tool
         """
@@ -137,38 +139,38 @@ class BaseToolbar(wx.ToolBar):
         tool = -1
         if label:
             tool = vars(self)[label] = wx.NewId()
-            Debug.msg(3, "CreateTool(): tool=%d, label=%s bitmap=%s" % \
-                          (tool, label, bitmap))
+            Debug.msg(3, "CreateTool(): tool=%d, label=%s bitmap=%s" %
+                      (tool, label, bitmap))
             if pos < 0:
                 toolWin = self.AddLabelTool(tool, label, bitmap,
                                             bmpDisabled, kind,
                                             shortHelp, longHelp)
             else:
                 toolWin = self.InsertLabelTool(pos, tool, label, bitmap,
-                                            bmpDisabled, kind,
-                                            shortHelp, longHelp)
+                                               bmpDisabled, kind,
+                                               shortHelp, longHelp)
             self.handlers[tool] = handler
             self.Bind(wx.EVT_TOOL, handler, toolWin)
             self.Bind(wx.EVT_TOOL, self.OnTool, toolWin)
-        else: # separator
+        else:  # separator
             self.AddSeparator()
 
         return tool
 
-    def EnableLongHelp(self, enable = True):
+    def EnableLongHelp(self, enable=True):
         """Enable/disable long help
-        
+
         :param enable: True for enable otherwise disable
         """
         for tool in self._data:
-            if tool[0] == '': # separator
+            if tool[0] == '':  # separator
                 continue
 
             if enable:
                 self.SetToolLongHelp(vars(self)[tool[0]], tool[4])
             else:
                 self.SetToolLongHelp(vars(self)[tool[0]], "")
-        
+
     def OnTool(self, event):
         """Tool selected
         """
@@ -180,16 +182,16 @@ class BaseToolbar(wx.ToolBar):
     def SelectTool(self, id):
         self.ToggleTool(id, True)
         self.toolSwitcher.ToolChanged(id)
-        
+
         self.handlers[id](event=None)
 
     def SelectDefault(self):
         """Select default tool"""
         self.SelectTool(self._default)
-        
+
     def FixSize(self, width):
         """Fix toolbar width on Windows
-            
+
         .. todo::
             Determine why combobox causes problems here
         """
@@ -197,9 +199,9 @@ class BaseToolbar(wx.ToolBar):
             size = self.GetBestSize()
             self.SetSize((size[0] + width, size[1]))
 
-    def Enable(self, tool, enable = True):
+    def Enable(self, tool, enable=True):
         """Enable/Disable defined tool
-        
+
         :param tool: name
         :param enable: True to enable otherwise disable tool
         """
@@ -210,19 +212,19 @@ class BaseToolbar(wx.ToolBar):
             # this error was ignored for a long time
             raise AttributeError("Toolbar does not have a tool %s." % tool)
             return
-        
+
         self.EnableTool(id, enable)
 
-    def EnableAll(self, enable = True):
+    def EnableAll(self, enable=True):
         """Enable/Disable all tools
-        
+
         :param enable: True to enable otherwise disable tool
         """
         for item in self._toolbarData():
             if not item[0]:
                 continue
             self.Enable(item[0], enable)
-        
+
     def _getToolbarData(self, data):
         """Define tool
         """
@@ -231,73 +233,77 @@ class BaseToolbar(wx.ToolBar):
             retData.append(self._defineTool(*args))
         return retData
 
-    def _defineTool(self, name = None, icon = None, handler = None, item = wx.ITEM_NORMAL, pos = -1):
+    def _defineTool(self, name=None, icon=None, handler=None,
+                    item=wx.ITEM_NORMAL, pos=-1):
         """Define tool
         """
         if name:
             return (name, icon.GetBitmap(),
                     item, icon.GetLabel(), icon.GetDesc(),
                     handler, pos)
-        return ("", "", "", "", "", "") # separator
+        return ("", "", "", "", "", "")  # separator
 
     def _onMenu(self, data):
         """Toolbar pop-up menu"""
         menu = wx.Menu()
-        
+
         for icon, handler in data:
             item = wx.MenuItem(menu, wx.ID_ANY, icon.GetLabel())
             item.SetBitmap(icon.GetBitmap(self.parent.iconsize))
             menu.AppendItem(item)
             self.Bind(wx.EVT_MENU, handler, item)
-        
+
         self.PopupMenu(menu)
         menu.Destroy()
 
-    def CreateSelectionButton(self, tooltip = _("Select graphics tool")):
+    def CreateSelectionButton(self, tooltip=_("Select graphics tool")):
         """Add button to toolbar for selection of graphics drawing mode.
 
         Button must be custom (not toolbar tool) to set smaller width.
         """
         arrowPath = os.path.join(IMGDIR, 'small_down_arrow.png')
         if os.path.isfile(arrowPath) and os.path.getsize(arrowPath):
-            bitmap = wx.Bitmap(name = arrowPath)
+            bitmap = wx.Bitmap(name=arrowPath)
         else:
-            bitmap = wx.ArtProvider.GetBitmap(id = wx.ART_MISSING_IMAGE, client = wx.ART_TOOLBAR)
-        button =  wx.BitmapButton(parent=self, id=wx.ID_ANY, size=((-1, self.GetToolSize()[1])),
-                                  bitmap=bitmap, style=wx.NO_BORDER)
+            bitmap = wx.ArtProvider.GetBitmap(
+                id=wx.ART_MISSING_IMAGE, client=wx.ART_TOOLBAR)
+        button = wx.BitmapButton(parent=self, id=wx.ID_ANY, size=(
+            (-1, self.GetToolSize()[1])), bitmap=bitmap, style=wx.NO_BORDER)
         button.SetToolTipString(tooltip)
 
         return button
 
+
 class ToolSwitcher:
     """Class handling switching tools in toolbar and custom toggle buttons."""
+
     def __init__(self):
         self._groups = defaultdict(lambda: defaultdict(list))
         self._toolsGroups = defaultdict(list)
-        
+
         # emitted when tool is changed
         self.toggleToolChanged = Signal('ToolSwitcher.toggleToolChanged')
 
     def AddToolToGroup(self, group, toolbar, tool):
         """Adds tool from toolbar to group of exclusive tools.
-        
+
         :param group: name of group (e.g. 'mouseUse')
         :param toolbar: instance of toolbar
         :param tool: id of a tool from the toolbar
         """
         self._groups[group][toolbar].append(tool)
         self._toolsGroups[tool].append(group)
-        
+
     def AddCustomToolToGroup(self, group, btnId, toggleHandler):
         """Adds custom tool from to group of exclusive tools (some toggle button).
-        
+
         :param group: name of group (e.g. 'mouseUse')
         :param btnId: id of a tool (typically button)
         :param toggleHandler: handler to be called to switch the button
         """
         self._groups[group]['custom'].append((btnId, toggleHandler))
         self._toolsGroups[btnId].append(group)
-       
+
     def RemoveCustomToolFromGroup(self, tool):
         """Removes custom tool from group.
 
@@ -308,14 +314,14 @@ class ToolSwitcher:
         for group in self._toolsGroups[tool]:
             self._groups[group]['custom'] = \
                 [(bid, hdlr) for (bid, hdlr)
-                in self._groups[group]['custom'] if bid != tool]
-        
+                 in self._groups[group]['custom'] if bid != tool]
+
     def RemoveToolbarFromGroup(self, group, toolbar):
         """Removes toolbar from group.
-        
+
         Before toolbar is destroyed, it must be removed from group, too.
         Otherwise we can expect some DeadObject errors.
-        
+
         :param group: name of group (e.g. 'mouseUse')
         :param toolbar: instance of toolbar
         """
@@ -342,7 +348,7 @@ class ToolSwitcher:
 
     def ToolChanged(self, tool):
         """When any tool/button is pressed, other tools from group must be unchecked.
-        
+
         :param tool: id of a tool/button
         """
         for group in self._toolsGroups[tool]:

+ 31 - 18
gui/wxpython/gui_core/treeview.py

@@ -42,6 +42,7 @@ class AbstractTreeViewMixin(VirtualTree):
         itemActivated - attribute 'node'
         contextMenu - attribute 'node'
     """
+
     def __init__(self, model, parent, *args, **kw):
         self._model = model
         super(AbstractTreeViewMixin, self).__init__(parent=parent, *args, **kw)
@@ -51,16 +52,16 @@ class AbstractTreeViewMixin(VirtualTree):
         self.contextMenu = Signal('TreeView.contextMenu')
 
         self.Bind(wx.EVT_TREE_SEL_CHANGED, lambda evt:
-                                           self._emitSignal(evt.GetItem(), self.selectionChanged))
+                  self._emitSignal(evt.GetItem(), self.selectionChanged))
         self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, lambda evt:
-                                           self._emitSignal(evt.GetItem(), self.itemActivated))
+                  self._emitSignal(evt.GetItem(), self.itemActivated))
         self.Bind(wx.EVT_TREE_ITEM_MENU, lambda evt:
-                                           self._emitSignal(evt.GetItem(), self.contextMenu))
+                  self._emitSignal(evt.GetItem(), self.contextMenu))
 
     def SetModel(self, model):
         """Set tree model and refresh.
-        
-        :param model: tree model        
+
+        :param model: tree model
         """
         self._model = model
         self.RefreshItems()
@@ -127,7 +128,7 @@ class AbstractTreeViewMixin(VirtualTree):
         item = self.GetItemByIndex(index)
 
         return self.IsExpanded(item)
-    
+
     def CollapseNode(self, node, recursive=True):
         """Collapse items.
 
@@ -163,26 +164,31 @@ class AbstractTreeViewMixin(VirtualTree):
 
 class TreeView(AbstractTreeViewMixin, wx.TreeCtrl):
     """Tree view class inheriting from wx.TreeCtrl"""
+
     def __init__(self, model, parent, *args, **kw):
         super(TreeView, self).__init__(parent=parent, model=model, *args, **kw)
         self.RefreshItems()
 
+
 class CTreeView(AbstractTreeViewMixin, CT.CustomTreeCtrl):
     """Tree view class inheriting from wx.TreeCtrl"""
+
     def __init__(self, model, parent, **kw):
         if hasAgw:
             style = 'agwStyle'
         else:
             style = 'style'
-        
+
         if style not in kw:
             kw[style] = CT.TR_HIDE_ROOT | CT.TR_FULL_ROW_HIGHLIGHT |\
                 CT.TR_HAS_BUTTONS | CT.TR_LINES_AT_ROOT | CT.TR_SINGLE
         super(CTreeView, self).__init__(parent=parent, model=model, **kw)
         self.SetBackgroundColour("white")
         self.RefreshItems()
-        
+
+
 class TreeListView(AbstractTreeViewMixin, ExpansionState, gizmos.TreeListCtrl):
+
     def __init__(self, model, parent, columns, **kw):
         self._columns = columns
         super(TreeListView, self).__init__(parent=parent, model=model, **kw)
@@ -191,8 +197,8 @@ class TreeListView(AbstractTreeViewMixin, ExpansionState, gizmos.TreeListCtrl):
         self.SetMainColumn(0)
         self.RefreshItems()
         # to solve events inconsitency
-        self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK,  lambda evt:
-                                           self._emitSignal(evt.GetItem(), self.contextMenu))
+        self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, lambda evt:
+                  self._emitSignal(evt.GetItem(), self.contextMenu))
         self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnRightClick)
 
     def OnGetItemText(self, index, column=0):
@@ -211,16 +217,18 @@ class TreeListView(AbstractTreeViewMixin, ExpansionState, gizmos.TreeListCtrl):
 
     def OnRightClick(self, event):
         """Select item on right click.
-        
-        With multiple selection we don't want to deselect all items        
+
+        With multiple selection we don't want to deselect all items
         """
         item = event.GetItem()
         if not self.IsSelected(item):
             self.SelectItem(item)
         event.Skip()
 
+
 class TreeFrame(wx.Frame):
     """Frame for testing purposes only."""
+
     def __init__(self, model=None):
         wx.Frame.__init__(self, None, title='Test tree')
 
@@ -240,7 +248,7 @@ class TreeFrame(wx.Frame):
     def OnSelChanged(self):
         print 'selected items: ' + \
               str([node.label for node in self.tree.GetSelected()])
-        
+
     def OnItemActivated(self, node):
         print 'activated: ' + node.label
 
@@ -250,12 +258,17 @@ def main():
     root = tree.root
     n1 = tree.AppendNode(parent=root, label='node1')
     n2 = tree.AppendNode(parent=root, label='node2')
-    n3 = tree.AppendNode(parent=root, label='node3') # pylint: disable=W0612
+    n3 = tree.AppendNode(parent=root, label='node3')  # pylint: disable=W0612
     n11 = tree.AppendNode(parent=n1, label='node11', data={'xxx': 'A'})
-    n12 = tree.AppendNode(parent=n1, label='node12', data={'xxx': 'B'}) # pylint: disable=W0612
-    n21 = tree.AppendNode(parent=n2, label='node21', data={'xxx': 'A'}) # pylint: disable=W0612
-    n111 = tree.AppendNode(parent=n11, label='node111', data={'xxx': 'A'}) # pylint: disable=W0612
-
+    n12 = tree.AppendNode(
+        parent=n1, label='node12', data={
+            'xxx': 'B'})  # pylint: disable=W0612
+    n21 = tree.AppendNode(
+        parent=n2, label='node21', data={
+            'xxx': 'A'})  # pylint: disable=W0612
+    n111 = tree.AppendNode(
+        parent=n11, label='node111', data={
+            'xxx': 'A'})  # pylint: disable=W0612
 
     app = wx.App()
     frame = TreeFrame(model=tree)

+ 67 - 45
gui/wxpython/gui_core/vselect.py

@@ -32,13 +32,19 @@ from core.gcmd import RunCommand
 import grass.script as grass
 from grass.pydispatch.signal import Signal
 
+
 class VectorSelectList(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
     """Widget for managing vector features selected from map display
     """
+
     def __init__(self, parent):
-        wx.ListCtrl.__init__(self, parent=parent, id=wx.ID_ANY, style=wx.LC_REPORT | wx.BORDER_SUNKEN)
+        wx.ListCtrl.__init__(
+            self,
+            parent=parent,
+            id=wx.ID_ANY,
+            style=wx.LC_REPORT | wx.BORDER_SUNKEN)
         listmix.ListCtrlAutoWidthMixin.__init__(self)
-        
+
         self.InsertColumn(col=0, heading=_('category'))
         self.InsertColumn(col=1, heading=_('type'))
         self.SetColumnWidth(0, 100)
@@ -50,7 +56,7 @@ class VectorSelectList(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
     def AddItem(self, item):
         if 'Category' not in item:
             return
-        
+
         pos = self.InsertStringItem(0, str(item['Category']))
         self.SetStringItem(pos, 1, str(item['Type']))
         self.dictIndex[str(item['Category'])] = pos
@@ -59,12 +65,19 @@ class VectorSelectList(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
         index = self.dictIndex.get(str(item['Category']), -1)
         if index > -1:
             self.DeleteItem(index)
-        
+
+
 class VectorSelectDialog(wx.Dialog):
     """Dialog for managing vector features selected from map display"""
+
     def __init__(self, parent, title=_("Select features"), size=(200, 300)):
-        wx.Dialog.__init__(self, parent=parent, id=wx.ID_ANY,
-                           title=title, size=size, style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
+        wx.Dialog.__init__(
+            self,
+            parent=parent,
+            id=wx.ID_ANY,
+            title=title,
+            size=size,
+            style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
 
         self._layout()
 
@@ -78,6 +91,7 @@ class VectorSelectDialog(wx.Dialog):
 
         self.Show()
 
+
 class VectorSelectBase():
     """@brief Main class of vector selection function
 
@@ -88,6 +102,7 @@ class VectorSelectBase():
     This class can be initialized with (see CreateDialog()) or without
     (see gselect) dialog (see VectorSelectDialog).
     """
+
     def __init__(self, parent, giface):
         self.parent = parent
         self._giface = giface
@@ -97,13 +112,13 @@ class VectorSelectBase():
         self.RegisterMapEvtHandler()
 
         self.selectedFeatures = []
-        self.mapName = None # chosen map for selecting features
+        self.mapName = None  # chosen map for selecting features
 
         self._dialog = None
         self.onCloseDialog = None
-        
+
         self.updateLayer = Signal('VectorSelectBase.updateLayer')
-        
+
         self.painter = VectorSelectHighlighter(self.mapDisp, giface)
 
     def CreateDialog(self, createButton=True):
@@ -113,20 +128,21 @@ class VectorSelectBase():
         """
         if self._dialog:
             return
-        
+
         self._dialog = VectorSelectDialog(parent=self.parent)
-        self._dialog.Bind(wx.EVT_CLOSE,self.OnCloseDialog)
+        self._dialog.Bind(wx.EVT_CLOSE, self.OnCloseDialog)
         if createButton:
-            createMap = wx.Button(self._dialog, wx.ID_ANY, _("Create a new map"))
+            createMap = wx.Button(
+                self._dialog, wx.ID_ANY, _("Create a new map"))
             createMap.Bind(wx.EVT_BUTTON, self.OnExportMap)
             self._dialog.AddWidget(createMap, proportion=0.1)
         self.slist = VectorSelectList(self._dialog)
         self.slist.Bind(wx.EVT_LIST_KEY_DOWN, self.OnDelete)
         self.slist.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnDeleteRow)
         self._dialog.AddWidget(self.slist)
-        
+
         self.onCloseDialog = Signal('VectorSelectBase.onCloseDialog')
-        
+
     def OnDeleteRow(self, event=None):
         """Delete row in widget
         """
@@ -151,26 +167,26 @@ class VectorSelectBase():
             self.mapWin.RegisterMouseEventHandler(wx.EVT_LEFT_DOWN,
                                                   self._onMapClickHandler,
                                                   'cross')
-        self.register=True
+        self.register = True
 
     def UnregisterMapEvtHandler(self):
         """Unregistrates _onMapClickHandler from mapWin"""
         if self.register:
             self.mapWin.UnregisterMouseEventHandler(wx.EVT_LEFT_DOWN,
                                                     self._onMapClickHandler)
-        self.register=False
+        self.register = False
 
     def OnClose(self):
-        self.selectedFeatures=[]
+        self.selectedFeatures = []
         self._draw()
         self.UnregisterMapEvtHandler()
 
-    def OnCloseDialog(self,evt=None):
+    def OnCloseDialog(self, evt=None):
         if not self.onCloseDialog:
             return
-        
+
         self.onCloseDialog.emit()
-        self.selectedFeatures=[]
+        self.selectedFeatures = []
         self.painter.Clear()
         self._dialog.Destroy()
         self.UnregisterMapEvtHandler()
@@ -197,22 +213,23 @@ class VectorSelectBase():
 
     def AddVecInfo(self, vInfoDictTMP):
         """Update vector in list
-        
+
         Note: click on features add category
               second click on the same vector remove category from list
         """
         if len(self.selectedFeatures) > 0:
             for sel in self.selectedFeatures:
-                if sel['Category'] == vInfoDictTMP['Category']: #features is selected=> remove features
+                if sel['Category'] == vInfoDictTMP[
+                        'Category']:  # features is selected=> remove features
                     self.selectedFeatures.remove(sel)
-                    if self._dialog:#if dialog initilized->update dialog
+                    if self._dialog:  # if dialog initilized->update dialog
                         self.slist.RemoveItem(vInfoDictTMP)
                     return True
 
             self.selectedFeatures.append(vInfoDictTMP)
             if self._dialog:
                 self.slist.AddItem(vInfoDictTMP)
-        else: # only one is selected
+        else:  # only one is selected
             self.selectedFeatures.append(vInfoDictTMP)
             if self._dialog:
                 self.slist.AddItem(vInfoDictTMP)
@@ -252,7 +269,7 @@ class VectorSelectBase():
         if layerSelected:
             mapName = str(layerSelected)
             if self.mapName is not None:
-                if self.mapName!=mapName:
+                if self.mapName != mapName:
                     self.Reset()
         else:
             mapName = None
@@ -269,7 +286,8 @@ class VectorSelectBase():
             return {}
 
         mapInfo = self.mapWin.GetMap()
-        threshold = 10.0 * ((mapInfo.region['e'] - mapInfo.region['w']) / mapInfo.width)
+        threshold = 10.0 * (
+            (mapInfo.region['e'] - mapInfo.region['w']) / mapInfo.width)
         try:
             query = grass.vector_what(map=[self.mapName],
                                       coord=self.mapWin.GetLastEN(),
@@ -288,25 +306,27 @@ class VectorSelectBase():
             strTMP += str(cat['Category']) + ','
         return strTMP[:-1]
 
-    def _id_generator(self, size=6, chars=string.ascii_uppercase + string.digits):
+    def _id_generator(self, size=6,
+                      chars=string.ascii_uppercase + string.digits):
         return ''.join(random.choice(chars) for _ in range(size))
 
     def OnExportMap(self, event):
         """Export selected features to a new map
-        
+
         Add new map layer to layer tree and checked it
 
         @todo: set color of map to higlight color
         """
 
-        if len(self.selectedFeatures)==0:
+        if len(self.selectedFeatures) == 0:
             GMessage(_('No features selected'))
             return
         lst = ''
-        for cat in self.selectedFeatures: # build text string of categories for v.extract input
+        for cat in self.selectedFeatures:  # build text string of categories for v.extract input
             lst += str(cat['Category']) + ','
         lst = lst[:-1]
-        outMap = str(self.selectedFeatures[0]['Map']) + '_selection' + str(self._id_generator(3))
+        outMap = str(self.selectedFeatures[0][
+                     'Map']) + '_selection' + str(self._id_generator(3))
         ret, err = RunCommand('v.extract',
                               input=self.selectedFeatures[0]['Map'],
                               layer=self.selectedFeatures[0]['Layer'],
@@ -320,14 +340,14 @@ class VectorSelectBase():
                               lcmd=['d.vect', 'map=%s' % outMap],
                               lchecked=True)
 
-                #TODO colorize new map
+                # TODO colorize new map
                 self.Reset()
             else:
                 GMessage(_('Vector map <%s> was created') % outMap)
                 self.Reset()
         else:
             GError(_("Unable to create a new vector map.\n\nReason: %s") % err)
-        
+
     """
     def SetSelectedCat(self, cats):
         # allows setting selected vector categories by list of cats (per line)
@@ -345,12 +365,14 @@ class VectorSelectBase():
 
         self._draw()
     """
-    
+
+
 class VectorSelectHighlighter():
     """Class for highlighting selected features on display
 
     :param mapdisp: Map display frame
     """
+
     def __init__(self, mapdisp, giface):
         self.qlayer = None
         self.mapdisp = mapdisp
@@ -359,7 +381,7 @@ class VectorSelectHighlighter():
         self.data = {}
         self.data['Category'] = list()
         self.data['Map'] = None
-        self.data['Layer']= None
+        self.data['Layer'] = None
 
     def SetMap(self, map):
         self.data['Map'] = map
@@ -373,14 +395,14 @@ class VectorSelectHighlighter():
     def Clear(self):
         self.data['Category'] = list()
         self.data['Map'] = None
-        self.data['Layer']= None
+        self.data['Layer'] = None
         self.mapdisp.RemoveQueryLayer()
-        self.giface.GetMapWindow().UpdateMap(render = False)
+        self.giface.GetMapWindow().UpdateMap(render=False)
 
     def DrawSelected(self):
         """Highlight selected features"""
         self.layerCat[int(self.data['Layer'])] = self.data['Category']
-        
+
         # add map layer with higlighted vector features
         self.AddQueryMapLayer()  # -> self.qlayer
         self.qlayer.SetOpacity(0.7)
@@ -395,13 +417,13 @@ class VectorSelectHighlighter():
             self.qlayer = None
 
         if self.qlayer:
-            self.qlayer.SetCmd(self.mapdisp.AddTmpVectorMapLayer(self.data['Map'], self.layerCat, addLayer=False))
+            self.qlayer.SetCmd(
+                self.mapdisp.AddTmpVectorMapLayer(
+                    self.data['Map'],
+                    self.layerCat,
+                    addLayer=False))
         else:
-            self.qlayer = self.mapdisp.AddTmpVectorMapLayer(self.data['Map'], self.layerCat)
+            self.qlayer = self.mapdisp.AddTmpVectorMapLayer(
+                self.data['Map'], self.layerCat)
 
         return self.qlayer
-
-
-
-
-

+ 202 - 107
gui/wxpython/gui_core/widgets.py

@@ -58,12 +58,12 @@ from wx.lib.stattext import GenStaticText
 from wx.lib.wordwrap import wordwrap
 import wx.combo
 try:
-    import wx.lib.agw.flatnotebook   as FN
+    import wx.lib.agw.flatnotebook as FN
 except ImportError:
-    import wx.lib.flatnotebook   as FN
+    import wx.lib.flatnotebook as FN
 try:
     from wx.lib.buttons import ThemedGenBitmapTextButton as BitmapTextButton
-except ImportError: # not sure about TGBTButton version
+except ImportError:  # not sure about TGBTButton version
     from wx.lib.buttons import GenBitmapTextButton as BitmapTextButton
 try:
     import wx.lib.agw.customtreectrl as CT
@@ -74,10 +74,10 @@ from grass.script import core as grass
 
 from grass.pydispatch.signal import Signal
 
-from core        import globalvar
+from core import globalvar
 from core.utils import _
-from core.gcmd   import GMessage, GError
-from core.debug  import Debug
+from core.gcmd import GMessage, GError
+from core.debug import Debug
 
 
 class NotebookController:
@@ -89,6 +89,7 @@ class NotebookController:
     Methods inherited from notebook class must be delegated explicitly
     and other methods can be delegated by @c __getattr__.
     """
+
     def __init__(self, classObject, widget):
         """
         :param classObject: notebook class name (object, i.e. FlatNotebook)
@@ -121,7 +122,7 @@ class NotebookController:
             del kwargs['name']
         try:
             self.classObject.InsertPage(self.widget, **kwargs)
-        except TypeError, e:  # documentation says 'index', but certain versions of wx require 'n'
+        except TypeError as e:  # documentation says 'index', but certain versions of wx require 'n'
             kwargs['n'] = kwargs['index']
             del kwargs['index']
             self.classObject.InsertPage(self.widget, **kwargs)
@@ -192,7 +193,8 @@ class NotebookController:
         if page not in self.notebookPages:
             return -1
         for pageIndex in range(self.classObject.GetPageCount(self.widget)):
-            if self.notebookPages[page] == self.classObject.GetPage(self.widget, pageIndex):
+            if self.notebookPages[page] == self.classObject.GetPage(
+                    self.widget, pageIndex):
                 break
         return pageIndex
 
@@ -219,11 +221,14 @@ class NotebookController:
 
 class FlatNotebookController(NotebookController):
     """Controller specialized for FN.FlatNotebook subclasses"""
+
     def __init__(self, classObject, widget):
         NotebookController.__init__(self, classObject, widget)
 
     def BindPageChanged(self):
-        self.widget.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.OnRemoveHighlight)
+        self.widget.Bind(
+            FN.EVT_FLATNOTEBOOK_PAGE_CHANGED,
+            self.OnRemoveHighlight)
 
     def GetPageIndexByName(self, page):
         """Get notebook page index
@@ -233,7 +238,8 @@ class FlatNotebookController(NotebookController):
         if page not in self.notebookPages:
             return -1
 
-        return self.classObject.GetPageIndex(self.widget, self.notebookPages[page])
+        return self.classObject.GetPageIndex(
+            self.widget, self.notebookPages[page])
 
     def InsertPage(self, **kwargs):
         """Insert a new page
@@ -252,6 +258,7 @@ class GNotebook(FN.FlatNotebook):
     Enables advanced style settings.
     Problems with hidden tabs and does not respect system colors (native look).
     """
+
     def __init__(self, parent, style, **kwargs):
         if globalvar.hasAgw:
             FN.FlatNotebook.__init__(self, parent, id=wx.ID_ANY,
@@ -292,6 +299,7 @@ class FormNotebook(wx.Notebook):
 
     Respects native look.
     """
+
     def __init__(self, parent, style):
         wx.Notebook.__init__(self, parent, id=wx.ID_ANY, style=style)
         self.controller = NotebookController(classObject=wx.Notebook,
@@ -326,6 +334,7 @@ class FormListbook(wx.Listbook):
 
     Respects native look.
     """
+
     def __init__(self, parent, style):
         wx.Listbook.__init__(self, parent, id=wx.ID_ANY, style=style)
         self.controller = NotebookController(classObject=wx.Listbook,
@@ -357,6 +366,7 @@ class FormListbook(wx.Listbook):
 
 class ScrolledPanel(SP.ScrolledPanel):
     """Custom ScrolledPanel to avoid strange behaviour concerning focus"""
+
     def __init__(self, parent, style=wx.TAB_TRAVERSAL):
         SP.ScrolledPanel.__init__(self, parent=parent, id=wx.ID_ANY,
                                   style=style)
@@ -367,8 +377,9 @@ class ScrolledPanel(SP.ScrolledPanel):
 
 class NumTextCtrl(wx.TextCtrl):
     """Class derived from wx.TextCtrl for numerical values only"""
-    def __init__(self, parent,  **kwargs):
-##        self.precision = kwargs.pop('prec')
+
+    def __init__(self, parent, **kwargs):
+        ##        self.precision = kwargs.pop('prec')
         wx.TextCtrl.__init__(self, parent=parent,
                              validator=NTCValidator(flag='DIGIT_ONLY'),
                              **kwargs)
@@ -392,11 +403,12 @@ class NumTextCtrl(wx.TextCtrl):
 
 class FloatSlider(wx.Slider):
     """Class derived from wx.Slider for floats"""
+
     def __init__(self, **kwargs):
         Debug.msg(1, "FloatSlider.__init__()")
         wx.Slider.__init__(self, **kwargs)
         self.coef = 1.
-        #init range
+        # init range
         self.minValueOrig = 0
         self.maxValueOrig = 1
 
@@ -417,22 +429,32 @@ class FloatSlider(wx.Slider):
         self.minValueOrig = minValue
         self.maxValueOrig = maxValue
         if abs(minValue) < 1 or abs(maxValue) < 1:
-            while (abs(minValue) < 1 and minValue != 0) or (abs(maxValue) < 1 and maxValue != 0):
+            while (abs(minValue) < 1 and minValue != 0) or (
+                    abs(maxValue) < 1 and maxValue != 0):
                 minValue *= 100
                 maxValue *= 100
                 self.coef *= 100
-            super(FloatSlider, self).SetValue(super(FloatSlider, self).GetValue() * self.coef)
+            super(
+                FloatSlider,
+                self).SetValue(
+                super(
+                    FloatSlider,
+                    self).GetValue() *
+                self.coef)
         super(FloatSlider, self).SetRange(minValue, maxValue)
-        Debug.msg(4, "FloatSlider.SetRange(): minValue = %f, maxValue = %f" % (minValue, maxValue))
+        Debug.msg(
+            4, "FloatSlider.SetRange(): minValue = %f, maxValue = %f" %
+            (minValue, maxValue))
 
     def GetValue(self):
         val = super(FloatSlider, self).GetValue()
-        Debug.msg(4, "FloatSlider.GetValue(): value = %f" % (val/self.coef))
-        return val/self.coef
+        Debug.msg(4, "FloatSlider.GetValue(): value = %f" % (val / self.coef))
+        return val / self.coef
 
 
 class SymbolButton(BitmapTextButton):
     """Button with symbol and label."""
+
     def __init__(self, parent, usage, label, **kwargs):
         """Constructor
 
@@ -468,7 +490,7 @@ class SymbolButton(BitmapTextButton):
     def DrawRecord(self, dc, size):
         """Draw record symbol"""
         dc.SetBrush(wx.Brush(wx.Colour(255, 0, 0)))
-        dc.DrawCircle(size[0]/2, size[1] / 2, size[0] / 2)
+        dc.DrawCircle(size[0] / 2, size[1] / 2, size[0] / 2)
 
     def DrawStop(self, dc, size):
         """Draw stop symbol"""
@@ -479,7 +501,7 @@ class SymbolButton(BitmapTextButton):
         """Draw play symbol"""
         dc.SetBrush(wx.Brush(wx.Colour(0, 255, 0)))
         points = (wx.Point(0, 0), wx.Point(0, size[1]), wx.Point(size[0],
-                  size[1] / 2))
+                                                                 size[1] / 2))
         dc.DrawPolygon(points)
 
     def DrawPause(self, dc, size):
@@ -493,7 +515,8 @@ class StaticWrapText(GenStaticText):
     """A Static Text widget that wraps its text to fit parents width,
     enlarging its height if necessary."""
 
-    def __init__(self, parent, id=wx.ID_ANY, label='', margin=0, *args, **kwds):
+    def __init__(self, parent, id=wx.ID_ANY,
+                 label='', margin=0, *args, **kwds):
         self._margin = margin
         self._initialLabel = label
         self.init = False
@@ -507,7 +530,8 @@ class StaticWrapText(GenStaticText):
             self.init = True
         parent = self.GetParent()
         newExtent = wx.ClientDC(parent).GetMultiLineTextExtent(self.GetLabel())
-        # when starting, width is very small and height is big which creates very high windows
+        # when starting, width is very small and height is big which creates
+        # very high windows
         if newExtent[0] < newExtent[1]:
             return (0, 0)
         return newExtent[:2]
@@ -530,6 +554,7 @@ class StaticWrapText(GenStaticText):
 
 
 class BaseValidator(wx.PyValidator):
+
     def __init__(self):
         wx.PyValidator.__init__(self)
 
@@ -573,10 +598,10 @@ class BaseValidator(wx.PyValidator):
         return True
 
     def TransferToWindow(self):
-        return True # Prevent wxDialog from complaining.
+        return True  # Prevent wxDialog from complaining.
 
     def TransferFromWindow(self):
-        return True # Prevent wxDialog from complaining.
+        return True  # Prevent wxDialog from complaining.
 
 
 class CoordinatesValidator(BaseValidator):
@@ -614,6 +639,7 @@ class CoordinatesValidator(BaseValidator):
 
 class IntegerValidator(BaseValidator):
     """Validator for floating-point input"""
+
     def __init__(self):
         BaseValidator.__init__(self)
         self.type = int
@@ -625,6 +651,7 @@ class IntegerValidator(BaseValidator):
 
 class FloatValidator(BaseValidator):
     """Validator for floating-point input"""
+
     def __init__(self):
         BaseValidator.__init__(self)
         self.type = float
@@ -636,6 +663,7 @@ class FloatValidator(BaseValidator):
 
 class EmailValidator(BaseValidator):
     """Validator for email input"""
+
     def __init__(self):
         BaseValidator.__init__(self)
 
@@ -658,6 +686,7 @@ class EmailValidator(BaseValidator):
 
 class TimeISOValidator(BaseValidator):
     """Validator for time ISO format (YYYY-MM-DD) input"""
+
     def __init__(self):
         BaseValidator.__init__(self)
 
@@ -679,8 +708,10 @@ class TimeISOValidator(BaseValidator):
         """Clone validator"""
         return TimeISOValidator()
 
+
 class NTCValidator(wx.PyValidator):
     """validates input in textctrls, taken from wxpython demo"""
+
     def __init__(self, flag=None):
         wx.PyValidator.__init__(self)
         self.flag = flag
@@ -708,6 +739,7 @@ class SimpleValidator(wx.PyValidator):
     """This validator is used to ensure that the user has entered something
         into the text object editor dialog's text field.
     """
+
     def __init__(self, callback):
         """Standard constructor.
         """
@@ -739,7 +771,7 @@ class SimpleValidator(wx.PyValidator):
         error occurred.  We simply return True, as we don't do any data
         transfer.
         """
-        return True # Prevent wxDialog from complaining.
+        return True  # Prevent wxDialog from complaining.
 
     def TransferFromWindow(self):
         """Transfer data from window to validator.
@@ -748,13 +780,14 @@ class SimpleValidator(wx.PyValidator):
         error occurred.  We simply return True, as we don't do any data
         transfer.
         """
-        return True # Prevent wxDialog from complaining.
+        return True  # Prevent wxDialog from complaining.
 
 
 class GenericValidator(wx.PyValidator):
     """This validator checks condition and calls callback
     in case the condition is not fulfilled.
     """
+
     def __init__(self, condition, callback):
         """Standard constructor.
 
@@ -786,35 +819,42 @@ class GenericValidator(wx.PyValidator):
     def TransferToWindow(self):
         """Transfer data from validator to window.
         """
-        return True # Prevent wxDialog from complaining.
+        return True  # Prevent wxDialog from complaining.
 
     def TransferFromWindow(self):
         """Transfer data from window to validator.
         """
-        return True # Prevent wxDialog from complaining.
+        return True  # Prevent wxDialog from complaining.
+
 
 class MapValidator(GenericValidator):
     """Validator for map name input
 
     See G_legal_filename()
     """
+
     def __init__(self):
         def _mapNameValidationFailed(ctrl):
-            message = _("Name <%(name)s> is not a valid name for GRASS map. "
-                        "Please use only ASCII characters excluding %(chars)s "
-                        "and space.") % {'name': ctrl.GetValue(), 'chars': '/"\'@,=*~'}
+            message = _(
+                "Name <%(name)s> is not a valid name for GRASS map. "
+                "Please use only ASCII characters excluding %(chars)s "
+                "and space.") % {
+                'name': ctrl.GetValue(),
+                'chars': '/"\'@,=*~'}
             GError(message, caption=_("Invalid name"))
-        
+
         GenericValidator.__init__(self,
                                   grass.legal_name,
                                   _mapNameValidationFailed)
-       
+
+
 class SingleSymbolPanel(wx.Panel):
     """Panel for displaying one symbol.
 
     Changes background when selected. Assumes that parent will catch
     events emitted on mouse click. Used in gui_core::dialog::SymbolDialog.
     """
+
     def __init__(self, parent, symbolPath):
         """Panel constructor
 
@@ -825,7 +865,8 @@ class SingleSymbolPanel(wx.Panel):
         :param parent: parent (gui_core::dialog::SymbolDialog)
         :param symbolPath: absolute path to symbol
         """
-        self.symbolSelectionChanged = Signal('SingleSymbolPanel.symbolSelectionChanged')
+        self.symbolSelectionChanged = Signal(
+            'SingleSymbolPanel.symbolSelectionChanged')
 
         wx.Panel.__init__(self, parent, id=wx.ID_ANY, style=wx.BORDER_RAISED)
         self.SetName(os.path.splitext(os.path.basename(symbolPath))[0])
@@ -836,7 +877,11 @@ class SingleSymbolPanel(wx.Panel):
         self.deselectColor = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)
 
         sizer = wx.BoxSizer()
-        sizer.Add(item = self.sBmp, proportion=0, flag=wx.ALL | wx.ALIGN_CENTER, border = 5)
+        sizer.Add(
+            item=self.sBmp,
+            proportion=0,
+            flag=wx.ALL | wx.ALIGN_CENTER,
+            border=5)
         self.SetBackgroundColour(self.deselectColor)
         self.SetMinSize(self.GetBestSize())
         self.SetSizerAndFit(sizer)
@@ -854,7 +899,8 @@ class SingleSymbolPanel(wx.Panel):
         self.Refresh()
         event.Skip()
 
-        self.symbolSelectionChanged.emit(name=self.GetName(), doubleClick=False)
+        self.symbolSelectionChanged.emit(
+            name=self.GetName(), doubleClick=False)
 
     def OnDoubleClick(self, event):
         self.symbolSelectionChanged.emit(name=self.GetName(), doubleClick=True)
@@ -872,9 +918,11 @@ class SingleSymbolPanel(wx.Panel):
         self.Refresh()
 
 
-class GListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.CheckListCtrlMixin):
+class GListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin,
+                listmix.CheckListCtrlMixin):
     """Generic ListCtrl with popup menu to select/deselect all
     items"""
+
     def __init__(self, parent):
         self.parent = parent
 
@@ -885,8 +933,8 @@ class GListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.CheckListCt
         # setup mixins
         listmix.ListCtrlAutoWidthMixin.__init__(self)
 
-        self.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.OnPopupMenu) #wxMSW
-        self.Bind(wx.EVT_RIGHT_UP,            self.OnPopupMenu) #wxGTK
+        self.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.OnPopupMenu)  # wxMSW
+        self.Bind(wx.EVT_RIGHT_UP, self.OnPopupMenu)  # wxGTK
 
     def LoadData(self):
         """Load data into list"""
@@ -901,7 +949,7 @@ class GListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.CheckListCt
             self.popupDataID1 = wx.NewId()
             self.popupDataID2 = wx.NewId()
 
-            self.Bind(wx.EVT_MENU, self.OnSelectAll,  id=self.popupDataID1)
+            self.Bind(wx.EVT_MENU, self.OnSelectAll, id=self.popupDataID1)
             self.Bind(wx.EVT_MENU, self.OnSelectNone, id=self.popupDataID2)
 
         # generate popup-menu
@@ -940,24 +988,24 @@ class GListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.CheckListCt
         """Get list data"""
         data = []
         checkedList = []
-        
+
         item = -1
         while True:
-            
+
             row = []
             item = self.GetNextItem(item)
             if item == -1:
                 break
 
             isChecked = self.IsChecked(item)
-            if checked is not None and  checked != isChecked:
+            if checked is not None and checked != isChecked:
                 continue
 
             checkedList.append(isChecked)
 
             for i in range(self.GetColumnCount()):
                 row.append(self.GetItem(item, i).GetText())
-            
+
             row.append(item)
             data.append(tuple(row))
 
@@ -971,16 +1019,17 @@ class GListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.CheckListCt
         self.DeleteAllItems()
         if data is None:
             return
-        
+
         for item in data:
-            index = self.InsertStringItem(sys.maxint, str(item[0]))
+            index = self.InsertStringItem(sys.maxsize, str(item[0]))
             for i in range(1, self.GetColumnCount()):
                 self.SetStringItem(index, i, item[i])
-        
+
         # check by default only on one item
         if len(data) == 1 and selectOne:
             self.CheckItem(index, True)
 
+
 class SearchModuleWidget(wx.Panel):
     """Search module widget (used e.g. in SearchModuleWindow)
 
@@ -989,12 +1038,13 @@ class SearchModuleWidget(wx.Panel):
         showSearchResult - attribute 'result' is a node (representing module)
         showNotification - attribute 'message'
     """
+
     def __init__(self, parent, model,
                  showChoice=True, showTip=False, **kwargs):
         self._showTip = showTip
         self._showChoice = showChoice
         self._model = model
-        self._results = [] # list of found nodes
+        self._results = []  # list of found nodes
         self._resultIndex = -1
         self._searchKeys = ['description', 'keywords', 'command']
         self._oldValue = ''
@@ -1006,27 +1056,32 @@ class SearchModuleWidget(wx.Panel):
         wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY, **kwargs)
 
 #        self._box = wx.StaticBox(parent = self, id = wx.ID_ANY,
-#                                label = " %s " % _("Find module - (press Enter for next match)"))
+# label = " %s " % _("Find module - (press Enter for next match)"))
 
         if sys.platform == 'win32':
-            self._search = wx.TextCtrl(parent = self, id = wx.ID_ANY,
-                                       size = (-1, 25), style = wx.TE_PROCESS_ENTER)
+            self._search = wx.TextCtrl(
+                parent=self, id=wx.ID_ANY, size=(-1, 25),
+                style=wx.TE_PROCESS_ENTER)
         else:
-            self._search = wx.SearchCtrl(parent = self, id = wx.ID_ANY,
-                                         size = (-1, 25), style = wx.TE_PROCESS_ENTER)
+            self._search = wx.SearchCtrl(
+                parent=self, id=wx.ID_ANY, size=(-1, 25),
+                style=wx.TE_PROCESS_ENTER)
             self._search.SetDescriptiveText(_('Fulltext search'))
-            self._search.SetToolTipString(_("Type to search in all modules. Press Enter for next match."))
+            self._search.SetToolTipString(
+                _("Type to search in all modules. Press Enter for next match."))
 
         self._search.Bind(wx.EVT_TEXT, self.OnSearchModule)
         self._search.Bind(wx.EVT_TEXT_ENTER, self.OnEnter)
 
         if self._showTip:
-            self._searchTip = StaticWrapText(parent = self, id = wx.ID_ANY,
-                                             size = (-1, 35))
+            self._searchTip = StaticWrapText(parent=self, id=wx.ID_ANY,
+                                             size=(-1, 35))
 
         if self._showChoice:
             self._searchChoice = wx.Choice(parent=self, id=wx.ID_ANY)
-            self._searchChoice.SetItems(self._searchModule(keys=['command'], value=''))
+            self._searchChoice.SetItems(
+                self._searchModule(
+                    keys=['command'], value=''))
             self._searchChoice.Bind(wx.EVT_CHOICE, self.OnSelectModule)
 
         self._layout()
@@ -1048,7 +1103,7 @@ class SearchModuleWidget(wx.Panel):
             boxSizer.Add(item=hSizer, flag=wx.EXPAND)
         if self._showTip:
             boxSizer.Add(item=self._searchTip,
-                          flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)
+                         flag=wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)
 
         sizer.Add(item=boxSizer, proportion=1)
 
@@ -1076,10 +1131,11 @@ class SearchModuleWidget(wx.Panel):
         self._oldValue = value
 
         if len(value) <= 2:
-            if len(value) == 0: # reset
+            if len(value) == 0:  # reset
                 commands = self._searchModule(keys=['command'], value='')
             else:
-                self.showNotification.emit(message=_("Searching, please type more characters."))
+                self.showNotification.emit(
+                    message=_("Searching, please type more characters."))
                 return
         else:
             commands = self._searchModule(keys=self._searchKeys, value=value)
@@ -1110,14 +1166,14 @@ class SearchModuleWidget(wx.Panel):
         nodes.sort(key=lambda node: self._model.GetIndexOfNode(node))
         self._results = nodes
         self._resultIndex = -1
-        commands = [node.data['command'] for node in nodes if node.data['command']]
-        commands.sort() # return sorted list of commands (TODO: sort in better way)
+        commands = sorted([node.data['command']
+                           for node in nodes if node.data['command']])
 
         return commands
 
     def OnSelectModule(self, event):
         """Module selected from choice, update command prompt"""
-        cmd  = self._searchChoice.GetStringSelection()
+        cmd = self._searchChoice.GetStringSelection()
         self.moduleSelected.emit(name=cmd)
 
         if self._showTip:
@@ -1135,6 +1191,7 @@ class SearchModuleWidget(wx.Panel):
 
 class ManageSettingsWidget(wx.Panel):
     """Widget which allows loading and saving settings into file."""
+
     def __init__(self, parent, settingsFile):
         """
         Signals:
@@ -1166,13 +1223,14 @@ class ManageSettingsWidget(wx.Panel):
         self.btnSettingsSave.SetToolTipString(_("Save current settings"))
         self.btnSettingsDel = wx.Button(parent=self, id=wx.ID_REMOVE)
         self.btnSettingsDel.Bind(wx.EVT_BUTTON, self.OnSettingsDelete)
-        self.btnSettingsSave.SetToolTipString(_("Delete currently selected settings"))
+        self.btnSettingsSave.SetToolTipString(
+            _("Delete currently selected settings"))
 
         # escaping with '$' character - index in self.esc_chars
         self.e_char_i = 0
         self.esc_chars = ['$', ';']
 
-        self._settings = self._loadSettings() # -> self.settingsChoice.SetItems()
+        self._settings = self._loadSettings()  # -> self.settingsChoice.SetItems()
         self.settingsLoaded.emit(settings=self._settings)
 
         self.data_to_save = []
@@ -1185,12 +1243,18 @@ class ManageSettingsWidget(wx.Panel):
     def _layout(self):
 
         self.settingsSizer = wx.StaticBoxSizer(self.settingsBox, wx.HORIZONTAL)
-        self.settingsSizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY,
-                                                  label=_("Load:")),
-                               flag=wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.LEFT,
-                               border=5)
-        self.settingsSizer.Add(item=self.settingsChoice,
-                               proportion=1, flag=wx.EXPAND | wx.BOTTOM, border=3)
+        self.settingsSizer.Add(
+            item=wx.StaticText(
+                parent=self,
+                id=wx.ID_ANY,
+                label=_("Load:")),
+            flag=wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.LEFT,
+            border=5)
+        self.settingsSizer.Add(
+            item=self.settingsChoice,
+            proportion=1,
+            flag=wx.EXPAND | wx.BOTTOM,
+            border=3)
         self.settingsSizer.Add(item=self.btnSettingsSave,
                                flag=wx.LEFT | wx.RIGHT | wx.BOTTOM, border=3)
         self.settingsSizer.Add(item=self.btnSettingsDel,
@@ -1200,8 +1264,8 @@ class ManageSettingsWidget(wx.Panel):
         """Load named settings"""
         name = event.GetString()
         if name not in self._settings:
-            GError(parent = self,
-                   message = _("Settings <%s> not found") % name)
+            GError(parent=self,
+                   message=_("Settings <%s> not found") % name)
             return
 
         data = self._settings[name]
@@ -1229,10 +1293,14 @@ class ManageSettingsWidget(wx.Panel):
     def SaveSettings(self, name):
         # check if settings item already exists
         if name in self._settings:
-            dlgOwt = wx.MessageDialog(self, message=_("Settings <%s> already exists. "
-                                                      "Do you want to overwrite the settings?") % name,
-                                      caption=_("Save settings"),
-                                      style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
+            dlgOwt = wx.MessageDialog(
+                self,
+                message=_(
+                    "Settings <%s> already exists. "
+                    "Do you want to overwrite the settings?") %
+                name,
+                caption=_("Save settings"),
+                style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
             if dlgOwt.ShowModal() != wx.ID_YES:
                 dlgOwt.Destroy()
                 return
@@ -1278,8 +1346,8 @@ class ManageSettingsWidget(wx.Panel):
         """
         name = self.settingsChoice.GetStringSelection()
         if not name:
-            GMessage(parent = self,
-                     message = _("No settings is defined. Operation canceled."))
+            GMessage(parent=self,
+                     message=_("No settings is defined. Operation canceled."))
             return
 
         self._settings.pop(name)
@@ -1300,11 +1368,15 @@ class ManageSettingsWidget(wx.Panel):
                 for v in values:
                     # escaping characters
                     for e_ch in self.esc_chars:
-                        v = v.replace(e_ch, self.esc_chars[self.e_char_i] + e_ch)
+                        v = v.replace(
+                            e_ch, self.esc_chars[
+                                self.e_char_i] + e_ch)
                     if first:
                         # escaping characters
                         for e_ch in self.esc_chars:
-                            key = key.replace(e_ch, self.esc_chars[self.e_char_i] + e_ch)
+                            key = key.replace(
+                                e_ch, self.esc_chars[
+                                    self.e_char_i] + e_ch)
                         fd.write('%s;%s;' % (key, v))
                         first = False
                     else:
@@ -1312,8 +1384,8 @@ class ManageSettingsWidget(wx.Panel):
                 fd.write('\n')
 
         except IOError:
-            GError(parent = self,
-                   message = _("Unable to save settings"))
+            GError(parent=self,
+                   message=_("Unable to save settings"))
             return -1
         fd.close()
 
@@ -1382,18 +1454,20 @@ class ManageSettingsWidget(wx.Panel):
                         # $$$$$; - it is not separator
                         i_esc_chars = 0
                         while True:
-                            if line[idx - (i_esc_chars + 1)] == self.esc_chars[self.e_char_i]:
+                            if line[idx - (i_esc_chars + 1)
+                                    ] == self.esc_chars[self.e_char_i]:
                                 i_esc_chars += 1
                             else:
                                 break
-                        if i_esc_chars%2 != 0:
+                        if i_esc_chars % 2 != 0:
                             i_last = idx + 1
                             continue
 
-                    lineItem = line[i_last_found : idx]
+                    lineItem = line[i_last_found: idx]
                     # unescape characters
                     for e_ch in self.esc_chars:
-                        lineItem = lineItem.replace(self.esc_chars[self.e_char_i] + e_ch, e_ch)
+                        lineItem = lineItem.replace(
+                            self.esc_chars[self.e_char_i] + e_ch, e_ch)
                     if i_last_found == 0:
                         key = lineItem
                     else:
@@ -1421,19 +1495,31 @@ class ManageSettingsWidget(wx.Panel):
                 lineData = line.rstrip('\n').split(';')
                 if len(lineData) > 4:
                     # type, dsn, format, options
-                    data[lineData[0]] = (lineData[1], lineData[2], lineData[3], lineData[4])
+                    data[
+                        lineData[0]] = (
+                        lineData[1],
+                        lineData[2],
+                        lineData[3],
+                        lineData[4])
                 else:
-                    data[lineData[0]] = (lineData[1], lineData[2], lineData[3], '')
+                    data[
+                        lineData[0]] = (
+                        lineData[1],
+                        lineData[2],
+                        lineData[3],
+                        '')
             except ValueError:
                 pass
 
         return data
 
+
 class PictureComboBox(wx.combo.OwnerDrawnComboBox):
     """Abstract class of ComboBox with pictures.
 
         Derived class has to specify has to specify _getPath method.
     """
+
     def OnDrawItem(self, dc, rect, item, flags):
         """Overridden from OwnerDrawnComboBox.
 
@@ -1449,7 +1535,8 @@ class PictureComboBox(wx.combo.OwnerDrawnComboBox):
         # for painting the items in the popup
         bitmap = self.GetPictureBitmap(self.GetString(item))
         if bitmap:
-            dc.DrawBitmap(bitmap, r.x, r.y + (r.height - bitmap.GetHeight()) / 2)
+            dc.DrawBitmap(
+                bitmap, r.x, r.y + (r.height - bitmap.GetHeight()) / 2)
             width = bitmap.GetWidth() + 10
         else:
             width = 0
@@ -1487,18 +1574,25 @@ class ColorTablesComboBox(PictureComboBox):
     """ComboBox with drawn color tables (created by thumbnails.py).
 
     Used in r(3).colors dialog."""
+
     def _getPath(self, name):
-        return os.path.join(os.getenv("GISBASE"), "docs", "html", "colortables", "%s.png" % name)
+        return os.path.join(
+            os.getenv("GISBASE"),
+            "docs", "html", "colortables", "%s.png" % name)
 
 
 class BarscalesComboBox(PictureComboBox):
     """ComboBox with barscales for d.barscale."""
+
     def _getPath(self, name):
-        return os.path.join(os.getenv("GISBASE"), "docs", "html", "barscales", name + '.png')
+        return os.path.join(
+            os.getenv("GISBASE"),
+            "docs", "html", "barscales", name + '.png')
 
 
 class NArrowsComboBox(PictureComboBox):
     """ComboBox with north arrows for d.barscale."""
+
     def _getPath(self, name):
         path = os.path.join(os.getenv("GISBASE"), "gui", "images",
                             'symbols', 'n_arrows')
@@ -1511,52 +1605,54 @@ class NArrowsComboBox(PictureComboBox):
     def OnMeasureItem(self, item):
         return 32
 
+
 class LayersList(GListCtrl, listmix.TextEditMixin):
     """List of layers to be imported (dxf, shp...)"""
-    def __init__(self, parent, columns, log = None):
+
+    def __init__(self, parent, columns, log=None):
         GListCtrl.__init__(self, parent)
-        
+
         self.log = log
-        
+
         # setup mixins
         listmix.TextEditMixin.__init__(self)
-        
+
         for i in range(len(columns)):
             self.InsertColumn(i, columns[i])
-        
+
         if len(columns) == 4:
             width = (65, 200, 90)
         else:
             width = (65, 180, 90, 70)
-        
+
         for i in range(len(width)):
-            self.SetColumnWidth(col = i, width = width[i])
-                
+            self.SetColumnWidth(col=i, width=width[i])
+
     def OnLeftDown(self, event):
         """Allow editing only output name
-        
+
         Code taken from TextEditMixin class.
         """
         x, y = event.GetPosition()
-        
+
         colLocs = [0]
         loc = 0
         for n in range(self.GetColumnCount()):
             loc = loc + self.GetColumnWidth(n)
             colLocs.append(loc)
-        
+
         col = bisect(colLocs, x + self.GetScrollPos(wx.HORIZONTAL)) - 1
-        
+
         if col == self.GetColumnCount() - 1:
             listmix.TextEditMixin.OnLeftDown(self, event)
         else:
             event.Skip()
-        
+
     def GetLayers(self):
         """Get list of layers (layer name, output name, list id)"""
         layers = []
 
-        data = self.GetData(checked=True);
+        data = self.GetData(checked=True)
 
         for itm in data:
 
@@ -1568,4 +1664,3 @@ class LayersList(GListCtrl, listmix.TextEditMixin):
             layers.append((layer, output, itm[-1]))
 
         return layers
-

+ 1 - 1
gui/wxpython/iclass/__init__.py

@@ -6,4 +6,4 @@ all = [
     'toolbars',
     'statistics',
     'frame',
-    ]
+]

File diff ditekan karena terlalu besar
+ 348 - 276
gui/wxpython/iclass/dialogs.py


+ 64 - 47
gui/wxpython/iclass/digit.py

@@ -19,26 +19,28 @@ for details.
 import wx
 
 from vdigit.mapwindow import VDigitWindow
-from vdigit.wxdigit   import IVDigit
+from vdigit.wxdigit import IVDigit
 from vdigit.wxdisplay import DisplayDriver, TYPE_AREA
-from core.gcmd        import GWarning
+from core.gcmd import GWarning
 from core.utils import _
 try:
-    from grass.lib.gis    import G_verbose, G_set_verbose
+    from grass.lib.gis import G_verbose, G_set_verbose
     from grass.lib.vector import *
-    from grass.lib.vedit  import *
+    from grass.lib.vedit import *
 except ImportError:
     pass
 
 import grass.script as grass
 
+
 class IClassVDigitWindow(VDigitWindow):
     """Class similar to VDigitWindow but specialized for wxIClass."""
+
     def __init__(self, parent, giface, map, properties):
         """
-        
+
         @a parent should has toolbar providing current class (category).
-        
+
         :param parent: gui parent
         :param map: map renderer instance
         """
@@ -52,45 +54,49 @@ class IClassVDigitWindow(VDigitWindow):
 
         region = grass.region()
         e, n = self.Pixel2Cell(event.GetPositionTuple())
-        if not ((region['s'] <= n <= region['n']) and (region['w'] <= e <= region['e'])):
-            GWarning(parent = self.parent, 
-                     message = _("You are trying to create a training area "
-                                 "outside the computational region. "
-                                 "Please, use g.region to set the appropriate region first."))
+        if not((region['s'] <= n <= region['n'])
+               and(region['w'] <= e <= region['e'])):
+            GWarning(
+                parent=self.parent, message=_(
+                    "You are trying to create a training area "
+                    "outside the computational region. "
+                    "Please, use g.region to set the appropriate region first."))
             return
 
         cat = self.GetCurrentCategory()
-        
+
         if cat is None and action == "addLine":
-            dlg = wx.MessageDialog(parent = self.parent,
-                      message = _("In order to create a training area, "
-                                  "you have to select class first.\n\n"
-                                  "There is no class yet, "
-                                  "do you want to create one?"),
-                      caption = _("No class selected"),
-                      style = wx.YES_NO)
+            dlg = wx.MessageDialog(
+                parent=self.parent,
+                message=_(
+                    "In order to create a training area, "
+                    "you have to select class first.\n\n"
+                    "There is no class yet, "
+                    "do you want to create one?"),
+                caption=_("No class selected"),
+                style=wx.YES_NO)
             if dlg.ShowModal() == wx.ID_YES:
                 self.parent.OnCategoryManager(None)
-                
+
             dlg.Destroy()
             event.Skip()
             return
-        
+
         super(IClassVDigitWindow, self)._onLeftDown(event)
-        
+
     def _addRecord(self):
         return False
-        
+
     def _updateATM(self):
         pass
-        
+
     def _onRightUp(self, event):
         super(IClassVDigitWindow, self)._onRightUp(event)
-        self.parent.UpdateChangeState(changes = True)
-        
+        self.parent.UpdateChangeState(changes=True)
+
     def GetCurrentCategory(self):
         """Returns current category (class).
-        
+
         Category should be assigned to new features (areas).
         It is taken from parent's toolbar.
         """
@@ -100,20 +106,22 @@ class IClassVDigitWindow(VDigitWindow):
         """Get color associated with given category"""
         r, g, b = map(int, self.parent.GetClassColor(cat).split(':'))
         return wx.Colour(r, g, b)
-        
+
+
 class IClassVDigit(IVDigit):
     """Class similar to IVDigit but specialized for wxIClass."""
+
     def __init__(self, mapwindow):
-        IVDigit.__init__(self, mapwindow, driver = IClassDisplayDriver)
-        self._settings['closeBoundary'] = True # snap to the first node
-        
+        IVDigit.__init__(self, mapwindow, driver=IClassDisplayDriver)
+        self._settings['closeBoundary'] = True  # snap to the first node
+
     def _getNewFeaturesLayer(self):
         return 1
-        
+
     def _getNewFeaturesCat(self):
         cat = self.mapWindow.GetCurrentCategory()
         return cat
-        
+
     def DeleteAreasByCat(self, cats):
         """Delete areas (centroid+boundaries) by categories
 
@@ -121,12 +129,12 @@ class IClassVDigit(IVDigit):
         """
         for cat in cats:
             Vedit_delete_areas_cat(self.poMapInfo, 1, cat)
-       
-    def CopyMap(self, name, tmp = False):
+
+    def CopyMap(self, name, tmp=False):
         """Make a copy of open vector map
 
         Note: Attributes are not copied
-        
+
         :param name: name for a copy
         :param tmp: True for temporary map
 
@@ -136,9 +144,9 @@ class IClassVDigit(IVDigit):
         if not self.poMapInfo:
             # nothing to copy
             return -1
-        
+
         poMapInfoNew = pointer(Map_info())
-        
+
         if not tmp:
             open_fn = Vect_open_new
         else:
@@ -150,33 +158,42 @@ class IClassVDigit(IVDigit):
 
         verbose = G_verbose()
         G_set_verbose(-1)      # be silent
-        
+
         if Vect_copy_map_lines(self.poMapInfo, poMapInfoNew) == 1:
             G_set_verbose(verbose)
             return -1
-        
+
         Vect_build(poMapInfoNew)
         G_set_verbose(verbose)
-        
+
         ret = Vect_get_num_lines(poMapInfoNew)
         Vect_close(poMapInfoNew)
-        
+
         return ret
 
     def GetMapInfo(self):
         """Returns Map_info() struct of open vector map"""
         return self.poMapInfo
 
+
 class IClassDisplayDriver(DisplayDriver):
     """Class similar to DisplayDriver but specialized for wxIClass
 
     .. todo::
         needs refactoring (glog, gprogress)
     """
+
     def __init__(self, device, deviceTmp, mapObj, window, glog, gprogress):
-        DisplayDriver.__init__(self, device, deviceTmp, mapObj, window, glog, gprogress)
+        DisplayDriver.__init__(
+            self,
+            device,
+            deviceTmp,
+            mapObj,
+            window,
+            glog,
+            gprogress)
         self._cat = -1
-        
+
     def _drawObject(self, robj):
         """Draw given object to the device
 
@@ -185,9 +202,9 @@ class IClassDisplayDriver(DisplayDriver):
         if robj.type == TYPE_AREA:
             self._cat = Vect_get_area_cat(self.poMapInfo, robj.fid, 1)
         elif robj.type == TYPE_CENTROIDIN:
-            return # skip centroids
+            return  # skip centroids
         DisplayDriver._drawObject(self, robj)
-        
+
     def _definePen(self, rtype):
         """Define pen/brush based on rendered object)
 
@@ -198,7 +215,7 @@ class IClassDisplayDriver(DisplayDriver):
         pen, brush = DisplayDriver._definePen(self, rtype)
         if self._cat > 0 and rtype == TYPE_AREA:
             brush = wx.Brush(self.window.GetCategoryColor(self._cat), wx.SOLID)
-        
+
         return pen, brush
 
     def CloseMap(self):

File diff ditekan karena terlalu besar
+ 583 - 454
gui/wxpython/iclass/frame.py


+ 4 - 2
gui/wxpython/iclass/g.gui.iclass.py

@@ -61,7 +61,7 @@ def main():
 
     from grass.script.setup import set_gui_path
     set_gui_path()
-    
+
     from core.settings import UserSettings
     from core.globalvar import CheckWxVersion
     from core.giface import StandaloneGrassInterface
@@ -94,7 +94,9 @@ def main():
         trainingmap_name = gscript.find_file(name=options['trainingmap'],
                                              element='vector')['fullname']
         if not trainingmap_name:
-            gscript.fatal(_("Vector map <%s> not found") % options['trainingmap'])
+            gscript.fatal(
+                _("Vector map <%s> not found") %
+                options['trainingmap'])
 
     # define display driver
     driver = UserSettings.Get(group='display', key='driver', subkey='type')

+ 126 - 94
gui/wxpython/iclass/plots.py

@@ -21,25 +21,27 @@ import wx.lib.scrolledpanel as scrolled
 from core.utils import _
 from core.gcmd import GError
 
+
 class PlotPanel(scrolled.ScrolledPanel):
     """Panel for drawing multiple plots.
-    
+
     There are three types of plots: histograms, coincidence plots and scatter plots.
     Histograms show frequency of cell category values in training areas
     for each band and for one category. Coincidence plots show min max range
     of classes for each band.
     """
+
     def __init__(self, parent, giface, stats_data):
         scrolled.ScrolledPanel.__init__(self, parent)
-        
-        self.SetupScrolling(scroll_x = False, scroll_y = True)
+
+        self.SetupScrolling(scroll_x=False, scroll_y=True)
         self._giface = giface
         self.parent = parent
         self.canvasList = []
         self.bandList = []
         self.stats_data = stats_data
         self.currentCat = None
-        
+
         self.mainSizer = wx.BoxSizer(wx.VERTICAL)
 
         self._createControlPanel()
@@ -57,46 +59,64 @@ class PlotPanel(scrolled.ScrolledPanel):
     def _createPlotPanel(self):
 
         self.canvasPanel = wx.Panel(parent=self)
-        self.mainSizer.Add(item = self.canvasPanel, proportion = 1, flag = wx.EXPAND, border = 0)
+        self.mainSizer.Add(
+            item=self.canvasPanel,
+            proportion=1,
+            flag=wx.EXPAND,
+            border=0)
         self.canvasSizer = wx.BoxSizer(wx.VERTICAL)
         self.canvasPanel.SetSizer(self.canvasSizer)
 
     def _createControlPanel(self):
-        self.plotSwitch = wx.Choice(self, id = wx.ID_ANY,
-                                     choices = [_("Histograms"),
-                                                _("Coincident plots"),
-                                                _("Scatter plots")])
-        self.mainSizer.Add(self.plotSwitch, proportion = 0, flag = wx.EXPAND|wx.ALL, border = 5)
+        self.plotSwitch = wx.Choice(self, id=wx.ID_ANY,
+                                    choices=[_("Histograms"),
+                                             _("Coincident plots"),
+                                             _("Scatter plots")])
+        self.mainSizer.Add(
+            self.plotSwitch,
+            proportion=0,
+            flag=wx.EXPAND | wx.ALL,
+            border=5)
         self.plotSwitch.Bind(wx.EVT_CHOICE, self.OnPlotTypeSelected)
-    
+
     def _createScatterPlotPanel(self):
         """Init interactive scatter plot tool
         """
         try:
             from iscatt.frame import IClassIScattPanel
-            self.iscatt_panel = IClassIScattPanel(parent=self, 
-                                                  giface=self._giface, 
-                                                  iclass_mapwin = self.parent.GetFirstWindow())
-            self.mainSizer.Add(self.iscatt_panel, proportion = 1, flag = wx.EXPAND, border = 0)
+            self.iscatt_panel = IClassIScattPanel(
+                parent=self, giface=self._giface,
+                iclass_mapwin=self.parent.GetFirstWindow())
+            self.mainSizer.Add(
+                self.iscatt_panel,
+                proportion=1,
+                flag=wx.EXPAND,
+                border=0)
             self.iscatt_panel.Hide()
         except ImportError as e:
-            self.scatt_error = _("Scatter plot functionality is disabled.\n\nReason: " \
-                                 "Unable to import packages needed for scatter plot.\n%s" % e)
-            wx.CallAfter(GError, self.scatt_error, showTraceback=False, parent=self)
+            self.scatt_error = _(
+                "Scatter plot functionality is disabled.\n\nReason: "
+                "Unable to import packages needed for scatter plot.\n%s" %
+                e)
+            wx.CallAfter(
+                GError,
+                self.scatt_error,
+                showTraceback=False,
+                parent=self)
             self.iscatt_panel = None
 
     def OnPlotTypeSelected(self, event):
         """Plot type selected"""
 
         if self.plotSwitch.GetSelection() in [0, 1]:
-            self.SetupScrolling(scroll_x = False, scroll_y = True)
+            self.SetupScrolling(scroll_x=False, scroll_y=True)
             if self.iscatt_panel:
                 self.iscatt_panel.Hide()
             self.canvasPanel.Show()
             self.Layout()
 
         elif self.plotSwitch.GetSelection() == 2:
-            self.SetupScrolling(scroll_x = False, scroll_y = False)
+            self.SetupScrolling(scroll_x=False, scroll_y=False)
             if self.iscatt_panel:
                 self.iscatt_panel.Show()
             else:
@@ -123,35 +143,35 @@ class PlotPanel(scrolled.ScrolledPanel):
         if self.plotSwitch.GetSelection() == 0:
             stat = self.stats_data.GetStatistics(self.currentCat)
             self.UpdateRanges(stat)
-        
-    def EnableZoom(self, type, enable = True):
+
+    def EnableZoom(self, type, enable=True):
         for canvas in self.canvasList:
             canvas.SetEnableZoom(enable)
-            
+
         #canvas.zoom = type
-        
-    def EnablePan(self, enable = True):
+
+    def EnablePan(self, enable=True):
         for canvas in self.canvasList:
             canvas.SetEnableDrag(enable)
-            
+
     def DestroyPlots(self):
         """Destroy all plot canvases"""
         for panel in self.canvasList:
             panel.Destroy()
-            
+
         self.canvasList = []
 
     def ClearPlots(self):
         """Clears plot canvases"""
         for bandIdx in range(len(self.bandList)):
             self.canvasList[bandIdx].Clear()
-            
+
     def Reset(self):
         """Reset plots (when new map imported)"""
         self.currentCat = None
         self.ClearPlots()
         # bands are still the same
-        
+
     def CreatePlotCanvases(self):
         """Create plot canvases according to the number of bands"""
         for band in self.bandList:
@@ -160,15 +180,19 @@ class PlotPanel(scrolled.ScrolledPanel):
             canvas.SetFontSizeTitle(10)
             canvas.SetFontSizeAxis(8)
             self.canvasList.append(canvas)
-            
-            self.canvasSizer.Add(item = canvas, proportion = 1, flag = wx.EXPAND, border = 0)
-        
+
+            self.canvasSizer.Add(
+                item=canvas,
+                proportion=1,
+                flag=wx.EXPAND,
+                border=0)
+
         self.SetVirtualSize(self.GetBestVirtualSize())
         self.Layout()
-        
+
     def UpdatePlots(self, group, subgroup, currentCat, stats_data):
         """Update plots after new analysis
-        
+
         :param group: imagery group
         :param subgroup: imagery group
         :param currentCat: currently selected category (class)
@@ -177,24 +201,24 @@ class PlotPanel(scrolled.ScrolledPanel):
         self.stats_data = stats_data
         self.currentCat = currentCat
         self.bandList = self.parent.GetGroupLayers(group, subgroup)
-        
+
         graphType = self.plotSwitch.GetSelection()
 
         stat = self.stats_data.GetStatistics(currentCat)
         if not stat.IsReady() and graphType == 0:
             return
-            
+
         self.DestroyPlots()
         self.CreatePlotCanvases()
         self.OnPlotTypeSelected(None)
-        
+
     def UpdateCategory(self, cat):
         self.currentCat = cat
-    
+
     def DrawCoincidencePlots(self):
         """Draw coincidence plots"""
         for bandIdx in range(len(self.bandList)):
-            self.canvasList[bandIdx].SetYSpec(type = 'none')
+            self.canvasList[bandIdx].SetYSpec(type='none')
             lines = []
             level = 0.5
             lines.append(self.DrawInvisibleLine(level))
@@ -206,19 +230,20 @@ class PlotPanel(scrolled.ScrolledPanel):
                     continue
                 color = stat.color
                 level = i + 1
-                line = self.DrawCoincidenceLine(level, color, stat.bands[bandIdx])
+                line = self.DrawCoincidenceLine(
+                    level, color, stat.bands[bandIdx])
                 lines.append(line)
-            
-            # invisible 
+
+            # invisible
             level += 0.5
             lines.append(self.DrawInvisibleLine(level))
-            
-            plotGraph = plot.PlotGraphics(lines, title = self.bandList[bandIdx])
+
+            plotGraph = plot.PlotGraphics(lines, title=self.bandList[bandIdx])
             self.canvasList[bandIdx].Draw(plotGraph)
-        
+
     def DrawCoincidenceLine(self, level, color, bandValues):
         """Draw line between band min and max values
-        
+
         :param level: y coordinate of line
         :param color: class color
         :param bandValues: BandStatistics instance
@@ -227,75 +252,80 @@ class PlotPanel(scrolled.ScrolledPanel):
         maxim = bandValues.max
         points = [(minim, level), (maxim, level)]
         color = wx.Colour(*map(int, color.split(':')))
-        return plot.PolyLine(points, colour = color, width = 4)
-        
+        return plot.PolyLine(points, colour=color, width=4)
+
     def DrawInvisibleLine(self, level):
         """Draw white line to achieve better margins"""
         points = [(100, level), (101, level)]
-        return plot.PolyLine(points, colour = wx.WHITE, width = 1)
-        
+        return plot.PolyLine(points, colour=wx.WHITE, width=1)
+
     def DrawHistograms(self, statistics):
         """Draw histograms for one class
-        
+
         :param statistics: statistics for one class
         """
         self.histogramLines = []
         for bandIdx in range(len(self.bandList)):
             self.canvasList[bandIdx].Clear()
-            self.canvasList[bandIdx].SetYSpec(type = 'auto')
-            histgramLine = self.CreateHistogramLine(bandValues = statistics.bands[bandIdx])
-                                                
-            meanLine = self.CreateMean(bandValues = statistics.bands[bandIdx])
-            
-            minLine = self.CreateMin(bandValues = statistics.bands[bandIdx])
-            
-            maxLine = self.CreateMax(bandValues = statistics.bands[bandIdx])
-            
-            self.histogramLines.append([histgramLine, meanLine, minLine, maxLine])
-            
-            maxRangeLine = self.CreateMaxRange(bandValues = statistics.bands[bandIdx])
-            minRangeLine = self.CreateMinRange(bandValues = statistics.bands[bandIdx])
-            
-            plotGraph = plot.PlotGraphics(self.histogramLines[bandIdx] + [minRangeLine, maxRangeLine],
-                                          title = self.bandList[bandIdx])
+            self.canvasList[bandIdx].SetYSpec(type='auto')
+            histgramLine = self.CreateHistogramLine(
+                bandValues=statistics.bands[bandIdx])
+
+            meanLine = self.CreateMean(bandValues=statistics.bands[bandIdx])
+
+            minLine = self.CreateMin(bandValues=statistics.bands[bandIdx])
+
+            maxLine = self.CreateMax(bandValues=statistics.bands[bandIdx])
+
+            self.histogramLines.append(
+                [histgramLine, meanLine, minLine, maxLine])
+
+            maxRangeLine = self.CreateMaxRange(
+                bandValues=statistics.bands[bandIdx])
+            minRangeLine = self.CreateMinRange(
+                bandValues=statistics.bands[bandIdx])
+
+            plotGraph = plot.PlotGraphics(
+                self.histogramLines[bandIdx] + [minRangeLine, maxRangeLine],
+                title=self.bandList[bandIdx])
             self.canvasList[bandIdx].Draw(plotGraph)
-                            
+
     def CreateMinRange(self, bandValues):
         maxVal = max(bandValues.histo)
         rMin = bandValues.rangeMin
-        
+
         points = [(rMin, 0), (rMin, maxVal)]
-        
-        return plot.PolyLine(points, colour = wx.RED, width = 1)
-        
+
+        return plot.PolyLine(points, colour=wx.RED, width=1)
+
     def CreateMaxRange(self, bandValues):
         maxVal = max(bandValues.histo)
         rMax = bandValues.rangeMax
         points = [(rMax, 0), (rMax, maxVal)]
-        
-        return plot.PolyLine(points, colour = wx.RED, width = 1)
-        
+
+        return plot.PolyLine(points, colour=wx.RED, width=1)
+
     def CreateMean(self, bandValues):
         maxVal = max(bandValues.histo)
         mean = bandValues.mean
         points = [(mean, 0), (mean, maxVal)]
-        
-        return plot.PolyLine(points, colour = wx.BLUE, width = 1)
-        
+
+        return plot.PolyLine(points, colour=wx.BLUE, width=1)
+
     def CreateMin(self, bandValues):
         maxVal = max(bandValues.histo)
         minim = bandValues.min
         points = [(minim, 0), (minim, maxVal)]
-        
-        return plot.PolyLine(points, colour = wx.Colour(200, 200, 200), width = 1)
-        
+
+        return plot.PolyLine(points, colour=wx.Colour(200, 200, 200), width=1)
+
     def CreateMax(self, bandValues):
         maxVal = max(bandValues.histo)
         maxim = bandValues.max
         points = [(maxim, 0), (maxim, maxVal)]
-        
-        return plot.PolyLine(points, colour = wx.Colour(200, 200, 200), width = 1)
-        
+
+        return plot.PolyLine(points, colour=wx.Colour(200, 200, 200), width=1)
+
     def CreateHistogramLine(self, bandValues):
         points = []
         for cellCat, count in enumerate(bandValues.histo):
@@ -304,20 +334,22 @@ class PlotPanel(scrolled.ScrolledPanel):
             if cellCat > bandValues.max + 5:
                 break
             points.append((cellCat, count))
-            
-        return plot.PolyLine(points, colour = wx.BLACK, width = 1)
-         
+
+        return plot.PolyLine(points, colour=wx.BLACK, width=1)
+
     def UpdateRanges(self, statistics):
         """Redraw ranges lines in histograms when std dev multiplier changes
-        
+
         :param statistics: python Statistics instance
         """
         for bandIdx in range(len(self.bandList)):
             self.canvasList[bandIdx].Clear()
-            maxRangeLine = self.CreateMaxRange(bandValues = statistics.bands[bandIdx])
-            minRangeLine = self.CreateMinRange(bandValues = statistics.bands[bandIdx])
-            
-            plotGraph = plot.PlotGraphics(self.histogramLines[bandIdx] + [minRangeLine, maxRangeLine],
-                                          title = self.bandList[bandIdx])
+            maxRangeLine = self.CreateMaxRange(
+                bandValues=statistics.bands[bandIdx])
+            minRangeLine = self.CreateMinRange(
+                bandValues=statistics.bands[bandIdx])
+
+            plotGraph = plot.PlotGraphics(
+                self.histogramLines[bandIdx] + [minRangeLine, maxRangeLine],
+                title=self.bandList[bandIdx])
             self.canvasList[bandIdx].Draw(plotGraph)
-        

+ 42 - 36
gui/wxpython/iclass/statistics.py

@@ -30,38 +30,42 @@ except ImportError as e:
 
 from grass.pydispatch.signal import Signal
 
+
 class StatisticsData:
     """Stores all statistics.
     """
+
     def __init__(self):
         self.statisticsDict = {}
         self.statisticsList = []
 
-        self.statisticsAdded = Signal("StatisticsData.statisticsAdded") 
-        self.statisticsDeleted = Signal("StatisticsData.statisticsDeleted") 
-        self.allStatisticsDeleted = Signal("StatisticsData.allStatisticsDeleted") 
+        self.statisticsAdded = Signal("StatisticsData.statisticsAdded")
+        self.statisticsDeleted = Signal("StatisticsData.statisticsDeleted")
+        self.allStatisticsDeleted = Signal(
+            "StatisticsData.allStatisticsDeleted")
 
-        self.statisticsSet = Signal("StatisticsData.statisticsSet") 
+        self.statisticsSet = Signal("StatisticsData.statisticsSet")
 
     def GetStatistics(self, cat):
         return self.statisticsDict[cat]
 
     def AddStatistics(self, cat, name, color):
         st = Statistics()
-        st.SetBaseStatistics(cat = cat, name = name, color = color)
-        st.statisticsSet.connect(lambda stats : self.statisticsSet.emit(cat = cat, 
-                                                                        stats = stats))
+        st.SetBaseStatistics(cat=cat, name=name, color=color)
+        st.statisticsSet.connect(
+            lambda stats: self.statisticsSet.emit(
+                cat=cat, stats=stats))
 
         self.statisticsDict[cat] = st
         self.statisticsList.append(cat)
 
-        self.statisticsAdded.emit(cat = cat, name = name, color = color)
+        self.statisticsAdded.emit(cat=cat, name=name, color=color)
 
     def DeleteStatistics(self, cat):
         del self.statisticsDict[cat]
         self.statisticsList.remove(cat)
 
-        self.statisticsDeleted.emit(cat = cat)
+        self.statisticsDeleted.emit(cat=cat)
 
     def GetCategories(self):
         return self.statisticsList[:]
@@ -72,13 +76,15 @@ class StatisticsData:
 
         self.allStatisticsDeleted.emit()
 
+
 class Statistics:
     """Statistis conected to one class (category).
-    
+
     It is Python counterpart of similar C structure.
     But it adds some attributes or features used in wxIClass.
     It is not interface to C structure (it copies values).
     """
+
     def __init__(self):
         self.category = -1
         self.name = ""
@@ -90,19 +96,19 @@ class Statistics:
         self.bands = []
         self.ready = False
 
-        self.statisticsSet = Signal("Statistics.statisticsSet") 
+        self.statisticsSet = Signal("Statistics.statisticsSet")
 
-    def SetReady(self, ready = True):
+    def SetReady(self, ready=True):
         self.ready = ready
-        
+
     def IsReady(self):
         return self.ready
-        
+
     def SetBaseStatistics(self, cat, name, color):
         """Sets basic (non-statistical) values.
-        
+
         .. todo::
-            Later self.name is changed but self.rasterName is not. 
+            Later self.name is changed but self.rasterName is not.
             self.rasterName should not be set by user. It can remains
             the same. But it should be done more explicitly. Currently
             it looks like unintentional feature or bug.
@@ -110,16 +116,16 @@ class Statistics:
         self.category = cat
         self.name = name
         self.color = color
-        
-        rasterPath = grass.tempfile(create = False)
+
+        rasterPath = grass.tempfile(create=False)
         name = name.replace(' ', '_')
         self.rasterName = name + '_' + os.path.basename(rasterPath)
-        
+
     def SetFromcStatistics(self, cStatistics):
         """Sets all statistical values.
-        
+
         Copies all statistic values from \a cStattistics.
-        
+
         :param cStatistics: pointer to C statistics structure
         """
         cat = c_int()
@@ -138,12 +144,12 @@ class Statistics:
         I_iclass_statistics_get_color(cStatistics, byref(color))
         if self.color != color.value:
             set_stats["color"] = color.value
-        
+
         nbands = c_int()
         I_iclass_statistics_get_nbands(cStatistics, byref(nbands))
         if self.nbands != nbands.value:
             set_stats["nbands"] = nbands.value
-        
+
         ncells = c_int()
         I_iclass_statistics_get_ncells(cStatistics, byref(ncells))
         if self.ncells != ncells.value:
@@ -153,19 +159,19 @@ class Statistics:
         I_iclass_statistics_get_nstd(cStatistics, byref(nstd))
         if self.nstd != nstd.value:
             set_stats["nstd"] = nstd.value
-                
+
         self.SetStatistics(set_stats)
         self.SetBandStatistics(cStatistics)
 
     def SetBandStatistics(self, cStatistics):
         """Sets all band statistics.
-        
+
         :param cStatistics: pointer to C statistics structure
         """
         self.bands = []
         for i in range(self.nbands):
             band = BandStatistics()
-            band.SetFromcStatistics(cStatistics, index = i)
+            band.SetFromcStatistics(cStatistics, index=i)
             self.bands.append(band)
 
     def SetStatistics(self, stats):
@@ -173,24 +179,25 @@ class Statistics:
         for st, val in stats.iteritems():
             setattr(self, st, val)
 
-        self.statisticsSet.emit(stats = stats)
+        self.statisticsSet.emit(stats=stats)
+
 
 class BandStatistics:
     """Statistis conected to one band within class (category).
-    
+
     :class:`Statistics`
     """
+
     def __init__(self):
         self.min = self.max = None
         self.rangeMin = self.rangeMax = None
         self.mean = None
         self.stddev = None
-        self.histo = [0] * 256 # max categories
-        
-        
+        self.histo = [0] * 256  # max categories
+
     def SetFromcStatistics(self, cStatistics, index):
         """Sets statistics for one band by given index.
-        
+
         :param cStatistics: pointer to C statistics structure
         :param index: index of band in C statistics structure
         """
@@ -198,19 +205,18 @@ class BandStatistics:
         I_iclass_statistics_get_min(cStatistics, index, byref(min))
         I_iclass_statistics_get_max(cStatistics, index, byref(max))
         self.min, self.max = min.value, max.value
-        
+
         rangeMin, rangeMax = c_int(), c_int()
         I_iclass_statistics_get_range_min(cStatistics, index, byref(rangeMin))
         I_iclass_statistics_get_range_max(cStatistics, index, byref(rangeMax))
         self.rangeMin, self.rangeMax = rangeMin.value, rangeMax.value
-        
+
         mean, stddev = c_float(), c_float()
         I_iclass_statistics_get_mean(cStatistics, index, byref(mean))
         I_iclass_statistics_get_stddev(cStatistics, index, byref(stddev))
         self.mean, self.stddev = mean.value, stddev.value
-        
+
         histo = c_int()
         for i in range(len(self.histo)):
             I_iclass_statistics_get_histo(cStatistics, index, i, byref(histo))
             self.histo[i] = histo.value
-        

+ 131 - 104
gui/wxpython/iclass/toolbars.py

@@ -29,67 +29,80 @@ from gui_core.forms import GUI
 import grass.script as grass
 
 iClassIcons = {
-        'opacity' : MetaIcon(img = 'layer-opacity',
-                             label = _('Set opacity level')),
-        'classManager' : MetaIcon(img = 'table-manager',
-                                  label = _('Class manager')),
-        'selectGroup' : MetaIcon(img = 'layer-group-add',
-                                 label = _('Select imagery group')),
-        'run' : MetaIcon(img = 'execute',
-                         label = _('Run analysis, update histogram and coincidence plots')),
-        'sigFile' : MetaIcon(img = 'script-save',
-                             label = _('Save signature file for i.maxlik')),
-        'delCmd' : MetaIcon(img = 'layer-remove',
-                            label = _('Remove selected map layer')),
-        'exportAreas' : MetaIcon(img = 'layer-export',
-                            label = _('Export training areas to vector map')),
-        'importAreas' : MetaIcon(img = 'layer-import',
-                            label = _('Import training areas from vector map')),
-        'addRgb' : MetaIcon(img = 'layer-rgb-add',
-                            label = _('Add RGB map layer'))
-        }
-        
+    'opacity': MetaIcon(
+        img='layer-opacity',
+        label=_('Set opacity level')),
+    'classManager': MetaIcon(
+        img='table-manager',
+        label=_('Class manager')),
+    'selectGroup': MetaIcon(
+        img='layer-group-add',
+        label=_('Select imagery group')),
+    'run': MetaIcon(
+        img='execute',
+        label=_('Run analysis, update histogram and coincidence plots')),
+    'sigFile': MetaIcon(
+        img='script-save',
+        label=_('Save signature file for i.maxlik')),
+    'delCmd': MetaIcon(
+        img='layer-remove',
+        label=_('Remove selected map layer')),
+    'exportAreas': MetaIcon(
+        img='layer-export',
+        label=_('Export training areas to vector map')),
+    'importAreas': MetaIcon(
+        img='layer-import',
+        label=_('Import training areas from vector map')),
+    'addRgb': MetaIcon(
+        img='layer-rgb-add',
+        label=_('Add RGB map layer'))}
+
+
 class IClassMapToolbar(BaseToolbar):
     """IClass Map toolbar
     """
+
     def __init__(self, parent, toolSwitcher):
         """IClass Map toolbar constructor
         """
         BaseToolbar.__init__(self, parent, toolSwitcher)
-        
+
         self.InitToolbar(self._toolbarData())
         self._default = self.pan
-        
+
         # add tool to toggle active map window
         self.togglemapid = wx.NewId()
-        self.togglemap = wx.Choice(parent = self, id = self.togglemapid,
-                                   choices = [_('Training'), _('Preview')])
-        
+        self.togglemap = wx.Choice(parent=self, id=self.togglemapid,
+                                   choices=[_('Training'), _('Preview')])
+
         self.InsertControl(9, self.togglemap)
 
-        self.SetToolShortHelp(self.togglemapid, '%s %s %s' % (_('Set map canvas for '),
-                                                              BaseIcons["zoomBack"].GetLabel(),
-                                                              _('/ Zoom to map')))
+        self.SetToolShortHelp(
+            self.togglemapid, '%s %s %s' %
+            (_('Set map canvas for '),
+             BaseIcons["zoomBack"].GetLabel(),
+             _('/ Zoom to map')))
 
         for tool in (self.pan, self.zoomIn, self.zoomOut):
-            self.toolSwitcher.AddToolToGroup(group='mouseUse', toolbar=self, tool=tool)
+            self.toolSwitcher.AddToolToGroup(
+                group='mouseUse', toolbar=self, tool=tool)
         # realize the toolbar
         self.Realize()
-        
+
         self.EnableTool(self.zoomBack, False)
-        
+
     def GetActiveMapTool(self):
         """Return widget for selecting active maps"""
         return self.togglemap
-        
+
     def GetActiveMap(self):
         """Get currently selected map"""
         return self.togglemap.GetSelection()
-        
+
     def SetActiveMap(self, index):
         """Set currently selected map"""
         return self.togglemap.SetSelection(index)
-        
+
     def _toolbarData(self):
         """Toolbar data"""
         icons = BaseIcons
@@ -118,10 +131,13 @@ class IClassMapToolbar(BaseToolbar):
                                       self.parent.OnZoomBack),
                                      ("zoomToMap", icons["zoomExtent"],
                                       self.parent.OnZoomToMap)
-                                    ))
+                                     ))
+
+
 class IClassToolbar(BaseToolbar):
     """IClass toolbar
     """
+
     def __init__(self, parent, stats_data):
         """IClass toolbar constructor
         """
@@ -129,25 +145,25 @@ class IClassToolbar(BaseToolbar):
 
         BaseToolbar.__init__(self, parent)
         self.InitToolbar(self._toolbarData())
-        
-        self.choice = wx.Choice(parent = self, id = wx.ID_ANY, size = (110, -1))
+
+        self.choice = wx.Choice(parent=self, id=wx.ID_ANY, size=(110, -1))
         choiceid = self.InsertControl(3, self.choice)
-        
+
         self.choice.Bind(wx.EVT_CHOICE, self.OnSelectCategory)
-        
+
         # stupid workaround to insert small space between controls
-        self.InsertControl(4, wx.StaticText(self, id = wx.ID_ANY, label = ' '))
-        
-        self.combo = wx.ComboBox(self, id = wx.ID_ANY, size = (130, -1), 
-                                 style = wx.TE_PROCESS_ENTER)
+        self.InsertControl(4, wx.StaticText(self, id=wx.ID_ANY, label=' '))
+
+        self.combo = wx.ComboBox(self, id=wx.ID_ANY, size=(130, -1),
+                                 style=wx.TE_PROCESS_ENTER)
         self.InitStddev()
         comboid = self.InsertControl(5, self.combo)
-        
+
         self.EnableControls(False)
-        
+
         self.combo.Bind(wx.EVT_COMBOBOX, self.OnStdChangeSelection)
         self.combo.Bind(wx.EVT_TEXT_ENTER, self.OnStdChangeText)
-    
+
         self.stats_data.statisticsAdded.connect(self.Update)
         self.stats_data.statisticsDeleted.connect(self.Update)
         self.stats_data.allStatisticsDeleted.connect(self.Update)
@@ -155,37 +171,37 @@ class IClassToolbar(BaseToolbar):
 
         # realize the toolbar
         self.Realize()
-        
+
     def _toolbarData(self):
         """Toolbar data"""
         icons = iClassIcons
         return self._getToolbarData((("selectGroup", icons['selectGroup'],
-                                      lambda event : self.parent.AddBands()),
-                                      (None, ),
-                                      ("classManager", icons['classManager'],
+                                      lambda event: self.parent.AddBands()),
+                                     (None, ),
+                                     ("classManager", icons['classManager'],
                                       self.parent.OnCategoryManager),
-                                      (None, ),
-                                      ("runAnalysis", icons['run'],
+                                     (None, ),
+                                     ("runAnalysis", icons['run'],
                                       self.parent.OnRunAnalysis),
-                                      (None, ),
-                                      ("importAreas", icons['importAreas'],
+                                     (None, ),
+                                     ("importAreas", icons['importAreas'],
                                       self.parent.OnImportAreas),
-                                      ("exportAreas", icons['exportAreas'],
+                                     ("exportAreas", icons['exportAreas'],
                                       self.parent.OnExportAreas),
-                                      ("sigFile", icons['sigFile'],
+                                     ("sigFile", icons['sigFile'],
                                       self.parent.OnSaveSigFile),
-                                    ))
+                                     ))
 
     def OnMotion(self, event):
         print self.choice.GetStringSelection()
-                                
+
     def OnSelectCategory(self, event):
         idx = self.choice.GetSelection()
         cat = self.choice.GetClientData(idx)
 
         self._updateColor(cat)
-        self.parent.CategoryChanged(currentCat = cat)
-        
+        self.parent.CategoryChanged(currentCat=cat)
+
     def _updateColor(self, cat):
 
         if cat:
@@ -203,23 +219,23 @@ class IClassToolbar(BaseToolbar):
         self.choice.Clear()
         for name, idx in zip(catNames, catIdx):
             self.choice.Append(name, idx)
-        
+
     def GetSelectedCategoryName(self):
         return self.choice.GetStringSelection()
-        
+
     def GetSelectedCategoryIdx(self):
         idx = self.choice.GetSelection()
         if idx != wx.NOT_FOUND:
             return self.choice.GetClientData(idx)
-        
+
         return None
-        
+
     def OnStdChangeSelection(self, event):
         idx = self.combo.GetSelection()
         nstd = self.combo.GetClientData(idx)
-        
+
         self.StddevChanged(nstd)
-        
+
     def OnStdChangeText(self, event):
         val = self.combo.GetValue().strip()
         try:
@@ -229,27 +245,32 @@ class IClassToolbar(BaseToolbar):
                 nstd = float(val.split()[0])
             except ValueError:
                 nstd = None
-                
+
         if nstd is not None:
             self.StddevChanged(nstd)
-            
+
     def StddevChanged(self, nstd):
         idx = self.GetSelectedCategoryIdx()
         if not idx:
             return
-            
-        self.parent.StddevChanged(cat = idx, nstd = nstd)
-        
+
+        self.parent.StddevChanged(cat=idx, nstd=nstd)
+
     def UpdateStddev(self, nstd):
         self.combo.SetValue(' '.join(("%.2f" % nstd, _('std dev'))))
-        
+
     def InitStddev(self):
         for nstd in range(50, 250, 25):
             nstd /= 100.
-            self.combo.Append(item = ' '.join(("%.2f" % nstd, _('std dev'))), clientData = nstd)
-        self.combo.SetSelection(4) # 1.5
-        
-    def EnableControls(self, enable = True):
+            self.combo.Append(
+                item=' '.join(
+                    ("%.2f" %
+                     nstd,
+                     _('std dev'))),
+                clientData=nstd)
+        self.combo.SetSelection(4)  # 1.5
+
+    def EnableControls(self, enable=True):
         self.combo.Enable(enable)
         self.choice.Enable(enable)
 
@@ -261,7 +282,7 @@ class IClassToolbar(BaseToolbar):
         for cat in cats:
             stat = self.stats_data.GetStatistics(cat)
             catNames.append(stat.name)
-        self.SetCategories(catNames = catNames, catIdx = cats)
+        self.SetCategories(catNames=catNames, catIdx=cats)
         if name in catNames:
             self.choice.SetStringSelection(name)
             cat = self.GetSelectedCategoryIdx()
@@ -279,26 +300,28 @@ class IClassToolbar(BaseToolbar):
         self._updateColor(cat)
         self.parent.CategoryChanged(cat)
         # don't forget to update maps, histo, ...
-        
+
+
 class IClassMapManagerToolbar(BaseToolbar):
     """IClass toolbar
     """
+
     def __init__(self, parent, mapManager):
         """IClass toolbar constructor
         """
         BaseToolbar.__init__(self, parent)
-        
+
         self.InitToolbar(self._toolbarData())
-        self.choice = wx.Choice(parent = self, id = wx.ID_ANY, size = (300, -1))
-        
+        self.choice = wx.Choice(parent=self, id=wx.ID_ANY, size=(300, -1))
+
         self.choiceid = self.AddControl(self.choice)
-        
+
         self.choice.Bind(wx.EVT_CHOICE, self.OnSelectLayer)
-        
+
         self.mapManager = mapManager
         # realize the toolbar
         self.Realize()
-        
+
     def _toolbarData(self):
         """Toolbar data"""
         return self._getToolbarData((("addRast", BaseIcons['addRast'],
@@ -306,58 +329,63 @@ class IClassMapManagerToolbar(BaseToolbar):
                                      ('addRgb', iClassIcons['addRgb'],
                                       self.OnAddRGB),
                                      ("delRast", iClassIcons['delCmd'],
-                                     self.OnDelRast),
+                                      self.OnDelRast),
                                      ("setOpacity", iClassIcons['opacity'],
-                                     self.OnSetOpacity),
-                                    ))
-                                    
+                                      self.OnSetOpacity),
+                                     ))
+
     def OnSelectLayer(self, event):
         layer = self.choice.GetStringSelection()
-        self.mapManager.SelectLayer(name = layer)
-        
+        self.mapManager.SelectLayer(name=layer)
+
     def OnAddRast(self, event):
-        dlg = IClassMapDialog(self, title = _("Add raster map"), element = 'raster')
+        dlg = IClassMapDialog(
+            self, title=_("Add raster map"),
+            element='raster')
         if dlg.ShowModal() == wx.ID_OK:
-            raster = grass.find_file(name = dlg.GetMap(), element = 'cell')
+            raster = grass.find_file(name=dlg.GetMap(), element='cell')
             if raster['fullname']:
-                self.mapManager.AddLayer(name = raster['fullname'])
-                
+                self.mapManager.AddLayer(name=raster['fullname'])
+
         dlg.Destroy()
-        
+
     def OnAddRGB(self, event):
         cmd = ['d.rgb']
-        GUI(parent = self.parent).ParseCommand(cmd, completed = (self.GetOptData, '', ''))
+        GUI(parent=self.parent).ParseCommand(
+            cmd, completed=(self.GetOptData, '', ''))
 
     def GetOptData(self, dcmd, layer, params, propwin):
         if dcmd:
-            self.mapManager.AddLayerRGB(cmd = dcmd)
+            self.mapManager.AddLayerRGB(cmd=dcmd)
 
     def OnDelRast(self, event):
         layer = self.choice.GetStringSelection()
         idx = self.choice.GetSelection()
         if layer:
-            self.mapManager.RemoveLayer(name = layer, idx = idx)
-            
+            self.mapManager.RemoveLayer(name=layer, idx=idx)
+
     def OnSetOpacity(self, event):
         layer = self.choice.GetStringSelection()
         idx = self.choice.GetSelection()
         if idx == wx.NOT_FOUND:
             return
-            
-        self.mapManager.SetOpacity(name = layer)
+
+        self.mapManager.SetOpacity(name=layer)
+
 
 class IClassMiscToolbar(BaseToolbar):
     """IClass toolbar
     """
+
     def __init__(self, parent):
         """IClass toolbar constructor
         """
         BaseToolbar.__init__(self, parent)
-        
+
         self.InitToolbar(self._toolbarData())
         # realize the toolbar
         self.Realize()
-        
+
     def _toolbarData(self):
         """Toolbar data"""
         icons = BaseIcons
@@ -366,4 +394,3 @@ class IClassMiscToolbar(BaseToolbar):
                                      ("quit", icons['quit'],
                                       self.parent.OnCloseWindow),
                                      ))
-    

+ 1 - 1
gui/wxpython/icons/__init__.py

@@ -1 +1 @@
-all = [ "grass" ]
+all = ["grass"]

+ 38 - 27
gui/wxpython/icons/icon.py

@@ -26,84 +26,95 @@ from core.utils import _
 
 # default icon set
 import grass_icons
-iconSetDefault  = grass_icons.iconSet
+iconSetDefault = grass_icons.iconSet
 iconPathDefault = grass_icons.iconPath
 
-iconTheme = UserSettings.Get(group = 'appearance', key = 'iconTheme', subkey = 'type')
+iconTheme = UserSettings.Get(
+    group='appearance',
+    key='iconTheme',
+    subkey='type')
 if iconTheme != 'grass':
-    sys.stderr.write(_("Unknown iconset '%s', using default 'grass'...\n") % (iconTheme))
+    sys.stderr.write(
+        _("Unknown iconset '%s', using default 'grass'...\n") %
+        (iconTheme))
 
-iconSet  = iconSetDefault
+iconSet = iconSetDefault
 iconPath = iconPathDefault
 
 # join paths
 try:
     if iconPath and not os.path.exists(iconPath):
         raise OSError
-    
+
     for key, img in iconSet.iteritems():
         if key not in iconSet or \
-                iconSet[key] is None: # add key
+                iconSet[key] is None:  # add key
             iconSet[key] = img
-        
+
         iconSet[key] = os.path.join(iconPath, iconSet[key])
-except StandardError as e:
+except Exception as e:
     sys.exit(_("Unable to load icon theme. Reason: %s. Quiting wxGUI...") % e)
-    
+
+
 class MetaIcon:
     """Handle icon metadata (image path, tooltip, ...)
     """
-    def __init__(self, img, label = None, desc = None):
+
+    def __init__(self, img, label=None, desc=None):
         self.imagepath = iconSet.get(img, wx.ART_MISSING_IMAGE)
         if not self.imagepath:
             self.type = 'unknown'
         else:
-            if self.imagepath.find ('wxART_') > -1:
+            if self.imagepath.find('wxART_') > -1:
                 self.type = 'wx'
             else:
                 self.type = 'img'
-        
+
         self.label = label
-        
+
         if desc:
             self.description = desc
         else:
             self.description = ''
-        
+
     def __str__(self):
-        return "label=%s, img=%s, type=%s" % (self.label, self.imagepath, self.type)
+        return "label=%s, img=%s, type=%s" % (
+            self.label, self.imagepath, self.type)
 
-    def GetBitmap(self, size = None):
+    def GetBitmap(self, size=None):
         bmp = None
-        
+
         if self.type == 'wx':
-            bmp = wx.ArtProvider.GetBitmap(id = self.imagepath, client = wx.ART_TOOLBAR, size = size)
+            bmp = wx.ArtProvider.GetBitmap(
+                id=self.imagepath, client=wx.ART_TOOLBAR, size=size)
         elif self.type == 'img':
-            if os.path.isfile(self.imagepath) and os.path.getsize(self.imagepath):
+            if os.path.isfile(
+                    self.imagepath) and os.path.getsize(
+                    self.imagepath):
                 if size and len(size) == 2:
-                    image = wx.Image(name = self.imagepath)
+                    image = wx.Image(name=self.imagepath)
                     image.Rescale(size[0], size[1])
                     bmp = image.ConvertToBitmap()
                 elif self.imagepath:
-                    bmp = wx.Bitmap(name = self.imagepath)
-        
+                    bmp = wx.Bitmap(name=self.imagepath)
+
         return bmp
-    
+
     def GetLabel(self):
         return self.label
 
     def GetDesc(self):
         return self.description
-    
+
     def GetImageName(self):
         return os.path.basename(self.imagepath)
 
-    def SetLabel(self, label = None, desc = None):
+    def SetLabel(self, label=None, desc=None):
         """Set label/description for icon
 
         :param label: icon label (None for no change)
         :param desc: icon description (None for no change)
-        
+
         :return: copy of original object
         """
         cobj = copy.copy(self)
@@ -111,5 +122,5 @@ class MetaIcon:
             cobj.label = label
         if desc:
             cobj.description = desc
-        
+
         return cobj

+ 1 - 1
gui/wxpython/iscatt/__init__.py

@@ -6,4 +6,4 @@ all = [
     'iscatt_core',
     'toolbars',
     'core_c',
-    ]
+]

File diff ditekan karena terlalu besar
+ 271 - 233
gui/wxpython/iscatt/controllers.py


+ 96 - 57
gui/wxpython/iscatt/core_c.py

@@ -24,10 +24,11 @@ except ImportError as e:
 
 from core.gcmd import GException
 
+
 def Rasterize(polygon, rast, region, value):
-    rows, cols = rast.shape 
+    rows, cols = rast.shape
 
-    #TODO creating of region is on many places
+    # TODO creating of region is on many places
     region['rows'] = rows
     region['cols'] = cols
 
@@ -42,16 +43,16 @@ def Rasterize(polygon, rast, region, value):
 
     return rast
 
+
 def ApplyColormap(vals, vals_mask, colmap, out_vals):
-    
+
     c_uint8_p = POINTER(c_uint8)
 
     vals_p = vals.ctypes.data_as(c_uint8_p)
 
-
     if hasattr(vals_mask, "ctypes"):
         vals_mask_p = vals_mask.ctypes.data_as(c_uint8_p)
-    else: #vals mask is empty (all data are selected)
+    else:  # vals mask is empty (all data are selected)
         vals_mask_p = None
     colmap_p = colmap.ctypes.data_as(c_uint8_p)
     out_vals_p = out_vals.ctypes.data_as(c_uint8_p)
@@ -59,6 +60,7 @@ def ApplyColormap(vals, vals_mask, colmap, out_vals):
     vals_size = vals.reshape((-1)).shape[0]
     I_apply_colormap(vals_p, vals_mask_p, vals_size, colmap_p, out_vals_p)
 
+
 def MergeArrays(merged_arr, overlay_arr, alpha):
     if merged_arr.shape != overlay_arr.shape:
         GException("MergeArrays: merged_arr.shape != overlay_arr.shape")
@@ -67,61 +69,89 @@ def MergeArrays(merged_arr, overlay_arr, alpha):
     merged_p = merged_arr.ctypes.data_as(c_uint8_p)
     overlay_p = overlay_arr.ctypes.data_as(c_uint8_p)
 
-    I_merge_arrays(merged_p, overlay_p, merged_arr.shape[0], merged_arr.shape[1], alpha)
+    I_merge_arrays(
+        merged_p,
+        overlay_p,
+        merged_arr.shape[0],
+        merged_arr.shape[1],
+        alpha)
+
 
-def ComputeScatts(region, scatt_conds, bands, n_bands, scatts, cats_rasts_conds, cats_rasts):
+def ComputeScatts(region, scatt_conds, bands, n_bands,
+                  scatts, cats_rasts_conds, cats_rasts):
     _memmapToFileNames(scatts)
     _memmapToFileNames(scatt_conds)
 
     q = Queue()
-    p = Process(target=_computeScattsProcess, args=(region, scatt_conds, bands, 
-                                                    n_bands, scatts, cats_rasts_conds, cats_rasts, q))
+    p = Process(
+        target=_computeScattsProcess,
+        args=(
+            region,
+            scatt_conds,
+            bands,
+            n_bands,
+            scatts,
+            cats_rasts_conds,
+            cats_rasts,
+            q))
     p.start()
     ret = q.get()
     p.join()
-    
+
     return ret[0], ret[1]
 
-#_memmapToFileNames and _fileNamesToMemmap are  workaround for older numpy version, 
+#_memmapToFileNames and _fileNamesToMemmap are  workaround for older numpy version,
 # where memmap objects are not pickable,
 # and therefore cannot be passed to process spawned by multiprocessing module
+
+
 def _memmapToFileNames(data):
 
-    for k, v in data.iteritems(): 
-        if v.has_key('np_vals'):
+    for k, v in data.iteritems():
+        if 'np_vals' in v:
             data[k]['np_vals'] = v['np_vals'].filename()
 
+
 def _fileNamesToMemmap(data):
-    for k, v in data.iteritems(): 
-        if v.has_key('np_vals'):
+    for k, v in data.iteritems():
+        if 'np_vals' in v:
             data[k]['np_vals'] = np.memmap(filename=v['np_vals'])
 
+
 def UpdateCatRast(patch_rast, region, cat_rast):
     q = Queue()
-    p = Process(target=_updateCatRastProcess, args=(patch_rast, region, cat_rast, q))
+    p = Process(
+        target=_updateCatRastProcess,
+        args=(
+            patch_rast,
+            region,
+            cat_rast,
+            q))
     p.start()
     ret = q.get()
     p.join()
 
     return ret
 
+
 def CreateCatRast(region, cat_rast):
     cell_head = _regionToCellHead(region)
-    I_create_cat_rast(pointer(cell_head), cat_rast)   
+    I_create_cat_rast(pointer(cell_head), cat_rast)
 
-def _computeScattsProcess(region, scatt_conds, bands, n_bands, scatts, 
+
+def _computeScattsProcess(region, scatt_conds, bands, n_bands, scatts,
                           cats_rasts_conds, cats_rasts, output_queue):
 
     _fileNamesToMemmap(scatts)
     _fileNamesToMemmap(scatt_conds)
 
-    sccats_c, cats_rasts_c, refs = _getComputationStruct(scatts, cats_rasts, 
-                                                         SC_SCATT_DATA, n_bands)
-    scatt_conds_c, cats_rasts_conds_c, refs2 = _getComputationStruct(scatt_conds, cats_rasts_conds, 
-                                                                     SC_SCATT_CONDITIONS, n_bands)
+    sccats_c, cats_rasts_c, refs = _getComputationStruct(
+        scatts, cats_rasts, SC_SCATT_DATA, n_bands)
+    scatt_conds_c, cats_rasts_conds_c, refs2 = _getComputationStruct(
+        scatt_conds, cats_rasts_conds, SC_SCATT_CONDITIONS, n_bands)
 
     char_bands = _stringListToCharArr(bands)
-   
+
     cell_head = _regionToCellHead(region)
 
     ret = I_compute_scatts(pointer(cell_head),
@@ -137,7 +167,8 @@ def _computeScattsProcess(region, scatt_conds, bands, n_bands, scatts,
 
     output_queue.put((ret, scatts))
 
-def _getBandcRange( band_info):
+
+def _getBandcRange(band_info):
     band_c_range = struct_Range()
 
     band_c_range.max = band_info['max']
@@ -145,14 +176,15 @@ def _getBandcRange( band_info):
 
     return band_c_range
 
+
 def _regionToCellHead(region):
     cell_head = struct_Cell_head()
     G_get_window(pointer(cell_head))
 
-    convert_dict = {'n' : 'north', 'e' : 'east', 
-                    'w' : 'west',  's' : 'south', 
-                    'nsres' : 'ns_res',
-                    'ewres' : 'ew_res'}
+    convert_dict = {'n': 'north', 'e': 'east',
+                    'w': 'west', 's': 'south',
+                    'nsres': 'ns_res',
+                    'ewres': 'ew_res'}
 
     for k, v in region.iteritems():
         if k in ["rows", "cols", "cells", "zone"]:  # zone added in r65224
@@ -160,13 +192,14 @@ def _regionToCellHead(region):
         else:
             v = float(v)
 
-        if convert_dict.has_key(k):
+        if k in convert_dict:
             k = convert_dict[k]
-           
+
         setattr(cell_head, k, v)
 
     return cell_head
 
+
 def _stringListToCharArr(str_list):
 
     arr = c_char_p * len(str_list)
@@ -179,56 +212,62 @@ def _stringListToCharArr(str_list):
 
     return char_arr
 
+
 def _getComputationStruct(cats, cats_rasts, cats_type, n_bands):
 
     sccats = struct_scCats()
-    I_sc_init_cats(pointer(sccats), c_int(n_bands), c_int(cats_type));
+    I_sc_init_cats(pointer(sccats), c_int(n_bands), c_int(cats_type))
 
-    refs = []        
+    refs = []
     cats_rasts_core = []
-    
+
     for cat_id, scatt_ids in cats.iteritems():
         cat_c_id = I_sc_add_cat(pointer(sccats))
         cats_rasts_core.append(cats_rasts[cat_id])
 
         for scatt_id, dt in scatt_ids.iteritems():
-            # if key is missing condition is always True (full scatter plor is computed)
-                vals = dt['np_vals']
+            # if key is missing condition is always True (full scatter plor is
+            # computed)
+            vals = dt['np_vals']
 
-                scatt_vals = scdScattData()
+            scatt_vals = scdScattData()
 
-                c_void_p = ctypes.POINTER(ctypes.c_void_p)
+            c_void_p = ctypes.POINTER(ctypes.c_void_p)
 
-                if cats_type == SC_SCATT_DATA:
-                    vals[:] = 0
-                elif cats_type == SC_SCATT_CONDITIONS:
-                    pass
-                else:
-                    return None
-                data_p = vals.ctypes.data_as(c_void_p)
-                I_scd_init_scatt_data(pointer(scatt_vals), cats_type, len(vals), data_p)
+            if cats_type == SC_SCATT_DATA:
+                vals[:] = 0
+            elif cats_type == SC_SCATT_CONDITIONS:
+                pass
+            else:
+                return None
+            data_p = vals.ctypes.data_as(c_void_p)
+            I_scd_init_scatt_data(
+                pointer(scatt_vals),
+                cats_type, len(vals),
+                data_p)
 
-                refs.append(scatt_vals)
+            refs.append(scatt_vals)
 
-                I_sc_insert_scatt_data(pointer(sccats),  
-                                       pointer(scatt_vals),
-                                       cat_c_id, scatt_id)
+            I_sc_insert_scatt_data(pointer(sccats),
+                                   pointer(scatt_vals),
+                                   cat_c_id, scatt_id)
 
     cats_rasts_c = _stringListToCharArr(cats_rasts_core)
 
     return sccats, cats_rasts_c, refs
 
+
 def _updateCatRastProcess(patch_rast, region, cat_rast, output_queue):
     cell_head = _regionToCellHead(region)
-    
-    
-    ret = I_insert_patch_to_cat_rast(patch_rast, 
-                                     pointer(cell_head), 
+
+    ret = I_insert_patch_to_cat_rast(patch_rast,
+                                     pointer(cell_head),
                                      cat_rast)
 
     output_queue.put(ret)
 
-def _rasterize(polygon, rast, region, value, output_queue):    
+
+def _rasterize(polygon, rast, region, value, output_queue):
     pol_size = len(polygon) * 2
     pol = np.array(polygon, dtype=float)
 
@@ -239,9 +278,9 @@ def _rasterize(polygon, rast, region, value, output_queue):
     rast_p = rast.ctypes.data_as(c_uint8_p)
 
     cell_h = _regionToCellHead(region)
-    I_rasterize(pol_p, 
-                len(polygon), 
-                value, 
+    I_rasterize(pol_p,
+                len(polygon),
+                value,
                 pointer(cell_h), rast_p)
 
     output_queue.put(rast)

+ 216 - 155
gui/wxpython/iscatt/dialogs.py

@@ -32,10 +32,11 @@ from core.gcmd import GMessage
 from core.settings import UserSettings
 from gui_core.dialogs import SimpleDialog
 
+
 class AddScattPlotDialog(wx.Dialog):
 
-    def __init__(self, parent, bands, check_bands_callback, id  = wx.ID_ANY):
-        wx.Dialog.__init__(self, parent, title = _("Add scatter plots"), id = id)
+    def __init__(self, parent, bands, check_bands_callback, id=wx.ID_ANY):
+        wx.Dialog.__init__(self, parent, title=_("Add scatter plots"), id=id)
 
         self.bands = bands
 
@@ -53,71 +54,89 @@ class AddScattPlotDialog(wx.Dialog):
         self.labels = {}
         self.params = {}
 
-        self.band_1_label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("x axis:"))
+        self.band_1_label = wx.StaticText(
+            parent=self, id=wx.ID_ANY, label=_("x axis:"))
 
-        self.band_1_ch = wx.ComboBox(parent = self, id = wx.ID_ANY,
-                                     choices = self.bands,
-                                     style = wx.CB_READONLY, size = (350, 30))
+        self.band_1_ch = wx.ComboBox(parent=self, id=wx.ID_ANY,
+                                     choices=self.bands,
+                                     style=wx.CB_READONLY, size=(350, 30))
 
-        self.band_2_label = wx.StaticText(parent = self, id = wx.ID_ANY, label = _("y axis:"))
+        self.band_2_label = wx.StaticText(
+            parent=self, id=wx.ID_ANY, label=_("y axis:"))
 
-        self.band_2_ch = wx.ComboBox(parent = self, id = wx.ID_ANY,
-                                     choices = self.bands,
-                                     style = wx.CB_READONLY, size = (350, 30))
+        self.band_2_ch = wx.ComboBox(parent=self, id=wx.ID_ANY,
+                                     choices=self.bands,
+                                     style=wx.CB_READONLY, size=(350, 30))
 
-        self.scattsBox = wx.ListBox(parent = self,  id = wx.ID_ANY, size = (-1, 150),
-                                    style = wx.LB_MULTIPLE | wx.LB_NEEDED_SB)
+        self.scattsBox = wx.ListBox(parent=self, id=wx.ID_ANY, size=(-1, 150),
+                                    style=wx.LB_MULTIPLE | wx.LB_NEEDED_SB)
 
         # buttons
         self.btn_add = wx.Button(parent=self, id=wx.ID_ADD)
         self.btn_remove = wx.Button(parent=self, id=wx.ID_REMOVE)
-        
-        self.btn_close = wx.Button(parent=self, id=wx.ID_CANCEL)        
+
+        self.btn_close = wx.Button(parent=self, id=wx.ID_CANCEL)
         self.btn_ok = wx.Button(parent=self, id=wx.ID_OK)
 
         self._layout()
 
     def _layout(self):
 
-        border = wx.BoxSizer(wx.VERTICAL) 
+        border = wx.BoxSizer(wx.VERTICAL)
         dialogSizer = wx.BoxSizer(wx.VERTICAL)
 
         regionSizer = wx.BoxSizer(wx.HORIZONTAL)
 
-        dialogSizer.Add(item = self._addSelectSizer(title = self.band_1_label, 
-                                                    sel = self.band_1_ch))
-
-        dialogSizer.Add(item = self._addSelectSizer(title = self.band_2_label, 
-                                                    sel = self.band_2_ch))
+        dialogSizer.Add(item=self._addSelectSizer(title=self.band_1_label,
+                                                  sel=self.band_1_ch))
 
+        dialogSizer.Add(item=self._addSelectSizer(title=self.band_2_label,
+                                                  sel=self.band_2_ch))
 
-        dialogSizer.Add(item=self.btn_add, proportion=0,  flag = wx.TOP | wx.ALIGN_RIGHT, border = 5)
+        dialogSizer.Add(
+            item=self.btn_add,
+            proportion=0,
+            flag=wx.TOP | wx.ALIGN_RIGHT,
+            border=5)
 
-        box = wx.StaticBox(self, id = wx.ID_ANY,
-                           label = " %s " % _("Bands of scatter plots to be added (x y):"))
+        box = wx.StaticBox(
+            self, id=wx.ID_ANY, label=" %s " %
+            _("Bands of scatter plots to be added (x y):"))
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
 
-        sizer.Add(item=self.scattsBox, proportion=1, flag=wx.EXPAND | wx.TOP, border=5)
-        sizer.Add(item=self.btn_remove, proportion=0, flag=wx.TOP | wx.ALIGN_RIGHT, border = 5)
-
-        dialogSizer.Add(item=sizer, proportion=1,  flag = wx.EXPAND | wx.TOP, border = 5)
+        sizer.Add(
+            item=self.scattsBox,
+            proportion=1,
+            flag=wx.EXPAND | wx.TOP,
+            border=5)
+        sizer.Add(
+            item=self.btn_remove,
+            proportion=0,
+            flag=wx.TOP | wx.ALIGN_RIGHT,
+            border=5)
+
+        dialogSizer.Add(
+            item=sizer,
+            proportion=1,
+            flag=wx.EXPAND | wx.TOP,
+            border=5)
 
         # buttons
-        self.btnsizer = wx.BoxSizer(orient = wx.HORIZONTAL)
+        self.btnsizer = wx.BoxSizer(orient=wx.HORIZONTAL)
+
+        self.btnsizer.Add(item=self.btn_close, proportion=0,
+                          flag=wx.RIGHT | wx.LEFT | wx.ALIGN_CENTER,
+                          border=10)
 
-        self.btnsizer.Add(item = self.btn_close, proportion = 0,
-                          flag = wx.RIGHT | wx.LEFT | wx.ALIGN_CENTER,
-                          border = 10)
-        
-        self.btnsizer.Add(item = self.btn_ok, proportion = 0,
-                          flag = wx.RIGHT | wx.LEFT | wx.ALIGN_CENTER,
-                          border = 10)
+        self.btnsizer.Add(item=self.btn_ok, proportion=0,
+                          flag=wx.RIGHT | wx.LEFT | wx.ALIGN_CENTER,
+                          border=10)
 
-        dialogSizer.Add(item = self.btnsizer, proportion = 0,
-                        flag = wx.ALIGN_CENTER | wx.TOP, border = 5)
+        dialogSizer.Add(item=self.btnsizer, proportion=0,
+                        flag=wx.ALIGN_CENTER | wx.TOP, border=5)
 
-        border.Add(item = dialogSizer, proportion = 0,
-                   flag = wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 10)
+        border.Add(item=dialogSizer, proportion=0,
+                   flag=wx.LEFT | wx.RIGHT | wx.BOTTOM, border=10)
 
         self.SetSizer(border)
         self.Layout()
@@ -130,28 +149,28 @@ class AddScattPlotDialog(wx.Dialog):
         self.btn_remove.Bind(wx.EVT_BUTTON, self.OnRemoveLayer)
 
     def OnOk(self, event):
-        
+
         if not self.GetBands():
             GMessage(parent=self, message=_("No scatter plots selected."))
             return
 
         event.Skip()
 
-    def _addSelectSizer(self, title, sel): 
+    def _addSelectSizer(self, title, sel):
         """Helper layout function.
         """
-        selSizer = wx.BoxSizer(orient = wx.VERTICAL)
+        selSizer = wx.BoxSizer(orient=wx.VERTICAL)
 
         selTitleSizer = wx.BoxSizer(wx.HORIZONTAL)
-        selTitleSizer.Add(item = title, proportion = 1,
-                          flag = wx.TOP | wx.EXPAND, border = 5)
+        selTitleSizer.Add(item=title, proportion=1,
+                          flag=wx.TOP | wx.EXPAND, border=5)
 
-        selSizer.Add(item = selTitleSizer, proportion = 0,
-                     flag = wx.EXPAND)
+        selSizer.Add(item=selTitleSizer, proportion=0,
+                     flag=wx.EXPAND)
 
-        selSizer.Add(item = sel, proportion = 1,
-                     flag = wx.EXPAND | wx.TOP| wx.ALIGN_CENTER_VERTICAL,
-                     border = 5)
+        selSizer.Add(item=sel, proportion=1,
+                     flag=wx.EXPAND | wx.TOP | wx.ALIGN_CENTER_VERTICAL,
+                     border=5)
 
         return selSizer
 
@@ -183,13 +202,16 @@ class AddScattPlotDialog(wx.Dialog):
             GMessage(parent=self, message=_("Select both x and y bands."))
             return
         if b_y == b_x:
-            GMessage(parent=self, message=_("Selected bands must be different."))
+            GMessage(parent=self, message=_(
+                "Selected bands must be different."))
             return
 
-        if [b_x, b_y] in self.sel_bands_ids or [b_y, b_x] in self.sel_bands_ids:
-            GMessage(parent=self, 
-                     message=_("Scatter plot with same bands combination (regardless x y order) " 
-                               "has been already added into the list."))
+        if [b_x, b_y] in self.sel_bands_ids or [
+                b_y, b_x] in self.sel_bands_ids:
+            GMessage(
+                parent=self, message=_(
+                    "Scatter plot with same bands combination (regardless x y order) "
+                    "has been already added into the list."))
             return
 
         if not self.chb_callback(b_x, b_y):
@@ -205,36 +227,38 @@ class AddScattPlotDialog(wx.Dialog):
         self.scattsBox.Append(text)
         event.Skip()
 
+
 class ExportCategoryRaster(wx.Dialog):
-    def __init__(self, parent, title, rasterName = None, id = wx.ID_ANY,
-                 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
+
+    def __init__(self, parent, title, rasterName=None, id=wx.ID_ANY,
+                 style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
                  **kwargs):
         """Dialog for export of category raster.
-        
+
         :param parent: window
         :param str rasterName name of vector layer for export
         :param title: window title
         """
-        wx.Dialog.__init__(self, parent, id, title, style = style, **kwargs)
-        
+        wx.Dialog.__init__(self, parent, id, title, style=style, **kwargs)
+
         self.rasterName = rasterName
-        self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
-        
-        self.btnCancel = wx.Button(parent = self.panel, id = wx.ID_CANCEL)
-        self.btnOK     = wx.Button(parent = self.panel, id = wx.ID_OK)
+        self.panel = wx.Panel(parent=self, id=wx.ID_ANY)
+
+        self.btnCancel = wx.Button(parent=self.panel, id=wx.ID_CANCEL)
+        self.btnOK = wx.Button(parent=self.panel, id=wx.ID_OK)
         self.btnOK.SetDefault()
         self.btnOK.Enable(False)
         self.btnOK.Bind(wx.EVT_BUTTON, self.OnOK)
-        
+
         self.__layout()
-        
+
         self.vectorNameCtrl.Bind(wx.EVT_TEXT, self.OnTextChanged)
         self.OnTextChanged(None)
         wx.CallAfter(self.vectorNameCtrl.SetFocus)
 
     def OnTextChanged(self, event):
         """Name of new vector map given.
-        
+
         Enable/diable OK button.
         """
         file = self.vectorNameCtrl.GetValue()
@@ -242,66 +266,76 @@ class ExportCategoryRaster(wx.Dialog):
             self.btnOK.Enable(True)
         else:
             self.btnOK.Enable(False)
-        
+
     def __layout(self):
         """Do layout"""
         sizer = wx.BoxSizer(wx.VERTICAL)
-        
+
         dataSizer = wx.BoxSizer(wx.VERTICAL)
-        
-        dataSizer.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
-                                           label = _("Enter name of new vector map:")),
-                      proportion = 0, flag = wx.ALL, border = 3)
-        self.vectorNameCtrl = Select(parent = self.panel, type = 'raster',
-                                     mapsets = [grass.gisenv()['MAPSET']],
-                                     size = globalvar.DIALOG_GSELECT_SIZE)
+
+        dataSizer.Add(
+            item=wx.StaticText(
+                parent=self.panel,
+                id=wx.ID_ANY,
+                label=_("Enter name of new vector map:")),
+            proportion=0,
+            flag=wx.ALL,
+            border=3)
+        self.vectorNameCtrl = Select(parent=self.panel, type='raster',
+                                     mapsets=[grass.gisenv()['MAPSET']],
+                                     size=globalvar.DIALOG_GSELECT_SIZE)
         if self.rasterName:
             self.vectorNameCtrl.SetValue(self.rasterName)
-        dataSizer.Add(item = self.vectorNameCtrl,
-                      proportion = 0, flag = wx.ALL | wx.EXPAND, border = 3)
-        
-                      
+        dataSizer.Add(item=self.vectorNameCtrl,
+                      proportion=0, flag=wx.ALL | wx.EXPAND, border=3)
+
         # buttons
         btnSizer = wx.StdDialogButtonSizer()
         btnSizer.AddButton(self.btnCancel)
         btnSizer.AddButton(self.btnOK)
         btnSizer.Realize()
-        
-        sizer.Add(item = dataSizer, proportion = 1,
-                       flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
-        
-        sizer.Add(item = btnSizer, proportion = 0,
-                       flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
-        
+
+        sizer.Add(item=dataSizer, proportion=1,
+                  flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
+
+        sizer.Add(item=btnSizer, proportion=0,
+                  flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
+
         self.panel.SetSizer(sizer)
         sizer.Fit(self)
-        
+
         self.SetMinSize(self.GetSize())
-        
+
     def GetRasterName(self):
         """Returns vector name"""
         return self.vectorNameCtrl.GetValue()
 
     def OnOK(self, event):
         """Checks if map exists and can be overwritten."""
-        overwrite = UserSettings.Get(group = 'cmd', key = 'overwrite', subkey = 'enabled')
+        overwrite = UserSettings.Get(
+            group='cmd', key='overwrite', subkey='enabled')
         rast_name = self.GetRasterName()
-        res = grass.find_file(rast_name, element = 'cell')
+        res = grass.find_file(rast_name, element='cell')
         if res['fullname'] and overwrite is False:
-            qdlg = wx.MessageDialog(parent = self,
-                                        message = _("Raster map <%s> already exists."
-                                                    " Do you want to overwrite it?" % rast_name) ,
-                                        caption = _("Raster <%s> exists" % rast_name),
-                                        style = wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION | wx.CENTRE)
+            qdlg = wx.MessageDialog(
+                parent=self, message=_(
+                    "Raster map <%s> already exists."
+                    " Do you want to overwrite it?" %
+                    rast_name), caption=_(
+                    "Raster <%s> exists" %
+                    rast_name), style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION | wx.CENTRE)
             if qdlg.ShowModal() == wx.ID_YES:
                 event.Skip()
             qdlg.Destroy()
         else:
             event.Skip()
 
+
 class SettingsDialog(wx.Dialog):
-    def __init__(self, parent, id, title, scatt_mgr, pos=wx.DefaultPosition, size=wx.DefaultSize,
-                 style=wx.DEFAULT_DIALOG_STYLE):
+
+    def __init__(
+            self, parent, id, title, scatt_mgr, pos=wx.DefaultPosition,
+            size=wx.DefaultSize, style=wx.DEFAULT_DIALOG_STYLE):
         """Settings dialog"""
         wx.Dialog.__init__(self, parent, id, title, pos, size, style)
 
@@ -311,41 +345,45 @@ class SettingsDialog(wx.Dialog):
         self.parent = parent
         self.settings = {}
 
-        settsLabels = {} 
+        settsLabels = {}
 
-        self.settings["show_ellips"] = wx.CheckBox(parent = self, id=wx.ID_ANY,
-                                                   label = _('Show confidence ellipses'))
-        show_ellips = UserSettings.Get(group ='scatt', key = "ellipses", subkey = "show_ellips")
+        self.settings["show_ellips"] = wx.CheckBox(
+            parent=self, id=wx.ID_ANY, label=_('Show confidence ellipses'))
+        show_ellips = UserSettings.Get(
+            group='scatt', key="ellipses", subkey="show_ellips")
         self.settings["show_ellips"].SetValue(show_ellips)
 
-
         self.colorsSetts = {
-                            "sel_pol" : ["selection", _("Selection polygon color:")],
-                            "sel_pol_vertex" : ["selection", _("Color of selection polygon vertex:")], 
-                            "sel_area" : ["selection", _("Selected area color:")]
-                           }
+            "sel_pol": [
+                "selection", _("Selection polygon color:")], "sel_pol_vertex": [
+                "selection", _("Color of selection polygon vertex:")], "sel_area": [
+                "selection", _("Selected area color:")]}
 
         for settKey, sett in self.colorsSetts.iteritems():
-            settsLabels[settKey] = wx.StaticText(parent = self, id = wx.ID_ANY, label = sett[1])
-            col = UserSettings.Get(group ='scatt', key = sett[0], subkey = settKey)
-            self.settings[settKey] = csel.ColourSelect(parent = self, id = wx.ID_ANY,
-                                            colour = wx.Colour(col[0],
-                                                               col[1],
-                                                               col[2], 
-                                                               255))
+            settsLabels[settKey] = wx.StaticText(
+                parent=self, id=wx.ID_ANY, label=sett[1])
+            col = UserSettings.Get(group='scatt', key=sett[0], subkey=settKey)
+            self.settings[settKey] = csel.ColourSelect(
+                parent=self, id=wx.ID_ANY, colour=wx.Colour(
+                    col[0], col[1], col[2], 255))
 
         self.sizeSetts = {
-                          "snap_tresh" : ["selection", _("Snapping treshold in pixels:")],
-                          "sel_area_opacty" : ["selection", _("Selected area opacity:")]
-                         }
+            "snap_tresh": ["selection", _("Snapping treshold in pixels:")],
+            "sel_area_opacty": ["selection", _("Selected area opacity:")]
+        }
 
         for settKey, sett in self.sizeSetts.iteritems():
-            settsLabels[settKey] = wx.StaticText(parent = self, id = wx.ID_ANY, label = sett[1])
-            self.settings[settKey] = wx.SpinCtrl(parent = self, id = wx.ID_ANY, min=0, max = 100)
-            size = int(UserSettings.Get(group = 'scatt', key = sett[0], subkey = settKey))
+            settsLabels[settKey] = wx.StaticText(
+                parent=self, id=wx.ID_ANY, label=sett[1])
+            self.settings[settKey] = wx.SpinCtrl(
+                parent=self, id=wx.ID_ANY, min=0, max=100)
+            size = int(
+                UserSettings.Get(
+                    group='scatt',
+                    key=sett[0],
+                    subkey=settKey))
             self.settings[settKey].SetValue(size)
 
-
         # buttons
         self.btnSave = wx.Button(self, wx.ID_SAVE)
         self.btnApply = wx.Button(self, wx.ID_APPLY)
@@ -354,24 +392,26 @@ class SettingsDialog(wx.Dialog):
 
         # bindings
         self.btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
-        self.btnApply.SetToolTipString(_("Apply changes for the current session"))
+        self.btnApply.SetToolTipString(
+            _("Apply changes for the current session"))
         self.btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
-        self.btnSave.SetToolTipString(_("Apply and save changes to user settings file (default for next sessions)"))
+        self.btnSave.SetToolTipString(
+            _("Apply and save changes to user settings file (default for next sessions)"))
         self.btnClose.Bind(wx.EVT_BUTTON, self.OnClose)
         self.btnClose.SetToolTipString(_("Close dialog"))
 
-        #Layout
+        # Layout
 
         # Analysis result style layout
         self.SetMinSize(self.GetBestSize())
 
         sizer = wx.BoxSizer(wx.VERTICAL)
 
-        sel_pol_box = wx.StaticBox(parent = self, id = wx.ID_ANY,
-                                   label =" %s " % _("Selection style:"))
+        sel_pol_box = wx.StaticBox(parent=self, id=wx.ID_ANY,
+                                   label=" %s " % _("Selection style:"))
         selPolBoxSizer = wx.StaticBoxSizer(sel_pol_box, wx.VERTICAL)
 
-        gridSizer = wx.GridBagSizer(vgap = 1, hgap = 1)
+        gridSizer = wx.GridBagSizer(vgap=1, hgap=1)
 
         row = 0
         setts = dict(self.colorsSetts.items() + self.sizeSetts.items())
@@ -380,25 +420,30 @@ class SettingsDialog(wx.Dialog):
                       "sel_area_opacty", "snap_tresh"]
         for settKey in settsOrder:
             sett = setts[settKey]
-            gridSizer.Add(item = settsLabels[settKey], flag = wx.ALIGN_CENTER_VERTICAL, pos =(row, 0))
-            gridSizer.Add(item = self.settings[settKey],
-                          flag = wx.ALIGN_RIGHT | wx.ALL, border = 5,
-                          pos =(row, 1))  
+            gridSizer.Add(
+                item=settsLabels[settKey],
+                flag=wx.ALIGN_CENTER_VERTICAL,
+                pos=(
+                    row,
+                    0))
+            gridSizer.Add(item=self.settings[settKey],
+                          flag=wx.ALIGN_RIGHT | wx.ALL, border=5,
+                          pos=(row, 1))
             row += 1
 
         gridSizer.AddGrowableCol(1)
-        selPolBoxSizer.Add(item = gridSizer, flag = wx.EXPAND)
+        selPolBoxSizer.Add(item=gridSizer, flag=wx.EXPAND)
 
-        ell_box = wx.StaticBox(parent = self, id = wx.ID_ANY,
-                               label =" %s " % _("Ellipses settings:"))
+        ell_box = wx.StaticBox(parent=self, id=wx.ID_ANY,
+                               label=" %s " % _("Ellipses settings:"))
         ellPolBoxSizer = wx.StaticBoxSizer(ell_box, wx.VERTICAL)
-        gridSizer = wx.GridBagSizer(vgap = 1, hgap = 1)
+        gridSizer = wx.GridBagSizer(vgap=1, hgap=1)
 
         sett = setts[settKey]
 
         row = 0
-        gridSizer.Add(item=self.settings["show_ellips"], 
-                      flag=wx.ALIGN_CENTER_VERTICAL, 
+        gridSizer.Add(item=self.settings["show_ellips"],
+                      flag=wx.ALIGN_CENTER_VERTICAL,
                       pos=(row, 0))
 
         gridSizer.AddGrowableCol(1)
@@ -411,11 +456,15 @@ class SettingsDialog(wx.Dialog):
 
         sizer.Add(item=selPolBoxSizer, flag=wx.EXPAND | wx.ALL, border=5)
         sizer.Add(item=ellPolBoxSizer, flag=wx.EXPAND | wx.ALL, border=5)
-        sizer.Add(item=btnSizer, flag=wx.EXPAND | wx.ALL, border=5, proportion=0)    
+        sizer.Add(
+            item=btnSizer,
+            flag=wx.EXPAND | wx.ALL,
+            border=5,
+            proportion=0)
 
         self.SetSizer(sizer)
         sizer.Fit(self)
-     
+
     def OnSave(self, event):
         """Button 'Save' pressed"""
         self.UpdateSettings()
@@ -429,47 +478,57 @@ class SettingsDialog(wx.Dialog):
 
     def UpdateSettings(self):
 
-        chanaged_setts = [];
+        chanaged_setts = []
         for settKey, sett in self.colorsSetts.iteritems():
             col = tuple(self.settings[settKey].GetColour())
-            col_s = UserSettings.Get(group='scatt', key=sett[0], subkey=settKey)
+            col_s = UserSettings.Get(
+                group='scatt', key=sett[0], subkey=settKey)
             if col_s != col:
-                UserSettings.Set(group='scatt', 
-                                 key=sett[0], 
+                UserSettings.Set(group='scatt',
+                                 key=sett[0],
                                  subkey=settKey,
                                  value=col)
                 chanaged_setts.append([settKey, sett[0]])
 
         for settKey, sett in self.sizeSetts.iteritems():
             val = self.settings[settKey].GetValue()
-            val_s = UserSettings.Get(group ='scatt', key = sett[0], subkey = settKey)
+            val_s = UserSettings.Get(
+                group='scatt', key=sett[0], subkey=settKey)
 
             if val_s != val:
-                UserSettings.Set(group = 'scatt', key = sett[0], subkey = settKey, 
-                                 value = val)
+                UserSettings.Set(group='scatt', key=sett[0], subkey=settKey,
+                                 value=val)
                 chanaged_setts.append([settKey, sett[0]])
 
         val = self.settings['show_ellips'].IsChecked()
-        val_s = UserSettings.Get(group ='scatt', key='ellipses', subkey='show_ellips')
+        val_s = UserSettings.Get(
+            group='scatt',
+            key='ellipses',
+            subkey='show_ellips')
 
         if val != val_s:
-            UserSettings.Set(group='scatt', key='ellipses', subkey='show_ellips', 
-                             value=val)
+            UserSettings.Set(
+                group='scatt',
+                key='ellipses',
+                subkey='show_ellips',
+                value=val)
             chanaged_setts.append(['ellipses', 'show_ellips'])
 
-        if chanaged_setts: 
+        if chanaged_setts:
             self.scatt_mgr.SettingsUpdated(chanaged_setts)
 
     def OnApply(self, event):
         """Button 'Apply' pressed"""
         self.UpdateSettings()
-        #self.Close()
+        # self.Close()
 
     def OnClose(self, event):
         """Button 'Cancel' pressed"""
         self.Close()
 
+
 class ManageBusyCursorMixin:
+
     def __init__(self, window):
         self.win = window
 
@@ -479,8 +538,8 @@ class ManageBusyCursorMixin:
         self.win.Bind(wx.EVT_ENTER_WINDOW, self.OnEnter)
         self.win.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeave)
 
-    def OnLeave(self, event):   
-        self.cur_inside = False     
+    def OnLeave(self, event):
+        self.cur_inside = False
         self.busy_cur = None
 
     def OnEnter(self, event):
@@ -496,15 +555,17 @@ class ManageBusyCursorMixin:
 
         self.busy_cur = None
 
+
 class RenameClassDialog(SimpleDialog):
+
     def __init__(self, parent, old_name, title=("Change class name")):
         SimpleDialog.__init__(self, parent, title)
 
-        self.name = wx.TextCtrl(self.panel, id = wx.ID_ANY) 
+        self.name = wx.TextCtrl(self.panel, id=wx.ID_ANY)
         self.name.SetValue(old_name)
 
-        self.dataSizer.Add(self.name, proportion = 0,
-                           flag = wx.EXPAND | wx.ALL, border = 1)
+        self.dataSizer.Add(self.name, proportion=0,
+                           flag=wx.EXPAND | wx.ALL, border=1)
 
         self.panel.SetSizer(self.sizer)
         self.name.SetMinSize((200, -1))

+ 176 - 129
gui/wxpython/iscatt/frame.py

@@ -41,44 +41,54 @@ try:
 except ImportError:
     import wx.lib.agw.aui as aui
 
+
 class IClassIScattPanel(wx.Panel, ManageBusyCursorMixin):
-    def __init__(self, parent, giface, iclass_mapwin = None,
-                 id = wx.ID_ANY):
 
-        #wx.SplitterWindow.__init__(self, parent = parent, id = id,
+    def __init__(self, parent, giface, iclass_mapwin=None,
+                 id=wx.ID_ANY):
+
+        # wx.SplitterWindow.__init__(self, parent = parent, id = id,
         #                           style = wx.SP_LIVE_UPDATE)
-        wx.Panel.__init__(self, parent = parent, id = wx.ID_ANY)
+        wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY)
         ManageBusyCursorMixin.__init__(self, window=self)
 
-        self.scatt_mgr = self._createScattMgr(guiparent=parent, giface=giface, 
+        self.scatt_mgr = self._createScattMgr(guiparent=parent, giface=giface,
                                               iclass_mapwin=iclass_mapwin)
 
         # toobars
         self.toolbars = {}
         self.toolbars['mainToolbar'] = self._createMainToolbar()
-        self.toolbars['editingToolbar'] = EditingToolbar(parent = self, scatt_mgr = self.scatt_mgr)
-        
+        self.toolbars['editingToolbar'] = EditingToolbar(
+            parent=self, scatt_mgr=self.scatt_mgr)
+
         self._createCategoryPanel(self)
 
         self.plot_panel = ScatterPlotsPanel(self, self.scatt_mgr)
 
         self.mainsizer = wx.BoxSizer(wx.VERTICAL)
-        self.mainsizer.Add(item = self.toolbars['mainToolbar'], proportion = 0, flag = wx.EXPAND)
-        self.mainsizer.Add(item = self.toolbars['editingToolbar'], proportion = 0, flag = wx.EXPAND)
-        self.mainsizer.Add(item = self.catsPanel, proportion = 0, 
-                           flag = wx.EXPAND | wx.LEFT | wx.RIGHT , border = 5)
-        self.mainsizer.Add(item = self.plot_panel, proportion = 1, flag = wx.EXPAND)
+        self.mainsizer.Add(
+            item=self.toolbars['mainToolbar'],
+            proportion=0, flag=wx.EXPAND)
+        self.mainsizer.Add(
+            item=self.toolbars['editingToolbar'],
+            proportion=0, flag=wx.EXPAND)
+        self.mainsizer.Add(item=self.catsPanel, proportion=0,
+                           flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=5)
+        self.mainsizer.Add(item=self.plot_panel, proportion=1, flag=wx.EXPAND)
 
         self.catsPanel.Hide()
         self.toolbars['editingToolbar'].Hide()
 
         self.SetSizer(self.mainsizer)
-        
-        self.scatt_mgr.computingStarted.connect(lambda : self.UpdateCur(busy=True))
-        self.scatt_mgr.renderingStarted.connect(lambda : self.UpdateCur(busy=True))
-        self.scatt_mgr.renderingFinished.connect(lambda : self.UpdateCur(busy=False))
 
-        #self.SetSashGravity(0.5)
+        self.scatt_mgr.computingStarted.connect(
+            lambda: self.UpdateCur(busy=True))
+        self.scatt_mgr.renderingStarted.connect(
+            lambda: self.UpdateCur(busy=True))
+        self.scatt_mgr.renderingFinished.connect(
+            lambda: self.UpdateCur(busy=False))
+
+        # self.SetSashGravity(0.5)
         #self.SplitHorizontally(self.head_panel, self.plot_panel, -50)
         self.Layout()
 
@@ -90,14 +100,14 @@ class IClassIScattPanel(wx.Panel, ManageBusyCursorMixin):
         ManageBusyCursorMixin.UpdateCur(self, busy)
 
     def _selCatInIScatt(self):
-         return False
+        return False
 
     def _createMainToolbar(self):
-         return MainToolbar(parent = self, scatt_mgr = self.scatt_mgr)
+        return MainToolbar(parent=self, scatt_mgr=self.scatt_mgr)
 
     def _createScattMgr(self, guiparent, giface, iclass_mapwin):
-        return ScattsManager(guiparent=self, giface=giface, iclass_mapwin=iclass_mapwin)
-
+        return ScattsManager(guiparent=self, giface=giface,
+                             iclass_mapwin=iclass_mapwin)
 
     def NewScatterPlot(self, scatt_id, transpose):
         return self.plot_panel.NewScatterPlot(scatt_id, transpose)
@@ -108,45 +118,66 @@ class IClassIScattPanel(wx.Panel, ManageBusyCursorMixin):
 
     def ShowCategoryPanel(self, show):
         self.catsPanel.Show(show)
-        
-        #if show:
-        #    self.SetSashSize(5) 
-        #else:
+
+        # if show:
+        #    self.SetSashSize(5)
+        # else:
         #    self.SetSashSize(0)
         self.plot_panel.SetVirtualSize(self.plot_panel.GetBestVirtualSize())
         self.Layout()
 
     def _createCategoryPanel(self, parent):
         self.catsPanel = wx.Panel(parent=parent)
-        self.cats_list = CategoryListCtrl(parent=self.catsPanel, 
-                                          cats_mgr=self.scatt_mgr.GetCategoriesManager(),
-                                          sel_cats_in_iscatt=self._selCatInIScatt())
+        self.cats_list = CategoryListCtrl(
+            parent=self.catsPanel,
+            cats_mgr=self.scatt_mgr.GetCategoriesManager(),
+            sel_cats_in_iscatt=self._selCatInIScatt())
 
         self.catsPanel.SetMinSize((-1, 100))
         self.catsPanel.SetInitialSize((-1, 150))
 
         box_capt = wx.StaticBox(parent=self.catsPanel, id=wx.ID_ANY,
-                             label=' %s ' % _("Classes"),)
+                                label=' %s ' % _("Classes"),)
         catsSizer = wx.StaticBoxSizer(box_capt, wx.VERTICAL)
 
-        self.toolbars['categoryToolbar'] = self._createCategoryToolbar(self.catsPanel)
+        self.toolbars['categoryToolbar'] = self._createCategoryToolbar(
+            self.catsPanel)
 
-        catsSizer.Add(item=self.cats_list, proportion=1,  flag=wx.EXPAND | wx.TOP, border = 5)
+        catsSizer.Add(
+            item=self.cats_list,
+            proportion=1,
+            flag=wx.EXPAND | wx.TOP,
+            border=5)
         if self.toolbars['categoryToolbar']:
             catsSizer.Add(item=self.toolbars['categoryToolbar'], proportion=0)
 
         self.catsPanel.SetSizer(catsSizer)
-    
+
     def _createCategoryToolbar(self, parent):
         return CategoryToolbar(parent=parent,
-                               scatt_mgr=self.scatt_mgr, 
+                               scatt_mgr=self.scatt_mgr,
                                cats_list=self.cats_list)
 
+
 class IScattDialog(wx.Dialog):
-    def __init__(self, parent, giface, title=_("GRASS GIS Interactive Scatter Plot Tool"),
-                 id=wx.ID_ANY, style=wx.DEFAULT_FRAME_STYLE, **kwargs):
-        wx.Dialog.__init__(self, parent, id, style=style, title = title, **kwargs)
-        self.SetIcon(wx.Icon(os.path.join(globalvar.ICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
+
+    def __init__(
+            self, parent, giface,
+            title=_("GRASS GIS Interactive Scatter Plot Tool"),
+            id=wx.ID_ANY, style=wx.DEFAULT_FRAME_STYLE, **kwargs):
+        wx.Dialog.__init__(
+            self,
+            parent,
+            id,
+            style=style,
+            title=title,
+            **kwargs)
+        self.SetIcon(
+            wx.Icon(
+                os.path.join(
+                    globalvar.ICONDIR,
+                    'grass.ico'),
+                wx.BITMAP_TYPE_ICO))
 
         self.iscatt_panel = MapDispIScattPanel(self, giface)
 
@@ -161,26 +192,31 @@ class IScattDialog(wx.Dialog):
 
     def OnCloseWindow(self, event):
         event.Skip()
-        #self.
+        # self.
+
 
 class MapDispIScattPanel(IClassIScattPanel):
+
     def __init__(self, parent, giface,
                  id=wx.ID_ANY, **kwargs):
         IClassIScattPanel.__init__(self, parent=parent, giface=giface,
-                                         id=id, **kwargs)
+                                   id=id, **kwargs)
 
     def _createScattMgr(self, guiparent, giface, iclass_mapwin):
-        return ScattsManager(guiparent = self, giface = giface)
+        return ScattsManager(guiparent=self, giface=giface)
 
     def _createMainToolbar(self):
-         return MainToolbar(parent = self, scatt_mgr = self.scatt_mgr, opt_tools=['add_group'])
+        return MainToolbar(
+            parent=self, scatt_mgr=self.scatt_mgr, opt_tools=['add_group'])
 
     def _selCatInIScatt(self):
-         return True
+        return True
+
 
 class ScatterPlotsPanel(scrolled.ScrolledPanel):
+
     def __init__(self, parent, scatt_mgr, id=wx.ID_ANY):
-    
+
         scrolled.ScrolledPanel.__init__(self, parent)
         self.SetupScrolling(scroll_x=False, scroll_y=True, scrollToTop=False)
 
@@ -188,10 +224,10 @@ class ScatterPlotsPanel(scrolled.ScrolledPanel):
 
         self.mainPanel = wx.Panel(parent=self, id=wx.ID_ANY)
 
-        #self._createCategoryPanel()
+        # self._createCategoryPanel()
         # Fancy gui
         self._mgr = aui.AuiManager(self.mainPanel)
-        #self._mgr.SetManagedWindow(self)
+        # self._mgr.SetManagedWindow(self)
 
         self._mgr.Update()
 
@@ -202,11 +238,11 @@ class ScatterPlotsPanel(scrolled.ScrolledPanel):
         self.Bind(aui.EVT_AUI_PANE_CLOSE, self.OnPlotPaneClosed)
 
         dlgSize = (-1, 400)
-        #self.SetBestSize(dlgSize)
-        #self.SetInitialSize(dlgSize)
+        # self.SetBestSize(dlgSize)
+        # self.SetInitialSize(dlgSize)
         self.SetAutoLayout(1)
-        #fix goutput's pane size (required for Mac OSX)
-        #if self.gwindow:         
+        # fix goutput's pane size (required for Mac OSX)
+        # if self.gwindow:
         #    self.gwindow.SetSashPosition(int(self.GetSize()[1] * .75))
         self.ignore_scroll = 0
         self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
@@ -217,7 +253,7 @@ class ScatterPlotsPanel(scrolled.ScrolledPanel):
         self.scatts = {}
 
         self.Bind(wx.EVT_CLOSE, self.OnClose)
-        
+
         self.scatt_mgr.cursorPlotMove.connect(self.CursorPlotMove)
 
     def SetBusy(self, busy):
@@ -256,17 +292,18 @@ class ScatterPlotsPanel(scrolled.ScrolledPanel):
         del self.scatt_id_scatt_i[scatt_id]
         del self.scatts[scatt_id]
 
-        if pane.IsOk(): 
-          self._mgr.ClosePane(pane) 
-        self._mgr.Update() 
+        if pane.IsOk():
+            self._mgr.ClosePane(pane)
+        self._mgr.Update()
 
     def OnMouseWheel(self, event):
-        #TODO very ugly find some better solution        
+        # TODO very ugly find some better solution
         self.ignore_scroll = 3
         event.Skip()
 
     def ScrollChildIntoView(self, child):
-        #For aui manager it does not work and returns position always to the top -> deactivated.
+        # For aui manager it does not work and returns position always to the
+        # top -> deactivated.
         pass
 
     def OnPlotPaneClosed(self, event):
@@ -282,13 +319,13 @@ class ScatterPlotsPanel(scrolled.ScrolledPanel):
         else:
             event.Skip()
 
-        #wx.CallAfter(self._mgr.Update)
-        #wx.CallAfter(self.Layout)
+        # wx.CallAfter(self._mgr.Update)
+        # wx.CallAfter(self.Layout)
 
     def _doLayout(self):
 
         mainsizer = wx.BoxSizer(wx.VERTICAL)
-        mainsizer.Add(item = self.mainPanel, proportion = 1, flag = wx.EXPAND)
+        mainsizer.Add(item=self.mainPanel, proportion=1, flag=wx.EXPAND)
         self.SetSizer(mainsizer)
 
         self.Layout()
@@ -296,7 +333,7 @@ class ScatterPlotsPanel(scrolled.ScrolledPanel):
 
     def OnClose(self, event):
         """Close dialog"""
-        #TODO
+        # TODO
         print "closed"
         self.scatt_mgr.CleanUp()
         self.Destroy()
@@ -305,7 +342,7 @@ class ScatterPlotsPanel(scrolled.ScrolledPanel):
         pass
 
     def _newScatterPlotName(self, scatt_id):
-        name = self._getScatterPlotName(self.scatt_i) 
+        name = self._getScatterPlotName(self.scatt_i)
         self.scatt_id_scatt_i[scatt_id] = self.scatt_i
         self.scatt_i += 1
         return name
@@ -315,26 +352,26 @@ class ScatterPlotsPanel(scrolled.ScrolledPanel):
         return name
 
     def NewScatterPlot(self, scatt_id, transpose):
-        #TODO needs to be resolved (should be in this class)
+        # TODO needs to be resolved (should be in this class)
 
-        scatt = ScatterPlotWidget(parent = self.mainPanel, 
-                                  scatt_mgr = self.scatt_mgr, 
-                                  scatt_id = scatt_id, 
-                                  transpose = transpose)
+        scatt = ScatterPlotWidget(parent=self.mainPanel,
+                                  scatt_mgr=self.scatt_mgr,
+                                  scatt_id=scatt_id,
+                                  transpose=transpose)
         scatt.plotClosed.connect(self.ScatterPlotClosed)
         self.transpose[scatt_id] = transpose
-        
+
         caption = self._creteCaption(scatt_id)
         self._mgr.AddPane(scatt,
-                           aui.AuiPaneInfo().Dockable(True).Floatable(True).
-                           Name(self._newScatterPlotName(scatt_id)).MinSize((-1, 300)).
-                           Caption(caption).
-                           Center().Position(1).MaximizeButton(True).
-                           MinimizeButton(True).CaptionVisible(True).
-                           CloseButton(True).Layer(0))
+                          aui.AuiPaneInfo().Dockable(True).Floatable(True).
+                          Name(self._newScatterPlotName(scatt_id)).MinSize((-1, 300)).
+                          Caption(caption).
+                          Center().Position(1).MaximizeButton(True).
+                          MinimizeButton(True).CaptionVisible(True).
+                          CloseButton(True).Layer(0))
 
         self._mgr.Update()
-  
+
         self.SetVirtualSize(self.GetBestVirtualSize())
         self.Layout()
 
@@ -347,10 +384,10 @@ class ScatterPlotsPanel(scrolled.ScrolledPanel):
         transpose = self.transpose[scatt_id]
         bands = self.scatt_mgr.GetBands()
 
-        #TODO too low level
+        # TODO too low level
         b1_id, b2_id = idScattToidBands(scatt_id, len(bands))
 
-        x_b =  bands[b1_id].split('@')[0]
+        x_b = bands[b1_id].split('@')[0]
         y_b = bands[b2_id].split('@')[0]
 
         if transpose:
@@ -361,39 +398,40 @@ class ScatterPlotsPanel(scrolled.ScrolledPanel):
         return "%s x: %s y: %s" % (_("scatter plot"), x_b, y_b)
 
     def GetScattMgr(self):
-        return  self.scatt_mgr
+        return self.scatt_mgr
+
 
 class CategoryListCtrl(wx.ListCtrl,
                        listmix.ListCtrlAutoWidthMixin):
-                       #listmix.TextEditMixin):
+                       # listmix.TextEditMixin):
 
-    def __init__(self, parent, cats_mgr, sel_cats_in_iscatt, id = wx.ID_ANY):
+    def __init__(self, parent, cats_mgr, sel_cats_in_iscatt, id=wx.ID_ANY):
 
-        wx.ListCtrl.__init__(self, parent, id,
-                             style = wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_HRULES|
-                                     wx.LC_VRULES|wx.LC_SINGLE_SEL|wx.LC_NO_HEADER)
+        wx.ListCtrl.__init__(
+            self, parent, id, style=wx.LC_REPORT | wx.LC_VIRTUAL | wx.LC_HRULES |
+            wx.LC_VRULES | wx.LC_SINGLE_SEL | wx.LC_NO_HEADER)
         self.columns = ((_('Class name'), 'name'), )
-                        #(_('Color'), 'color'))
+        #(_('Color'), 'color'))
 
         self.sel_cats_in_iscatt = sel_cats_in_iscatt
 
-        self.Populate(columns = self.columns)
-        
+        self.Populate(columns=self.columns)
+
         self.cats_mgr = cats_mgr
         self.SetItemCount(len(self.cats_mgr.GetCategories()))
 
         self.rightClickedItemIdx = wx.NOT_FOUND
-        
+
         listmix.ListCtrlAutoWidthMixin.__init__(self)
 
-        #listmix.TextEditMixin.__init__(self)
-      
-        self.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.OnCategoryRightUp) #wxMSW
-        self.Bind(wx.EVT_RIGHT_UP,            self.OnCategoryRightUp) #wxGTK
+        # listmix.TextEditMixin.__init__(self)
+
+        self.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.OnCategoryRightUp)  # wxMSW
+        self.Bind(wx.EVT_RIGHT_UP, self.OnCategoryRightUp)  # wxGTK
 
         #self.Bind(wx.EVT_LIST_BEGIN_LABEL_EDIT, self.OnEdit)
         self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSel)
-             
+
         self.cats_mgr.setCategoryAttrs.connect(self.Update)
         self.cats_mgr.deletedCategory.connect(self.Update)
         self.cats_mgr.addedCategory.connect(self.Update)
@@ -409,24 +447,25 @@ class CategoryListCtrl(wx.ListCtrl,
             try:
                 text.encode('ascii')
             except UnicodeEncodeError:
-                GMessage(parent = self, message = _("Please use only ASCII characters."))
+                GMessage(parent=self, message=_(
+                    "Please use only ASCII characters."))
                 return
 
         cat_id = self.cats_mgr.GetCategories()[row]
 
         self.cats_mgr.setCategoryAttrs.disconnect(self.Update)
-        self.cats_mgr.SetCategoryAttrs(cat_id, {attr : text})
+        self.cats_mgr.SetCategoryAttrs(cat_id, {attr: text})
         self.cats_mgr.setCategoryAttrs.connect(self.Update)
-        
+
         self.Select(row)
-        
+
     def Populate(self, columns):
         for i, col in enumerate(columns):
-            self.InsertColumn(i, col[0])#wx.LIST_FORMAT_RIGHT
+            self.InsertColumn(i, col[0])  # wx.LIST_FORMAT_RIGHT
 
         #self.SetColumnWidth(0, 100)
         #self.SetColumnWidth(1, 100)
-        
+
     def AddCategory(self):
 
         self.cats_mgr.addedCategory.disconnect(self.Update)
@@ -437,35 +476,35 @@ class CategoryListCtrl(wx.ListCtrl,
             GError(_("Maximum limit of categories number was reached."))
             return
         self.SetItemCount(len(self.cats_mgr.GetCategories()))
-                        
+
     def DeleteCategory(self):
-        indexList = sorted(self.GetSelectedIndices(), reverse = True)
+        indexList = sorted(self.GetSelectedIndices(), reverse=True)
         cats = []
         for i in indexList:
             # remove temporary raster
             cat_id = self.cats_mgr.GetCategories()[i]
-            
+
             cats.append(cat_id)
 
             self.cats_mgr.deletedCategory.disconnect(self.Update)
             self.cats_mgr.DeleteCategory(cat_id)
             self.cats_mgr.deletedCategory.connect(self.Update)
-            
+
         self.SetItemCount(len(self.cats_mgr.GetCategories()))
-        
+
     def OnSel(self, event):
         if self.sel_cats_in_iscatt:
             indexList = self.GetSelectedIndices()
             sel_cats = []
             cats = self.cats_mgr.GetCategories()
             for i in indexList:
-                sel_cats.append(cats[i])       
+                sel_cats.append(cats[i])
 
             if sel_cats:
                 self.cats_mgr.SetSelectedCat(sel_cats[0])
         event.Skip()
 
-    def GetSelectedIndices(self, state =  wx.LIST_STATE_SELECTED):
+    def GetSelectedIndices(self, state=wx.LIST_STATE_SELECTED):
         indices = []
         lastFound = -1
         while True:
@@ -475,17 +514,17 @@ class CategoryListCtrl(wx.ListCtrl,
             else:
                 lastFound = index
                 indices.append(index)
-        return indices        
+        return indices
 
     def DeselectAll(self):
         """Deselect all items"""
         indexList = self.GetSelectedIndices()
         for i in indexList:
-            self.Select(i, on = 0)
-         
+            self.Select(i, on=0)
+
         # no highlight
         self.OnCategorySelected(None)
-        
+
     def OnGetItemText(self, item, col):
         attr = self.columns[col][1]
         cat_id = self.cats_mgr.GetCategories()[item]
@@ -499,17 +538,18 @@ class CategoryListCtrl(wx.ListCtrl,
         cat_id = self.cats_mgr.GetCategories()[item]
 
         cattr = self.cats_mgr.GetCategoryAttrs(cat_id)
-        
+
         if cattr['show']:
             c = cattr['color']
-            
+
             back_c = wx.Colour(*map(int, c.split(':')))
             text_c = wx.Colour(*ContrastColor(back_c))
         else:
             back_c = wx.SystemSettings.GetColour(wx.SYS_COLOUR_INACTIVECAPTION)
-            text_c = wx.SystemSettings.GetColour(wx.SYS_COLOUR_INACTIVECAPTIONTEXT)
+            text_c = wx.SystemSettings.GetColour(
+                wx.SYS_COLOUR_INACTIVECAPTIONTEXT)
 
-        # if it is in scope of the method, gui falls, using self solved it 
+        # if it is in scope of the method, gui falls, using self solved it
         self.l = wx.ListItemAttr(colText=text_c, colBack=back_c)
         return self.l
 
@@ -525,7 +565,7 @@ class CategoryListCtrl(wx.ListCtrl,
         cats = self.cats_mgr.GetCategories()
         cat_id = cats[cat_idx]
         showed = self.cats_mgr.GetCategoryAttrs(cat_id)['show']
-        
+
         menu = wx.Menu()
 
         item_id = wx.NewId()
@@ -546,13 +586,17 @@ class CategoryListCtrl(wx.ListCtrl,
             text = _("Show")
 
         item_id = wx.NewId()
-        menu.Append(item_id, text = text)
-        self.Bind(wx.EVT_MENU, lambda event : self._setCatAttrs(cat_id=cat_id,
-                                                                attrs={'show' : not showed}), 
-                                                                id=item_id) 
-        
+        menu.Append(item_id, text=text)
+        self.Bind(
+            wx.EVT_MENU,
+            lambda event: self._setCatAttrs(
+                cat_id=cat_id,
+                attrs={
+                    'show': not showed}),
+            id=item_id)
+
         menu.AppendSeparator()
-        
+
         item_id = wx.NewId()
         menu.Append(item_id, text=_("Move to top"))
         self.Bind(wx.EVT_MENU, self.OnMoveTop, id=item_id)
@@ -590,7 +634,7 @@ class CategoryListCtrl(wx.ListCtrl,
 
     def OnExportCatRast(self, event):
         """Export training areas"""
-        #TODO
+        # TODO
         #   GMessage(parent=self, message=_("No class raster to export."))
         #    return
 
@@ -632,7 +676,7 @@ class CategoryListCtrl(wx.ListCtrl,
         col = self.cats_mgr.GetCategoryAttrs(cat_id)['color']
         col = map(int, col.split(':'))
 
-        col_data =  wx.ColourData()
+        col_data = wx.ColourData()
         col_data.SetColour(wx.Colour(*col))
 
         dlg = wx.ColourDialog(self, col_data)
@@ -641,7 +685,7 @@ class CategoryListCtrl(wx.ListCtrl,
         if dlg.ShowModal() == wx.ID_OK:
             color = dlg.GetColourData().GetColour().Get()
             color = ':'.join(map(str, color))
-            self.cats_mgr.SetCategoryAttrs(cat_id, {"color" : color})
+            self.cats_mgr.SetCategoryAttrs(cat_id, {"color": color})
 
         dlg.Destroy()
 
@@ -653,16 +697,18 @@ class CategoryListCtrl(wx.ListCtrl,
         value = cat_attrs['opacity'] * 100
         name = cat_attrs['name']
 
-        dlg = SetOpacityDialog(self, opacity = value,
-                               title = _("Change opacity of class <%s>" % name))
+        dlg = SetOpacityDialog(self, opacity=value,
+                               title=_("Change opacity of class <%s>" % name))
 
-        dlg.applyOpacity.connect(lambda value:
-                                 self._setCatAttrs(cat_id=cat_id, attrs={'opacity' : value}))
+        dlg.applyOpacity.connect(
+            lambda value: self._setCatAttrs(
+                cat_id=cat_id, attrs={
+                    'opacity': value}))
         dlg.CentreOnParent()
 
         if dlg.ShowModal() == wx.ID_OK:
-            self._setCatAttrs(cat_id=cat_id, attrs={'opacity' : value})
-        
+            self._setCatAttrs(cat_id=cat_id, attrs={'opacity': value})
+
         dlg.Destroy()
 
     def OnRename(self, event):
@@ -676,9 +722,10 @@ class CategoryListCtrl(wx.ListCtrl,
             if dlg.ShowModal() == wx.ID_OK:
                 name = dlg.GetNewName().strip()
                 if not name:
-                    GMessage(parent=self, message=_("Empty name was inserted."))
+                    GMessage(parent=self, message=_(
+                        "Empty name was inserted."))
                 else:
-                    self.cats_mgr.SetCategoryAttrs(cat_id, {"name" : name})
+                    self.cats_mgr.SetCategoryAttrs(cat_id, {"name": name})
                     break
             else:
                 break

+ 181 - 139
gui/wxpython/iscatt/iscatt_core.py

@@ -25,7 +25,7 @@ import time
 import numpy as np
 
 # used iclass perimeters algorithm instead of convolve2d
-#from matplotlib.path import Path 
+#from matplotlib.path import Path
 #from scipy.signal import convolve2d
 
 from math import sqrt, ceil, floor
@@ -36,24 +36,27 @@ from core.gcmd import GException, GError, RunCommand
 import grass.script as grass
 
 from core_c import CreateCatRast, ComputeScatts, UpdateCatRast, \
-                   Rasterize, SC_SCATT_DATA, SC_SCATT_CONDITIONS
+    Rasterize, SC_SCATT_DATA, SC_SCATT_CONDITIONS
 
 MAX_SCATT_SIZE = 4100 * 4100
 WARN_SCATT_SIZE = 2000 * 2000
 MAX_NCELLS = 65536 * 65536
 WARN_NCELLS = 12000 * 12000
 
+
 class Core:
     """Represents scatter plot backend.
     """
+
     def __init__(self):
-        
+
         self.an_data = AnalyzedData()
 
         self.scatts_dt = ScattPlotsData(self.an_data)
         self.scatt_conds_dt = ScattPlotsCondsData(self.an_data)
 
-        self.cat_rast_updater = CatRastUpdater(self.scatts_dt, self.an_data, self)
+        self.cat_rast_updater = CatRastUpdater(
+            self.scatts_dt, self.an_data, self)
 
     def SetData(self, bands):
         """Set bands for analysis.
@@ -85,7 +88,7 @@ class Core:
         return self.an_data.GetBands()
 
     def GetScattsData(self):
-        return self.scatts_dt, self.scatt_conds_dt;
+        return self.scatts_dt, self.scatt_conds_dt
 
     def GetRegion(self):
         return self.an_data.GetRegion()
@@ -94,9 +97,9 @@ class Core:
         return self.scatts_dt.GetCatRast(cat_id)
 
     def AddScattPlots(self, scatt_ids):
-    
+
         for s_id in scatt_ids:
-            self.scatts_dt.AddScattPlot(scatt_id = s_id)
+            self.scatts_dt.AddScattPlot(scatt_id=s_id)
 
         cats_ids = self.scatts_dt.GetCategories()
         self.ComputeCatsScatts(cats_ids)
@@ -114,7 +117,7 @@ class Core:
         for k, v in bbox.iteritems():
             bbox[k] = self._validExtend(v)
 
-        arr[bbox['btm_y'] : bbox['up_y'], bbox['btm_x'] : bbox['up_x']] = value
+        arr[bbox['btm_y']: bbox['up_y'], bbox['btm_x']: bbox['up_x']] = value
 
         self.ComputeCatsScatts([cat_id])
         return cat_id
@@ -136,12 +139,12 @@ class Core:
         cats_rasts = self.scatts_dt.GetCatsRasts()
         cats_rasts_conds = self.scatts_dt.GetCatsRastsConds()
 
-        returncode, scatts = ComputeScatts(self.an_data.GetRegion(), 
-                                           scatt_conds, 
+        returncode, scatts = ComputeScatts(self.an_data.GetRegion(),
+                                           scatt_conds,
                                            bands,
-                                           len(self.GetBands()), 
-                                           scatts, 
-                                           cats_rasts_conds, 
+                                           len(self.GetBands()),
+                                           scatts,
+                                           cats_rasts_conds,
                                            cats_rasts)
 
         if returncode < 0:
@@ -149,7 +152,7 @@ class Core:
 
     def CatRastUpdater(self):
         return self.cat_rast_updater
-    
+
     def UpdateCategoryWithPolygons(self, cat_id, scatts_pols, value):
         start_time = time.clock()
 
@@ -161,7 +164,7 @@ class Core:
             if self.scatt_conds_dt.AddScattPlot(cat_id, scatt_id) < 0:
                 return False
 
-            b1, b2 = idScattToidBands(scatt_id, len(self.an_data.GetBands()))    
+            b1, b2 = idScattToidBands(scatt_id, len(self.an_data.GetBands()))
             b = self.scatts_dt.GetBandsInfo(scatt_id)
 
             region = {}
@@ -172,50 +175,52 @@ class Core:
             region['e'] = b['b1']['max'] + 0.5
 
             arr = self.scatt_conds_dt.GetValuesArr(cat_id, scatt_id)
-            arr = Rasterize(polygon=coords, 
-                            rast=arr, 
-                            region=region, 
+            arr = Rasterize(polygon=coords,
+                            rast=arr,
+                            region=region,
                             value=value)
 
             # previous way of rasterization / used scipy
-            #raster_pol = RasterizePolygon(coords, b['b1']['range'], b['b1']['min'], 
-            #                                      b['b2']['range'], b['b2']['min'])
+            # raster_pol = RasterizePolygon(coords, b['b1']['range'], b['b1']['min'],
+            # b['b2']['range'], b['b2']['min'])
 
-            #raster_ind = np.where(raster_pol > 0) 
+            #raster_ind = np.where(raster_pol > 0)
             #arr = self.scatt_conds_dt.GetValuesArr(cat_id, scatt_id)
 
             #arr[raster_ind] = value
-            #arr.flush()
-        
+            # arr.flush()
+
         self.ComputeCatsScatts([cat_id])
         return cat_id
 
     def ExportCatRast(self, cat_id, rast_name):
 
-        cat_rast = self.scatts_dt.GetCatRast(cat_id);
+        cat_rast = self.scatts_dt.GetCatRast(cat_id)
         if not cat_rast:
             return 1
-        
-        return RunCommand("g.copy", 
+
+        return RunCommand("g.copy",
                           raster=cat_rast + ',' + rast_name,
                           getErrorMsg=True,
                           overwrite=True)
 
     def _validExtend(self, val):
-        #TODO do it general
-        if  val > 255:
+        # TODO do it general
+        if val > 255:
             val = 255
         elif val < 0:
             val = 0
 
         return val
 
+
 class CatRastUpdater:
     """Update backend data structures according to selected areas in mapwindow.
     """
+
     def __init__(self, scatts_dt, an_data, core):
         self.scatts_dt = scatts_dt
-        self.an_data = an_data # TODO may be confusing
+        self.an_data = an_data  # TODO may be confusing
         self.core = core
         self.vectMap = None
 
@@ -223,7 +228,8 @@ class CatRastUpdater:
         self.vectMap = vectMap
 
     def SyncWithMap(self):
-        #TODO possible optimization - bbox only of vertex and its two neighbours
+        # TODO possible optimization - bbox only of vertex and its two
+        # neighbours
 
         region = self.an_data.GetRegion()
 
@@ -238,23 +244,25 @@ class CatRastUpdater:
         for cat_id in self.scatts_dt.GetCategories():
             if cat_id == 0:
                 continue
-            
-            cat = [{1 : [cat_id]}]
+
+            cat = [{1: [cat_id]}]
             self._updateCatRast(bbox, cat, updated_cats)
 
         return updated_cats
 
-    def EditedFeature(self, new_bboxs, new_areas_cats, old_bboxs, old_areas_cats):
-        #TODO possible optimization - bbox only of vertex and its two neighbours
+    def EditedFeature(self, new_bboxs, new_areas_cats,
+                      old_bboxs, old_areas_cats):
+        # TODO possible optimization - bbox only of vertex and its two
+        # neighbours
 
         bboxs = old_bboxs + new_bboxs
-        areas_cats = old_areas_cats + new_areas_cats 
+        areas_cats = old_areas_cats + new_areas_cats
 
         updated_cats = []
 
         for i in range(len(areas_cats)):
             self._updateCatRast(bboxs[i], areas_cats[i], updated_cats)
-        
+
         return updated_cats
 
     def _updateCatRast(self, bbox, areas_cats, updated_cats):
@@ -266,7 +274,7 @@ class CatRastUpdater:
                 continue
 
             layer = areas_cats[c].keys()[0]
-            cat =  areas_cats[c][layer][0]
+            cat = areas_cats[c][layer][0]
 
             if cat in rasterized_cats:
                 continue
@@ -276,34 +284,38 @@ class CatRastUpdater:
 
             grass_region = self._create_grass_region_env(bbox)
 
-            #TODO hack check if raster exists?
+            # TODO hack check if raster exists?
             patch_rast = "temp_scatt_patch_%d" % (os.getpid())
             self._rasterize(grass_region, layer, cat, patch_rast)
 
             region = self.an_data.GetRegion()
-            ret = UpdateCatRast(patch_rast, region, self.scatts_dt.GetCatRastCond(cat))
+            ret = UpdateCatRast(
+                patch_rast,
+                region,
+                self.scatts_dt.GetCatRastCond(cat))
             if ret < 0:
-                GException(_("Patching category raster conditions file failed."))            
+                GException(
+                    _("Patching category raster conditions file failed."))
             RunCommand("g.remove", flags='f', type='raster', name=patch_rast)
 
     def _rasterize(self, grass_region, layer, cat, out_rast):
 
-        #TODO different thread may be problem when user edits map
+        # TODO different thread may be problem when user edits map
         environs = os.environ.copy()
         environs['GRASS_VECTOR_TEMPORARY'] = '1'
 
         ret, text, msg = RunCommand("v.category",
                                     input=self.vectMap,
-                                    getErrorMsg = True,
+                                    getErrorMsg=True,
                                     option='report',
                                     read=True,
                                     env=environs)
 
         ret, text, msg = RunCommand("v.build",
-                                    map = self.vectMap,
-                                    getErrorMsg = True,
-                                    read = True,
-                                    env = environs)
+                                    map=self.vectMap,
+                                    getErrorMsg=True,
+                                    read=True,
+                                    env=environs)
 
         if ret != 0:
             GException(_("v.build failed:\n%s" % msg))
@@ -313,15 +325,15 @@ class CatRastUpdater:
         environs['GRASS_VECTOR_TEMPORARY'] = '1'
 
         ret, text, msg = RunCommand("v.to.rast",
-                                    input = self.vectMap,
-                                    use = "cat",
-                                    layer = str(layer),
-                                    cat = str(cat),
-                                    output = out_rast,
-                                    getErrorMsg = True,
-                                    read = True,
-                                    overwrite = True,
-                                    env = environs)
+                                    input=self.vectMap,
+                                    use="cat",
+                                    layer=str(layer),
+                                    cat=str(cat),
+                                    output=out_rast,
+                                    getErrorMsg=True,
+                                    read=True,
+                                    overwrite=True,
+                                    env=environs)
 
         if ret != 0:
             GException(_("v.to.rast failed:\n%s" % msg))
@@ -336,40 +348,46 @@ class CatRastUpdater:
         elif bbox["maxy"] >= r["n"]:
             new_r["n"] = bbox["maxy"]
         else:
-            new_r["n"] = ceil((bbox["maxy"] - r["s"]) / r["nsres"]) * r["nsres"] + r["s"]
+            new_r["n"] = ceil(
+                (bbox["maxy"] - r["s"]) / r["nsres"]) * r["nsres"] + r["s"]
 
         if bbox["miny"] >= r["n"]:
             return 0
         elif bbox["miny"] <= r["s"]:
             new_r["s"] = bbox["miny"]
         else:
-            new_r["s"] = floor((bbox["miny"] - r["s"]) / r["nsres"]) * r["nsres"] + r["s"]
+            new_r["s"] = floor(
+                (bbox["miny"] - r["s"]) / r["nsres"]) * r["nsres"] + r["s"]
 
         if bbox["maxx"] <= r["w"]:
             return 0
         elif bbox["maxx"] >= r["e"]:
             new_r["e"] = bbox["maxx"]
         else:
-            new_r["e"] = ceil((bbox["maxx"] - r["w"]) / r["ewres"]) * r["ewres"] + r["w"]
+            new_r["e"] = ceil(
+                (bbox["maxx"] - r["w"]) / r["ewres"]) * r["ewres"] + r["w"]
 
         if bbox["minx"] >= r["e"]:
             return 0
         elif bbox["minx"] <= r["w"]:
             new_r["w"] = bbox["minx"]
         else:
-            new_r["w"] = floor((bbox["minx"] - r["w"]) / r["ewres"]) * r["ewres"] + r["w"]
+            new_r["w"] = floor(
+                (bbox["minx"] - r["w"]) / r["ewres"]) * r["ewres"] + r["w"]
 
-        #TODO check regions resolution
+        # TODO check regions resolution
         new_r["nsres"] = r["nsres"]
         new_r["ewres"] = r["ewres"]
 
-        return {"GRASS_REGION" :  grass.region_env(**new_r)}
+        return {"GRASS_REGION": grass.region_env(**new_r)}
+
 
 class AnalyzedData:
     """Represents analyzed data (bands, region).
     """
+
     def __init__(self):
-        
+
         self.bands = []
         self.bands_info = {}
 
@@ -393,9 +411,9 @@ class AnalyzedData:
 
             if i is None:
                 GException("raster %s is not CELL type" % (b))
-    
+
             self.bands_info[b] = i
-            #TODO check size of raster
+            # TODO check size of raster
 
         return True
 
@@ -406,22 +424,24 @@ class AnalyzedData:
         band = self.bands[band_id]
         return self.bands_info[band]
 
+
 class ScattPlotsCondsData:
     """Data structure for selected areas in scatter plot(condtions).
     """
+
     def __init__(self, an_data):
 
         self.an_data = an_data
 
-        #TODO
+        # TODO
         self.max_n_cats = 10
-    
+
         self.dtype = 'uint8'
-        self.type = 1;
+        self.type = 1
         self.CleanUp()
 
     def CleanUp(self):
-    
+
         self.cats = {}
 
         self.n_scatts = -1
@@ -434,10 +454,10 @@ class ScattPlotsCondsData:
 
         self.CleanUp()
 
-        self.n_scatts =  (n_bands - 1) * n_bands / 2;
+        self.n_scatts = (n_bands - 1) * n_bands / 2
         self.n_bands = n_bands
 
-        self.AddCategory(cat_id = 0)
+        self.AddCategory(cat_id=0)
 
     def AddCategory(self, cat_id):
 
@@ -464,27 +484,36 @@ class ScattPlotsCondsData:
 
     def GetCatScatts(self, cat_id):
 
-        if not self.cats.has_key(cat_id):
+        if cat_id not in self.cats:
             return False
 
         return self.cats[cat_id].keys()
 
-
     def AddScattPlot(self, cat_id, scatt_id):
 
-        if not self.cats.has_key(cat_id):
+        if cat_id not in self.cats:
             return -1
 
-        if self.cats[cat_id].has_key(scatt_id):
+        if scatt_id in self.cats[cat_id]:
             return 0
 
         b_i = self.GetBandsInfo(scatt_id)
 
-        shape = (b_i['b2']['max'] - b_i['b2']['min'] + 1, b_i['b1']['max'] - b_i['b1']['min'] + 1)
+        shape = (
+            b_i['b2']['max'] -
+            b_i['b2']['min'] +
+            1,
+            b_i['b1']['max'] -
+            b_i['b1']['min'] +
+            1)
 
-        np_vals = np.memmap(grass.tempfile(), dtype=self.dtype, mode='w+', shape=shape)
+        np_vals = np.memmap(
+            grass.tempfile(),
+            dtype=self.dtype,
+            mode='w+',
+            shape=shape)
 
-        self.cats[cat_id][scatt_id] = {'np_vals' : np_vals}
+        self.cats[cat_id][scatt_id] = {'np_vals': np_vals}
 
         return 1
 
@@ -494,17 +523,17 @@ class ScattPlotsCondsData:
         b1_info = self.an_data.GetBandInfo(b1)
         b2_info = self.an_data.GetBandInfo(b2)
 
-        bands_info = {'b1' : b1_info,
-                      'b2' : b2_info}
+        bands_info = {'b1': b1_info,
+                      'b2': b2_info}
 
         return bands_info
 
     def DeleScattPlot(self, cat_id, scatt_id):
 
-        if not self.cats.has_key(cat_id):
+        if cat_id not in self.cats:
             return False
 
-        if not self.cats[cat_id].has_key(scatt_id):
+        if scatt_id not in self.cats[cat_id]:
             return False
 
         del self.cats[cat_id][scatt_id]
@@ -512,63 +541,68 @@ class ScattPlotsCondsData:
 
     def GetValuesArr(self, cat_id, scatt_id):
 
-        if not self.cats.has_key(cat_id):
+        if cat_id not in self.cats:
             return None
 
-        if not self.cats[cat_id].has_key(scatt_id):
+        if scatt_id not in self.cats[cat_id]:
             return None
 
         return self.cats[cat_id][scatt_id]['np_vals']
 
     def GetData(self, requested_dt):
-        
+
         cats = {}
         for cat_id, scatt_ids in requested_dt.iteritems():
-            if not cats.has_key(cat_id):
+            if cat_id not in cats:
                 cats[cat_id] = {}
             for scatt_id in scatt_ids:
-                # if key is missing condition is always True (full scatter plor is computed)
-                if self.cats[cat_id].has_key(scatt_id):
-                    cats[cat_id][scatt_id] = {'np_vals' : self.cats[cat_id][scatt_id]['np_vals'],
-                                              'bands_info' : self.GetBandsInfo(scatt_id)}
-                        
+                # if key is missing condition is always True (full scatter plor
+                # is computed)
+                if scatt_id in self.cats[cat_id]:
+                    cats[cat_id][scatt_id] = {
+                        'np_vals': self.cats[cat_id][scatt_id]['np_vals'],
+                        'bands_info': self.GetBandsInfo(scatt_id)}
+
         return cats
 
     def SetData(self, cats):
-        
-        for cat_id, scatt_ids in cats.iteritems():            
+
+        for cat_id, scatt_ids in cats.iteritems():
             for scatt_id in scatt_ids:
-                # if key is missing condition is always True (full scatter plor is computed)
-                if self.cats[cat_id].has_key(scatt_id):
-                    self.cats[cat_id][scatt_id]['np_vals'] = cats[cat_id][scatt_id]['np_vals']
+                # if key is missing condition is always True (full scatter plor
+                # is computed)
+                if scatt_id in self.cats[cat_id]:
+                    self.cats[cat_id][scatt_id]['np_vals'] = cats[
+                        cat_id][scatt_id]['np_vals']
 
-    def GetScatt(self, scatt_id, cats_ids = None):
+    def GetScatt(self, scatt_id, cats_ids=None):
         scatts = {}
         for cat_id in self.cats.iterkeys():
             if cats_ids and cat_id not in cats_ids:
                 continue
-            if not self.cats[cat_id].has_key(scatt_id):
+            if scatt_id not in self.cats[cat_id]:
                 continue
 
-            scatts[cat_id] = {'np_vals' : self.cats[cat_id][scatt_id]['np_vals'],
-                              'bands_info' : self.GetBandsInfo(scatt_id)}
+            scatts[cat_id] = {'np_vals': self.cats[cat_id][scatt_id][
+                'np_vals'], 'bands_info': self.GetBandsInfo(scatt_id)}
         return scatts
 
-                   
+
 class ScattPlotsData(ScattPlotsCondsData):
     """Data structure for computed points (classes) in scatter plots.\
     """
+
     def __init__(self, an_data):
 
         self.cats_rasts = {}
-        self.cats_rasts_conds = {}    
-        self.scatts_ids = []    
+        self.cats_rasts_conds = {}
+        self.scatts_ids = []
 
         ScattPlotsCondsData.__init__(self, an_data)
 
         self.dtype = 'uint32'
 
-        #TODO
+        # TODO
         self.type = 0
 
     def AddCategory(self, cat_id):
@@ -584,7 +618,8 @@ class ScattPlotsData(ScattPlotsCondsData):
             self.cats_rasts[cat_id] = None
         else:
             self.cats_rasts_conds[cat_id] = grass.tempfile()
-            self.cats_rasts[cat_id] = "temp_cat_rast_%d_%d" % (cat_id, os.getpid())
+            self.cats_rasts[cat_id] = "temp_cat_rast_%d_%d" % (
+                cat_id, os.getpid())
             region = self.an_data.GetRegion()
             CreateCatRast(region, self.cats_rasts_conds[cat_id])
 
@@ -593,7 +628,7 @@ class ScattPlotsData(ScattPlotsCondsData):
     def DeleteCategory(self, cat_id):
 
         ScattPlotsCondsData.DeleteCategory(self, cat_id)
-        
+
         grass.try_remove(self.cats_rasts_conds[cat_id])
         del self.cats_rasts_conds[cat_id]
 
@@ -604,26 +639,26 @@ class ScattPlotsData(ScattPlotsCondsData):
         return True
 
     def AddScattPlot(self, scatt_id):
-        
+
         if scatt_id in self.scatts_ids:
             return False
 
         self.scatts_ids.append(scatt_id)
         for cat_id in self.cats.iterkeys():
-                ScattPlotsCondsData.AddScattPlot(self, cat_id, scatt_id)
-                self.cats[cat_id][scatt_id]['ellipse'] = None
+            ScattPlotsCondsData.AddScattPlot(self, cat_id, scatt_id)
+            self.cats[cat_id][scatt_id]['ellipse'] = None
 
         return True
 
     def DeleteScatterPlot(self, scatt_id):
-        
+
         if scatt_id not in self.scatts_ids:
             return False
 
         self.scatts_ids.remove(scatt_id)
 
         for cat_id in self.cats.iterkeys():
-                ScattPlotsCondsData.DeleteScattPlot(self, cat_id, scatt_id)
+            ScattPlotsCondsData.DeleteScattPlot(self, cat_id, scatt_id)
 
         return True
 
@@ -664,36 +699,36 @@ class ScattPlotsData(ScattPlotsCondsData):
 
         x_diff = (x - x_avg)
         y_diff = (y - y_avg)
-        
-        x_diff = (x - x_avg) 
-        y_diff = (y - y_avg) 
+
+        x_diff = (x - x_avg)
+        y_diff = (y - y_avg)
 
         diffs = x_diff * y_diff.T
         cov = np.dot(diffs, weights) / (np.sum(weights) - 1)
 
         diffs = x_diff * x_diff.T
-        var_x = np.dot(diffs, weights) /  (np.sum(weights) - 1)
-        
+        var_x = np.dot(diffs, weights) / (np.sum(weights) - 1)
+
         diffs = y_diff * y_diff.T
-        var_y = np.dot(diffs, weights) /  (np.sum(weights) - 1)
+        var_y = np.dot(diffs, weights) / (np.sum(weights) - 1)
 
-        cov = np.array([[var_x, cov],[cov, var_y]])
+        cov = np.array([[var_x, cov], [cov, var_y]])
 
         def eigsorted(cov):
             vals, vecs = np.linalg.eigh(cov)
             order = vals.argsort()[::-1]
-            return vals[order], vecs[:,order]
+            return vals[order], vecs[:, order]
 
         vals, vecs = eigsorted(cov)
-        theta = np.degrees(np.arctan2(*vecs[:,0][::-1]))
+        theta = np.degrees(np.arctan2(*vecs[:, 0][::-1]))
 
         # Width and height are "full" widths, not radius
         width, height = 2 * nstd * np.sqrt(vals)
 
-        ellipse = {'pos' : pos, 
-                   'width' : width,
-                   'height' : height,
-                   'theta' : theta}
+        ellipse = {'pos': pos,
+                   'width': width,
+                   'height': height,
+                   'theta': theta}
 
         del data
         del flatten_data
@@ -704,9 +739,9 @@ class ScattPlotsData(ScattPlotsCondsData):
 
     def CleanUp(self):
 
-        ScattPlotsCondsData.CleanUp(self)        
+        ScattPlotsCondsData.CleanUp(self)
         for tmp in self.cats_rasts_conds.itervalues():
-            grass.try_remove(tmp) 
+            grass.try_remove(tmp)
         for tmp in self.cats_rasts.itervalues():
             RunCommand("g.remove", flags='f',
                        type='raster', name=tmp,
@@ -716,7 +751,7 @@ class ScattPlotsData(ScattPlotsCondsData):
         self.cats_rasts_conds = {}
 
     def GetCatRast(self, cat_id):
-        if self.cats_rasts.has_key(cat_id):
+        if cat_id in self.cats_rasts:
             return self.cats_rasts[cat_id]
         return None
 
@@ -754,7 +789,7 @@ def RasterizePolygon(pol, height, min_h, width, min_w):
     nx = width
     ny = height
 
-    x, y =  np.meshgrid(np.arange(-0.5 + min_w, nx + 0.5 + min_w, dtype=float), 
+    x, y =  np.meshgrid(np.arange(-0.5 + min_w, nx + 0.5 + min_w, dtype=float),
                         np.arange(-0.5 + min_h, ny + 0.5 + min_h, dtype=float))
     x, y = x.flatten(), y.flatten()
 
@@ -772,40 +807,46 @@ def RasterizePolygon(pol, height, min_h, width, min_w):
     return raster
 """
 
+
 def idScattToidBands(scatt_id, n_bands):
     """Get bands ids from scatter plot id."""
     n_b1 = n_bands - 1
 
-    band_1 = (int) ((2 * n_b1 + 1 - sqrt(((2 * n_b1 + 1) * (2 * n_b1 + 1) - 8 * scatt_id))) / 2)
+    band_1 = (int)(
+        (2 * n_b1 + 1 - sqrt(((2 * n_b1 + 1) * (2 * n_b1 + 1) - 8 * scatt_id))) / 2)
 
     band_2 = scatt_id - (band_1 * (2 * n_b1 + 1) - band_1 * band_1) / 2 + band_1 + 1
 
     return band_1, band_2
 
+
 def idBandsToidScatt(band_1_id, band_2_id, n_bands):
     """Get scatter plot id from band ids."""
-    if band_2_id <  band_1_id:
+    if band_2_id < band_1_id:
         tmp = band_1_id
         band_1_id = band_2_id
         band_2_id = tmp
 
     n_b1 = n_bands - 1
 
-    scatt_id = (band_1_id * (2 * n_b1 + 1) - band_1_id * band_1_id) / 2 + band_2_id - band_1_id - 1
+    scatt_id = (
+        band_1_id * (2 * n_b1 + 1) - band_1_id * band_1_id) / 2 + band_2_id - band_1_id - 1
 
     return scatt_id
 
+
 def GetRegion():
     ret, region, msg = RunCommand("g.region",
-                                  flags = "gp",
-                                  getErrorMsg = True,
-                                  read = True)
+                                  flags="gp",
+                                  getErrorMsg=True,
+                                  read=True)
 
     if ret != 0:
         raise GException("g.region failed:\n%s" % msg)
 
     return _parseRegion(region)
 
+
 def _parseRegion(region_str):
 
     region = {}
@@ -821,18 +862,19 @@ def _parseRegion(region_str):
 
     return region
 
+
 def GetRasterInfo(rast):
     ret, out, msg = RunCommand("r.info",
-                                map = rast,
-                                flags = "rg",
-                                getErrorMsg = True,
-                                read = True)
+                               map=rast,
+                               flags="rg",
+                               getErrorMsg=True,
+                               read=True)
 
-    if  ret != 0:
+    if ret != 0:
         raise GException("r.info failed:\n%s" % msg)
 
     out = out.splitlines()
-    raster_info = {} 
+    raster_info = {}
 
     for b in out:
         if not b.strip():

File diff ditekan karena terlalu besar
+ 307 - 228
gui/wxpython/iscatt/plots.py


+ 144 - 131
gui/wxpython/iscatt/toolbars.py

@@ -22,16 +22,18 @@ from core.gcmd import GException, GError, RunCommand
 from iscatt.iscatt_core import idBandsToidScatt
 from iscatt.dialogs import SettingsDialog
 
+
 class MainToolbar(BaseToolbar):
     """Main toolbar
     """
+
     def __init__(self, parent, scatt_mgr, opt_tools=None):
         BaseToolbar.__init__(self, parent)
         self.scatt_mgr = scatt_mgr
         self.opt_tools = opt_tools
 
         self.InitToolbar(self._toolbarData())
-        
+
         # realize the toolbar
         self.Realize()
         self.scatt_mgr.modeSet.connect(self.ModeSet)
@@ -39,81 +41,90 @@ class MainToolbar(BaseToolbar):
     def _toolbarData(self):
 
         icons = {
-                'selectGroup' : MetaIcon(img = 'layer-group-add',
-                                 label = _('Select imagery group')),
-                'settings'   : BaseIcons['settings'].SetLabel( _('Settings')),
-                'help'       : MetaIcon(img = 'help',
-                                         label = _('Show manual')),
-                'add_scatt_pl'  : MetaIcon(img = 'layer-raster-analyze',
-                                            label = _('Add scatter plot')),
-                'selCatPol'  : MetaIcon(img = 'polygon',
-                                      label = _('Select area with polygon')),
-                'pan'        : MetaIcon(img = 'pan',
-                                         label = _('Pan mode for scatter plots')),
-                'zoomIn'     : MetaIcon(img = 'zoom-in',
-                                        label = _('Zoom mode for scatter plots (left mouse button, wheel)')),
-                'zoomExtent' : MetaIcon(img = 'zoom-extent',
-                                       label = _('Zoom to scatter plot data extend mode (click on scatter plot for zooming to extend)')),
-                'cats_mgr' : MetaIcon(img = 'table-manager',
-                                          label = _('Show/hide class manager'))
-                }
-            
+            'selectGroup': MetaIcon(
+                img='layer-group-add',
+                label=_('Select imagery group')),
+            'settings': BaseIcons['settings'].SetLabel(
+                _('Settings')),
+            'help': MetaIcon(
+                img='help',
+                label=_('Show manual')),
+            'add_scatt_pl': MetaIcon(
+                img='layer-raster-analyze',
+                label=_('Add scatter plot')),
+            'selCatPol': MetaIcon(
+                img='polygon',
+                label=_('Select area with polygon')),
+            'pan': MetaIcon(
+                img='pan',
+                label=_('Pan mode for scatter plots')),
+            'zoomIn': MetaIcon(
+                img='zoom-in',
+                label=_('Zoom mode for scatter plots (left mouse button, wheel)')),
+            'zoomExtent': MetaIcon(
+                img='zoom-extent',
+                label=_('Zoom to scatter plot data extend mode (click on scatter plot for zooming to extend)')),
+            'cats_mgr': MetaIcon(
+                img='table-manager',
+                label=_('Show/hide class manager'))}
+
         tools = [
-                    ('add_scatt', icons["add_scatt_pl"],
-                    lambda event : self.scatt_mgr.AddScattPlot()),
-                    (None, ),
-                    ("cats_mgr", icons['cats_mgr'],
-                    lambda event: self.parent.ShowCategoryPanel(event.Checked()), wx.ITEM_CHECK),
-                    (None, ),
-                    ("pan", icons["pan"],
-                    lambda event: self.SetPloltsMode(event, 'pan'),
-                    wx.ITEM_CHECK),
-                    ("zoom", icons["zoomIn"],
-                    lambda event: self.SetPloltsMode(event, 'zoom'),
-                    wx.ITEM_CHECK),
-                    ("zoom_extend", icons["zoomExtent"],
-                    lambda event: self.SetPloltsMode(event, 'zoom_extend'),
-                    wx.ITEM_CHECK),
-                    (None, ),
-                    ('sel_pol_mode', icons['selCatPol'],
-                    self.ActivateSelectionPolygonMode,
-                    wx.ITEM_CHECK),
-                    (None, ),
-                    ('settings', icons["settings"],
-                    self.OnSettings),
-                    ('help', icons["help"],
-                     self.OnHelp)                    
-                ]
+            ('add_scatt', icons["add_scatt_pl"],
+             lambda event: self.scatt_mgr.AddScattPlot()),
+            (None,),
+            ("cats_mgr", icons['cats_mgr'],
+             lambda event: self.parent.ShowCategoryPanel(event.Checked()),
+             wx.ITEM_CHECK),
+            (None,),
+            ("pan", icons["pan"],
+             lambda event: self.SetPloltsMode(event, 'pan'),
+             wx.ITEM_CHECK),
+            ("zoom", icons["zoomIn"],
+             lambda event: self.SetPloltsMode(event, 'zoom'),
+             wx.ITEM_CHECK),
+            ("zoom_extend", icons["zoomExtent"],
+             lambda event: self.SetPloltsMode(event, 'zoom_extend'),
+             wx.ITEM_CHECK),
+            (None,),
+            ('sel_pol_mode', icons['selCatPol'],
+             self.ActivateSelectionPolygonMode, wx.ITEM_CHECK),
+            (None,),
+            ('settings', icons["settings"],
+             self.OnSettings),
+            ('help', icons["help"],
+             self.OnHelp)]
 
         if self.opt_tools and "add_group" in self.opt_tools:
             tools.insert(0, ("selectGroup", icons['selectGroup'],
-                             lambda event : self.scatt_mgr.SetData()))
+                             lambda event: self.scatt_mgr.SetData()))
 
         return self._getToolbarData(tools)
 
-    def GetToolId(self, toolName): #TODO can be useful in base
-        return vars(self)[toolName]            
+    def GetToolId(self, toolName):  # TODO can be useful in base
+        return vars(self)[toolName]
 
     def SetPloltsMode(self, event, tool_name):
         self.scatt_mgr.modeSet.disconnect(self.ModeSet)
-        if event.Checked()  == True:
-            for i_tool_data in  self._data:
+        if event.Checked() == True:
+            for i_tool_data in self._data:
                 i_tool_name = i_tool_data[0]
-                if not i_tool_name or i_tool_name in ["cats_mgr", "sel_pol_mode"]:
+                if not i_tool_name or i_tool_name in [
+                        "cats_mgr", "sel_pol_mode"]:
                     continue
                 if i_tool_name == tool_name:
                     continue
                 i_tool_id = vars(self)[i_tool_name]
                 self.ToggleTool(i_tool_id, False)
 
-            self.scatt_mgr.SetPlotsMode(mode = tool_name)
+            self.scatt_mgr.SetPlotsMode(mode=tool_name)
         else:
-            self.scatt_mgr.SetPlotsMode(mode = None)
+            self.scatt_mgr.SetPlotsMode(mode=None)
         self.scatt_mgr.modeSet.connect(self.ModeSet)
 
     def ActivateSelectionPolygonMode(self, event):
 
-        activated = self.scatt_mgr.ActivateSelectionPolygonMode(event.Checked())
+        activated = self.scatt_mgr.ActivateSelectionPolygonMode(
+            event.Checked())
         self.parent.ShowPlotEditingToolbar(activated)
 
         i_tool_id = vars(self)['sel_pol_mode']
@@ -123,33 +134,35 @@ class MainToolbar(BaseToolbar):
         self.UnsetMode()
 
     def UnsetMode(self):
-        for i_tool_data in  self._data:
-                i_tool_name = i_tool_data[0]
-                if not i_tool_name or i_tool_name in ["cats_mgr", "sel_pol_mode"]:
-                    continue
-                i_tool_id = vars(self)[i_tool_name]
-                self.ToggleTool(i_tool_id, False)
+        for i_tool_data in self._data:
+            i_tool_name = i_tool_data[0]
+            if not i_tool_name or i_tool_name in ["cats_mgr", "sel_pol_mode"]:
+                continue
+            i_tool_id = vars(self)[i_tool_name]
+            self.ToggleTool(i_tool_id, False)
 
     def OnSettings(self, event):
-        dlg = SettingsDialog(parent=self, id=wx.ID_ANY, 
-                             title=_('Settings'), scatt_mgr = self.scatt_mgr)
-        
+        dlg = SettingsDialog(parent=self, id=wx.ID_ANY,
+                             title=_('Settings'), scatt_mgr=self.scatt_mgr)
+
         dlg.ShowModal()
         dlg.Destroy()
 
-    def OnHelp(self, event) :
-            RunCommand('g.manual',
-                       entry = 'wxGUI.iscatt')
+    def OnHelp(self, event):
+        RunCommand('g.manual',
+                   entry='wxGUI.iscatt')
+
 
 class EditingToolbar(BaseToolbar):
     """Main toolbar
     """
+
     def __init__(self, parent, scatt_mgr):
         BaseToolbar.__init__(self, parent)
         self.scatt_mgr = scatt_mgr
 
         self.InitToolbar(self._toolbarData())
-        
+
         # realize the toolbar
         self.Realize()
         self.scatt_mgr.modeSet.connect(self.ModeSet)
@@ -158,55 +171,54 @@ class EditingToolbar(BaseToolbar):
         """Toolbar data
         """
         self.icons = {
-            'sel_add'         : MetaIcon(img = 'layer-add',
-                                         label = _('Include selected area to class'),
-                                         desc = _('Include selected area to class')),
-            'sel_remove'      : MetaIcon(img = 'layer-remove',
-                                         label = _('Exclude selected area from class'),
-                                         desc = _('Exclude selected area from class')),
-            'addVertex'       : MetaIcon(img = 'vertex-create',
-                                         label = _('Add new vertex'),
-                                         desc = _('Add new vertex to polygon boundary scatter plot')),
-            'editLine'        : MetaIcon(img = 'polygon-create',
-                                         label = _('Create selection polygon'),
-                                         desc = _('Add new vertex between last and first points of the boundary')),
-            'moveVertex'      : MetaIcon(img = 'vertex-move',
-                                         label = _('Move vertex'),
-                                         desc = _('Move boundary vertex')),
-            'removeVertex'    : MetaIcon(img = 'vertex-delete',
-                                         label = _('Remove vertex'),
-                                         desc = _('Remove boundary vertex')),
-            'delete'        : MetaIcon(img = 'polygon-delete',
-                                       label = _("Remove polygon (click on scatter plot for removing it's polygon)")),
-            }
-
-        return self._getToolbarData((
-                                    ("sel_add", self.icons["sel_add"],
-                                     lambda event: self.scatt_mgr.ProcessSelectionPolygons('add')),
-                                     ("sel_remove", self.icons['sel_remove'],
-                                     lambda event: self.scatt_mgr.ProcessSelectionPolygons('remove')),
-                                     (None, ),
-                                     ("add_vertex", self.icons["editLine"],
-                                     lambda event: self.SetMode(event, 'add_vertex'),
-                                     wx.ITEM_CHECK),
-                                     ("add_boundary_vertex", self.icons['addVertex'],
-                                     lambda event: self.SetMode(event, 'add_boundary_vertex'),
-                                     wx.ITEM_CHECK),
-                                     ("move_vertex", self.icons["moveVertex"],
-                                     lambda event: self.SetMode(event, 'move_vertex'),
-                                     wx.ITEM_CHECK),
-                                     ('delete_vertex', self.icons['removeVertex'],
-                                     lambda event: self.SetMode(event, 'delete_vertex'),
-                                     wx.ITEM_CHECK),
-                                     ('remove_polygon', self.icons['delete'],
-                                     lambda event: self.SetMode(event, 'remove_polygon'),
-                                     wx.ITEM_CHECK)
-                                    ))
+            'sel_add': MetaIcon(img='layer-add',
+                                label=_('Include selected area to class'),
+                                desc=_('Include selected area to class')),
+            'sel_remove': MetaIcon(img='layer-remove',
+                                   label=_('Exclude selected area from class'),
+                                   desc=_('Exclude selected area from class')),
+            'addVertex': MetaIcon(img='vertex-create',
+                                  label=_('Add new vertex'),
+                                  desc=_('Add new vertex to polygon boundary scatter plot')),
+            'editLine': MetaIcon(img='polygon-create',
+                                 label=_('Create selection polygon'),
+                                 desc=_('Add new vertex between last and first points of the boundary')),
+            'moveVertex': MetaIcon(img='vertex-move',
+                                   label=_('Move vertex'),
+                                   desc=_('Move boundary vertex')),
+            'removeVertex': MetaIcon(img='vertex-delete',
+                                     label=_('Remove vertex'),
+                                     desc=_('Remove boundary vertex')),
+            'delete': MetaIcon(img='polygon-delete',
+                               label=_("Remove polygon (click on scatter plot for removing it's polygon)")),
+        }
+
+        return self._getToolbarData(
+            (("sel_add", self.icons["sel_add"],
+              lambda event: self.scatt_mgr.ProcessSelectionPolygons('add')),
+             ("sel_remove", self.icons['sel_remove'],
+              lambda event: self.scatt_mgr.ProcessSelectionPolygons('remove')),
+             (None,),
+             ("add_vertex", self.icons["editLine"],
+              lambda event: self.SetMode(event, 'add_vertex'),
+              wx.ITEM_CHECK),
+             ("add_boundary_vertex", self.icons['addVertex'],
+              lambda event: self.SetMode(event, 'add_boundary_vertex'),
+              wx.ITEM_CHECK),
+             ("move_vertex", self.icons["moveVertex"],
+              lambda event: self.SetMode(event, 'move_vertex'),
+              wx.ITEM_CHECK),
+             ('delete_vertex', self.icons['removeVertex'],
+              lambda event: self.SetMode(event, 'delete_vertex'),
+              wx.ITEM_CHECK),
+             ('remove_polygon', self.icons['delete'],
+              lambda event: self.SetMode(event, 'remove_polygon'),
+              wx.ITEM_CHECK)))
 
     def SetMode(self, event, tool_name):
         self.scatt_mgr.modeSet.disconnect(self.ModeSet)
         if event.Checked() == True:
-            for i_tool_data in  self._data:
+            for i_tool_data in self._data:
                 i_tool_name = i_tool_data[0]
                 if not i_tool_name:
                     continue
@@ -225,19 +237,21 @@ class EditingToolbar(BaseToolbar):
             self.UnsetMode()
 
     def UnsetMode(self):
-        for i_tool_data in  self._data:
-                i_tool_name = i_tool_data[0]
-                if not i_tool_name:
-                    continue
-                i_tool_id = vars(self)[i_tool_name]
-                self.ToggleTool(i_tool_id, False)
+        for i_tool_data in self._data:
+            i_tool_name = i_tool_data[0]
+            if not i_tool_name:
+                continue
+            i_tool_id = vars(self)[i_tool_name]
+            self.ToggleTool(i_tool_id, False)
 
     def GetToolId(self, toolName):
         return vars(self)[toolName]
 
+
 class CategoryToolbar(BaseToolbar):
     """Main toolbar
     """
+
     def __init__(self, parent, scatt_mgr, cats_list):
         BaseToolbar.__init__(self, parent)
         self.scatt_mgr = scatt_mgr
@@ -245,7 +259,7 @@ class CategoryToolbar(BaseToolbar):
         self.cats_list = cats_list
 
         self.InitToolbar(self._toolbarData())
-        
+
         # realize the toolbar
         self.Realize()
 
@@ -253,15 +267,14 @@ class CategoryToolbar(BaseToolbar):
         """Toolbar data
         """
         self.icons = {
-            'add_class'     : MetaIcon(img = 'layer-add',
-                                       label = _('Add class')),
-            'remove_class'  : MetaIcon(img = 'layer-remove',
-                                       label = _('Remove selected class'))
-            }
-
-        return self._getToolbarData((
-                                    ("add_class", self.icons["add_class"],
-                                     lambda event: self.cats_mgr.AddCategory()),
-                                     ("remove_class", self.icons['remove_class'],
-                                     lambda event: self.cats_list.DeleteCategory()),
-                                    ))
+            'add_class': MetaIcon(img='layer-add',
+                                  label=_('Add class')),
+            'remove_class': MetaIcon(img='layer-remove',
+                                     label=_('Remove selected class'))
+        }
+
+        return self._getToolbarData(
+            (("add_class", self.icons["add_class"],
+              lambda event: self.cats_mgr.AddCategory()),
+             ("remove_class", self.icons['remove_class'],
+              lambda event: self.cats_list.DeleteCategory()),))

+ 1 - 1
gui/wxpython/lmgr/__init__.py

@@ -6,4 +6,4 @@ all = [
     'frame',
     'giface',
     'datacatalog'
-    ]
+]

File diff ditekan karena terlalu besar
+ 892 - 712
gui/wxpython/lmgr/frame.py


+ 12 - 6
gui/wxpython/lmgr/giface.py

@@ -29,6 +29,7 @@ class Layer(object):
         Currently implemented without specifying the interface.
         It only provides all attributes of existing layer as used in lmgr.
     """
+
     def __init__(self, pydata):
         self._pydata = pydata
 
@@ -44,19 +45,20 @@ class Layer(object):
 
 class LayerList(object):
     """@implements core.giface.Layer"""
+
     def __init__(self, tree):
         self._tree = tree
 
     def __len__(self):
         return len([layer for layer in self])
-        
+
     def __iter__(self):
         """Iterates over the contents of the list."""
         item = self._tree.GetFirstChild(self._tree.root)[0]
         while item and item.IsOk():
             yield Layer(self._tree.GetPyData(item))
             item = self._tree.GetNextItem(item)
-        
+
     def __getitem__(self, index):
         """Select a layer from the LayerList using the index."""
         return [l for l in self][index]
@@ -133,6 +135,7 @@ class LayerList(object):
 
 class LayerManagerGrassInterface(object):
     """@implements core::giface::GrassInterface"""
+
     def __init__(self, lmgr):
         """Costructor is specific to the current implementation.
 
@@ -199,7 +202,7 @@ class LayerManagerGrassInterface(object):
 
     def UpdateCmdHistory(self, cmd):
         self.lmgr.goutput.GetPrompt().UpdateCmdHistory(cmd)
-        
+
     def ShowStatusbar(self, show=True):
         self.lmgr.GetMapDisplay().statusbarManager.Show(show)
 
@@ -207,22 +210,24 @@ class LayerManagerGrassInterface(object):
         return self.lmgr.GetMapDisplay().statusbarManager.IsShown()
 
     def ShowAllToolbars(self, show=True):
-        if not show: # hide
+        if not show:  # hide
             action = self.lmgr.GetMapDisplay().RemoveToolbar
         else:
             action = self.lmgr.GetMapDisplay().AddToolbar
         for toolbar in self.lmgr.GetMapDisplay().GetToolbarNames():
             action(toolbar)
-            
+
     def AreAllToolbarsShown(self):
         return self.lmgr.GetMapDisplay().GetMapToolbar().IsShown()
 
+
 class LayerManagerGrassInterfaceForMapDisplay(object):
     """Provides reference only to the given layer list (according to tree),
         not to the current.
 
         @implements core::giface::GrassInterface
     """
+
     def __init__(self, giface, tree):
         """
         :param giface: original grass interface
@@ -232,7 +237,8 @@ class LayerManagerGrassInterfaceForMapDisplay(object):
         self.tree = tree
 
         # Signal emitted to request updating of map
-        self.updateMap = Signal('LayerManagerGrassInterfaceForMapDisplay.updateMap')
+        self.updateMap = Signal(
+            'LayerManagerGrassInterfaceForMapDisplay.updateMap')
 
     def GetLayerTree(self):
         return self.tree

+ 0 - 0
gui/wxpython/lmgr/layertree.py


Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini