Przeglądaj źródła

Apply Black to wxGUI (#1527)

This applies Black 20.8b1 to wxGUI and GUI scripts in gui dir.
Uses Black with settings from pyproject.toml file, i.e., enables the gui subdir.
Ignores lmgr/layertree.py because of a bug in Black.
Fixed formatting checks enabled in Flake8.
Black does not add (but preserves) some empty lines required by Flake8. Adding these manually.
Vaclav Petras 4 lat temu
rodzic
commit
02bfae03d5
100 zmienionych plików z 21449 dodań i 19463 usunięć
  1. 3 3
      gui/scripts/d.rast3d.py
  2. 19 15
      gui/scripts/d.wms.py
  3. 6 31
      gui/wxpython/.flake8
  4. 10 10
      gui/wxpython/animation/__init__.py
  5. 4 9
      gui/wxpython/animation/anim.py
  6. 155 147
      gui/wxpython/animation/controller.py
  7. 61 59
      gui/wxpython/animation/data.py
  8. 633 720
      gui/wxpython/animation/dialogs.py
  9. 163 127
      gui/wxpython/animation/frame.py
  10. 20 17
      gui/wxpython/animation/g.gui.animation.py
  11. 23 23
      gui/wxpython/animation/mapwindow.py
  12. 174 148
      gui/wxpython/animation/nviztask.py
  13. 233 194
      gui/wxpython/animation/provider.py
  14. 136 135
      gui/wxpython/animation/temporal_manager.py
  15. 73 80
      gui/wxpython/animation/toolbars.py
  16. 87 67
      gui/wxpython/animation/utils.py
  17. 14 14
      gui/wxpython/core/__init__.py
  18. 17 12
      gui/wxpython/core/debug.py
  19. 140 119
      gui/wxpython/core/gcmd.py
  20. 227 184
      gui/wxpython/core/gconsole.py
  21. 41 41
      gui/wxpython/core/giface.py
  22. 45 41
      gui/wxpython/core/globalvar.py
  23. 17 13
      gui/wxpython/core/gthread.py
  24. 46 34
      gui/wxpython/core/layerlist.py
  25. 69 54
      gui/wxpython/core/menutree.py
  26. 430 336
      gui/wxpython/core/render.py
  27. 704 828
      gui/wxpython/core/settings.py
  28. 178 149
      gui/wxpython/core/toolboxes.py
  29. 11 8
      gui/wxpython/core/treemodel.py
  30. 49 44
      gui/wxpython/core/units.py
  31. 349 351
      gui/wxpython/core/utils.py
  32. 1056 983
      gui/wxpython/core/workspace.py
  33. 103 109
      gui/wxpython/core/ws.py
  34. 1 7
      gui/wxpython/datacatalog/__init__.py
  35. 58 26
      gui/wxpython/datacatalog/catalog.py
  36. 142 69
      gui/wxpython/datacatalog/dialogs.py
  37. 3 10
      gui/wxpython/datacatalog/frame.py
  38. 3 1
      gui/wxpython/datacatalog/g.gui.datacatalog.py
  39. 75 72
      gui/wxpython/datacatalog/toolbars.py
  40. 813 547
      gui/wxpython/datacatalog/tree.py
  41. 6 6
      gui/wxpython/dbmgr/__init__.py
  42. 1588 1474
      gui/wxpython/dbmgr/base.py
  43. 241 210
      gui/wxpython/dbmgr/dialogs.py
  44. 5 5
      gui/wxpython/dbmgr/g.gui.dbmgr.py
  45. 68 60
      gui/wxpython/dbmgr/manager.py
  46. 341 302
      gui/wxpython/dbmgr/sqlbuilder.py
  47. 60 60
      gui/wxpython/dbmgr/vinfo.py
  48. 99 106
      gui/wxpython/docs/wxgui_sphinx/conf.py
  49. 3 3
      gui/wxpython/gcp/__init__.py
  50. 7 5
      gui/wxpython/gcp/g.gui.gcp.py
  51. 1229 1097
      gui/wxpython/gcp/manager.py
  52. 196 130
      gui/wxpython/gcp/mapdisplay.py
  53. 13 13
      gui/wxpython/gcp/statusbar.py
  54. 65 88
      gui/wxpython/gcp/toolbars.py
  55. 8 8
      gui/wxpython/gmodeler/__init__.py
  56. 341 277
      gui/wxpython/gmodeler/dialogs.py
  57. 536 525
      gui/wxpython/gmodeler/frame.py
  58. 4 2
      gui/wxpython/gmodeler/g.gui.gmodeler.py
  59. 2 2
      gui/wxpython/gmodeler/giface.py
  60. 1 3
      gui/wxpython/gmodeler/menudata.py
  61. 883 812
      gui/wxpython/gmodeler/model.py
  62. 429 443
      gui/wxpython/gmodeler/preferences.py
  63. 55 74
      gui/wxpython/gmodeler/toolbars.py
  64. 15 15
      gui/wxpython/gui_core/__init__.py
  65. 740 735
      gui/wxpython/gui_core/dialogs.py
  66. 1375 1113
      gui/wxpython/gui_core/forms.py
  67. 308 283
      gui/wxpython/gui_core/ghelp.py
  68. 194 148
      gui/wxpython/gui_core/goutput.py
  69. 960 855
      gui/wxpython/gui_core/gselect.py
  70. 9 4
      gui/wxpython/gui_core/infobar.py
  71. 142 121
      gui/wxpython/gui_core/mapdisp.py
  72. 71 59
      gui/wxpython/gui_core/menu.py
  73. 1028 1096
      gui/wxpython/gui_core/preferences.py
  74. 154 147
      gui/wxpython/gui_core/prompt.py
  75. 152 118
      gui/wxpython/gui_core/pyedit.py
  76. 78 107
      gui/wxpython/gui_core/pystc.py
  77. 72 85
      gui/wxpython/gui_core/query.py
  78. 132 126
      gui/wxpython/gui_core/simplelmgr.py
  79. 98 90
      gui/wxpython/gui_core/toolbars.py
  80. 58 41
      gui/wxpython/gui_core/treeview.py
  81. 103 86
      gui/wxpython/gui_core/vselect.py
  82. 213 236
      gui/wxpython/gui_core/widgets.py
  83. 142 42
      gui/wxpython/gui_core/wrap.py
  84. 7 7
      gui/wxpython/iclass/__init__.py
  85. 191 175
      gui/wxpython/iclass/dialogs.py
  86. 21 20
      gui/wxpython/iclass/digit.py
  87. 485 360
      gui/wxpython/iclass/frame.py
  88. 28 29
      gui/wxpython/iclass/g.gui.iclass.py
  89. 36 52
      gui/wxpython/iclass/plots.py
  90. 6 8
      gui/wxpython/iclass/statistics.py
  91. 98 127
      gui/wxpython/iclass/toolbars.py
  92. 1 1
      gui/wxpython/icons/grass_icons.py
  93. 18 24
      gui/wxpython/icons/icon.py
  94. 3 3
      gui/wxpython/image2target/__init__.py
  95. 50 49
      gui/wxpython/image2target/g.gui.image2target.py
  96. 465 356
      gui/wxpython/image2target/ii2t_gis_set.py
  97. 3 4
      gui/wxpython/image2target/ii2t_gis_set_error.py
  98. 1226 1069
      gui/wxpython/image2target/ii2t_manager.py
  99. 196 130
      gui/wxpython/image2target/ii2t_mapdisplay.py
  100. 0 0
      gui/wxpython/image2target/ii2t_statusbar.py

+ 3 - 3
gui/scripts/d.rast3d.py

@@ -10,9 +10,9 @@
 #
 #
 # COPYRIGHT:	(C) 2008, 2010 by the GRASS Development Team
 # COPYRIGHT:	(C) 2008, 2010 by the GRASS Development Team
 #
 #
-#		This program is free software under the GNU General
-#		Public License (>=v2). Read the file COPYING that
-#		comes with GRASS for details.
+# 		This program is free software under the GNU General
+# 		Public License (>=v2). Read the file COPYING that
+# 		comes with GRASS for details.
 #
 #
 #############################################################################
 #############################################################################
 
 

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

@@ -165,25 +165,26 @@ sys.path.append(os.path.join(os.getenv("GISBASE"), "etc", "r.in.wms"))
 
 
 
 
 def GetRegion():
 def GetRegion():
-    """!Parse region from GRASS_REGION env var.
-    """
+    """!Parse region from GRASS_REGION env var."""
     region = os.environ["GRASS_REGION"]
     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()
     keys_to_convert = conv_reg_vals.keys()
 
 
     conv_region = {}
     conv_region = {}
-    region = region.split(';')
+    region = region.split(";")
 
 
     for r in region:
     for r in region:
-        r = r.split(':')
+        r = r.split(":")
         r[0] = r[0].strip()
         r[0] = r[0].strip()
 
 
         if r[0] in keys_to_convert:
         if r[0] in keys_to_convert:
@@ -193,15 +194,17 @@ def GetRegion():
 
 
 
 
 def main():
 def main():
-    options['region'] = GetRegion()
+    options["region"] = GetRegion()
 
 
-    if 'GRASS' in options['driver']:
+    if "GRASS" in options["driver"]:
         grass.debug("Using GRASS driver")
         grass.debug("Using GRASS driver")
         from wms_drv import WMSDrv
         from wms_drv import WMSDrv
+
         wms = WMSDrv()
         wms = WMSDrv()
-    elif 'GDAL' in options['driver']:
+    elif "GDAL" in options["driver"]:
         grass.debug("Using GDAL WMS driver")
         grass.debug("Using GDAL WMS driver")
         from wms_gdal_drv import WMSGdalDrv
         from wms_gdal_drv import WMSGdalDrv
+
         wms = WMSGdalDrv()
         wms = WMSGdalDrv()
 
 
     temp_map = wms.GetMap(options, flags)
     temp_map = wms.GetMap(options, flags)
@@ -209,6 +212,7 @@ def main():
 
 
     return 0
     return 0
 
 
+
 if __name__ == "__main__":
 if __name__ == "__main__":
     options, flags = grass.parser()
     options, flags = grass.parser()
     sys.exit(main())
     sys.exit(main())

+ 6 - 31
gui/wxpython/.flake8

@@ -1,36 +1,9 @@
 [flake8]
 [flake8]
 ignore =
 ignore =
-    E265, # block comment should start with '# '
-    E117, # over-indented
-    E122, # continuation line missing indentation or outdented
-    E123, # closing bracket does not match indentation of opening bracket's line
-    E124, # closing bracket does not match visual indentation
-    E125, # continuation line with same indent as next logical line
-    E126, # continuation line over-indented for hanging indent
-    E127, # continuation line over-indented for visual indent
-    E128, # continuation line under-indented for visual indent
-    E131, # continuation line unaligned for hanging indent
-    E202, # whitespace before '}'
-    E203, # whitespace before ':'
-    E211, # whitespace before '('
-    E222, # multiple spaces after operator
-    E225, # missing whitespace around operator
-    E226, # missing whitespace around arithmetic operator
-    E231, # missing whitespace after ','
-    E241, # multiple spaces after ','
-    E261, # at least two spaces before inline comment
-    E271, # multiple spaces after keyword
-    E272, # multiple spaces before keyword
-    E301, # expected 1 blank line, found 0
-    E302, # expected 2 blank lines, found 1
-    E303, # too many blank lines (3)
-    E305, # expected 2 blank lines after class or function definition, found 1
-    E306, # expected 1 blank line before a nested definition, found 0
-    E501, # line too long (96 > 79 characters)
-    W291, # trailing whitespace
-    W293, # blank line contains whitespace
-    W503, # line break before binary operator
-    W504, # line break after binary operator
+    E203,  # whitespace before ':' (Black)
+    W503,  # line break before binary operator (Black)
+    E501,  # line too long (fix needed)
+    E265,  # block comment should start with '# ' (fix needed)
 
 
 per-file-ignores =
 per-file-ignores =
     # Many of these ignores can and should be removed and the problem fixed.
     # Many of these ignores can and should be removed and the problem fixed.
@@ -56,6 +29,8 @@ per-file-ignores =
     image2target/*: F841, E722
     image2target/*: F841, E722
     iscatt/*: F841, E722, E741, F405, F403
     iscatt/*: F841, E722, E741, F405, F403
     lmgr/*: F841, E266, E722, E741, W605
     lmgr/*: F841, E266, E722, E741, W605
+    # layertree still includes some formatting issues (it is ignored by Black)
+    lmgr/layertree.py: E722, E266, W504, E225
     modules/*: F841, E722, W605
     modules/*: F841, E722, W605
     nviz/*: F841, E266, E722, W605, F403, F405
     nviz/*: F841, E266, E722, W605, F403, F405
     photo2image/*: F841, E722
     photo2image/*: F841, E722

+ 10 - 10
gui/wxpython/animation/__init__.py

@@ -1,12 +1,12 @@
 all = [
 all = [
-    'nviztask',
-    'temporal_manager',
-    'dialogs',
-    'mapwindow',
-    'g.gui.animation',
-    'controller',
-    'anim',
-    'toolbars',
-    'utils',
-    'frame',
+    "nviztask",
+    "temporal_manager",
+    "dialogs",
+    "mapwindow",
+    "g.gui.animation",
+    "controller",
+    "anim",
+    "toolbars",
+    "utils",
+    "frame",
 ]
 ]

+ 4 - 9
gui/wxpython/animation/anim.py

@@ -103,9 +103,7 @@ class Animation(wx.EvtHandler):
         if not self.IsActive():
         if not self.IsActive():
             return
             return
         self.currentIndex = 0
         self.currentIndex = 0
-        self.callbackEndAnimation(
-            self.currentIndex, self.GetFrame(
-                self.currentIndex))
+        self.callbackEndAnimation(self.currentIndex, self.GetFrame(self.currentIndex))
 
 
     def _arrivedToEnd(self):
     def _arrivedToEnd(self):
         """Decides which action to do after animation end (stop, repeat)."""
         """Decides which action to do after animation end (stop, repeat)."""
@@ -134,9 +132,7 @@ class Animation(wx.EvtHandler):
         if not self.IsActive():
         if not self.IsActive():
             return
             return
 
 
-        self.callbackUpdateFrame(
-            self.currentIndex, self.GetFrame(
-                self.currentIndex))
+        self.callbackUpdateFrame(self.currentIndex, self.GetFrame(self.currentIndex))
         if self.orientation == Orientation.FORWARD:
         if self.orientation == Orientation.FORWARD:
             self.currentIndex += 1
             self.currentIndex += 1
             if self.currentIndex == self.count:
             if self.currentIndex == self.count:
@@ -151,9 +147,7 @@ class Animation(wx.EvtHandler):
         if not self.IsActive():
         if not self.IsActive():
             return
             return
         self.currentIndex = index
         self.currentIndex = index
-        self.callbackUpdateFrame(
-            self.currentIndex, self.GetFrame(
-                self.currentIndex))
+        self.callbackUpdateFrame(self.currentIndex, self.GetFrame(self.currentIndex))
 
 
     def PreviousFrameIndex(self):
     def PreviousFrameIndex(self):
         if not self.IsActive():
         if not self.IsActive():
@@ -179,6 +173,7 @@ class Animation(wx.EvtHandler):
             if self.currentIndex == -1:
             if self.currentIndex == -1:
                 self.currentIndex = 0
                 self.currentIndex = 0
 
 
+
 # def test():
 # def test():
 #    import wx
 #    import wx
 #    app = wx.PySimpleApp()
 #    app = wx.PySimpleApp()

+ 155 - 147
gui/wxpython/animation/controller.py

@@ -24,22 +24,30 @@ from gui_core.wrap import EmptyImage, ImageFromBitmap
 
 
 from animation.temporal_manager import TemporalManager
 from animation.temporal_manager import TemporalManager
 from animation.dialogs import InputDialog, EditDialog, ExportDialog
 from animation.dialogs import InputDialog, EditDialog, ExportDialog
-from animation.utils import TemporalMode, TemporalType, Orientation, RenderText, WxImageToPil, \
-    sampleCmdMatrixAndCreateNames, layerListToCmdsMatrix, HashCmds
+from animation.utils import (
+    TemporalMode,
+    TemporalType,
+    Orientation,
+    RenderText,
+    WxImageToPil,
+    sampleCmdMatrixAndCreateNames,
+    layerListToCmdsMatrix,
+    HashCmds,
+)
 from animation.data import AnimationData
 from animation.data import AnimationData
 
 
 
 
 class AnimationController(wx.EvtHandler):
 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)
         wx.EvtHandler.__init__(self)
 
 
         self.mapwindows = mapwindows
         self.mapwindows = mapwindows
 
 
         self.frame = frame
         self.frame = frame
         self.sliders = sliders
         self.sliders = sliders
-        self.slider = self.sliders['temporal']
+        self.slider = self.sliders["temporal"]
         self.animationToolbar = None
         self.animationToolbar = None
 
 
         self.temporalMode = None
         self.temporalMode = None
@@ -53,13 +61,12 @@ class AnimationController(wx.EvtHandler):
         self.bitmapProvider = provider
         self.bitmapProvider = provider
         for anim, win in zip(self.animations, self.mapwindows):
         for anim, win in zip(self.animations, self.mapwindows):
             anim.SetCallbackUpdateFrame(
             anim.SetCallbackUpdateFrame(
-                lambda index, dataId, win=win: self.UpdateFrame(
-                    index, win, dataId))
+                lambda index, dataId, win=win: self.UpdateFrame(index, win, dataId)
+            )
             anim.SetCallbackEndAnimation(
             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():
         for slider in self.sliders.values():
             slider.SetCallbackSliderChanging(self.SliderChanging)
             slider.SetCallbackSliderChanging(self.SliderChanging)
@@ -138,8 +145,9 @@ class AnimationController(wx.EvtHandler):
 
 
     def UpdateFrame(self, index, win, dataId):
     def UpdateFrame(self, index, win, dataId):
         bitmap = self.bitmapProvider.GetBitmap(dataId)
         bitmap = self.bitmapProvider.GetBitmap(dataId)
-        if not UserSettings.Get(group='animation', key='temporal',
-                                subkey=['nodata', 'enable']):
+        if not UserSettings.Get(
+            group="animation", key="temporal", subkey=["nodata", "enable"]
+        ):
             if dataId is not None:
             if dataId is not None:
                 win.DrawBitmap(bitmap)
                 win.DrawBitmap(bitmap)
         else:
         else:
@@ -209,8 +217,8 @@ class AnimationController(wx.EvtHandler):
             parent=self.frame,
             parent=self.frame,
             evalFunction=self.EvaluateInput,
             evalFunction=self.EvaluateInput,
             animationData=self.animationData,
             animationData=self.animationData,
-            maxAnimations=len(
-                self.animations))
+            maxAnimations=len(self.animations),
+        )
         dlg.CenterOnParent()
         dlg.CenterOnParent()
         if dlg.ShowModal() == wx.ID_CANCEL:
         if dlg.ShowModal() == wx.ID_CANCEL:
             dlg.Destroy()
             dlg.Destroy()
@@ -232,8 +240,8 @@ class AnimationController(wx.EvtHandler):
         if not found:
         if not found:
             GMessage(
             GMessage(
                 parent=self.frame,
                 parent=self.frame,
-                message=_("Maximum number of animations is %d.") %
-                len(self.animations))
+                message=_("Maximum number of animations is %d.") % len(self.animations),
+            )
             return
             return
 
 
         # running = False
         # running = False
@@ -244,13 +252,9 @@ class AnimationController(wx.EvtHandler):
 
 
         animData = AnimationData()
         animData = AnimationData()
         # number of active animations
         # 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)
         animData.SetDefaultValues(windowIndex, animationIndex)
-        dlg = InputDialog(
-            parent=self.frame,
-            mode='add',
-            animationData=animData)
+        dlg = InputDialog(parent=self.frame, mode="add", animationData=animData)
         dlg.CenterOnParent()
         dlg.CenterOnParent()
         if dlg.ShowModal() == wx.ID_CANCEL:
         if dlg.ShowModal() == wx.ID_CANCEL:
             dlg.UnInit()
             dlg.UnInit()
@@ -260,13 +264,17 @@ class AnimationController(wx.EvtHandler):
         # check compatibility
         # check compatibility
         if animData.windowIndex in indices:
         if animData.windowIndex in indices:
             GMessage(
             GMessage(
-                parent=self.frame, message=_(
+                parent=self.frame,
+                message=_(
                     "More animations are using one window."
                     "More animations are using one window."
-                    " Please select different window for each animation."))
+                    " Please select different window for each animation."
+                ),
+            )
             return
             return
         try:
         try:
             temporalMode, tempManager = self.EvaluateInput(
             temporalMode, tempManager = self.EvaluateInput(
-                self.animationData + [animData])
+                self.animationData + [animData]
+            )
         except GException as e:
         except GException as e:
             GError(parent=self.frame, message=e.value, showTraceback=False)
             GError(parent=self.frame, message=e.value, showTraceback=False)
             return
             return
@@ -293,8 +301,12 @@ class AnimationController(wx.EvtHandler):
                     animationData.append(anim)
                     animationData.append(anim)
 
 
         except (GException, ValueError, IOError) as e:
         except (GException, ValueError, IOError) as e:
-            GError(parent=self.frame, message=str(e),
-                   showTraceback=False, caption=_("Invalid input"))
+            GError(
+                parent=self.frame,
+                message=str(e),
+                showTraceback=False,
+                caption=_("Invalid input"),
+            )
             return
             return
         try:
         try:
             temporalMode, tempManager = self.EvaluateInput(animationData)
             temporalMode, tempManager = self.EvaluateInput(animationData)
@@ -316,16 +328,12 @@ class AnimationController(wx.EvtHandler):
         else:
         else:
             timeLabels, mapNamesDict = None, None
             timeLabels, mapNamesDict = None, None
         for anim in self.animationData:
         for anim in self.animationData:
-            if anim.viewMode == '2d':
+            if anim.viewMode == "2d":
                 anim.cmdMatrix = layerListToCmdsMatrix(anim.layerList)
                 anim.cmdMatrix = layerListToCmdsMatrix(anim.layerList)
             else:
             else:
-                anim.cmdMatrix = [(cmd,)
-                                  for cmd in anim.GetNvizCommands()
-                                  ['commands']]
+                anim.cmdMatrix = [(cmd,) for cmd in anim.GetNvizCommands()["commands"]]
         self._updateSlider(timeLabels=timeLabels)
         self._updateSlider(timeLabels=timeLabels)
-        self._updateAnimations(
-            activeIndices=indices,
-            mapNamesDict=mapNamesDict)
+        self._updateAnimations(activeIndices=indices, mapNamesDict=mapNamesDict)
         self._updateBitmapData()
         self._updateBitmapData()
         # if running:
         # if running:
         #     self.PauseAnimation(False)
         #     self.PauseAnimation(False)
@@ -335,13 +343,13 @@ class AnimationController(wx.EvtHandler):
 
 
     def _updateSlider(self, timeLabels=None):
     def _updateSlider(self, timeLabels=None):
         if self.temporalMode == TemporalMode.NONTEMPORAL:
         if self.temporalMode == TemporalMode.NONTEMPORAL:
-            self.frame.SetSlider('nontemporal')
-            self.slider = self.sliders['nontemporal']
+            self.frame.SetSlider("nontemporal")
+            self.slider = self.sliders["nontemporal"]
             frameCount = self.animationData[0].mapCount
             frameCount = self.animationData[0].mapCount
             self.slider.SetFrames(frameCount)
             self.slider.SetFrames(frameCount)
         elif self.temporalMode == TemporalMode.TEMPORAL:
         elif self.temporalMode == TemporalMode.TEMPORAL:
-            self.frame.SetSlider('temporal')
-            self.slider = self.sliders['temporal']
+            self.frame.SetSlider("temporal")
+            self.slider = self.sliders["temporal"]
             self.slider.SetTemporalType(self.temporalManager.temporalType)
             self.slider.SetTemporalType(self.temporalManager.temporalType)
             self.slider.SetFrames(timeLabels)
             self.slider.SetFrames(timeLabels)
         else:
         else:
@@ -354,34 +362,40 @@ class AnimationController(wx.EvtHandler):
                 if i not in activeIndices:
                 if i not in activeIndices:
                     self.animations[i].SetActive(False)
                     self.animations[i].SetActive(False)
                     continue
                     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]
                 regions = anim.GetRegions()
                 regions = anim.GetRegions()
                 self.animations[i].SetFrames(
                 self.animations[i].SetFrames(
-                    [HashCmds(cmdList, region) for cmdList,
-                     region in zip(anim.cmdMatrix, regions)])
+                    [
+                        HashCmds(cmdList, region)
+                        for cmdList, region in zip(anim.cmdMatrix, regions)
+                    ]
+                )
                 self.animations[i].SetActive(True)
                 self.animations[i].SetActive(True)
         else:
         else:
             for i in range(len(self.animations)):
             for i in range(len(self.animations)):
                 if i not in activeIndices:
                 if i not in activeIndices:
                     self.animations[i].SetActive(False)
                     self.animations[i].SetActive(False)
                     continue
                     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]
                 regions = anim.GetRegions()
                 regions = anim.GetRegions()
                 identifiers = sampleCmdMatrixAndCreateNames(
                 identifiers = sampleCmdMatrixAndCreateNames(
-                    anim.cmdMatrix, mapNamesDict[
-                        anim.firstStdsNameType[0]], regions)
+                    anim.cmdMatrix, mapNamesDict[anim.firstStdsNameType[0]], regions
+                )
                 self.animations[i].SetFrames(identifiers)
                 self.animations[i].SetFrames(identifiers)
                 self.animations[i].SetActive(True)
                 self.animations[i].SetActive(True)
 
 
     def _updateWindows(self, activeIndices):
     def _updateWindows(self, activeIndices):
         # add or remove window
         # add or remove window
         for windowIndex in range(len(self.animations)):
         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)
                 self.frame.AddWindow(windowIndex)
-            elif self.frame.IsWindowShown(windowIndex) and windowIndex not in activeIndices:
+            elif (
+                self.frame.IsWindowShown(windowIndex)
+                and windowIndex not in activeIndices
+            ):
                 self.frame.RemoveWindow(windowIndex)
                 self.frame.RemoveWindow(windowIndex)
 
 
     def _updateBitmapData(self):
     def _updateBitmapData(self):
@@ -390,54 +404,43 @@ class AnimationController(wx.EvtHandler):
 
 
         # load new data
         # load new data
         for animData in self.animationData:
         for animData in self.animationData:
-            if animData.viewMode == '2d':
+            if animData.viewMode == "2d":
                 self._set2DData(animData)
                 self._set2DData(animData)
             else:
             else:
                 self._load3DData(animData)
                 self._load3DData(animData)
             self._loadLegend(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)
         self.bitmapProvider.Load(nprocs=cpus, bgcolor=color)
         # clear pools
         # clear pools
         self.bitmapPool.Clear()
         self.bitmapPool.Clear()
         self.mapFilesPool.Clear()
         self.mapFilesPool.Clear()
 
 
     def _set2DData(self, animationData):
     def _set2DData(self, animationData):
-        opacities = [
-            layer.opacity for layer in animationData.layerList
-            if layer.active]
-        #w, h = self.mapwindows[animationData.GetWindowIndex()].GetClientSize()
+        opacities = [layer.opacity for layer in animationData.layerList if layer.active]
+        # w, h = self.mapwindows[animationData.GetWindowIndex()].GetClientSize()
         regions = animationData.GetRegions()
         regions = animationData.GetRegions()
-        self.bitmapProvider.SetCmds(
-            animationData.cmdMatrix, opacities, regions)
+        self.bitmapProvider.SetCmds(animationData.cmdMatrix, opacities, regions)
 
 
     def _load3DData(self, animationData):
     def _load3DData(self, animationData):
         nviz = animationData.GetNvizCommands()
         nviz = animationData.GetNvizCommands()
-        self.bitmapProvider.SetCmds3D(nviz['commands'], nviz['region'])
+        self.bitmapProvider.SetCmds3D(nviz["commands"], nviz["region"])
 
 
     def _loadLegend(self, animationData):
     def _loadLegend(self, animationData):
         if animationData.legendCmd:
         if animationData.legendCmd:
             try:
             try:
-                bitmap = self.bitmapProvider.LoadOverlay(
-                    animationData.legendCmd)
+                bitmap = self.bitmapProvider.LoadOverlay(animationData.legendCmd)
                 try:
                 try:
                     from PIL import Image  # noqa: F401
                     from PIL import Image  # noqa: F401
+
                     for param in animationData.legendCmd:
                     for param in animationData.legendCmd:
-                        if param.startswith('at'):
-                            b, t, l, r = param.split('=')[1].split(',')
-                            x, y = float(l) / 100., 1 - float(t) / 100.
+                        if param.startswith("at"):
+                            b, t, l, r = param.split("=")[1].split(",")
+                            x, y = float(l) / 100.0, 1 - float(t) / 100.0
                             break
                             break
                 except ImportError:
                 except ImportError:
                     x, y = 0, 0
                     x, y = 0, 0
-                self.mapwindows[
-                    animationData.windowIndex].SetOverlay(
-                    bitmap, x, y)
+                self.mapwindows[animationData.windowIndex].SetOverlay(bitmap, x, y)
             except GException:
             except GException:
                 GError(message=_("Failed to display legend."))
                 GError(message=_("Failed to display legend."))
         else:
         else:
@@ -451,8 +454,8 @@ class AnimationController(wx.EvtHandler):
         windowIndex = []
         windowIndex = []
         for anim in animationData:
         for anim in animationData:
             for layer in anim.layerList:
             for layer in anim.layerList:
-                if layer.active and hasattr(layer, 'maps'):
-                    if layer.mapType in ('strds', 'stvds', 'str3ds'):
+                if layer.active and hasattr(layer, "maps"):
+                    if layer.mapType in ("strds", "stvds", "str3ds"):
                         stds += 1
                         stds += 1
                     else:
                     else:
                         maps += 1
                         maps += 1
@@ -471,7 +474,8 @@ class AnimationController(wx.EvtHandler):
         if temporalMode == TemporalMode.NONTEMPORAL:
         if temporalMode == TemporalMode.NONTEMPORAL:
             if len(mapCount) > 1:
             if len(mapCount) > 1:
                 raise GException(
                 raise GException(
-                    _("Inconsistent number of maps, please check input data."))
+                    _("Inconsistent number of maps, please check input data.")
+                )
         elif temporalMode == TemporalMode.TEMPORAL:
         elif temporalMode == TemporalMode.TEMPORAL:
             tempManager = TemporalManager()
             tempManager = TemporalManager()
             # these raise GException:
             # these raise GException:
@@ -487,14 +491,8 @@ class AnimationController(wx.EvtHandler):
     def Reload(self):
     def Reload(self):
         self.EndAnimation()
         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.bitmapProvider.Load(nprocs=cpus, bgcolor=color, force=True)
 
 
         self.EndAnimation()
         self.EndAnimation()
@@ -504,15 +502,16 @@ class AnimationController(wx.EvtHandler):
             GMessage(parent=self.frame, message=_("No animation to export."))
             GMessage(parent=self.frame, message=_("No animation to export."))
             return
             return
 
 
-        if 'export' in self._dialogs:
-            self._dialogs['export'].Show()
-            self._dialogs['export'].Raise()
+        if "export" in self._dialogs:
+            self._dialogs["export"].Show()
+            self._dialogs["export"].Raise()
         else:
         else:
-            dlg = ExportDialog(self.frame, temporal=self.temporalMode,
-                               timeTick=self.timeTick)
+            dlg = ExportDialog(
+                self.frame, temporal=self.temporalMode, timeTick=self.timeTick
+            )
             dlg.CenterOnParent()
             dlg.CenterOnParent()
             dlg.doExport.connect(self._export)
             dlg.doExport.connect(self._export)
-            self._dialogs['export'] = dlg
+            self._dialogs["export"] = dlg
             dlg.Show()
             dlg.Show()
 
 
     def _export(self, exportInfo, decorations):
     def _export(self, exportInfo, decorations):
@@ -521,8 +520,7 @@ class AnimationController(wx.EvtHandler):
             timeLabels, mapNamesDict = self.temporalManager.GetLabelsAndMaps()
             timeLabels, mapNamesDict = self.temporalManager.GetLabelsAndMaps()
             frameCount = len(timeLabels)
             frameCount = len(timeLabels)
         else:
         else:
-            frameCount = self.animationData[
-                0].mapCount  # should be the same for all
+            frameCount = self.animationData[0].mapCount  # should be the same for all
 
 
         animWinSize = []
         animWinSize = []
         animWinPos = []
         animWinPos = []
@@ -537,27 +535,20 @@ class AnimationController(wx.EvtHandler):
                 animWinIndex.append(i)
                 animWinIndex.append(i)
 
 
         images = []
         images = []
-        busy = wx.BusyInfo(
-            _("Preparing export, please wait..."),
-            parent=self.frame)
+        busy = wx.BusyInfo(_("Preparing export, please wait..."), parent=self.frame)
         wx.GetApp().Yield()
         wx.GetApp().Yield()
         lastBitmaps = {}
         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):
         for frameIndex in range(frameCount):
             image = EmptyImage(*size)
             image = EmptyImage(*size)
             image.Replace(0, 0, 0, 255, 255, 255)
             image.Replace(0, 0, 0, 255, 255, 255)
             # collect bitmaps of all windows and paste them into the one
             # collect bitmaps of all windows and paste them into the one
             for i in animWinIndex:
             for i in animWinIndex:
                 frameId = self.animations[i].GetFrame(frameIndex)
                 frameId = self.animations[i].GetFrame(frameIndex)
-                if not UserSettings.Get(group='animation', key='temporal',
-                                        subkey=['nodata', 'enable']):
+                if not UserSettings.Get(
+                    group="animation", key="temporal", subkey=["nodata", "enable"]
+                ):
                     if frameId is not None:
                     if frameId is not None:
                         bitmap = self.bitmapProvider.GetBitmap(frameId)
                         bitmap = self.bitmapProvider.GetBitmap(frameId)
                         lastBitmaps[i] = bitmap
                         lastBitmaps[i] = bitmap
@@ -587,31 +578,38 @@ class AnimationController(wx.EvtHandler):
             # paste decorations
             # paste decorations
             for decoration in decorations:
             for decoration in decorations:
                 # add image
                 # add image
-                x = decoration['pos'][0] / 100. * size[0]
-                y = decoration['pos'][1] / 100. * size[1]
-                if decoration['name'] == 'image':
-                    decImage = wx.Image(decoration['file'])
-                elif decoration['name'] == 'time':
+                x = decoration["pos"][0] / 100.0 * size[0]
+                y = decoration["pos"][1] / 100.0 * size[1]
+                if decoration["name"] == "image":
+                    decImage = wx.Image(decoration["file"])
+                elif decoration["name"] == "time":
                     timeLabel = timeLabels[frameIndex]
                     timeLabel = timeLabels[frameIndex]
                     if timeLabel[1]:  # interval
                     if timeLabel[1]:  # interval
                         text = _("%(from)s %(dash)s %(to)s") % {
                         text = _("%(from)s %(dash)s %(to)s") % {
-                            'from': timeLabel[0],
-                            'dash': u"\u2013", 'to': timeLabel[1]}
+                            "from": timeLabel[0],
+                            "dash": "\u2013",
+                            "to": timeLabel[1],
+                        }
                     else:
                     else:
-                        if self.temporalManager.GetTemporalType() == TemporalType.ABSOLUTE:
+                        if (
+                            self.temporalManager.GetTemporalType()
+                            == TemporalType.ABSOLUTE
+                        ):
                             text = timeLabel[0]
                             text = timeLabel[0]
                         else:
                         else:
-                            text = _("%(start)s %(unit)s") % \
-                                {'start': timeLabel[0], 'unit': timeLabel[2]}
+                            text = _("%(start)s %(unit)s") % {
+                                "start": timeLabel[0],
+                                "unit": timeLabel[2],
+                            }
 
 
                     decImage = RenderText(
                     decImage = RenderText(
-                        text, decoration['font'],
-                        bgcolor, fgcolor).ConvertToImage()
-                elif decoration['name'] == 'text':
-                    text = decoration['text']
+                        text, decoration["font"], bgcolor, fgcolor
+                    ).ConvertToImage()
+                elif decoration["name"] == "text":
+                    text = decoration["text"]
                     decImage = RenderText(
                     decImage = RenderText(
-                        text, decoration['font'],
-                        bgcolor, fgcolor).ConvertToImage()
+                        text, decoration["font"], bgcolor, fgcolor
+                    ).ConvertToImage()
 
 
                 image.Paste(decImage, x, y)
                 image.Paste(decImage, x, y)
 
 
@@ -620,10 +618,12 @@ class AnimationController(wx.EvtHandler):
 
 
         # export
         # export
         pilImages = [WxImageToPil(image) for image in images]
         pilImages = [WxImageToPil(image) for image in images]
-        self.busy = wx.BusyInfo(_("Exporting animation, please wait..."),
-                                parent=self.frame)
+        self.busy = wx.BusyInfo(
+            _("Exporting animation, please wait..."), parent=self.frame
+        )
         wx.GetApp().Yield()
         wx.GetApp().Yield()
         try:
         try:
+
             def export_avi_callback(event):
             def export_avi_callback(event):
                 error = event.ret
                 error = event.ret
                 del self.busy
                 del self.busy
@@ -631,33 +631,41 @@ class AnimationController(wx.EvtHandler):
                     GError(parent=self.frame, message=error)
                     GError(parent=self.frame, message=error)
                     return
                     return
 
 
-            if exportInfo['method'] == 'sequence':
+            if exportInfo["method"] == "sequence":
                 filename = os.path.join(
                 filename = os.path.join(
-                    exportInfo['directory'],
-                    exportInfo['prefix'] +
-                    '.' +
-                    exportInfo['format'].lower())
+                    exportInfo["directory"],
+                    exportInfo["prefix"] + "." + exportInfo["format"].lower(),
+                )
                 writeIms(filename=filename, images=pilImages)
                 writeIms(filename=filename, images=pilImages)
-            elif exportInfo['method'] == 'gif':
-                writeGif(filename=exportInfo['file'], images=pilImages,
-                         duration=self.timeTick / float(1000), repeat=True)
-            elif exportInfo['method'] == 'swf':
-                writeSwf(filename=exportInfo['file'], images=pilImages,
-                         duration=self.timeTick / float(1000), repeat=True)
-            elif exportInfo['method'] == 'avi':
+            elif exportInfo["method"] == "gif":
+                writeGif(
+                    filename=exportInfo["file"],
+                    images=pilImages,
+                    duration=self.timeTick / float(1000),
+                    repeat=True,
+                )
+            elif exportInfo["method"] == "swf":
+                writeSwf(
+                    filename=exportInfo["file"],
+                    images=pilImages,
+                    duration=self.timeTick / float(1000),
+                    repeat=True,
+                )
+            elif exportInfo["method"] == "avi":
                 thread = gThread()
                 thread = gThread()
-                thread.Run(callable=writeAvi,
-                           filename=exportInfo['file'],
-                           images=pilImages,
-                           duration=self.timeTick / float(1000),
-                           encoding=exportInfo['encoding'],
-                           inputOptions=exportInfo['options'],
-                           bg_task=True,
-                           ondone=export_avi_callback,
-                           )
+                thread.Run(
+                    callable=writeAvi,
+                    filename=exportInfo["file"],
+                    images=pilImages,
+                    duration=self.timeTick / float(1000),
+                    encoding=exportInfo["encoding"],
+                    inputOptions=exportInfo["options"],
+                    bg_task=True,
+                    ondone=export_avi_callback,
+                )
         except Exception as e:
         except Exception as e:
             del self.busy
             del self.busy
             GError(parent=self.frame, message=str(e))
             GError(parent=self.frame, message=str(e))
             return
             return
-        if exportInfo['method'] in ('sequence', 'gif', 'swf'):
+        if exportInfo["method"] in ("sequence", "gif", "swf"):
             del self.busy
             del self.busy

+ 61 - 59
gui/wxpython/animation/data.py

@@ -23,13 +23,17 @@ from grass.script import core as gcore
 
 
 from core.gcmd import GException
 from core.gcmd import GException
 from animation.nviztask import NvizTask
 from animation.nviztask import NvizTask
-from animation.utils import validateMapNames, getRegisteredMaps, \
-    checkSeriesCompatibility, validateTimeseriesName, interpolate
+from animation.utils import (
+    validateMapNames,
+    getRegisteredMaps,
+    checkSeriesCompatibility,
+    validateTimeseriesName,
+    interpolate,
+)
 from core.layerlist import LayerList, Layer
 from core.layerlist import LayerList, Layer
 
 
 
 
 class AnimationData(object):
 class AnimationData(object):
-
     def __init__(self):
     def __init__(self):
         self._name = None
         self._name = None
         self._windowIndex = 0
         self._windowIndex = 0
@@ -39,9 +43,8 @@ class AnimationData(object):
         self._firstStdsNameType = None
         self._firstStdsNameType = None
         self._mapCount = None
         self._mapCount = None
         self._cmdMatrix = None
         self._cmdMatrix = None
-        self._viewModes = [('2d', _("2D view")),
-                           ('3d', _("3D view"))]
-        self.viewMode = '2d'
+        self._viewModes = [("2d", _("2D view")), ("3d", _("3D view"))]
+        self.viewMode = "2d"
 
 
         self.nvizTask = NvizTask()
         self.nvizTask = NvizTask()
         self._nvizParameters = self.nvizTask.ListMapParameters()
         self._nvizParameters = self.nvizTask.ListMapParameters()
@@ -59,7 +62,7 @@ class AnimationData(object):
         return self._name
         return self._name
 
 
     def SetName(self, name):
     def SetName(self, name):
-        if name == '':
+        if name == "":
             raise ValueError(_("No animation name selected."))
             raise ValueError(_("No animation name selected."))
         self._name = name
         self._name = name
 
 
@@ -80,8 +83,8 @@ class AnimationData(object):
         mapSeriesList = []
         mapSeriesList = []
         timeseriesList = []
         timeseriesList = []
         for layer in layerList:
         for layer in layerList:
-            if layer.active and hasattr(layer, 'maps'):
-                if layer.mapType in ('strds', 'stvds', 'str3ds'):
+            if layer.active and hasattr(layer, "maps"):
+                if layer.mapType in ("strds", "stvds", "str3ds"):
                     timeseriesList.append((layer.name, layer.mapType))
                     timeseriesList.append((layer.name, layer.mapType))
                     self._firstStdsNameType = layer.name, layer.mapType
                     self._firstStdsNameType = layer.name, layer.mapType
                 else:
                 else:
@@ -89,8 +92,9 @@ class AnimationData(object):
         if not timeseriesList:
         if not timeseriesList:
             self._firstStdsNameType = None, None
             self._firstStdsNameType = None, None
         # this throws GException
         # this throws GException
-        count = checkSeriesCompatibility(mapSeriesList=mapSeriesList,
-                                         timeseriesList=timeseriesList)
+        count = checkSeriesCompatibility(
+            mapSeriesList=mapSeriesList, timeseriesList=timeseriesList
+        )
         self._mapCount = count
         self._mapCount = count
         self._layerList = layerList
         self._layerList = layerList
 
 
@@ -125,7 +129,7 @@ class AnimationData(object):
             self._workspaceFile = None
             self._workspaceFile = None
             return
             return
 
 
-        if fileName == '':
+        if fileName == "":
             raise ValueError(_("No workspace file selected."))
             raise ValueError(_("No workspace file selected."))
 
 
         if not os.path.exists(fileName):
         if not os.path.exists(fileName):
@@ -179,11 +183,12 @@ class AnimationData(object):
         if not self.workspaceFile or not self._layerList:
         if not self.workspaceFile or not self._layerList:
             return []
             return []
 
 
-        cmds = self.nvizTask.GetCommandSeries(layerList=self._layerList,
-                                              paramName=self.nvizParameter)
+        cmds = self.nvizTask.GetCommandSeries(
+            layerList=self._layerList, paramName=self.nvizParameter
+        )
         region = self.nvizTask.GetRegion()
         region = self.nvizTask.GetRegion()
 
 
-        return {'commands': cmds, 'region': region}
+        return {"commands": cmds, "region": region}
 
 
     def SetStartRegion(self, region):
     def SetStartRegion(self, region):
         self._startRegion = region
         self._startRegion = region
@@ -207,34 +212,33 @@ class AnimationData(object):
     def GetZoomRegionValue(self):
     def GetZoomRegionValue(self):
         return self._zoomRegionValue
         return self._zoomRegionValue
 
 
-    zoomRegionValue = property(
-        fset=SetZoomRegionValue,
-        fget=GetZoomRegionValue)
+    zoomRegionValue = property(fset=SetZoomRegionValue, fget=GetZoomRegionValue)
 
 
     def GetRegions(self):
     def GetRegions(self):
-        self._computeRegions(self._mapCount, self._startRegion,
-                             self._endRegion, self._zoomRegionValue)
+        self._computeRegions(
+            self._mapCount, self._startRegion, self._endRegion, self._zoomRegionValue
+        )
         return self._regions
         return self._regions
 
 
-    def _computeRegions(
-            self, count, startRegion, endRegion=None,
-            zoomValue=None):
+    def _computeRegions(self, count, startRegion, endRegion=None, zoomValue=None):
         """Computes regions based on start region and end region or zoom value
         """Computes regions based on start region and end region or zoom value
         for each of the animation frames."""
         for each of the animation frames."""
         region = dict(gcore.region())  # cast to dict, otherwise deepcopy error
         region = dict(gcore.region())  # cast to dict, otherwise deepcopy error
         if startRegion:
         if startRegion:
-            region = dict(parse_key_val(gcore.read_command('g.region',
-                                                           flags='gu',
-                                                           region=startRegion),
-                                        val_type=float))
-
-        del region['cells']
-        del region['cols']
-        del region['rows']
-        if 'projection' in region:
-            del region['projection']
-        if 'zone' in region:
-            del region['zone']
+            region = dict(
+                parse_key_val(
+                    gcore.read_command("g.region", flags="gu", region=startRegion),
+                    val_type=float,
+                )
+            )
+
+        del region["cells"]
+        del region["cols"]
+        del region["rows"]
+        if "projection" in region:
+            del region["projection"]
+        if "zone" in region:
+            del region["zone"]
         regions = []
         regions = []
         for i in range(self._mapCount):
         for i in range(self._mapCount):
             regions.append(copy.copy(region))
             regions.append(copy.copy(region))
@@ -243,36 +247,33 @@ class AnimationData(object):
             return
             return
 
 
         startRegionDict = parse_key_val(
         startRegionDict = parse_key_val(
-            gcore.read_command(
-                'g.region',
-                flags='gu',
-                region=startRegion),
-            val_type=float)
+            gcore.read_command("g.region", flags="gu", region=startRegion),
+            val_type=float,
+        )
         if endRegion:
         if endRegion:
             endRegionDict = parse_key_val(
             endRegionDict = parse_key_val(
-                gcore.read_command(
-                    'g.region',
-                    flags='gu',
-                    region=endRegion),
-                val_type=float)
-            for key in ('n', 's', 'e', 'w', 'nsres', 'ewres'):
+                gcore.read_command("g.region", flags="gu", region=endRegion),
+                val_type=float,
+            )
+            for key in ("n", "s", "e", "w", "nsres", "ewres"):
                 values = interpolate(
                 values = interpolate(
-                    startRegionDict[key],
-                    endRegionDict[key],
-                    self._mapCount)
+                    startRegionDict[key], endRegionDict[key], self._mapCount
+                )
                 for value, region in zip(values, regions):
                 for value, region in zip(values, regions):
                     region[key] = value
                     region[key] = value
 
 
         elif zoomValue:
         elif zoomValue:
             for i in range(self._mapCount):
             for i in range(self._mapCount):
-                regions[i]['n'] -= zoomValue[0] * i
-                regions[i]['e'] -= zoomValue[1] * i
-                regions[i]['s'] += zoomValue[0] * i
-                regions[i]['w'] += zoomValue[1] * i
+                regions[i]["n"] -= zoomValue[0] * i
+                regions[i]["e"] -= zoomValue[1] * i
+                regions[i]["s"] += zoomValue[0] * i
+                regions[i]["w"] += zoomValue[1] * i
 
 
                 # handle cases when north < south and similarly EW
                 # handle cases when north < south and similarly EW
-                if regions[i]['n'] < regions[i]['s'] or \
-                   regions[i]['e'] < regions[i]['w']:
+                if (
+                    regions[i]["n"] < regions[i]["s"]
+                    or regions[i]["e"] < regions[i]["w"]
+                ):
                     regions[i] = regions[i - 1]
                     regions[i] = regions[i - 1]
 
 
         self._regions = regions
         self._regions = regions
@@ -287,22 +288,23 @@ class AnimLayer(Layer):
 
 
     def __init__(self):
     def __init__(self):
         Layer.__init__(self)
         Layer.__init__(self)
-        self._mapTypes.extend(['strds', 'stvds', 'str3ds'])
+        self._mapTypes.extend(["strds", "stvds", "str3ds"])
         self._maps = []
         self._maps = []
 
 
     def SetName(self, name):
     def SetName(self, name):
         if not self.hidden:
         if not self.hidden:
             if self._mapType is None:
             if self._mapType is None:
                 raise ValueError(
                 raise ValueError(
-                    "To set layer name, the type of layer must be specified.")
-            if self._mapType in ('strds', 'stvds', 'str3ds'):
+                    "To set layer name, the type of layer must be specified."
+                )
+            if self._mapType in ("strds", "stvds", "str3ds"):
                 try:
                 try:
                     name = validateTimeseriesName(name, self._mapType)
                     name = validateTimeseriesName(name, self._mapType)
                     self._maps = getRegisteredMaps(name, self._mapType)
                     self._maps = getRegisteredMaps(name, self._mapType)
                 except (GException, gcore.ScriptError) as e:
                 except (GException, gcore.ScriptError) as e:
                     raise ValueError(str(e))
                     raise ValueError(str(e))
             else:
             else:
-                self._maps = validateMapNames(name.split(','), self._mapType)
+                self._maps = validateMapNames(name.split(","), self._mapType)
         self._name = name
         self._name = name
         self.label = name
         self.label = name
 
 

Plik diff jest za duży
+ 633 - 720
gui/wxpython/animation/dialogs.py


+ 163 - 127
gui/wxpython/animation/frame.py

@@ -31,8 +31,7 @@ from gui_core.wrap import StaticText, TextCtrl
 from core.gcmd import RunCommand, GWarning
 from core.gcmd import RunCommand, GWarning
 
 
 from animation.mapwindow import AnimationWindow
 from animation.mapwindow import AnimationWindow
-from animation.provider import BitmapProvider, BitmapPool, \
-    MapFilesPool, CleanUp
+from animation.provider import BitmapProvider, BitmapPool, MapFilesPool, CleanUp
 from animation.controller import AnimationController
 from animation.controller import AnimationController
 from animation.anim import Animation
 from animation.anim import Animation
 from animation.toolbars import MainToolbar, AnimationToolbar, MiscToolbar
 from animation.toolbars import MainToolbar, AnimationToolbar, MiscToolbar
@@ -47,21 +46,21 @@ gcore.set_raise_on_error(True)
 
 
 
 
 class AnimationFrame(wx.Frame):
 class AnimationFrame(wx.Frame):
-
-    def __init__(self, parent, giface, title=_("Animation Tool"),
-                 rasters=None, timeseries=None):
-        wx.Frame.__init__(self, parent, title=title,
-                          style=wx.DEFAULT_FRAME_STYLE, size=(800, 600))
+    def __init__(
+        self, parent, giface, title=_("Animation Tool"), rasters=None, timeseries=None
+    ):
+        wx.Frame.__init__(
+            self, parent, title=title, style=wx.DEFAULT_FRAME_STYLE, size=(800, 600)
+        )
         self._giface = giface
         self._giface = giface
         self.SetClientSize(self.GetSize())
         self.SetClientSize(self.GetSize())
         self.iconsize = (16, 16)
         self.iconsize = (16, 16)
 
 
         self.SetIcon(
         self.SetIcon(
             wx.Icon(
             wx.Icon(
-                os.path.join(
-                    globalvar.ICONDIR,
-                    'grass_map.ico'),
-                wx.BITMAP_TYPE_ICO))
+                os.path.join(globalvar.ICONDIR, "grass_map.ico"), wx.BITMAP_TYPE_ICO
+            )
+        )
 
 
         # Make sure the temporal database exists
         # Make sure the temporal database exists
         try:
         try:
@@ -77,7 +76,8 @@ class AnimationFrame(wx.Frame):
         self.animations = [Animation() for i in range(MAX_COUNT)]
         self.animations = [Animation() for i in range(MAX_COUNT)]
         self.windows = []
         self.windows = []
         self.animationPanel = AnimationsPanel(
         self.animationPanel = AnimationsPanel(
-            self, self.windows, initialCount=MAX_COUNT)
+            self, self.windows, initialCount=MAX_COUNT
+        )
         bitmapPool = BitmapPool()
         bitmapPool = BitmapPool()
         mapFilesPool = MapFilesPool()
         mapFilesPool = MapFilesPool()
 
 
@@ -85,27 +85,27 @@ class AnimationFrame(wx.Frame):
         self._progressDlgMax = None
         self._progressDlgMax = None
 
 
         self.provider = BitmapProvider(
         self.provider = BitmapProvider(
+            bitmapPool=bitmapPool, mapFilesPool=mapFilesPool, tempDir=TMP_DIR
+        )
+        self.animationSliders = {}
+        self.animationSliders["nontemporal"] = SimpleAnimationSlider(self)
+        self.animationSliders["temporal"] = TimeAnimationSlider(self)
+        self.controller = AnimationController(
+            frame=self,
+            sliders=self.animationSliders,
+            animations=self.animations,
+            mapwindows=self.windows,
+            provider=self.provider,
             bitmapPool=bitmapPool,
             bitmapPool=bitmapPool,
             mapFilesPool=mapFilesPool,
             mapFilesPool=mapFilesPool,
-            tempDir=TMP_DIR)
-        self.animationSliders = {}
-        self.animationSliders['nontemporal'] = SimpleAnimationSlider(self)
-        self.animationSliders['temporal'] = TimeAnimationSlider(self)
-        self.controller = AnimationController(frame=self,
-                                              sliders=self.animationSliders,
-                                              animations=self.animations,
-                                              mapwindows=self.windows,
-                                              provider=self.provider,
-                                              bitmapPool=bitmapPool,
-                                              mapFilesPool=mapFilesPool)
+        )
         for win in self.windows:
         for win in self.windows:
             win.Bind(wx.EVT_SIZE, self.FrameSizeChanged)
             win.Bind(wx.EVT_SIZE, self.FrameSizeChanged)
-            self.provider.mapsLoaded.connect(lambda: self.SetStatusText(''))
+            self.provider.mapsLoaded.connect(lambda: self.SetStatusText(""))
             self.provider.renderingStarted.connect(self._showRenderingProgress)
             self.provider.renderingStarted.connect(self._showRenderingProgress)
             self.provider.renderingContinues.connect(self._updateProgress)
             self.provider.renderingContinues.connect(self._updateProgress)
             self.provider.renderingFinished.connect(self._closeProgress)
             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.compositionContinues.connect(self._updateProgress)
             self.provider.compositionFinished.connect(self._closeProgress)
             self.provider.compositionFinished.connect(self._closeProgress)
 
 
@@ -119,8 +119,8 @@ class AnimationFrame(wx.Frame):
         self._mgr.Update()
         self._mgr.Update()
 
 
         self.dialogs = dict()
         self.dialogs = dict()
-        self.dialogs['speed'] = None
-        self.dialogs['preferences'] = None
+        self.dialogs["speed"] = None
+        self.dialogs["preferences"] = None
 
 
         self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
         self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
 
 
@@ -129,19 +129,34 @@ class AnimationFrame(wx.Frame):
         self.CreateStatusBar(number=1, style=0)
         self.CreateStatusBar(number=1, style=0)
 
 
     def _addPanes(self):
     def _addPanes(self):
-        self._mgr.AddPane(self.animationPanel,
-                          wx.aui.AuiPaneInfo().CentrePane().
-                          Name('animPanel').CentrePane().CaptionVisible(False).PaneBorder(False).
-                          Floatable(False).BestSize((-1, -1)).
-                          CloseButton(False).DestroyOnClose(True).Layer(0))
+        self._mgr.AddPane(
+            self.animationPanel,
+            wx.aui.AuiPaneInfo()
+            .CentrePane()
+            .Name("animPanel")
+            .CentrePane()
+            .CaptionVisible(False)
+            .PaneBorder(False)
+            .Floatable(False)
+            .BestSize((-1, -1))
+            .CloseButton(False)
+            .DestroyOnClose(True)
+            .Layer(0),
+        )
         for name, slider in six.iteritems(self.animationSliders):
         for name, slider in six.iteritems(self.animationSliders):
             self._mgr.AddPane(
             self._mgr.AddPane(
                 slider,
                 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()
+                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 _addToolbars(self):
     def _addToolbars(self):
         """Add toolbars to the window
         """Add toolbars to the window
@@ -152,36 +167,62 @@ class AnimationFrame(wx.Frame):
          - 'miscToolbar'          - help, close
          - 'miscToolbar'          - help, close
         """
         """
         self.toolbars["mainToolbar"] = MainToolbar(self)
         self.toolbars["mainToolbar"] = MainToolbar(self)
-        self._mgr.AddPane(self.toolbars["mainToolbar"],
-                          wx.aui.AuiPaneInfo().
-                          Name('mainToolbar').Caption(_("Main Toolbar")).
-                          ToolbarPane().Top().
-                          LeftDockable(False).RightDockable(False).
-                          BottomDockable(True).TopDockable(True).
-                          CloseButton(False).Layer(2).Row(1).Position(0).
-                          BestSize((self.toolbars['mainToolbar'].GetBestSize())))
-
-        self.toolbars['animationToolbar'] = AnimationToolbar(self)
-        self._mgr.AddPane(self.toolbars['animationToolbar'],
-                          wx.aui.AuiPaneInfo().
-                          Name('animationToolbar').Caption(_("Animation Toolbar")).
-                          ToolbarPane().Top().
-                          LeftDockable(False).RightDockable(False).
-                          BottomDockable(True).TopDockable(True).
-                          CloseButton(False).Layer(2).Row(1).Position(1).
-                          BestSize((self.toolbars['animationToolbar'].GetBestSize())))
-        self.controller.SetAnimationToolbar(
-            self.toolbars['animationToolbar'])
-
-        self.toolbars['miscToolbar'] = MiscToolbar(self)
-        self._mgr.AddPane(self.toolbars['miscToolbar'],
-                          wx.aui.AuiPaneInfo().
-                          Name('miscToolbar').Caption(_("Misc Toolbar")).
-                          ToolbarPane().Top().
-                          LeftDockable(False).RightDockable(False).
-                          BottomDockable(True).TopDockable(True).
-                          CloseButton(False).Layer(2).Row(1).Position(2).
-                          BestSize((self.toolbars['miscToolbar'].GetBestSize())))
+        self._mgr.AddPane(
+            self.toolbars["mainToolbar"],
+            wx.aui.AuiPaneInfo()
+            .Name("mainToolbar")
+            .Caption(_("Main Toolbar"))
+            .ToolbarPane()
+            .Top()
+            .LeftDockable(False)
+            .RightDockable(False)
+            .BottomDockable(True)
+            .TopDockable(True)
+            .CloseButton(False)
+            .Layer(2)
+            .Row(1)
+            .Position(0)
+            .BestSize((self.toolbars["mainToolbar"].GetBestSize())),
+        )
+
+        self.toolbars["animationToolbar"] = AnimationToolbar(self)
+        self._mgr.AddPane(
+            self.toolbars["animationToolbar"],
+            wx.aui.AuiPaneInfo()
+            .Name("animationToolbar")
+            .Caption(_("Animation Toolbar"))
+            .ToolbarPane()
+            .Top()
+            .LeftDockable(False)
+            .RightDockable(False)
+            .BottomDockable(True)
+            .TopDockable(True)
+            .CloseButton(False)
+            .Layer(2)
+            .Row(1)
+            .Position(1)
+            .BestSize((self.toolbars["animationToolbar"].GetBestSize())),
+        )
+        self.controller.SetAnimationToolbar(self.toolbars["animationToolbar"])
+
+        self.toolbars["miscToolbar"] = MiscToolbar(self)
+        self._mgr.AddPane(
+            self.toolbars["miscToolbar"],
+            wx.aui.AuiPaneInfo()
+            .Name("miscToolbar")
+            .Caption(_("Misc Toolbar"))
+            .ToolbarPane()
+            .Top()
+            .LeftDockable(False)
+            .RightDockable(False)
+            .BottomDockable(True)
+            .TopDockable(True)
+            .CloseButton(False)
+            .Layer(2)
+            .Row(1)
+            .Position(2)
+            .BestSize((self.toolbars["miscToolbar"].GetBestSize())),
+        )
 
 
     def SetAnimations(self, layerLists):
     def SetAnimations(self, layerLists):
         """Set animation data
         """Set animation data
@@ -206,16 +247,16 @@ class AnimationFrame(wx.Frame):
         self.controller.EditAnimations()
         self.controller.EditAnimations()
 
 
     def SetSlider(self, name):
     def SetSlider(self, name):
-        if name == 'nontemporal':
-            self._mgr.GetPane('slider_nontemporal').Show()
-            self._mgr.GetPane('slider_temporal').Hide()
+        if name == "nontemporal":
+            self._mgr.GetPane("slider_nontemporal").Show()
+            self._mgr.GetPane("slider_temporal").Hide()
 
 
-        elif name == 'temporal':
-            self._mgr.GetPane('slider_temporal').Show()
-            self._mgr.GetPane('slider_nontemporal').Hide()
+        elif name == "temporal":
+            self._mgr.GetPane("slider_temporal").Show()
+            self._mgr.GetPane("slider_nontemporal").Hide()
         else:
         else:
-            self._mgr.GetPane('slider_temporal').Hide()
-            self._mgr.GetPane('slider_nontemporal').Hide()
+            self._mgr.GetPane("slider_temporal").Hide()
+            self._mgr.GetPane("slider_nontemporal").Hide()
         self._mgr.Update()
         self._mgr.Update()
 
 
     def OnPlayForward(self, event):
     def OnPlayForward(self, event):
@@ -247,7 +288,7 @@ class AnimationFrame(wx.Frame):
         self.controller.SetReplayMode(mode)
         self.controller.SetReplayMode(mode)
 
 
     def OnAdjustSpeed(self, event):
     def OnAdjustSpeed(self, event):
-        win = self.dialogs['speed']
+        win = self.dialogs["speed"]
         if win:
         if win:
             win.SetTemporalMode(self.controller.GetTemporalMode())
             win.SetTemporalMode(self.controller.GetTemporalMode())
             win.SetTimeGranularity(self.controller.GetTimeGranularity())
             win.SetTimeGranularity(self.controller.GetTimeGranularity())
@@ -258,11 +299,13 @@ class AnimationFrame(wx.Frame):
                 win.Show()
                 win.Show()
         else:  # start
         else:  # start
             win = SpeedDialog(
             win = SpeedDialog(
-                self, temporalMode=self.controller.GetTemporalMode(),
+                self,
+                temporalMode=self.controller.GetTemporalMode(),
                 timeGranularity=self.controller.GetTimeGranularity(),
                 timeGranularity=self.controller.GetTimeGranularity(),
-                initialSpeed=self.controller.timeTick)
+                initialSpeed=self.controller.timeTick,
+            )
             win.CenterOnParent()
             win.CenterOnParent()
-            self.dialogs['speed'] = win
+            self.dialogs["speed"] = win
             win.speedChanged.connect(self.ChangeSpeed)
             win.speedChanged.connect(self.ChangeSpeed)
             win.Show()
             win.Show()
 
 
@@ -280,12 +323,12 @@ class AnimationFrame(wx.Frame):
             message="Loading data started, please be patient.",
             message="Loading data started, please be patient.",
             maximum=count,
             maximum=count,
             parent=self,
             parent=self,
-            style=wx.PD_CAN_ABORT | wx.PD_APP_MODAL | wx.PD_AUTO_HIDE | wx.PD_SMOOTH)
+            style=wx.PD_CAN_ABORT | wx.PD_APP_MODAL | wx.PD_AUTO_HIDE | wx.PD_SMOOTH,
+        )
         self._progressDlgMax = count
         self._progressDlgMax = count
 
 
     def _updateProgress(self, current, text):
     def _updateProgress(self, current, text):
-        text += _(" ({c} out of {p})").format(c=current,
-                                              p=self._progressDlgMax)
+        text += _(" ({c} out of {p})").format(c=current, p=self._progressDlgMax)
         keepGoing, skip = self._progressDlg.Update(current, text)
         keepGoing, skip = self._progressDlg.Update(current, text)
         if not keepGoing:
         if not keepGoing:
             self.provider.RequestStopRendering()
             self.provider.RequestStopRendering()
@@ -307,19 +350,16 @@ class AnimationFrame(wx.Frame):
         event.Skip()
         event.Skip()
 
 
     def OnPreferences(self, event):
     def OnPreferences(self, event):
-        if not self.dialogs['preferences']:
+        if not self.dialogs["preferences"]:
             dlg = PreferencesDialog(parent=self, giface=self._giface)
             dlg = PreferencesDialog(parent=self, giface=self._giface)
-            self.dialogs['preferences'] = dlg
-            dlg.formatChanged.connect(
-                lambda: self.controller.UpdateAnimations())
+            self.dialogs["preferences"] = dlg
+            dlg.formatChanged.connect(lambda: self.controller.UpdateAnimations())
             dlg.CenterOnParent()
             dlg.CenterOnParent()
 
 
-        self.dialogs['preferences'].Show()
+        self.dialogs["preferences"].Show()
 
 
     def OnHelp(self, event):
     def OnHelp(self, event):
-        RunCommand('g.manual',
-                   quiet=True,
-                   entry='wxGUI.animation')
+        RunCommand("g.manual", quiet=True, entry="wxGUI.animation")
 
 
     def OnCloseWindow(self, event):
     def OnCloseWindow(self, event):
         if self.controller.timer.IsRunning():
         if self.controller.timer.IsRunning():
@@ -330,14 +370,13 @@ class AnimationFrame(wx.Frame):
 
 
     def __del__(self):
     def __del__(self):
         """It might not be called, therefore we try to clean it all in OnCloseWindow."""
         """It might not be called, therefore we try to clean it all in OnCloseWindow."""
-        if hasattr(self, 'controller') and hasattr(self.controller, 'timer'):
+        if hasattr(self, "controller") and hasattr(self.controller, "timer"):
             if self.controller.timer.IsRunning():
             if self.controller.timer.IsRunning():
                 self.controller.timer.Stop()
                 self.controller.timer.Stop()
         CleanUp(TMP_DIR)()
         CleanUp(TMP_DIR)()
 
 
 
 
 class AnimationsPanel(wx.Panel):
 class AnimationsPanel(wx.Panel):
-
     def __init__(self, parent, windows, initialCount=4):
     def __init__(self, parent, windows, initialCount=4):
         wx.Panel.__init__(self, parent, id=wx.ID_ANY, style=wx.NO_BORDER)
         wx.Panel.__init__(self, parent, id=wx.ID_ANY, style=wx.NO_BORDER)
         self.shown = []
         self.shown = []
@@ -378,14 +417,17 @@ class AnimationsPanel(wx.Panel):
 
 
 
 
 class AnimationSliderBase(wx.Panel):
 class AnimationSliderBase(wx.Panel):
-
     def __init__(self, parent):
     def __init__(self, parent):
         wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY)
         wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY)
         self.label1 = StaticText(self, id=wx.ID_ANY)
         self.label1 = StaticText(self, id=wx.ID_ANY)
         self.slider = wx.Slider(self, id=wx.ID_ANY, style=wx.SL_HORIZONTAL)
         self.slider = wx.Slider(self, id=wx.ID_ANY, style=wx.SL_HORIZONTAL)
-        self.indexField = TextCtrl(self, id=wx.ID_ANY, size=(40, -1),
-                                   style=wx.TE_PROCESS_ENTER | wx.TE_RIGHT,
-                                   validator=IntegerValidator())
+        self.indexField = TextCtrl(
+            self,
+            id=wx.ID_ANY,
+            size=(40, -1),
+            style=wx.TE_PROCESS_ENTER | wx.TE_RIGHT,
+            validator=IntegerValidator(),
+        )
 
 
         self.callbackSliderChanging = None
         self.callbackSliderChanging = None
         self.callbackSliderChanged = None
         self.callbackSliderChanged = None
@@ -467,7 +509,6 @@ class AnimationSliderBase(wx.Panel):
 
 
 
 
 class SimpleAnimationSlider(AnimationSliderBase):
 class SimpleAnimationSlider(AnimationSliderBase):
-
     def __init__(self, parent):
     def __init__(self, parent):
         AnimationSliderBase.__init__(self, parent)
         AnimationSliderBase.__init__(self, parent)
 
 
@@ -476,15 +517,16 @@ class SimpleAnimationSlider(AnimationSliderBase):
 
 
     def _doLayout(self):
     def _doLayout(self):
         hbox = wx.BoxSizer(wx.HORIZONTAL)
         hbox = wx.BoxSizer(wx.HORIZONTAL)
-        hbox.Add(self.indexField, proportion=0,
-                 flag=wx.ALIGN_CENTER | wx.LEFT, border=5)
-        hbox.Add(self.label1, proportion=0,
-                 flag=wx.ALIGN_CENTER | wx.LEFT | wx.RIGHT, border=5)
         hbox.Add(
         hbox.Add(
-            self.slider,
-            proportion=1,
-            flag=wx.EXPAND,
-            border=0)
+            self.indexField, proportion=0, flag=wx.ALIGN_CENTER | wx.LEFT, border=5
+        )
+        hbox.Add(
+            self.label1,
+            proportion=0,
+            flag=wx.ALIGN_CENTER | wx.LEFT | wx.RIGHT,
+            border=5,
+        )
+        hbox.Add(self.slider, proportion=1, flag=wx.EXPAND, border=0)
         self.SetSizerAndFit(hbox)
         self.SetSizerAndFit(hbox)
 
 
     def _setFrames(self, count):
     def _setFrames(self, count):
@@ -497,7 +539,7 @@ class SimpleAnimationSlider(AnimationSliderBase):
         self._setLabel()
         self._setLabel()
 
 
     def _setLabel(self):
     def _setLabel(self):
-        label = "/ %(framesCount)s" % {'framesCount': self.framesCount}
+        label = "/ %(framesCount)s" % {"framesCount": self.framesCount}
         self.label1.SetLabel(label)
         self.label1.SetLabel(label)
         self.Layout()
         self.Layout()
 
 
@@ -506,7 +548,6 @@ class SimpleAnimationSlider(AnimationSliderBase):
 
 
 
 
 class TimeAnimationSlider(AnimationSliderBase):
 class TimeAnimationSlider(AnimationSliderBase):
-
     def __init__(self, parent):
     def __init__(self, parent):
         AnimationSliderBase.__init__(self, parent)
         AnimationSliderBase.__init__(self, parent)
         self.timeLabels = []
         self.timeLabels = []
@@ -521,24 +562,18 @@ class TimeAnimationSlider(AnimationSliderBase):
     def _doLayout(self):
     def _doLayout(self):
         vbox = wx.BoxSizer(wx.VERTICAL)
         vbox = wx.BoxSizer(wx.VERTICAL)
         hbox = wx.BoxSizer(wx.HORIZONTAL)
         hbox = wx.BoxSizer(wx.HORIZONTAL)
-        hbox.Add(self.label1, proportion=0,
-                 flag=wx.ALIGN_CENTER_VERTICAL, border=0)
+        hbox.Add(self.label1, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL, border=0)
         hbox.AddStretchSpacer()
         hbox.AddStretchSpacer()
-        hbox.Add(self.indexField, proportion=0,
-                 flag=wx.ALIGN_CENTER_VERTICAL, border=0)
-        hbox.Add(self.label2, proportion=0,
-                 flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=3)
+        hbox.Add(self.indexField, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL, border=0)
+        hbox.Add(
+            self.label2, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=3
+        )
         hbox.AddStretchSpacer()
         hbox.AddStretchSpacer()
-        hbox.Add(self.label3, proportion=0,
-                 flag=wx.ALIGN_CENTER_VERTICAL, border=0)
+        hbox.Add(self.label3, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL, border=0)
         vbox.Add(hbox, proportion=0, flag=wx.EXPAND, border=0)
         vbox.Add(hbox, proportion=0, flag=wx.EXPAND, border=0)
 
 
         hbox = wx.BoxSizer(wx.HORIZONTAL)
         hbox = wx.BoxSizer(wx.HORIZONTAL)
-        hbox.Add(
-            self.slider,
-            proportion=1,
-            flag=wx.EXPAND,
-            border=0)
+        hbox.Add(self.slider, proportion=1, flag=wx.EXPAND, border=0)
         vbox.Add(hbox, proportion=0, flag=wx.EXPAND, border=0)
         vbox.Add(hbox, proportion=0, flag=wx.EXPAND, border=0)
 
 
         self._setTemporalType()
         self._setTemporalType()
@@ -584,7 +619,7 @@ class TimeAnimationSlider(AnimationSliderBase):
                     end = self.timeLabels[-1][1]
                     end = self.timeLabels[-1][1]
                 else:
                 else:
                     end = self.timeLabels[-1][0]
                     end = self.timeLabels[-1][0]
-                end = "%(end)s %(unit)s" % {'end': end, 'unit': unit}
+                end = "%(end)s %(unit)s" % {"end": end, "unit": unit}
                 self.label3.SetLabel(end)
                 self.label3.SetLabel(end)
 
 
             self.label2Length = len(start)
             self.label2Length = len(start)
@@ -601,16 +636,17 @@ class TimeAnimationSlider(AnimationSliderBase):
         if self.timeLabels[index][1]:  # interval
         if self.timeLabels[index][1]:  # interval
             if self.temporalType == TemporalType.ABSOLUTE:
             if self.temporalType == TemporalType.ABSOLUTE:
                 label = _("%(from)s %(dash)s %(to)s") % {
                 label = _("%(from)s %(dash)s %(to)s") % {
-                    'from': start,
-                    'dash': u"\u2013",
-                    'to': self.timeLabels[index][1]}
+                    "from": start,
+                    "dash": "\u2013",
+                    "to": self.timeLabels[index][1],
+                }
             else:
             else:
-                label = _("to %(to)s") % {'to': self.timeLabels[index][1]}
+                label = _("to %(to)s") % {"to": self.timeLabels[index][1]}
         else:
         else:
             if self.temporalType == TemporalType.ABSOLUTE:
             if self.temporalType == TemporalType.ABSOLUTE:
                 label = start
                 label = start
             else:
             else:
-                label = ''
+                label = ""
         self.label2.SetLabel(label)
         self.label2.SetLabel(label)
         if self.temporalType == TemporalType.RELATIVE:
         if self.temporalType == TemporalType.RELATIVE:
             self.indexField.SetValue(start)
             self.indexField.SetValue(start)

+ 20 - 17
gui/wxpython/animation/g.gui.animation.py

@@ -64,6 +64,7 @@ def main():
     import wx
     import wx
 
 
     from grass.script.setup import set_gui_path
     from grass.script.setup import set_gui_path
+
     set_gui_path()
     set_gui_path()
 
 
     from core.giface import StandaloneGrassInterface
     from core.giface import StandaloneGrassInterface
@@ -71,10 +72,10 @@ def main():
     from animation.frame import AnimationFrame, MAX_COUNT
     from animation.frame import AnimationFrame, MAX_COUNT
     from animation.data import AnimLayer
     from animation.data import AnimLayer
 
 
-    rast = options['raster']
-    vect = options['vector']
-    strds = options['strds']
-    stvds = options['stvds']
+    rast = options["raster"]
+    vect = options["vector"]
+    strds = options["strds"]
+    stvds = options["stvds"]
 
 
     numInputs = 0
     numInputs = 0
 
 
@@ -88,8 +89,10 @@ def main():
         numInputs += 1
         numInputs += 1
 
 
     if numInputs > 1:
     if numInputs > 1:
-        gscript.fatal(_("%s=, %s=, %s= and %s= are mutually exclusive.") %
-                       ("raster", "vector", "strds", "stvds"))
+        gscript.fatal(
+            _("%s=, %s=, %s= and %s= are mutually exclusive.")
+            % ("raster", "vector", "strds", "stvds")
+        )
 
 
     if numInputs > 0:
     if numInputs > 0:
         # We need to initialize the temporal framework in case
         # We need to initialize the temporal framework in case
@@ -103,27 +106,27 @@ def main():
     layerList = LayerList()
     layerList = LayerList()
     if rast:
     if rast:
         layer = AnimLayer()
         layer = AnimLayer()
-        layer.mapType = 'raster'
+        layer.mapType = "raster"
         layer.name = rast
         layer.name = rast
-        layer.cmd = ['d.rast', 'map={name}'.format(name=rast.split(',')[0])]
+        layer.cmd = ["d.rast", "map={name}".format(name=rast.split(",")[0])]
         layerList.AddLayer(layer)
         layerList.AddLayer(layer)
     if vect:
     if vect:
         layer = AnimLayer()
         layer = AnimLayer()
-        layer.mapType = 'vector'
+        layer.mapType = "vector"
         layer.name = vect
         layer.name = vect
-        layer.cmd = ['d.vect', 'map={name}'.format(name=vect.split(',')[0])]
+        layer.cmd = ["d.vect", "map={name}".format(name=vect.split(",")[0])]
         layerList.AddLayer(layer)
         layerList.AddLayer(layer)
     if strds:
     if strds:
         layer = AnimLayer()
         layer = AnimLayer()
-        layer.mapType = 'strds'
+        layer.mapType = "strds"
         layer.name = strds
         layer.name = strds
-        layer.cmd = ['d.rast', 'map=']
+        layer.cmd = ["d.rast", "map="]
         layerList.AddLayer(layer)
         layerList.AddLayer(layer)
     if stvds:
     if stvds:
         layer = AnimLayer()
         layer = AnimLayer()
-        layer.mapType = 'stvds'
+        layer.mapType = "stvds"
         layer.name = stvds
         layer.name = stvds
-        layer.cmd = ['d.vect', 'map=']
+        layer.cmd = ["d.vect", "map="]
         layerList.AddLayer(layer)
         layerList.AddLayer(layer)
 
 
     app = wx.App()
     app = wx.App()
@@ -137,9 +140,9 @@ def main():
     frame.Show()
     frame.Show()
     if len(layerList) >= 1:
     if len(layerList) >= 1:
         # CallAfter added since it was crashing with wxPython 3 gtk
         # 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()
     app.MainLoop()
 
 
-if __name__ == '__main__':
+
+if __name__ == "__main__":
     main()
     main()

+ 23 - 23
gui/wxpython/animation/mapwindow.py

@@ -17,8 +17,7 @@ This program is free software under the GNU General Public License
 
 
 import wx
 import wx
 from core.debug import Debug
 from core.debug import Debug
-from gui_core.wrap import BitmapFromImage, EmptyBitmap, ImageFromBitmap, \
-    PseudoDC, Rect
+from gui_core.wrap import BitmapFromImage, EmptyBitmap, ImageFromBitmap, PseudoDC, Rect
 from .utils import ComputeScaledRect
 from .utils import ComputeScaledRect
 
 
 
 
@@ -40,8 +39,10 @@ class BufferedWindow(wx.Window):
 
 
     def __init__(self, *args, **kwargs):
     def __init__(self, *args, **kwargs):
         # make sure the NO_FULL_REPAINT_ON_RESIZE style flag is set.
         # 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)
         wx.Window.__init__(self, *args, **kwargs)
 
 
         Debug.msg(2, "BufferedWindow.__init__()")
         Debug.msg(2, "BufferedWindow.__init__()")
@@ -66,7 +67,7 @@ class BufferedWindow(wx.Window):
         Debug.msg(5, "BufferedWindow.OnSize()")
         Debug.msg(5, "BufferedWindow.OnSize()")
         # The Buffer init is done here, to make sure the buffer is always
         # The Buffer init is done here, to make sure the buffer is always
         # the same size as the Window
         # the same size as the Window
-        #Size  = self.GetClientSizeTuple()
+        # Size  = self.GetClientSizeTuple()
         size = self.GetClientSize()
         size = self.GetClientSize()
 
 
         # Make new offscreen bitmap: this bitmap will always have the
         # Make new offscreen bitmap: this bitmap will always have the
@@ -103,10 +104,12 @@ class BufferedWindow(wx.Window):
 
 
 
 
 class AnimationWindow(BufferedWindow):
 class AnimationWindow(BufferedWindow):
-
-    def __init__(self, parent, id=wx.ID_ANY,
-                 style=wx.DEFAULT_FRAME_STYLE | wx.FULL_REPAINT_ON_RESIZE |
-                 wx.BORDER_RAISED):
+    def __init__(
+        self,
+        parent,
+        id=wx.ID_ANY,
+        style=wx.DEFAULT_FRAME_STYLE | wx.FULL_REPAINT_ON_RESIZE | wx.BORDER_RAISED,
+    ):
         Debug.msg(2, "AnimationWindow.__init__()")
         Debug.msg(2, "AnimationWindow.__init__()")
 
 
         self.bitmap = EmptyBitmap(1, 1)
         self.bitmap = EmptyBitmap(1, 1)
@@ -145,21 +148,18 @@ class AnimationWindow(BufferedWindow):
         if abs(bW - wW) > 5 or abs(bH - wH) > 5:
         if abs(bW - wW) > 5 or abs(bH - wH) > 5:
             params = ComputeScaledRect((bW, bH), (wW, wH))
             params = ComputeScaledRect((bW, bH), (wW, wH))
             im = ImageFromBitmap(bitmap)
             im = ImageFromBitmap(bitmap)
-            im.Rescale(params['width'], params['height'])
-            self.x = params['x']
-            self.y = params['y']
+            im.Rescale(params["width"], params["height"])
+            self.x = params["x"]
+            self.y = params["y"]
             bitmap = BitmapFromImage(im)
             bitmap = BitmapFromImage(im)
             if self._overlay:
             if self._overlay:
                 im = ImageFromBitmap(self.bitmap_overlay)
                 im = ImageFromBitmap(self.bitmap_overlay)
                 im.Rescale(
                 im.Rescale(
-                    im.GetWidth() *
-                    params['scale'],
-                    im.GetHeight() *
-                    params['scale'])
+                    im.GetWidth() * params["scale"], im.GetHeight() * params["scale"]
+                )
                 self._setOverlay(
                 self._setOverlay(
-                    BitmapFromImage(im),
-                    xperc=self.perc[0],
-                    yperc=self.perc[1])
+                    BitmapFromImage(im), xperc=self.perc[0], yperc=self.perc[1]
+                )
         else:
         else:
             self.x = 0
             self.x = 0
             self.y = 0
             self.y = 0
@@ -180,8 +180,9 @@ class AnimationWindow(BufferedWindow):
         self._pdc.BeginDrawing()
         self._pdc.BeginDrawing()
         self._pdc.SetId(1)
         self._pdc.SetId(1)
         self._pdc.DrawBitmap(bmp=self._overlay, x=x, y=y)
         self._pdc.DrawBitmap(bmp=self._overlay, x=x, y=y)
-        self._pdc.SetIdBounds(1, Rect(x, y, self._overlay.GetWidth(),
-                                         self._overlay.GetHeight()))
+        self._pdc.SetIdBounds(
+            1, Rect(x, y, self._overlay.GetWidth(), self._overlay.GetHeight())
+        )
         self._pdc.EndDrawing()
         self._pdc.EndDrawing()
 
 
     def _setOverlay(self, bitmap, xperc, yperc):
     def _setOverlay(self, bitmap, xperc, yperc):
@@ -232,8 +233,7 @@ class AnimationWindow(BufferedWindow):
         current = event.GetPosition()
         current = event.GetPosition()
         if event.LeftDown():
         if event.LeftDown():
             self._dragid = None
             self._dragid = None
-            idlist = self._pdc.FindObjects(current[0], current[1],
-                                           radius=10)
+            idlist = self._pdc.FindObjects(current[0], current[1], radius=10)
             if 1 in idlist:
             if 1 in idlist:
                 self._dragid = 1
                 self._dragid = 1
             self._tmpMousePos = current
             self._tmpMousePos = current

+ 174 - 148
gui/wxpython/animation/nviztask.py

@@ -29,7 +29,6 @@ from core.settings import UserSettings
 
 
 
 
 class NvizTask:
 class NvizTask:
-
     def __init__(self):
     def __init__(self):
         self.task = None
         self.task = None
         self.filename = None
         self.filename = None
@@ -41,18 +40,23 @@ class NvizTask:
         try:
         try:
             gxwXml = ProcessWorkspaceFile(etree.parse(self.filename))
             gxwXml = ProcessWorkspaceFile(etree.parse(self.filename))
         except Exception:
         except Exception:
-            raise GException(_("Reading workspace file <%s> failed.\n"
-                               "Invalid file, unable to parse XML document.") % filename)
+            raise GException(
+                _(
+                    "Reading workspace file <%s> failed.\n"
+                    "Invalid file, unable to parse XML document."
+                )
+                % filename
+            )
         # for display in gxwXml.displays:
         # for display in gxwXml.displays:
-            # pprint(display)
+        # pprint(display)
         # for layer in gxwXml.layers:
         # for layer in gxwXml.layers:
-            # pprint(layer)
+        # pprint(layer)
         # pprint(gxwXml.nviz_state)
         # pprint(gxwXml.nviz_state)
 
 
         if not gxwXml.nviz_state:
         if not gxwXml.nviz_state:
             raise GException(
             raise GException(
-                _("No 3d view information in workspace file <%s>.") %
-                self.filename)
+                _("No 3d view information in workspace file <%s>.") % self.filename
+            )
 
 
         self._getExtent(gxwXml)
         self._getExtent(gxwXml)
         self._processState(gxwXml.nviz_state)
         self._processState(gxwXml.nviz_state)
@@ -60,56 +64,62 @@ class NvizTask:
 
 
     def _getExtent(self, root):
     def _getExtent(self, root):
         for display in root.displays:
         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['tbres'] = display['tbres']
+            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["tbres"] = display["tbres"]
 
 
     def _processLayers(self, layers):
     def _processLayers(self, layers):
         for layer in layers:
         for layer in layers:
-            if not layer['checked']:
+            if not layer["checked"]:
                 continue
                 continue
 
 
-            if not layer['nviz']:
+            if not layer["nviz"]:
                 continue
                 continue
             layerName, found = GetLayerNameFromCmd(
             layerName, found = GetLayerNameFromCmd(
-                layer['cmd'], fullyQualified=False, param='map')
+                layer["cmd"], fullyQualified=False, param="map"
+            )
             if not found:
             if not found:
                 continue
                 continue
 
 
-            if 'surface' in layer['nviz']:
-                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']:
+            if "surface" in layer["nviz"]:
+                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(
                     self._processPoints(
-                        layer['nviz']['vector']['points'],
-                        mapName=layerName)
+                        layer["nviz"]["vector"]["points"], mapName=layerName
+                    )
 
 
     def _processSurface(self, surface, mapName):
     def _processSurface(self, surface, mapName):
-        self._setMultiTaskParam('elevation_map', mapName)
+        self._setMultiTaskParam("elevation_map", mapName)
 
 
         # attributes like color, shine, transparency
         # attributes like color, shine, transparency
-        attributes = ('color', 'shine', 'transp')  # mask missing
-        parameters = (('color_map', 'color'),
-                      ('shininess_map', 'shininess_value'),
-                      ('transparency_map', 'transparency_value'))
+        attributes = ("color", "shine", "transp")  # mask missing
+        parameters = (
+            ("color_map", "color"),
+            ("shininess_map", "shininess_value"),
+            ("transparency_map", "transparency_value"),
+        )
         for attr, params in zip(attributes, parameters):
         for attr, params in zip(attributes, parameters):
             mapname = None
             mapname = None
             const = None
             const = None
-            if attr in surface['attribute']:
-                if surface['attribute'][attr]['map']:
-                    mapname = surface['attribute'][attr]['value']
+            if attr in surface["attribute"]:
+                if surface["attribute"][attr]["map"]:
+                    mapname = surface["attribute"][attr]["value"]
                 else:
                 else:
-                    const = surface['attribute'][attr]['value']
+                    const = surface["attribute"][attr]["value"]
             else:
             else:
-                if attr == 'transp':
+                if attr == "transp":
                     const = 0
                     const = 0
-                elif attr == 'color':
+                elif attr == "color":
                     mapname = mapName
                     mapname = mapName
 
 
             if mapname:
             if mapname:
@@ -118,155 +128,173 @@ class NvizTask:
                 self._setMultiTaskParam(params[1], const)
                 self._setMultiTaskParam(params[1], const)
 
 
         # draw mode
         # draw mode
-        for mode in ('mode', 'shading', 'style'):
-            value = surface['draw']['mode']['desc'][mode]
+        for mode in ("mode", "shading", "style"):
+            value = surface["draw"]["mode"]["desc"][mode]
             self._setMultiTaskParam(mode, value)
             self._setMultiTaskParam(mode, value)
         # wire color
         # wire color
-        value = surface['draw']['wire-color']['value']
-        self._setMultiTaskParam('wire_color', value)
+        value = surface["draw"]["wire-color"]["value"]
+        self._setMultiTaskParam("wire_color", value)
         # resolution
         # resolution
         for mode1, mode2 in zip(
         for mode1, mode2 in zip(
-                ('coarse', 'fine'),
-                ('resolution_coarse', 'resolution_fine')):
-            value = surface['draw']['resolution'][mode1]
+            ("coarse", "fine"), ("resolution_coarse", "resolution_fine")
+        ):
+            value = surface["draw"]["resolution"][mode1]
             self._setMultiTaskParam(mode2, value)
             self._setMultiTaskParam(mode2, value)
 
 
         # position
         # position
         pos = []
         pos = []
-        for coor in ('x', 'y', 'z'):
-            pos.append(str(surface['position'][coor]))
-        value = ','.join(pos)
-        self._setMultiTaskParam('surface_position', value)
+        for coor in ("x", "y", "z"):
+            pos.append(str(surface["position"][coor]))
+        value = ",".join(pos)
+        self._setMultiTaskParam("surface_position", value)
 
 
     def _processPoints(self, points, mapName):
     def _processPoints(self, points, mapName):
-        for attrib in ('color', 'size', 'width'):
+        for attrib in ("color", "size", "width"):
             if attrib in points:
             if attrib in points:
-                val = points[attrib]['value']
-                self._setMultiTaskParam('vpoint_' + attrib, str(val))
-        if 'height' in points:
-            height = points['height']['value']
-            self._setMultiTaskParam(
-                'vpoint_position',
-                '0,0,{h}'.format(
-                    h=height))
-        if 'marker' in points:
+                val = points[attrib]["value"]
+                self._setMultiTaskParam("vpoint_" + attrib, str(val))
+        if "height" in points:
+            height = points["height"]["value"]
+            self._setMultiTaskParam("vpoint_position", "0,0,{h}".format(h=height))
+        if "marker" in points:
             marker = list(
             marker = list(
                 UserSettings.Get(
                 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':
-                self._setMultiTaskParam('vpoint_mode', '3D')
+                    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":
+                self._setMultiTaskParam("vpoint_mode", "3D")
             else:
             else:
-                self._setMultiTaskParam('vpoint_mode', 'surface')
+                self._setMultiTaskParam("vpoint_mode", "surface")
 
 
     def _processVolume(self, volume, mapName):
     def _processVolume(self, volume, mapName):
-        self._setMultiTaskParam('volume', mapName)
+        self._setMultiTaskParam("volume", mapName)
 
 
-        if volume['draw']['box']['enabled']:
-            self.task.set_flag('b', True)
+        if volume["draw"]["box"]["enabled"]:
+            self.task.set_flag("b", True)
 
 
         # isosurfaces
         # isosurfaces
-        isosurfaces = volume['isosurface']
+        isosurfaces = volume["isosurface"]
         if isosurfaces:
         if isosurfaces:
-            res_value = volume['draw']['resolution']['isosurface']['value']
-            self._setMultiTaskParam('volume_resolution', res_value)
+            res_value = volume["draw"]["resolution"]["isosurface"]["value"]
+            self._setMultiTaskParam("volume_resolution", res_value)
             for isosurface in isosurfaces:
             for isosurface in isosurfaces:
-                attributes = ('topo', 'color', 'shine', 'transp')
+                attributes = ("topo", "color", "shine", "transp")
                 parameters = (
                 parameters = (
-                    (None, 'isosurf_level'),
-                    ('isosurf_color_map', 'isosurf_color_value'),
-                    ('isosurf_shininess_map', 'isosurf_shininess_value'),
-                    ('isosurf_transparency_map', 'isosurf_transparency_value'))
+                    (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):
                 for attr, params in zip(attributes, parameters):
                     mapname = None
                     mapname = None
                     const = None
                     const = None
                     if attr in isosurface:
                     if attr in isosurface:
-                        if isosurface[attr]['map']:
-                            mapname = isosurface[attr]['value']
+                        if isosurface[attr]["map"]:
+                            mapname = isosurface[attr]["value"]
                         else:
                         else:
-                            const = float(isosurface[attr]['value'])
+                            const = float(isosurface[attr]["value"])
                     else:
                     else:
-                        if attr == 'transp':
+                        if attr == "transp":
                             const = 0
                             const = 0
-                        elif attr == 'color':
+                        elif attr == "color":
                             mapname = mapName
                             mapname = mapName
 
 
                     if mapname:
                     if mapname:
                         self._setMultiTaskParam(params[0], mapname)
                         self._setMultiTaskParam(params[0], mapname)
                     else:
                     else:
-                        if attr == 'topo':
+                        if attr == "topo":
                             # TODO: we just assume it's the first volume, what
                             # TODO: we just assume it's the first volume, what
                             # to do else?
                             # to do else?
-                            self._setMultiTaskParam(
-                                params[1], '1:' + str(const))
+                            self._setMultiTaskParam(params[1], "1:" + str(const))
                         else:
                         else:
                             self._setMultiTaskParam(params[1], const)
                             self._setMultiTaskParam(params[1], const)
-                if isosurface['inout']['value']:
-                    self.task.set_flag('n', True)
+                if isosurface["inout"]["value"]:
+                    self.task.set_flag("n", True)
         # slices
         # slices
-        slices = volume['slice']
+        slices = volume["slice"]
         if slices:
         if slices:
-            res_value = volume['draw']['resolution']['slice']['value']
-            self._setMultiTaskParam('volume_resolution', res_value)
+            res_value = volume["draw"]["resolution"]["slice"]["value"]
+            self._setMultiTaskParam("volume_resolution", res_value)
             for slice_ in slices:
             for slice_ in slices:
+                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(
                 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]))
+                    "slice_position", ",".join([str(c) for c in coords])
+                )
 
 
         # position
         # position
         pos = []
         pos = []
-        for coor in ('x', 'y', 'z'):
-            pos.append(str(volume['position'][coor]))
-            value = ','.join(pos)
+        for coor in ("x", "y", "z"):
+            pos.append(str(volume["position"][coor]))
+            value = ",".join(pos)
 
 
-        self._setMultiTaskParam('volume_position', value)
+        self._setMultiTaskParam("volume_position", value)
 
 
     def _processState(self, state):
     def _processState(self, state):
-        color = state['view']['background']['color']
-        self.task.set_param('bgcolor', self._join(color, delim=':'))
+        color = state["view"]["background"]["color"]
+        self.task.set_param("bgcolor", self._join(color, delim=":"))
         self.task.set_param(
         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'])
+            "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
         # TODO: fix zexag
-        self.task.set_param('zexag', state['view']['z-exag']['value'])
+        self.task.set_param("zexag", state["view"]["z-exag"]["value"])
         self.task.set_param(
         self.task.set_param(
-            'focus', self._join(
-                (state['iview']['focus']['x'],
-                 state['iview']['focus']['y'],
-                 state['iview']['focus']['z'])))
+            "focus",
+            self._join(
+                (
+                    state["iview"]["focus"]["x"],
+                    state["iview"]["focus"]["y"],
+                    state["iview"]["focus"]["z"],
+                )
+            ),
+        )
         self.task.set_param(
         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']))
-        self.task.set_param('light_ambient', state['light']['ambient'])
+            "light_position",
+            self._join(
+                (
+                    state["light"]["position"]["x"],
+                    state["light"]["position"]["y"],
+                    state["light"]["position"]["z"] / 100.0,
+                )
+            ),
+        )
+        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"]))
+        self.task.set_param("light_ambient", state["light"]["ambient"])
 
 
     def _setMultiTaskParam(self, param, value):
     def _setMultiTaskParam(self, param, value):
-        last = self.task.get_param(param)['value']
+        last = self.task.get_param(param)["value"]
         self.task.set_param(param, self._join((last, value)))
         self.task.set_param(param, self._join((last, value)))
 
 
-    def _join(self, toJoin, delim=','):
+    def _join(self, toJoin, delim=","):
         toJoin = filter(self._ignore, toJoin)
         toJoin = filter(self._ignore, toJoin)
         return delim.join(map(str, toJoin))
         return delim.join(map(str, toJoin))
 
 
     def _ignore(self, value):
     def _ignore(self, value):
-        if value == '' or value is None:
+        if value == "" or value is None:
             return False
             return False
         else:
         else:
             return True
             return True
@@ -275,7 +303,7 @@ class NvizTask:
         # params = self.task.get_list_params()
         # params = self.task.get_list_params()
         # parameter with 'map' name
         # parameter with 'map' name
         # params = filter(lambda x: 'map' in x, params)
         # params = filter(lambda x: 'map' in x, params)
-        return ('elevation_map', 'color_map', 'vline', 'vpoint', 'volume')
+        return ("elevation_map", "color_map", "vline", "vpoint", "volume")
 
 
     def GetCommandSeries(self, layerList, paramName):
     def GetCommandSeries(self, layerList, paramName):
         commands = []
         commands = []
@@ -286,25 +314,25 @@ class NvizTask:
             raise GException(_("Please add only one layer in the list."))
             raise GException(_("Please add only one layer in the list."))
             return
             return
         layer = layerList[0]
         layer = layerList[0]
-        if hasattr(layer, 'maps'):
+        if hasattr(layer, "maps"):
             series = layer.maps
             series = layer.maps
         else:
         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:
         for value in series:
             self.task.set_param(paramName, value)
             self.task.set_param(paramName, value)
             # FIXME: we assume we want always default color map
             # FIXME: we assume we want always default color map
-            if paramName == 'elevation_map':
-                self.task.set_param('color_map', self.task.get_param(paramName)['value'])
-            if paramName == 'volume':
-                self.task.set_param('isosurf_color_map', '')
-            self.task.set_flag('overwrite', True)
-            self.task.set_param('output', 'tobechanged')
+            if paramName == "elevation_map":
+                self.task.set_param(
+                    "color_map", self.task.get_param(paramName)["value"]
+                )
+            if paramName == "volume":
+                self.task.set_param("isosurf_color_map", "")
+            self.task.set_flag("overwrite", True)
+            self.task.set_param("output", "tobechanged")
             cmd = self.task.get_cmd(
             cmd = self.task.get_cmd(
-                ignoreErrors=False,
-                ignoreRequired=False,
-                ignoreDefault=True)
+                ignoreErrors=False, ignoreRequired=False, ignoreDefault=True
+            )
             commands.append(cmd)
             commands.append(cmd)
 
 
         return commands
         return commands
@@ -312,12 +340,11 @@ class NvizTask:
     def GetCommand(self):
     def GetCommand(self):
         if not self.task:
         if not self.task:
             return None
             return None
-        self.task.set_flag('overwrite', True)
-        self.task.set_param('output', 'tobechanged')
+        self.task.set_flag("overwrite", True)
+        self.task.set_param("output", "tobechanged")
         cmd = self.task.get_cmd(
         cmd = self.task.get_cmd(
-            ignoreErrors=False,
-            ignoreRequired=False,
-            ignoreDefault=True)
+            ignoreErrors=False, ignoreRequired=False, ignoreDefault=True
+        )
         return gtask.cmdlist_to_tuple(cmd)
         return gtask.cmdlist_to_tuple(cmd)
 
 
     def GetRegion(self):
     def GetRegion(self):
@@ -325,18 +352,17 @@ class NvizTask:
 
 
 
 
 def test():
 def test():
-    nviz = NvizTask('/home/anna/testy/nviz/t12.gxw')
+    nviz = NvizTask("/home/anna/testy/nviz/t12.gxw")
     # nviz = NvizState('/home/anna/testy/nviz/t3.gxw')
     # nviz = NvizState('/home/anna/testy/nviz/t3.gxw')
 
 
     # cmd = nviz.GetCommand()
     # cmd = nviz.GetCommand()
-    cmds = nviz.GetCommandSeries(['aspect', 'elevation'], 'color_map')
+    cmds = nviz.GetCommandSeries(["aspect", "elevation"], "color_map")
     for cmd in cmds:
     for cmd in cmds:
         print(cmd)
         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)
         print(returncode, message)
 
 
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
 
 
     test()
     test()

+ 233 - 194
gui/wxpython/animation/provider.py

@@ -45,12 +45,15 @@ class BitmapProvider:
     It handles both 2D and 3D animations.
     It handles both 2D and 3D animations.
     """
     """
 
 
-    def __init__(self, bitmapPool, mapFilesPool, tempDir,
-                 imageWidth=640, imageHeight=480):
+    def __init__(
+        self, bitmapPool, mapFilesPool, tempDir, imageWidth=640, imageHeight=480
+    ):
 
 
         self._bitmapPool = bitmapPool
         self._bitmapPool = bitmapPool
         self._mapFilesPool = mapFilesPool
         self._mapFilesPool = mapFilesPool
-        self.imageWidth = imageWidth  # width of the image to render with d.rast or d.vect
+        self.imageWidth = (
+            imageWidth  # width of the image to render with d.rast or d.vect
+        )
         # 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.imageHeight = imageHeight
         self._tempDir = tempDir
         self._tempDir = tempDir
@@ -64,19 +67,23 @@ class BitmapProvider:
         self._regions = []
         self._regions = []
         self._regionsForUniqueCmds = []
         self._regionsForUniqueCmds = []
 
 
-        self._renderer = BitmapRenderer(self._mapFilesPool, self._tempDir,
-                                        self.imageWidth, self.imageHeight)
-        self._composer = BitmapComposer(self._tempDir, self._mapFilesPool,
-                                        self._bitmapPool, self.imageWidth,
-                                        self.imageHeight)
-        self.renderingStarted = Signal('BitmapProvider.renderingStarted')
-        self.compositionStarted = Signal('BitmapProvider.compositionStarted')
-        self.renderingContinues = Signal('BitmapProvider.renderingContinues')
-        self.compositionContinues = Signal(
-            'BitmapProvider.compositionContinues')
-        self.renderingFinished = Signal('BitmapProvider.renderingFinished')
-        self.compositionFinished = Signal('BitmapProvider.compositionFinished')
-        self.mapsLoaded = Signal('BitmapProvider.mapsLoaded')
+        self._renderer = BitmapRenderer(
+            self._mapFilesPool, self._tempDir, self.imageWidth, self.imageHeight
+        )
+        self._composer = BitmapComposer(
+            self._tempDir,
+            self._mapFilesPool,
+            self._bitmapPool,
+            self.imageWidth,
+            self.imageHeight,
+        )
+        self.renderingStarted = Signal("BitmapProvider.renderingStarted")
+        self.compositionStarted = Signal("BitmapProvider.compositionStarted")
+        self.renderingContinues = Signal("BitmapProvider.renderingContinues")
+        self.compositionContinues = Signal("BitmapProvider.compositionContinues")
+        self.renderingFinished = Signal("BitmapProvider.renderingFinished")
+        self.compositionFinished = Signal("BitmapProvider.compositionFinished")
+        self.mapsLoaded = Signal("BitmapProvider.mapsLoaded")
 
 
         self._renderer.renderingContinues.connect(self.renderingContinues)
         self._renderer.renderingContinues.connect(self.renderingContinues)
         self._composer.compositionContinues.connect(self.compositionContinues)
         self._composer.compositionContinues.connect(self.compositionContinues)
@@ -93,8 +100,8 @@ class BitmapProvider:
         :param regions: list of regions
         :param regions: list of regions
         """
         """
         Debug.msg(
         Debug.msg(
-            2, "BitmapProvider.SetCmds: {n} lists".format(
-                n=len(cmdsForComposition)))
+            2, "BitmapProvider.SetCmds: {n} lists".format(n=len(cmdsForComposition))
+        )
         self._cmdsForComposition.extend(cmdsForComposition)
         self._cmdsForComposition.extend(cmdsForComposition)
         self._opacities.extend(opacities)
         self._opacities.extend(opacities)
         self._regions.extend(regions)
         self._regions.extend(regions)
@@ -107,9 +114,7 @@ class BitmapProvider:
         :param cmds: list of commands m.nviz.image (cmd as a list)
         :param cmds: list of commands m.nviz.image (cmd as a list)
         :param region: for 3D rendering
         :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._cmds3D = cmds
         self._regionFor3D = region
         self._regionFor3D = region
 
 
@@ -125,8 +130,12 @@ class BitmapProvider:
                     unique.append((tuple(cmd), None))
                     unique.append((tuple(cmd), None))
         unique = list(set(unique))
         unique = list(set(unique))
         self._uniqueCmds = [cmdAndRegion[0] for cmdAndRegion in 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):
     def Unload(self):
         """Unloads currently loaded data.
         """Unloads currently loaded data.
@@ -134,12 +143,10 @@ class BitmapProvider:
         """
         """
         Debug.msg(2, "BitmapProvider.Unload")
         Debug.msg(2, "BitmapProvider.Unload")
         if self._cmdsForComposition:
         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)]
                 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)]
                 del self._bitmapPool[HashCmds(cmdList, region)]
             self._uniqueCmds = []
             self._uniqueCmds = []
             self._cmdsForComposition = []
             self._cmdsForComposition = []
@@ -160,15 +167,18 @@ class BitmapProvider:
         count = 0
         count = 0
         for cmd, region in zip(uniqueCmds, regions):
         for cmd, region in zip(uniqueCmds, regions):
             filename = GetFileFromCmd(self._tempDir, cmd, region)
             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
                 continue
             count += 1
             count += 1
 
 
         Debug.msg(
         Debug.msg(
-            3,
-            "BitmapProvider._dryRender: {c} files to be rendered".format(
-                c=count))
+            3, "BitmapProvider._dryRender: {c} files to be rendered".format(c=count)
+        )
 
 
         return count
         return count
 
 
@@ -182,17 +192,18 @@ class BitmapProvider:
         """
         """
         count = 0
         count = 0
         for cmdList, region in zip(cmdLists, regions):
         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
                 continue
             count += 1
             count += 1
 
 
         Debug.msg(
         Debug.msg(
-            2,
-            "BitmapProvider._dryCompose: {c} files to be composed".format(
-                c=count))
+            2, "BitmapProvider._dryCompose: {c} files to be composed".format(c=count)
+        )
 
 
         return count
         return count
 
 
@@ -204,10 +215,11 @@ class BitmapProvider:
         :param bgcolor: background color as a tuple of 3 values 0 to 255
         :param bgcolor: background color as a tuple of 3 values 0 to 255
         :param nprocs: number of procs to be used for rendering
         :param nprocs: number of procs to be used for rendering
         """
         """
-        Debug.msg(2, "BitmapProvider.Load: "
-                     "force={f}, bgcolor={b}, nprocs={n}".format(f=force,
-                                                                 b=bgcolor,
-                                                                 n=nprocs))
+        Debug.msg(
+            2,
+            "BitmapProvider.Load: "
+            "force={f}, bgcolor={b}, nprocs={n}".format(f=force, b=bgcolor, n=nprocs),
+        )
         cmds = []
         cmds = []
         regions = []
         regions = []
         if self._uniqueCmds:
         if self._uniqueCmds:
@@ -223,7 +235,8 @@ class BitmapProvider:
         # create no data bitmap
         # create no data bitmap
         if None not in self._bitmapPool or force:
         if None not in self._bitmapPool or force:
             self._bitmapPool[None] = createNoDataBitmap(
             self._bitmapPool[None] = createNoDataBitmap(
-                self.imageWidth, self.imageHeight)
+                self.imageWidth, self.imageHeight
+            )
 
 
         ok = self._renderer.Render(
         ok = self._renderer.Render(
             cmds,
             cmds,
@@ -231,16 +244,16 @@ class BitmapProvider:
             regionFor3D=self._regionFor3D,
             regionFor3D=self._regionFor3D,
             bgcolor=bgcolor,
             bgcolor=bgcolor,
             force=force,
             force=force,
-            nprocs=nprocs)
+            nprocs=nprocs,
+        )
         self.renderingFinished.emit()
         self.renderingFinished.emit()
         if not ok:
         if not ok:
             self.mapsLoaded.emit()  # what to do here?
             self.mapsLoaded.emit()  # what to do here?
             return
             return
         if self._cmdsForComposition:
         if self._cmdsForComposition:
             count = self._dryCompose(
             count = self._dryCompose(
-                self._cmdsForComposition,
-                self._regions,
-                force=force)
+                self._cmdsForComposition, self._regions, force=force
+            )
             self.compositionStarted.emit(count=count)
             self.compositionStarted.emit(count=count)
             self._composer.Compose(
             self._composer.Compose(
                 self._cmdsForComposition,
                 self._cmdsForComposition,
@@ -248,12 +261,14 @@ class BitmapProvider:
                 self._opacities,
                 self._opacities,
                 bgcolor=bgcolor,
                 bgcolor=bgcolor,
                 force=force,
                 force=force,
-                nprocs=nprocs)
+                nprocs=nprocs,
+            )
             self.compositionFinished.emit()
             self.compositionFinished.emit()
         if self._cmds3D:
         if self._cmds3D:
             for cmd in self._cmds3D:
             for cmd in self._cmds3D:
-                self._bitmapPool[HashCmds([cmd], None)] = \
-                    wx.Bitmap(GetFileFromCmd(self._tempDir, cmd, None))
+                self._bitmapPool[HashCmds([cmd], None)] = wx.Bitmap(
+                    GetFileFromCmd(self._tempDir, cmd, None)
+                )
 
 
         self.mapsLoaded.emit()
         self.mapsLoaded.emit()
 
 
@@ -278,8 +293,9 @@ class BitmapProvider:
     def WindowSizeChanged(self, width, height):
     def WindowSizeChanged(self, width, height):
         """Sets size when size of related window changes."""
         """Sets size when size of related window changes."""
         Debug.msg(
         Debug.msg(
-            5, "BitmapProvider.WindowSizeChanged: w={w}, h={h}".format(
-                w=width, h=height))
+            5,
+            "BitmapProvider.WindowSizeChanged: w={w}, h={h}".format(w=width, h=height),
+        )
 
 
         self.imageWidth, self.imageHeight = width, height
         self.imageWidth, self.imageHeight = width, height
 
 
@@ -298,13 +314,17 @@ class BitmapProvider:
         fileHandler, filename = tempfile.mkstemp(suffix=".png")
         fileHandler, filename = tempfile.mkstemp(suffix=".png")
         os.close(fileHandler)
         os.close(fileHandler)
         # Set the environment variables for this process
         # Set the environment variables for this process
-        _setEnvironment(self.imageWidth, self.imageHeight, filename,
-                        transparent=True, bgcolor=(0, 0, 0))
+        _setEnvironment(
+            self.imageWidth,
+            self.imageHeight,
+            filename,
+            transparent=True,
+            bgcolor=(0, 0, 0),
+        )
 
 
         Debug.msg(1, "Render raster legend " + str(filename))
         Debug.msg(1, "Render raster legend " + str(filename))
         cmdTuple = cmdlist_to_tuple(cmd)
         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:
         if returncode == 0:
             return BitmapFromImage(autoCropImageFromFile(filename))
             return BitmapFromImage(autoCropImageFromFile(filename))
@@ -316,14 +336,13 @@ class BitmapProvider:
 class BitmapRenderer:
 class BitmapRenderer:
     """Class which renders 2D and 3D images to files."""
     """Class which renders 2D and 3D images to files."""
 
 
-    def __init__(self, mapFilesPool, tempDir,
-                 imageWidth, imageHeight):
+    def __init__(self, mapFilesPool, tempDir, imageWidth, imageHeight):
         self._mapFilesPool = mapFilesPool
         self._mapFilesPool = mapFilesPool
         self._tempDir = tempDir
         self._tempDir = tempDir
         self.imageWidth = imageWidth
         self.imageWidth = imageWidth
         self.imageHeight = imageHeight
         self.imageHeight = imageHeight
 
 
-        self.renderingContinues = Signal('BitmapRenderer.renderingContinues')
+        self.renderingContinues = Signal("BitmapRenderer.renderingContinues")
         self._stopRendering = False
         self._stopRendering = False
         self._isRendering = False
         self._isRendering = False
 
 
@@ -349,8 +368,12 @@ class BitmapRenderer:
         filteredCmdList = []
         filteredCmdList = []
         for cmd, region in zip(cmdList, regions):
         for cmd, region in zip(cmdList, regions):
             filename = GetFileFromCmd(self._tempDir, cmd, region)
             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
                 # for reference counting
                 self._mapFilesPool[HashCmd(cmd, region)] = filename
                 self._mapFilesPool[HashCmd(cmd, region)] = filename
                 continue
                 continue
@@ -365,7 +388,7 @@ class BitmapRenderer:
             # Queue object for interprocess communication
             # Queue object for interprocess communication
             q = Queue()
             q = Queue()
             # The separate render process
             # The separate render process
-            if cmd[0] == 'm.nviz.image':
+            if cmd[0] == "m.nviz.image":
                 p = Process(
                 p = Process(
                     target=RenderProcess3D,
                     target=RenderProcess3D,
                     args=(
                     args=(
@@ -375,7 +398,9 @@ class BitmapRenderer:
                         cmd,
                         cmd,
                         regionFor3D,
                         regionFor3D,
                         bgcolor,
                         bgcolor,
-                        q))
+                        q,
+                    ),
+                )
             else:
             else:
                 p = Process(
                 p = Process(
                     target=RenderProcess2D,
                     target=RenderProcess2D,
@@ -386,7 +411,9 @@ class BitmapRenderer:
                         cmd,
                         cmd,
                         region,
                         region,
                         bgcolor,
                         bgcolor,
-                        q))
+                        q,
+                    ),
+                )
             p.start()
             p.start()
 
 
             queue_list.append(q)
             queue_list.append(q)
@@ -400,21 +427,19 @@ class BitmapRenderer:
                     proc_list[i].join()
                     proc_list[i].join()
                     filename = queue_list[i].get()
                     filename = queue_list[i].get()
                     self._mapFilesPool[
                     self._mapFilesPool[
-                        HashCmd(
-                            cmd_list[i][0],
-                            cmd_list[i][1])] = filename
+                        HashCmd(cmd_list[i][0], cmd_list[i][1])
+                    ] = filename
                     self._mapFilesPool.SetSize(
                     self._mapFilesPool.SetSize(
-                        HashCmd(cmd_list[i][0],
-                                cmd_list[i][1]),
-                        (self.imageWidth, self.imageHeight))
+                        HashCmd(cmd_list[i][0], cmd_list[i][1]),
+                        (self.imageWidth, self.imageHeight),
+                    )
 
 
                 proc_count = 0
                 proc_count = 0
                 proc_list = []
                 proc_list = []
                 queue_list = []
                 queue_list = []
                 cmd_list = []
                 cmd_list = []
 
 
-            self.renderingContinues.emit(
-                current=count, text=_("Rendering map layers"))
+            self.renderingContinues.emit(current=count, text=_("Rendering map layers"))
             if self._stopRendering:
             if self._stopRendering:
                 self._stopRendering = False
                 self._stopRendering = False
                 stopped = True
                 stopped = True
@@ -432,15 +457,14 @@ class BitmapRenderer:
 class BitmapComposer:
 class BitmapComposer:
     """Class which handles the composition of image files with g.pnmcomp."""
     """Class which handles the composition of image files with g.pnmcomp."""
 
 
-    def __init__(self, tempDir, mapFilesPool, bitmapPool,
-                 imageWidth, imageHeight):
+    def __init__(self, tempDir, mapFilesPool, bitmapPool, imageWidth, imageHeight):
         self._mapFilesPool = mapFilesPool
         self._mapFilesPool = mapFilesPool
         self._bitmapPool = bitmapPool
         self._bitmapPool = bitmapPool
         self._tempDir = tempDir
         self._tempDir = tempDir
         self.imageWidth = imageWidth
         self.imageWidth = imageWidth
         self.imageHeight = imageHeight
         self.imageHeight = imageHeight
 
 
-        self.compositionContinues = Signal('BitmapComposer.composingContinues')
+        self.compositionContinues = Signal("BitmapComposer.composingContinues")
         self._stopComposing = False
         self._stopComposing = False
         self._isComposing = False
         self._isComposing = False
 
 
@@ -466,19 +490,17 @@ class BitmapComposer:
 
 
         filteredCmdLists = []
         filteredCmdLists = []
         for cmdList, region in zip(cmdLists, regions):
         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)
+            ):
                 # TODO: find a better way than to assign the same to increase
                 # TODO: find a better way than to assign the same to increase
                 # the reference
                 # the reference
-                self._bitmapPool[
-                    HashCmds(
-                        cmdList,
-                        region)] = self._bitmapPool[
-                    HashCmds(
-                        cmdList,
-                        region)]
+                self._bitmapPool[HashCmds(cmdList, region)] = self._bitmapPool[
+                    HashCmds(cmdList, region)
+                ]
                 continue
                 continue
             filteredCmdLists.append((cmdList, region))
             filteredCmdLists.append((cmdList, region))
 
 
@@ -490,9 +512,19 @@ class BitmapComposer:
             # Queue object for interprocess communication
             # Queue object for interprocess communication
             q = Queue()
             q = Queue()
             # The separate render process
             # The separate render process
-            p = Process(target=CompositeProcess,
-                        args=(self.imageWidth, self.imageHeight, self._tempDir,
-                              cmdList, region, opacityList, bgcolor, q))
+            p = Process(
+                target=CompositeProcess,
+                args=(
+                    self.imageWidth,
+                    self.imageHeight,
+                    self._tempDir,
+                    cmdList,
+                    region,
+                    opacityList,
+                    bgcolor,
+                    q,
+                ),
+            )
             p.start()
             p.start()
 
 
             queue_list.append(q)
             queue_list.append(q)
@@ -508,18 +540,14 @@ class BitmapComposer:
                     filename = queue_list[i].get()
                     filename = queue_list[i].get()
                     if filename is None:
                     if filename is None:
                         self._bitmapPool[
                         self._bitmapPool[
-                            HashCmds(
-                                cmd_lists[i][0],
-                                cmd_lists[i][1])] = createNoDataBitmap(
-                            self.imageWidth,
-                            self.imageHeight,
-                            text="Failed to render")
+                            HashCmds(cmd_lists[i][0], cmd_lists[i][1])
+                        ] = createNoDataBitmap(
+                            self.imageWidth, self.imageHeight, text="Failed to render"
+                        )
                     else:
                     else:
                         self._bitmapPool[
                         self._bitmapPool[
-                            HashCmds(
-                                cmd_lists[i][0],
-                                cmd_lists[i][1])] = BitmapFromImage(
-                            wx.Image(filename))
+                            HashCmds(cmd_lists[i][0], cmd_lists[i][1])
+                        ] = BitmapFromImage(wx.Image(filename))
                         os.remove(filename)
                         os.remove(filename)
                 proc_count = 0
                 proc_count = 0
                 proc_list = []
                 proc_list = []
@@ -527,7 +555,8 @@ class BitmapComposer:
                 cmd_lists = []
                 cmd_lists = []
 
 
             self.compositionContinues.emit(
             self.compositionContinues.emit(
-                current=count, text=_("Overlaying map layers"))
+                current=count, text=_("Overlaying map layers")
+            )
             if self._stopComposing:
             if self._stopComposing:
                 self._stopComposing = False
                 self._stopComposing = False
                 break
                 break
@@ -540,8 +569,7 @@ class BitmapComposer:
             self._stopComposing = True
             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
     """Render raster or vector files as ppm image and write the
        resulting ppm filename in the provided file queue
        resulting ppm filename in the provided file queue
 
 
@@ -559,27 +587,27 @@ def RenderProcess2D(imageWidth, imageHeight, tempDir,
     transparency = True
     transparency = True
 
 
     # Set the environment variables for this process
     # Set the environment variables for this process
-    _setEnvironment(imageWidth, imageHeight, filename,
-                    transparent=transparency, bgcolor=bgcolor)
+    _setEnvironment(
+        imageWidth, imageHeight, filename, transparent=transparency, bgcolor=bgcolor
+    )
     if region:
     if region:
-        os.environ['GRASS_REGION'] = gcore.region_env(**region)
+        os.environ["GRASS_REGION"] = gcore.region_env(**region)
     cmdTuple = cmdlist_to_tuple(cmd)
     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:
     if returncode != 0:
         gcore.warning("Rendering failed:\n" + messages)
         gcore.warning("Rendering failed:\n" + messages)
         fileQueue.put(None)
         fileQueue.put(None)
         if region:
         if region:
-            os.environ.pop('GRASS_REGION')
+            os.environ.pop("GRASS_REGION")
         os.remove(filename)
         os.remove(filename)
         return
         return
 
 
     if region:
     if region:
-        os.environ.pop('GRASS_REGION')
+        os.environ.pop("GRASS_REGION")
     fileQueue.put(filename)
     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
     """Renders image with m.nviz.image and writes the
        resulting ppm filename in the provided file queue
        resulting ppm filename in the provided file queue
 
 
@@ -594,30 +622,30 @@ def RenderProcess3D(imageWidth, imageHeight, tempDir,
     """
     """
 
 
     filename = GetFileFromCmd(tempDir, cmd, None)
     filename = GetFileFromCmd(tempDir, cmd, None)
-    os.environ['GRASS_REGION'] = gcore.region_env(region3d=True, **region)
+    os.environ["GRASS_REGION"] = gcore.region_env(region3d=True, **region)
     Debug.msg(1, "Render image to file " + str(filename))
     Debug.msg(1, "Render image to file " + str(filename))
 
 
     cmdTuple = cmdlist_to_tuple(cmd)
     cmdTuple = cmdlist_to_tuple(cmd)
-    cmdTuple[1]['output'] = os.path.splitext(filename)[0]
+    cmdTuple[1]["output"] = os.path.splitext(filename)[0]
     # set size
     # set size
-    cmdTuple[1]['size'] = '%d,%d' % (imageWidth, imageHeight)
+    cmdTuple[1]["size"] = "%d,%d" % (imageWidth, imageHeight)
     # set format
     # set format
-    cmdTuple[1]['format'] = 'ppm'
-    cmdTuple[1]['bgcolor'] = bgcolor = ':'.join(
-        [str(part) for part in bgcolor])
+    cmdTuple[1]["format"] = "ppm"
+    cmdTuple[1]["bgcolor"] = bgcolor = ":".join([str(part) for part in bgcolor])
     returncode, stdout, messages = read2_command(cmdTuple[0], **cmdTuple[1])
     returncode, stdout, messages = read2_command(cmdTuple[0], **cmdTuple[1])
     if returncode != 0:
     if returncode != 0:
         gcore.warning("Rendering failed:\n" + messages)
         gcore.warning("Rendering failed:\n" + messages)
         fileQueue.put(None)
         fileQueue.put(None)
-        os.environ.pop('GRASS_REGION')
+        os.environ.pop("GRASS_REGION")
         return
         return
 
 
-    os.environ.pop('GRASS_REGION')
+    os.environ.pop("GRASS_REGION")
     fileQueue.put(filename)
     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
     """Performs the composition of image ppm files and writes the
        resulting ppm filename in the provided file queue
        resulting ppm filename in the provided file queue
 
 
@@ -636,19 +664,26 @@ def CompositeProcess(imageWidth, imageHeight, tempDir,
     masks = []
     masks = []
     for cmd in cmdList:
     for cmd in cmdList:
         maps.append(GetFileFromCmd(tempDir, cmd, region))
         maps.append(GetFileFromCmd(tempDir, cmd, region))
-        masks.append(GetFileFromCmd(tempDir, cmd, region, 'pgm'))
+        masks.append(GetFileFromCmd(tempDir, cmd, region, "pgm"))
     filename = GetFileFromCmds(tempDir, cmdList, region)
     filename = GetFileFromCmds(tempDir, cmdList, region)
     # Set the environment variables for this process
     # Set the environment variables for this process
-    _setEnvironment(imageWidth, imageHeight, filename,
-                    transparent=False, bgcolor=bgcolor)
+    _setEnvironment(
+        imageWidth, imageHeight, filename, transparent=False, bgcolor=bgcolor
+    )
 
 
     opacities = [str(op) for op in opacities]
     opacities = [str(op) for op in opacities]
-    bgcolor = ':'.join([str(part) for part in bgcolor])
+    bgcolor = ":".join([str(part) for part in bgcolor])
     returncode, stdout, messages = read2_command(
     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)
+        "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:
     if returncode != 0:
         gcore.warning("Rendering composite failed:\n" + messages)
         gcore.warning("Rendering composite failed:\n" + messages)
@@ -677,23 +712,21 @@ class DictRefCounter:
             self.referenceCount[key] = 1
             self.referenceCount[key] = 1
         else:
         else:
             self.referenceCount[key] += 1
             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):
     def __contains__(self, key):
         return key in self.dictionary
         return key in self.dictionary
 
 
     def __delitem__(self, key):
     def __delitem__(self, key):
         self.referenceCount[key] -= 1
         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):
     def keys(self):
         return self.dictionary.keys()
         return self.dictionary.keys()
 
 
     def Clear(self):
     def Clear(self):
         """Clears items which are not needed any more."""
         """Clears items which are not needed any more."""
-        Debug.msg(4, 'DictRefCounter.Clear')
+        Debug.msg(4, "DictRefCounter.Clear")
         for key in self.dictionary.copy().keys():
         for key in self.dictionary.copy().keys():
             if key is not None:
             if key is not None:
                 if self.referenceCount[key] <= 0:
                 if self.referenceCount[key] <= 0:
@@ -718,14 +751,14 @@ class MapFilesPool(DictRefCounter):
         """Removes files which are not needed anymore.
         """Removes files which are not needed anymore.
         Removes both ppm and pgm.
         Removes both ppm and pgm.
         """
         """
-        Debug.msg(4, 'MapFilesPool.Clear')
+        Debug.msg(4, "MapFilesPool.Clear")
 
 
         for key in self.dictionary.keys():
         for key in self.dictionary.keys():
             if self.referenceCount[key] <= 0:
             if self.referenceCount[key] <= 0:
                 name, ext = os.path.splitext(self.dictionary[key])
                 name, ext = os.path.splitext(self.dictionary[key])
                 os.remove(self.dictionary[key])
                 os.remove(self.dictionary[key])
-                if ext == '.ppm':
-                    os.remove(name + '.pgm')
+                if ext == ".ppm":
+                    os.remove(name + ".pgm")
                 del self.dictionary[key]
                 del self.dictionary[key]
                 del self.referenceCount[key]
                 del self.referenceCount[key]
                 del self.size[key]
                 del self.size[key]
@@ -746,16 +779,13 @@ class CleanUp:
 
 
     def __call__(self):
     def __call__(self):
         import shutil
         import shutil
+
         if os.path.exists(self._tempDir):
         if os.path.exists(self._tempDir):
             try:
             try:
                 shutil.rmtree(self._tempDir)
                 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:
             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):
 def _setEnvironment(width, height, filename, transparent, bgcolor):
@@ -771,24 +801,23 @@ def _setEnvironment(width, height, filename, transparent, bgcolor):
         5,
         5,
         "_setEnvironment: width={w}, height={h}, "
         "_setEnvironment: width={w}, height={h}, "
         "filename={f}, transparent={t}, bgcolor={b}".format(
         "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_TRUECOLOR'] = "TRUE"
+            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_TRUECOLOR"] = "TRUE"
     if transparent:
     if transparent:
-        os.environ['GRASS_RENDER_TRANSPARENT'] = "TRUE"
+        os.environ["GRASS_RENDER_TRANSPARENT"] = "TRUE"
     else:
     else:
-        os.environ['GRASS_RENDER_TRANSPARENT'] = "FALSE"
-    os.environ['GRASS_RENDER_FILE'] = str(filename)
+        os.environ["GRASS_RENDER_TRANSPARENT"] = "FALSE"
+    os.environ["GRASS_RENDER_FILE"] = str(filename)
 
 
 
 
 def createNoDataBitmap(imageWidth, imageHeight, text="No data"):
 def createNoDataBitmap(imageWidth, imageHeight, text="No data"):
@@ -800,15 +829,25 @@ def createNoDataBitmap(imageWidth, imageHeight, text="No data"):
     :param imageWidth: image width
     :param imageWidth: image width
     :param imageHeight: image height
     :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 = EmptyBitmap(imageWidth, imageHeight)
     bitmap = EmptyBitmap(imageWidth, imageHeight)
     dc = wx.MemoryDC()
     dc = wx.MemoryDC()
     dc.SelectObject(bitmap)
     dc.SelectObject(bitmap)
     dc.Clear()
     dc.Clear()
     text = _(text)
     text = _(text)
-    dc.SetFont(wx.Font(pointSize=40, family=wx.FONTFAMILY_SCRIPT,
-                       style=wx.FONTSTYLE_NORMAL, weight=wx.FONTWEIGHT_BOLD))
+    dc.SetFont(
+        wx.Font(
+            pointSize=40,
+            family=wx.FONTFAMILY_SCRIPT,
+            style=wx.FONTSTYLE_NORMAL,
+            weight=wx.FONTWEIGHT_BOLD,
+        )
+    )
     tw, th = dc.GetTextExtent(text)
     tw, th = dc.GetTextExtent(text)
     dc.DrawText(text, (imageWidth - tw) / 2, (imageHeight - th) / 2)
     dc.DrawText(text, (imageWidth - tw) / 2, (imageHeight - th) / 2)
     dc.SelectObject(wx.NullBitmap)
     dc.SelectObject(wx.NullBitmap)
@@ -816,8 +855,8 @@ def createNoDataBitmap(imageWidth, imageHeight, text="No data"):
 
 
 
 
 def read2_command(*args, **kwargs):
 def read2_command(*args, **kwargs):
-    kwargs['stdout'] = gcore.PIPE
-    kwargs['stderr'] = gcore.PIPE
+    kwargs["stdout"] = gcore.PIPE
+    kwargs["stderr"] = gcore.PIPE
     ps = gcore.start_command(*args, **kwargs)
     ps = gcore.start_command(*args, **kwargs)
     stdout, stderr = ps.communicate()
     stdout, stderr = ps.communicate()
     return ps.returncode, DecodeString(stdout), DecodeString(stderr)
     return ps.returncode, DecodeString(stdout), DecodeString(stderr)
@@ -830,53 +869,55 @@ def test():
     from animation.data import AnimLayer
     from animation.data import AnimLayer
     from animation.utils import layerListToCmdsMatrix
     from animation.utils import layerListToCmdsMatrix
     import grass.temporal as tgis
     import grass.temporal as tgis
+
     tgis.init()
     tgis.init()
 
 
     layerList = LayerList()
     layerList = LayerList()
     layer = AnimLayer()
     layer = AnimLayer()
-    layer.mapType = 'strds'
-    layer.name = 'JR'
-    layer.cmd = ['d.rast', 'map=elev_2007_1m']
+    layer.mapType = "strds"
+    layer.name = "JR"
+    layer.cmd = ["d.rast", "map=elev_2007_1m"]
     layerList.AddLayer(layer)
     layerList.AddLayer(layer)
 
 
     layer = Layer()
     layer = Layer()
-    layer.mapType = 'vector'
-    layer.name = 'buildings_2009_approx'
-    layer.cmd = ['d.vect', 'map=buildings_2009_approx',
-                 'color=grey']
+    layer.mapType = "vector"
+    layer.name = "buildings_2009_approx"
+    layer.cmd = ["d.vect", "map=buildings_2009_approx", "color=grey"]
     layer.opacity = 50
     layer.opacity = 50
     layerList.AddLayer(layer)
     layerList.AddLayer(layer)
 
 
     bPool = BitmapPool()
     bPool = BitmapPool()
     mapFilesPool = MapFilesPool()
     mapFilesPool = MapFilesPool()
 
 
-    tempDir = '/tmp/test'
+    tempDir = "/tmp/test"
     if os.path.exists(tempDir):
     if os.path.exists(tempDir):
         shutil.rmtree(tempDir)
         shutil.rmtree(tempDir)
     os.mkdir(tempDir)
     os.mkdir(tempDir)
     # comment this line to keep the directory after prgm ends
     # comment this line to keep the directory after prgm ends
-#    cleanUp = CleanUp(tempDir)
-#    import atexit
-#    atexit.register(cleanUp)
+    #    cleanUp = CleanUp(tempDir)
+    #    import atexit
+    #    atexit.register(cleanUp)
 
 
-    prov = BitmapProvider(bPool, mapFilesPool, tempDir,
-                          imageWidth=640, imageHeight=480)
+    prov = BitmapProvider(bPool, mapFilesPool, tempDir, imageWidth=640, imageHeight=480)
     prov.renderingStarted.connect(
     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(
     prov.renderingContinues.connect(
         lambda current, text: sys.stdout.write(
         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)))
+            "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(
     prov.compositionContinues.connect(
         lambda current, text: sys.stdout.write(
         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"))
+            "Composition: Current number: {c}\n".format(c=current)
+        )
+    )
+    prov.mapsLoaded.connect(lambda: sys.stdout.write("Maps loading finished\n"))
     cmdMatrix = layerListToCmdsMatrix(layerList)
     cmdMatrix = layerListToCmdsMatrix(layerList)
     prov.SetCmds(cmdMatrix, [layer.opacity for layer in layerList])
     prov.SetCmds(cmdMatrix, [layer.opacity for layer in layerList])
     app = wx.App()
     app = wx.App()
@@ -885,11 +926,9 @@ def test():
 
 
     for key in bPool.keys():
     for key in bPool.keys():
         if key is not None:
         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.Unload()
 #    prov.SetCmds(cmdMatrix, [l.opacity for l in layerList])
 #    prov.SetCmds(cmdMatrix, [l.opacity for l in layerList])
 #    prov.Load(bgcolor=(13, 156, 230))
 #    prov.Load(bgcolor=(13, 156, 230))
@@ -903,5 +942,5 @@ def test():
 #    print bPool.keys(), mapFilesPool.keys()
 #    print bPool.keys(), mapFilesPool.keys()
 
 
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     test()
     test()

+ 136 - 135
gui/wxpython/animation/temporal_manager.py

@@ -71,10 +71,8 @@ class TemporalManager(object):
         :param etype: element type (strds, stvds)
         :param etype: element type (strds, stvds)
         """
         """
         self._gatherInformation(
         self._gatherInformation(
-            timeseries,
-            etype,
-            self.timeseriesList,
-            self.timeseriesInfo)
+            timeseries, etype, self.timeseriesList, self.timeseriesInfo
+        )
 
 
     def EvaluateInputData(self):
     def EvaluateInputData(self):
         """Checks if all timeseries are compatible (raises GException).
         """Checks if all timeseries are compatible (raises GException).
@@ -102,13 +100,15 @@ class TemporalManager(object):
         # check for absolute x relative
         # check for absolute x relative
         absolute, relative = 0, 0
         absolute, relative = 0, 0
         for infoDict in self.timeseriesInfo.values():
         for infoDict in self.timeseriesInfo.values():
-            if infoDict['temporal_type'] == 'absolute':
+            if infoDict["temporal_type"] == "absolute":
                 absolute += 1
                 absolute += 1
             else:
             else:
                 relative += 1
                 relative += 1
         if bool(absolute) == bool(relative):
         if bool(absolute) == bool(relative):
-            message = _("It is not allowed to display data with different "
-                        "temporal types (absolute and relative).")
+            message = _(
+                "It is not allowed to display data with different "
+                "temporal types (absolute and relative)."
+            )
             return False, message
             return False, message
         if absolute:
         if absolute:
             self.temporalType = TemporalType.ABSOLUTE
             self.temporalType = TemporalType.ABSOLUTE
@@ -119,16 +119,17 @@ class TemporalManager(object):
         if relative:
         if relative:
             units = set()
             units = set()
             for infoDict in self.timeseriesInfo.values():
             for infoDict in self.timeseriesInfo.values():
-                units.add(infoDict['unit'])
+                units.add(infoDict["unit"])
             if len(units) > 1:
             if len(units) > 1:
                 message = _(
                 message = _(
-                    "It is not allowed to display data with different units (%s).") % ','.join(units)
+                    "It is not allowed to display data with different units (%s)."
+                ) % ",".join(units)
                 return False, message
                 return False, message
 
 
         # check for interval x point
         # check for interval x point
         interval, point = 0, 0
         interval, point = 0, 0
         for infoDict in self.timeseriesInfo.values():
         for infoDict in self.timeseriesInfo.values():
-            if infoDict['map_time'] == 'interval':
+            if infoDict["map_time"] == "interval":
                 interval += 1
                 interval += 1
             else:
             else:
                 point += 1
                 point += 1
@@ -136,20 +137,19 @@ class TemporalManager(object):
             message = _(
             message = _(
                 "You are going to display data with different "
                 "You are going to display data with different "
                 "temporal types of maps (interval and point)."
                 "temporal types of maps (interval and point)."
-                " It is recommended to use data of one temporal type to avoid confusion.")
+                " It is recommended to use data of one temporal type to avoid confusion."
+            )
             return True, message  # warning
             return True, message  # warning
 
 
         return True, None
         return True, None
 
 
     def GetGranularity(self):
     def GetGranularity(self):
-        """Returns temporal granularity of currently loaded timeseries.
-        """
+        """Returns temporal granularity of currently loaded timeseries."""
         if self.dataMode == DataMode.SIMPLE:
         if self.dataMode == DataMode.SIMPLE:
-            gran = self.timeseriesInfo[self.timeseriesList[0]]['granularity']
-            if 'unit' in self.timeseriesInfo[
-                    self.timeseriesList[0]]:  # relative:
+            gran = self.timeseriesInfo[self.timeseriesList[0]]["granularity"]
+            if "unit" in self.timeseriesInfo[self.timeseriesList[0]]:  # relative:
                 granNum = gran
                 granNum = gran
-                unit = self.timeseriesInfo[self.timeseriesList[0]]['unit']
+                unit = self.timeseriesInfo[self.timeseriesList[0]]["unit"]
                 if self.granularityMode == GranularityMode.ONE_UNIT:
                 if self.granularityMode == GranularityMode.ONE_UNIT:
                     granNum = 1
                     granNum = 1
             else:  # absolute
             else:  # absolute
@@ -165,7 +165,7 @@ class TemporalManager(object):
     def _getCommonGranularity(self):
     def _getCommonGranularity(self):
         allMaps = []
         allMaps = []
         for dataset in self.timeseriesList:
         for dataset in self.timeseriesList:
-            maps = self.timeseriesInfo[dataset]['maps']
+            maps = self.timeseriesInfo[dataset]["maps"]
             allMaps.extend(maps)
             allMaps.extend(maps)
 
 
         if self.temporalType == TemporalType.ABSOLUTE:
         if self.temporalType == TemporalType.ABSOLUTE:
@@ -175,15 +175,14 @@ class TemporalManager(object):
                 granNum = 1
                 granNum = 1
             return int(granNum), unit
             return int(granNum), unit
         if self.temporalType == TemporalType.RELATIVE:
         if self.temporalType == TemporalType.RELATIVE:
-            unit = self.timeseriesInfo[self.timeseriesList[0]]['unit']
+            unit = self.timeseriesInfo[self.timeseriesList[0]]["unit"]
             granNum = tgis.compute_relative_time_granularity(allMaps)
             granNum = tgis.compute_relative_time_granularity(allMaps)
             if self.granularityMode == GranularityMode.ONE_UNIT:
             if self.granularityMode == GranularityMode.ONE_UNIT:
                 granNum = 1
                 granNum = 1
             return (granNum, unit)
             return (granNum, unit)
 
 
     def GetLabelsAndMaps(self):
     def GetLabelsAndMaps(self):
-        """Returns time labels and map names.
-        """
+        """Returns time labels and map names."""
         mapLists = []
         mapLists = []
         labelLists = []
         labelLists = []
         labelListSet = set()
         labelListSet = set()
@@ -209,7 +208,7 @@ class TemporalManager(object):
             # compare start time
             # compare start time
             while timestamps[i][0] != labelList[0][0]:  # compare
             while timestamps[i][0] != labelList[0][0]:  # compare
                 i += 1
                 i += 1
-            newMapList[i:i + len(mapList)] = mapList
+            newMapList[i : i + len(mapList)] = mapList
             newMapLists.append(newMapList)
             newMapLists.append(newMapList)
 
 
         mapDict = {}
         mapDict = {}
@@ -219,28 +218,33 @@ class TemporalManager(object):
         if self.temporalType == TemporalType.ABSOLUTE:
         if self.temporalType == TemporalType.ABSOLUTE:
             # ('1996-01-01 00:00:00', '1997-01-01 00:00:00', 'year'),
             # ('1996-01-01 00:00:00', '1997-01-01 00:00:00', 'year'),
             formatString = UserSettings.Get(
             formatString = UserSettings.Get(
-                group='animation', key='temporal', subkey='format')
+                group="animation", key="temporal", subkey="format"
+            )
             timestamps = [
             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]
+                (
+                    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:
         else:
             # ('15', '16', u'years'),
             # ('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
         return timestamps, mapDict
 
 
     def _getLabelsAndMaps(self, timeseries):
     def _getLabelsAndMaps(self, timeseries):
         """Returns time labels and map names (done by sampling)
         """Returns time labels and map names (done by sampling)
         for both interval and point data.
         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:
         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()
         sp.select()
 
 
         listOfMaps = []
         listOfMaps = []
@@ -248,12 +252,12 @@ class TemporalManager(object):
         granNum, unit = self.GetGranularity()
         granNum, unit = self.GetGranularity()
         if self.temporalType == TemporalType.ABSOLUTE:
         if self.temporalType == TemporalType.ABSOLUTE:
             if self.granularityMode == GranularityMode.ONE_UNIT:
             if self.granularityMode == GranularityMode.ONE_UNIT:
-                gran = '%(one)d %(unit)s' % {'one': 1, 'unit': unit}
+                gran = "%(one)d %(unit)s" % {"one": 1, "unit": unit}
             else:
             else:
-                gran = '%(num)d %(unit)s' % {'num': granNum, 'unit': unit}
+                gran = "%(num)d %(unit)s" % {"num": granNum, "unit": unit}
 
 
         elif self.temporalType == TemporalType.RELATIVE:
         elif self.temporalType == TemporalType.RELATIVE:
-            unit = self.timeseriesInfo[timeseries]['unit']
+            unit = self.timeseriesInfo[timeseries]["unit"]
             if self.granularityMode == GranularityMode.ONE_UNIT:
             if self.granularityMode == GranularityMode.ONE_UNIT:
                 gran = 1
                 gran = 1
             else:
             else:
@@ -277,7 +281,7 @@ class TemporalManager(object):
                 series = map.get_id()
                 series = map.get_id()
 
 
                 start, end = map.get_temporal_extent_as_tuple()
                 start, end = map.get_temporal_extent_as_tuple()
-                if self.timeseriesInfo[timeseries]['map_time'] == 'point':
+                if self.timeseriesInfo[timeseries]["map_time"] == "point":
                     # point data
                     # point data
                     listOfMaps.append(series)
                     listOfMaps.append(series)
                     afterPoint = True
                     afterPoint = True
@@ -322,14 +326,13 @@ class TemporalManager(object):
                 end = tgis.string_to_datetime(end)
                 end = tgis.string_to_datetime(end)
                 end = tgis.datetime_to_grass_datetime_string(end)
                 end = tgis.datetime_to_grass_datetime_string(end)
             grassLabels.append((start, end, unit))
             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
                 isTime = True
         if not isTime:
         if not isTime:
             for i, (start, end, unit) in enumerate(grassLabels):
             for i, (start, end, unit) in enumerate(grassLabels):
-                start = start.replace('00:00:00', '').strip()
+                start = start.replace("00:00:00", "").strip()
                 if end is not None:
                 if end is not None:
-                    end = end.replace('00:00:00', '').strip()
+                    end = end.replace("00:00:00", "").strip()
                 grassLabels[i] = (start, end, unit)
                 grassLabels[i] = (start, end, unit)
         return grassLabels
         return grassLabels
 
 
@@ -343,33 +346,33 @@ class TemporalManager(object):
         maps = sp.get_registered_maps_as_objects()
         maps = sp.get_registered_maps_as_objects()
 
 
         if not sp.check_temporal_topology(maps):
         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)
         timeseriesList.append(id)
         infoDict[id] = {}
         infoDict[id] = {}
-        infoDict[id]['etype'] = etype
-        infoDict[id]['temporal_type'] = sp.get_temporal_type()
+        infoDict[id]["etype"] = etype
+        infoDict[id]["temporal_type"] = sp.get_temporal_type()
         if sp.is_time_relative():
         if sp.is_time_relative():
-            infoDict[id]['unit'] = sp.get_relative_time_unit()
-        infoDict[id]['granularity'] = sp.get_granularity()
-        infoDict[id]['map_time'] = sp.get_map_time()
-        infoDict[id]['maps'] = maps
+            infoDict[id]["unit"] = sp.get_relative_time_unit()
+        infoDict[id]["granularity"] = sp.get_granularity()
+        infoDict[id]["map_time"] = sp.get_map_time()
+        infoDict[id]["maps"] = maps
 
 
 
 
 def test():
 def test():
     from pprint import pprint
     from pprint import pprint
+
     # Make sure the temporal database exists
     # Make sure the temporal database exists
     tgis.init()
     tgis.init()
 
 
     temp = TemporalManager()
     temp = TemporalManager()
-#    timeseries = createAbsolutePoint()
-#    timeseries = createRelativePoint()
-#    timeseries1, timeseries2 = createAbsoluteInterval()
+    #    timeseries = createAbsolutePoint()
+    #    timeseries = createRelativePoint()
+    #    timeseries1, timeseries2 = createAbsoluteInterval()
     timeseries1, timeseries2 = createRelativeInterval()
     timeseries1, timeseries2 = createRelativeInterval()
 
 
-    temp.AddTimeSeries(timeseries1, 'strds')
-    temp.AddTimeSeries(timeseries2, 'strds')
+    temp.AddTimeSeries(timeseries1, "strds")
+    temp.AddTimeSeries(timeseries2, "strds")
 
 
     try:
     try:
         warn = temp.EvaluateInputData()
         warn = temp.EvaluateInputData()
@@ -378,7 +381,7 @@ def test():
         print(e)
         print(e)
         return
         return
 
 
-    print('///////////////////////////')
+    print("///////////////////////////")
     gran = temp.GetGranularity()
     gran = temp.GetGranularity()
     print("granularity: " + str(gran))
     print("granularity: " + str(gran))
     pprint(temp.GetLabelsAndMaps())
     pprint(temp.GetLabelsAndMaps())
@@ -386,7 +389,7 @@ def test():
 
 
 def createAbsoluteInterval():
 def createAbsoluteInterval():
     grass.run_command(
     grass.run_command(
-        'g.region',
+        "g.region",
         s=0,
         s=0,
         n=80,
         n=80,
         w=0,
         w=0,
@@ -395,8 +398,9 @@ def createAbsoluteInterval():
         t=50,
         t=50,
         res=10,
         res=10,
         res3=10,
         res3=10,
-        flags='p3',
-        quiet=True)
+        flags="p3",
+        quiet=True,
+    )
 
 
     grass.mapcalc(exp="prec_1 = rand(0, 550)", overwrite=True)
     grass.mapcalc(exp="prec_1 = rand(0, 550)", overwrite=True)
     grass.mapcalc(exp="prec_2 = rand(0, 450)", overwrite=True)
     grass.mapcalc(exp="prec_2 = rand(0, 450)", overwrite=True)
@@ -412,8 +416,8 @@ def createAbsoluteInterval():
     grass.mapcalc(exp="temp_5 = rand(0, 300)", overwrite=True)
     grass.mapcalc(exp="temp_5 = rand(0, 300)", overwrite=True)
     grass.mapcalc(exp="temp_6 = rand(0, 650)", overwrite=True)
     grass.mapcalc(exp="temp_6 = rand(0, 650)", overwrite=True)
 
 
-    n1 = grass.read_command("g.tempfile", pid=1, flags='d').strip()
-    fd = open(n1, 'w')
+    n1 = grass.read_command("g.tempfile", pid=1, flags="d").strip()
+    fd = open(n1, "w")
     fd.write(
     fd.write(
         "prec_1|2001-01-01|2001-02-01\n"
         "prec_1|2001-01-01|2001-02-01\n"
         "prec_2|2001-04-01|2001-05-01\n"
         "prec_2|2001-04-01|2001-05-01\n"
@@ -424,8 +428,8 @@ def createAbsoluteInterval():
     )
     )
     fd.close()
     fd.close()
 
 
-    n2 = grass.read_command("g.tempfile", pid=2, flags='d').strip()
-    fd = open(n2, 'w')
+    n2 = grass.read_command("g.tempfile", pid=2, flags="d").strip()
+    fd = open(n2, "w")
     fd.write(
     fd.write(
         "temp_1|2000-10-01|2001-01-01\n"
         "temp_1|2000-10-01|2001-01-01\n"
         "temp_2|2001-04-01|2001-05-01\n"
         "temp_2|2001-04-01|2001-05-01\n"
@@ -435,33 +439,34 @@ def createAbsoluteInterval():
         "temp_6|2002-05-01|2002-07-01\n"
         "temp_6|2002-05-01|2002-07-01\n"
     )
     )
     fd.close()
     fd.close()
-    name1 = 'absinterval1'
-    name2 = 'absinterval2'
-    grass.run_command('t.unregister', type='raster',
-                      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')
+    name1 = "absinterval1"
+    name2 = "absinterval2"
+    grass.run_command(
+        "t.unregister",
+        type="raster",
+        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)):
     for name, fname in zip((name1, name2), (n1, n2)):
         grass.run_command(
         grass.run_command(
-            't.create',
+            "t.create",
             overwrite=True,
             overwrite=True,
-            type='strds',
-            temporaltype='absolute',
+            type="strds",
+            temporaltype="absolute",
             output=name,
             output=name,
             title="A test with input files",
             title="A test with input files",
-            descr="A test with input files")
+            descr="A test with input files",
+        )
         grass.run_command(
         grass.run_command(
-            't.register',
-            flags='i',
-            input=name,
-            file=fname,
-            overwrite=True)
+            "t.register", flags="i", input=name, file=fname, overwrite=True
+        )
 
 
     return name1, name2
     return name1, name2
 
 
 
 
 def createRelativeInterval():
 def createRelativeInterval():
     grass.run_command(
     grass.run_command(
-        'g.region',
+        "g.region",
         s=0,
         s=0,
         n=80,
         n=80,
         w=0,
         w=0,
@@ -470,8 +475,9 @@ def createRelativeInterval():
         t=50,
         t=50,
         res=10,
         res=10,
         res3=10,
         res3=10,
-        flags='p3',
-        quiet=True)
+        flags="p3",
+        quiet=True,
+    )
 
 
     grass.mapcalc(exp="prec_1 = rand(0, 550)", overwrite=True)
     grass.mapcalc(exp="prec_1 = rand(0, 550)", overwrite=True)
     grass.mapcalc(exp="prec_2 = rand(0, 450)", overwrite=True)
     grass.mapcalc(exp="prec_2 = rand(0, 450)", overwrite=True)
@@ -487,8 +493,8 @@ def createRelativeInterval():
     grass.mapcalc(exp="temp_5 = rand(0, 300)", overwrite=True)
     grass.mapcalc(exp="temp_5 = rand(0, 300)", overwrite=True)
     grass.mapcalc(exp="temp_6 = rand(0, 650)", overwrite=True)
     grass.mapcalc(exp="temp_6 = rand(0, 650)", overwrite=True)
 
 
-    n1 = grass.read_command("g.tempfile", pid=1, flags='d').strip()
-    fd = open(n1, 'w')
+    n1 = grass.read_command("g.tempfile", pid=1, flags="d").strip()
+    fd = open(n1, "w")
     fd.write(
     fd.write(
         "prec_1|1|4\n"
         "prec_1|1|4\n"
         "prec_2|6|7\n"
         "prec_2|6|7\n"
@@ -499,8 +505,8 @@ def createRelativeInterval():
     )
     )
     fd.close()
     fd.close()
 
 
-    n2 = grass.read_command("g.tempfile", pid=2, flags='d').strip()
-    fd = open(n2, 'w')
+    n2 = grass.read_command("g.tempfile", pid=2, flags="d").strip()
+    fd = open(n2, "w")
     fd.write(
     fd.write(
         "temp_1|5|6\n"
         "temp_1|5|6\n"
         "temp_2|6|7\n"
         "temp_2|6|7\n"
@@ -510,33 +516,38 @@ def createRelativeInterval():
         "temp_6|19|22\n"
         "temp_6|19|22\n"
     )
     )
     fd.close()
     fd.close()
-    name1 = 'relinterval1'
-    name2 = 'relinterval2'
-    grass.run_command('t.unregister', type='raster',
-                      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')
+    name1 = "relinterval1"
+    name2 = "relinterval2"
+    grass.run_command(
+        "t.unregister",
+        type="raster",
+        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)):
     for name, fname in zip((name1, name2), (n1, n2)):
         grass.run_command(
         grass.run_command(
-            't.create',
+            "t.create",
             overwrite=True,
             overwrite=True,
-            type='strds',
-            temporaltype='relative',
+            type="strds",
+            temporaltype="relative",
             output=name,
             output=name,
             title="A test with input files",
             title="A test with input files",
-            descr="A test with input files")
+            descr="A test with input files",
+        )
         grass.run_command(
         grass.run_command(
-            't.register',
-            flags='i',
+            "t.register",
+            flags="i",
             input=name,
             input=name,
             file=fname,
             file=fname,
             unit="years",
             unit="years",
-            overwrite=True)
+            overwrite=True,
+        )
     return name1, name2
     return name1, name2
 
 
 
 
 def createAbsolutePoint():
 def createAbsolutePoint():
     grass.run_command(
     grass.run_command(
-        'g.region',
+        "g.region",
         s=0,
         s=0,
         n=80,
         n=80,
         w=0,
         w=0,
@@ -545,8 +556,9 @@ def createAbsolutePoint():
         t=50,
         t=50,
         res=10,
         res=10,
         res3=10,
         res3=10,
-        flags='p3',
-        quiet=True)
+        flags="p3",
+        quiet=True,
+    )
 
 
     grass.mapcalc(exp="prec_1 = rand(0, 550)", overwrite=True)
     grass.mapcalc(exp="prec_1 = rand(0, 550)", overwrite=True)
     grass.mapcalc(exp="prec_2 = rand(0, 450)", overwrite=True)
     grass.mapcalc(exp="prec_2 = rand(0, 450)", overwrite=True)
@@ -555,8 +567,8 @@ def createAbsolutePoint():
     grass.mapcalc(exp="prec_5 = rand(0, 300)", overwrite=True)
     grass.mapcalc(exp="prec_5 = rand(0, 300)", overwrite=True)
     grass.mapcalc(exp="prec_6 = rand(0, 650)", overwrite=True)
     grass.mapcalc(exp="prec_6 = rand(0, 650)", overwrite=True)
 
 
-    n1 = grass.read_command("g.tempfile", pid=1, flags='d').strip()
-    fd = open(n1, 'w')
+    n1 = grass.read_command("g.tempfile", pid=1, flags="d").strip()
+    fd = open(n1, "w")
     fd.write(
     fd.write(
         "prec_1|2001-01-01\n"
         "prec_1|2001-01-01\n"
         "prec_2|2001-03-01\n"
         "prec_2|2001-03-01\n"
@@ -566,28 +578,24 @@ def createAbsolutePoint():
         "prec_6|2001-09-01\n"
         "prec_6|2001-09-01\n"
     )
     )
     fd.close()
     fd.close()
-    name = 'abspoint'
+    name = "abspoint"
     grass.run_command(
     grass.run_command(
-        't.create',
+        "t.create",
         overwrite=True,
         overwrite=True,
-        type='strds',
-        temporaltype='absolute',
+        type="strds",
+        temporaltype="absolute",
         output=name,
         output=name,
         title="A test with input files",
         title="A test with input files",
-        descr="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.register", flags="i", input=name, file=n1, overwrite=True)
     return name
     return name
 
 
 
 
 def createRelativePoint():
 def createRelativePoint():
     grass.run_command(
     grass.run_command(
-        'g.region',
+        "g.region",
         s=0,
         s=0,
         n=80,
         n=80,
         w=0,
         w=0,
@@ -596,8 +604,9 @@ def createRelativePoint():
         t=50,
         t=50,
         res=10,
         res=10,
         res3=10,
         res3=10,
-        flags='p3',
-        quiet=True)
+        flags="p3",
+        quiet=True,
+    )
 
 
     grass.mapcalc(exp="prec_1 = rand(0, 550)", overwrite=True)
     grass.mapcalc(exp="prec_1 = rand(0, 550)", overwrite=True)
     grass.mapcalc(exp="prec_2 = rand(0, 450)", overwrite=True)
     grass.mapcalc(exp="prec_2 = rand(0, 450)", overwrite=True)
@@ -606,35 +615,27 @@ def createRelativePoint():
     grass.mapcalc(exp="prec_5 = rand(0, 300)", overwrite=True)
     grass.mapcalc(exp="prec_5 = rand(0, 300)", overwrite=True)
     grass.mapcalc(exp="prec_6 = rand(0, 650)", overwrite=True)
     grass.mapcalc(exp="prec_6 = rand(0, 650)", overwrite=True)
 
 
-    n1 = grass.read_command("g.tempfile", pid=1, flags='d').strip()
-    fd = open(n1, 'w')
+    n1 = grass.read_command("g.tempfile", pid=1, flags="d").strip()
+    fd = open(n1, "w")
     fd.write(
     fd.write(
-        "prec_1|1\n"
-        "prec_2|3\n"
-        "prec_3|5\n"
-        "prec_4|7\n"
-        "prec_5|11\n"
-        "prec_6|13\n"
+        "prec_1|1\n" "prec_2|3\n" "prec_3|5\n" "prec_4|7\n" "prec_5|11\n" "prec_6|13\n"
     )
     )
     fd.close()
     fd.close()
-    name = 'relpoint'
+    name = "relpoint"
     grass.run_command(
     grass.run_command(
-        't.create',
+        "t.create",
         overwrite=True,
         overwrite=True,
-        type='strds',
-        temporaltype='relative',
+        type="strds",
+        temporaltype="relative",
         output=name,
         output=name,
         title="A test with input files",
         title="A test with input files",
-        descr="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.register", unit="day", input=name, file=n1, overwrite=True)
     return name
     return name
 
 
-if __name__ == '__main__':
+
+if __name__ == "__main__":
 
 
     test()
     test()

+ 73 - 80
gui/wxpython/animation/toolbars.py

@@ -24,58 +24,45 @@ from gui_core.simplelmgr import SimpleLmgrToolbar
 from animation.anim import ReplayMode
 from animation.anim import ReplayMode
 
 
 ganimIcons = {
 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',
+    "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"),
         label=_("Add, edit or remove animation"),
-        desc=_("Add, edit or remove animation")),
-    'exportAnimation': MetaIcon(
-        img='layer-export',
-        label=_("Export animation"),
-        desc=_("Export animation"))}
+        desc=_("Add, edit or remove animation"),
+    ),
+    "exportAnimation": MetaIcon(
+        img="layer-export", label=_("Export animation"), desc=_("Export animation")
+    ),
+}
 
 
 SIMPLE_LMGR_STDS = 256
 SIMPLE_LMGR_STDS = 256
 
 
 
 
 simpleLmgrIcons = {
 simpleLmgrIcons = {
-    'addSeries': MetaIcon(
-        img='mapset-add',
+    "addSeries": MetaIcon(
+        img="mapset-add",
         label=_("Add space-time dataset or series of map layers"),
         label=_("Add space-time dataset or series of map layers"),
-        desc=_("Add space-time dataset or series of map layers for animation")),
+        desc=_("Add space-time dataset or series of map layers for animation"),
+    ),
 }
 }
 
 
 
 
 class MainToolbar(BaseToolbar):
 class MainToolbar(BaseToolbar):
-    """Main toolbar (data management)
-    """
+    """Main toolbar (data management)"""
 
 
     def __init__(self, parent):
     def __init__(self, parent):
-        """Main toolbar constructor
-        """
+        """Main toolbar constructor"""
         BaseToolbar.__init__(self, parent)
         BaseToolbar.__init__(self, parent)
 
 
         self.InitToolbar(self._toolbarData())
         self.InitToolbar(self._toolbarData())
@@ -89,23 +76,24 @@ class MainToolbar(BaseToolbar):
         # to reuse icons in ./trunk/gui/icons/grass or add new ones there.
         # to reuse icons in ./trunk/gui/icons/grass or add new ones there.
         icons = ganimIcons
         icons = ganimIcons
         return self._getToolbarData(
         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)))
+            (
+                ("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):
 class AnimationToolbar(BaseToolbar):
-    """Animation toolbar (to control animation)
-    """
+    """Animation toolbar (to control animation)"""
 
 
     def __init__(self, parent):
     def __init__(self, parent):
-        """Animation toolbar constructor
-        """
+        """Animation toolbar constructor"""
         BaseToolbar.__init__(self, parent)
         BaseToolbar.__init__(self, parent)
 
 
         self.InitToolbar(self._toolbarData())
         self.InitToolbar(self._toolbarData())
@@ -122,22 +110,28 @@ class AnimationToolbar(BaseToolbar):
         # to reuse icons in ./trunk/gui/icons/grass or add new ones there.
         # to reuse icons in ./trunk/gui/icons/grass or add new ones there.
         icons = ganimIcons
         icons = ganimIcons
         return self._getToolbarData(
         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)))
+            (
+                ("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):
     def OnPlayForward(self, event):
         self.PlayForward()
         self.PlayForward()
@@ -220,12 +214,10 @@ class AnimationToolbar(BaseToolbar):
 
 
 
 
 class MiscToolbar(BaseToolbar):
 class MiscToolbar(BaseToolbar):
-    """Toolbar with miscellaneous tools related to app
-    """
+    """Toolbar with miscellaneous tools related to app"""
 
 
     def __init__(self, parent):
     def __init__(self, parent):
-        """Toolbar constructor
-        """
+        """Toolbar constructor"""
         BaseToolbar.__init__(self, parent)
         BaseToolbar.__init__(self, parent)
 
 
         self.InitToolbar(self._toolbarData())
         self.InitToolbar(self._toolbarData())
@@ -234,13 +226,13 @@ class MiscToolbar(BaseToolbar):
 
 
     def _toolbarData(self):
     def _toolbarData(self):
         """Toolbar data"""
         """Toolbar data"""
-        return self._getToolbarData((("settings", BaseIcons['settings'],
-                                      self.parent.OnPreferences),
-                                     ("help", BaseIcons['help'],
-                                      self.parent.OnHelp),
-                                     ("quit", BaseIcons['quit'],
-                                      self.parent.OnCloseWindow),
-                                     ))
+        return self._getToolbarData(
+            (
+                ("settings", BaseIcons["settings"], self.parent.OnPreferences),
+                ("help", BaseIcons["help"], self.parent.OnHelp),
+                ("quit", BaseIcons["quit"], self.parent.OnCloseWindow),
+            )
+        )
 
 
 
 
 class AnimSimpleLmgrToolbar(SimpleLmgrToolbar):
 class AnimSimpleLmgrToolbar(SimpleLmgrToolbar):
@@ -254,8 +246,9 @@ class AnimSimpleLmgrToolbar(SimpleLmgrToolbar):
     def _toolbarData(self):
     def _toolbarData(self):
         data = SimpleLmgrToolbar._toolbarData(self)
         data = SimpleLmgrToolbar._toolbarData(self)
         if self._style & SIMPLE_LMGR_STDS:
         if self._style & SIMPLE_LMGR_STDS:
-            data.insert(0, ('addSeries', simpleLmgrIcons['addSeries'],
-                            self.parent.OnAddStds))
+            data.insert(
+                0, ("addSeries", simpleLmgrIcons["addSeries"], self.parent.OnAddStds)
+            )
         return data
         return data
 
 
     def EnableTools(self, tools, enable=True):
     def EnableTools(self, tools, enable=True):

+ 87 - 67
gui/wxpython/animation/utils.py

@@ -22,8 +22,10 @@ import wx
 import hashlib
 import hashlib
 import six
 import six
 from multiprocessing import cpu_count
 from multiprocessing import cpu_count
+
 try:
 try:
     from PIL import Image
     from PIL import Image
+
     hasPIL = True
     hasPIL = True
 except ImportError:
 except ImportError:
     hasPIL = False
     hasPIL = False
@@ -57,20 +59,18 @@ class ReplayMode:
     REPEAT = 3
     REPEAT = 3
 
 
 
 
-def validateTimeseriesName(timeseries, etype='strds'):
+def validateTimeseriesName(timeseries, etype="strds"):
     """Checks if space time dataset exists and completes missing mapset.
     """Checks if space time dataset exists and completes missing mapset.
 
 
     Raises GException if dataset doesn't exist.
     Raises GException if dataset doesn't exist.
     """
     """
     trastDict = tgis.tlist_grouped(etype)
     trastDict = tgis.tlist_grouped(etype)
     if timeseries.find("@") >= 0:
     if timeseries.find("@") >= 0:
-        nameShort, mapset = timeseries.split('@', 1)
+        nameShort, mapset = timeseries.split("@", 1)
         if nameShort in trastDict[mapset]:
         if nameShort in trastDict[mapset]:
             return timeseries
             return timeseries
         else:
         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()
     mapsets = tgis.get_tgis_c_library_interface().available_mapsets()
     for mapset in mapsets:
     for mapset in mapsets:
@@ -92,7 +92,7 @@ def validateMapNames(names, etype):
     newNames = []
     newNames = []
     for name in names:
     for name in names:
         if name.find("@") >= 0:
         if name.find("@") >= 0:
-            nameShort, mapset = name.split('@', 1)
+            nameShort, mapset = name.split("@", 1)
             if nameShort in mapDict[mapset]:
             if nameShort in mapDict[mapset]:
                 newNames.append(name)
                 newNames.append(name)
             else:
             else:
@@ -136,12 +136,12 @@ def getNameAndLayer(name):
     ('name', '2')
     ('name', '2')
     """
     """
     mapset = layer = None
     mapset = layer = None
-    if '@' in name:
-        name, mapset = name.split('@')
-    if ':' in name:
-        name, layer = name.split(':')
+    if "@" in name:
+        name, mapset = name.split("@")
+    if ":" in name:
+        name, layer = name.split(":")
     if mapset:
     if mapset:
-        name = name + '@' + mapset
+        name = name + "@" + mapset
     return name, layer
     return name, layer
 
 
 
 
@@ -153,66 +153,89 @@ def checkSeriesCompatibility(mapSeriesList=None, timeseriesList=None):
 
 
     :return: number of maps for animation
     :return: number of maps for animation
     """
     """
-    timeseriesInfo = {'count': set(), 'temporalType': set(), 'mapType': set(),
-                      'mapTimes': set()}
+    timeseriesInfo = {
+        "count": set(),
+        "temporalType": set(),
+        "mapType": set(),
+        "mapTimes": set(),
+    }
 
 
     if timeseriesList:
     if timeseriesList:
         for stds, etype in timeseriesList:
         for stds, etype in timeseriesList:
             sp = tgis.open_old_stds(stds, etype)
             sp = tgis.open_old_stds(stds, etype)
             mapType = sp.get_map_time()  # interval, ...
             mapType = sp.get_map_time()  # interval, ...
             tempType = sp.get_initial_values()[0]  # absolute
             tempType = sp.get_initial_values()[0]  # absolute
-            timeseriesInfo['mapType'].add(mapType)
-            timeseriesInfo['temporalType'].add(tempType)
-            rows = sp.get_registered_maps_as_objects(where=None,
-                                                     order="start_time")
+            timeseriesInfo["mapType"].add(mapType)
+            timeseriesInfo["temporalType"].add(tempType)
+            rows = sp.get_registered_maps_as_objects(where=None, order="start_time")
 
 
             if rows:
             if rows:
                 times = []
                 times = []
-                timeseriesInfo['count'].add(len(rows))
+                timeseriesInfo["count"].add(len(rows))
                 for row in rows:
                 for row in rows:
-                    if tempType == 'absolute':
+                    if tempType == "absolute":
                         time = row.get_absolute_time()
                         time = row.get_absolute_time()
                     else:
                     else:
                         time = row.get_relative_time()
                         time = row.get_relative_time()
                     times.append(time)
                     times.append(time)
-                timeseriesInfo['mapTimes'].add(tuple(times))
+                timeseriesInfo["mapTimes"].add(tuple(times))
             else:
             else:
-                timeseriesInfo['mapTimes'].add(None)
-                timeseriesInfo['count'].add(None)
-
-    if len(timeseriesInfo['count']) > 1:
-        raise GException(_("The number of maps in space-time datasets "
-                           "has to be the same."))
-
-    if len(timeseriesInfo['temporalType']) > 1:
-        raise GException(_("The temporal type (absolute/relative) of space-time datasets "
-                           "has to be the same."))
-
-    if len(timeseriesInfo['mapType']) > 1:
-        raise GException(_("The map type (point/interval) of space-time datasets "
-                           "has to be the same."))
-
-    if len(timeseriesInfo['mapTimes']) > 1:
-        raise GException(_("The temporal extents of maps in space-time datasets "
-                           "have to be the same."))
+                timeseriesInfo["mapTimes"].add(None)
+                timeseriesInfo["count"].add(None)
+
+    if len(timeseriesInfo["count"]) > 1:
+        raise GException(
+            _("The number of maps in space-time datasets " "has to be the same.")
+        )
+
+    if len(timeseriesInfo["temporalType"]) > 1:
+        raise GException(
+            _(
+                "The temporal type (absolute/relative) of space-time datasets "
+                "has to be the same."
+            )
+        )
+
+    if len(timeseriesInfo["mapType"]) > 1:
+        raise GException(
+            _(
+                "The map type (point/interval) of space-time datasets "
+                "has to be the same."
+            )
+        )
+
+    if len(timeseriesInfo["mapTimes"]) > 1:
+        raise GException(
+            _(
+                "The temporal extents of maps in space-time datasets "
+                "have to be the same."
+            )
+        )
 
 
     if mapSeriesList:
     if mapSeriesList:
         count = set()
         count = set()
         for mapSeries in mapSeriesList:
         for mapSeries in mapSeriesList:
             count.add(len(mapSeries))
             count.add(len(mapSeries))
         if len(count) > 1:
         if len(count) > 1:
-            raise GException(_("The number of maps to animate has to be "
-                               "the same for each map series."))
+            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]:
-            raise GException(_("The number of maps to animate has to be "
-                               "the same as the number of maps in temporal dataset."))
+        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."
+                )
+            )
 
 
     if mapSeriesList:
     if mapSeriesList:
         return list(count)[0]
         return list(count)[0]
     if timeseriesList:
     if timeseriesList:
-        return list(timeseriesInfo['count'])[0]
+        return list(timeseriesInfo["count"])[0]
 
 
 
 
 def ComputeScaledRect(sourceSize, destSize):
 def ComputeScaledRect(sourceSize, destSize):
@@ -234,15 +257,15 @@ def ComputeScaledRect(sourceSize, destSize):
         width = int(sourceSize[0] * scale + 0.5)
         width = int(sourceSize[0] * scale + 0.5)
         height = int(sourceSize[1] * scale + 0.5)
         height = int(sourceSize[1] * scale + 0.5)
         x = 0
         x = 0
-        y = int((destSize[1] - height) / 2. + 0.5)
+        y = int((destSize[1] - height) / 2.0 + 0.5)
     else:
     else:
         scale = ratio2
         scale = ratio2
         width = int(sourceSize[0] * scale + 0.5)
         width = int(sourceSize[0] * scale + 0.5)
         height = int(sourceSize[1] * scale + 0.5)
         height = int(sourceSize[1] * scale + 0.5)
         y = 0
         y = 0
-        x = int((destSize[0] - width) / 2. + 0.5)
+        x = int((destSize[0] - width) / 2.0 + 0.5)
 
 
-    return {'width': width, 'height': height, 'x': x, 'y': y, 'scale': scale}
+    return {"width": width, "height": height, "x": x, "y": y, "scale": scale}
 
 
 
 
 def RenderText(text, font, bgcolor, fgcolor):
 def RenderText(text, font, bgcolor, fgcolor):
@@ -264,14 +287,14 @@ def RenderText(text, font, bgcolor, fgcolor):
 
 
 def WxImageToPil(image):
 def WxImageToPil(image):
     """Converts wx.Image to PIL image"""
     """Converts wx.Image to PIL image"""
-    pilImage = Image.new('RGB', (image.GetWidth(), image.GetHeight()))
+    pilImage = Image.new("RGB", (image.GetWidth(), image.GetHeight()))
     pilImage.frombytes(bytes(image.GetData()))
     pilImage.frombytes(bytes(image.GetData()))
     return pilImage
     return pilImage
 
 
 
 
 def HashCmd(cmd, region):
 def HashCmd(cmd, region):
     """Returns a hash from command given as a list and a region as a dict."""
     """Returns a hash from command given as a list and a region as a dict."""
-    name = '_'.join(cmd)
+    name = "_".join(cmd)
     if region:
     if region:
         name += str(sorted(region.items()))
         name += str(sorted(region.items()))
     return hashlib.sha1(encode(name)).hexdigest()
     return hashlib.sha1(encode(name)).hexdigest()
@@ -279,20 +302,20 @@ def HashCmd(cmd, region):
 
 
 def HashCmds(cmds, region):
 def HashCmds(cmds, region):
     """Returns a hash from list of commands and regions as dicts."""
     """Returns a hash from list of commands and regions as dicts."""
-    name = ';'.join([item for sublist in cmds for item in sublist])
+    name = ";".join([item for sublist in cmds for item in sublist])
     if region:
     if region:
         name += str(sorted(region.items()))
         name += str(sorted(region.items()))
     return hashlib.sha1(encode(name)).hexdigest()
     return hashlib.sha1(encode(name)).hexdigest()
 
 
 
 
-def GetFileFromCmd(dirname, cmd, region, extension='ppm'):
+def GetFileFromCmd(dirname, cmd, region, extension="ppm"):
     """Returns file path created as a hash from command and region."""
     """Returns file path created as a hash from command and region."""
-    return os.path.join(dirname, HashCmd(cmd, region) + '.' + extension)
+    return os.path.join(dirname, HashCmd(cmd, region) + "." + extension)
 
 
 
 
-def GetFileFromCmds(dirname, cmds, region, extension='ppm'):
+def GetFileFromCmds(dirname, cmds, region, extension="ppm"):
     """Returns file path created as a hash from list of commands and regions."""
     """Returns file path created as a hash from list of commands and regions."""
-    return os.path.join(dirname, HashCmds(cmds, region) + '.' + extension)
+    return os.path.join(dirname, HashCmds(cmds, region) + "." + extension)
 
 
 
 
 def layerListToCmdsMatrix(layerList):
 def layerListToCmdsMatrix(layerList):
@@ -303,7 +326,7 @@ def layerListToCmdsMatrix(layerList):
     """
     """
     count = 0
     count = 0
     for layer in layerList:
     for layer in layerList:
-        if layer.active and hasattr(layer, 'maps'):
+        if layer.active and hasattr(layer, "maps"):
             # assuming the consistency of map number is checked already
             # assuming the consistency of map number is checked already
             count = len(layer.maps)
             count = len(layer.maps)
             break
             break
@@ -311,24 +334,21 @@ def layerListToCmdsMatrix(layerList):
     for layer in layerList:
     for layer in layerList:
         if not layer.active:
         if not layer.active:
             continue
             continue
-        if hasattr(layer, 'maps'):
+        if hasattr(layer, "maps"):
             for i, part in enumerate(layer.cmd):
             for i, part in enumerate(layer.cmd):
-                if part.startswith('map='):
+                if part.startswith("map="):
                     cmd = layer.cmd[:]
                     cmd = layer.cmd[:]
                     cmds = []
                     cmds = []
                     for map_ in layer.maps:
                     for map_ in layer.maps:
                         # check if dataset uses layers instead of maps
                         # check if dataset uses layers instead of maps
                         mapName, mapLayer = getNameAndLayer(map_)
                         mapName, mapLayer = getNameAndLayer(map_)
-                        cmd[i] = 'map={name}'.format(name=mapName)
+                        cmd[i] = "map={name}".format(name=mapName)
                         if mapLayer:
                         if mapLayer:
                             try:
                             try:
-                                idx = cmd.index('layer')
-                                cmd[idx] = 'layer={layer}'.format(
-                                    layer=mapLayer)
+                                idx = cmd.index("layer")
+                                cmd[idx] = "layer={layer}".format(layer=mapLayer)
                             except ValueError:
                             except ValueError:
-                                cmd.append(
-                                    'layer={layer}'.format(
-                                        layer=mapLayer))
+                                cmd.append("layer={layer}".format(layer=mapLayer))
                         cmds.append(cmd[:])
                         cmds.append(cmd[:])
                     cmdsForComposition.append(cmds)
                     cmdsForComposition.append(cmds)
         else:
         else:
@@ -342,7 +362,7 @@ def sampleCmdMatrixAndCreateNames(cmdMatrix, sampledSeries, regions):
     to the command matrix."""
     to the command matrix."""
     namesList = []
     namesList = []
     j = -1
     j = -1
-    lastName = ''
+    lastName = ""
     for name in sampledSeries:
     for name in sampledSeries:
         if name is not None:
         if name is not None:
             if lastName != name:
             if lastName != name:
@@ -351,7 +371,7 @@ def sampleCmdMatrixAndCreateNames(cmdMatrix, sampledSeries, regions):
             namesList.append(HashCmds(cmdMatrix[j], regions[j]))
             namesList.append(HashCmds(cmdMatrix[j], regions[j]))
         else:
         else:
             namesList.append(None)
             namesList.append(None)
-    assert(j == len(cmdMatrix) - 1)
+    assert j == len(cmdMatrix) - 1
     return namesList
     return namesList
 
 
 
 

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

@@ -1,16 +1,16 @@
 all = [
 all = [
-    'debug',
-    'gcmd',
-    'treemodel',
-    'ws',
-    'menutree',
-    'gconsole',
-    'events',
-    'render',
-    'units',
-    'settings',
-    'workspace',
-    'utils',
-    'globalvar',
-    'giface',
+    "debug",
+    "gcmd",
+    "treemodel",
+    "ws",
+    "menutree",
+    "gconsole",
+    "events",
+    "render",
+    "units",
+    "settings",
+    "workspace",
+    "utils",
+    "globalvar",
+    "giface",
 ]
 ]

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

@@ -28,7 +28,7 @@ import grass.script as grass
 class DebugMsg:
 class DebugMsg:
     """wxGUI debugging
     """wxGUI debugging
 
 
-        g.gisenv set=WX_DEBUG=[0-5]
+    g.gisenv set=WX_DEBUG=[0-5]
 
 
     """
     """
 
 
@@ -39,18 +39,18 @@ class DebugMsg:
         self.SetLevel()
         self.SetLevel()
 
 
     def SetLevel(self):
     def SetLevel(self):
-        """Initialize gui debug level
-        """
+        """Initialize gui debug level"""
         try:
         try:
-            self.debuglevel = int(grass.gisenv().get('WX_DEBUG', 0))
+            self.debuglevel = int(grass.gisenv().get("WX_DEBUG", 0))
             if self.debuglevel < 0 or self.debuglevel > 5:
             if self.debuglevel < 0 or self.debuglevel > 5:
-                raise ValueError(
-                    _("Wx debug level {0}.").format(
-                        self.debuglevel))
+                raise ValueError(_("Wx debug level {0}.").format(self.debuglevel))
         except ValueError as e:
         except ValueError as e:
             self.debuglevel = 0
             self.debuglevel = 0
             sys.stderr.write(
             sys.stderr.write(
-                _("WARNING: Ignoring unsupported wx debug level (must be >=0 and <=5). {0}\n").format(e))
+                _(
+                    "WARNING: Ignoring unsupported wx debug level (must be >=0 and <=5). {0}\n"
+                ).format(e)
+            )
 
 
     def msg(self, level, message, *args):
     def msg(self, level, message, *args):
         """Print debug message
         """Print debug message
@@ -62,16 +62,21 @@ class DebugMsg:
         # self.SetLevel()
         # self.SetLevel()
         if self.debuglevel > 0 and level > 0 and level <= self.debuglevel:
         if self.debuglevel > 0 and level > 0 and level <= self.debuglevel:
             if args:
             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:
             else:
-                sys.stderr.write("GUI D%d/%d: " % (level, self.debuglevel) +
-                                 message + os.linesep)
+                sys.stderr.write(
+                    "GUI D%d/%d: " % (level, self.debuglevel) + message + os.linesep
+                )
             sys.stderr.flush()  # force flush (required for MS Windows)
             sys.stderr.flush()  # force flush (required for MS Windows)
 
 
     def GetLevel(self):
     def GetLevel(self):
         """Return current GUI debug level"""
         """Return current GUI debug level"""
         return self.debuglevel
         return self.debuglevel
 
 
+
 # Debug instance
 # Debug instance
 Debug = DebugMsg()
 Debug = DebugMsg()

+ 140 - 119
gui/wxpython/core/gcmd.py

@@ -38,7 +38,7 @@ import subprocess
 from threading import Thread
 from threading import Thread
 import wx
 import wx
 
 
-is_mswindows = sys.platform == 'win32'
+is_mswindows = sys.platform == "win32"
 if is_mswindows:
 if is_mswindows:
     from win32file import ReadFile, WriteFile
     from win32file import ReadFile, WriteFile
     from win32pipe import PeekNamedPipe
     from win32pipe import PeekNamedPipe
@@ -89,7 +89,6 @@ def EncodeString(string):
 
 
 
 
 class GError:
 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
         """Show error message window
 
 
@@ -99,55 +98,43 @@ class GError:
         :param showTraceback: True to show also Python traceback
         :param showTraceback: True to show also Python traceback
         """
         """
         if not caption:
         if not caption:
-            caption = _('Error')
+            caption = _("Error")
         style = wx.OK | wx.ICON_ERROR | wx.CENTRE
         style = wx.OK | wx.ICON_ERROR | wx.CENTRE
         exc_type, exc_value, exc_traceback = sys.exc_info()
         exc_type, exc_value, exc_traceback = sys.exc_info()
         if exc_traceback:
         if exc_traceback:
             exception = traceback.format_exc()
             exception = traceback.format_exc()
-            reason = exception.splitlines()[-1].split(':', 1)[-1].strip()
+            reason = exception.splitlines()[-1].split(":", 1)[-1].strip()
 
 
         if Debug.GetLevel() > 0 and exc_traceback:
         if Debug.GetLevel() > 0 and exc_traceback:
             sys.stderr.write(exception)
             sys.stderr.write(exception)
 
 
         if showTraceback and exc_traceback:
         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:
         else:
-            wx.MessageBox(parent=parent,
-                          message=message,
-                          caption=caption,
-                          style=style)
+            wx.MessageBox(parent=parent, message=message, caption=caption, style=style)
 
 
 
 
 class GWarning:
 class GWarning:
-
     def __init__(self, message, parent=None):
     def __init__(self, message, parent=None):
-        caption = _('Warning')
+        caption = _("Warning")
         style = wx.OK | wx.ICON_WARNING | wx.CENTRE
         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:
 class GMessage:
-
     def __init__(self, message, parent=None):
     def __init__(self, message, parent=None):
-        caption = _('Message')
+        caption = _("Message")
         style = wx.OK | wx.ICON_INFORMATION | wx.CENTRE
         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):
 class GException(Exception):
-
-    def __init__(self, value=''):
+    def __init__(self, value=""):
         self.value = value
         self.value = value
 
 
     def __str__(self):
     def __str__(self):
@@ -175,7 +162,7 @@ class Popen(subprocess.Popen):
                         if "=" in args[i]:
                         if "=" in args[i]:
                             a = args[i].split("=")
                             a = args[i].split("=")
                             k = a[0] + "="
                             k = a[0] + "="
-                            v = "=".join(a[1:len(a)])
+                            v = "=".join(a[1 : len(a)])
                         else:
                         else:
                             k = ""
                             k = ""
                             v = args[i]
                             v = args[i]
@@ -194,12 +181,12 @@ class Popen(subprocess.Popen):
         subprocess.Popen.__init__(self, args, **kwargs)
         subprocess.Popen.__init__(self, args, **kwargs)
 
 
     def recv(self, maxsize=None):
     def recv(self, maxsize=None):
-        return self._recv('stdout', maxsize)
+        return self._recv("stdout", maxsize)
 
 
     def recv_err(self, maxsize=None):
     def recv_err(self, maxsize=None):
-        return self._recv('stderr', maxsize)
+        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)
         return self.send(input), self.recv(maxsize), self.recv_err(maxsize)
 
 
     def get_conn_maxsize(self, which, maxsize):
     def get_conn_maxsize(self, which, maxsize):
@@ -217,28 +204,31 @@ class Popen(subprocess.Popen):
         """Try to kill running process"""
         """Try to kill running process"""
         if is_mswindows:
         if is_mswindows:
             import win32api
             import win32api
+
             handle = win32api.OpenProcess(1, 0, self.pid)
             handle = win32api.OpenProcess(1, 0, self.pid)
-            return (0 != win32api.TerminateProcess(handle, 0))
+            return 0 != win32api.TerminateProcess(handle, 0)
         else:
         else:
             try:
             try:
                 os.kill(-self.pid, signal.SIGTERM)  # kill whole group
                 os.kill(-self.pid, signal.SIGTERM)  # kill whole group
             except OSError:
             except OSError:
                 pass
                 pass
 
 
-    if sys.platform == 'win32':
+    if sys.platform == "win32":
+
         def send(self, input):
         def send(self, input):
             if not self.stdin:
             if not self.stdin:
                 return None
                 return None
 
 
             import pywintypes
             import pywintypes
+
             try:
             try:
                 x = msvcrt.get_osfhandle(self.stdin.fileno())
                 x = msvcrt.get_osfhandle(self.stdin.fileno())
                 (errCode, written) = WriteFile(x, input)
                 (errCode, written) = WriteFile(x, input)
             except ValueError:
             except ValueError:
-                return self._close('stdin')
+                return self._close("stdin")
             except (pywintypes.error, Exception) as why:
             except (pywintypes.error, Exception) as why:
                 if why.winerror in (109, errno.ESHUTDOWN):
                 if why.winerror in (109, errno.ESHUTDOWN):
-                    return self._close('stdin')
+                    return self._close("stdin")
                 raise
                 raise
 
 
             return written
             return written
@@ -249,6 +239,7 @@ class Popen(subprocess.Popen):
                 return None
                 return None
 
 
             import pywintypes
             import pywintypes
+
             try:
             try:
                 x = msvcrt.get_osfhandle(conn.fileno())
                 x = msvcrt.get_osfhandle(conn.fileno())
                 (read, nAvail, nMessage) = PeekNamedPipe(x, 0)
                 (read, nAvail, nMessage) = PeekNamedPipe(x, 0)
@@ -268,6 +259,7 @@ class Popen(subprocess.Popen):
             return read
             return read
 
 
     else:
     else:
+
         def send(self, input):
         def send(self, input):
             if not self.stdin:
             if not self.stdin:
                 return None
                 return None
@@ -279,7 +271,7 @@ class Popen(subprocess.Popen):
                 written = os.write(self.stdin.fileno(), input)
                 written = os.write(self.stdin.fileno(), input)
             except OSError as why:
             except OSError as why:
                 if why[0] == errno.EPIPE:  # broken pipe
                 if why[0] == errno.EPIPE:  # broken pipe
-                    return self._close('stdin')
+                    return self._close("stdin")
                 raise
                 raise
 
 
             return written
             return written
@@ -295,7 +287,7 @@ class Popen(subprocess.Popen):
 
 
             try:
             try:
                 if not select.select([conn], [], [], 0)[0]:
                 if not select.select([conn], [], [], 0)[0]:
-                    return ''
+                    return ""
 
 
                 r = conn.read()
                 r = conn.read()
 
 
@@ -309,15 +301,16 @@ class Popen(subprocess.Popen):
                 if not conn.closed:
                 if not conn.closed:
                     fcntl.fcntl(conn, fcntl.F_SETFL, flags)
                     fcntl.fcntl(conn, fcntl.F_SETFL, flags)
 
 
+
 message = "Other end disconnected!"
 message = "Other end disconnected!"
 
 
 
 
-def recv_some(p, t=.1, e=1, tr=5, stderr=0):
+def recv_some(p, t=0.1, e=1, tr=5, stderr=0):
     if tr < 1:
     if tr < 1:
         tr = 1
         tr = 1
     x = time.time() + t
     x = time.time() + t
     y = []
     y = []
-    r = ''
+    r = ""
     pr = p.recv
     pr = p.recv
     if stderr:
     if stderr:
         pr = p.recv_err
         pr = p.recv_err
@@ -332,7 +325,7 @@ def recv_some(p, t=.1, e=1, tr=5, stderr=0):
             y.append(decode(r))
             y.append(decode(r))
         else:
         else:
             time.sleep(max((x - time.time()) / tr, 0))
             time.sleep(max((x - time.time()) / tr, 0))
-    return ''.join(y)
+    return "".join(y)
 
 
 
 
 class Command:
 class Command:
@@ -352,9 +345,16 @@ class Command:
             print 'FAILURE (%d)' % cmd.returncode
             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 cmd: command given as list
         :param stdin: standard input stream
         :param stdin: standard input stream
@@ -366,7 +366,7 @@ class Command:
         :param stdout:  redirect standard output or None
         :param stdout:  redirect standard output or None
         :param stderr:  redirect standard error output or None
         :param stderr:  redirect standard error output or None
         """
         """
-        Debug.msg(1, "gcmd.Command(): %s" % ' '.join(cmd))
+        Debug.msg(1, "gcmd.Command(): %s" % " ".join(cmd))
         self.cmd = cmd
         self.cmd = cmd
         self.stderr = stderr
         self.stderr = stderr
 
 
@@ -374,13 +374,14 @@ class Command:
         # set verbosity level
         # set verbosity level
         #
         #
         verbose_orig = None
         verbose_orig = None
-        if ('--q' not in self.cmd and '--quiet' not in self.cmd) and \
-                ('--v' not in self.cmd and '--verbose' not in self.cmd):
+        if ("--q" not in self.cmd and "--quiet" not in self.cmd) and (
+            "--v" not in self.cmd and "--verbose" not in self.cmd
+        ):
             if verbose is not None:
             if verbose is not None:
                 if verbose == 0:
                 if verbose == 0:
-                    self.cmd.append('--quiet')
+                    self.cmd.append("--quiet")
                 elif verbose == 3:
                 elif verbose == 3:
-                    self.cmd.append('--verbose')
+                    self.cmd.append("--verbose")
                 else:
                 else:
                     verbose_orig = os.getenv("GRASS_VERBOSE")
                     verbose_orig = os.getenv("GRASS_VERBOSE")
                     os.environ["GRASS_VERBOSE"] = str(verbose)
                     os.environ["GRASS_VERBOSE"] = str(verbose)
@@ -388,8 +389,7 @@ class Command:
         #
         #
         # create command thread
         # create command thread
         #
         #
-        self.cmdThread = CommandThread(cmd, stdin,
-                                       stdout, stderr)
+        self.cmdThread = CommandThread(cmd, stdin, stdout, stderr)
         self.cmdThread.start()
         self.cmdThread.start()
 
 
         if wait:
         if wait:
@@ -405,32 +405,38 @@ class Command:
 
 
         if self.returncode is not None:
         if self.returncode is not None:
             Debug.msg(
             Debug.msg(
-                3, "Command(): cmd='%s', wait=%s, returncode=%d, alive=%s" %
-                (' '.join(cmd), wait, self.returncode, self.cmdThread.isAlive()))
+                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 not None and self.returncode != 0:
                 if rerr is False:  # GUI dialog
                 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()))
+                    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
                 elif rerr == sys.stderr:  # redirect message to sys
-                    stderr.write("Execution failed: '%s'" %
-                                 (' '.join(self.cmd)))
+                    stderr.write("Execution failed: '%s'" % (" ".join(self.cmd)))
                     stderr.write(
                     stderr.write(
-                        "%sDetails:%s%s" %
-                        (os.linesep,
-                         _("Error: ") +
-                            self.__GetError(),
-                            os.linesep))
+                        "%sDetails:%s%s"
+                        % (os.linesep, _("Error: ") + self.__GetError(), os.linesep)
+                    )
             else:
             else:
                 pass  # nop
                 pass  # nop
         else:
         else:
             Debug.msg(
             Debug.msg(
-                3, "Command(): cmd='%s', wait=%s, returncode=?, alive=%s" %
-                (' '.join(cmd), wait, self.cmdThread.isAlive()))
+                3,
+                "Command(): cmd='%s', wait=%s, returncode=?, alive=%s"
+                % (" ".join(cmd), wait, self.cmdThread.isAlive()),
+            )
 
 
         if verbose_orig:
         if verbose_orig:
             os.environ["GRASS_VERBOSE"] = verbose_orig
             os.environ["GRASS_VERBOSE"] = verbose_orig
@@ -451,7 +457,7 @@ class Command:
             line = stream.readline()
             line = stream.readline()
             if not line:
             if not line:
                 break
                 break
-            line = line.replace('%s' % os.linesep, '').strip()
+            line = line.replace("%s" % os.linesep, "").strip()
             lineList.append(line)
             lineList.append(line)
 
 
         return lineList
         return lineList
@@ -469,8 +475,9 @@ class Command:
         if self.stderr is None:
         if self.stderr is None:
             lines = self.__ReadErrOutput()
             lines = self.__ReadErrOutput()
         else:
         else:
-            lines = self.cmdThread.error.strip('%s' % os.linesep). \
-                split('%s' % os.linesep)
+            lines = self.cmdThread.error.strip("%s" % os.linesep).split(
+                "%s" % os.linesep
+            )
 
 
         msg = []
         msg = []
 
 
@@ -479,18 +486,18 @@ class Command:
         for line in lines:
         for line in lines:
             if len(line) == 0:
             if len(line) == 0:
                 continue
                 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"
                     type = "WARNING"
-                elif 'GRASS_INFO_ERROR' in line:  # error
+                elif "GRASS_INFO_ERROR" in line:  # error
                     type = "ERROR"
                     type = "ERROR"
-                elif 'GRASS_INFO_END':  # end of message
+                elif "GRASS_INFO_END":  # end of message
                     msg.append((type, content))
                     msg.append((type, content))
                     type = None
                     type = None
                     content = ""
                     content = ""
 
 
                 if type:
                 if type:
-                    content += line.split(':', 1)[1].strip()
+                    content += line.split(":", 1)[1].strip()
             else:  # stderr
             else:  # stderr
                 msg.append((None, line.strip()))
                 msg.append((None, line.strip()))
 
 
@@ -499,21 +506,20 @@ class Command:
     def __GetError(self):
     def __GetError(self):
         """Get error message or ''"""
         """Get error message or ''"""
         if not self.cmdThread.module:
         if not self.cmdThread.module:
-            return _("Unable to exectute command: '%s'") % ' '.join(self.cmd)
+            return _("Unable to exectute command: '%s'") % " ".join(self.cmd)
 
 
         for type, msg in self.__ProcessStdErr():
         for type, msg in self.__ProcessStdErr():
-            if type == 'ERROR':
+            if type == "ERROR":
                 return msg
                 return msg
 
 
-        return ''
+        return ""
 
 
 
 
 class CommandThread(Thread):
 class CommandThread(Thread):
     """Create separate thread for command. Used for commands launched
     """Create separate thread for command. Used for commands launched
     on the background."""
     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 cmd: command (given as list)
         :param env: environmental variables
         :param env: environmental variables
@@ -530,7 +536,7 @@ class CommandThread(Thread):
         self.env = env
         self.env = env
 
 
         self.module = None
         self.module = None
-        self.error = ''
+        self.error = ""
 
 
         self._want_abort = False
         self._want_abort = False
         self.aborted = False
         self.aborted = False
@@ -552,7 +558,7 @@ class CommandThread(Thread):
         if len(self.cmd) == 0:
         if len(self.cmd) == 0:
             return
             return
 
 
-        Debug.msg(1, "gcmd.CommandThread(): %s" % ' '.join(self.cmd))
+        Debug.msg(1, "gcmd.CommandThread(): %s" % " ".join(self.cmd))
 
 
         self.startTime = time.time()
         self.startTime = time.time()
 
 
@@ -561,7 +567,7 @@ class CommandThread(Thread):
         # also unifying this with 3 other places in code would be nice
         # also unifying this with 3 other places in code would be nice
         # changing from one chdir to get_real_command function
         # changing from one chdir to get_real_command function
         args = self.cmd
         args = self.cmd
-        if sys.platform == 'win32':
+        if sys.platform == "win32":
             if os.path.splitext(args[0])[1] == SCT_EXT:
             if os.path.splitext(args[0])[1] == SCT_EXT:
                 args[0] = args[0][:-3]
                 args[0] = args[0][:-3]
             # using Python executable to run the module if it is a script
             # using Python executable to run the module if it is a script
@@ -569,16 +575,18 @@ class CommandThread(Thread):
             # cannot use make_command for this now because it is used in GUI
             # cannot use make_command for this now because it is used in GUI
             # The same code is in grass.script.core already twice.
             # The same code is in grass.script.core already twice.
             args[0] = grass.get_real_command(args[0])
             args[0] = grass.get_real_command(args[0])
-            if args[0].endswith('.py'):
+            if args[0].endswith(".py"):
                 args.insert(0, sys.executable)
                 args.insert(0, sys.executable)
 
 
         try:
         try:
-            self.module = Popen(args,
-                                stdin=subprocess.PIPE,
-                                stdout=subprocess.PIPE,
-                                stderr=subprocess.PIPE,
-                                shell=sys.platform == "win32",
-                                env=self.env)
+            self.module = Popen(
+                args,
+                stdin=subprocess.PIPE,
+                stdout=subprocess.PIPE,
+                stderr=subprocess.PIPE,
+                shell=sys.platform == "win32",
+                env=self.env,
+            )
 
 
         except OSError as e:
         except OSError as e:
             self.error = str(e)
             self.error = str(e)
@@ -639,29 +647,39 @@ class CommandThread(Thread):
 
 
 
 
 def _formatMsg(text):
 def _formatMsg(text):
-    """Format error messages for dialogs
-    """
-    message = ''
+    """Format error messages for dialogs"""
+    message = ""
     for line in text.splitlines():
     for line in text.splitlines():
         if len(line) == 0:
         if len(line) == 0:
             continue
             continue
-        elif 'GRASS_INFO_MESSAGE' in line:
-            message += line.split(':', 1)[1].strip() + '\n'
-        elif 'GRASS_INFO_WARNING' in line:
-            message += line.split(':', 1)[1].strip() + '\n'
-        elif 'GRASS_INFO_ERROR' in line:
-            message += line.split(':', 1)[1].strip() + '\n'
-        elif 'GRASS_INFO_END' in line:
+        elif "GRASS_INFO_MESSAGE" in line:
+            message += line.split(":", 1)[1].strip() + "\n"
+        elif "GRASS_INFO_WARNING" in line:
+            message += line.split(":", 1)[1].strip() + "\n"
+        elif "GRASS_INFO_ERROR" in line:
+            message += line.split(":", 1)[1].strip() + "\n"
+        elif "GRASS_INFO_END" in line:
             return message
             return message
         else:
         else:
-            message += line.strip() + '\n'
+            message += line.strip() + "\n"
 
 
     return message
     return message
 
 
 
 
-def RunCommand(prog, flags="", overwrite=False, quiet=False,
-               verbose=False, parent=None, read=False,
-               parse=None, stdin=None, getErrorMsg=False, env=None, **kwargs):
+def RunCommand(
+    prog,
+    flags="",
+    overwrite=False,
+    quiet=False,
+    verbose=False,
+    parent=None,
+    read=False,
+    parse=None,
+    stdin=None,
+    getErrorMsg=False,
+    env=None,
+    **kwargs,
+):
     """Run GRASS command
     """Run GRASS command
 
 
     :param prog: program to run
     :param prog: program to run
@@ -683,18 +701,19 @@ def RunCommand(prog, flags="", overwrite=False, quiet=False,
     :return: returncode, stdout, messages (read == True and getErrorMsg == True)
     :return: returncode, stdout, messages (read == True and getErrorMsg == True)
     :return: stdout, stderr
     :return: stdout, stderr
     """
     """
-    cmdString = ' '.join(grass.make_command(prog, flags, overwrite,
-                                            quiet, verbose, **kwargs))
+    cmdString = " ".join(
+        grass.make_command(prog, flags, overwrite, quiet, verbose, **kwargs)
+    )
 
 
     Debug.msg(1, "gcmd.RunCommand(): %s" % cmdString)
     Debug.msg(1, "gcmd.RunCommand(): %s" % cmdString)
 
 
-    kwargs['stderr'] = subprocess.PIPE
+    kwargs["stderr"] = subprocess.PIPE
 
 
     if read:
     if read:
-        kwargs['stdout'] = subprocess.PIPE
+        kwargs["stdout"] = subprocess.PIPE
 
 
     if stdin:
     if stdin:
-        kwargs['stdin'] = subprocess.PIPE
+        kwargs["stdin"] = subprocess.PIPE
 
 
     # Do not change the environment, only a local copy.
     # Do not change the environment, only a local copy.
     if env:
     if env:
@@ -703,7 +722,7 @@ def RunCommand(prog, flags="", overwrite=False, quiet=False,
         env = os.environ.copy()
         env = os.environ.copy()
 
 
     if parent:
     if parent:
-        env['GRASS_MESSAGE_FORMAT'] = 'standard'
+        env["GRASS_MESSAGE_FORMAT"] = "standard"
 
 
     start = time.time()
     start = time.time()
 
 
@@ -719,8 +738,11 @@ def RunCommand(prog, flags="", overwrite=False, quiet=False,
     stdout = decode(stdout) if read else stdout
     stdout = decode(stdout) if read else stdout
 
 
     ret = ps.returncode
     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 ret != 0:
         if stderr:
         if stderr:
@@ -729,9 +751,7 @@ def RunCommand(prog, flags="", overwrite=False, quiet=False,
             Debug.msg(2, "gcmd.RunCommand(): nothing to print ???")
             Debug.msg(2, "gcmd.RunCommand(): nothing to print ???")
 
 
         if parent:
         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 read:
         if not getErrorMsg:
         if not getErrorMsg:
@@ -764,8 +784,8 @@ def GetDefaultEncoding(forceUTF8=False):
     :return: system encoding (can be None)
     :return: system encoding (can be None)
     """
     """
     enc = locale.getdefaultlocale()[1]
     enc = locale.getdefaultlocale()[1]
-    if forceUTF8 and (enc is None or enc == 'UTF8'):
-        return 'UTF-8'
+    if forceUTF8 and (enc is None or enc == "UTF8"):
+        return "UTF-8"
 
 
     if enc is None:
     if enc is None:
         enc = locale.getpreferredencoding()
         enc = locale.getpreferredencoding()
@@ -773,4 +793,5 @@ def GetDefaultEncoding(forceUTF8=False):
     Debug.msg(1, "GetSystemEncoding(): %s" % enc)
     Debug.msg(1, "GetSystemEncoding(): %s" % enc)
     return enc
     return enc
 
 
+
 _enc = GetDefaultEncoding()  # define as global variable
 _enc = GetDefaultEncoding()  # define as global variable

+ 227 - 184
gui/wxpython/core/gconsole.py

@@ -62,12 +62,12 @@ wxCmdPrepare, EVT_CMD_PREPARE = NewEvent()
 
 
 def GrassCmd(cmd, env=None, stdout=None, stderr=None):
 def GrassCmd(cmd, env=None, stdout=None, stderr=None):
     """Return GRASS command thread"""
     """Return GRASS command thread"""
-    return CommandThread(cmd, env=env,
-                         stdout=stdout, stderr=stderr)
+    return CommandThread(cmd, env=env, stdout=stdout, stderr=stderr)
 
 
 
 
 class CmdThread(threading.Thread):
 class CmdThread(threading.Thread):
     """Thread for GRASS commands"""
     """Thread for GRASS commands"""
+
     requestId = 0
     requestId = 0
 
 
     def __init__(self, receiver, requestQ=None, resultQ=None, **kwds):
     def __init__(self, receiver, requestQ=None, resultQ=None, **kwds):
@@ -119,41 +119,49 @@ class CmdThread(threading.Thread):
         CmdThread.requestId = id
         CmdThread.requestId = id
 
 
     def run(self):
     def run(self):
-        os.environ['GRASS_MESSAGE_FORMAT'] = 'gui'
+        os.environ["GRASS_MESSAGE_FORMAT"] = "gui"
         while True:
         while True:
             requestId, args, kwds = self.requestQ.get()
             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:
                 if key in kwds:
                     vars()[key] = kwds[key]
                     vars()[key] = kwds[key]
                     del kwds[key]
                     del kwds[key]
                 else:
                 else:
                     vars()[key] = None
                     vars()[key] = None
 
 
-            if not vars()['callable']:
-                vars()['callable'] = GrassCmd
+            if not vars()["callable"]:
+                vars()["callable"] = GrassCmd
 
 
             requestTime = time.time()
             requestTime = time.time()
 
 
             # prepare
             # prepare
             if self.receiver:
             if self.receiver:
-                event = wxCmdPrepare(cmd=args[0],
-                                     time=requestTime,
-                                     pid=requestId,
-                                     onPrepare=vars()['onPrepare'],
-                                     userData=vars()['userData'])
+                event = wxCmdPrepare(
+                    cmd=args[0],
+                    time=requestTime,
+                    pid=requestId,
+                    onPrepare=vars()["onPrepare"],
+                    userData=vars()["userData"],
+                )
 
 
                 wx.PostEvent(self.receiver, event)
                 wx.PostEvent(self.receiver, event)
 
 
                 # run command
                 # run command
-                event = wxCmdRun(cmd=args[0],
-                                 pid=requestId,
-                                 notification=vars()['notification'])
+                event = wxCmdRun(
+                    cmd=args[0], pid=requestId, notification=vars()["notification"]
+                )
 
 
                 wx.PostEvent(self.receiver, event)
                 wx.PostEvent(self.receiver, event)
 
 
-            time.sleep(.1)
-            self.requestCmd = vars()['callable'](*args, **kwds)
+            time.sleep(0.1)
+            self.requestCmd = vars()["callable"](*args, **kwds)
             if self._want_abort_all and self.requestCmd is not None:
             if self._want_abort_all and self.requestCmd is not None:
                 self.requestCmd.abort()
                 self.requestCmd.abort()
                 if self.requestQ.empty():
                 if self.requestQ.empty():
@@ -171,47 +179,54 @@ class CmdThread(threading.Thread):
             except AttributeError:
             except AttributeError:
                 aborted = False
                 aborted = False
 
 
-            time.sleep(.1)
+            time.sleep(0.1)
 
 
             # set default color table for raster data
             # set default color table for raster data
-            if UserSettings.Get(group='rasterLayer',
-                                key='colorTable', subkey='enabled') and \
-                    args[0][0][:2] == 'r.':
-                colorTable = UserSettings.Get(group='rasterLayer',
-                                              key='colorTable',
-                                              subkey='selection')
+            if (
+                UserSettings.Get(
+                    group="rasterLayer", key="colorTable", subkey="enabled"
+                )
+                and args[0][0][:2] == "r."
+            ):
+                colorTable = UserSettings.Get(
+                    group="rasterLayer", key="colorTable", subkey="selection"
+                )
                 mapName = None
                 mapName = None
-                if args[0][0] == 'r.mapcalc':
+                if args[0][0] == "r.mapcalc":
                     try:
                     try:
-                        mapName = args[0][1].split('=', 1)[0].strip()
+                        mapName = args[0][1].split("=", 1)[0].strip()
                     except KeyError:
                     except KeyError:
                         pass
                         pass
                 else:
                 else:
                     moduleInterface = GUI(show=None).ParseCommand(args[0])
                     moduleInterface = GUI(show=None).ParseCommand(args[0])
-                    outputParam = moduleInterface.get_param(value='output',
-                                                            raiseError=False)
-                    if outputParam and outputParam['prompt'] == 'raster':
-                        mapName = outputParam['value']
+                    outputParam = moduleInterface.get_param(
+                        value="output", raiseError=False
+                    )
+                    if outputParam and outputParam["prompt"] == "raster":
+                        mapName = outputParam["value"]
 
 
                 if mapName:
                 if mapName:
                     argsColor = list(args)
                     argsColor = list(args)
-                    argsColor[0] = ['r.colors',
-                                    'map=%s' % mapName,
-                                    'color=%s' % colorTable]
-                    self.requestCmdColor = vars()['callable'](
-                        *argsColor, **kwds)
+                    argsColor[0] = [
+                        "r.colors",
+                        "map=%s" % mapName,
+                        "color=%s" % colorTable,
+                    ]
+                    self.requestCmdColor = vars()["callable"](*argsColor, **kwds)
                     self.resultQ.put((requestId, self.requestCmdColor.run()))
                     self.resultQ.put((requestId, self.requestCmdColor.run()))
 
 
             if self.receiver:
             if self.receiver:
-                event = wxCmdDone(cmd=args[0],
-                                  aborted=aborted,
-                                  returncode=returncode,
-                                  time=requestTime,
-                                  pid=requestId,
-                                  onDone=vars()['onDone'],
-                                  userData=vars()['userData'],
-                                  addLayer=vars()['addLayer'],
-                                  notification=vars()['notification'])
+                event = wxCmdDone(
+                    cmd=args[0],
+                    aborted=aborted,
+                    returncode=returncode,
+                    time=requestTime,
+                    pid=requestId,
+                    onDone=vars()["onDone"],
+                    userData=vars()["userData"],
+                    addLayer=vars()["addLayer"],
+                    notification=vars()["notification"],
+                )
 
 
                 # send event
                 # send event
                 wx.PostEvent(self.receiver, event)
                 wx.PostEvent(self.receiver, event)
@@ -248,15 +263,14 @@ class GStdout:
         pass
         pass
 
 
     def write(self, s):
     def write(self, s):
-        if len(s) == 0 or s == '\n':
+        if len(s) == 0 or s == "\n":
             return
             return
 
 
         for line in s.splitlines():
         for line in s.splitlines():
             if len(line) == 0:
             if len(line) == 0:
                 continue
                 continue
 
 
-            evt = wxCmdOutput(text=line + '\n',
-                              type='')
+            evt = wxCmdOutput(text=line + "\n", type="")
             wx.PostEvent(self.receiver, evt)
             wx.PostEvent(self.receiver, evt)
 
 
 
 
@@ -277,8 +291,8 @@ class GStderr:
         :param receiver: event receiver (used in PostEvent)
         :param receiver: event receiver (used in PostEvent)
         """
         """
         self.receiver = receiver
         self.receiver = receiver
-        self.type = ''
-        self.message = ''
+        self.type = ""
+        self.message = ""
         self.printMessage = False
         self.printMessage = False
 
 
     def flush(self):
     def flush(self):
@@ -295,39 +309,37 @@ class GStderr:
             if len(line) == 0:
             if len(line) == 0:
                 continue
                 continue
 
 
-            if 'GRASS_INFO_PERCENT' in line:
-                value = int(line.rsplit(':', 1)[1].strip())
+            if "GRASS_INFO_PERCENT" in line:
+                value = int(line.rsplit(":", 1)[1].strip())
                 if value >= 0 and value < 100:
                 if value >= 0 and value < 100:
                     progressValue = value
                     progressValue = value
                 else:
                 else:
                     progressValue = 0
                     progressValue = 0
-            elif 'GRASS_INFO_MESSAGE' in line:
-                self.type = 'message'
-                self.message += line.split(':', 1)[1].strip() + '\n'
-            elif 'GRASS_INFO_WARNING' in line:
-                self.type = 'warning'
-                self.message += line.split(':', 1)[1].strip() + '\n'
-            elif 'GRASS_INFO_ERROR' in line:
-                self.type = 'error'
-                self.message += line.split(':', 1)[1].strip() + '\n'
-            elif 'GRASS_INFO_END' in line:
+            elif "GRASS_INFO_MESSAGE" in line:
+                self.type = "message"
+                self.message += line.split(":", 1)[1].strip() + "\n"
+            elif "GRASS_INFO_WARNING" in line:
+                self.type = "warning"
+                self.message += line.split(":", 1)[1].strip() + "\n"
+            elif "GRASS_INFO_ERROR" in line:
+                self.type = "error"
+                self.message += line.split(":", 1)[1].strip() + "\n"
+            elif "GRASS_INFO_END" in line:
                 self.printMessage = True
                 self.printMessage = True
-            elif self.type == '':
+            elif self.type == "":
                 if len(line) == 0:
                 if len(line) == 0:
                     continue
                     continue
-                evt = wxCmdOutput(text=line,
-                                  type='')
+                evt = wxCmdOutput(text=line, type="")
                 wx.PostEvent(self.receiver, evt)
                 wx.PostEvent(self.receiver, evt)
             elif len(line) > 0:
             elif len(line) > 0:
-                self.message += line.strip() + '\n'
+                self.message += line.strip() + "\n"
 
 
             if self.printMessage and len(self.message) > 0:
             if self.printMessage and len(self.message) > 0:
-                evt = wxCmdOutput(text=self.message,
-                                  type=self.type)
+                evt = wxCmdOutput(text=self.message, type=self.type)
                 wx.PostEvent(self.receiver, evt)
                 wx.PostEvent(self.receiver, evt)
 
 
-                self.type = ''
-                self.message = ''
+                self.type = ""
+                self.message = ""
                 self.printMessage = False
                 self.printMessage = False
 
 
         # update progress message
         # update progress message
@@ -343,8 +355,7 @@ gIgnoredCmdRun, EVT_IGNORED_CMD_RUN = NewEvent()
 
 
 
 
 class GConsole(wx.EvtHandler):
 class GConsole(wx.EvtHandler):
-    """
-    """
+    """"""
 
 
     def __init__(self, guiparent=None, giface=None, ignoredCmdPattern=None):
     def __init__(self, guiparent=None, giface=None, ignoredCmdPattern=None):
         """
         """
@@ -358,17 +369,17 @@ class GConsole(wx.EvtHandler):
 
 
         # Signal when some map is created or updated by a module.
         # Signal when some map is created or updated by a module.
         # attributes: name: map name, ltype: map type,
         # attributes: name: map name, ltype: map type,
-        self.mapCreated = Signal('GConsole.mapCreated')
+        self.mapCreated = Signal("GConsole.mapCreated")
         # emitted when map display should be re-render
         # emitted when map display should be re-render
-        self.updateMap = Signal('GConsole.updateMap')
+        self.updateMap = Signal("GConsole.updateMap")
         # emitted when log message should be written
         # emitted when log message should be written
-        self.writeLog = Signal('GConsole.writeLog')
+        self.writeLog = Signal("GConsole.writeLog")
         # emitted when command log message should be written
         # emitted when command log message should be written
-        self.writeCmdLog = Signal('GConsole.writeCmdLog')
+        self.writeCmdLog = Signal("GConsole.writeCmdLog")
         # emitted when warning message should be written
         # emitted when warning message should be written
-        self.writeWarning = Signal('GConsole.writeWarning')
+        self.writeWarning = Signal("GConsole.writeWarning")
         # emitted when error message should be written
         # emitted when error message should be written
-        self.writeError = Signal('GConsole.writeError')
+        self.writeError = Signal("GConsole.writeError")
 
 
         self._guiparent = guiparent
         self._guiparent = guiparent
         self._giface = giface
         self._giface = giface
@@ -392,8 +403,7 @@ class GConsole(wx.EvtHandler):
         self.cmdThread = CmdThread(self, self.requestQ, self.resultQ)
         self.cmdThread = CmdThread(self, self.requestQ, self.resultQ)
 
 
     def Redirect(self):
     def Redirect(self):
-        """Redirect stdout/stderr
-        """
+        """Redirect stdout/stderr"""
         if Debug.GetLevel() == 0 and grass.debug_level(force=True) == 0:
         if Debug.GetLevel() == 0 and grass.debug_level(force=True) == 0:
             # don't redirect when debugging is enabled
             # don't redirect when debugging is enabled
             sys.stdout = self.cmdStdOut
             sys.stdout = self.cmdStdOut
@@ -412,27 +422,25 @@ class GConsole(wx.EvtHandler):
                 sys.stdout = sys.__stdout__
                 sys.stdout = sys.__stdout__
                 sys.stderr = sys.__stderr__
                 sys.stderr = sys.__stderr__
 
 
-    def WriteLog(self, text, style=None, wrap=None,
-                 notification=Notification.HIGHLIGHT):
+    def WriteLog(
+        self, text, style=None, wrap=None, notification=Notification.HIGHLIGHT
+    ):
         """Generic method for writing log message in
         """Generic method for writing log message in
         given style
         given style
 
 
         :param text: text line
         :param text: text line
         :param notification: form of notification
         :param notification: form of notification
         """
         """
-        self.writeLog.emit(text=text, wrap=wrap,
-                           notification=notification)
+        self.writeLog.emit(text=text, wrap=wrap, 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
         """Write message in selected style
 
 
         :param text: message to be printed
         :param text: message to be printed
         :param pid: process pid or None
         :param pid: process pid or None
         :param notification: form of notification
         :param notification: form of notification
         """
         """
-        self.writeCmdLog.emit(text=text, pid=pid,
-                              notification=notification)
+        self.writeCmdLog.emit(text=text, pid=pid, notification=notification)
 
 
     def WriteWarning(self, text):
     def WriteWarning(self, text):
         """Write message in warning style"""
         """Write message in warning style"""
@@ -442,9 +450,18 @@ class GConsole(wx.EvtHandler):
         """Write message in error style"""
         """Write message in error style"""
         self.writeError.emit(text=text)
         self.writeError.emit(text=text)
 
 
-    def RunCmd(self, command, compReg=True, env=None, skipInterface=False,
-               onDone=None, onPrepare=None, userData=None, addLayer=None,
-               notification=Notification.MAKE_VISIBLE):
+    def RunCmd(
+        self,
+        command,
+        compReg=True,
+        env=None,
+        skipInterface=False,
+        onDone=None,
+        onPrepare=None,
+        userData=None,
+        addLayer=None,
+        notification=Notification.MAKE_VISIBLE,
+    ):
         """Run command typed into console command prompt (GPrompt).
         """Run command typed into console command prompt (GPrompt).
 
 
         .. todo::
         .. todo::
@@ -475,14 +492,17 @@ class GConsole(wx.EvtHandler):
             return
             return
 
 
         # update history file
         # update history file
-        self.UpdateHistoryFile(' '.join(command))
+        self.UpdateHistoryFile(" ".join(command))
 
 
         if command[0] in globalvar.grassCmd:
         if command[0] in globalvar.grassCmd:
             # send GRASS command without arguments to GUI command interface
             # send GRASS command without arguments to GUI command interface
             # except ignored commands (event is emitted)
             # 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:
+            if (
+                self._ignoredCmdPattern
+                and re.compile(self._ignoredCmdPattern).search(" ".join(command))
+                and "--help" not in command
+                and "--ui" not in command
+            ):
                 event = gIgnoredCmdRun(cmd=command)
                 event = gIgnoredCmdRun(cmd=command)
                 wx.PostEvent(self, event)
                 wx.PostEvent(self, event)
                 return
                 return
@@ -492,67 +512,66 @@ class GConsole(wx.EvtHandler):
                 try:
                 try:
                     task = GUI(show=None).ParseCommand(command)
                     task = GUI(show=None).ParseCommand(command)
                 except GException as e:
                 except GException as e:
-                    GError(parent=self._guiparent,
-                           message=str(e),
-                           showTraceback=False)
+                    GError(parent=self._guiparent, message=str(e), showTraceback=False)
                     return
                     return
 
 
                 hasParams = False
                 hasParams = False
                 if task:
                 if task:
                     options = task.get_options()
                     options = task.get_options()
-                    hasParams = options['params'] and options['flags']
+                    hasParams = options["params"] and options["flags"]
                     # check for <input>=-
                     # check for <input>=-
-                    for p in options['params']:
-                        if p.get('prompt', '') == 'input' and \
-                                p.get('element', '') == 'file' and \
-                                p.get('age', 'new') == 'old' and \
-                                p.get('value', '') == '-':
+                    for p in options["params"]:
+                        if (
+                            p.get("prompt", "") == "input"
+                            and p.get("element", "") == "file"
+                            and p.get("age", "new") == "old"
+                            and p.get("value", "") == "-"
+                        ):
                             GError(
                             GError(
                                 parent=self._guiparent,
                                 parent=self._guiparent,
                                 message=_(
                                 message=_(
                                     "Unable to run command:\n%(cmd)s\n\n"
                                     "Unable to run command:\n%(cmd)s\n\n"
                                     "Option <%(opt)s>: read from standard input is not "
                                     "Option <%(opt)s>: read from standard input is not "
-                                    "supported by wxGUI") % {
-                                    'cmd': ' '.join(command),
-                                    'opt': p.get(
-                                        'name',
-                                        '')})
+                                    "supported by wxGUI"
+                                )
+                                % {"cmd": " ".join(command), "opt": p.get("name", "")},
+                            )
                             return
                             return
 
 
                 if len(command) == 1:
                 if len(command) == 1:
-                    if command[0].startswith('g.gui.'):
+                    if command[0].startswith("g.gui."):
                         import imp
                         import imp
                         import inspect
                         import inspect
+
                         pyFile = command[0]
                         pyFile = command[0]
-                        if sys.platform == 'win32':
-                            pyFile += '.py'
-                        pyPath = os.path.join(
-                            os.environ['GISBASE'], 'scripts', pyFile)
+                        if sys.platform == "win32":
+                            pyFile += ".py"
+                        pyPath = os.path.join(os.environ["GISBASE"], "scripts", pyFile)
                         if not os.path.exists(pyPath):
                         if not os.path.exists(pyPath):
                             pyPath = os.path.join(
                             pyPath = os.path.join(
-                                os.environ['GRASS_ADDON_BASE'], 'scripts', pyFile)
+                                os.environ["GRASS_ADDON_BASE"], "scripts", pyFile
+                            )
                         if not os.path.exists(pyPath):
                         if not os.path.exists(pyPath):
                             GError(
                             GError(
                                 parent=self._guiparent,
                                 parent=self._guiparent,
-                                message=_("Module <%s> not found.") %
-                                command[0])
-                        pymodule = imp.load_source(
-                            command[0].replace('.', '_'), pyPath)
+                                message=_("Module <%s> not found.") % command[0],
+                            )
+                        pymodule = imp.load_source(command[0].replace(".", "_"), pyPath)
                         try:  # PY3
                         try:  # PY3
                             pymain = inspect.getfullargspec(pymodule.main)
                             pymain = inspect.getfullargspec(pymodule.main)
                         except AttributeError:
                         except AttributeError:
                             pymain = inspect.getargspec(pymodule.main)
                             pymain = inspect.getargspec(pymodule.main)
-                        if pymain and 'giface' in pymain.args:
+                        if pymain and "giface" in pymain.args:
                             pymodule.main(self._giface)
                             pymodule.main(self._giface)
                             return
                             return
 
 
                     # no arguments given
                     # no arguments given
-                    if hasParams and \
-                       not isinstance(self._guiparent, FormNotebook):
+                    if hasParams and not isinstance(self._guiparent, FormNotebook):
                         # also parent must be checked, see #3135 for details
                         # also parent must be checked, see #3135 for details
                         try:
                         try:
-                            GUI(parent=self._guiparent,
-                                giface=self._giface).ParseCommand(command)
+                            GUI(
+                                parent=self._guiparent, giface=self._giface
+                            ).ParseCommand(command)
                         except GException as e:
                         except GException as e:
                             print(e, file=sys.stderr)
                             print(e, file=sys.stderr)
 
 
@@ -568,13 +587,17 @@ class GConsole(wx.EvtHandler):
                     del env["GRASS_REGION"]
                     del env["GRASS_REGION"]
 
 
                 # process GRASS command with argument
                 # process GRASS command with argument
-                self.cmdThread.RunCmd(command,
-                                      stdout=self.cmdStdOut,
-                                      stderr=self.cmdStdErr,
-                                      onDone=onDone, onPrepare=onPrepare,
-                                      userData=userData, addLayer=addLayer,
-                                      env=env,
-                                      notification=notification)
+                self.cmdThread.RunCmd(
+                    command,
+                    stdout=self.cmdStdOut,
+                    stderr=self.cmdStdErr,
+                    onDone=onDone,
+                    onPrepare=onPrepare,
+                    userData=userData,
+                    addLayer=addLayer,
+                    env=env,
+                    notification=notification,
+                )
                 self.cmdOutputTimer.Start(50)
                 self.cmdOutputTimer.Start(50)
 
 
                 # we don't need to change computational region settings
                 # we don't need to change computational region settings
@@ -587,20 +610,21 @@ class GConsole(wx.EvtHandler):
             # of the script)
             # of the script)
 
 
             # check if we ignore the command (similar to grass commands part)
             # check if we ignore the command (similar to grass commands part)
-            if self._ignoredCmdPattern and \
-               re.compile(self._ignoredCmdPattern).search(' '.join(command)):
+            if self._ignoredCmdPattern and re.compile(self._ignoredCmdPattern).search(
+                " ".join(command)
+            ):
                 event = gIgnoredCmdRun(cmd=command)
                 event = gIgnoredCmdRun(cmd=command)
                 wx.PostEvent(self, event)
                 wx.PostEvent(self, event)
                 return
                 return
 
 
             skipInterface = True
             skipInterface = True
-            if os.path.splitext(command[0])[1] in ('.py', '.sh'):
+            if os.path.splitext(command[0])[1] in (".py", ".sh"):
                 try:
                 try:
                     sfile = open(command[0], "r")
                     sfile = open(command[0], "r")
                     for line in sfile.readlines():
                     for line in sfile.readlines():
                         if len(line) < 2:
                         if len(line) < 2:
                             continue
                             continue
-                        if line[0] == '#' and line[1] == '%':
+                        if line[0] == "#" and line[1] == "%":
                             skipInterface = False
                             skipInterface = False
                             break
                             break
                     sfile.close()
                     sfile.close()
@@ -617,16 +641,19 @@ class GConsole(wx.EvtHandler):
 
 
             if task:
             if task:
                 # process GRASS command without argument
                 # process GRASS command without argument
-                GUI(parent=self._guiparent,
-                    giface=self._giface).ParseCommand(command)
+                GUI(parent=self._guiparent, giface=self._giface).ParseCommand(command)
             else:
             else:
-                self.cmdThread.RunCmd(command,
-                                      stdout=self.cmdStdOut,
-                                      stderr=self.cmdStdErr,
-                                      onDone=onDone, onPrepare=onPrepare,
-                                      userData=userData, addLayer=addLayer,
-                                      env=env,
-                                      notification=notification)
+                self.cmdThread.RunCmd(
+                    command,
+                    stdout=self.cmdStdOut,
+                    stderr=self.cmdStdErr,
+                    onDone=onDone,
+                    onPrepare=onPrepare,
+                    userData=userData,
+                    addLayer=addLayer,
+                    env=env,
+                    notification=notification,
+                )
             self.cmdOutputTimer.Start(50)
             self.cmdOutputTimer.Start(50)
 
 
     def GetLog(self, err=False):
     def GetLog(self, err=False):
@@ -653,8 +680,10 @@ class GConsole(wx.EvtHandler):
 
 
     def OnCmdRun(self, event):
     def OnCmdRun(self, event):
         """Run command"""
         """Run command"""
-        self.WriteCmdLog('(%s)\n%s' % (str(time.ctime()), ' '.join(event.cmd)),
-                         notification=event.notification)
+        self.WriteCmdLog(
+            "(%s)\n%s" % (str(time.ctime()), " ".join(event.cmd)),
+            notification=event.notification,
+        )
         event.Skip()
         event.Skip()
 
 
     def OnCmdDone(self, event):
     def OnCmdDone(self, event):
@@ -671,28 +700,36 @@ class GConsole(wx.EvtHandler):
             else:
             else:
                 mtime = int(ctime / 60)
                 mtime = int(ctime / 60)
                 stime = _("%(min)d min %(sec)d sec") % {
                 stime = _("%(min)d min %(sec)d sec") % {
-                    'min': mtime, 'sec': int(ctime - (mtime * 60))}
+                    "min": mtime,
+                    "sec": int(ctime - (mtime * 60)),
+                }
         except KeyError:
         except KeyError:
             # stopped deamon
             # stopped deamon
             stime = _("unknown")
             stime = _("unknown")
 
 
         if event.aborted:
         if event.aborted:
             # Thread aborted (using our convention of None return)
             # Thread aborted (using our convention of None return)
-            self.WriteWarning(_('Please note that the data are left in'
-                                ' inconsistent state and may be corrupted'))
-            msg = _('Command aborted')
+            self.WriteWarning(
+                _(
+                    "Please note that the data are left in"
+                    " inconsistent state and may be corrupted"
+                )
+            )
+            msg = _("Command aborted")
         else:
         else:
-            msg = _('Command finished')
+            msg = _("Command finished")
 
 
-        self.WriteCmdLog('(%s) %s (%s)' % (str(time.ctime()), msg, stime),
-                         notification=event.notification)
+        self.WriteCmdLog(
+            "(%s) %s (%s)" % (str(time.ctime()), msg, stime),
+            notification=event.notification,
+        )
 
 
         if event.onDone:
         if event.onDone:
             event.onDone(event)
             event.onDone(event)
 
 
         self.cmdOutputTimer.Stop()
         self.cmdOutputTimer.Stop()
 
 
-        if event.cmd[0] == 'g.gisenv':
+        if event.cmd[0] == "g.gisenv":
             Debug.SetLevel()
             Debug.SetLevel()
             self.Redirect()
             self.Redirect()
 
 
@@ -713,38 +750,43 @@ class GConsole(wx.EvtHandler):
             return
             return
 
 
         name = task.get_name()
         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'):
+        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 multiple maps (e.g. r.series.interp), we need add each
                     # if multiple maps (e.g. r.series.interp), we need add each
-                    if p.get('multiple', False):
-                        lnames = p.get('value').split(',')
+                    if p.get("multiple", False):
+                        lnames = p.get("value").split(",")
                         # in case multiple input (old) maps in r.colors
                         # in case multiple input (old) maps in r.colors
                         # we don't want to rerender it multiple times! just
                         # we don't want to rerender it multiple times! just
                         # once
                         # once
-                        if p.get('age', 'old') == 'old':
+                        if p.get("age", "old") == "old":
                             lnames = lnames[0:1]
                             lnames = lnames[0:1]
                     else:
                     else:
-                        lnames = [p.get('value')]
+                        lnames = [p.get("value")]
                     for lname in lnames:
                     for lname in lnames:
-                        if '@' not in lname:
-                            lname += '@' + grass.gisenv()['MAPSET']
-                        if grass.find_file(lname, element=p.get('element'))[
-                                'fullname']:
+                        if "@" not in lname:
+                            lname += "@" + grass.gisenv()["MAPSET"]
+                        if grass.find_file(lname, element=p.get("element"))["fullname"]:
                             self.mapCreated.emit(
                             self.mapCreated.emit(
-                                name=lname, ltype=prompt, add=event.addLayer)
+                                name=lname, ltype=prompt, add=event.addLayer
+                            )
                             gisenv = grass.gisenv()
                             gisenv = grass.gisenv()
-                            self._giface.grassdbChanged.emit(grassdb=gisenv['GISDBASE'],
-                                                             location=gisenv['LOCATION_NAME'],
-                                                             mapset=gisenv['MAPSET'],
-                                                             action='new',
-                                                             map=lname.split('@')[0],
-                                                             element=prompt)
-        if name == 'r.mask':
+                            self._giface.grassdbChanged.emit(
+                                grassdb=gisenv["GISDBASE"],
+                                location=gisenv["LOCATION_NAME"],
+                                mapset=gisenv["MAPSET"],
+                                action="new",
+                                map=lname.split("@")[0],
+                                element=prompt,
+                            )
+        if name == "r.mask":
             self.updateMap.emit()
             self.updateMap.emit()
 
 
         event.Skip()
         event.Skip()
@@ -759,15 +801,16 @@ class GConsole(wx.EvtHandler):
         """
         """
         env = grass.gisenv()
         env = grass.gisenv()
         try:
         try:
-            filePath = os.path.join(env['GISDBASE'],
-                                    env['LOCATION_NAME'],
-                                    env['MAPSET'],
-                                    '.bash_history')
-            fileHistory = codecs.open(filePath, encoding='utf-8', mode='a')
+            filePath = os.path.join(
+                env["GISDBASE"], env["LOCATION_NAME"], env["MAPSET"], ".bash_history"
+            )
+            fileHistory = codecs.open(filePath, encoding="utf-8", mode="a")
         except IOError as e:
         except IOError as e:
-            GError(_("Unable to write file '%(filePath)s'.\n\nDetails: %(error)s") %
-                   {'filePath': filePath, 'error': e},
-                   parent=self._guiparent)
+            GError(
+                _("Unable to write file '%(filePath)s'.\n\nDetails: %(error)s")
+                % {"filePath": filePath, "error": e},
+                parent=self._guiparent,
+            )
             return
             return
 
 
         try:
         try:

+ 41 - 41
gui/wxpython/core/giface.py

@@ -32,6 +32,7 @@ class Notification:
     The value is the suggestion how user should be notified
     The value is the suggestion how user should be notified
     about the new message.
     about the new message.
     """
     """
+
     NO_NOTIFICATION = 0
     NO_NOTIFICATION = 0
     HIGHLIGHT = 1
     HIGHLIGHT = 1
     MAKE_VISIBLE = 2
     MAKE_VISIBLE = 2
@@ -46,11 +47,11 @@ class Layer(object):
         Current implementations only provides all attributes of existing
         Current implementations only provides all attributes of existing
         layer as used in lmgr.
         layer as used in lmgr.
     """
     """
+
     pass
     pass
 
 
 
 
 class LayerList(object):
 class LayerList(object):
-
     def GetSelectedLayers(self, checkedOnly=True):
     def GetSelectedLayers(self, checkedOnly=True):
         """Returns list of selected layers.
         """Returns list of selected layers.
 
 
@@ -71,8 +72,7 @@ class LayerList(object):
         """
         """
         raise NotImplementedError()
         raise NotImplementedError()
 
 
-    def AddLayer(self, ltype, name=None, checked=None,
-                 opacity=1.0, cmd=None):
+    def AddLayer(self, ltype, name=None, checked=None, opacity=1.0, cmd=None):
         """Adds a new layer to the layer list.
         """Adds a new layer to the layer list.
 
 
         Launches property dialog if needed (raster, vector, etc.)
         Launches property dialog if needed (raster, vector, etc.)
@@ -118,29 +118,23 @@ class GrassInterface:
     """
     """
 
 
     def RunCmd(self, *args, **kwargs):
     def RunCmd(self, *args, **kwargs):
-        """Executes a command.
-        """
+        """Executes a command."""
         raise NotImplementedError()
         raise NotImplementedError()
 
 
     def Help(self, entry):
     def Help(self, entry):
-        """Shows a manual page for a given entry.
-        """
+        """Shows a manual page for a given entry."""
         raise NotImplementedError()
         raise NotImplementedError()
 
 
     def WriteLog(self, text, wrap=None, notification=Notification.HIGHLIGHT):
     def WriteLog(self, text, wrap=None, notification=Notification.HIGHLIGHT):
-        """Writes log message.
-        """
+        """Writes log message."""
         raise NotImplementedError()
         raise NotImplementedError()
 
 
-    def WriteCmdLog(self, text, pid=None,
-                    notification=Notification.MAKE_VISIBLE):
-        """Writes message related to start or end of the command.
-        """
+    def WriteCmdLog(self, text, pid=None, notification=Notification.MAKE_VISIBLE):
+        """Writes message related to start or end of the command."""
         raise NotImplementedError()
         raise NotImplementedError()
 
 
     def WriteWarning(self, text):
     def WriteWarning(self, text):
-        """Writes warning message for the user.
-        """
+        """Writes warning message for the user."""
         raise NotImplementedError()
         raise NotImplementedError()
 
 
     def WriteError(self, text):
     def WriteError(self, text):
@@ -156,8 +150,7 @@ class GrassInterface:
         raise NotImplementedError()
         raise NotImplementedError()
 
 
     def GetLayerList(self):
     def GetLayerList(self):
-        """Returns a layer management object.
-        """
+        """Returns a layer management object."""
         raise NotImplementedError()
         raise NotImplementedError()
 
 
     def GetMapDisplay(self):
     def GetMapDisplay(self):
@@ -220,10 +213,12 @@ class StandaloneGrassInterface(GrassInterface):
         # Used for adding/refreshing displayed layers.
         # Used for adding/refreshing displayed layers.
         # attributes: name: map name, ltype: map type,
         # attributes: name: map name, ltype: map type,
         # add: if map should be added to layer tree (questionable attribute)
         # add: if map should be added to layer tree (questionable attribute)
-        self.mapCreated = Signal('StandaloneGrassInterface.mapCreated')
+        self.mapCreated = Signal("StandaloneGrassInterface.mapCreated")
 
 
         # Signal for communicating current mapset has been switched
         # Signal for communicating current mapset has been switched
-        self.currentMapsetChanged = Signal('StandaloneGrassInterface.currentMapsetChanged')
+        self.currentMapsetChanged = Signal(
+            "StandaloneGrassInterface.currentMapsetChanged"
+        )
 
 
         # Signal for communicating something in current grassdb has changed.
         # Signal for communicating something in current grassdb has changed.
         # Parameters:
         # Parameters:
@@ -234,17 +229,16 @@ class StandaloneGrassInterface(GrassInterface):
         # mapset: mapset name, required when element is 'mapset', 'raster', 'vector' or 'raster_3d'
         # mapset: mapset name, required when element is 'mapset', 'raster', 'vector' or 'raster_3d'
         # map: map name, required when element is 'raster', 'vector' or 'raster_3d'
         # map: map name, required when element is 'raster', 'vector' or 'raster_3d'
         # newname: new name (of mapset, map), required with action='rename'
         # newname: new name (of mapset, map), required with action='rename'
-        self.grassdbChanged = Signal('StandaloneGrassInterface.grassdbChanged')
+        self.grassdbChanged = Signal("StandaloneGrassInterface.grassdbChanged")
 
 
         # Signal emitted to request updating of map
         # Signal emitted to request updating of map
-        self.updateMap = Signal('StandaloneGrassInterface.updateMap')
+        self.updateMap = Signal("StandaloneGrassInterface.updateMap")
 
 
         # Signal emitted when workspace is changed
         # Signal emitted when workspace is changed
-        self.workspaceChanged = Signal('StandaloneGrassInterface.workspaceChanged')
+        self.workspaceChanged = Signal("StandaloneGrassInterface.workspaceChanged")
 
 
         # workaround, standalone grass interface should be moved to sep. file
         # workaround, standalone grass interface should be moved to sep. file
-        from core.gconsole import GConsole, \
-            EVT_CMD_OUTPUT, EVT_CMD_PROGRESS
+        from core.gconsole import GConsole, EVT_CMD_OUTPUT, EVT_CMD_PROGRESS
 
 
         self._gconsole = GConsole()
         self._gconsole = GConsole()
         self._gconsole.Bind(EVT_CMD_PROGRESS, self._onCmdProgress)
         self._gconsole.Bind(EVT_CMD_PROGRESS, self._onCmdProgress)
@@ -259,9 +253,9 @@ class StandaloneGrassInterface(GrassInterface):
         message = event.text
         message = event.text
         style = event.type
         style = event.type
 
 
-        if style == 'warning':
+        if style == "warning":
             self.WriteWarning(message)
             self.WriteWarning(message)
-        elif style == 'error':
+        elif style == "error":
             self.WriteError(message)
             self.WriteError(message)
         else:
         else:
             self.WriteLog(message)
             self.WriteLog(message)
@@ -272,9 +266,18 @@ class StandaloneGrassInterface(GrassInterface):
         grass.percent(event.value, 100, 1)
         grass.percent(event.value, 100, 1)
         event.Skip()
         event.Skip()
 
 
-    def RunCmd(self, command, compReg=True, env=None, skipInterface=False,
-               onDone=None, onPrepare=None, userData=None, addLayer=None,
-               notification=Notification.MAKE_VISIBLE):
+    def RunCmd(
+        self,
+        command,
+        compReg=True,
+        env=None,
+        skipInterface=False,
+        onDone=None,
+        onPrepare=None,
+        userData=None,
+        addLayer=None,
+        notification=Notification.MAKE_VISIBLE,
+    ):
         self._gconsole.RunCmd(
         self._gconsole.RunCmd(
             command=command,
             command=command,
             compReg=compReg,
             compReg=compReg,
@@ -284,19 +287,18 @@ class StandaloneGrassInterface(GrassInterface):
             onPrepare=onPrepare,
             onPrepare=onPrepare,
             userData=userData,
             userData=userData,
             addLayer=addLayer,
             addLayer=addLayer,
-            notification=notification)
+            notification=notification,
+        )
 
 
     def Help(self, entry):
     def Help(self, entry):
-        self._gconsole.RunCmd(['g.manual', 'entry=%s' % entry])
+        self._gconsole.RunCmd(["g.manual", "entry=%s" % entry])
 
 
-    def WriteLog(self, text, wrap=None,
-                 notification=Notification.HIGHLIGHT):
+    def WriteLog(self, text, wrap=None, notification=Notification.HIGHLIGHT):
         self._write(grass.message, text)
         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:
         if pid:
-            text = '(' + str(pid) + ') ' + text
+            text = "(" + str(pid) + ") " + text
         self._write(grass.message, text)
         self._write(grass.message, text)
 
 
     def WriteWarning(self, text):
     def WriteWarning(self, text):
@@ -307,7 +309,7 @@ class StandaloneGrassInterface(GrassInterface):
 
 
     def _write(self, function, text):
     def _write(self, function, text):
         orig = os.getenv("GRASS_MESSAGE_FORMAT")
         orig = os.getenv("GRASS_MESSAGE_FORMAT")
-        os.environ["GRASS_MESSAGE_FORMAT"] = 'standard'
+        os.environ["GRASS_MESSAGE_FORMAT"] = "standard"
         function(text)
         function(text)
         os.environ["GRASS_MESSAGE_FORMAT"] = orig
         os.environ["GRASS_MESSAGE_FORMAT"] = orig
 
 
@@ -318,13 +320,11 @@ class StandaloneGrassInterface(GrassInterface):
         return None
         return None
 
 
     def GetMapDisplay(self):
     def GetMapDisplay(self):
-        """Get current map display.
-        """
+        """Get current map display."""
         return None
         return None
 
 
     def GetAllMapDisplays(self):
     def GetAllMapDisplays(self):
-        """Get list of all map displays.
-        """
+        """Get list of all map displays."""
         return []
         return []
 
 
     def GetMapWindow(self):
     def GetMapWindow(self):

+ 45 - 41
gui/wxpython/core/globalvar.py

@@ -74,7 +74,7 @@ def version_as_string(version):
 
 
 
 
 def CheckWxPhoenix():
 def CheckWxPhoenix():
-    if 'phoenix' in wx.version():
+    if "phoenix" in wx.version():
         return True
         return True
     return False
     return False
 
 
@@ -92,25 +92,27 @@ def CheckWxVersion(version):
 
 
 def CheckForWx():
 def CheckForWx():
     """Try to import wx module"""
     """Try to import wx module"""
-    if 'wx' in sys.modules.keys():
+    if "wx" in sys.modules.keys():
         return
         return
 
 
     try:
     try:
         import wx
         import wx
+
         version = parse_version_string(wx.__version__)
         version = parse_version_string(wx.__version__)
         if version < WXPY3_MIN_VERSION:
         if version < WXPY3_MIN_VERSION:
-            raise ValueError(
-                "Your wxPython version is {}".format(wx.__version__))
+            raise ValueError("Your wxPython version is {}".format(wx.__version__))
         return
         return
     except ImportError as e:
     except ImportError as e:
-        print('ERROR: wxGUI requires wxPython. {}'.format(e),
-              file=sys.stderr)
-        print('You can still use GRASS GIS modules in'
-              ' the command line or in Python.', file=sys.stderr)
+        print("ERROR: wxGUI requires wxPython. {}".format(e), file=sys.stderr)
+        print(
+            "You can still use GRASS GIS modules in" " the command line or in Python.",
+            file=sys.stderr,
+        )
         sys.exit(1)
         sys.exit(1)
     except locale.Error as e:
     except locale.Error as e:
         print("Unable to set locale:", e, file=sys.stderr)
         print("Unable to set locale:", e, file=sys.stderr)
-        os.environ['LC_ALL'] = ''
+        os.environ["LC_ALL"] = ""
+
 
 
 if not os.getenv("GRASS_WXBUNDLED"):
 if not os.getenv("GRASS_WXBUNDLED"):
     CheckForWx()
     CheckForWx()
@@ -120,31 +122,31 @@ import wx  # noqa: E402
 if CheckWxPhoenix():
 if CheckWxPhoenix():
     try:
     try:
         import agw.flatnotebook as FN
         import agw.flatnotebook as FN
-    except ImportError: # if it's not there locally, try the wxPython lib.
+    except ImportError:  # if it's not there locally, try the wxPython lib.
         import wx.lib.agw.flatnotebook as FN
         import wx.lib.agw.flatnotebook as FN
 else:
 else:
     import wx.lib.flatnotebook as FN
     import wx.lib.flatnotebook as FN
 
 
 
 
-
 """
 """
 Query layer (generated for example by selecting item in the Attribute Table Manager)
 Query layer (generated for example by selecting item in the Attribute Table Manager)
 Deleted automatically on re-render action
 Deleted automatically on re-render action
 """
 """
 # temporal query layer (removed on re-render action)
 # temporal query layer (removed on re-render action)
-QUERYLAYER = 'qlayer'
+QUERYLAYER = "qlayer"
 
 
 """Style definition for FlatNotebook pages"""
 """Style definition for FlatNotebook pages"""
-FNPageStyle = FN.FNB_FF2 | \
-    FN.FNB_BACKGROUND_GRADIENT | \
-    FN.FNB_NODRAG | \
-    FN.FNB_TABS_BORDER_SIMPLE
-
-FNPageDStyle = FN.FNB_FANCY_TABS | \
-    FN.FNB_BOTTOM | \
-    FN.FNB_NODRAG | \
-    FN.FNB_NO_NAV_BUTTONS | \
-    FN.FNB_NO_X_BUTTON
+FNPageStyle = (
+    FN.FNB_FF2 | FN.FNB_BACKGROUND_GRADIENT | FN.FNB_NODRAG | FN.FNB_TABS_BORDER_SIMPLE
+)
+
+FNPageDStyle = (
+    FN.FNB_FANCY_TABS
+    | FN.FNB_BOTTOM
+    | FN.FNB_NODRAG
+    | FN.FNB_NO_NAV_BUTTONS
+    | FN.FNB_NO_X_BUTTON
+)
 
 
 FNPageColor = wx.Colour(125, 200, 175)
 FNPageColor = wx.Colour(125, 200, 175)
 
 
@@ -168,16 +170,16 @@ GM_WINDOW_MIN_SIZE = (525, 400)
 # use UBUNTU_MENUPROXY=0 to disbale global menu on ubuntu but in the same time
 # use UBUNTU_MENUPROXY=0 to disbale global menu on ubuntu but in the same time
 # to get smaller lmgr
 # to get smaller lmgr
 # [1] https://wiki.ubuntu.com/DesktopExperienceTeam/ApplicationMenu#Troubleshooting
 # [1] https://wiki.ubuntu.com/DesktopExperienceTeam/ApplicationMenu#Troubleshooting
-if sys.platform in ('win32', 'darwin') or os.environ.get('UBUNTU_MENUPROXY'):
+if sys.platform in ("win32", "darwin") or os.environ.get("UBUNTU_MENUPROXY"):
     GM_WINDOW_SIZE = (GM_WINDOW_MIN_SIZE[0], 600)
     GM_WINDOW_SIZE = (GM_WINDOW_MIN_SIZE[0], 600)
 else:
 else:
     GM_WINDOW_SIZE = (625, 600)
     GM_WINDOW_SIZE = (625, 600)
 
 
-if sys.platform == 'win32':
-    BIN_EXT = '.exe'
-    SCT_EXT = '.bat'
+if sys.platform == "win32":
+    BIN_EXT = ".exe"
+    SCT_EXT = ".bat"
 else:
 else:
-    BIN_EXT = SCT_EXT = ''
+    BIN_EXT = SCT_EXT = ""
 
 
 
 
 def UpdateGRASSAddOnCommands(eList=None):
 def UpdateGRASSAddOnCommands(eList=None):
@@ -189,12 +191,12 @@ def UpdateGRASSAddOnCommands(eList=None):
     global grassCmd, grassScripts
     global grassCmd, grassScripts
 
 
     # scan addons (path)
     # scan addons (path)
-    addonPath = os.getenv('GRASS_ADDON_PATH', '')
-    addonBase = os.getenv('GRASS_ADDON_BASE')
+    addonPath = os.getenv("GRASS_ADDON_PATH", "")
+    addonBase = os.getenv("GRASS_ADDON_BASE")
     if addonBase:
     if addonBase:
-        addonPath += os.pathsep + os.path.join(addonBase, 'bin')
-        if sys.platform != 'win32':
-            addonPath += os.pathsep + os.path.join(addonBase, 'scripts')
+        addonPath += os.pathsep + os.path.join(addonBase, "bin")
+        if sys.platform != "win32":
+            addonPath += os.pathsep + os.path.join(addonBase, "scripts")
 
 
     # remove commands first
     # remove commands first
     if eList:
     if eList:
@@ -204,17 +206,17 @@ def UpdateGRASSAddOnCommands(eList=None):
         Debug.msg(1, "Number of removed AddOn commands: %d", len(eList))
         Debug.msg(1, "Number of removed AddOn commands: %d", len(eList))
 
 
     nCmd = 0
     nCmd = 0
-    pathList = os.getenv('PATH', '').split(os.pathsep)
+    pathList = os.getenv("PATH", "").split(os.pathsep)
     for path in addonPath.split(os.pathsep):
     for path in addonPath.split(os.pathsep):
         if not os.path.exists(path) or not os.path.isdir(path):
         if not os.path.exists(path) or not os.path.isdir(path):
             continue
             continue
 
 
         # check if addon is in the path
         # check if addon is in the path
         if pathList and path not in pathList:
         if pathList and path not in pathList:
-            os.environ['PATH'] = path + os.pathsep + os.environ['PATH']
+            os.environ["PATH"] = path + os.pathsep + os.environ["PATH"]
 
 
         for fname in os.listdir(path):
         for fname in os.listdir(path):
-            if fname in ['docs', 'modules.xml']:
+            if fname in ["docs", "modules.xml"]:
                 continue
                 continue
             if grassScripts:  # win32
             if grassScripts:  # win32
                 name, ext = os.path.splitext(fname)
                 name, ext = os.path.splitext(fname)
@@ -225,9 +227,11 @@ def UpdateGRASSAddOnCommands(eList=None):
                         grassCmd.add(name)
                         grassCmd.add(name)
                         Debug.msg(3, "AddOn commands: %s", name)
                         Debug.msg(3, "AddOn commands: %s", name)
                         nCmd += 1
                         nCmd += 1
-                if ext == SCT_EXT and \
-                        ext in grassScripts.keys() and \
-                        name not in grassScripts[ext]:
+                if (
+                    ext == SCT_EXT
+                    and ext in grassScripts.keys()
+                    and name not in grassScripts[ext]
+                ):
                     grassScripts[ext].append(name)
                     grassScripts[ext].append(name)
             else:
             else:
                 if fname not in grassCmd:
                 if fname not in grassCmd:
@@ -237,6 +241,7 @@ def UpdateGRASSAddOnCommands(eList=None):
 
 
     Debug.msg(1, "Number of GRASS AddOn commands: %d", nCmd)
     Debug.msg(1, "Number of GRASS AddOn commands: %d", nCmd)
 
 
+
 """@brief Collected GRASS-relared binaries/scripts"""
 """@brief Collected GRASS-relared binaries/scripts"""
 grassCmd, grassScripts = get_commands()
 grassCmd, grassScripts = get_commands()
 Debug.msg(1, "Number of core GRASS commands: %d", len(grassCmd))
 Debug.msg(1, "Number of core GRASS commands: %d", len(grassCmd))
@@ -249,8 +254,7 @@ toolbarSize = (24, 24)
 hasAgw = CheckWxVersion([2, 8, 11, 0])
 hasAgw = CheckWxVersion([2, 8, 11, 0])
 wxPythonPhoenix = CheckWxPhoenix()
 wxPythonPhoenix = CheckWxPhoenix()
 
 
-gtk3 = True if 'gtk3' in wx.PlatformInfo else False
+gtk3 = True if "gtk3" in wx.PlatformInfo else False
 
 
 """@Add GUIDIR/scripts into path"""
 """@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"]

+ 17 - 13
gui/wxpython/core/gthread.py

@@ -21,6 +21,7 @@ import wx
 from wx.lib.newevent import NewEvent
 from wx.lib.newevent import NewEvent
 
 
 import sys
 import sys
+
 if sys.version_info.major == 2:
 if sys.version_info.major == 2:
     import Queue
     import Queue
 else:
 else:
@@ -37,6 +38,7 @@ class gThread(threading.Thread, wx.EvtHandler):
     terminating thread:
     terminating thread:
     https://www.geeksforgeeks.org/python-different-ways-to-kill-a-thread/
     https://www.geeksforgeeks.org/python-different-ways-to-kill-a-thread/
     """
     """
+
     requestId = 0
     requestId = 0
 
 
     def __init__(self, requestQ=None, resultQ=None, **kwds):
     def __init__(self, requestQ=None, resultQ=None, **kwds):
@@ -89,7 +91,7 @@ class gThread(threading.Thread, wx.EvtHandler):
     def run(self):
     def run(self):
         while True:
         while True:
             requestId, args, kwds = self.requestQ.get()
             requestId, args, kwds = self.requestQ.get()
-            for key in ('callable', 'ondone', 'userdata', 'onterminate'):
+            for key in ("callable", "ondone", "userdata", "onterminate"):
                 if key in kwds:
                 if key in kwds:
                     vars()[key] = kwds[key]
                     vars()[key] = kwds[key]
                     del kwds[key]
                     del kwds[key]
@@ -100,10 +102,10 @@ class gThread(threading.Thread, wx.EvtHandler):
 
 
             ret = None
             ret = None
             exception = None
             exception = None
-            time.sleep(.01)
+            time.sleep(0.01)
 
 
             self._terminate_evt = wxThdTerminate(
             self._terminate_evt = wxThdTerminate(
-                onterminate=vars()['onterminate'],
+                onterminate=vars()["onterminate"],
                 kwds=kwds,
                 kwds=kwds,
                 args=args,
                 args=args,
                 pid=requestId,
                 pid=requestId,
@@ -112,7 +114,7 @@ class gThread(threading.Thread, wx.EvtHandler):
             if self.terminate:
             if self.terminate:
                 return
                 return
 
 
-            ret = vars()['callable'](*args, **kwds)
+            ret = vars()["callable"](*args, **kwds)
 
 
             if self.terminate:
             if self.terminate:
                 return
                 return
@@ -121,13 +123,15 @@ class gThread(threading.Thread, wx.EvtHandler):
 
 
             self.resultQ.put((requestId, ret))
             self.resultQ.put((requestId, ret))
 
 
-            event = wxCmdDone(ondone=vars()['ondone'],
-                              kwds=kwds,
-                              args=args,  # TODO expand args to kwds
-                              ret=ret,
-                              exception=exception,
-                              userdata=vars()['userdata'],
-                              pid=requestId)
+            event = wxCmdDone(
+                ondone=vars()["ondone"],
+                kwds=kwds,
+                args=args,  # TODO expand args to kwds
+                ret=ret,
+                exception=exception,
+                userdata=vars()["userdata"],
+                pid=requestId,
+            )
 
 
             # send event
             # send event
             wx.PostEvent(self, event)
             wx.PostEvent(self, event)
@@ -151,14 +155,14 @@ class gThread(threading.Thread, wx.EvtHandler):
         self.run = self.__run_backup
         self.run = self.__run_backup
 
 
     def globaltrace(self, frame, event, arg):
     def globaltrace(self, frame, event, arg):
-        if event == 'call':
+        if event == "call":
             return self.localtrace
             return self.localtrace
         else:
         else:
             return None
             return None
 
 
     def localtrace(self, frame, event, arg):
     def localtrace(self, frame, event, arg):
         if self.terminate:
         if self.terminate:
-            if event == 'line':
+            if event == "line":
                 # Send event
                 # Send event
                 wx.PostEvent(self, self._terminate_evt)
                 wx.PostEvent(self, self._terminate_evt)
                 raise SystemExit()
                 raise SystemExit()

+ 46 - 34
gui/wxpython/core/layerlist.py

@@ -69,8 +69,17 @@ class LayerList(object):
                 layers.append(layer)
                 layers.append(layer)
         return layers
         return layers
 
 
-    def AddNewLayer(self, name, mapType, cmd, active=True, hidden=False,
-                    opacity=1, label=None, pos=0):
+    def AddNewLayer(
+        self,
+        name,
+        mapType,
+        cmd,
+        active=True,
+        hidden=False,
+        opacity=1,
+        label=None,
+        pos=0,
+    ):
         """Creates new layer and adds it to the list (insert to the first position).
         """Creates new layer and adds it to the list (insert to the first position).
 
 
         :param ltype: layer type (raster, vector, raster_3d, ...)
         :param ltype: layer type (raster, vector, raster_3d, ...)
@@ -96,13 +105,11 @@ class LayerList(object):
         return layer
         return layer
 
 
     def AddLayer(self, layer):
     def AddLayer(self, layer):
-        """Adds a layer to the layer list.
-        """
+        """Adds a layer to the layer list."""
         self._list.insert(0, layer)
         self._list.insert(0, layer)
 
 
     def InsertLayer(self, index, layer):
     def InsertLayer(self, index, layer):
-        """Adds a layer to the layer list.
-        """
+        """Adds a layer to the layer list."""
         self._list.insert(index, layer)
         self._list.insert(index, layer)
 
 
     def RemoveLayer(self, layer):
     def RemoveLayer(self, layer):
@@ -149,9 +156,9 @@ class LayerList(object):
         return len(self._list)
         return len(self._list)
 
 
     def __str__(self):
     def __str__(self):
-        text = ''
+        text = ""
         for layer in self._list:
         for layer in self._list:
-            text += str(layer.name) + '\n'
+            text += str(layer.name) + "\n"
         return text
         return text
 
 
 
 
@@ -192,11 +199,13 @@ class Layer(object):
         self._hidden = False
         self._hidden = False
         self._initialized = False
         self._initialized = False
 
 
-        self._mapTypes = ['raster', 'vector', 'raster_3d', 'rgb']
-        self._internalTypes = {'raster': 'cell',
-                               'vector': 'vector',
-                               'raster_3d': 'grid3',
-                               'rgb': 'rgb'}
+        self._mapTypes = ["raster", "vector", "raster_3d", "rgb"]
+        self._internalTypes = {
+            "raster": "cell",
+            "vector": "vector",
+            "raster_3d": "grid3",
+            "rgb": "rgb",
+        }
 
 
     def GetName(self):
     def GetName(self):
         return self._name
         return self._name
@@ -209,22 +218,21 @@ class Layer(object):
         Therefore map type has to be set first.
         Therefore map type has to be set first.
         """
         """
         if not self.hidden:
         if not self.hidden:
-            fullName = name.split('@')
-            if len(
-                    fullName) == 1 and self._mapType != 'rgb':  # skip checking rgb maps for now
+            fullName = name.split("@")
+            if (
+                len(fullName) == 1 and self._mapType != "rgb"
+            ):  # skip checking rgb maps for now
                 if self._mapType is None:
                 if self._mapType is None:
                     raise ValueError(
                     raise ValueError(
-                        "To set layer name, the type of layer must be specified.")
+                        "To set layer name, the type of layer must be specified."
+                    )
 
 
                 res = gcore.find_file(
                 res = gcore.find_file(
-                    name=fullName,
-                    element=self._internalTypes[
-                        self._mapType])
-                if not res['mapset']:
-                    raise ValueError(
-                        "Map <{name}> not found.".format(
-                            name=name))
-                self._name = name + '@' + res['mapset']
+                    name=fullName, element=self._internalTypes[self._mapType]
+                )
+                if not res["mapset"]:
+                    raise ValueError("Map <{name}> not found.".format(name=name))
+                self._name = name + "@" + res["mapset"]
             else:
             else:
                 self._name = name
                 self._name = name
         self.label = name
         self.label = name
@@ -256,9 +264,7 @@ class Layer(object):
         :param mapType: can be 'raster', 'vector', 'raster_3d'
         :param mapType: can be 'raster', 'vector', 'raster_3d'
         """
         """
         if mapType not in self._mapTypes:
         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
         self._mapType = mapType
 
 
@@ -278,8 +284,8 @@ class Layer(object):
         """
         """
         if not (0 <= opacity <= 1):
         if not (0 <= opacity <= 1):
             raise ValueError(
             raise ValueError(
-                "Opacity value must be between 0 and 1, not {op}.".format(
-                    op=opacity))
+                "Opacity value must be between 0 and 1, not {op}.".format(op=opacity)
+            )
         self._opacity = opacity
         self._opacity = opacity
 
 
     opacity = property(fget=GetOpacity, fset=SetOpacity)
     opacity = property(fget=GetOpacity, fset=SetOpacity)
@@ -369,10 +375,16 @@ class LayerListToRendererConverter:
 
 
     def AddLayer(self, index, layer):
     def AddLayer(self, index, layer):
         """Adds layer to renderer (prepends)."""
         """Adds layer to renderer (prepends)."""
-        self._renderer.AddLayer(ltype=layer.mapType, command=layer.cmd,
-                                name=layer.name, active=layer.active,
-                                hidden=False, opacity=layer.opacity,
-                                render=True, pos=-1)
+        self._renderer.AddLayer(
+            ltype=layer.mapType,
+            command=layer.cmd,
+            name=layer.name,
+            active=layer.active,
+            hidden=False,
+            opacity=layer.opacity,
+            render=True,
+            pos=-1,
+        )
 
 
     def RemoveLayer(self, index):
     def RemoveLayer(self, index):
         """Removes layer from renderer."""
         """Removes layer from renderer."""

+ 69 - 54
gui/wxpython/core/menutree.py

@@ -38,6 +38,7 @@ from __future__ import print_function
 import os
 import os
 import sys
 import sys
 import copy
 import copy
+
 try:
 try:
     import xml.etree.ElementTree as etree
     import xml.etree.ElementTree as etree
 except ImportError:
 except ImportError:
@@ -64,9 +65,9 @@ class MenuTreeModelBuilder:
     # message_handler=GError should be replaced by None
     # message_handler=GError should be replaced by None
     def __init__(self, filename, expandAddons=True, message_handler=GError):
     def __init__(self, filename, expandAddons=True, message_handler=GError):
 
 
-        self.menustyle = UserSettings.Get(group='appearance',
-                                          key='menustyle',
-                                          subkey='selection')
+        self.menustyle = UserSettings.Get(
+            group="appearance", key="menustyle", subkey="selection"
+        )
 
 
         xmlTree = etree.parse(filename)
         xmlTree = etree.parse(filename)
         if expandAddons:
         if expandAddons:
@@ -80,32 +81,40 @@ class MenuTreeModelBuilder:
 
 
     def _createModel(self, xmlTree):
     def _createModel(self, xmlTree):
         root = xmlTree.getroot()
         root = xmlTree.getroot()
-        menubar = root.findall('menubar')[0]
-        menus = menubar.findall('menu')
+        menubar = root.findall("menubar")[0]
+        menus = menubar.findall("menu")
         for m in menus:
         for m in menus:
             self._createMenu(m, self.model.root)
             self._createMenu(m, self.model.root)
 
 
     def _createMenu(self, menu, node):
     def _createMenu(self, menu, node):
-        label = _(menu.find('label').text)
-        items = menu.find('items')
+        label = _(menu.find("label").text)
+        items = menu.find("items")
         node = self.model.AppendNode(parent=node, label=label)
         node = self.model.AppendNode(parent=node, label=label)
         for item in items:
         for item in items:
             self._createItem(item, node)
             self._createItem(item, node)
 
 
     def _createItem(self, item, node):
     def _createItem(self, item, node):
-        if item.tag == 'separator':
-            data = dict(label='', description='', handler='',
-                        command='', keywords='', shortcut='', wxId='', icon='')
-            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 item.tag == "separator":
+            data = dict(
+                label="",
+                description="",
+                handler="",
+                command="",
+                keywords="",
+                shortcut="",
+                wxId="",
+                icon="",
+            )
+            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 is not None:
             if gcmd is not None:
                 gcmd = gcmd.text
                 gcmd = gcmd.text
             else:
             else:
@@ -123,19 +132,19 @@ class MenuTreeModelBuilder:
             else:
             else:
                 shortcut = ""
                 shortcut = ""
             if wxId is not None:
             if wxId is not None:
-                wxId = eval('wx.' + wxId.text)
+                wxId = eval("wx." + wxId.text)
             else:
             else:
                 wxId = wx.ID_ANY
                 wxId = wx.ID_ANY
             if icon is not None:
             if icon is not None:
                 icon = icon.text
                 icon = icon.text
             else:
             else:
-                icon = ''
+                icon = ""
             label = origLabel
             label = origLabel
             if gcmd:
             if gcmd:
                 if self.menustyle == 1:
                 if self.menustyle == 1:
-                    label += '   [' + gcmd + ']'
+                    label += "   [" + gcmd + "]"
                 elif self.menustyle == 2:
                 elif self.menustyle == 2:
-                    label = '      [' + gcmd + ']'
+                    label = "      [" + gcmd + "]"
             data = dict(
             data = dict(
                 label=origLabel,
                 label=origLabel,
                 description=desc,
                 description=desc,
@@ -144,9 +153,10 @@ class MenuTreeModelBuilder:
                 keywords=keywords,
                 keywords=keywords,
                 shortcut=shortcut,
                 shortcut=shortcut,
                 wxId=wxId,
                 wxId=wxId,
-                icon=icon)
+                icon=icon,
+            )
             self.model.AppendNode(parent=node, label=label, data=data)
             self.model.AppendNode(parent=node, label=label, data=data)
-        elif item.tag == 'menu':
+        elif item.tag == "menu":
             self._createMenu(item, node)
             self._createMenu(item, node)
         else:
         else:
             raise ValueError(_("Unknow tag %s") % item.tag)
             raise ValueError(_("Unknow tag %s") % item.tag)
@@ -172,13 +182,13 @@ class MenuTreeModelBuilder:
         :param fh: file descriptor
         :param fh: file descriptor
         """
         """
         className = self.__class__.__name__
         className = self.__class__.__name__
-        fh.write('menustrings_%s = [\n' % className)
+        fh.write("menustrings_%s = [\n" % className)
         for child in self.model.root.children:
         for child in self.model.root.children:
             printStrings(child, fh)
             printStrings(child, fh)
-        fh.write('    \'\']\n')
+        fh.write("    '']\n")
 
 
     def PrintCommands(self, fh):
     def PrintCommands(self, fh):
-        printCommands(self.model.root, fh, itemSep=' | ', menuSep=' > ')
+        printCommands(self.model.root, fh, itemSep=" | ", menuSep=" > ")
 
 
 
 
 def removeSeparators(model, node=None):
 def removeSeparators(model, node=None):
@@ -194,7 +204,7 @@ def removeSeparators(model, node=None):
 def printTree(node, fh, indent=0):
 def printTree(node, fh, indent=0):
     if not node.label:
     if not node.label:
         return
         return
-    text = '%s- %s\n' % (' ' * indent, node.label.replace('&', ''))
+    text = "%s- %s\n" % (" " * indent, node.label.replace("&", ""))
     fh.write(text)
     fh.write(text)
     for child in node.children:
     for child in node.children:
         printTree(node=child, fh=fh, indent=indent + 2)
         printTree(node=child, fh=fh, indent=indent + 2)
@@ -204,18 +214,17 @@ def printStrings(node, fh):
     # node.label  - with module in brackets
     # node.label  - with module in brackets
     # node.data['label'] - without module in brackets
     # node.data['label'] - without module in brackets
     if node.label and not node.data:
     if node.label and not node.data:
-        fh.write('    _(%r),\n' % str(node.label))
+        fh.write("    _(%r),\n" % str(node.label))
     if node.data:
     if node.data:
-        if 'label' in node.data and node.data['label']:
-            fh.write('    _(%r),\n' % str(node.data['label']))
-        if 'description' in node.data and node.data['description']:
-            fh.write('    _(%r),\n' % str(node.data['description']))
+        if "label" in node.data and node.data["label"]:
+            fh.write("    _(%r),\n" % str(node.data["label"]))
+        if "description" in node.data and node.data["description"]:
+            fh.write("    _(%r),\n" % str(node.data["description"]))
     for child in node.children:
     for child in node.children:
         printStrings(node=child, fh=fh)
         printStrings(node=child, fh=fh)
 
 
 
 
 def printCommands(node, fh, itemSep, menuSep):
 def printCommands(node, fh, itemSep, menuSep):
-
     def collectParents(node, parents):
     def collectParents(node, parents):
         parent = node.parent
         parent = node.parent
         if parent.parent:
         if parent.parent:
@@ -223,13 +232,13 @@ def printCommands(node, fh, itemSep, menuSep):
             collectParents(node.parent, parents)
             collectParents(node.parent, parents)
 
 
     data = node.data
     data = node.data
-    if data and 'command' in data and data['command']:
-        fh.write('%s%s' % (data['command'], itemSep))
+    if data and "command" in data and data["command"]:
+        fh.write("%s%s" % (data["command"], itemSep))
         parents = [node]
         parents = [node]
         collectParents(node, parents)
         collectParents(node, parents)
-        labels = [parent.label.replace('&', '') for parent in parents]
+        labels = [parent.label.replace("&", "") for parent in parents]
         fh.write(menuSep.join(labels))
         fh.write(menuSep.join(labels))
-        fh.write('\n')
+        fh.write("\n")
 
 
     for child in node.children:
     for child in node.children:
         printCommands(child, fh, itemSep, menuSep)
         printCommands(child, fh, itemSep, menuSep)
@@ -237,48 +246,54 @@ def printCommands(node, fh, itemSep, menuSep):
 
 
 if __name__ == "__main__":
 if __name__ == "__main__":
 
 
-    action = 'strings'
-    menu = 'manager'
+    action = "strings"
+    menu = "manager"
 
 
     for arg in sys.argv:
     for arg in sys.argv:
-        if arg in ('strings', 'tree', 'commands', 'dump'):
+        if arg in ("strings", "tree", "commands", "dump"):
             action = arg
             action = arg
-        elif arg in ('manager', 'module_tree', 'modeler', 'psmap'):
+        elif arg in ("manager", "module_tree", "modeler", "psmap"):
             menu = arg
             menu = arg
 
 
     # FIXME: cross-dependencies
     # FIXME: cross-dependencies
-    if menu == 'manager':
+    if menu == "manager":
         from lmgr.menudata import LayerManagerMenuData
         from lmgr.menudata import LayerManagerMenuData
         from core.globalvar import WXGUIDIR
         from core.globalvar import WXGUIDIR
-        filename = os.path.join(WXGUIDIR, 'xml', 'menudata.xml')
+
+        filename = os.path.join(WXGUIDIR, "xml", "menudata.xml")
         menudata = LayerManagerMenuData(filename)
         menudata = LayerManagerMenuData(filename)
     # FIXME: since module descriptions are used again we have now the third
     # FIXME: since module descriptions are used again we have now the third
     # copy of the same string (one is in modules)
     # copy of the same string (one is in modules)
-    elif menu == 'module_tree':
+    elif menu == "module_tree":
         from lmgr.menudata import LayerManagerModuleTree
         from lmgr.menudata import LayerManagerModuleTree
         from core.globalvar import WXGUIDIR
         from core.globalvar import WXGUIDIR
-        filename = os.path.join(WXGUIDIR, 'xml', 'module_tree_menudata.xml')
+
+        filename = os.path.join(WXGUIDIR, "xml", "module_tree_menudata.xml")
         menudata = LayerManagerModuleTree(filename)
         menudata = LayerManagerModuleTree(filename)
-    elif menu == 'modeler':
+    elif menu == "modeler":
         from gmodeler.menudata import ModelerMenuData
         from gmodeler.menudata import ModelerMenuData
+
         menudata = ModelerMenuData()
         menudata = ModelerMenuData()
-    elif menu == 'psmap':
+    elif menu == "psmap":
         from psmap.menudata import PsMapMenuData
         from psmap.menudata import PsMapMenuData
+
         menudata = PsMapMenuData()
         menudata = PsMapMenuData()
     else:
     else:
         import grass.script.core as gscore
         import grass.script.core as gscore
+
         gscore.fatal("Unknown value for parameter menu: " % menu)
         gscore.fatal("Unknown value for parameter menu: " % menu)
 
 
-    if action == 'strings':
+    if action == "strings":
         menudata.PrintStrings(sys.stdout)
         menudata.PrintStrings(sys.stdout)
-    elif action == 'tree':
+    elif action == "tree":
         menudata.PrintTree(sys.stdout)
         menudata.PrintTree(sys.stdout)
-    elif action == 'commands':
+    elif action == "commands":
         menudata.PrintCommands(sys.stdout)
         menudata.PrintCommands(sys.stdout)
-    elif action == 'dump':
+    elif action == "dump":
         print(menudata.model)
         print(menudata.model)
     else:
     else:
         import grass.script.core as gscore
         import grass.script.core as gscore
+
         gscore.fatal("Unknown value for parameter action: " % action)
         gscore.fatal("Unknown value for parameter action: " % action)
 
 
     sys.exit(0)
     sys.exit(0)

Plik diff jest za duży
+ 430 - 336
gui/wxpython/core/render.py


Plik diff jest za duży
+ 704 - 828
gui/wxpython/core/settings.py


+ 178 - 149
gui/wxpython/core/toolboxes.py

@@ -22,10 +22,10 @@ from xml.parsers import expat
 
 
 # Get the XML parsing exceptions to catch. The behavior chnaged with Python 2.7
 # Get the XML parsing exceptions to catch. The behavior chnaged with Python 2.7
 # and ElementTree 1.3.
 # and ElementTree 1.3.
-if hasattr(etree, 'ParseError'):
+if hasattr(etree, "ParseError"):
     ETREE_EXCEPTIONS = (etree.ParseError, expat.ExpatError)
     ETREE_EXCEPTIONS = (etree.ParseError, expat.ExpatError)
 else:
 else:
-    ETREE_EXCEPTIONS = (expat.ExpatError)
+    ETREE_EXCEPTIONS = expat.ExpatError
 
 
 if sys.version_info[0:2] > (2, 6):
 if sys.version_info[0:2] > (2, 6):
     has_xpath = True
     has_xpath = True
@@ -46,10 +46,10 @@ WXGUIDIR = os.path.join(os.getenv("GISBASE"), "gui", "wxpython")
 
 
 
 
 # this could be placed to functions
 # 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')
-moduleItemsFile = os.path.join(WXGUIDIR, 'xml', 'module_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")
 
 
 
 
 def GetSettingsPath():
 def GetSettingsPath():
@@ -58,6 +58,7 @@ def GetSettingsPath():
     # no need to do this
     # no need to do this
     try:
     try:
         from core.utils import GetSettingsPath as actualGetSettingsPath
         from core.utils import GetSettingsPath as actualGetSettingsPath
+
         return actualGetSettingsPath()
         return actualGetSettingsPath()
     except ImportError:
     except ImportError:
         # expecting that there will be no such path
         # expecting that there will be no such path
@@ -66,18 +67,14 @@ def GetSettingsPath():
 
 
 
 
 def _getUserToolboxesFile():
 def _getUserToolboxesFile():
-    userToolboxesFile = os.path.join(
-        GetSettingsPath(),
-        'toolboxes', 'toolboxes.xml')
+    userToolboxesFile = os.path.join(GetSettingsPath(), "toolboxes", "toolboxes.xml")
     if not os.path.exists(userToolboxesFile):
     if not os.path.exists(userToolboxesFile):
         userToolboxesFile = None
         userToolboxesFile = None
     return userToolboxesFile
     return userToolboxesFile
 
 
 
 
 def _getUserMainMenuFile():
 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):
     if not os.path.exists(userMainMenuFile):
         userMainMenuFile = None
         userMainMenuFile = None
     return userMainMenuFile
     return userMainMenuFile
@@ -109,7 +106,7 @@ def _debug(level, message):
 def toolboxesOutdated():
 def toolboxesOutdated():
     """Removes auto-generated menudata.xml
     """Removes auto-generated menudata.xml
     to let gui regenerate it next time it starts."""
     to let gui regenerate it next time it starts."""
-    path = os.path.join(GetSettingsPath(), 'toolboxes', 'menudata.xml')
+    path = os.path.join(GetSettingsPath(), "toolboxes", "menudata.xml")
     if os.path.exists(path):
     if os.path.exists(path):
         try_remove(path)
         try_remove(path)
 
 
@@ -126,10 +123,12 @@ def getMenudataFile(userRootFile, newFile, fallback):
     _debug(
     _debug(
         1,
         1,
         "toolboxes.getMenudataFile: {userRootFile}, {newFile}, {fallback}".format(
         "toolboxes.getMenudataFile: {userRootFile}, {newFile}, {fallback}".format(
-            **locals()))
+            **locals()
+        ),
+    )
 
 
-    distributionRootFile = os.path.join(WXGUIDIR, 'xml', userRootFile)
-    userRootFile = os.path.join(GetSettingsPath(), 'toolboxes', userRootFile)
+    distributionRootFile = os.path.join(WXGUIDIR, "xml", userRootFile)
+    userRootFile = os.path.join(GetSettingsPath(), "toolboxes", userRootFile)
     if not os.path.exists(userRootFile):
     if not os.path.exists(userRootFile):
         userRootFile = None
         userRootFile = None
 
 
@@ -147,7 +146,9 @@ def getMenudataFile(userRootFile, newFile, fallback):
             if not _getUserToolboxesFile() and not userRootFile:
             if not _getUserToolboxesFile() and not userRootFile:
                 os.remove(menudataFile)
                 os.remove(menudataFile)
                 _debug(
                 _debug(
-                    2, "toolboxes.getMenudataFile: no user defined files, menudata deleted")
+                    2,
+                    "toolboxes.getMenudataFile: no user defined files, menudata deleted",
+                )
                 return fallback
                 return fallback
 
 
             if bool(_getUserToolboxesFile()) != bool(userRootFile):
             if bool(_getUserToolboxesFile()) != bool(userRootFile):
@@ -155,20 +156,24 @@ def getMenudataFile(userRootFile, newFile, fallback):
                 # any change
                 # any change
                 generateNew = True
                 generateNew = True
                 _debug(
                 _debug(
-                    2, "toolboxes.getMenudataFile: only one of the user defined files")
+                    2, "toolboxes.getMenudataFile: only one of the user defined files"
+                )
             else:
             else:
                 # if newer files -> generate new
                 # if newer files -> generate new
                 menudataTime = os.path.getmtime(menudataFile)
                 menudataTime = os.path.getmtime(menudataFile)
                 if _getUserToolboxesFile():
                 if _getUserToolboxesFile():
-                    if os.path.getmtime(
-                            _getUserToolboxesFile()) > menudataTime:
+                    if os.path.getmtime(_getUserToolboxesFile()) > menudataTime:
                         _debug(
                         _debug(
-                            2, "toolboxes.getMenudataFile: user toolboxes is newer than menudata")
+                            2,
+                            "toolboxes.getMenudataFile: user toolboxes is newer than menudata",
+                        )
                         generateNew = True
                         generateNew = True
                 if userRootFile:
                 if userRootFile:
                     if os.path.getmtime(userRootFile) > menudataTime:
                     if os.path.getmtime(userRootFile) > menudataTime:
                         _debug(
                         _debug(
-                            2, "toolboxes.getMenudataFile: user root file is newer than menudata")
+                            2,
+                            "toolboxes.getMenudataFile: user root file is newer than menudata",
+                        )
                         generateNew = True
                         generateNew = True
         elif _getUserToolboxesFile() or userRootFile:
         elif _getUserToolboxesFile() or userRootFile:
             _debug(2, "toolboxes.getMenudataFile: no menudata")
             _debug(2, "toolboxes.getMenudataFile: no menudata")
@@ -185,23 +190,28 @@ def getMenudataFile(userRootFile, newFile, fallback):
                 # toolboxes but undefined module tree file.
                 # toolboxes but undefined module tree file.
                 _debug(2, "toolboxes.getMenudataFile: creating a tree")
                 _debug(2, "toolboxes.getMenudataFile: creating a tree")
                 tree = createTree(
                 tree = createTree(
-                    distributionRootFile=distributionRootFile,
-                    userRootFile=userRootFile)
+                    distributionRootFile=distributionRootFile, userRootFile=userRootFile
+                )
             except ETREE_EXCEPTIONS:
             except ETREE_EXCEPTIONS:
-                _warning(_("Unable to parse user toolboxes XML files. "
-                           "Default files will be loaded."))
+                _warning(
+                    _(
+                        "Unable to parse user toolboxes XML files. "
+                        "Default files will be loaded."
+                    )
+                )
                 return fallback
                 return fallback
 
 
             try:
             try:
                 xml = _getXMLString(tree.getroot())
                 xml = _getXMLString(tree.getroot())
-                fh = open(menudataFile, 'w')
+                fh = open(menudataFile, "w")
                 fh.write(xml)
                 fh.write(xml)
                 fh.close()
                 fh.close()
                 return menudataFile
                 return menudataFile
             except:
             except:
                 _debug(
                 _debug(
                     2,
                     2,
-                    "toolboxes.getMenudataFile: writing menudata failed, returning fallback file")
+                    "toolboxes.getMenudataFile: writing menudata failed, returning fallback file",
+                )
                 return fallback
                 return fallback
         else:
         else:
             return menudataFile
             return menudataFile
@@ -213,7 +223,7 @@ def getMenudataFile(userRootFile, newFile, fallback):
 def _setupToolboxes():
 def _setupToolboxes():
     """Create 'toolboxes' directory if doesn't exist."""
     """Create 'toolboxes' directory if doesn't exist."""
     basePath = GetSettingsPath()
     basePath = GetSettingsPath()
-    path = os.path.join(basePath, 'toolboxes')
+    path = os.path.join(basePath, "toolboxes")
     if not os.path.exists(basePath):
     if not os.path.exists(basePath):
         return None
         return None
 
 
@@ -231,9 +241,14 @@ def _createPath(path):
             # we cannot use GError or similar because the gui doesn't start at
             # we cannot use GError or similar because the gui doesn't start at
             # all
             # all
             gcore.warning(
             gcore.warning(
-                '%(reason)s\n%(detail)s' % ({
-                    'reason': _('Unable to create toolboxes directory.'),
-                    'detail': str(e)}))
+                "%(reason)s\n%(detail)s"
+                % (
+                    {
+                        "reason": _("Unable to create toolboxes directory."),
+                        "detail": str(e),
+                    }
+                )
+            )
             return False
             return False
     return True
     return True
 
 
@@ -264,15 +279,16 @@ def createTree(distributionRootFile, userRootFile, userDefined=True):
     wxguiItems = etree.parse(wxguiItemsFile)
     wxguiItems = etree.parse(wxguiItemsFile)
     moduleItems = etree.parse(moduleItemsFile)
     moduleItems = etree.parse(moduleItemsFile)
 
 
-    return toolboxes2menudata(mainMenu=mainMenu,
-                              toolboxes=toolboxes,
-                              userToolboxes=userToolboxes,
-                              wxguiItems=wxguiItems,
-                              moduleItems=moduleItems)
+    return toolboxes2menudata(
+        mainMenu=mainMenu,
+        toolboxes=toolboxes,
+        userToolboxes=userToolboxes,
+        wxguiItems=wxguiItems,
+        moduleItems=moduleItems,
+    )
 
 
 
 
-def toolboxes2menudata(mainMenu, toolboxes, userToolboxes,
-                       wxguiItems, moduleItems):
+def toolboxes2menudata(mainMenu, toolboxes, userToolboxes, wxguiItems, moduleItems):
     """Creates XML file with data for menu.
     """Creates XML file with data for menu.
 
 
     Parses toolboxes files from distribution and from users,
     Parses toolboxes files from distribution and from users,
@@ -288,7 +304,7 @@ def toolboxes2menudata(mainMenu, toolboxes, userToolboxes,
     userHasToolboxes = False
     userHasToolboxes = False
 
 
     # in case user has empty toolboxes file (to avoid genereation)
     # in case user has empty toolboxes file (to avoid genereation)
-    if userToolboxes and userToolboxes.findall('.//toolbox'):
+    if userToolboxes and userToolboxes.findall(".//toolbox"):
         _expandUserToolboxesItem(root, userToolboxes)
         _expandUserToolboxesItem(root, userToolboxes)
         _expandToolboxes(root, userToolboxes)
         _expandToolboxes(root, userToolboxes)
         userHasToolboxes = True
         userHasToolboxes = True
@@ -300,8 +316,8 @@ def toolboxes2menudata(mainMenu, toolboxes, userToolboxes,
 
 
     # we do not expand addons here since they need to be expanded in runtime
     # we do not expand addons here since they need to be expanded in runtime
 
 
-    _expandItems(root, moduleItems, 'module-item')
-    _expandItems(root, wxguiItems, 'wxgui-item')
+    _expandItems(root, moduleItems, "module-item")
+    _expandItems(root, wxguiItems, "wxgui-item")
 
 
     # in case of compilation there are no additional runtime modules
     # in case of compilation there are no additional runtime modules
     # but we need to create empty elements
     # but we need to create empty elements
@@ -332,8 +348,7 @@ def _indent(elem, level=0):
 
 
 
 
 def expandAddons(tree):
 def expandAddons(tree):
-    """Expands addons element.
-    """
+    """Expands addons element."""
     root = tree.getroot()
     root = tree.getroot()
     _expandAddonsItem(root)
     _expandAddonsItem(root)
     # expanding and converting is done twice, so there is some overhead
     # expanding and converting is done twice, so there is some overhead
@@ -405,26 +420,26 @@ def _expandToolboxes(node, toolboxes):
     </items>
     </items>
     </toolbox>
     </toolbox>
     """
     """
-    nodes = node.findall('.//toolbox')
-    if node.tag == 'toolbox':  # root
+    nodes = node.findall(".//toolbox")
+    if node.tag == "toolbox":  # root
         nodes.append(node)
         nodes.append(node)
     for n in nodes:
     for n in nodes:
-        if n.find('items') is None:
+        if n.find("items") is None:
             continue
             continue
-        for subtoolbox in n.findall('./items/subtoolbox'):
-            items = n.find('./items')
+        for subtoolbox in n.findall("./items/subtoolbox"):
+            items = n.find("./items")
             idx = list(items).index(subtoolbox)
             idx = list(items).index(subtoolbox)
 
 
             if has_xpath:
             if has_xpath:
                 toolbox = toolboxes.find(
                 toolbox = toolboxes.find(
-                    './/toolbox[@name="%s"]' %
-                    subtoolbox.get('name'))
+                    './/toolbox[@name="%s"]' % subtoolbox.get("name")
+                )
             else:
             else:
                 toolbox = None
                 toolbox = None
-                potentialToolboxes = toolboxes.findall('.//toolbox')
-                sName = subtoolbox.get('name')
+                potentialToolboxes = toolboxes.findall(".//toolbox")
+                sName = subtoolbox.get("name")
                 for pToolbox in potentialToolboxes:
                 for pToolbox in potentialToolboxes:
-                    if pToolbox.get('name') == sName:
+                    if pToolbox.get("name") == sName:
                         toolbox = pToolbox
                         toolbox = pToolbox
                         break
                         break
 
 
@@ -446,18 +461,16 @@ def _expandUserToolboxesItem(node, toolboxes):
     >>> etree.tostring(tree)
     >>> etree.tostring(tree)
     b'<toolbox><items><toolbox name="GeneratedUserToolboxesList"><label>Custom toolboxes</label><items><toolbox name="UserToolbox"><items><module-item name="g.region" /></items></toolbox></items></toolbox></items></toolbox>'
     b'<toolbox><items><toolbox name="GeneratedUserToolboxesList"><label>Custom toolboxes</label><items><toolbox name="UserToolbox"><items><module-item name="g.region" /></items></toolbox></items></toolbox></items></toolbox>'
     """
     """
-    tboxes = toolboxes.findall('.//toolbox')
+    tboxes = toolboxes.findall(".//toolbox")
 
 
-    for n in node.findall('./items/user-toolboxes-list'):
-        items = node.find('./items')
+    for n in node.findall("./items/user-toolboxes-list"):
+        items = node.find("./items")
         idx = list(items).index(n)
         idx = list(items).index(n)
-        el = etree.Element(
-            'toolbox', attrib={
-                'name': 'GeneratedUserToolboxesList'})
+        el = etree.Element("toolbox", attrib={"name": "GeneratedUserToolboxesList"})
         items.insert(idx, el)
         items.insert(idx, el)
-        label = etree.SubElement(el, 'label')
+        label = etree.SubElement(el, "label")
         label.text = _("Custom toolboxes")
         label.text = _("Custom toolboxes")
-        it = etree.SubElement(el, 'items')
+        it = etree.SubElement(el, "items")
         for toolbox in tboxes:
         for toolbox in tboxes:
             it.append(copy.deepcopy(toolbox))
             it.append(copy.deepcopy(toolbox))
         items.remove(n)
         items.remove(n)
@@ -471,25 +484,30 @@ def _removeUserToolboxesItem(root):
     >>> etree.tostring(tree)
     >>> etree.tostring(tree)
     b'<toolbox><items /></toolbox>'
     b'<toolbox><items /></toolbox>'
     """
     """
-    for n in root.findall('./items/user-toolboxes-list'):
-        items = root.find('./items')
+    for n in root.findall("./items/user-toolboxes-list"):
+        items = root.find("./items")
         items.remove(n)
         items.remove(n)
 
 
 
 
 def _getAddons():
 def _getAddons():
     try:
     try:
-        output = gcore.read_command('g.extension', quiet=True, flags='ag')
+        output = gcore.read_command("g.extension", quiet=True, flags="ag")
     except CalledModuleError as error:
     except CalledModuleError as error:
-        _warning(_("List of addons cannot be obtained"
-                   " because g.extension failed."
-                   " Details: %s") % error)
+        _warning(
+            _(
+                "List of addons cannot be obtained"
+                " because g.extension failed."
+                " Details: %s"
+            )
+            % error
+        )
         return []
         return []
 
 
     flist = []
     flist = []
     for line in output.splitlines():
     for line in output.splitlines():
-        if not line.startswith('name'):
+        if not line.startswith("name"):
             continue
             continue
-        for fexe in line.split('=', 1)[1].split(','):
+        for fexe in line.split("=", 1)[1].split(","):
             flist.append(fexe)
             flist.append(fexe)
 
 
     return sorted(flist)
     return sorted(flist)
@@ -498,11 +516,11 @@ def _getAddons():
 def _removeAddonsItem(node, addonsNodes):
 def _removeAddonsItem(node, addonsNodes):
     # TODO: change impl to be similar with the remove toolboxes
     # TODO: change impl to be similar with the remove toolboxes
     for n in addonsNodes:
     for n in addonsNodes:
-        items = node.find('./items')
+        items = node.find("./items")
         if items is not None:
         if items is not None:
             items.remove(n)
             items.remove(n)
         # because of inconsistent menudata file
         # because of inconsistent menudata file
-        items = node.find('./menubar')
+        items = node.find("./menubar")
         if items is not None:
         if items is not None:
             items.remove(n)
             items.remove(n)
 
 
@@ -515,7 +533,7 @@ def _expandAddonsItem(node):
         menudata.xml file when new addons are added/removed.
         menudata.xml file when new addons are added/removed.
     """
     """
     # no addonsTag -> do nothing
     # no addonsTag -> do nothing
-    addonsTags = node.findall('.//addons')
+    addonsTags = node.findall(".//addons")
     if not addonsTags:
     if not addonsTags:
         return
         return
     # fetch addons
     # fetch addons
@@ -530,19 +548,19 @@ def _expandAddonsItem(node):
     # keywords and desc are handled later automatically
     # keywords and desc are handled later automatically
     for n in addonsTags:
     for n in addonsTags:
         # find parent is not possible with implementation of etree (in 2.7)
         # find parent is not possible with implementation of etree (in 2.7)
-        items = node.find('./menubar')
+        items = node.find("./menubar")
         idx = list(items).index(n)
         idx = list(items).index(n)
         # do not set name since it is already in menudata file
         # do not set name since it is already in menudata file
         # attib={'name': 'AddonsList'}
         # attib={'name': 'AddonsList'}
-        el = etree.Element('menu')
+        el = etree.Element("menu")
         items.insert(idx, el)
         items.insert(idx, el)
-        label = etree.SubElement(el, 'label')
+        label = etree.SubElement(el, "label")
         label.text = _("Addons")
         label.text = _("Addons")
-        it = etree.SubElement(el, 'items')
+        it = etree.SubElement(el, "items")
         for addon in addons:
         for addon in addons:
-            addonItem = etree.SubElement(it, 'module-item')
-            addonItem.attrib = {'name': addon}
-            addonLabel = etree.SubElement(addonItem, 'label')
+            addonItem = etree.SubElement(it, "module-item")
+            addonItem.attrib = {"name": addon}
+            addonLabel = etree.SubElement(addonItem, "label")
             addonLabel.text = addon
             addonLabel.text = addon
         items.remove(n)
         items.remove(n)
 
 
@@ -556,15 +574,15 @@ def _expandItems(node, items, itemTag):
     >>> etree.tostring(tree)
     >>> etree.tostring(tree)
     b'<items><module-item name="g.region"><module>g.region</module><description>GRASS region management</description></module-item></items>'
     b'<items><module-item name="g.region"><module>g.region</module><description>GRASS region management</description></module-item></items>'
     """
     """
-    for moduleItem in node.findall('.//' + itemTag):
-        itemName = moduleItem.get('name')
+    for moduleItem in node.findall(".//" + itemTag):
+        itemName = moduleItem.get("name")
         if has_xpath:
         if has_xpath:
             moduleNode = items.find('.//%s[@name="%s"]' % (itemTag, itemName))
             moduleNode = items.find('.//%s[@name="%s"]' % (itemTag, itemName))
         else:
         else:
             moduleNode = None
             moduleNode = None
-            potentialModuleNodes = items.findall('.//%s' % itemTag)
+            potentialModuleNodes = items.findall(".//%s" % itemTag)
             for mNode in potentialModuleNodes:
             for mNode in potentialModuleNodes:
-                if mNode.get('name') == itemName:
+                if mNode.get("name") == itemName:
                     moduleNode = mNode
                     moduleNode = mNode
                     break
                     break
 
 
@@ -596,22 +614,22 @@ def _expandRuntimeModules(node, loadMetadata=True):
     b'<items><module-item name="m.proj"><module>m.proj</module><description>Converts coordinates from one projection to another (cs2cs frontend).</description><keywords>miscellaneous,projection,transformation</keywords></module-item></items>'
     b'<items><module-item name="m.proj"><module>m.proj</module><description>Converts coordinates from one projection to another (cs2cs frontend).</description><keywords>miscellaneous,projection,transformation</keywords></module-item></items>'
     """
     """
     hasErrors = False
     hasErrors = False
-    modules = node.findall('.//module-item')
+    modules = node.findall(".//module-item")
     for module in modules:
     for module in modules:
-        name = module.get('name')
-        if module.find('module') is None:
-            n = etree.SubElement(module, 'module')
+        name = module.get("name")
+        if module.find("module") is None:
+            n = etree.SubElement(module, "module")
             n.text = name
             n.text = name
 
 
-        if module.find('description') is None:
+        if module.find("description") is None:
             if loadMetadata:
             if loadMetadata:
                 desc, keywords = _loadMetadata(name)
                 desc, keywords = _loadMetadata(name)
             else:
             else:
-                desc, keywords = '', ''
-            n = etree.SubElement(module, 'description')
+                desc, keywords = "", ""
+            n = etree.SubElement(module, "description")
             n.text = _escapeXML(desc)
             n.text = _escapeXML(desc)
-            n = etree.SubElement(module, 'keywords')
-            n.text = _escapeXML(','.join(keywords))
+            n = etree.SubElement(module, "keywords")
+            n.text = _escapeXML(",".join(keywords))
             if loadMetadata and not desc:
             if loadMetadata and not desc:
                 hasErrors = True
                 hasErrors = True
 
 
@@ -620,7 +638,8 @@ def _expandRuntimeModules(node, loadMetadata=True):
         # translating causes importing globalvar, where sys.exit is called
         # translating causes importing globalvar, where sys.exit is called
         sys.stderr.write(
         sys.stderr.write(
             "WARNING: Some addons failed when loading. "
             "WARNING: Some addons failed when loading. "
-            "Please consider to update your addons by running 'g.extension.all -f'.\n")
+            "Please consider to update your addons by running 'g.extension.all -f'.\n"
+        )
 
 
 
 
 def _escapeXML(text):
 def _escapeXML(text):
@@ -632,7 +651,7 @@ def _escapeXML(text):
     >>> _escapeXML('<>&')
     >>> _escapeXML('<>&')
     '&amp;lt;&gt;&amp;'
     '&amp;lt;&gt;&amp;'
     """
     """
-    return text.replace('<', '&lt;').replace("&", '&amp;').replace(">", '&gt;')
+    return text.replace("<", "&lt;").replace("&", "&amp;").replace(">", "&gt;")
 
 
 
 
 def _loadMetadata(module):
 def _loadMetadata(module):
@@ -645,24 +664,23 @@ def _loadMetadata(module):
         task = gtask.parse_interface(module)
         task = gtask.parse_interface(module)
     except ScriptError as e:
     except ScriptError as e:
         sys.stderr.write("%s: %s\n" % (module, e))
         sys.stderr.write("%s: %s\n" % (module, e))
-        return '', ''
+        return "", ""
 
 
-    return task.get_description(full=True), \
-        task.get_keywords()
+    return task.get_description(full=True), task.get_keywords()
 
 
 
 
 def _addHandlers(node):
 def _addHandlers(node):
     """Add missing handlers to modules"""
     """Add missing handlers to modules"""
-    for n in node.findall('.//module-item'):
-        if n.find('handler') is None:
-            handlerNode = etree.SubElement(n, 'handler')
-            handlerNode.text = 'OnMenuCmd'
+    for n in node.findall(".//module-item"):
+        if n.find("handler") is None:
+            handlerNode = etree.SubElement(n, "handler")
+            handlerNode.text = "OnMenuCmd"
 
 
     # e.g. g.region -p
     # e.g. g.region -p
-    for n in node.findall('.//wxgui-item'):
-        if n.find('command') is not None:
-            handlerNode = etree.SubElement(n, 'handler')
-            handlerNode.text = 'RunMenuCmd'
+    for n in node.findall(".//wxgui-item"):
+        if n.find("command") is not None:
+            handlerNode = etree.SubElement(n, "handler")
+            handlerNode.text = "RunMenuCmd"
 
 
 
 
 def _convertTag(node, old, new):
 def _convertTag(node, old, new):
@@ -674,7 +692,7 @@ def _convertTag(node, old, new):
     >>> etree.tostring(tree)
     >>> etree.tostring(tree)
     b'<toolboxes><menu><items><menuitem /></items></menu></toolboxes>'
     b'<toolboxes><menu><items><menuitem /></items></menu></toolboxes>'
     """
     """
-    for n in node.findall('.//%s' % old):
+    for n in node.findall(".//%s" % old):
         n.tag = new
         n.tag = new
 
 
 
 
@@ -687,7 +705,7 @@ def _convertTagAndRemoveAttrib(node, old, new):
     >>> etree.tostring(tree)
     >>> etree.tostring(tree)
     b'<toolboxes><menu><items><menuitem /></items></menu></toolboxes>'
     b'<toolboxes><menu><items><menuitem /></items></menu></toolboxes>'
     """
     """
-    for n in node.findall('.//%s' % old):
+    for n in node.findall(".//%s" % old):
         n.tag = new
         n.tag = new
         n.attrib = {}
         n.attrib = {}
 
 
@@ -701,23 +719,23 @@ def _convertTree(root):
     b'<menudata><menubar><menu><label>Raster</label><items><menuitem><command>g.region</command></menuitem></items></menu></menubar></menudata>'
     b'<menudata><menubar><menu><label>Raster</label><items><menuitem><command>g.region</command></menuitem></items></menu></menubar></menudata>'
     """
     """
     root.attrib = {}
     root.attrib = {}
-    label = root.find('label')
+    label = root.find("label")
     # must check because of inconsistent XML menudata file
     # must check because of inconsistent XML menudata file
     if label is not None:
     if label is not None:
         root.remove(label)
         root.remove(label)
-    _convertTag(root, 'description', 'help')
-    _convertTag(root, 'wx-id', 'id')
-    _convertTag(root, 'module', 'command')
-    _convertTag(root, 'related-module', 'command')
-    _convertTagAndRemoveAttrib(root, 'wxgui-item', 'menuitem')
-    _convertTagAndRemoveAttrib(root, 'module-item', 'menuitem')
-
-    root.tag = 'menudata'
-    i1 = root.find('./items')
+    _convertTag(root, "description", "help")
+    _convertTag(root, "wx-id", "id")
+    _convertTag(root, "module", "command")
+    _convertTag(root, "related-module", "command")
+    _convertTagAndRemoveAttrib(root, "wxgui-item", "menuitem")
+    _convertTagAndRemoveAttrib(root, "module-item", "menuitem")
+
+    root.tag = "menudata"
+    i1 = root.find("./items")
     # must check because of inconsistent XML menudata file
     # must check because of inconsistent XML menudata file
     if i1 is not None:
     if i1 is not None:
-        i1.tag = 'menubar'
-    _convertTagAndRemoveAttrib(root, 'toolbox', 'menu')
+        i1.tag = "menubar"
+    _convertTagAndRemoveAttrib(root, "toolbox", "menu")
 
 
 
 
 def _getXMLString(root):
 def _getXMLString(root):
@@ -728,10 +746,12 @@ def _getXMLString(root):
 
 
     :return: XML as string
     :return: XML as string
     """
     """
-    xml = etree.tostring(root, encoding='UTF-8')
-    return xml.replace(b"<?xml version='1.0' encoding='UTF-8'?>\n",
-                       b"<?xml version='1.0' encoding='UTF-8'?>\n"
-                       b"<!--This is an auto-generated file-->\n")
+    xml = etree.tostring(root, encoding="UTF-8")
+    return xml.replace(
+        b"<?xml version='1.0' encoding='UTF-8'?>\n",
+        b"<?xml version='1.0' encoding='UTF-8'?>\n"
+        b"<!--This is an auto-generated file-->\n",
+    )
 
 
 
 
 def do_doctest_gettext_workaround():
 def do_doctest_gettext_workaround():
@@ -756,6 +776,7 @@ def do_doctest_gettext_workaround():
     workaround function is still needed when you import something from
     workaround function is still needed when you import something from
     GRASS Python libraries.
     GRASS Python libraries.
     """
     """
+
     def new_displayhook(string):
     def new_displayhook(string):
         """A replacement for default `sys.displayhook`"""
         """A replacement for default `sys.displayhook`"""
         if string is not None:
         if string is not None:
@@ -769,6 +790,7 @@ def do_doctest_gettext_workaround():
     sys.__displayhook__ = new_displayhook
     sys.__displayhook__ = new_displayhook
 
 
     import __builtin__
     import __builtin__
+
     __builtin__._ = new_translator
     __builtin__._ = new_translator
 
 
 
 
@@ -778,6 +800,7 @@ def doc_test():
     :return: a number of failed tests
     :return: a number of failed tests
     """
     """
     import doctest
     import doctest
+
     do_doctest_gettext_workaround()
     do_doctest_gettext_workaround()
     return doctest.testmod().failed
     return doctest.testmod().failed
 
 
@@ -786,11 +809,11 @@ def module_test():
     """Tests the module using test files included in the current
     """Tests the module using test files included in the current
     directory and in files from distribution.
     directory and in files from distribution.
     """
     """
-    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')
-    moduleItemsFile = os.path.join(WXGUIDIR, 'xml', 'module_items.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")
+    moduleItemsFile = os.path.join(WXGUIDIR, "xml", "module_items.xml")
 
 
     toolboxes = etree.parse(toolboxesFile)
     toolboxes = etree.parse(toolboxesFile)
     userToolboxes = etree.parse(userToolboxesFile)
     userToolboxes = etree.parse(userToolboxesFile)
@@ -799,11 +822,13 @@ def module_test():
     wxguiItems = etree.parse(wxguiItemsFile)
     wxguiItems = etree.parse(wxguiItemsFile)
     moduleItems = etree.parse(moduleItemsFile)
     moduleItems = etree.parse(moduleItemsFile)
 
 
-    tree = toolboxes2menudata(mainMenu=menu,
-                              toolboxes=toolboxes,
-                              userToolboxes=userToolboxes,
-                              wxguiItems=wxguiItems,
-                              moduleItems=moduleItems)
+    tree = toolboxes2menudata(
+        mainMenu=menu,
+        toolboxes=toolboxes,
+        userToolboxes=userToolboxes,
+        wxguiItems=wxguiItems,
+        moduleItems=moduleItems,
+    )
     root = tree.getroot()
     root = tree.getroot()
     tested = _getXMLString(root)
     tested = _getXMLString(root)
 
 
@@ -815,18 +840,18 @@ def module_test():
         sys.stdout.write(_getXMLString(root))
         sys.stdout.write(_getXMLString(root))
         return 0
         return 0
 
 
-    menudataFile = 'data/test_toolboxes_menudata_ref.xml'
+    menudataFile = "data/test_toolboxes_menudata_ref.xml"
     with open(menudataFile) as correctMenudata:
     with open(menudataFile) as correctMenudata:
         correct = str(correctMenudata.read())
         correct = str(correctMenudata.read())
 
 
     import difflib
     import difflib
+
     differ = difflib.Differ()
     differ = difflib.Differ()
-    result = list(differ.compare(correct.splitlines(True),
-                                 tested.splitlines(True)))
+    result = list(differ.compare(correct.splitlines(True), tested.splitlines(True)))
 
 
     someDiff = False
     someDiff = False
     for line in result:
     for line in result:
-        if line.startswith('+') or line.startswith('-'):
+        if line.startswith("+") or line.startswith("-"):
             sys.stdout.write(line)
             sys.stdout.write(line)
             someDiff = True
             someDiff = True
     if someDiff:
     if someDiff:
@@ -841,8 +866,11 @@ def validate_file(filename):
     try:
     try:
         etree.parse(filename)
         etree.parse(filename)
     except ETREE_EXCEPTIONS as error:
     except ETREE_EXCEPTIONS as error:
-        print("XML file <{name}> is not well formed: {error}".format(
-            name=filename, error=error))
+        print(
+            "XML file <{name}> is not well formed: {error}".format(
+                name=filename, error=error
+            )
+        )
         return 1
         return 1
     return 0
     return 0
 
 
@@ -854,24 +882,25 @@ def main():
     """
     """
     # TODO: fix parameter handling
     # TODO: fix parameter handling
     if len(sys.argv) > 1:
     if len(sys.argv) > 1:
-        mainFile = os.path.join(WXGUIDIR, 'xml', 'module_tree.xml')
+        mainFile = os.path.join(WXGUIDIR, "xml", "module_tree.xml")
     else:
     else:
-        mainFile = os.path.join(WXGUIDIR, 'xml', 'main_menu.xml')
-    tree = createTree(distributionRootFile=mainFile, userRootFile=None,
-                      userDefined=False)
+        mainFile = os.path.join(WXGUIDIR, "xml", "main_menu.xml")
+    tree = createTree(
+        distributionRootFile=mainFile, userRootFile=None, userDefined=False
+    )
     root = tree.getroot()
     root = tree.getroot()
-    sys.stdout.write(decode(_getXMLString(root), encoding='UTF-8'))
+    sys.stdout.write(decode(_getXMLString(root), encoding="UTF-8"))
 
 
     return 0
     return 0
 
 
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     # TODO: fix parameter handling
     # TODO: fix parameter handling
     if len(sys.argv) > 1:
     if len(sys.argv) > 1:
-        if sys.argv[1] == 'doctest':
+        if sys.argv[1] == "doctest":
             sys.exit(doc_test())
             sys.exit(doc_test())
-        elif sys.argv[1] == 'test':
+        elif sys.argv[1] == "test":
             sys.exit(module_test())
             sys.exit(module_test())
-        elif sys.argv[1] == 'validate':
+        elif sys.argv[1] == "validate":
             sys.exit(validate_file(sys.argv[2]))
             sys.exit(validate_file(sys.argv[2]))
     sys.exit(main())
     sys.exit(main())

+ 11 - 8
gui/wxpython/core/treemodel.py

@@ -157,6 +157,7 @@ class TreeModel(object):
         """Filters model based on parameters in kwargs
         """Filters model based on parameters in kwargs
         that are passed to node's match function.
         that are passed to node's match function.
         Copies tree and returns a filtered copy."""
         Copies tree and returns a filtered copy."""
+
         def _filter(node):
         def _filter(node):
             if node.children:
             if node.children:
                 to_remove = []
                 to_remove = []
@@ -216,12 +217,13 @@ class DictNode(object):
         return self._children
         return self._children
 
 
     def nprint(self, text, indent=0):
     def nprint(self, text, indent=0):
-        text.append(indent * ' ' + self.label)
+        text.append(indent * " " + self.label)
         if self.data:
         if self.data:
             for key, value in six.iteritems(self.data):
             for key, value in six.iteritems(self.data):
                 text.append(
                 text.append(
-                    "%(indent)s* %(key)s : %(value)s" %
-                    {'indent': (indent + 2) * ' ', 'key': key, 'value': value})
+                    "%(indent)s* %(key)s : %(value)s"
+                    % {"indent": (indent + 2) * " ", "key": key, "value": value}
+                )
 
 
         if self.children:
         if self.children:
             for child in self.children:
             for child in self.children:
@@ -243,7 +245,7 @@ class ModuleNode(DictNode):
 
 
     def __init__(self, label=None, data=None):
     def __init__(self, label=None, data=None):
         super(ModuleNode, self).__init__(data=data)
         super(ModuleNode, self).__init__(data=data)
-        self._label = label if label else ''
+        self._label = label if label else ""
         if not data:
         if not data:
             self.data = {}
             self.data = {}
 
 
@@ -262,7 +264,7 @@ class ModuleNode(DictNode):
             keys = key
             keys = key
 
 
         for key in keys:
         for key in keys:
-            if key not in ('command', 'keywords', 'description'):
+            if key not in ("command", "keywords", "description"):
                 return False
                 return False
             try:
             try:
                 text = self.data[key]
                 text = self.data[key]
@@ -272,20 +274,21 @@ class ModuleNode(DictNode):
                 continue
                 continue
             if case_sensitive:
             if case_sensitive:
                 # start supported but unused, so testing last
                 # start supported but unused, so testing last
-                if value in text or value == '*':
+                if value in text or value == "*":
                     return True
                     return True
             else:
             else:
                 # this works fully only for English and requires accents
                 # this works fully only for English and requires accents
                 # to be exact match (even Python 3 casefold() does not help)
                 # to be exact match (even Python 3 casefold() does not help)
-                if value.lower() in text.lower() or value == '*':
+                if value.lower() in text.lower() or value == "*":
                     return True
                     return True
         return False
         return False
 
 
 
 
 def main():
 def main():
     import doctest
     import doctest
+
     doctest.testmod()
     doctest.testmod()
 
 
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     main()
     main()

+ 49 - 44
gui/wxpython/core/units.py

@@ -24,26 +24,28 @@ This program is free software under the GNU General Public License
 import six
 import six
 import math
 import math
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     import sys
     import sys
 
 
 
 
-
 class BaseUnits:
 class BaseUnits:
-
     def __init__(self):
     def __init__(self):
         self._units = dict()
         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):
     def GetUnitsList(self, type):
         """Get list of units (their labels)
         """Get list of units (their labels)
@@ -56,7 +58,7 @@ class BaseUnits:
         try:
         try:
             keys = sorted(self._units[type].keys())
             keys = sorted(self._units[type].keys())
             for idx in keys:
             for idx in keys:
-                result.append(self._units[type][idx]['label'])
+                result.append(self._units[type][idx]["label"])
         except KeyError:
         except KeyError:
             pass
             pass
 
 
@@ -68,7 +70,7 @@ class BaseUnits:
         :param type: units type ('length' or 'area')
         :param type: units type ('length' or 'area')
         :param index: units index
         :param index: units index
         """
         """
-        return self._units[type][index]['key']
+        return self._units[type][index]["key"]
 
 
     def GetUnitsIndex(self, type, key):
     def GetUnitsIndex(self, type, key):
         """Get units index based on key
         """Get units index based on key
@@ -79,10 +81,11 @@ class BaseUnits:
         :return: index
         :return: index
         """
         """
         for k, u in six.iteritems(self._units[type]):
         for k, u in six.iteritems(self._units[type]):
-            if u['key'] == key:
+            if u["key"] == key:
                 return k
                 return k
         return 0
         return 0
 
 
+
 Units = BaseUnits()
 Units = BaseUnits()
 
 
 
 
@@ -99,27 +102,27 @@ def ConvertValue(value, type, units):
     # TODO
     # TODO
 
 
     f = 1
     f = 1
-    if type == 'length':
-        if units == 'me':
+    if type == "length":
+        if units == "me":
             f = 1.0
             f = 1.0
-        elif units == 'km':
+        elif units == "km":
             f = 1.0e-3
             f = 1.0e-3
-        elif units == 'mi':
+        elif units == "mi":
             f = 6.21371192237334e-4
             f = 6.21371192237334e-4
-        elif units == 'ft':
+        elif units == "ft":
             f = 3.28083989501312
             f = 3.28083989501312
     else:  # -> area
     else:  # -> area
-        if units == 'me':
+        if units == "me":
             f = 1.0
             f = 1.0
-        elif units == 'km':
+        elif units == "km":
             f = 1.0e-6
             f = 1.0e-6
-        elif units == 'mi':
+        elif units == "mi":
             f = 3.86102158542446e-7
             f = 3.86102158542446e-7
-        elif units == 'ft':
+        elif units == "ft":
             f = 10.7639104167097
             f = 10.7639104167097
-        elif units == 'ar':
+        elif units == "ar":
             f = 2.47105381467165e-4
             f = 2.47105381467165e-4
-        elif units == 'ht':
+        elif units == "ht":
             f = 1.0e-4
             f = 1.0e-4
 
 
     return f * value
     return f * value
@@ -153,38 +156,38 @@ def formatDist(distance, mapunits):
 
 
     From code by Hamish Bowman Grass Development Team 2006.
     From code by Hamish Bowman Grass Development Team 2006.
     """
     """
-    if mapunits == 'metres':
-        mapunits = 'meters'
+    if mapunits == "metres":
+        mapunits = "meters"
     outunits = mapunits
     outunits = mapunits
     distance = float(distance)
     distance = float(distance)
     divisor = 1.0
     divisor = 1.0
 
 
     # figure out which units to use
     # figure out which units to use
-    if mapunits == 'meters':
+    if mapunits == "meters":
         if distance > 2500.0:
         if distance > 2500.0:
-            outunits = 'km'
+            outunits = "km"
             divisor = 1000.0
             divisor = 1000.0
         else:
         else:
-            outunits = 'm'
-    elif mapunits == 'feet':
+            outunits = "m"
+    elif mapunits == "feet":
         # nano-bug: we match any "feet", but US Survey feet is really
         # 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
         #  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
         #  miles the tick markers are rounded to the nearest 10th of a
         #  mile (528'), the difference in foot flavours is ignored.
         #  mile (528'), the difference in foot flavours is ignored.
         if distance > 5280.0:
         if distance > 5280.0:
-            outunits = 'miles'
+            outunits = "miles"
             divisor = 5280.0
             divisor = 5280.0
         else:
         else:
-            outunits = 'ft'
-    elif 'degree' in mapunits:
+            outunits = "ft"
+    elif "degree" in mapunits:
         # was: 'degree' in mapunits and not haveCtypes (for unknown reason)
         # was: 'degree' in mapunits and not haveCtypes (for unknown reason)
         if distance < 1:
         if distance < 1:
-            outunits = 'min'
-            divisor = (1 / 60.0)
+            outunits = "min"
+            divisor = 1 / 60.0
         else:
         else:
-            outunits = 'deg'
+            outunits = "deg"
     else:
     else:
-        return (distance, 'units')
+        return (distance, "units")
 
 
     # format numbers in a nice way
     # format numbers in a nice way
     if (distance / divisor) >= 2500.0:
     if (distance / divisor) >= 2500.0:
@@ -192,8 +195,9 @@ def formatDist(distance, mapunits):
     elif (distance / divisor) >= 1000.0:
     elif (distance / divisor) >= 1000.0:
         outdistance = round(distance / divisor, 1)
         outdistance = round(distance / divisor, 1)
     elif (distance / divisor) > 0.0:
     elif (distance / divisor) > 0.0:
-        outdistance = round(distance / divisor,
-                            int(math.ceil(3 - math.log10(distance / divisor))))
+        outdistance = round(
+            distance / divisor, int(math.ceil(3 - math.log10(distance / divisor)))
+        )
     else:
     else:
         outdistance = float(distance / divisor)
         outdistance = float(distance / divisor)
 
 
@@ -207,9 +211,10 @@ def doc_test():
     """
     """
     import doctest
     import doctest
     from core.utils import do_doctest_gettext_workaround
     from core.utils import do_doctest_gettext_workaround
+
     do_doctest_gettext_workaround()
     do_doctest_gettext_workaround()
     return doctest.testmod().failed
     return doctest.testmod().failed
 
 
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     sys.exit(doc_test())
     sys.exit(doc_test())

Plik diff jest za duży
+ 349 - 351
gui/wxpython/core/utils.py


Plik diff jest za duży
+ 1056 - 983
gui/wxpython/core/workspace.py


+ 103 - 109
gui/wxpython/core/ws.py

@@ -40,13 +40,16 @@ from grass.pydispatch.signal import Signal
 
 
 
 
 class RenderWMSMgr(wx.EvtHandler):
 class RenderWMSMgr(wx.EvtHandler):
-    """Fetch and prepare WMS data for rendering.
-    """
+    """Fetch and prepare WMS data for rendering."""
 
 
     def __init__(self, layer, env):
     def __init__(self, layer, env):
         if not haveGdal:
         if not haveGdal:
-            sys.stderr.write(_("Unable to load GDAL Python bindings.\n"
-                               "WMS layers can not be displayed without the 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
         self.layer = layer
 
 
@@ -64,9 +67,9 @@ class RenderWMSMgr(wx.EvtHandler):
         self.tempMap = grass.tempfile()
         self.tempMap = grass.tempfile()
         self.dstSize = {}
         self.dstSize = {}
 
 
-        self.dataFetched = Signal('RenderWMSMgr.dataFetched')
-        self.updateProgress = Signal('RenderWMSMgr.updateProgress')
-        self.renderingFailed = Signal('RenderWMSMgr.renderingFailed')
+        self.dataFetched = Signal("RenderWMSMgr.dataFetched")
+        self.updateProgress = Signal("RenderWMSMgr.updateProgress")
+        self.renderingFailed = Signal("RenderWMSMgr.renderingFailed")
 
 
     def __del__(self):
     def __del__(self):
         try_remove(self.tempMap)
         try_remove(self.tempMap)
@@ -81,12 +84,15 @@ class RenderWMSMgr(wx.EvtHandler):
         if not haveGdal:
         if not haveGdal:
             return
             return
 
 
-        Debug.msg(1, "RenderWMSMgr.Render(%s): force=%d img=%s" %
-                  (self.layer, self.layer.forceRender, self.layer.mapfile))
+        Debug.msg(
+            1,
+            "RenderWMSMgr.Render(%s): force=%d img=%s"
+            % (self.layer, self.layer.forceRender, self.layer.mapfile),
+        )
 
 
         env = copy.copy(env)
         env = copy.copy(env)
-        self.dstSize['cols'] = int(env["GRASS_RENDER_WIDTH"])
-        self.dstSize['rows'] = int(env["GRASS_RENDER_HEIGHT"])
+        self.dstSize["cols"] = int(env["GRASS_RENDER_WIDTH"])
+        self.dstSize["rows"] = int(env["GRASS_RENDER_HEIGHT"])
 
 
         region = self._getRegionDict(env)
         region = self._getRegionDict(env)
         self._fitAspect(region, self.dstSize)
         self._fitAspect(region, self.dstSize)
@@ -95,19 +101,16 @@ class RenderWMSMgr(wx.EvtHandler):
         fetchData = True  # changed to True when calling Render()
         fetchData = True  # changed to True when calling Render()
         zoomChanged = False
         zoomChanged = False
 
 
-        if self.renderedRegion is None or \
-           cmd != self.fetched_data_cmd:
+        if self.renderedRegion is None or cmd != self.fetched_data_cmd:
             fetchData = True
             fetchData = True
         else:
         else:
-            for c in ['north', 'south', 'east', 'west']:
-                if self.renderedRegion and \
-                   region[c] != self.renderedRegion[c]:
+            for c in ["north", "south", "east", "west"]:
+                if self.renderedRegion and region[c] != self.renderedRegion[c]:
                     fetchData = True
                     fetchData = True
                     break
                     break
 
 
-            for c in ['e-w resol', 'n-s resol']:
-                if self.renderedRegion and \
-                        region[c] != self.renderedRegion[c]:
+            for c in ["e-w resol", "n-s resol"]:
+                if self.renderedRegion and region[c] != self.renderedRegion[c]:
                     zoomChanged = True
                     zoomChanged = True
                     break
                     break
 
 
@@ -128,11 +131,16 @@ class RenderWMSMgr(wx.EvtHandler):
             env["GRASS_REGION"] = self._createRegionStr(region)
             env["GRASS_REGION"] = self._createRegionStr(region)
 
 
             cmd_render = copy.deepcopy(cmd)
             cmd_render = copy.deepcopy(cmd)
-            cmd_render[1]['quiet'] = True  # be quiet
+            cmd_render[1]["quiet"] = True  # be quiet
 
 
             self._startTime = time.time()
             self._startTime = time.time()
-            self.thread.Run(callable=self._render, cmd=cmd_render, env=env,
-                            ondone=self.OnRenderDone, userdata={'env': env})
+            self.thread.Run(
+                callable=self._render,
+                cmd=cmd_render,
+                env=env,
+                ondone=self.OnRenderDone,
+                userdata={"env": env},
+            )
             self.layer.forceRender = False
             self.layer.forceRender = False
 
 
         self.updateProgress.emit(env=env, layer=self.layer)
         self.updateProgress.emit(env=env, layer=self.layer)
@@ -147,13 +155,12 @@ class RenderWMSMgr(wx.EvtHandler):
             return 1
             return 1
 
 
     def OnRenderDone(self, event):
     def OnRenderDone(self, event):
-        """Fetch data
-        """
+        """Fetch data"""
         if event.pid != self.currentPid:
         if event.pid != self.currentPid:
             return
             return
         self.downloading = False
         self.downloading = False
         if not self.updateMap:
         if not self.updateMap:
-            self.updateProgress.emit(env=event.userdata['env'], layer=self.layer)
+            self.updateProgress.emit(env=event.userdata["env"], layer=self.layer)
             self.renderedRegion = None
             self.renderedRegion = None
             self.fetched_data_cmd = None
             self.fetched_data_cmd = None
             return
             return
@@ -162,51 +169,56 @@ class RenderWMSMgr(wx.EvtHandler):
             targetFile=self.layer.mapfile,
             targetFile=self.layer.mapfile,
             region=self.renderedRegion,
             region=self.renderedRegion,
             bandsNum=3,
             bandsNum=3,
-            gdalDriver='PNM',
-            fillValue=0)
+            gdalDriver="PNM",
+            fillValue=0,
+        )
         self.mapMerger.AddRasterBands(self.tempMap, {1: 1, 2: 2, 3: 3})
         self.mapMerger.AddRasterBands(self.tempMap, {1: 1, 2: 2, 3: 3})
         del self.mapMerger
         del self.mapMerger
 
 
         add_alpha_channel = True
         add_alpha_channel = True
         mask_fill_value = 0
         mask_fill_value = 0
-        if self.fetching_cmd[1]['format'] == 'jpeg':
-            mask_fill_value = 255 # white color, g.pnmcomp doesn't apply mask (alpha channel)
+        if self.fetching_cmd[1]["format"] == "jpeg":
+            mask_fill_value = (
+                255  # white color, g.pnmcomp doesn't apply mask (alpha channel)
+            )
             add_alpha_channel = False
             add_alpha_channel = False
 
 
         self.maskMerger = GDALRasterMerger(
         self.maskMerger = GDALRasterMerger(
             targetFile=self.layer.maskfile,
             targetFile=self.layer.maskfile,
             region=self.renderedRegion,
             region=self.renderedRegion,
             bandsNum=1,
             bandsNum=1,
-            gdalDriver='PNM',
-            fillValue=mask_fill_value)
+            gdalDriver="PNM",
+            fillValue=mask_fill_value,
+        )
         if add_alpha_channel:
         if add_alpha_channel:
-            #{4 : 1} alpha channel (4) to first and only channel (1) in mask
+            # {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
         del self.maskMerger
 
 
         self.fetched_data_cmd = self.fetching_cmd
         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(env=event.userdata['env'], layer=self.layer)
+        self.dataFetched.emit(env=event.userdata["env"], layer=self.layer)
 
 
     def _getRegionDict(self, env):
     def _getRegionDict(self, env):
-        """Parse string from GRASS_REGION env variable into dict.
-        """
+        """Parse string from GRASS_REGION env variable into dict."""
         region = {}
         region = {}
-        parsedRegion = env["GRASS_REGION"].split(';')
+        parsedRegion = env["GRASS_REGION"].split(";")
         for r in parsedRegion:
         for r in parsedRegion:
-            r = r.split(':')
+            r = r.split(":")
             r[0] = r[0].strip()
             r[0] = r[0].strip()
             if len(r) < 2:
             if len(r) < 2:
                 continue
                 continue
             try:
             try:
-                if r[0] in ['e-w resol3', 'n-s resol3', 'rows3', 'cols3',
-                            'depths']:
+                if r[0] in ["e-w resol3", "n-s resol3", "rows3", "cols3", "depths"]:
                     # ignore 3D region values (causing problems in latlong locations)
                     # ignore 3D region values (causing problems in latlong locations)
                     continue
                     continue
-                if r[0] in ['cols', 'rows', 'zone', 'proj']:
+                if r[0] in ["cols", "rows", "zone", "proj"]:
                     region[r[0]] = int(r[1])
                     region[r[0]] = int(r[1])
                 else:
                 else:
                     region[r[0]] = float(r[1])
                     region[r[0]] = float(r[1])
@@ -216,42 +228,39 @@ class RenderWMSMgr(wx.EvtHandler):
         return region
         return region
 
 
     def _createRegionStr(self, region):
     def _createRegionStr(self, region):
-        """Create string for GRASS_REGION env variable from  dict created by _getRegionDict.
-        """
-        regionStr = ''
+        """Create string for GRASS_REGION env variable from  dict created by _getRegionDict."""
+        regionStr = ""
         for k, v in six.iteritems(region):
         for k, v in six.iteritems(region):
-            item = k + ': ' + str(v)
+            item = k + ": " + str(v)
             if regionStr:
             if regionStr:
-                regionStr += '; '
+                regionStr += "; "
             regionStr += item
             regionStr += item
 
 
         return regionStr
         return regionStr
 
 
     def IsDownloading(self):
     def IsDownloading(self):
-        """Is it downloading any data from WMS server?
-        """
+        """Is it downloading any data from WMS server?"""
         return self.downloading
         return self.downloading
 
 
     def _fitAspect(self, region, size):
     def _fitAspect(self, region, size):
-        """Compute region parameters to have direction independent resolution.
-        """
-        if region['n-s resol'] > region['e-w resol']:
-            delta = region['n-s resol'] * size['cols'] / 2
+        """Compute region parameters to have direction independent resolution."""
+        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']
-            region['e-w resol'] = region['n-s resol']
+            region["east"] = center + delta + region["west"]
+            region["west"] = center - delta + region["west"]
+            region["e-w resol"] = region["n-s resol"]
 
 
         else:
         else:
-            delta = region['e-w resol'] * size['rows'] / 2
+            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']
-            region['n-s resol'] = region['e-w resol']
+            region["north"] = center + delta + region["south"]
+            region["south"] = center - delta + region["south"]
+            region["n-s resol"] = region["e-w resol"]
 
 
     def Abort(self):
     def Abort(self):
         """Abort rendering process"""
         """Abort rendering process"""
@@ -267,31 +276,26 @@ class RenderWMSMgr(wx.EvtHandler):
 class GDALRasterMerger:
 class GDALRasterMerger:
     """Merge rasters.
     """Merge rasters.
 
 
-        Based on gdal_merge.py utility.
+    Based on gdal_merge.py utility.
     """
     """
 
 
-    def __init__(self, targetFile, region, bandsNum,
-                 gdalDriver, fillValue=None):
-        """Create raster for merging.
-        """
+    def __init__(self, targetFile, region, bandsNum, gdalDriver, fillValue=None):
+        """Create raster for merging."""
         self.gdalDrvType = gdalDriver
         self.gdalDrvType = gdalDriver
 
 
-        nsRes = (region['south'] - region['north']) / region['rows']
-        ewRes = (region['east'] - region['west']) / region['cols']
+        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.tUlx, self.tUly, self.tLrx, self.tLry = self._getCorners(
-            self.tGeotransform, region)
+            self.tGeotransform, region
+        )
 
 
         driver = gdal.GetDriverByName(self.gdalDrvType)
         driver = gdal.GetDriverByName(self.gdalDrvType)
         self.tDataset = driver.Create(
         self.tDataset = driver.Create(
-            targetFile, region['cols'],
-            region['rows'],
-            bandsNum, gdal.GDT_Byte)
+            targetFile, region["cols"], region["rows"], bandsNum, gdal.GDT_Byte
+        )
 
 
         if fillValue is not None:
         if fillValue is not None:
             # fill raster bands with a constant value
             # fill raster bands with a constant value
@@ -299,18 +303,14 @@ class GDALRasterMerger:
                 self.tDataset.GetRasterBand(iBand).Fill(fillValue)
                 self.tDataset.GetRasterBand(iBand).Fill(fillValue)
 
 
     def AddRasterBands(self, sourceFile, sTBands):
     def AddRasterBands(self, sourceFile, sTBands):
-        """Add raster bands from sourceFile into the merging raster.
-        """
+        """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:
         if sDataset is None:
             return
             return
 
 
         sGeotransform = sDataset.GetGeoTransform()
         sGeotransform = sDataset.GetGeoTransform()
 
 
-        sSize = {
-            'rows': sDataset.RasterYSize,
-            'cols': sDataset.RasterXSize
-        }
+        sSize = {"rows": sDataset.RasterYSize, "cols": sDataset.RasterXSize}
 
 
         sUlx, sUly, sLrx, sLry = self._getCorners(sGeotransform, sSize)
         sUlx, sUly, sLrx, sLry = self._getCorners(sGeotransform, sSize)
 
 
@@ -333,20 +333,16 @@ class GDALRasterMerger:
             return
             return
 
 
         # compute target window in pixel coordinates.
         # 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:
         if tXsize < 1 or tYsize < 1:
             return
             return
@@ -354,34 +350,32 @@ class GDALRasterMerger:
         # Compute source window in pixel coordinates.
         # Compute source window in pixel coordinates.
         sXoff = int((tIntsctUlx - sGeotransform[0]) / sGeotransform[1])
         sXoff = int((tIntsctUlx - sGeotransform[0]) / sGeotransform[1])
         sYoff = int((tIntsctUly - sGeotransform[3]) / sGeotransform[5])
         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:
         if sXsize < 1 or sYsize < 1:
             return
             return
 
 
         for sBandNnum, tBandNum in six.iteritems(sTBands):
         for sBandNnum, tBandNum in six.iteritems(sTBands):
             bandData = sDataset.GetRasterBand(sBandNnum).ReadRaster(
             bandData = sDataset.GetRasterBand(sBandNnum).ReadRaster(
-                sXoff, sYoff, sXsize, sYsize, tXsize, tYsize, gdal.GDT_Byte)
+                sXoff, sYoff, sXsize, sYsize, tXsize, tYsize, gdal.GDT_Byte
+            )
             self.tDataset.GetRasterBand(tBandNum).WriteRaster(
             self.tDataset.GetRasterBand(tBandNum).WriteRaster(
-                tXoff, tYoff, tXsize, tYsize, bandData, tXsize, tYsize, gdal.GDT_Byte)
+                tXoff, tYoff, tXsize, tYsize, bandData, tXsize, tYsize, gdal.GDT_Byte
+            )
 
 
     def _getCorners(self, geoTrans, size):
     def _getCorners(self, geoTrans, size):
 
 
         ulx = geoTrans[0]
         ulx = geoTrans[0]
         uly = geoTrans[3]
         uly = geoTrans[3]
-        lrx = geoTrans[0] + size['cols'] * geoTrans[1]
-        lry = geoTrans[3] + size['rows'] * geoTrans[5]
+        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):
     def SetGeorefAndProj(self):
-        """Set georeference and projection to target file
-        """
-        projection = grass.read_command('g.proj',
-                                        flags='wf')
+        """Set georeference and projection to target file"""
+        projection = grass.read_command("g.proj", flags="wf")
         self.tDataset.SetProjection(projection)
         self.tDataset.SetProjection(projection)
 
 
         self.tDataset.SetGeoTransform(self.tGeotransform)
         self.tDataset.SetGeoTransform(self.tGeotransform)

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

@@ -1,7 +1 @@
-all = [
-    'catalog',
-    'frame',
-    'tree',
-    'dialogs',
-    'infomanager'
-]
+all = ["catalog", "frame", "tree", "dialogs", "infomanager"]

+ 58 - 26
gui/wxpython/datacatalog/catalog.py

@@ -31,18 +31,27 @@ from grass.script import gisenv
 from grass.pydispatch.signal import Signal
 from grass.pydispatch.signal import Signal
 
 
 from grass.grassdb.manage import split_mapset_path
 from grass.grassdb.manage import split_mapset_path
-from grass.grassdb.checks import (get_reason_id_mapset_not_usable,
-                          is_fallback_session,
-                          is_first_time_user)
+from grass.grassdb.checks import (
+    get_reason_id_mapset_not_usable,
+    is_fallback_session,
+    is_first_time_user,
+)
 
 
 
 
 class DataCatalog(wx.Panel):
 class DataCatalog(wx.Panel):
     """Data catalog 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  """
         """Panel constructor  """
-        self.showNotification = Signal('DataCatalog.showNotification')
+        self.showNotification = Signal("DataCatalog.showNotification")
         self.parent = parent
         self.parent = parent
         self.baseTitle = title
         self.baseTitle = title
         self.giface = giface
         self.giface = giface
@@ -64,8 +73,9 @@ class DataCatalog(wx.Panel):
         self.giface.currentMapsetChanged.connect(self.dismissInfobar)
         self.giface.currentMapsetChanged.connect(self.dismissInfobar)
 
 
         # infobar manager for data catalog
         # infobar manager for data catalog
-        self.infoManager = DataCatalogInfoManager(infobar=self.infoBar,
-                                                  giface=self.giface)
+        self.infoManager = DataCatalogInfoManager(
+            infobar=self.infoBar, giface=self.giface
+        )
         self.tree.showImportDataInfo.connect(self.showImportDataInfo)
         self.tree.showImportDataInfo.connect(self.showImportDataInfo)
 
 
         # some layout
         # some layout
@@ -111,7 +121,9 @@ class DataCatalog(wx.Panel):
         self.infoManager.ShowFallbackSessionInfo(self.reason_id)
         self.infoManager.ShowFallbackSessionInfo(self.reason_id)
 
 
     def showImportDataInfo(self):
     def showImportDataInfo(self):
-        self.infoManager.ShowImportDataInfo(self.OnImportOgrLayers, self.OnImportGdalLayers)
+        self.infoManager.ShowImportDataInfo(
+            self.OnImportOgrLayers, self.OnImportGdalLayers
+        )
 
 
     def LoadItems(self):
     def LoadItems(self):
         self.tree.ReloadTreeItems()
         self.tree.ReloadTreeItems()
@@ -130,8 +142,9 @@ class DataCatalog(wx.Panel):
 
 
     def OnAddGrassDB(self, event):
     def OnAddGrassDB(self, event):
         """Add grass database"""
         """Add grass database"""
-        dlg = wx.DirDialog(self, _("Choose GRASS data directory:"),
-                           os.getcwd(), wx.DD_DEFAULT_STYLE)
+        dlg = wx.DirDialog(
+            self, _("Choose GRASS data directory:"), os.getcwd(), wx.DD_DEFAULT_STYLE
+        )
         if dlg.ShowModal() == wx.ID_OK:
         if dlg.ShowModal() == wx.ID_OK:
             grassdatabase = dlg.GetPath()
             grassdatabase = dlg.GetPath()
             grassdb_node = self.tree.InsertGrassDb(name=grassdatabase)
             grassdb_node = self.tree.InsertGrassDb(name=grassdatabase)
@@ -139,11 +152,12 @@ class DataCatalog(wx.Panel):
             # Offer to create a new location
             # Offer to create a new location
             if grassdb_node and not os.listdir(grassdatabase):
             if grassdb_node and not os.listdir(grassdatabase):
                 message = _("Do you want to create a location?")
                 message = _("Do you want to create a location?")
-                dlg2 = wx.MessageDialog(self,
-                                        message=message,
-                                        caption=_("Create location?"),
-                                        style=wx.YES_NO | wx.YES_DEFAULT |
-                                        wx.ICON_QUESTION)
+                dlg2 = wx.MessageDialog(
+                    self,
+                    message=message,
+                    caption=_("Create location?"),
+                    style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION,
+                )
                 if dlg2.ShowModal() == wx.ID_YES:
                 if dlg2.ShowModal() == wx.ID_YES:
                     self.tree.CreateLocation(grassdb_node)
                     self.tree.CreateLocation(grassdb_node)
                 dlg2.Destroy()
                 dlg2.Destroy()
@@ -173,6 +187,7 @@ class DataCatalog(wx.Panel):
     def OnImportGdalLayers(self, event):
     def OnImportGdalLayers(self, event):
         """Convert multiple GDAL layers to GRASS raster map layers"""
         """Convert multiple GDAL layers to GRASS raster map layers"""
         from modules.import_export import GdalImportDialog
         from modules.import_export import GdalImportDialog
+
         dlg = GdalImportDialog(parent=self, giface=self.giface)
         dlg = GdalImportDialog(parent=self, giface=self.giface)
         dlg.CentreOnScreen()
         dlg.CentreOnScreen()
         dlg.Show()
         dlg.Show()
@@ -180,6 +195,7 @@ class DataCatalog(wx.Panel):
     def OnImportOgrLayers(self, event):
     def OnImportOgrLayers(self, event):
         """Convert multiple OGR layers to GRASS vector map layers"""
         """Convert multiple OGR layers to GRASS vector map layers"""
         from modules.import_export import OgrImportDialog
         from modules.import_export import OgrImportDialog
+
         dlg = OgrImportDialog(parent=self, giface=self.giface)
         dlg = OgrImportDialog(parent=self, giface=self.giface)
         dlg.CentreOnScreen()
         dlg.CentreOnScreen()
         dlg.Show()
         dlg.Show()
@@ -187,6 +203,7 @@ class DataCatalog(wx.Panel):
     def OnLinkGdalLayers(self, event):
     def OnLinkGdalLayers(self, event):
         """Link multiple GDAL layers to GRASS raster map layers"""
         """Link multiple GDAL layers to GRASS raster map layers"""
         from modules.import_export import GdalImportDialog
         from modules.import_export import GdalImportDialog
+
         dlg = GdalImportDialog(parent=self, giface=self.giface, link=True)
         dlg = GdalImportDialog(parent=self, giface=self.giface, link=True)
         dlg.CentreOnScreen()
         dlg.CentreOnScreen()
         dlg.Show()
         dlg.Show()
@@ -194,6 +211,7 @@ class DataCatalog(wx.Panel):
     def OnLinkOgrLayers(self, event):
     def OnLinkOgrLayers(self, event):
         """Links multiple OGR layers to GRASS vector map layers"""
         """Links multiple OGR layers to GRASS vector map layers"""
         from modules.import_export import OgrImportDialog
         from modules.import_export import OgrImportDialog
+
         dlg = OgrImportDialog(parent=self, giface=self.giface, link=True)
         dlg = OgrImportDialog(parent=self, giface=self.giface, link=True)
         dlg.CentreOnScreen()
         dlg.CentreOnScreen()
         dlg.Show()
         dlg.Show()
@@ -201,6 +219,7 @@ class DataCatalog(wx.Panel):
     def OnRasterOutputFormat(self, event):
     def OnRasterOutputFormat(self, event):
         """Set raster output format handler"""
         """Set raster output format handler"""
         from modules.import_export import GdalOutputDialog
         from modules.import_export import GdalOutputDialog
+
         dlg = GdalOutputDialog(parent=self, ogr=False)
         dlg = GdalOutputDialog(parent=self, ogr=False)
         dlg.CentreOnScreen()
         dlg.CentreOnScreen()
         dlg.Show()
         dlg.Show()
@@ -208,6 +227,7 @@ class DataCatalog(wx.Panel):
     def OnVectorOutputFormat(self, event):
     def OnVectorOutputFormat(self, event):
         """Set vector output format handler"""
         """Set vector output format handler"""
         from modules.import_export import GdalOutputDialog
         from modules.import_export import GdalOutputDialog
+
         dlg = GdalOutputDialog(parent=self, ogr=True)
         dlg = GdalOutputDialog(parent=self, ogr=True)
         dlg.CentreOnScreen()
         dlg.CentreOnScreen()
         dlg.Show()
         dlg.Show()
@@ -231,21 +251,29 @@ class DataCatalog(wx.Panel):
         # create submenu
         # create submenu
         subMenu = Menu()
         subMenu = Menu()
 
 
-        subitem = wx.MenuItem(subMenu, wx.ID_ANY, _("Link external raster data  [r.external]"))
+        subitem = wx.MenuItem(
+            subMenu, wx.ID_ANY, _("Link external raster data  [r.external]")
+        )
         subMenu.AppendItem(subitem)
         subMenu.AppendItem(subitem)
         self.Bind(wx.EVT_MENU, self.OnLinkGdalLayers, subitem)
         self.Bind(wx.EVT_MENU, self.OnLinkGdalLayers, subitem)
 
 
-        subitem = wx.MenuItem(subMenu, wx.ID_ANY, _("Link external vector data  [v.external]"))
+        subitem = wx.MenuItem(
+            subMenu, wx.ID_ANY, _("Link external vector data  [v.external]")
+        )
         subMenu.AppendItem(subitem)
         subMenu.AppendItem(subitem)
         self.Bind(wx.EVT_MENU, self.OnLinkOgrLayers, subitem)
         self.Bind(wx.EVT_MENU, self.OnLinkOgrLayers, subitem)
 
 
         subMenu.AppendSeparator()
         subMenu.AppendSeparator()
 
 
-        subitem = wx.MenuItem(subMenu, wx.ID_ANY, _("Set raster output format  [r.external.out]"))
+        subitem = wx.MenuItem(
+            subMenu, wx.ID_ANY, _("Set raster output format  [r.external.out]")
+        )
         subMenu.AppendItem(subitem)
         subMenu.AppendItem(subitem)
         self.Bind(wx.EVT_MENU, self.OnRasterOutputFormat, subitem)
         self.Bind(wx.EVT_MENU, self.OnRasterOutputFormat, subitem)
 
 
-        subitem = wx.MenuItem(subMenu, wx.ID_ANY, _("Set vector output format  [v.external.out]"))
+        subitem = wx.MenuItem(
+            subMenu, wx.ID_ANY, _("Set vector output format  [v.external.out]")
+        )
         subMenu.AppendItem(subitem)
         subMenu.AppendItem(subitem)
         self.Bind(wx.EVT_MENU, self.OnVectorOutputFormat, subitem)
         self.Bind(wx.EVT_MENU, self.OnVectorOutputFormat, subitem)
 
 
@@ -254,21 +282,25 @@ class DataCatalog(wx.Panel):
 
 
         item = wx.MenuItem(menu, wx.ID_ANY, _("Unpack GRASS raster map  [r.unpack]"))
         item = wx.MenuItem(menu, wx.ID_ANY, _("Unpack GRASS raster map  [r.unpack]"))
         menu.AppendItem(item)
         menu.AppendItem(item)
-        self.Bind(wx.EVT_MENU, lambda evt: self.GuiParseCommand('r.unpack'), item)
+        self.Bind(wx.EVT_MENU, lambda evt: self.GuiParseCommand("r.unpack"), item)
 
 
         item = wx.MenuItem(menu, wx.ID_ANY, _("Unpack GRASS vector map  [v.unpack]"))
         item = wx.MenuItem(menu, wx.ID_ANY, _("Unpack GRASS vector map  [v.unpack]"))
         menu.AppendItem(item)
         menu.AppendItem(item)
-        self.Bind(wx.EVT_MENU, lambda evt: self.GuiParseCommand('v.unpack'), item)
+        self.Bind(wx.EVT_MENU, lambda evt: self.GuiParseCommand("v.unpack"), item)
 
 
         menu.AppendSeparator()
         menu.AppendSeparator()
 
 
-        item = wx.MenuItem(menu, wx.ID_ANY, _("Create raster map from x,y,z data  [r.in.xyz]"))
+        item = wx.MenuItem(
+            menu, wx.ID_ANY, _("Create raster map from x,y,z data  [r.in.xyz]")
+        )
         menu.AppendItem(item)
         menu.AppendItem(item)
-        self.Bind(wx.EVT_MENU, lambda evt: self.GuiParseCommand('r.in.xyz'), item)
+        self.Bind(wx.EVT_MENU, lambda evt: self.GuiParseCommand("r.in.xyz"), item)
 
 
-        item = wx.MenuItem(menu, wx.ID_ANY, _("Create vector map from x,y,z data  [v.in.ascii]"))
+        item = wx.MenuItem(
+            menu, wx.ID_ANY, _("Create vector map from x,y,z data  [v.in.ascii]")
+        )
         menu.AppendItem(item)
         menu.AppendItem(item)
-        self.Bind(wx.EVT_MENU, lambda evt: self.GuiParseCommand('v.in.ascii'), item)
+        self.Bind(wx.EVT_MENU, lambda evt: self.GuiParseCommand("v.in.ascii"), item)
 
 
         menu.AppendSeparator()
         menu.AppendSeparator()
         menu.AppendMenu(wx.ID_ANY, _("Link external data"), subMenu)
         menu.AppendMenu(wx.ID_ANY, _("Link external data"), subMenu)

+ 142 - 69
gui/wxpython/datacatalog/dialogs.py

@@ -25,18 +25,33 @@ from grass.script import parse_key_val, region_env
 
 
 
 
 class CatalogReprojectionDialog(wx.Dialog):
 class CatalogReprojectionDialog(wx.Dialog):
-    def __init__(self, parent, giface, inputGisdbase, inputLocation,
-                 inputMapset, inputLayer, inputEnv,
-                 outputGisdbase, outputLocation, outputMapset, outputLayer,
-                 etype, outputEnv, callback,
-                 id=wx.ID_ANY, title=_("Reprojection"),
-                 style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
+    def __init__(
+        self,
+        parent,
+        giface,
+        inputGisdbase,
+        inputLocation,
+        inputMapset,
+        inputLayer,
+        inputEnv,
+        outputGisdbase,
+        outputLocation,
+        outputMapset,
+        outputLayer,
+        etype,
+        outputEnv,
+        callback,
+        id=wx.ID_ANY,
+        title=_("Reprojection"),
+        style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
+    ):
 
 
         self.parent = parent
         self.parent = parent
         self._giface = giface
         self._giface = giface
 
 
-        wx.Dialog.__init__(self, parent, id, title, style=style,
-                           name="ReprojectionDialog")
+        wx.Dialog.__init__(
+            self, parent, id, title, style=style, name="ReprojectionDialog"
+        )
 
 
         self.panel = wx.Panel(parent=self)
         self.panel = wx.Panel(parent=self)
         self.iGisdbase = inputGisdbase
         self.iGisdbase = inputGisdbase
@@ -55,19 +70,29 @@ class CatalogReprojectionDialog(wx.Dialog):
         self._widgets()
         self._widgets()
         self._doLayout()
         self._doLayout()
 
 
-        if self.etype == 'raster':
+        if self.etype == "raster":
             self._estimateResampling()
             self._estimateResampling()
             self._estimateResolution()
             self._estimateResolution()
 
 
     def _widgets(self):
     def _widgets(self):
-        if self.etype == 'raster':
+        if self.etype == "raster":
             self.resolution = TextCtrl(self.panel, validator=FloatValidator())
             self.resolution = TextCtrl(self.panel, validator=FloatValidator())
-            self.resampling = wx.Choice(self.panel, size=(200, -1),
-                                        choices=['nearest', 'bilinear', 'bicubic', 'lanczos',
-                                                 'bilinear_f', 'bicubic_f', 'lanczos_f'])
+            self.resampling = wx.Choice(
+                self.panel,
+                size=(200, -1),
+                choices=[
+                    "nearest",
+                    "bilinear",
+                    "bicubic",
+                    "lanczos",
+                    "bilinear_f",
+                    "bicubic_f",
+                    "lanczos_f",
+                ],
+            )
         else:
         else:
             self.vsplit = TextCtrl(self.panel, validator=IntegerValidator())
             self.vsplit = TextCtrl(self.panel, validator=IntegerValidator())
-            self.vsplit.SetValue('10000')
+            self.vsplit.SetValue("10000")
 
 
         #
         #
         # buttons
         # buttons
@@ -77,9 +102,9 @@ class CatalogReprojectionDialog(wx.Dialog):
 
 
         # run
         # run
         self.btn_run = Button(parent=self.panel, id=wx.ID_OK, label=_("Reproject"))
         self.btn_run = Button(parent=self.panel, id=wx.ID_OK, label=_("Reproject"))
-        if self.etype == 'raster':
+        if self.etype == "raster":
             self.btn_run.SetToolTip(_("Reproject raster"))
             self.btn_run.SetToolTip(_("Reproject raster"))
-        elif self.etype == 'vector':
+        elif self.etype == "vector":
             self.btn_run.SetToolTip(_("Reproject vector"))
             self.btn_run.SetToolTip(_("Reproject vector"))
         self.btn_run.SetDefault()
         self.btn_run.SetDefault()
         self.btn_run.Bind(wx.EVT_BUTTON, self.OnReproject)
         self.btn_run.Bind(wx.EVT_BUTTON, self.OnReproject)
@@ -89,27 +114,42 @@ class CatalogReprojectionDialog(wx.Dialog):
         dialogSizer = wx.BoxSizer(wx.VERTICAL)
         dialogSizer = wx.BoxSizer(wx.VERTICAL)
         optionsSizer = wx.GridBagSizer(5, 5)
         optionsSizer = wx.GridBagSizer(5, 5)
 
 
-        label = _("Map layer <{ml}> needs to be reprojected.\n"
-                  "Please review and modify reprojection parameters:").format(ml=self.iLayer)
-        dialogSizer.Add(StaticText(self.panel, label=label),
-                        flag=wx.ALL | wx.EXPAND, border=10)
-        if self.etype == 'raster':
-            optionsSizer.Add(StaticText(self.panel, label=_("Estimated resolution:")),
-                             pos=(0, 0), flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)
+        label = _(
+            "Map layer <{ml}> needs to be reprojected.\n"
+            "Please review and modify reprojection parameters:"
+        ).format(ml=self.iLayer)
+        dialogSizer.Add(
+            StaticText(self.panel, label=label), flag=wx.ALL | wx.EXPAND, border=10
+        )
+        if self.etype == "raster":
+            optionsSizer.Add(
+                StaticText(self.panel, label=_("Estimated resolution:")),
+                pos=(0, 0),
+                flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL,
+            )
             optionsSizer.Add(self.resolution, pos=(0, 1), flag=wx.EXPAND)
             optionsSizer.Add(self.resolution, pos=(0, 1), flag=wx.EXPAND)
-            optionsSizer.Add(StaticText(self.panel, label=_("Resampling method:")),
-                             pos=(1, 0), flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)
+            optionsSizer.Add(
+                StaticText(self.panel, label=_("Resampling method:")),
+                pos=(1, 0),
+                flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL,
+            )
             optionsSizer.Add(self.resampling, pos=(1, 1), flag=wx.EXPAND)
             optionsSizer.Add(self.resampling, pos=(1, 1), flag=wx.EXPAND)
         else:
         else:
-            optionsSizer.Add(StaticText(self.panel, label=_("Maximum segment length:")),
-                             pos=(1, 0), flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)
+            optionsSizer.Add(
+                StaticText(self.panel, label=_("Maximum segment length:")),
+                pos=(1, 0),
+                flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL,
+            )
             optionsSizer.Add(self.vsplit, pos=(1, 1), flag=wx.EXPAND)
             optionsSizer.Add(self.vsplit, pos=(1, 1), flag=wx.EXPAND)
         optionsSizer.AddGrowableCol(1)
         optionsSizer.AddGrowableCol(1)
         dialogSizer.Add(optionsSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=10)
         dialogSizer.Add(optionsSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=10)
-        helptext = StaticText(self.panel,
-                              label="For more reprojection options,"
-                              " please see {module}".format(module='r.proj' if self.etype == 'raster'
-                                                            else 'v.proj'))
+        helptext = StaticText(
+            self.panel,
+            label="For more reprojection options,"
+            " please see {module}".format(
+                module="r.proj" if self.etype == "raster" else "v.proj"
+            ),
+        )
         dialogSizer.Add(helptext, proportion=0, flag=wx.ALL | wx.EXPAND, border=10)
         dialogSizer.Add(helptext, proportion=0, flag=wx.ALL | wx.EXPAND, border=10)
         #
         #
         # buttons
         # buttons
@@ -127,53 +167,86 @@ class CatalogReprojectionDialog(wx.Dialog):
         self.SetSize(self.GetBestSize())
         self.SetSize(self.GetBestSize())
 
 
     def _estimateResolution(self):
     def _estimateResolution(self):
-        output = RunCommand('r.proj', flags='g', quiet=False, read=True, input=self.iLayer,
-                            dbase=self.iGisdbase, location=self.iLocation, mapset=self.iMapset,
-                            env=self.oEnv).strip()
-        params = parse_key_val(output, vsep=' ')
-        output = RunCommand('g.region', flags='ug', quiet=False, read=True, env=self.oEnv,
-                            parse=lambda x: parse_key_val(x, val_type=float), **params)
-        cell_ns = (output['n'] - output['s']) / output['rows']
-        cell_ew = (output['e'] - output['w']) / output['cols']
-        estimate = (cell_ew + cell_ns) / 2.
+        output = RunCommand(
+            "r.proj",
+            flags="g",
+            quiet=False,
+            read=True,
+            input=self.iLayer,
+            dbase=self.iGisdbase,
+            location=self.iLocation,
+            mapset=self.iMapset,
+            env=self.oEnv,
+        ).strip()
+        params = parse_key_val(output, vsep=" ")
+        output = RunCommand(
+            "g.region",
+            flags="ug",
+            quiet=False,
+            read=True,
+            env=self.oEnv,
+            parse=lambda x: parse_key_val(x, val_type=float),
+            **params,
+        )
+        cell_ns = (output["n"] - output["s"]) / output["rows"]
+        cell_ew = (output["e"] - output["w"]) / output["cols"]
+        estimate = (cell_ew + cell_ns) / 2.0
         self.resolution.SetValue(str(estimate))
         self.resolution.SetValue(str(estimate))
         self.params = params
         self.params = params
 
 
     def _estimateResampling(self):
     def _estimateResampling(self):
-        output = RunCommand('r.info', flags='g', quiet=False, read=True, map=self.iLayer,
-                            env=self.iEnv, parse=parse_key_val)
-        if output['datatype'] == 'CELL':
-            self.resampling.SetStringSelection('nearest')
+        output = RunCommand(
+            "r.info",
+            flags="g",
+            quiet=False,
+            read=True,
+            map=self.iLayer,
+            env=self.iEnv,
+            parse=parse_key_val,
+        )
+        if output["datatype"] == "CELL":
+            self.resampling.SetStringSelection("nearest")
         else:
         else:
-            self.resampling.SetStringSelection('bilinear')
+            self.resampling.SetStringSelection("bilinear")
 
 
     def OnReproject(self, event):
     def OnReproject(self, event):
         cmd = []
         cmd = []
-        if self.etype == 'raster':
-            cmd.append('r.proj')
-            cmd.append('dbase=' + self.iGisdbase)
-            cmd.append('location=' + self.iLocation)
-            cmd.append('mapset=' + self.iMapset)
-            cmd.append('input=' + self.iLayer)
-            cmd.append('output=' + self.oLayer)
-            cmd.append('method=' + self.resampling.GetStringSelection())
-
-            self.oEnv['GRASS_REGION'] = region_env(n=self.params['n'], s=self.params['s'],
-                                                   e=self.params['e'], w=self.params['w'],
-                                                   flags='a', res=float(self.resolution.GetValue()),
-                                                   env=self.oEnv)
+        if self.etype == "raster":
+            cmd.append("r.proj")
+            cmd.append("dbase=" + self.iGisdbase)
+            cmd.append("location=" + self.iLocation)
+            cmd.append("mapset=" + self.iMapset)
+            cmd.append("input=" + self.iLayer)
+            cmd.append("output=" + self.oLayer)
+            cmd.append("method=" + self.resampling.GetStringSelection())
+
+            self.oEnv["GRASS_REGION"] = region_env(
+                n=self.params["n"],
+                s=self.params["s"],
+                e=self.params["e"],
+                w=self.params["w"],
+                flags="a",
+                res=float(self.resolution.GetValue()),
+                env=self.oEnv,
+            )
         else:
         else:
-            cmd.append('v.proj')
-            cmd.append('dbase=' + self.iGisdbase)
-            cmd.append('location=' + self.iLocation)
-            cmd.append('mapset=' + self.iMapset)
-            cmd.append('input=' + self.iLayer)
-            cmd.append('output=' + self.oLayer)
-            cmd.append('smax=' + self.vsplit.GetValue())
-
-        self._giface.RunCmd(cmd, env=self.oEnv, compReg=False, addLayer=False,
-                            onDone=self._onDone, userData=None,
-                            notification=Notification.MAKE_VISIBLE)
+            cmd.append("v.proj")
+            cmd.append("dbase=" + self.iGisdbase)
+            cmd.append("location=" + self.iLocation)
+            cmd.append("mapset=" + self.iMapset)
+            cmd.append("input=" + self.iLayer)
+            cmd.append("output=" + self.oLayer)
+            cmd.append("smax=" + self.vsplit.GetValue())
+
+        self._giface.RunCmd(
+            cmd,
+            env=self.oEnv,
+            compReg=False,
+            addLayer=False,
+            onDone=self._onDone,
+            userData=None,
+            notification=Notification.MAKE_VISIBLE,
+        )
 
 
         event.Skip()
         event.Skip()
 
 

+ 3 - 10
gui/wxpython/datacatalog/frame.py

@@ -28,15 +28,10 @@ from gui_core.wrap import Button
 class DataCatalogFrame(wx.Frame):
 class DataCatalogFrame(wx.Frame):
     """Frame for testing purposes only."""
     """Frame for testing purposes only."""
 
 
-    def __init__(self, parent, giface=None, title=_('Data Catalog')):
+    def __init__(self, parent, giface=None, title=_("Data Catalog")):
         wx.Frame.__init__(self, parent=parent, title=title)
         wx.Frame.__init__(self, parent=parent, title=title)
         self.SetName("DataCatalog")
         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._giface = giface
         self.panel = wx.Panel(self)
         self.panel = wx.Panel(self)
@@ -61,9 +56,7 @@ class DataCatalogFrame(wx.Frame):
         btnSizer.AddStretchSpacer()
         btnSizer.AddStretchSpacer()
         btnSizer.Add(self.btnClose)
         btnSizer.Add(self.btnClose)
 
 
-        sizer.Add(btnSizer, proportion=0,
-                  flag=wx.ALL | wx.EXPAND,
-                  border=5)
+        sizer.Add(btnSizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
 
 
         self.panel.SetSizer(sizer)
         self.panel.SetSizer(sizer)
         sizer.Fit(self.panel)
         sizer.Fit(self.panel)

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

@@ -36,6 +36,7 @@ def main():
     import wx
     import wx
 
 
     from grass.script.setup import set_gui_path
     from grass.script.setup import set_gui_path
+
     set_gui_path()
     set_gui_path()
 
 
     from core.giface import StandaloneGrassInterface
     from core.giface import StandaloneGrassInterface
@@ -52,5 +53,6 @@ def main():
     frame.Show()
     frame.Show()
     app.MainLoop()
     app.MainLoop()
 
 
-if __name__ == '__main__':
+
+if __name__ == "__main__":
     main()
     main()

+ 75 - 72
gui/wxpython/datacatalog/toolbars.py

@@ -20,63 +20,62 @@ from gui_core.wrap import SearchCtrl
 from icons.icon import MetaIcon
 from icons.icon import MetaIcon
 
 
 icons = {
 icons = {
-    'reloadTree': MetaIcon(
-        img='redraw',
-        label=_("Reload GRASS locations")),
-    'reloadMapset': MetaIcon(
-        img='reload',
-        label=_("Reload current GRASS mapset only")),
-    'unlocked': MetaIcon(
-        img='edit',
-        label=_("Restrict edits to the current mapset only")),
-    'locked': MetaIcon(
-        img='edit',
-        label=_("Allow edits outside of the current mapset")),
-    'addGrassDB': MetaIcon(
-        img='grassdb-add',
-        label=_("Add existing or create new database")),
-    'addMapset': MetaIcon(
-        img='mapset-add',
-        label=_("Create new mapset in current location")),
-    'addLocation': MetaIcon(
-        img='location-add',
-        label=_("Create new location in current GRASS database")),
-    'downloadLocation': MetaIcon(
-        img='location-download',
-        label=_("Download sample location to current GRASS database")),
-    'importRaster': MetaIcon(
-        img='raster-import',
-        label=_("Import raster data  [r.import]")),
-    'importVector': MetaIcon(
-        img='vector-import',
-        label=_("Import vector data  [v.import]")),
-    'importLayer': MetaIcon(
-        img='layer-import',
-        label=_("Select another import option"))
+    "reloadTree": MetaIcon(img="redraw", label=_("Reload GRASS locations")),
+    "reloadMapset": MetaIcon(img="reload", label=_("Reload current GRASS mapset only")),
+    "unlocked": MetaIcon(
+        img="edit", label=_("Restrict edits to the current mapset only")
+    ),
+    "locked": MetaIcon(
+        img="edit", label=_("Allow edits outside of the current mapset")
+    ),
+    "addGrassDB": MetaIcon(
+        img="grassdb-add", label=_("Add existing or create new database")
+    ),
+    "addMapset": MetaIcon(
+        img="mapset-add", label=_("Create new mapset in current location")
+    ),
+    "addLocation": MetaIcon(
+        img="location-add", label=_("Create new location in current GRASS database")
+    ),
+    "downloadLocation": MetaIcon(
+        img="location-download",
+        label=_("Download sample location to current GRASS database"),
+    ),
+    "importRaster": MetaIcon(
+        img="raster-import", label=_("Import raster data  [r.import]")
+    ),
+    "importVector": MetaIcon(
+        img="vector-import", label=_("Import vector data  [v.import]")
+    ),
+    "importLayer": MetaIcon(
+        img="layer-import", label=_("Select another import option")
+    ),
 }
 }
 
 
 
 
 class DataCatalogToolbar(BaseToolbar):
 class DataCatalogToolbar(BaseToolbar):
-    """Main data catalog toolbar
-    """
+    """Main data catalog toolbar"""
 
 
     def __init__(self, parent):
     def __init__(self, parent):
-        """Main toolbar constructor
-        """
+        """Main toolbar constructor"""
 
 
         BaseToolbar.__init__(self, parent)
         BaseToolbar.__init__(self, parent)
 
 
         self.InitToolbar(self._toolbarData())
         self.InitToolbar(self._toolbarData())
         self.filter_element = None
         self.filter_element = None
         self.filter = SearchCtrl(parent=self)
         self.filter = SearchCtrl(parent=self)
-        self.filter.SetDescriptiveText(_('Search'))
+        self.filter.SetDescriptiveText(_("Search"))
         self.filter.ShowCancelButton(True)
         self.filter.ShowCancelButton(True)
         self.filter.SetSize((150, self.filter.GetBestSize()[1]))
         self.filter.SetSize((150, self.filter.GetBestSize()[1]))
-        self.filter.Bind(wx.EVT_TEXT,
-                         lambda event: self.parent.Filter(
-                             self.filter.GetValue(), self.filter_element))
-        self.filter.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN,
-                         lambda evt: self.parent.Filter(''))
+        self.filter.Bind(
+            wx.EVT_TEXT,
+            lambda event: self.parent.Filter(
+                self.filter.GetValue(), self.filter_element
+            ),
+        )
+        self.filter.Bind(
+            wx.EVT_SEARCHCTRL_CANCEL_BTN, lambda evt: self.parent.Filter("")
+        )
         self.AddControl(self.filter)
         self.AddControl(self.filter)
         filterMenu = wx.Menu()
         filterMenu = wx.Menu()
         item = filterMenu.AppendRadioItem(-1, "All")
         item = filterMenu.AppendRadioItem(-1, "All")
@@ -88,8 +87,10 @@ class DataCatalogToolbar(BaseToolbar):
         item = filterMenu.AppendRadioItem(-1, "3D raster maps")
         item = filterMenu.AppendRadioItem(-1, "3D raster maps")
         self.Bind(wx.EVT_MENU, self.OnFilterMenu, item)
         self.Bind(wx.EVT_MENU, self.OnFilterMenu, item)
         self.filter.SetMenu(filterMenu)
         self.filter.SetMenu(filterMenu)
-        help = _("Type to search database by map type or name. "
-                 "Use Python regular expressions to refine your search.")
+        help = _(
+            "Type to search database by map type or name. "
+            "Use Python regular expressions to refine your search."
+        )
         self.SetToolShortHelp(self.filter.GetId(), help)
         self.SetToolShortHelp(self.filter.GetId(), help)
         # realize the toolbar
         # realize the toolbar
         self.Realize()
         self.Realize()
@@ -98,47 +99,49 @@ class DataCatalogToolbar(BaseToolbar):
         """Returns toolbar data (name, icon, handler)"""
         """Returns toolbar data (name, icon, handler)"""
         # BaseIcons are a set of often used icons. It is possible
         # BaseIcons are a set of often used icons. It is possible
         # to reuse icons in ./trunk/gui/icons/grass or add new ones there.
         # to reuse icons in ./trunk/gui/icons/grass or add new ones there.
-        return self._getToolbarData((("reloadTree", icons["reloadTree"],
-                                      self.parent.OnReloadTree),
-                                     ("reloadMapset", icons["reloadMapset"],
-                                      self.parent.OnReloadCurrentMapset),
-                                     ("lock", icons['locked'],
-                                      self.OnSetRestriction, wx.ITEM_CHECK),
-                                     ("addGrassDB", icons['addGrassDB'],
-                                      self.parent.OnAddGrassDB),
-                                     ("addLocation", icons['addLocation'],
-                                      self.parent.OnCreateLocation),
-                                     ("downloadLocation", icons['downloadLocation'],
-                                      self.parent.OnDownloadLocation),
-                                     ("addMapset", icons['addMapset'],
-                                      self.parent.OnCreateMapset),
-                                     ("importRaster", icons['importRaster'],
-                                      self.parent.OnImportGdalLayers),
-                                     ("importVector", icons['importVector'],
-                                      self.parent.OnImportOgrLayers),
-                                     ("importLayer", icons['importLayer'],
-                                      self.parent.OnImportMenu)))
+        return self._getToolbarData(
+            (
+                ("reloadTree", icons["reloadTree"], self.parent.OnReloadTree),
+                (
+                    "reloadMapset",
+                    icons["reloadMapset"],
+                    self.parent.OnReloadCurrentMapset,
+                ),
+                ("lock", icons["locked"], self.OnSetRestriction, wx.ITEM_CHECK),
+                ("addGrassDB", icons["addGrassDB"], self.parent.OnAddGrassDB),
+                ("addLocation", icons["addLocation"], self.parent.OnCreateLocation),
+                (
+                    "downloadLocation",
+                    icons["downloadLocation"],
+                    self.parent.OnDownloadLocation,
+                ),
+                ("addMapset", icons["addMapset"], self.parent.OnCreateMapset),
+                ("importRaster", icons["importRaster"], self.parent.OnImportGdalLayers),
+                ("importVector", icons["importVector"], self.parent.OnImportOgrLayers),
+                ("importLayer", icons["importLayer"], self.parent.OnImportMenu),
+            )
+        )
 
 
     def OnFilterMenu(self, event):
     def OnFilterMenu(self, event):
         """Decide the element to filter by"""
         """Decide the element to filter by"""
         filterMenu = self.filter.GetMenu().GetMenuItems()
         filterMenu = self.filter.GetMenu().GetMenuItems()
         self.filter_element = None
         self.filter_element = None
         if filterMenu[1].IsChecked():
         if filterMenu[1].IsChecked():
-            self.filter_element = 'raster'
+            self.filter_element = "raster"
         elif filterMenu[2].IsChecked():
         elif filterMenu[2].IsChecked():
-            self.filter_element = 'vector'
+            self.filter_element = "vector"
         elif filterMenu[3].IsChecked():
         elif filterMenu[3].IsChecked():
-            self.filter_element = 'raster_3d'
+            self.filter_element = "raster_3d"
         # trigger filter on change
         # trigger filter on change
         if self.filter.GetValue():
         if self.filter.GetValue():
             self.parent.Filter(self.filter.GetValue(), self.filter_element)
             self.parent.Filter(self.filter.GetValue(), self.filter_element)
 
 
     def OnSetRestriction(self, event):
     def OnSetRestriction(self, event):
         if self.GetToolState(self.lock):
         if self.GetToolState(self.lock):
-            self.SetToolNormalBitmap(self.lock, icons['unlocked'].GetBitmap())
-            self.SetToolShortHelp(self.lock, icons['unlocked'].GetLabel())
+            self.SetToolNormalBitmap(self.lock, icons["unlocked"].GetBitmap())
+            self.SetToolShortHelp(self.lock, icons["unlocked"].GetLabel())
             self.parent.SetRestriction(restrict=False)
             self.parent.SetRestriction(restrict=False)
         else:
         else:
-            self.SetToolNormalBitmap(self.lock, icons['locked'].GetBitmap())
-            self.SetToolShortHelp(self.lock, icons['locked'].GetLabel())
+            self.SetToolNormalBitmap(self.lock, icons["locked"].GetBitmap())
+            self.SetToolShortHelp(self.lock, icons["locked"].GetLabel())
             self.parent.SetRestriction(restrict=True)
             self.parent.SetRestriction(restrict=True)

Plik diff jest za duży
+ 813 - 547
gui/wxpython/datacatalog/tree.py


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

@@ -1,8 +1,8 @@
 all = [
 all = [
-    'g.gui.dbmgr',
-    'sqlbuilder',
-    'vinfo',
-    'manager',
-    'base',
-    'dialogs',
+    "g.gui.dbmgr",
+    "sqlbuilder",
+    "vinfo",
+    "manager",
+    "base",
+    "dialogs",
 ]
 ]

Plik diff jest za duży
+ 1588 - 1474
gui/wxpython/dbmgr/base.py


+ 241 - 210
gui/wxpython/dbmgr/dialogs.py

@@ -26,17 +26,22 @@ from core.gcmd import RunCommand, GError
 from core.debug import Debug
 from core.debug import Debug
 from dbmgr.vinfo import VectorDBInfo, GetUnicodeValue, GetDbEncoding
 from dbmgr.vinfo import VectorDBInfo, GetUnicodeValue, GetDbEncoding
 from gui_core.widgets import IntegerValidator, FloatValidator
 from gui_core.widgets import IntegerValidator, FloatValidator
-from gui_core.wrap import SpinCtrl, Button, StaticText, StaticBox, \
-    TextCtrl
+from gui_core.wrap import SpinCtrl, Button, StaticText, StaticBox, TextCtrl
 
 
 
 
 class DisplayAttributesDialog(wx.Dialog):
 class DisplayAttributesDialog(wx.Dialog):
-
-    def __init__(self, parent, map,
-                 query=None, cats=None, line=None,
-                 style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
-                 pos=wx.DefaultPosition,
-                 action="add", ignoreError=False):
+    def __init__(
+        self,
+        parent,
+        map,
+        query=None,
+        cats=None,
+        line=None,
+        style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
+        pos=wx.DefaultPosition,
+        action="add",
+        ignoreError=False,
+    ):
         """Standard dialog used to add/update/display attributes linked
         """Standard dialog used to add/update/display attributes linked
         to the vector map.
         to the vector map.
 
 
@@ -75,42 +80,45 @@ class DisplayAttributesDialog(wx.Dialog):
                     message=_(
                     message=_(
                         "No attribute table found.\n\n"
                         "No attribute table found.\n\n"
                         "Do you want to create a new attribute table "
                         "Do you want to create a new attribute table "
-                        "and defined a link to vector map <%s>?") %
-                    self.map,
+                        "and defined a link to vector map <%s>?"
+                    )
+                    % self.map,
                     caption=_("Create table?"),
                     caption=_("Create table?"),
-                    style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
+                    style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION,
+                )
                 if dlg.ShowModal() == wx.ID_YES:
                 if dlg.ShowModal() == wx.ID_YES:
                     lmgr = self.parent.lmgr
                     lmgr = self.parent.lmgr
-                    lmgr.OnShowAttributeTable(event=None, selection='layers')
+                    lmgr.OnShowAttributeTable(event=None, selection="layers")
 
 
                 dlg.Destroy()
                 dlg.Destroy()
 
 
             self.mapDBInfo = None
             self.mapDBInfo = None
 
 
-        wx.Dialog.__init__(self, parent=self.parent, id=wx.ID_ANY,
-                           title="", style=style, pos=pos)
+        wx.Dialog.__init__(
+            self, parent=self.parent, id=wx.ID_ANY, title="", style=style, pos=pos
+        )
 
 
         # dialog body
         # dialog body
         mainSizer = wx.BoxSizer(wx.VERTICAL)
         mainSizer = wx.BoxSizer(wx.VERTICAL)
 
 
         # notebook
         # notebook
-        self.notebook = wx.Notebook(
-            parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
+        self.notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
 
 
-        self.closeDialog = wx.CheckBox(parent=self, id=wx.ID_ANY,
-                                       label=_("Close dialog on submit"))
+        self.closeDialog = wx.CheckBox(
+            parent=self, id=wx.ID_ANY, label=_("Close dialog on submit")
+        )
         self.closeDialog.SetValue(True)
         self.closeDialog.SetValue(True)
-        if self.action == 'display':
+        if self.action == "display":
             self.closeDialog.Enable(False)
             self.closeDialog.Enable(False)
 
 
         # feature id (text/choice for duplicates)
         # feature id (text/choice for duplicates)
-        self.fidMulti = wx.Choice(parent=self, id=wx.ID_ANY,
-                                  size=(150, -1))
+        self.fidMulti = wx.Choice(parent=self, id=wx.ID_ANY, size=(150, -1))
         self.fidMulti.Bind(wx.EVT_CHOICE, self.OnFeature)
         self.fidMulti.Bind(wx.EVT_CHOICE, self.OnFeature)
         self.fidText = StaticText(parent=self, id=wx.ID_ANY)
         self.fidText = StaticText(parent=self, id=wx.ID_ANY)
 
 
-        self.noFoundMsg = StaticText(parent=self, id=wx.ID_ANY,
-                                     label=_("No attributes found"))
+        self.noFoundMsg = StaticText(
+            parent=self, id=wx.ID_ANY, label=_("No attributes found")
+        )
 
 
         self.UpdateDialog(query=query, cats=cats)
         self.UpdateDialog(query=query, cats=cats)
 
 
@@ -126,7 +134,7 @@ class DisplayAttributesDialog(wx.Dialog):
         btnCancel = Button(self, wx.ID_CANCEL)
         btnCancel = Button(self, wx.ID_CANCEL)
         btnReset = Button(self, wx.ID_UNDO, _("&Reload"))
         btnReset = Button(self, wx.ID_UNDO, _("&Reload"))
         btnSubmit = Button(self, wx.ID_OK, _("&Submit"))
         btnSubmit = Button(self, wx.ID_OK, _("&Submit"))
-        if self.action == 'display':
+        if self.action == "display":
             btnSubmit.Enable(False)
             btnSubmit.Enable(False)
 
 
         btnSizer = wx.StdDialogButtonSizer()
         btnSizer = wx.StdDialogButtonSizer()
@@ -137,28 +145,27 @@ class DisplayAttributesDialog(wx.Dialog):
         btnSizer.AddButton(btnSubmit)
         btnSizer.AddButton(btnSubmit)
         btnSizer.Realize()
         btnSizer.Realize()
 
 
-        mainSizer.Add(self.noFoundMsg, proportion=0,
-                      flag=wx.EXPAND | wx.ALL, border=5)
-        mainSizer.Add(self.notebook, proportion=1,
-                      flag=wx.EXPAND | wx.ALL, border=5)
+        mainSizer.Add(self.noFoundMsg, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
+        mainSizer.Add(self.notebook, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
         fidSizer = wx.BoxSizer(wx.HORIZONTAL)
         fidSizer = wx.BoxSizer(wx.HORIZONTAL)
-        fidSizer.Add(StaticText(parent=self, id=wx.ID_ANY,
-                                label=_("Feature id:")),
-                     proportion=0, border=5,
-                     flag=wx.ALIGN_CENTER_VERTICAL)
-        fidSizer.Add(self.fidMulti, proportion=0,
-                     flag=wx.EXPAND | wx.ALL, border=5)
-        fidSizer.Add(self.fidText, proportion=0,
-                     flag=wx.EXPAND | wx.ALL, border=5)
-        mainSizer.Add(fidSizer, proportion=0,
-                      flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=5)
+        fidSizer.Add(
+            StaticText(parent=self, id=wx.ID_ANY, label=_("Feature id:")),
+            proportion=0,
+            border=5,
+            flag=wx.ALIGN_CENTER_VERTICAL,
+        )
+        fidSizer.Add(self.fidMulti, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
+        fidSizer.Add(self.fidText, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
+        mainSizer.Add(
+            fidSizer, proportion=0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=5
+        )
         mainSizer.Add(
         mainSizer.Add(
             self.closeDialog,
             self.closeDialog,
             proportion=0,
             proportion=0,
             flag=wx.EXPAND | wx.LEFT | wx.RIGHT,
             flag=wx.EXPAND | wx.LEFT | wx.RIGHT,
-            border=5)
-        mainSizer.Add(btnSizer, proportion=0,
-                      flag=wx.EXPAND | wx.ALL, border=5)
+            border=5,
+        )
+        mainSizer.Add(btnSizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
 
 
         # bindigs
         # bindigs
         btnReset.Bind(wx.EVT_BUTTON, self.OnReset)
         btnReset.Bind(wx.EVT_BUTTON, self.OnReset)
@@ -207,16 +214,16 @@ class DisplayAttributesDialog(wx.Dialog):
             table = self.mapDBInfo.GetTable(layer)
             table = self.mapDBInfo.GetTable(layer)
             key = self.mapDBInfo.GetKeyColumn(layer)
             key = self.mapDBInfo.GetKeyColumn(layer)
             columns = self.mapDBInfo.GetTableDesc(table)
             columns = self.mapDBInfo.GetTableDesc(table)
-            for idx in range(len(columns[key]['values'])):  # for each category
+            for idx in range(len(columns[key]["values"])):  # for each category
                 updatedColumns = []
                 updatedColumns = []
                 updatedValues = []
                 updatedValues = []
                 for name in columns.keys():
                 for name in columns.keys():
                     if name == key:
                     if name == key:
-                        cat = columns[name]['values'][idx]
+                        cat = columns[name]["values"][idx]
                         continue
                         continue
-                    ctype = columns[name]['ctype']
-                    value = columns[name]['values'][idx]
-                    id = columns[name]['ids'][idx]
+                    ctype = columns[name]["ctype"]
+                    value = columns[name]["values"][idx]
+                    id = columns[name]["ids"][idx]
                     try:
                     try:
                         newvalue = self.FindWindowById(id).GetValue()
                         newvalue = self.FindWindowById(id).GetValue()
                     except:
                     except:
@@ -231,27 +238,34 @@ class DisplayAttributesDialog(wx.Dialog):
                         except ValueError:
                         except ValueError:
                             GError(
                             GError(
                                 parent=self,
                                 parent=self,
-                                message=_("Column <%(col)s>: Value '%(value)s' needs to be entered as %(type)s.") % {
-                                    'col': name,
-                                    'value': str(newvalue),
-                                    'type': columns[name]['type'].lower()},
-                                showTraceback=False)
+                                message=_(
+                                    "Column <%(col)s>: Value '%(value)s' needs to be entered as %(type)s."
+                                )
+                                % {
+                                    "col": name,
+                                    "value": str(newvalue),
+                                    "type": columns[name]["type"].lower(),
+                                },
+                                showTraceback=False,
+                            )
                             sqlCommands.append(None)
                             sqlCommands.append(None)
                             continue
                             continue
                     else:
                     else:
-                        if self.action == 'add':
+                        if self.action == "add":
                             continue
                             continue
 
 
                     if newvalue != value:
                     if newvalue != value:
                         updatedColumns.append(name)
                         updatedColumns.append(name)
-                        if newvalue == '':
-                            updatedValues.append('NULL')
+                        if newvalue == "":
+                            updatedValues.append("NULL")
                         else:
                         else:
                             if ctype != str:
                             if ctype != str:
                                 updatedValues.append(str(newvalue))
                                 updatedValues.append(str(newvalue))
                             else:
                             else:
-                                updatedValues.append("'" + newvalue.replace("'", "''") + "'")
-                        columns[name]['values'][idx] = newvalue
+                                updatedValues.append(
+                                    "'" + newvalue.replace("'", "''") + "'"
+                                )
+                        columns[name]["values"][idx] = newvalue
 
 
                 if self.action != "add" and len(updatedValues) == 0:
                 if self.action != "add" and len(updatedValues) == 0:
                     continue
                     continue
@@ -282,9 +296,7 @@ class DisplayAttributesDialog(wx.Dialog):
             # for each category
             # for each category
         # for each layer END
         # for each layer END
 
 
-        Debug.msg(
-            3, "DisplayAttributesDialog.GetSQLString(): %s" %
-            sqlCommands)
+        Debug.msg(3, "DisplayAttributesDialog.GetSQLString(): %s" % sqlCommands)
 
 
         return sqlCommands
         return sqlCommands
 
 
@@ -294,14 +306,14 @@ class DisplayAttributesDialog(wx.Dialog):
             table = self.mapDBInfo.layers[layer]["table"]
             table = self.mapDBInfo.layers[layer]["table"]
             key = self.mapDBInfo.layers[layer]["key"]
             key = self.mapDBInfo.layers[layer]["key"]
             columns = self.mapDBInfo.tables[table]
             columns = self.mapDBInfo.tables[table]
-            for idx in range(len(columns[key]['values'])):
+            for idx in range(len(columns[key]["values"])):
                 for name in columns.keys():
                 for name in columns.keys():
-                    type = columns[name]['type']
-                    value = columns[name]['values'][idx]
+                    type = columns[name]["type"]
+                    value = columns[name]["values"][idx]
                     if value is None:
                     if value is None:
-                        value = ''
+                        value = ""
                     try:
                     try:
-                        id = columns[name]['ids'][idx]
+                        id = columns[name]["ids"][idx]
                     except IndexError:
                     except IndexError:
                         id = wx.NOT_FOUND
                         id = wx.NOT_FOUND
 
 
@@ -309,10 +321,9 @@ class DisplayAttributesDialog(wx.Dialog):
                         self.FindWindowById(id).SetValue(str(value))
                         self.FindWindowById(id).SetValue(str(value))
 
 
     def OnClose(self, event):
     def OnClose(self, event):
-        """Closes dialog and removes query layer.
-        """
+        """Closes dialog and removes query layer."""
         frame = self.parent.parent
         frame = self.parent.parent
-        frame.dialogs['attributes'] = None
+        frame.dialogs["attributes"] = None
         if hasattr(self, "digit"):
         if hasattr(self, "digit"):
             self.parent.digit.GetDisplay().SetSelected([])
             self.parent.digit.GetDisplay().SetSelected([])
             if frame.IsAutoRendered():
             if frame.IsAutoRendered():
@@ -339,13 +350,15 @@ class DisplayAttributesDialog(wx.Dialog):
 
 
             driver, database = self.mapDBInfo.GetDbSettings(layer)
             driver, database = self.mapDBInfo.GetDbSettings(layer)
             Debug.msg(1, "SQL: %s" % sql)
             Debug.msg(1, "SQL: %s" % sql)
-            RunCommand('db.execute',
-                       parent=self,
-                       quiet=True,
-                       input='-',
-                       stdin=sql,
-                       driver=driver,
-                       database=database)
+            RunCommand(
+                "db.execute",
+                parent=self,
+                quiet=True,
+                input="-",
+                stdin=sql,
+                driver=driver,
+                database=database,
+            )
 
 
             layer += 1
             layer += 1
 
 
@@ -370,8 +383,7 @@ class DisplayAttributesDialog(wx.Dialog):
         """Get selected feature id"""
         """Get selected feature id"""
         return self.fid
         return self.fid
 
 
-    def UpdateDialog(self, map=None, query=None, cats=None, fid=-1,
-                     action=None):
+    def UpdateDialog(self, map=None, query=None, cats=None, fid=-1, action=None):
         """Update dialog
         """Update dialog
 
 
         :param map: name of vector map
         :param map: name of vector map
@@ -385,7 +397,7 @@ class DisplayAttributesDialog(wx.Dialog):
         """
         """
         if action:
         if action:
             self.action = action
             self.action = action
-            if action == 'display':
+            if action == "display":
                 enabled = False
                 enabled = False
             else:
             else:
                 enabled = True
                 enabled = True
@@ -406,22 +418,21 @@ class DisplayAttributesDialog(wx.Dialog):
 
 
         # id of selected line
         # id of selected line
         if query:  # select by position
         if query:  # select by position
-            data = self.mapDBInfo.SelectByPoint(query[0],
-                                                query[1])
+            data = self.mapDBInfo.SelectByPoint(query[0], query[1])
             self.cats = {}
             self.cats = {}
-            if data and 'Layer' in data:
+            if data and "Layer" in data:
                 idx = 0
                 idx = 0
-                for layer in data['Layer']:
+                for layer in data["Layer"]:
                     layer = int(layer)
                     layer = int(layer)
-                    if data['Id'][idx] is not None:
-                        tfid = int(data['Id'][idx])
+                    if data["Id"][idx] is not None:
+                        tfid = int(data["Id"][idx])
                     else:
                     else:
                         tfid = 0  # Area / Volume
                         tfid = 0  # Area / Volume
                     if tfid not in self.cats:
                     if tfid not in self.cats:
                         self.cats[tfid] = {}
                         self.cats[tfid] = {}
                     if layer not in self.cats[tfid]:
                     if layer not in self.cats[tfid]:
                         self.cats[tfid][layer] = []
                         self.cats[tfid][layer] = []
-                    cat = int(data['Category'][idx])
+                    cat = int(data["Category"][idx])
                     self.cats[tfid][layer].append(cat)
                     self.cats[tfid][layer].append(cat)
                     idx += 1
                     idx += 1
         else:
         else:
@@ -458,8 +469,9 @@ class DisplayAttributesDialog(wx.Dialog):
                 if self.fid > 0 and layer in self.cats[self.fid]:
                 if self.fid > 0 and layer in self.cats[self.fid]:
                     for cat in self.cats[self.fid][layer]:
                     for cat in self.cats[self.fid][layer]:
                         nselected = self.mapDBInfo.SelectFromTable(
                         nselected = self.mapDBInfo.SelectFromTable(
-                            layer, where="%s=%d" %
-                            (self.mapDBInfo.layers[layer]['key'], cat))
+                            layer,
+                            where="%s=%d" % (self.mapDBInfo.layers[layer]["key"], cat),
+                        )
                 else:
                 else:
                     nselected = 0
                     nselected = 0
 
 
@@ -475,11 +487,13 @@ class DisplayAttributesDialog(wx.Dialog):
                         for name in columns.keys():
                         for name in columns.keys():
                             if name == key:
                             if name == key:
                                 for cat in self.cats[self.fid][layer]:
                                 for cat in self.cats[self.fid][layer]:
-                                    self.mapDBInfo.tables[table][
-                                        name]['values'].append(cat)
+                                    self.mapDBInfo.tables[table][name]["values"].append(
+                                        cat
+                                    )
                             else:
                             else:
-                                self.mapDBInfo.tables[table][
-                                    name]['values'].append(None)
+                                self.mapDBInfo.tables[table][name]["values"].append(
+                                    None
+                                )
                 else:  # change status 'add' -> 'update'
                 else:  # change status 'add' -> 'update'
                     self.action = "update"
                     self.action = "update"
 
 
@@ -487,21 +501,23 @@ class DisplayAttributesDialog(wx.Dialog):
             key = self.mapDBInfo.layers[layer]["key"]
             key = self.mapDBInfo.layers[layer]["key"]
             columns = self.mapDBInfo.tables[table]
             columns = self.mapDBInfo.tables[table]
 
 
-            for idx in range(len(columns[key]['values'])):
+            for idx in range(len(columns[key]["values"])):
                 for name in columns.keys():
                 for name in columns.keys():
                     if name == key:
                     if name == key:
-                        cat = int(columns[name]['values'][idx])
+                        cat = int(columns[name]["values"][idx])
                         break
                         break
 
 
                 # use scrolled panel instead (and fix initial max height of the
                 # use scrolled panel instead (and fix initial max height of the
                 # window to 480px)
                 # window to 480px)
                 panel = scrolled.ScrolledPanel(
                 panel = scrolled.ScrolledPanel(
-                    parent=self.notebook, id=wx.ID_ANY, size=(-1, 150))
+                    parent=self.notebook, id=wx.ID_ANY, size=(-1, 150)
+                )
                 panel.SetupScrolling(scroll_x=False)
                 panel.SetupScrolling(scroll_x=False)
 
 
                 self.notebook.AddPage(
                 self.notebook.AddPage(
-                    page=panel, text=" %s %d / %s %d" %
-                    (_("Layer"), layer, _("Category"), cat))
+                    page=panel,
+                    text=" %s %d / %s %d" % (_("Layer"), layer, _("Category"), cat),
+                )
 
 
                 # notebook body
                 # notebook body
                 border = wx.BoxSizer(wx.VERTICAL)
                 border = wx.BoxSizer(wx.VERTICAL)
@@ -509,31 +525,30 @@ class DisplayAttributesDialog(wx.Dialog):
                 flexSizer = wx.FlexGridSizer(cols=3, hgap=3, vgap=3)
                 flexSizer = wx.FlexGridSizer(cols=3, hgap=3, vgap=3)
                 flexSizer.AddGrowableCol(2)
                 flexSizer.AddGrowableCol(2)
                 # columns (sorted by index)
                 # columns (sorted by index)
-                names = [''] * len(columns.keys())
+                names = [""] * len(columns.keys())
                 for name in columns.keys():
                 for name in columns.keys():
-                    names[columns[name]['index']] = name
+                    names[columns[name]["index"]] = name
 
 
                 for name in names:
                 for name in names:
                     if name == key:  # skip key column (category)
                     if name == key:  # skip key column (category)
                         continue
                         continue
 
 
-                    vtype = columns[name]['type'].lower()
-                    ctype = columns[name]['ctype']
+                    vtype = columns[name]["type"].lower()
+                    ctype = columns[name]["ctype"]
 
 
-                    if columns[name]['values'][idx] is not None:
-                        if not isinstance(columns[name]['ctype'], six.string_types):
-                            value = str(columns[name]['values'][idx])
+                    if columns[name]["values"][idx] is not None:
+                        if not isinstance(columns[name]["ctype"], six.string_types):
+                            value = str(columns[name]["values"][idx])
                         else:
                         else:
-                            value = columns[name]['values'][idx]
+                            value = columns[name]["values"][idx]
                     else:
                     else:
-                        value = ''
-
-                    colName = StaticText(parent=panel, id=wx.ID_ANY,
-                                         label=name)
-                    colType = StaticText(parent=panel, id=wx.ID_ANY,
-                                         label="[%s]:" % vtype)
-                    colValue = TextCtrl(
-                        parent=panel, id=wx.ID_ANY, value=value)
+                        value = ""
+
+                    colName = StaticText(parent=panel, id=wx.ID_ANY, label=name)
+                    colType = StaticText(
+                        parent=panel, id=wx.ID_ANY, label="[%s]:" % vtype
+                    )
+                    colValue = TextCtrl(parent=panel, id=wx.ID_ANY, value=value)
                     colValue.SetName(name)
                     colValue.SetName(name)
                     if ctype == int:
                     if ctype == int:
                         colValue.SetValidator(IntegerValidator())
                         colValue.SetValidator(IntegerValidator())
@@ -541,26 +556,26 @@ class DisplayAttributesDialog(wx.Dialog):
                         colValue.SetValidator(FloatValidator())
                         colValue.SetValidator(FloatValidator())
 
 
                     self.Bind(wx.EVT_TEXT, self.OnSQLStatement, colValue)
                     self.Bind(wx.EVT_TEXT, self.OnSQLStatement, colValue)
-                    if self.action == 'display':
+                    if self.action == "display":
                         colValue.SetWindowStyle(wx.TE_READONLY)
                         colValue.SetWindowStyle(wx.TE_READONLY)
 
 
-                    flexSizer.Add(colName, proportion=0,
-                                  flag=wx.ALIGN_CENTER_VERTICAL)
+                    flexSizer.Add(colName, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
                     flexSizer.Add(
                     flexSizer.Add(
                         colType,
                         colType,
                         proportion=0,
                         proportion=0,
-                        flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
-                    flexSizer.Add(colValue, proportion=1,
-                                  flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)
+                        flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT,
+                    )
+                    flexSizer.Add(
+                        colValue,
+                        proportion=1,
+                        flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL,
+                    )
                     # add widget reference to self.columns
                     # add widget reference to self.columns
-                    columns[name]['ids'].append(
-                        colValue.GetId())  # name, type, values, id
+                    columns[name]["ids"].append(
+                        colValue.GetId()
+                    )  # name, type, values, id
                 # for each attribute (including category) END
                 # for each attribute (including category) END
-                border.Add(
-                    flexSizer,
-                    proportion=1,
-                    flag=wx.ALL | wx.EXPAND,
-                    border=5)
+                border.Add(flexSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=5)
                 panel.SetSizer(border)
                 panel.SetSizer(border)
             # for each category END
             # for each category END
         # for each layer END
         # for each layer END
@@ -585,14 +600,22 @@ class DisplayAttributesDialog(wx.Dialog):
 
 
         for key, col in six.iteritems(columns):
         for key, col in six.iteritems(columns):
             if key == column:
             if key == column:
-                col['values'] = [col['ctype'](value), ]
+                col["values"] = [
+                    col["ctype"](value),
+                ]
                 break
                 break
 
 
 
 
 class ModifyTableRecord(wx.Dialog):
 class ModifyTableRecord(wx.Dialog):
-
-    def __init__(self, parent, title, data, keyEditable=(-1, True),
-                 id=wx.ID_ANY, style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
+    def __init__(
+        self,
+        parent,
+        title,
+        data,
+        keyEditable=(-1, True),
+        id=wx.ID_ANY,
+        style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
+    ):
         """Dialog for inserting/updating table record
         """Dialog for inserting/updating table record
 
 
         :param data: a list: [(column, value)]
         :param data: a list: [(column, value)]
@@ -608,8 +631,9 @@ class ModifyTableRecord(wx.Dialog):
 
 
         box = StaticBox(parent=self, id=wx.ID_ANY)
         box = StaticBox(parent=self, id=wx.ID_ANY)
         box.Hide()
         box.Hide()
-        self.dataPanel = scrolled.ScrolledPanel(parent=self, id=wx.ID_ANY,
-                                                style=wx.TAB_TRAVERSAL)
+        self.dataPanel = scrolled.ScrolledPanel(
+            parent=self, id=wx.ID_ANY, style=wx.TAB_TRAVERSAL
+        )
         self.dataPanel.SetupScrolling(scroll_x=False)
         self.dataPanel.SetupScrolling(scroll_x=False)
 
 
         # buttons
         # buttons
@@ -636,11 +660,17 @@ class ModifyTableRecord(wx.Dialog):
                     continue
                     continue
                 else:
                 else:
                     valueWin = SpinCtrl(
                     valueWin = SpinCtrl(
-                        parent=self.dataPanel, id=wx.ID_ANY, value=value,
-                        min=-1e9, max=1e9, size=(250, -1))
+                        parent=self.dataPanel,
+                        id=wx.ID_ANY,
+                        value=value,
+                        min=-1e9,
+                        max=1e9,
+                        size=(250, -1),
+                    )
             else:
             else:
-                valueWin = TextCtrl(parent=self.dataPanel, id=wx.ID_ANY,
-                                    value=value, size=(250, -1))
+                valueWin = TextCtrl(
+                    parent=self.dataPanel, id=wx.ID_ANY, value=value, size=(250, -1)
+                )
                 if ctype == int:
                 if ctype == int:
                     valueWin.SetValidator(IntegerValidator())
                     valueWin.SetValidator(IntegerValidator())
                 elif ctype == float:
                 elif ctype == float:
@@ -649,12 +679,11 @@ class ModifyTableRecord(wx.Dialog):
                     wx.CallAfter(valueWin.SetFocus)
                     wx.CallAfter(valueWin.SetFocus)
                     winFocus = True
                     winFocus = True
 
 
-            label = StaticText(parent=self.dataPanel, id=wx.ID_ANY,
-                               label=column)
-            ctype = StaticText(parent=self.dataPanel, id=wx.ID_ANY,
-                               label="[%s]:" % ctypeStr.lower())
-            self.widgets.append(
-                (label.GetId(), ctype.GetId(), valueWin.GetId()))
+            label = StaticText(parent=self.dataPanel, id=wx.ID_ANY, label=column)
+            ctype = StaticText(
+                parent=self.dataPanel, id=wx.ID_ANY, label="[%s]:" % ctypeStr.lower()
+            )
+            self.widgets.append((label.GetId(), ctype.GetId(), valueWin.GetId()))
 
 
             cId += 1
             cId += 1
 
 
@@ -673,20 +702,22 @@ class ModifyTableRecord(wx.Dialog):
             ctype = self.FindWindowById(ctypeId)
             ctype = self.FindWindowById(ctypeId)
             value = self.FindWindowById(valueId)
             value = self.FindWindowById(valueId)
 
 
-            dataSizer.Add(label, proportion=0,
-                          flag=wx.ALIGN_CENTER_VERTICAL)
-            dataSizer.Add(ctype, proportion=0,
-                          flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT)
-            dataSizer.Add(value, proportion=0,
-                          flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)
+            dataSizer.Add(label, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
+            dataSizer.Add(
+                ctype, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT
+            )
+            dataSizer.Add(
+                value, proportion=0, flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL
+            )
 
 
         self.dataPanel.SetAutoLayout(True)
         self.dataPanel.SetAutoLayout(True)
         self.dataPanel.SetSizer(dataSizer)
         self.dataPanel.SetSizer(dataSizer)
         dataSizer.Fit(self.dataPanel)
         dataSizer.Fit(self.dataPanel)
 
 
         if self.usebox:
         if self.usebox:
-            self.boxSizer.Add(self.dataPanel, proportion=1,
-                              flag=wx.EXPAND | wx.ALL, border=5)
+            self.boxSizer.Add(
+                self.dataPanel, proportion=1, flag=wx.EXPAND | wx.ALL, border=5
+            )
 
 
         # buttons
         # buttons
         btnSizer = wx.StdDialogButtonSizer()
         btnSizer = wx.StdDialogButtonSizer()
@@ -695,14 +726,11 @@ class ModifyTableRecord(wx.Dialog):
         btnSizer.Realize()
         btnSizer.Realize()
 
 
         if not self.usebox:
         if not self.usebox:
-            sizer.Add(self.dataPanel, proportion=1,
-                      flag=wx.EXPAND | wx.ALL, border=5)
+            sizer.Add(self.dataPanel, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
         else:
         else:
-            sizer.Add(self.boxSizer, proportion=1,
-                      flag=wx.EXPAND | wx.ALL, border=5)
+            sizer.Add(self.boxSizer, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
 
 
-        sizer.Add(btnSizer, proportion=0,
-                  flag=wx.EXPAND | wx.ALL, border=5)
+        sizer.Add(btnSizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
 
 
         framewidth = self.GetBestSize()[0] + 25
         framewidth = self.GetBestSize()[0] + 25
         self.SetMinSize((framewidth, 250))
         self.SetMinSize((framewidth, 250))
@@ -722,8 +750,7 @@ class ModifyTableRecord(wx.Dialog):
         for labelId, ctypeId, valueId in self.widgets:
         for labelId, ctypeId, valueId in self.widgets:
             column = self.FindWindowById(labelId).GetLabel()
             column = self.FindWindowById(labelId).GetLabel()
             if columns is None or column in columns:
             if columns is None or column in columns:
-                value = GetUnicodeValue(
-                    self.FindWindowById(valueId).GetValue())
+                value = GetUnicodeValue(self.FindWindowById(valueId).GetValue())
                 valueList.append(value)
                 valueList.append(value)
 
 
         # add key value
         # add key value
@@ -734,32 +761,37 @@ class ModifyTableRecord(wx.Dialog):
 
 
 
 
 class AddColumnDialog(wx.Dialog):
 class AddColumnDialog(wx.Dialog):
-
-    def __init__(self, parent, title, id=wx.ID_ANY,
-                 style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
-        """Dialog for adding column into table
-        """
+    def __init__(
+        self,
+        parent,
+        title,
+        id=wx.ID_ANY,
+        style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
+    ):
+        """Dialog for adding column into table"""
         wx.Dialog.__init__(self, parent, id, title, style=style)
         wx.Dialog.__init__(self, parent, id, title, style=style)
 
 
         self.CenterOnParent()
         self.CenterOnParent()
 
 
         self.data = {}
         self.data = {}
-        self.data['addColName'] = TextCtrl(
-            parent=self, id=wx.ID_ANY, value='', size=(
-                150, -1), style=wx.TE_PROCESS_ENTER)
-
-        self.data['addColType'] = wx.Choice(parent=self, id=wx.ID_ANY,
-                                            choices=["integer",
-                                                     "double",
-                                                     "varchar",
-                                                     "date"])  # FIXME
-        self.data['addColType'].SetSelection(0)
-        self.data['addColType'].Bind(wx.EVT_CHOICE, self.OnTableChangeType)
-
-        self.data['addColLength'] = SpinCtrl(
-            parent=self, id=wx.ID_ANY, size=(
-                65, -1), initial=250, min=1, max=1e6)
-        self.data['addColLength'].Enable(False)
+        self.data["addColName"] = TextCtrl(
+            parent=self,
+            id=wx.ID_ANY,
+            value="",
+            size=(150, -1),
+            style=wx.TE_PROCESS_ENTER,
+        )
+
+        self.data["addColType"] = wx.Choice(
+            parent=self, id=wx.ID_ANY, choices=["integer", "double", "varchar", "date"]
+        )  # FIXME
+        self.data["addColType"].SetSelection(0)
+        self.data["addColType"].Bind(wx.EVT_CHOICE, self.OnTableChangeType)
+
+        self.data["addColLength"] = SpinCtrl(
+            parent=self, id=wx.ID_ANY, size=(65, -1), initial=250, min=1, max=1e6
+        )
+        self.data["addColLength"].Enable(False)
 
 
         # buttons
         # buttons
         self.btnCancel = Button(self, wx.ID_CANCEL)
         self.btnCancel = Button(self, wx.ID_CANCEL)
@@ -774,48 +806,47 @@ class AddColumnDialog(wx.Dialog):
         addSizer = wx.BoxSizer(wx.HORIZONTAL)
         addSizer = wx.BoxSizer(wx.HORIZONTAL)
 
 
         addSizer.Add(
         addSizer.Add(
-            StaticText(
-                parent=self,
-                id=wx.ID_ANY,
-                label=_("Column")),
+            StaticText(parent=self, id=wx.ID_ANY, label=_("Column")),
+            flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
+            border=5,
+        )
+        addSizer.Add(
+            self.data["addColName"],
+            proportion=1,
             flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
             flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
-            border=5)
-        addSizer.Add(self.data['addColName'], proportion=1,
-                     flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
-                     border=5)
+            border=5,
+        )
 
 
         addSizer.Add(
         addSizer.Add(
-            StaticText(
-                parent=self,
-                id=wx.ID_ANY,
-                label=_("Type")),
+            StaticText(parent=self, id=wx.ID_ANY, label=_("Type")),
             flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
             flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
-            border=5)
-        addSizer.Add(self.data['addColType'],
-                     flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
-                     border=5)
+            border=5,
+        )
+        addSizer.Add(
+            self.data["addColType"],
+            flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
+            border=5,
+        )
 
 
         addSizer.Add(
         addSizer.Add(
-            StaticText(
-                parent=self,
-                id=wx.ID_ANY,
-                label=_("Length")),
+            StaticText(parent=self, id=wx.ID_ANY, label=_("Length")),
+            flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
+            border=5,
+        )
+        addSizer.Add(
+            self.data["addColLength"],
             flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
             flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
-            border=5)
-        addSizer.Add(self.data['addColLength'],
-                     flag=wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT,
-                     border=5)
+            border=5,
+        )
 
 
-        sizer.Add(addSizer, proportion=0,
-                  flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
+        sizer.Add(addSizer, proportion=0, flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
 
 
         btnSizer = wx.StdDialogButtonSizer()
         btnSizer = wx.StdDialogButtonSizer()
         btnSizer.AddButton(self.btnCancel)
         btnSizer.AddButton(self.btnCancel)
         btnSizer.AddButton(self.btnOk)
         btnSizer.AddButton(self.btnOk)
         btnSizer.Realize()
         btnSizer.Realize()
 
 
-        sizer.Add(btnSizer, proportion=0,
-                  flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
+        sizer.Add(btnSizer, proportion=0, flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
 
 
         self.SetSizer(sizer)
         self.SetSizer(sizer)
 
 
@@ -824,9 +855,9 @@ class AddColumnDialog(wx.Dialog):
     def GetData(self):
     def GetData(self):
         """Get inserted data from dialog's widgets"""
         """Get inserted data from dialog's widgets"""
         values = {}
         values = {}
-        values['name'] = self.data['addColName'].GetValue()
-        values['ctype'] = self.data['addColType'].GetStringSelection()
-        values['length'] = int(self.data['addColLength'].GetValue())
+        values["name"] = self.data["addColName"].GetValue()
+        values["ctype"] = self.data["addColType"].GetStringSelection()
+        values["length"] = int(self.data["addColLength"].GetValue())
 
 
         return values
         return values
 
 
@@ -834,6 +865,6 @@ class AddColumnDialog(wx.Dialog):
         """Data type for new column changed. Enable or disable
         """Data type for new column changed. Enable or disable
         data length widget"""
         data length widget"""
         if event.GetString() == "varchar":
         if event.GetString() == "varchar":
-            self.data['addColLength'].Enable(True)
+            self.data["addColLength"].Enable(True)
         else:
         else:
-            self.data['addColLength'].Enable(False)
+            self.data["addColLength"].Enable(False)

+ 5 - 5
gui/wxpython/dbmgr/g.gui.dbmgr.py

@@ -37,19 +37,18 @@ def main():
     import wx
     import wx
 
 
     from grass.script.setup import set_gui_path
     from grass.script.setup import set_gui_path
+
     set_gui_path()
     set_gui_path()
 
 
     from dbmgr.manager import AttributeManager
     from dbmgr.manager import AttributeManager
 
 
-    mapName = gscript.find_file(options['map'], element='vector')['fullname']
+    mapName = gscript.find_file(options["map"], element="vector")["fullname"]
     if not mapName:
     if not mapName:
         gscript.set_raise_on_error(False)
         gscript.set_raise_on_error(False)
-        gscript.fatal(_("Vector map <%s> not found") % options['map'])
+        gscript.fatal(_("Vector map <%s> not found") % options["map"])
 
 
     app = wx.App()
     app = wx.App()
-    gscript.message(
-        _("Loading attribute data for vector map <%s>...") %
-        mapName)
+    gscript.message(_("Loading attribute data for vector map <%s>...") % mapName)
     f = AttributeManager(
     f = AttributeManager(
         parent=None,
         parent=None,
         id=wx.ID_ANY,
         id=wx.ID_ANY,
@@ -61,5 +60,6 @@ def main():
 
 
     app.MainLoop()
     app.MainLoop()
 
 
+
 if __name__ == "__main__":
 if __name__ == "__main__":
     main()
     main()

+ 68 - 60
gui/wxpython/dbmgr/manager.py

@@ -26,10 +26,11 @@ import os
 
 
 import wx
 import wx
 from core import globalvar
 from core import globalvar
+
 if globalvar.wxPythonPhoenix:
 if globalvar.wxPythonPhoenix:
     try:
     try:
         import agw.flatnotebook as FN
         import agw.flatnotebook as FN
-    except ImportError: # if it's not there locally, try the wxPython lib.
+    except ImportError:  # if it's not there locally, try the wxPython lib.
         import wx.lib.agw.flatnotebook as FN
         import wx.lib.agw.flatnotebook as FN
 else:
 else:
     import wx.lib.flatnotebook as FN
     import wx.lib.flatnotebook as FN
@@ -41,12 +42,18 @@ from gui_core.wrap import Button, ClearButton, CloseButton
 
 
 
 
 class AttributeManager(wx.Frame, DbMgrBase):
 class AttributeManager(wx.Frame, DbMgrBase):
-
-    def __init__(self, parent, id=wx.ID_ANY,
-                 title=None,
-                 base_title=None,
-                 vectorName=None, item=None, log=None,
-                 selection=None, **kwargs):
+    def __init__(
+        self,
+        parent,
+        id=wx.ID_ANY,
+        title=None,
+        base_title=None,
+        vectorName=None,
+        item=None,
+        log=None,
+        selection=None,
+        **kwargs,
+    ):
         """GRASS Attribute Table Manager window
         """GRASS Attribute Table Manager window
 
 
         :param parent: parent window
         :param parent: parent window
@@ -65,10 +72,16 @@ class AttributeManager(wx.Frame, DbMgrBase):
         except:
         except:
             mapdisplay = None
             mapdisplay = None
 
 
-        DbMgrBase.__init__(self, id=id, mapdisplay=mapdisplay,
-                           vectorName=vectorName, item=item,
-                           log=log, statusbar=self,
-                           **kwargs)
+        DbMgrBase.__init__(
+            self,
+            id=id,
+            mapdisplay=mapdisplay,
+            vectorName=vectorName,
+            item=item,
+            log=log,
+            statusbar=self,
+            **kwargs,
+        )
 
 
         wx.Frame.__init__(self, parent, id, *kwargs)
         wx.Frame.__init__(self, parent, id, *kwargs)
 
 
@@ -76,8 +89,8 @@ class AttributeManager(wx.Frame, DbMgrBase):
         if not title:
         if not title:
             if not base_title:
             if not base_title:
                 base_title = _("Attribute Table Manager")
                 base_title = _("Attribute Table Manager")
-            document = self.dbMgrData['vectName']
-            if not self.dbMgrData['editable']:
+            document = self.dbMgrData["vectName"]
+            if not self.dbMgrData["editable"]:
                 document = _("{document} (read-only)").format(document=document)
                 document = _("{document} (read-only)").format(document=document)
             title = "{document} - {tool_name}".format(
             title = "{document} - {tool_name}".format(
                 document=document, tool_name=base_title
                 document=document, tool_name=base_title
@@ -87,48 +100,50 @@ class AttributeManager(wx.Frame, DbMgrBase):
         # icon
         # icon
         self.SetIcon(
         self.SetIcon(
             wx.Icon(
             wx.Icon(
-                os.path.join(
-                    globalvar.ICONDIR,
-                    'grass_sql.ico'),
-                wx.BITMAP_TYPE_ICO))
+                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:
+        if len(self.dbMgrData["mapDBInfo"].layers.keys()) == 0:
             GMessage(
             GMessage(
-                parent=self.parent, message=_(
+                parent=self.parent,
+                message=_(
                     "Database connection for vector map <%s> "
                     "Database connection for vector map <%s> "
                     "is not defined in DB file. "
                     "is not defined in DB file. "
                     "You can define new connection in "
                     "You can define new connection in "
-                    "'Manage layers' tab.") %
-                self.dbMgrData['vectName'])
+                    "'Manage layers' tab."
+                )
+                % self.dbMgrData["vectName"],
+            )
 
 
-        busy = wx.BusyInfo(_("Please wait, loading attribute data..."),
-                           parent=self.parent)
+        busy = wx.BusyInfo(
+            _("Please wait, loading attribute data..."), parent=self.parent
+        )
         wx.SafeYield()
         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.pages['browse'].SetTabAreaColour(globalvar.FNPageColor)
+        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(
         self.notebook.AddPage(
-            page=self.pages['manageTable'],
-            text=_("Manage tables"),
-            name='table')
-        self.pages['manageTable'].SetTabAreaColour(globalvar.FNPageColor)
+            page=self.pages["manageTable"], text=_("Manage tables"), name="table"
+        )
+        self.pages["manageTable"].SetTabAreaColour(globalvar.FNPageColor)
 
 
-        self.CreateDbMgrPage(parent=self, pageName='manageLayer')
+        self.CreateDbMgrPage(parent=self, pageName="manageLayer")
         self.notebook.AddPage(
         self.notebook.AddPage(
-            page=self.pages['manageLayer'],
-            text=_("Manage layers"),
-            name='layers')
+            page=self.pages["manageLayer"], text=_("Manage layers"), name="layers"
+        )
         del busy
         del busy
 
 
         if selection:
         if selection:
@@ -140,11 +155,11 @@ class AttributeManager(wx.Frame, DbMgrBase):
         self.btnClose = CloseButton(parent=self.panel)
         self.btnClose = CloseButton(parent=self.panel)
         self.btnClose.SetToolTip(_("Close Attribute Table Manager"))
         self.btnClose.SetToolTip(_("Close Attribute Table Manager"))
         self.btnReload = Button(parent=self.panel, id=wx.ID_REFRESH)
         self.btnReload = Button(parent=self.panel, id=wx.ID_REFRESH)
-        self.btnReload.SetToolTip(
-            _("Reload currently selected attribute data"))
+        self.btnReload.SetToolTip(_("Reload currently selected attribute data"))
         self.btnReset = ClearButton(parent=self.panel)
         self.btnReset = ClearButton(parent=self.panel)
         self.btnReset.SetToolTip(
         self.btnReset.SetToolTip(
-            _("Reload all attribute data (drop current selection)"))
+            _("Reload all attribute data (drop current selection)")
+        )
 
 
         # bind closing to ESC
         # bind closing to ESC
         self.Bind(wx.EVT_MENU, self.OnCloseWindow, id=wx.ID_CANCEL)
         self.Bind(wx.EVT_MENU, self.OnCloseWindow, id=wx.ID_CANCEL)
@@ -156,9 +171,7 @@ class AttributeManager(wx.Frame, DbMgrBase):
         self.btnClose.Bind(wx.EVT_BUTTON, self.OnCloseWindow)
         self.btnClose.Bind(wx.EVT_BUTTON, self.OnCloseWindow)
         self.btnReload.Bind(wx.EVT_BUTTON, self.OnReloadData)
         self.btnReload.Bind(wx.EVT_BUTTON, self.OnReloadData)
         self.btnReset.Bind(wx.EVT_BUTTON, self.OnReloadDataAll)
         self.btnReset.Bind(wx.EVT_BUTTON, self.OnReloadDataAll)
-        self.notebook.Bind(
-            FN.EVT_FLATNOTEBOOK_PAGE_CHANGED,
-            self.OnPageChanged)
+        self.notebook.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
         self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
         self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
 
 
         # do layout
         # do layout
@@ -175,12 +188,9 @@ class AttributeManager(wx.Frame, DbMgrBase):
 
 
         # buttons
         # buttons
         btnSizer = wx.BoxSizer(wx.HORIZONTAL)
         btnSizer = wx.BoxSizer(wx.HORIZONTAL)
-        btnSizer.Add(self.btnReset, proportion=1,
-                     flag=wx.ALL, border=5)
-        btnSizer.Add(self.btnReload, proportion=1,
-                     flag=wx.ALL, border=5)
-        btnSizer.Add(self.btnClose, proportion=1,
-                     flag=wx.ALL, border=5)
+        btnSizer.Add(self.btnReset, proportion=1, flag=wx.ALL, border=5)
+        btnSizer.Add(self.btnReload, proportion=1, flag=wx.ALL, border=5)
+        btnSizer.Add(self.btnClose, proportion=1, flag=wx.ALL, border=5)
 
 
         mainSizer.Add(self.notebook, proportion=1, flag=wx.EXPAND)
         mainSizer.Add(self.notebook, proportion=1, flag=wx.EXPAND)
         mainSizer.Add(btnSizer, flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
         mainSizer.Add(btnSizer, flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
@@ -192,9 +202,9 @@ class AttributeManager(wx.Frame, DbMgrBase):
 
 
     def OnCloseWindow(self, event):
     def OnCloseWindow(self, event):
         """Cancel button pressed"""
         """Cancel button pressed"""
-        if self.parent and self.parent.GetName() == 'LayerManager':
+        if self.parent and self.parent.GetName() == "LayerManager":
             # deregister ATM
             # deregister ATM
-            self.parent.dialogs['atm'].remove(self)
+            self.parent.dialogs["atm"].remove(self)
 
 
         if not isinstance(event, wx.CloseEvent):
         if not isinstance(event, wx.CloseEvent):
             self.Destroy()
             self.Destroy()
@@ -203,31 +213,29 @@ class AttributeManager(wx.Frame, DbMgrBase):
 
 
     def OnReloadData(self, event):
     def OnReloadData(self, event):
         """Reload data"""
         """Reload data"""
-        if self.pages['browse']:
-            self.pages['browse'].OnDataReload(event)  # TODO replace by signal
+        if self.pages["browse"]:
+            self.pages["browse"].OnDataReload(event)  # TODO replace by signal
 
 
     def OnReloadDataAll(self, event):
     def OnReloadDataAll(self, event):
         """Reload all data"""
         """Reload all data"""
-        if self.pages['browse']:
-            self.pages['browse'].ResetPage()
+        if self.pages["browse"]:
+            self.pages["browse"].ResetPage()
 
 
     def OnPageChanged(self, event):
     def OnPageChanged(self, event):
         """On page in ATM is changed"""
         """On page in ATM is changed"""
         try:
         try:
             if self.pages["browse"]:
             if self.pages["browse"]:
                 selPage = self.pages["browse"].selLayer
                 selPage = self.pages["browse"].selLayer
-                id = self.pages["browse"].layerPage[selPage]['data']
+                id = self.pages["browse"].layerPage[selPage]["data"]
             else:
             else:
                 id = None
                 id = None
         except KeyError:
         except KeyError:
             id = None
             id = None
 
 
-        if event.GetSelection() == self.notebook.GetPageIndexByName('browse') and id:
+        if event.GetSelection() == self.notebook.GetPageIndexByName("browse") and id:
             win = self.FindWindowById(id)
             win = self.FindWindowById(id)
             if win:
             if win:
-                self.log.write(
-                    _("Number of loaded records: %d") %
-                    win.GetItemCount())
+                self.log.write(_("Number of loaded records: %d") % win.GetItemCount())
             else:
             else:
                 self.log.write("")
                 self.log.write("")
             self.btnReload.Enable()
             self.btnReload.Enable()
@@ -246,4 +254,4 @@ class AttributeManager(wx.Frame, DbMgrBase):
         """Updates dialog layout for given layer"""
         """Updates dialog layout for given layer"""
         DbMgrBase.UpdateDialog(self, layer=layer)
         DbMgrBase.UpdateDialog(self, layer=layer)
         # set current page selection
         # set current page selection
-        self.notebook.SetSelectionByName('layers')
+        self.notebook.SetSelectionByName("layers")

Plik diff jest za duży
+ 341 - 302
gui/wxpython/dbmgr/sqlbuilder.py


+ 60 - 60
gui/wxpython/dbmgr/vinfo.py

@@ -40,10 +40,13 @@ if sys.version_info.major >= 3:
             return value
             return value
         if isinstance(value, bytes):
         if isinstance(value, bytes):
             enc = GetDbEncoding()
             enc = GetDbEncoding()
-            return str(value, enc, errors='replace')
+            return str(value, enc, errors="replace")
         else:
         else:
             return str(value)
             return str(value)
+
+
 else:
 else:
+
     def GetUnicodeValue(value):
     def GetUnicodeValue(value):
         """Get unicode value
         """Get unicode value
 
 
@@ -54,17 +57,17 @@ else:
         if isinstance(value, unicode):
         if isinstance(value, unicode):
             return value
             return value
         enc = GetDbEncoding()
         enc = GetDbEncoding()
-        return unicode(str(value), enc, errors='replace')
+        return unicode(str(value), enc, errors="replace")
 
 
 
 
 def GetDbEncoding():
 def GetDbEncoding():
     """Checks if user set DB encoding (first user settings,
     """Checks if user set DB encoding (first user settings,
     then env variable), if not assumes unicode."""
     then env variable), if not assumes unicode."""
-    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']
+    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:
     else:
-        enc = 'utf-8'  # assuming UTF-8
+        enc = "utf-8"  # assuming UTF-8
     return enc
     return enc
 
 
 
 
@@ -73,31 +76,24 @@ def CreateDbInfoDesc(panel, mapDBInfo, layer):
     infoFlexSizer = wx.FlexGridSizer(cols=2, hgap=1, vgap=1)
     infoFlexSizer = wx.FlexGridSizer(cols=2, hgap=1, vgap=1)
     infoFlexSizer.AddGrowableCol(1)
     infoFlexSizer.AddGrowableCol(1)
 
 
-    infoFlexSizer.Add(StaticText(parent=panel, id=wx.ID_ANY,
-                                 label="Driver:"))
+    infoFlexSizer.Add(StaticText(parent=panel, id=wx.ID_ANY, label="Driver:"))
     infoFlexSizer.Add(
     infoFlexSizer.Add(
-        StaticText(
-            parent=panel,
-            id=wx.ID_ANY,
-            label=mapDBInfo.layers[layer]['driver']))
-    infoFlexSizer.Add(StaticText(parent=panel, id=wx.ID_ANY,
-                                 label="Database:"))
+        StaticText(parent=panel, id=wx.ID_ANY, label=mapDBInfo.layers[layer]["driver"])
+    )
+    infoFlexSizer.Add(StaticText(parent=panel, id=wx.ID_ANY, label="Database:"))
     infoFlexSizer.Add(
     infoFlexSizer.Add(
         StaticText(
         StaticText(
-            parent=panel,
-            id=wx.ID_ANY,
-            label=mapDBInfo.layers[layer]['database']))
-    infoFlexSizer.Add(StaticText(parent=panel, id=wx.ID_ANY,
-                                 label="Table:"))
+            parent=panel, id=wx.ID_ANY, label=mapDBInfo.layers[layer]["database"]
+        )
+    )
+    infoFlexSizer.Add(StaticText(parent=panel, id=wx.ID_ANY, label="Table:"))
     infoFlexSizer.Add(
     infoFlexSizer.Add(
-        StaticText(
-            parent=panel,
-            id=wx.ID_ANY,
-            label=mapDBInfo.layers[layer]['table']))
-    infoFlexSizer.Add(StaticText(parent=panel, id=wx.ID_ANY,
-                                 label="Key:"))
-    infoFlexSizer.Add(StaticText(parent=panel, id=wx.ID_ANY,
-                                 label=mapDBInfo.layers[layer]['key']))
+        StaticText(parent=panel, id=wx.ID_ANY, label=mapDBInfo.layers[layer]["table"])
+    )
+    infoFlexSizer.Add(StaticText(parent=panel, id=wx.ID_ANY, label="Key:"))
+    infoFlexSizer.Add(
+        StaticText(parent=panel, id=wx.ID_ANY, label=mapDBInfo.layers[layer]["key"])
+    )
 
 
     return infoFlexSizer
     return infoFlexSizer
 
 
@@ -112,12 +108,12 @@ class VectorDBInfo(VectorDBInfoBase):
     def GetColumns(self, table):
     def GetColumns(self, table):
         """Return list of columns names (based on their index)"""
         """Return list of columns names (based on their index)"""
         try:
         try:
-            names = [''] * len(self.tables[table].keys())
+            names = [""] * len(self.tables[table].keys())
         except KeyError:
         except KeyError:
             return []
             return []
 
 
         for name, desc in six.iteritems(self.tables[table]):
         for name, desc in six.iteritems(self.tables[table]):
-            names[desc['index']] = name
+            names[desc["index"]] = name
 
 
         return names
         return names
 
 
@@ -130,51 +126,53 @@ class VectorDBInfo(VectorDBInfoBase):
 
 
         try:
         try:
             data = grass.vector_what(
             data = grass.vector_what(
-                map=self.map, coord=(
-                    float(
-                        queryCoords[0]), float(
-                        queryCoords[1])), distance=float(qdist))
+                map=self.map,
+                coord=(float(queryCoords[0]), float(queryCoords[1])),
+                distance=float(qdist),
+            )
         except grass.ScriptError:
         except grass.ScriptError:
             GError(
             GError(
-                parent=None, message=_(
+                parent=None,
+                message=_(
                     "Failed to query vector map <{map}>. "
                     "Failed to query vector map <{map}>. "
-                    "Check database settings and topology.").format(
-                    map=self.map))
+                    "Check database settings and topology."
+                ).format(map=self.map),
+            )
 
 
-        if len(data) < 1 or all(('Table' not in record) for record in data):
+        if len(data) < 1 or all(("Table" not in record) for record in data):
             return None
             return None
 
 
         # process attributes
         # process attributes
         ret = dict()
         ret = dict()
-        for key in ['Category', 'Layer', 'Table', 'Id']:
+        for key in ["Category", "Layer", "Table", "Id"]:
             ret[key] = list()
             ret[key] = list()
 
 
         for record in data:
         for record in data:
-            if 'Table' not in record:
+            if "Table" not in record:
                 continue
                 continue
 
 
-            table = record['Table']
-            for key, value in six.iteritems(record['Attributes']):
+            table = record["Table"]
+            for key, value in six.iteritems(record["Attributes"]):
                 if len(value) < 1:
                 if len(value) < 1:
                     value = None
                     value = None
                 else:
                 else:
-                    if self.tables[table][key]['ctype'] != str:
-                        value = self.tables[table][key]['ctype'](value)
+                    if self.tables[table][key]["ctype"] != str:
+                        value = self.tables[table][key]["ctype"](value)
                     else:
                     else:
                         value = GetUnicodeValue(value)
                         value = GetUnicodeValue(value)
-                self.tables[table][key]['values'].append(value)
+                self.tables[table][key]["values"].append(value)
 
 
             for key, value in six.iteritems(record):
             for key, value in six.iteritems(record):
-                if key == 'Attributes':
+                if key == "Attributes":
                     continue
                     continue
                 if key in ret:
                 if key in ret:
                     ret[key].append(value)
                     ret[key].append(value)
-            if 'Id' not in record.keys():
-                ret['Id'].append(None)
+            if "Id" not in record.keys():
+                ret["Id"].append(None)
 
 
         return ret
         return ret
 
 
-    def SelectFromTable(self, layer, cols='*', where=None):
+    def SelectFromTable(self, layer, cols="*", where=None):
         """Select records from the table
         """Select records from the table
 
 
         Return number of selected records, -1 on error
         Return number of selected records, -1 on error
@@ -186,32 +184,34 @@ class VectorDBInfo(VectorDBInfoBase):
 
 
         table = self.layers[layer]["table"]  # get table desc
         table = self.layers[layer]["table"]  # get table desc
         # select values (only one record)
         # select values (only one record)
-        if where is None or where == '':
+        if where is None or where == "":
             sql = "SELECT %s FROM %s" % (cols, table)
             sql = "SELECT %s FROM %s" % (cols, table)
         else:
         else:
             sql = "SELECT %s FROM %s WHERE %s" % (cols, table, where)
             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"])
+        ret = RunCommand(
+            "db.select",
+            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)
         # self.tables[table][key][1] = str(cat)
         if ret:
         if ret:
             for line in ret.splitlines():
             for line in ret.splitlines():
-                name, value = line.split('|')
+                name, value = line.split("|")
                 # casting ...
                 # casting ...
                 if value:
                 if value:
-                    if not isinstance('', self.tables[table][name]['ctype']):
-                        value = self.tables[table][name]['ctype'](value)
+                    if not isinstance("", self.tables[table][name]["ctype"]):
+                        value = self.tables[table][name]["ctype"](value)
                     else:
                     else:
                         value = GetUnicodeValue(value)
                         value = GetUnicodeValue(value)
                 else:
                 else:
                     value = None
                     value = None
-                self.tables[table][name]['values'].append(value)
+                self.tables[table][name]["values"].append(value)
                 nselected = 1
                 nselected = 1
 
 
         return nselected
         return nselected

+ 99 - 106
gui/wxpython/docs/wxgui_sphinx/conf.py

@@ -20,16 +20,11 @@ from shutil import copy
 # If extensions (or modules to document with autodoc) are in another directory,
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.
 # documentation root, use os.path.abspath to make it absolute, like shown here.
-if not os.getenv('GISBASE'):
+if not os.getenv("GISBASE"):
     sys.exit("GISBASE not defined")
     sys.exit("GISBASE not defined")
 sys.path.insert(
 sys.path.insert(
-    0,
-    os.path.abspath(
-        os.path.join(
-            os.environ['GISBASE'],
-            'etc',
-            'python',
-            'grass')))
+    0, os.path.abspath(os.path.join(os.environ["GISBASE"], "etc", "python", "grass"))
+)
 
 
 from grass.script import core
 from grass.script import core
 
 
@@ -39,165 +34,163 @@ footer_tmpl = string.Template(
 <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><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="https://grass.osgeo.org">GRASS Development Team</a>, GRASS GIS ${grass_version} Reference Manual</p>
 <p>&copy; 2003-${year} <a href="https://grass.osgeo.org">GRASS Development Team</a>, GRASS GIS ${grass_version} Reference Manual</p>
 {% endblock %}
 {% endblock %}
-""")
+"""
+)
 
 
-grass_version = core.version()['version']
+grass_version = core.version()["version"]
 today = date.today()
 today = date.today()
 
 
 copy("_templates/layout.html.template", "_templates/layout.html")
 copy("_templates/layout.html.template", "_templates/layout.html")
 with open("_templates/layout.html", "a+b") as f:
 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()
     f.close()
 
 
 # -- General configuration -----------------------------------------------
 # -- General configuration -----------------------------------------------
 
 
 # If your documentation needs a minimal Sphinx version, state it here.
 # If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
+# needs_sphinx = '1.0'
 
 
 # Add any Sphinx extension module names here, as strings. They can be
 # Add any Sphinx extension module names here, as strings. They can be
 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 # ones.
 # ones.
 extensions = [
 extensions = [
-    'sphinx.ext.autodoc',
-    'sphinx.ext.doctest',
-    'sphinx.ext.todo',
-    'sphinx.ext.coverage',
-    'sphinx.ext.mathjax',
-    'sphinx.ext.ifconfig',
-    'sphinx.ext.viewcode',
-    'sphinx.ext.graphviz',
+    "sphinx.ext.autodoc",
+    "sphinx.ext.doctest",
+    "sphinx.ext.todo",
+    "sphinx.ext.coverage",
+    "sphinx.ext.mathjax",
+    "sphinx.ext.ifconfig",
+    "sphinx.ext.viewcode",
+    "sphinx.ext.graphviz",
 ]
 ]
 todo_include_todos = True
 todo_include_todos = True
 # Add any paths that contain templates here, relative to this directory.
 # Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
+templates_path = ["_templates"]
 
 
 # The suffix of source filenames.
 # The suffix of source filenames.
-source_suffix = '.rst'
+source_suffix = ".rst"
 
 
 # The encoding of source files.
 # The encoding of source files.
-#source_encoding = 'utf-8-sig'
+# source_encoding = 'utf-8-sig'
 
 
 # The master toctree document.
 # The master toctree document.
-master_doc = 'index'
+master_doc = "index"
 
 
 # General information about the project.
 # General information about the project.
-project = u'wxGUI'
-copyright = u'2014, GRASS Development Team'
+project = "wxGUI"
+copyright = "2014, GRASS Development Team"
 
 
 # The version info for the project you're documenting, acts as replacement for
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
 # |version| and |release|, also used in various other places throughout the
 # built documents.
 # built documents.
 #
 #
 # The short X.Y version.
 # The short X.Y version.
-#version = '0.1'
+# version = '0.1'
 # The full version, including alpha/beta/rc tags.
 # The full version, including alpha/beta/rc tags.
-#release = '0.1'
+# release = '0.1'
 
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
 # for a list of supported languages.
-language = 'python'
+language = "python"
 
 
 # There are two options for replacing |today|: either, you set today to some
 # There are two options for replacing |today|: either, you set today to some
 # non-false value, then it is used:
 # non-false value, then it is used:
-#today = ''
+# today = ''
 # Else, today_fmt is used as the format for a strftime call.
 # Else, today_fmt is used as the format for a strftime call.
-#today_fmt = '%B %d, %Y'
+# today_fmt = '%B %d, %Y'
 
 
 # List of patterns, relative to source directory, that match files and
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
 # directories to ignore when looking for source files.
-exclude_patterns = ['_build']
+exclude_patterns = ["_build"]
 
 
 # The reST default role (used for this markup: `text`) to use for all
 # The reST default role (used for this markup: `text`) to use for all
 # documents.
 # documents.
-#default_role = None
+# default_role = None
 
 
 # If true, '()' will be appended to :func: etc. cross-reference text.
 # If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
+# add_function_parentheses = True
 
 
 # If true, the current module name will be prepended to all description
 # If true, the current module name will be prepended to all description
 # unit titles (such as .. function::).
 # unit titles (such as .. function::).
-#add_module_names = True
+# add_module_names = True
 
 
 # If true, sectionauthor and moduleauthor directives will be shown in the
 # If true, sectionauthor and moduleauthor directives will be shown in the
 # output. They are ignored by default.
 # output. They are ignored by default.
-#show_authors = False
+# show_authors = False
 
 
 # The name of the Pygments (syntax highlighting) style to use.
 # The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
+pygments_style = "sphinx"
 
 
 # A list of ignored prefixes for module index sorting.
 # A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
+# modindex_common_prefix = []
 
 
 # If true, keep warnings as "system message" paragraphs in the built documents.
 # If true, keep warnings as "system message" paragraphs in the built documents.
-#keep_warnings = False
+# keep_warnings = False
 
 
 
 
 # -- Options for HTML output ----------------------------------------------
 # -- Options for HTML output ----------------------------------------------
 
 
 # The theme to use for HTML and HTML Help pages.  See the documentation for
 # The theme to use for HTML and HTML Help pages.  See the documentation for
 # a list of builtin themes.
 # a list of builtin themes.
-html_theme = 'traditional'
+html_theme = "traditional"
 
 
 # Theme options are theme-specific and customize the look and feel of a theme
 # Theme options are theme-specific and customize the look and feel of a theme
 # further.  For a list of options available for each theme, see the
 # further.  For a list of options available for each theme, see the
 # documentation.
 # documentation.
-#html_theme_options = {}
+# html_theme_options = {}
 
 
 # Add any paths that contain custom themes here, relative to this directory.
 # Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
+# html_theme_path = []
 
 
 # The name for this set of Sphinx documents.  If None, it defaults to
 # The name for this set of Sphinx documents.  If None, it defaults to
 # "<project> v<release> documentation".
 # "<project> v<release> documentation".
-#html_title = None
+# html_title = None
 
 
 # A shorter title for the navigation bar.  Default is the same as html_title.
 # A shorter title for the navigation bar.  Default is the same as html_title.
-#html_short_title = None
+# html_short_title = None
 
 
 # The name of an image file (relative to this directory) to place at the top
 # The name of an image file (relative to this directory) to place at the top
 # of the sidebar.
 # of the sidebar.
-#html_logo = None
+# html_logo = None
 
 
 # The name of an image file (within the static path) to use as favicon of the
 # The name of an image file (within the static path) to use as favicon of the
 # docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
 # docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
 # pixels large.
 # pixels large.
-#html_favicon = None
+# html_favicon = None
 
 
 # Add any paths that contain custom static files (such as style sheets) here,
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
 # relative to this directory. They are copied after the builtin static files,
 # so a file named "default.css" will overwrite the builtin "default.css".
 # so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
+html_static_path = ["_static"]
 
 
 # Add any extra paths that contain custom files (such as robots.txt or
 # Add any extra paths that contain custom files (such as robots.txt or
 # .htaccess) here, relative to this directory. These files are copied
 # .htaccess) here, relative to this directory. These files are copied
 # directly to the root of the documentation.
 # directly to the root of the documentation.
-#html_extra_path = []
+# html_extra_path = []
 
 
 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
 # using the given strftime format.
 # using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
+# html_last_updated_fmt = '%b %d, %Y'
 
 
 # If true, SmartyPants will be used to convert quotes and dashes to
 # If true, SmartyPants will be used to convert quotes and dashes to
 # typographically correct entities.
 # typographically correct entities.
-#html_use_smartypants = True
+# html_use_smartypants = True
 
 
 # Custom sidebar templates, maps document names to template names.
 # 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
 # Additional templates that should be rendered to pages, maps page names to
 # template names.
 # template names.
-#html_additional_pages = {}
+# html_additional_pages = {}
 
 
 # If false, no module index is generated.
 # If false, no module index is generated.
-#html_domain_indices = True
+# html_domain_indices = True
 
 
 # If false, no index is generated.
 # If false, no index is generated.
 html_use_index = True
 html_use_index = True
 
 
 # If true, the index is split into individual pages for each letter.
 # If true, the index is split into individual pages for each letter.
-#html_split_index = False
+# html_split_index = False
 
 
 # If true, links to the reST sources are added to the pages.
 # If true, links to the reST sources are added to the pages.
 html_show_sourcelink = True
 html_show_sourcelink = True
@@ -211,24 +204,22 @@ html_show_copyright = True
 # If true, an OpenSearch description file will be output, and all pages will
 # If true, an OpenSearch description file will be output, and all pages will
 # contain a <link> tag referring to it.  The value of this option must be the
 # contain a <link> tag referring to it.  The value of this option must be the
 # base URL from which the finished HTML is served.
 # base URL from which the finished HTML is served.
-#html_use_opensearch = ''
+# html_use_opensearch = ''
 
 
 # This is the file name suffix for HTML files (e.g. ".xhtml").
 # This is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = None
+# html_file_suffix = None
 
 
 # Output file base name for HTML help builder.
 # Output file base name for HTML help builder.
-htmlhelp_basename = 'wxGUIdoc'
+htmlhelp_basename = "wxGUIdoc"
 
 
 
 
 # -- Options for LaTeX output ---------------------------------------------
 # -- Options for LaTeX output ---------------------------------------------
 
 
 latex_elements = {
 latex_elements = {
     # The paper size ('letterpaper' or 'a4paper').
     # The paper size ('letterpaper' or 'a4paper').
-    'papersize': 'a4paper',
-
+    "papersize": "a4paper",
     # The font size ('10pt', '11pt' or '12pt').
     # The font size ('10pt', '11pt' or '12pt').
-    'pointsize': '10pt',
-
+    "pointsize": "10pt",
     # Additional stuff for the LaTeX preamble.
     # Additional stuff for the LaTeX preamble.
     #'preamble': '',
     #'preamble': '',
 }
 }
@@ -237,42 +228,38 @@ latex_elements = {
 # (source start file, target name, title,
 # (source start file, target name, title,
 #  author, documentclass [howto, manual, or own class]).
 #  author, documentclass [howto, manual, or own class]).
 latex_documents = [
 latex_documents = [
-    ('index', 'wxGUI.tex', u'wxGUI Documentation',
-     u'GRASS Development Team', 'manual'),
+    ("index", "wxGUI.tex", "wxGUI Documentation", "GRASS Development Team", "manual"),
 ]
 ]
 
 
 # The name of an image file (relative to this directory) to place at the top of
 # The name of an image file (relative to this directory) to place at the top of
 # the title page.
 # the title page.
-#latex_logo = None
+# latex_logo = None
 
 
 # For "manual" documents, if this is true, then toplevel headings are parts,
 # For "manual" documents, if this is true, then toplevel headings are parts,
 # not chapters.
 # not chapters.
-#latex_use_parts = False
+# latex_use_parts = False
 
 
 # If true, show page references after internal links.
 # If true, show page references after internal links.
-#latex_show_pagerefs = False
+# latex_show_pagerefs = False
 
 
 # If true, show URL addresses after external links.
 # If true, show URL addresses after external links.
-#latex_show_urls = False
+# latex_show_urls = False
 
 
 # Documents to append as an appendix to all manuals.
 # Documents to append as an appendix to all manuals.
-#latex_appendices = []
+# latex_appendices = []
 
 
 # If false, no module index is generated.
 # If false, no module index is generated.
-#latex_domain_indices = True
+# latex_domain_indices = True
 
 
 
 
 # -- Options for manual page output ---------------------------------------
 # -- Options for manual page output ---------------------------------------
 
 
 # One entry per manual page. List of tuples
 # One entry per manual page. List of tuples
 # (source start file, name, description, authors, manual section).
 # (source start file, name, description, authors, manual section).
-man_pages = [
-    ('index', 'wxgui', u'wxGUI Documentation',
-     [u'GRASS Development Team'], 1)
-]
+man_pages = [("index", "wxgui", "wxGUI Documentation", ["GRASS Development Team"], 1)]
 
 
 # If true, show URL addresses after external links.
 # If true, show URL addresses after external links.
-#man_show_urls = False
+# man_show_urls = False
 
 
 
 
 # -- Options for Texinfo output -------------------------------------------
 # -- Options for Texinfo output -------------------------------------------
@@ -281,89 +268,95 @@ man_pages = [
 # (source start file, target name, title, author,
 # (source start file, target name, title, author,
 #  dir menu entry, description, category)
 #  dir menu entry, description, category)
 texinfo_documents = [
 texinfo_documents = [
-    ('index', 'wxGUI', u'wxGUI Documentation',
-     u'GRASS Development Team', 'wxGUI', 'One line description of project.',
-     'Miscellaneous'),
+    (
+        "index",
+        "wxGUI",
+        "wxGUI Documentation",
+        "GRASS Development Team",
+        "wxGUI",
+        "One line description of project.",
+        "Miscellaneous",
+    ),
 ]
 ]
 
 
 # Documents to append as an appendix to all manuals.
 # Documents to append as an appendix to all manuals.
-#texinfo_appendices = []
+# texinfo_appendices = []
 
 
 # If false, no module index is generated.
 # If false, no module index is generated.
-#texinfo_domain_indices = True
+# texinfo_domain_indices = True
 
 
 # How to display URL addresses: 'footnote', 'no', or 'inline'.
 # How to display URL addresses: 'footnote', 'no', or 'inline'.
-#texinfo_show_urls = 'footnote'
+# texinfo_show_urls = 'footnote'
 
 
 # If true, do not generate a @detailmenu in the "Top" node's menu.
 # If true, do not generate a @detailmenu in the "Top" node's menu.
-#texinfo_no_detailmenu = False
+# texinfo_no_detailmenu = False
 
 
 
 
 # -- Options for Epub output ----------------------------------------------
 # -- Options for Epub output ----------------------------------------------
 
 
 # Bibliographic Dublin Core info.
 # Bibliographic Dublin Core info.
-epub_title = u'wxGUI'
-epub_author = u'GRASS Development Team'
-epub_publisher = u'GRASS Development Team'
-epub_copyright = u'2014, GRASS Development Team'
+epub_title = "wxGUI"
+epub_author = "GRASS Development Team"
+epub_publisher = "GRASS Development Team"
+epub_copyright = "2014, GRASS Development Team"
 
 
 # The basename for the epub file. It defaults to the project name.
 # The basename for the epub file. It defaults to the project name.
-#epub_basename = u'wxGUI'
+# epub_basename = u'wxGUI'
 
 
 # The HTML theme for the epub output. Since the default themes are not optimized
 # The HTML theme for the epub output. Since the default themes are not optimized
 # for small screen space, using the same theme for HTML and epub output is
 # for small screen space, using the same theme for HTML and epub output is
 # usually not wise. This defaults to 'epub', a theme designed to save visual
 # usually not wise. This defaults to 'epub', a theme designed to save visual
 # space.
 # space.
-#epub_theme = 'epub'
+# epub_theme = 'epub'
 
 
 # The language of the text. It defaults to the language option
 # The language of the text. It defaults to the language option
 # or en if the language is not set.
 # or en if the language is not set.
-#epub_language = ''
+# epub_language = ''
 
 
 # The scheme of the identifier. Typical schemes are ISBN or URL.
 # The scheme of the identifier. Typical schemes are ISBN or URL.
-#epub_scheme = ''
+# epub_scheme = ''
 
 
 # The unique identifier of the text. This can be a ISBN number
 # The unique identifier of the text. This can be a ISBN number
 # or the project homepage.
 # or the project homepage.
-#epub_identifier = ''
+# epub_identifier = ''
 
 
 # A unique identification for the text.
 # A unique identification for the text.
-#epub_uid = ''
+# epub_uid = ''
 
 
 # A tuple containing the cover image and cover page html template filenames.
 # A tuple containing the cover image and cover page html template filenames.
-#epub_cover = ()
+# epub_cover = ()
 
 
 # A sequence of (type, uri, title) tuples for the guide element of content.opf.
 # A sequence of (type, uri, title) tuples for the guide element of content.opf.
-#epub_guide = ()
+# epub_guide = ()
 
 
 # HTML files that should be inserted before the pages created by sphinx.
 # HTML files that should be inserted before the pages created by sphinx.
 # The format is a list of tuples containing the path and title.
 # The format is a list of tuples containing the path and title.
-#epub_pre_files = []
+# epub_pre_files = []
 
 
 # HTML files shat should be inserted after the pages created by sphinx.
 # HTML files shat should be inserted after the pages created by sphinx.
 # The format is a list of tuples containing the path and title.
 # The format is a list of tuples containing the path and title.
-#epub_post_files = []
+# epub_post_files = []
 
 
 # A list of files that should not be packed into the epub file.
 # A list of files that should not be packed into the epub file.
-epub_exclude_files = ['search.html']
+epub_exclude_files = ["search.html"]
 
 
 # The depth of the table of contents in toc.ncx.
 # The depth of the table of contents in toc.ncx.
-#epub_tocdepth = 3
+# epub_tocdepth = 3
 
 
 # Allow duplicate toc entries.
 # Allow duplicate toc entries.
-#epub_tocdup = True
+# epub_tocdup = True
 
 
 # Choose between 'default' and 'includehidden'.
 # Choose between 'default' and 'includehidden'.
-#epub_tocscope = 'default'
+# epub_tocscope = 'default'
 
 
 # Fix unsupported image types using the PIL.
 # Fix unsupported image types using the PIL.
-#epub_fix_images = False
+# epub_fix_images = False
 
 
 # Scale large images.
 # Scale large images.
-#epub_max_image_width = 0
+# epub_max_image_width = 0
 
 
 # How to display URL addresses: 'footnote', 'no', or 'inline'.
 # How to display URL addresses: 'footnote', 'no', or 'inline'.
-#epub_show_urls = 'inline'
+# epub_show_urls = 'inline'
 
 
 # If false, no index is generated.
 # If false, no index is generated.
-#epub_use_index = True
+# epub_use_index = True

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

@@ -1,5 +1,5 @@
 all = [
 all = [
-    'manager',
-    'mapdisplay',
-    'toolbars',
+    "manager",
+    "mapdisplay",
+    "toolbars",
 ]
 ]

+ 7 - 5
gui/wxpython/gcp/g.gui.gcp.py

@@ -50,17 +50,18 @@ def main():
     import wx
     import wx
 
 
     from grass.script.setup import set_gui_path
     from grass.script.setup import set_gui_path
+
     set_gui_path()
     set_gui_path()
 
 
     from core.settings import UserSettings
     from core.settings import UserSettings
     from core.giface import StandaloneGrassInterface
     from core.giface import StandaloneGrassInterface
     from gcp.manager import GCPWizard
     from gcp.manager import GCPWizard
 
 
-    driver = UserSettings.Get(group='display', key='driver', subkey='type')
-    if driver == 'png':
-        os.environ['GRASS_RENDER_IMMEDIATE'] = 'png'
+    driver = UserSettings.Get(group="display", key="driver", subkey="type")
+    if driver == "png":
+        os.environ["GRASS_RENDER_IMMEDIATE"] = "png"
     else:
     else:
-        os.environ['GRASS_RENDER_IMMEDIATE'] = 'cairo'
+        os.environ["GRASS_RENDER_IMMEDIATE"] = "cairo"
 
 
     app = wx.App()
     app = wx.App()
 
 
@@ -68,5 +69,6 @@ def main():
 
 
     app.MainLoop()
     app.MainLoop()
 
 
-if __name__ == '__main__':
+
+if __name__ == "__main__":
     main()
     main()

Plik diff jest za duży
+ 1229 - 1097
gui/wxpython/gcp/manager.py


+ 196 - 130
gui/wxpython/gcp/mapdisplay.py

@@ -44,10 +44,17 @@ class MapFrame(SingleMapFrame):
     child double buffered drawing window.
     child double buffered drawing window.
     """
     """
 
 
-    def __init__(self, parent, giface,
-                 title=_("Manage Ground Control Points"),
-                 toolbars=["gcpdisp"], Map=None, auimgr=None,
-                 name='GCPMapWindow', **kwargs):
+    def __init__(
+        self,
+        parent,
+        giface,
+        title=_("Manage Ground Control Points"),
+        toolbars=["gcpdisp"],
+        Map=None,
+        auimgr=None,
+        name="GCPMapWindow",
+        **kwargs,
+    ):
         """Main map display window with toolbars, statusbar and
         """Main map display window with toolbars, statusbar and
         DrawWindow
         DrawWindow
 
 
@@ -67,7 +74,8 @@ class MapFrame(SingleMapFrame):
             Map=Map,
             Map=Map,
             auimgr=auimgr,
             auimgr=auimgr,
             name=name,
             name=name,
-            **kwargs)
+            **kwargs,
+        )
 
 
         self._giface = giface
         self._giface = giface
         # properties are shared in other objects, so defining here
         # properties are shared in other objects, so defining here
@@ -81,11 +89,11 @@ class MapFrame(SingleMapFrame):
         for toolb in toolbars:
         for toolb in toolbars:
             self.AddToolbar(toolb)
             self.AddToolbar(toolb)
 
 
-        self.activemap = self.toolbars['gcpdisp'].togglemap
+        self.activemap = self.toolbars["gcpdisp"].togglemap
         self.activemap.SetSelection(0)
         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)
         self._mgr.SetDockSizeConstraint(0.5, 0.5)
 
 
         #
         #
@@ -93,58 +101,70 @@ class MapFrame(SingleMapFrame):
         #
         #
 
 
         # items for choice
         # items for choice
-        self.statusbarItems = [sb.SbCoordinates,
-                               sb.SbRegionExtent,
-                               sb.SbCompRegionExtent,
-                               sb.SbShowRegion,
-                               sb.SbResolution,
-                               sb.SbDisplayGeometry,
-                               sb.SbMapScale,
-                               sb.SbProjection,
-                               sbgcp.SbGoToGCP,
-                               sbgcp.SbRMSError]
+        self.statusbarItems = [
+            sb.SbCoordinates,
+            sb.SbRegionExtent,
+            sb.SbCompRegionExtent,
+            sb.SbShowRegion,
+            sb.SbResolution,
+            sb.SbDisplayGeometry,
+            sb.SbMapScale,
+            sb.SbProjection,
+            sbgcp.SbGoToGCP,
+            sbgcp.SbRMSError,
+        ]
 
 
         # create statusbar and its manager
         # 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])
         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
         # fill statusbar manager
         self.statusbarManager.AddStatusbarItemsByClass(
         self.statusbarManager.AddStatusbarItemsByClass(
-            self.statusbarItems, mapframe=self, statusbar=statusbar)
+            self.statusbarItems, mapframe=self, statusbar=statusbar
+        )
         self.statusbarManager.AddStatusbarItem(
         self.statusbarManager.AddStatusbarItem(
-            sb.SbMask(self, statusbar=statusbar, position=2))
+            sb.SbMask(self, statusbar=statusbar, position=2)
+        )
         self.statusbarManager.AddStatusbarItem(
         self.statusbarManager.AddStatusbarItem(
-            sb.SbRender(self, statusbar=statusbar, position=3))
+            sb.SbRender(self, statusbar=statusbar, position=3)
+        )
 
 
         self.statusbarManager.SetMode(8)  # goto GCP
         self.statusbarManager.SetMode(8)  # goto GCP
 
 
         #
         #
         # Init map display (buffered DC & set default cursor)
         # Init map display (buffered DC & set default cursor)
         #
         #
-        self.grwiz.SwitchEnv('source')
+        self.grwiz.SwitchEnv("source")
         self.SrcMapWindow = BufferedMapWindow(
         self.SrcMapWindow = BufferedMapWindow(
-            parent=self, giface=self._giface, id=wx.ID_ANY,
-            properties=self.mapWindowProperties, Map=self.SrcMap)
-
-        self.grwiz.SwitchEnv('target')
+            parent=self,
+            giface=self._giface,
+            id=wx.ID_ANY,
+            properties=self.mapWindowProperties,
+            Map=self.SrcMap,
+        )
+
+        self.grwiz.SwitchEnv("target")
         self.TgtMapWindow = BufferedMapWindow(
         self.TgtMapWindow = BufferedMapWindow(
-            parent=self, giface=self._giface, id=wx.ID_ANY,
-            properties=self.mapWindowProperties, Map=self.TgtMap)
+            parent=self,
+            giface=self._giface,
+            id=wx.ID_ANY,
+            properties=self.mapWindowProperties,
+            Map=self.TgtMap,
+        )
         self.MapWindow = self.SrcMapWindow
         self.MapWindow = self.SrcMapWindow
         self.Map = self.SrcMap
         self.Map = self.SrcMap
         self._setUpMapWindow(self.SrcMapWindow)
         self._setUpMapWindow(self.SrcMapWindow)
         self._setUpMapWindow(self.TgtMapWindow)
         self._setUpMapWindow(self.TgtMapWindow)
-        self.SrcMapWindow.SetNamedCursor('cross')
-        self.TgtMapWindow.SetNamedCursor('cross')
+        self.SrcMapWindow.SetNamedCursor("cross")
+        self.TgtMapWindow.SetNamedCursor("cross")
         # used to switch current map (combo box in toolbar)
         # used to switch current map (combo box in toolbar)
         self.SrcMapWindow.mouseEntered.connect(
         self.SrcMapWindow.mouseEntered.connect(
-            lambda:
-            self._setActiveMapWindow(self.SrcMapWindow))
+            lambda: self._setActiveMapWindow(self.SrcMapWindow)
+        )
         self.TgtMapWindow.mouseEntered.connect(
         self.TgtMapWindow.mouseEntered.connect(
-            lambda:
-            self._setActiveMapWindow(self.TgtMapWindow))
+            lambda: self._setActiveMapWindow(self.TgtMapWindow)
+        )
 
 
         #
         #
         # initialize region values
         # initialize region values
@@ -167,22 +187,47 @@ class MapFrame(SingleMapFrame):
         # windows
         # windows
         self.list = self.CreateGCPList()
         self.list = self.CreateGCPList()
 
 
-        #self.SrcMapWindow.SetSize((300, 300))
-        #self.TgtMapWindow.SetSize((300, 300))
+        # self.SrcMapWindow.SetSize((300, 300))
+        # self.TgtMapWindow.SetSize((300, 300))
         self.list.SetSize((100, 150))
         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)))
-        self._mgr.AddPane(self.SrcMapWindow, wx.aui.AuiPaneInfo().
-                          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))
+        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)),
+        )
+        self._mgr.AddPane(
+            self.SrcMapWindow,
+            wx.aui.AuiPaneInfo()
+            .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),
+        )
 
 
         srcwidth, srcheight = self.SrcMapWindow.GetSize()
         srcwidth, srcheight = self.SrcMapWindow.GetSize()
         tgtwidth, tgtheight = self.TgtMapWindow.GetSize()
         tgtwidth, tgtheight = self.TgtMapWindow.GetSize()
@@ -196,7 +241,7 @@ class MapFrame(SingleMapFrame):
         else:
         else:
             self.activemap.Enable(False)
             self.activemap.Enable(False)
         # needed by Mac OS, does not harm on Linux, breaks display on Windows
         # needed by Mac OS, does not harm on Linux, breaks display on Windows
-        if platform.system() != 'Windows':
+        if platform.system() != "Windows":
             self._mgr.Update()
             self._mgr.Update()
 
 
         #
         #
@@ -219,10 +264,10 @@ class MapFrame(SingleMapFrame):
         # Re-use dialogs
         # Re-use dialogs
         #
         #
         self.dialogs = {}
         self.dialogs = {}
-        self.dialogs['attributes'] = None
-        self.dialogs['category'] = None
-        self.dialogs['barscale'] = None
-        self.dialogs['legend'] = None
+        self.dialogs["attributes"] = None
+        self.dialogs["category"] = None
+        self.dialogs["barscale"] = None
+        self.dialogs["legend"] = None
 
 
         self.decorationDialog = None  # decoration/overlays
         self.decorationDialog = None  # decoration/overlays
 
 
@@ -233,11 +278,11 @@ class MapFrame(SingleMapFrame):
         # TODO: almost the same implementation as for MapFrameBase (only names differ)
         # TODO: almost the same implementation as for MapFrameBase (only names differ)
         # enable or disable zoom history tool
         # enable or disable zoom history tool
         mapWindow.zoomHistoryAvailable.connect(
         mapWindow.zoomHistoryAvailable.connect(
-            lambda:
-            self.GetMapToolbar().Enable('zoomback', enable=True))
+            lambda: self.GetMapToolbar().Enable("zoomback", enable=True)
+        )
         mapWindow.zoomHistoryUnavailable.connect(
         mapWindow.zoomHistoryUnavailable.connect(
-            lambda:
-            self.GetMapToolbar().Enable('zoomback', enable=False))
+            lambda: self.GetMapToolbar().Enable("zoomback", enable=False)
+        )
         mapWindow.mouseMoving.connect(self.CoordinatesChanged)
         mapWindow.mouseMoving.connect(self.CoordinatesChanged)
 
 
     def AddToolbar(self, name):
     def AddToolbar(self, name):
@@ -252,42 +297,63 @@ class MapFrame(SingleMapFrame):
         """
         """
         # default toolbar
         # default toolbar
         if name == "map":
         if name == "map":
-            self.toolbars['map'] = MapToolbar(self, self._toolSwitcher)
-
-            self._mgr.AddPane(self.toolbars['map'],
-                              wx.aui.AuiPaneInfo().
-                              Name("maptoolbar").Caption(_("Map Toolbar")).
-                              ToolbarPane().Top().
-                              LeftDockable(False).RightDockable(False).
-                              BottomDockable(False).TopDockable(True).
-                              CloseButton(False).Layer(2).
-                              BestSize((self.toolbars['map'].GetSize())))
+            self.toolbars["map"] = MapToolbar(self, self._toolSwitcher)
+
+            self._mgr.AddPane(
+                self.toolbars["map"],
+                wx.aui.AuiPaneInfo()
+                .Name("maptoolbar")
+                .Caption(_("Map Toolbar"))
+                .ToolbarPane()
+                .Top()
+                .LeftDockable(False)
+                .RightDockable(False)
+                .BottomDockable(False)
+                .TopDockable(True)
+                .CloseButton(False)
+                .Layer(2)
+                .BestSize((self.toolbars["map"].GetSize())),
+            )
 
 
         # GCP display
         # GCP display
         elif name == "gcpdisp":
         elif name == "gcpdisp":
-            self.toolbars['gcpdisp'] = GCPDisplayToolbar(
-                self, self._toolSwitcher)
-
-            self._mgr.AddPane(self.toolbars['gcpdisp'],
-                              wx.aui.AuiPaneInfo().
-                              Name("gcpdisplaytoolbar").Caption(_("GCP Display toolbar")).
-                              ToolbarPane().Top().
-                              LeftDockable(False).RightDockable(False).
-                              BottomDockable(False).TopDockable(True).
-                              CloseButton(False).Layer(2))
+            self.toolbars["gcpdisp"] = GCPDisplayToolbar(self, self._toolSwitcher)
+
+            self._mgr.AddPane(
+                self.toolbars["gcpdisp"],
+                wx.aui.AuiPaneInfo()
+                .Name("gcpdisplaytoolbar")
+                .Caption(_("GCP Display toolbar"))
+                .ToolbarPane()
+                .Top()
+                .LeftDockable(False)
+                .RightDockable(False)
+                .BottomDockable(False)
+                .TopDockable(True)
+                .CloseButton(False)
+                .Layer(2),
+            )
 
 
             if not self.show_target:
             if not self.show_target:
-                self.toolbars['gcpdisp'].Enable('zoommenu', enable=False)
-
-            self.toolbars['gcpman'] = GCPManToolbar(self)
-
-            self._mgr.AddPane(self.toolbars['gcpman'],
-                              wx.aui.AuiPaneInfo().
-                              Name("gcpmanagertoolbar").Caption(_("GCP Manager toolbar")).
-                              ToolbarPane().Top().Row(1).
-                              LeftDockable(False).RightDockable(False).
-                              BottomDockable(False).TopDockable(True).
-                              CloseButton(False).Layer(2))
+                self.toolbars["gcpdisp"].Enable("zoommenu", enable=False)
+
+            self.toolbars["gcpman"] = GCPManToolbar(self)
+
+            self._mgr.AddPane(
+                self.toolbars["gcpman"],
+                wx.aui.AuiPaneInfo()
+                .Name("gcpmanagertoolbar")
+                .Caption(_("GCP Manager toolbar"))
+                .ToolbarPane()
+                .Top()
+                .Row(1)
+                .LeftDockable(False)
+                .RightDockable(False)
+                .BottomDockable(False)
+                .TopDockable(True)
+                .CloseButton(False)
+                .Layer(2),
+            )
 
 
         self._mgr.Update()
         self._mgr.Update()
 
 
@@ -314,13 +380,11 @@ class MapFrame(SingleMapFrame):
         event.Skip()
         event.Skip()
 
 
     def OnDraw(self, event):
     def OnDraw(self, event):
-        """Re-display current map composition
-        """
+        """Re-display current map composition"""
         self.MapWindow.UpdateMap(render=False)
         self.MapWindow.UpdateMap(render=False)
 
 
     def OnRender(self, event):
     def OnRender(self, event):
-        """Re-render map composition (each map layer)
-        """
+        """Re-render map composition (each map layer)"""
         # FIXME: remove qlayer code or use RemoveQueryLayer() now in mapdisp.frame
         # FIXME: remove qlayer code or use RemoveQueryLayer() now in mapdisp.frame
         # delete tmp map layers (queries)
         # delete tmp map layers (queries)
         qlayer = self.Map.GetListOfLayers(name=globalvar.QUERYLAYER)
         qlayer = self.Map.GetListOfLayers(name=globalvar.QUERYLAYER)
@@ -335,13 +399,12 @@ class MapFrame(SingleMapFrame):
         self.StatusbarUpdate()
         self.StatusbarUpdate()
 
 
     def OnPointer(self, event):
     def OnPointer(self, event):
-        """Pointer button clicked
-        """
+        """Pointer button clicked"""
         self.SrcMapWindow.SetModePointer()
         self.SrcMapWindow.SetModePointer()
         self.TgtMapWindow.SetModePointer()
         self.TgtMapWindow.SetModePointer()
         # change the default cursor
         # change the default cursor
-        self.SrcMapWindow.SetNamedCursor('cross')
-        self.TgtMapWindow.SetNamedCursor('cross')
+        self.SrcMapWindow.SetNamedCursor("cross")
+        self.TgtMapWindow.SetNamedCursor("cross")
 
 
     def OnZoomIn(self, event):
     def OnZoomIn(self, event):
         """Zoom in the map."""
         """Zoom in the map."""
@@ -372,12 +435,13 @@ class MapFrame(SingleMapFrame):
         win.EraseMap()
         win.EraseMap()
 
 
     def SaveToFile(self, event):
     def SaveToFile(self, event):
-        """Save map to image
-        """
+        """Save map to image"""
         img = self.MapWindow.img
         img = self.MapWindow.img
         if not 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
             return
         filetype, ltype = GetImageHandlers(img)
         filetype, ltype = GetImageHandlers(img)
 
 
@@ -391,11 +455,14 @@ class MapFrame(SingleMapFrame):
         dlg.Destroy()
         dlg.Destroy()
 
 
         # get filename
         # get filename
-        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)
+        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:
         if dlg.ShowModal() == wx.ID_OK:
             path = dlg.GetPath()
             path = dlg.GetPath()
@@ -404,13 +471,12 @@ class MapFrame(SingleMapFrame):
                 return
                 return
 
 
             base, ext = os.path.splitext(path)
             base, ext = os.path.splitext(path)
-            fileType = ltype[dlg.GetFilterIndex()]['type']
-            extType = ltype[dlg.GetFilterIndex()]['ext']
+            fileType = ltype[dlg.GetFilterIndex()]["type"]
+            extType = ltype[dlg.GetFilterIndex()]["ext"]
             if ext != extType:
             if ext != extType:
-                path = base + '.' + extType
+                path = base + "." + extType
 
 
-            self.MapWindow.SaveToFile(path, fileType,
-                                      width, height)
+            self.MapWindow.SaveToFile(path, fileType, width, height)
 
 
         dlg.Destroy()
         dlg.Destroy()
 
 
@@ -421,15 +487,15 @@ class MapFrame(SingleMapFrame):
         point = wx.GetMousePosition()
         point = wx.GetMousePosition()
         printmenu = Menu()
         printmenu = Menu()
         # Add items to the menu
         # Add items to the menu
-        setup = wx.MenuItem(printmenu, wx.ID_ANY, _('Page setup'))
+        setup = wx.MenuItem(printmenu, wx.ID_ANY, _("Page setup"))
         printmenu.AppendItem(setup)
         printmenu.AppendItem(setup)
         self.Bind(wx.EVT_MENU, self.printopt.OnPageSetup, setup)
         self.Bind(wx.EVT_MENU, self.printopt.OnPageSetup, setup)
 
 
-        preview = wx.MenuItem(printmenu, wx.ID_ANY, _('Print preview'))
+        preview = wx.MenuItem(printmenu, wx.ID_ANY, _("Print preview"))
         printmenu.AppendItem(preview)
         printmenu.AppendItem(preview)
         self.Bind(wx.EVT_MENU, self.printopt.OnPrintPreview, preview)
         self.Bind(wx.EVT_MENU, self.printopt.OnPrintPreview, preview)
 
 
-        doprint = wx.MenuItem(printmenu, wx.ID_ANY, _('Print display'))
+        doprint = wx.MenuItem(printmenu, wx.ID_ANY, _("Print display"))
         printmenu.AppendItem(doprint)
         printmenu.AppendItem(doprint)
         self.Bind(wx.EVT_MENU, self.printopt.OnDoPrint, doprint)
         self.Bind(wx.EVT_MENU, self.printopt.OnDoPrint, doprint)
 
 
@@ -457,38 +523,38 @@ class MapFrame(SingleMapFrame):
         self.MapWindow.DisplayToWind()
         self.MapWindow.DisplayToWind()
 
 
     def SaveDisplayRegion(self, event):
     def SaveDisplayRegion(self, event):
-        """Save display extents to named region file.
-        """
+        """Save display extents to named region file."""
         self.MapWindow.SaveDisplayRegion()
         self.MapWindow.SaveDisplayRegion()
 
 
     def OnZoomMenu(self, event):
     def OnZoomMenu(self, event):
-        """Popup Zoom menu
-        """
+        """Popup Zoom menu"""
         point = wx.GetMousePosition()
         point = wx.GetMousePosition()
         zoommenu = Menu()
         zoommenu = Menu()
         # Add items to the 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)
         zoommenu.AppendItem(zoomwind)
         self.Bind(wx.EVT_MENU, self.OnZoomToWind, 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)
         zoommenu.AppendItem(zoomdefault)
         self.Bind(wx.EVT_MENU, self.OnZoomToDefault, zoomdefault)
         self.Bind(wx.EVT_MENU, self.OnZoomToDefault, zoomdefault)
 
 
-        zoomsaved = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to saved region'))
+        zoomsaved = wx.MenuItem(zoommenu, wx.ID_ANY, _("Zoom to saved region"))
         zoommenu.AppendItem(zoomsaved)
         zoommenu.AppendItem(zoomsaved)
         self.Bind(wx.EVT_MENU, self.OnZoomToSaved, 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)
         zoommenu.AppendItem(savewind)
         self.Bind(wx.EVT_MENU, self.OnDisplayToWind, 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)
         zoommenu.AppendItem(savezoom)
         self.Bind(wx.EVT_MENU, self.SaveDisplayRegion, savezoom)
         self.Bind(wx.EVT_MENU, self.SaveDisplayRegion, savezoom)
 
 
@@ -520,7 +586,7 @@ class MapFrame(SingleMapFrame):
 
 
     def GetMapToolbar(self):
     def GetMapToolbar(self):
         """Returns toolbar with zooming tools"""
         """Returns toolbar with zooming tools"""
-        return self.toolbars['gcpdisp']
+        return self.toolbars["gcpdisp"]
 
 
     def _setActiveMapWindow(self, mapWindow):
     def _setActiveMapWindow(self, mapWindow):
         if not self.MapWindow == mapWindow:
         if not self.MapWindow == mapWindow:

+ 13 - 13
gui/wxpython/gcp/statusbar.py

@@ -33,11 +33,10 @@ class SbGoToGCP(SbItem):
 
 
     def __init__(self, mapframe, statusbar, position=0):
     def __init__(self, mapframe, statusbar, position=0):
         SbItem.__init__(self, mapframe, statusbar, position)
         SbItem.__init__(self, mapframe, statusbar, position)
-        self.name = 'gotoGCP'
+        self.name = "gotoGCP"
         self.label = _("Go to GCP No.")
         self.label = _("Go to GCP No.")
 
 
-        self.widget = SpinCtrl(parent=self.statusbar, id=wx.ID_ANY,
-                               value="", min=0)
+        self.widget = SpinCtrl(parent=self.statusbar, id=wx.ID_ANY, value="", min=0)
         self.widget.Hide()
         self.widget.Hide()
 
 
         self.widget.Bind(wx.EVT_TEXT_ENTER, self.OnGoToGCP)
         self.widget.Bind(wx.EVT_TEXT_ENTER, self.OnGoToGCP)
@@ -50,9 +49,9 @@ class SbGoToGCP(SbItem):
 
 
         # always false, spin checks it
         # always false, spin checks it
         if gcpNumber < 0 or gcpNumber > len(mapCoords):
         if gcpNumber < 0 or gcpNumber > len(mapCoords):
-            GMessage(parent=self,
-                     message="%s 1 - %s." % (_("Valid Range:"),
-                                             len(mapCoords)))
+            GMessage(
+                parent=self, message="%s 1 - %s." % (_("Valid Range:"), len(mapCoords))
+            )
             return
             return
 
 
         if gcpNumber == 0:
         if gcpNumber == 0:
@@ -63,9 +62,9 @@ class SbGoToGCP(SbItem):
         listCtrl.selectedkey = gcpNumber
         listCtrl.selectedkey = gcpNumber
         listCtrl.selected = listCtrl.FindItem(-1, gcpNumber)
         listCtrl.selected = listCtrl.FindItem(-1, gcpNumber)
         listCtrl.render = False
         listCtrl.render = False
-        listCtrl.SetItemState(listCtrl.selected,
-                              wx.LIST_STATE_SELECTED,
-                              wx.LIST_STATE_SELECTED)
+        listCtrl.SetItemState(
+            listCtrl.selected, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED
+        )
         listCtrl.render = True
         listCtrl.render = True
 
 
         listCtrl.EnsureVisible(listCtrl.selected)
         listCtrl.EnsureVisible(listCtrl.selected)
@@ -116,12 +115,13 @@ class SbRMSError(SbTextItem):
 
 
     def __init__(self, mapframe, statusbar, position=0):
     def __init__(self, mapframe, statusbar, position=0):
         SbTextItem.__init__(self, mapframe, statusbar, position)
         SbTextItem.__init__(self, mapframe, statusbar, position)
-        self.name = 'RMSError'
+        self.name = "RMSError"
         self.label = _("RMS error")
         self.label = _("RMS error")
 
 
     def Show(self):
     def Show(self):
         """Shows the RMS errors."""
         """Shows the RMS errors."""
-        self.SetValue(_("Forward: %(forw)s, Backward: %(back)s") %
-                      {'forw': self.mapFrame.GetFwdError(),
-                       'back': self.mapFrame.GetBkwError()})
+        self.SetValue(
+            _("Forward: %(forw)s, Backward: %(back)s")
+            % {"forw": self.mapFrame.GetFwdError(), "back": self.mapFrame.GetBkwError()}
+        )
         SbTextItem.Show(self)
         SbTextItem.Show(self)

+ 65 - 88
gui/wxpython/gcp/toolbars.py

@@ -37,68 +37,61 @@ class GCPManToolbar(BaseToolbar):
 
 
     def _toolbarData(self):
     def _toolbarData(self):
         icons = {
         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"],
-                                      self.parent.DeleteGCP),
-                                     ('gcpClear', icons["gcpClear"],
-                                      self.parent.ClearGCP),
-                                     (None, ),
-                                     ('rms', icons["gcpRms"],
-                                      self.parent.OnRMS),
-                                     ('georect', icons["georectify"],
-                                      self.parent.OnGeorect),
-                                     (None, ),
-                                     ('gcpSave', icons["gcpSave"],
-                                      self.parent.SaveGCPs),
-                                     ('gcpReload', icons["gcpReload"],
-                                      self.parent.ReloadGCPs))
-                                    )
+        return self._getToolbarData(
+            (
+                ("gcpAdd", icons["gcpAdd"], self.parent.AddGCP),
+                ("gcpDelete", icons["gcpDelete"], self.parent.DeleteGCP),
+                ("gcpClear", icons["gcpClear"], self.parent.ClearGCP),
+                (None,),
+                ("rms", icons["gcpRms"], self.parent.OnRMS),
+                ("georect", icons["georectify"], self.parent.OnGeorect),
+                (None,),
+                ("gcpSave", icons["gcpSave"], self.parent.SaveGCPs),
+                ("gcpReload", icons["gcpReload"], self.parent.ReloadGCPs),
+            )
+        )
 
 
 
 
 class GCPDisplayToolbar(BaseToolbar):
 class GCPDisplayToolbar(BaseToolbar):
-    """GCP Display toolbar
-    """
+    """GCP Display toolbar"""
 
 
     def __init__(self, parent, toolSwitcher):
     def __init__(self, parent, toolSwitcher):
-        """GCP Display toolbar constructor
-        """
+        """GCP Display toolbar constructor"""
         BaseToolbar.__init__(self, parent, toolSwitcher)
         BaseToolbar.__init__(self, parent, toolSwitcher)
 
 
         self.InitToolbar(self._toolbarData())
         self.InitToolbar(self._toolbarData())
         self._default = self.gcpset
         self._default = self.gcpset
 
 
         # add tool to toggle active map window
         # add tool to toggle active map window
-        self.togglemap = wx.Choice(parent=self, id=wx.ID_ANY,
-                                   choices=[_('source'), _('target')])
+        self.togglemap = wx.Choice(
+            parent=self, id=wx.ID_ANY, choices=[_("source"), _("target")]
+        )
 
 
         self.InsertControl(10, self.togglemap)
         self.InsertControl(10, self.togglemap)
 
 
         self.SetToolShortHelp(
         self.SetToolShortHelp(
-            self.togglemap.GetId(), '%s %s %s' %
-            (_('Set map canvas for '),
-             BaseIcons["zoomBack"].GetLabel(),
-             _(' / Zoom to map')))
+            self.togglemap.GetId(),
+            "%s %s %s"
+            % (
+                _("Set map canvas for "),
+                BaseIcons["zoomBack"].GetLabel(),
+                _(" / Zoom to map"),
+            ),
+        )
 
 
         for tool in (self.gcpset, self.pan, self.zoomin, self.zoomout):
         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
         # realize the toolbar
         self.Realize()
         self.Realize()
@@ -108,50 +101,34 @@ class GCPDisplayToolbar(BaseToolbar):
     def _toolbarData(self):
     def _toolbarData(self):
         """Toolbar data"""
         """Toolbar data"""
         icons = {
         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"],
-                                      self.parent.OnRender),
-                                     ("erase", BaseIcons["erase"],
-                                      self.parent.OnErase),
-                                     (None, ),
-                                     ("gcpset", icons["gcpSet"],
-                                      self.parent.OnPointer,
-                                      wx.ITEM_CHECK),
-                                     ("pan", BaseIcons["pan"],
-                                      self.parent.OnPan,
-                                      wx.ITEM_CHECK),
-                                     ("zoomin", BaseIcons["zoomIn"],
-                                      self.parent.OnZoomIn,
-                                      wx.ITEM_CHECK),
-                                     ("zoomout", BaseIcons["zoomOut"],
-                                      self.parent.OnZoomOut,
-                                      wx.ITEM_CHECK),
-                                     ("zoommenu", BaseIcons["zoomMenu"],
-                                      self.parent.OnZoomMenuGCP),
-                                     (None, ),
-                                     ("zoomback", BaseIcons["zoomBack"],
-                                      self.parent.OnZoomBack),
-                                     ("zoomtomap", BaseIcons["zoomExtent"],
-                                      self.parent.OnZoomToMap),
-                                     (None, ),
-                                     ('settings', icons["settings"],
-                                      self.parent.OnSettings),
-                                     ('help', icons["help"],
-                                      self.parent.OnHelp),
-                                     (None, ),
-                                     ('quit', icons["quit"],
-                                      self.parent.OnQuit))
-                                    )
+        return self._getToolbarData(
+            (
+                ("displaymap", BaseIcons["display"], self.parent.OnDraw),
+                ("rendermap", BaseIcons["render"], self.parent.OnRender),
+                ("erase", BaseIcons["erase"], self.parent.OnErase),
+                (None,),
+                ("gcpset", icons["gcpSet"], self.parent.OnPointer, wx.ITEM_CHECK),
+                ("pan", BaseIcons["pan"], self.parent.OnPan, wx.ITEM_CHECK),
+                ("zoomin", BaseIcons["zoomIn"], self.parent.OnZoomIn, wx.ITEM_CHECK),
+                ("zoomout", BaseIcons["zoomOut"], self.parent.OnZoomOut, wx.ITEM_CHECK),
+                ("zoommenu", BaseIcons["zoomMenu"], self.parent.OnZoomMenuGCP),
+                (None,),
+                ("zoomback", BaseIcons["zoomBack"], self.parent.OnZoomBack),
+                ("zoomtomap", BaseIcons["zoomExtent"], self.parent.OnZoomToMap),
+                (None,),
+                ("settings", icons["settings"], self.parent.OnSettings),
+                ("help", icons["help"], self.parent.OnHelp),
+                (None,),
+                ("quit", icons["quit"], self.parent.OnQuit),
+            )
+        )

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

@@ -1,10 +1,10 @@
 all = [
 all = [
-    'preferences',
-    'g.gui.gmodeler',
-    'menudata',
-    'model',
-    'pystc',
-    'dialogs',
-    'toolbars',
-    'frame',
+    "preferences",
+    "g.gui.gmodeler",
+    "menudata",
+    "model",
+    "pystc",
+    "dialogs",
+    "toolbars",
+    "frame",
 ]
 ]

Plik diff jest za duży
+ 341 - 277
gui/wxpython/gmodeler/dialogs.py


Plik diff jest za duży
+ 536 - 525
gui/wxpython/gmodeler/frame.py


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

@@ -43,6 +43,7 @@ def main():
     import wx
     import wx
 
 
     from grass.script.setup import set_gui_path
     from grass.script.setup import set_gui_path
+
     set_gui_path()
     set_gui_path()
 
 
     from core.giface import StandaloneGrassInterface
     from core.giface import StandaloneGrassInterface
@@ -54,11 +55,12 @@ def main():
         giface=StandaloneGrassInterface(),
         giface=StandaloneGrassInterface(),
         title=_("Graphical Modeler - GRASS GIS"),
         title=_("Graphical Modeler - GRASS GIS"),
     )
     )
-    if options['file']:
-        frame.LoadModelFile(options['file'])
+    if options["file"]:
+        frame.LoadModelFile(options["file"])
     frame.Show()
     frame.Show()
 
 
     app.MainLoop()
     app.MainLoop()
 
 
+
 if __name__ == "__main__":
 if __name__ == "__main__":
     main()
     main()

+ 2 - 2
gui/wxpython/gmodeler/giface.py

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

+ 1 - 3
gui/wxpython/gmodeler/menudata.py

@@ -21,10 +21,8 @@ from core.menutree import MenuTreeModelBuilder
 
 
 
 
 class ModelerMenuData(MenuTreeModelBuilder):
 class ModelerMenuData(MenuTreeModelBuilder):
-
     def __init__(self, filename=None):
     def __init__(self, filename=None):
         if not filename:
         if not filename:
-            filename = os.path.join(
-                globalvar.WXGUIDIR, 'xml', 'menudata_modeler.xml')
+            filename = os.path.join(globalvar.WXGUIDIR, "xml", "menudata_modeler.xml")
 
 
         MenuTreeModelBuilder.__init__(self, filename)
         MenuTreeModelBuilder.__init__(self, filename)

Plik diff jest za duży
+ 883 - 812
gui/wxpython/gmodeler/model.py


Plik diff jest za duży
+ 429 - 443
gui/wxpython/gmodeler/preferences.py


+ 55 - 74
gui/wxpython/gmodeler/toolbars.py

@@ -22,14 +22,13 @@ from icons.icon import MetaIcon
 
 
 
 
 class ModelerToolbar(BaseToolbar):
 class ModelerToolbar(BaseToolbar):
-    """Graphical modeler toolbaro (see gmodeler.py)
-    """
+    """Graphical modeler toolbaro (see gmodeler.py)"""
 
 
     def __init__(self, parent):
     def __init__(self, parent):
         BaseToolbar.__init__(self, parent)
         BaseToolbar.__init__(self, parent)
 
 
         # workaround for http://trac.wxwidgets.org/ticket/13888
         # workaround for http://trac.wxwidgets.org/ticket/13888
-        if sys.platform == 'darwin':
+        if sys.platform == "darwin":
             parent.SetToolBar(self)
             parent.SetToolBar(self)
 
 
         self.InitToolbar(self._toolbarData())
         self.InitToolbar(self._toolbarData())
@@ -40,76 +39,58 @@ class ModelerToolbar(BaseToolbar):
     def _toolbarData(self):
     def _toolbarData(self):
         """Toolbar data"""
         """Toolbar data"""
         icons = {
         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'],
-                                      self.parent.OnModelOpen),
-                                     ('save', icons['save'],
-                                      self.parent.OnModelSave),
-                                     ('image', icons['toImage'],
-                                      self.parent.OnExportImage),
-                                     ('python', icons['toPython'],
-                                      self.parent.OnExportPython),
-                                     (None, ),
-                                     ('action', icons['actionAdd'],
-                                      self.parent.OnAddAction),
-                                     ('data', icons['dataAdd'],
-                                      self.parent.OnAddData),
-                                     ('relation', icons['relation'],
-                                      self.parent.OnDefineRelation),
-                                     ('loop', icons['loop'],
-                                      self.parent.OnDefineLoop),
-                                     ('comment', icons['comment'],
-                                      self.parent.OnAddComment),
-                                     (None, ),
-                                     ('redraw', icons['redraw'],
-                                      self.parent.OnCanvasRefresh),
-                                     ('validate', icons['validate'],
-                                      self.parent.OnValidateModel),
-                                     ('run', icons['run'],
-                                      self.parent.OnRunModel),
-                                     (None, ),
-                                     ("variables", icons['variables'],
-                                      self.parent.OnVariables),
-                                     ("settings", icons['settings'],
-                                      self.parent.OnPreferences),
-                                     ("help", BaseIcons['help'],
-                                      self.parent.OnHelp),
-                                     (None, ),
-                                     ('quit', icons['quit'],
-                                      self.parent.OnCloseWindow))
-                                    )
+        return self._getToolbarData(
+            (
+                ("new", icons["new"], self.parent.OnModelNew),
+                ("open", icons["open"], self.parent.OnModelOpen),
+                ("save", icons["save"], self.parent.OnModelSave),
+                ("image", icons["toImage"], self.parent.OnExportImage),
+                ("python", icons["toPython"], self.parent.OnExportPython),
+                (None,),
+                ("action", icons["actionAdd"], self.parent.OnAddAction),
+                ("data", icons["dataAdd"], self.parent.OnAddData),
+                ("relation", icons["relation"], self.parent.OnDefineRelation),
+                ("loop", icons["loop"], self.parent.OnDefineLoop),
+                ("comment", icons["comment"], self.parent.OnAddComment),
+                (None,),
+                ("redraw", icons["redraw"], self.parent.OnCanvasRefresh),
+                ("validate", icons["validate"], self.parent.OnValidateModel),
+                ("run", icons["run"], self.parent.OnRunModel),
+                (None,),
+                ("variables", icons["variables"], self.parent.OnVariables),
+                ("settings", icons["settings"], self.parent.OnPreferences),
+                ("help", BaseIcons["help"], self.parent.OnHelp),
+                (None,),
+                ("quit", icons["quit"], self.parent.OnCloseWindow),
+            )
+        )

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

@@ -1,17 +1,17 @@
 all = [
 all = [
-    'query',
-    'widgets',
-    'preferences',
-    'menu',
-    'infobar',
-    'dialogs',
-    'mapwindow',
-    'mapdisp',
-    'gselect',
-    'ghelp',
-    'prompt',
-    'goutput',
-    'forms',
-    'toolbars',
-    'treeview',
+    "query",
+    "widgets",
+    "preferences",
+    "menu",
+    "infobar",
+    "dialogs",
+    "mapwindow",
+    "mapdisp",
+    "gselect",
+    "ghelp",
+    "prompt",
+    "goutput",
+    "forms",
+    "toolbars",
+    "treeview",
 ]
 ]

Plik diff jest za duży
+ 740 - 735
gui/wxpython/gui_core/dialogs.py


Plik diff jest za duży
+ 1375 - 1113
gui/wxpython/gui_core/forms.py


+ 308 - 283
gui/wxpython/gui_core/ghelp.py

@@ -26,6 +26,7 @@ import sys
 import six
 import six
 import wx
 import wx
 from wx.html import HtmlWindow
 from wx.html import HtmlWindow
+
 try:
 try:
     from wx.lib.agw.hyperlink import HyperLinkCtrl
     from wx.lib.agw.hyperlink import HyperLinkCtrl
 except ImportError:
 except ImportError:
@@ -41,8 +42,9 @@ import grass.script as grass
 from grass.exceptions import CalledModuleError
 from grass.exceptions import CalledModuleError
 
 
 # needed just for testing
 # needed just for testing
-if __name__ == '__main__':
+if __name__ == "__main__":
     from grass.script.setup import set_gui_path
     from grass.script.setup import set_gui_path
+
     set_gui_path()
     set_gui_path()
 
 
 from core import globalvar
 from core import globalvar
@@ -53,41 +55,34 @@ from core.debug import Debug
 
 
 
 
 class AboutWindow(wx.Frame):
 class AboutWindow(wx.Frame):
-    """Create custom About Window
-    """
+    """Create custom About Window"""
 
 
-    def __init__(self, parent, size=(770, 460),
-                 title=_('About GRASS GIS'), **kwargs):
+    def __init__(self, parent, size=(770, 460), title=_("About GRASS GIS"), **kwargs):
         wx.Frame.__init__(
         wx.Frame.__init__(
-            self,
-            parent=parent,
-            id=wx.ID_ANY,
-            title=title,
-            size=size,
-            **kwargs)
+            self, parent=parent, id=wx.ID_ANY, title=title, size=size, **kwargs
+        )
 
 
         self.panel = wx.Panel(parent=self, id=wx.ID_ANY)
         self.panel = wx.Panel(parent=self, id=wx.ID_ANY)
 
 
         # icon
         # icon
         self.SetIcon(
         self.SetIcon(
-            wx.Icon(
-                os.path.join(
-                    globalvar.ICONDIR,
-                    'grass.ico'),
-                wx.BITMAP_TYPE_ICO))
+            wx.Icon(os.path.join(globalvar.ICONDIR, "grass.ico"), wx.BITMAP_TYPE_ICO)
+        )
 
 
         # notebook
         # notebook
         self.aboutNotebook = FormNotebook(self.panel, style=wx.BK_LEFT)
         self.aboutNotebook = FormNotebook(self.panel, style=wx.BK_LEFT)
 
 
-        for title, win in ((_("Info"), self._pageInfo()),
-                           (_("Copyright"), self._pageCopyright()),
-                           (_("License"), self._pageLicense()),
-                           (_("Citation"), self._pageCitation()),
-                           (_("Authors"), self._pageCredit()),
-                           (_("Contributors"), self._pageContributors()),
-                           (_("Extra contributors"), self._pageContributors(extra=True)),
-                           (_("Translators"), self._pageTranslators()),
-                           (_("Translation status"), self._pageStats())):
+        for title, win in (
+            (_("Info"), self._pageInfo()),
+            (_("Copyright"), self._pageCopyright()),
+            (_("License"), self._pageLicense()),
+            (_("Citation"), self._pageCitation()),
+            (_("Authors"), self._pageCredit()),
+            (_("Contributors"), self._pageContributors()),
+            (_("Extra contributors"), self._pageContributors(extra=True)),
+            (_("Translators"), self._pageTranslators()),
+            (_("Translation status"), self._pageStats()),
+        ):
             self.aboutNotebook.AddPage(page=win, text=title)
             self.aboutNotebook.AddPage(page=win, text=title)
         wx.CallAfter(self.aboutNotebook.SetSelection, 0)
         wx.CallAfter(self.aboutNotebook.SetSelection, 0)
         wx.CallAfter(self.aboutNotebook.Refresh)
         wx.CallAfter(self.aboutNotebook.Refresh)
@@ -103,10 +98,8 @@ class AboutWindow(wx.Frame):
         btnSizer.Add(self.btnClose, proportion=0, flag=wx.ALL, border=5)
         btnSizer.Add(self.btnClose, proportion=0, flag=wx.ALL, border=5)
 
 
         sizer = wx.BoxSizer(wx.VERTICAL)
         sizer = wx.BoxSizer(wx.VERTICAL)
-        sizer.Add(self.aboutNotebook, proportion=1,
-                  flag=wx.EXPAND | wx.ALL, border=1)
-        sizer.Add(btnSizer, proportion=0,
-                  flag=wx.ALL | wx.ALIGN_RIGHT, border=1)
+        sizer.Add(self.aboutNotebook, proportion=1, flag=wx.EXPAND | wx.ALL, border=1)
+        sizer.Add(btnSizer, proportion=0, flag=wx.ALL | wx.ALIGN_RIGHT, border=1)
 
 
         self.SetMinSize((400, 400))
         self.SetMinSize((400, 400))
 
 
@@ -127,59 +120,71 @@ class AboutWindow(wx.Frame):
         infoSizer = wx.BoxSizer(wx.VERTICAL)
         infoSizer = wx.BoxSizer(wx.VERTICAL)
         infoGridSizer = wx.GridBagSizer(vgap=5, hgap=5)
         infoGridSizer = wx.GridBagSizer(vgap=5, hgap=5)
         logo = os.path.join(globalvar.ICONDIR, "grass-64x64.png")
         logo = os.path.join(globalvar.ICONDIR, "grass-64x64.png")
-        logoBitmap = wx.StaticBitmap(infoTxt, wx.ID_ANY,
-                                     wx.Bitmap(name=logo, type=wx.BITMAP_TYPE_PNG))
-        infoSizer.Add(logoBitmap, proportion=0,
-                      flag=wx.ALL | wx.ALIGN_CENTER, border=20)
-
-        infoLabel = 'GRASS GIS %s' % vInfo.get('version', _('unknown version'))
-        if 'x86_64' in vInfo.get('build_platform', ''):
-            infoLabel += ' (64bit)'
-        info = StaticText(parent=infoTxt, id=wx.ID_ANY,
-                          label=infoLabel + os.linesep)
+        logoBitmap = wx.StaticBitmap(
+            infoTxt, wx.ID_ANY, wx.Bitmap(name=logo, type=wx.BITMAP_TYPE_PNG)
+        )
+        infoSizer.Add(
+            logoBitmap, proportion=0, flag=wx.ALL | wx.ALIGN_CENTER, border=20
+        )
+
+        infoLabel = "GRASS GIS %s" % vInfo.get("version", _("unknown version"))
+        if "x86_64" in vInfo.get("build_platform", ""):
+            infoLabel += " (64bit)"
+        info = StaticText(parent=infoTxt, id=wx.ID_ANY, label=infoLabel + os.linesep)
         info.SetFont(wx.Font(13, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
         info.SetFont(wx.Font(13, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
         info.SetForegroundColour(wx.Colour(35, 142, 35))
         info.SetForegroundColour(wx.Colour(35, 142, 35))
-        infoSizer.Add(info, proportion=0,
-                      flag=wx.BOTTOM | wx.ALIGN_CENTER, border=1)
+        infoSizer.Add(info, proportion=0, flag=wx.BOTTOM | wx.ALIGN_CENTER, border=1)
 
 
-        team = StaticText(parent=infoTxt, label=_grassDevTeam(1999) + '\n')
-        infoSizer.Add(team, proportion=0,
-                      flag=wx.BOTTOM | wx.ALIGN_CENTER, border=1)
+        team = StaticText(parent=infoTxt, label=_grassDevTeam(1999) + "\n")
+        infoSizer.Add(team, proportion=0, flag=wx.BOTTOM | wx.ALIGN_CENTER, border=1)
 
 
         row = 0
         row = 0
-        infoGridSizer.Add(StaticText(parent=infoTxt, id=wx.ID_ANY,
-                                     label=_('Official GRASS site:')),
-                          pos=(row, 0),
-                          flag=wx.ALIGN_RIGHT)
+        infoGridSizer.Add(
+            StaticText(parent=infoTxt, id=wx.ID_ANY, label=_("Official GRASS site:")),
+            pos=(row, 0),
+            flag=wx.ALIGN_RIGHT,
+        )
 
 
-        infoGridSizer.Add(HyperLinkCtrl(parent=infoTxt, id=wx.ID_ANY,
-                                        label='https://grass.osgeo.org'),
-                          pos=(row, 1),
-                          flag=wx.ALIGN_LEFT)
+        infoGridSizer.Add(
+            HyperLinkCtrl(
+                parent=infoTxt, id=wx.ID_ANY, label="https://grass.osgeo.org"
+            ),
+            pos=(row, 1),
+            flag=wx.ALIGN_LEFT,
+        )
 
 
         row += 2
         row += 2
-        infoGridSizer.Add(StaticText(parent=infoTxt, id=wx.ID_ANY,
-                                     label='%s:' % _('Code Revision')),
-                          pos=(row, 0),
-                          flag=wx.ALIGN_RIGHT)
+        infoGridSizer.Add(
+            StaticText(parent=infoTxt, id=wx.ID_ANY, label="%s:" % _("Code Revision")),
+            pos=(row, 0),
+            flag=wx.ALIGN_RIGHT,
+        )
 
 
-        infoGridSizer.Add(HyperLinkCtrl(parent=infoTxt, id=wx.ID_ANY,
-                                        label=vInfo.get('revision', '?'),
-                                        URL='https://github.com/OSGeo/grass.git'),
-                          pos=(row, 1),
-                          flag=wx.ALIGN_LEFT)
+        infoGridSizer.Add(
+            HyperLinkCtrl(
+                parent=infoTxt,
+                id=wx.ID_ANY,
+                label=vInfo.get("revision", "?"),
+                URL="https://github.com/OSGeo/grass.git",
+            ),
+            pos=(row, 1),
+            flag=wx.ALIGN_LEFT,
+        )
 
 
         row += 1
         row += 1
-        infoGridSizer.Add(StaticText(parent=infoTxt, id=wx.ID_ANY,
-                                     label='%s:' % _('Build Date')),
-                          pos=(row, 0),
-                          flag=wx.ALIGN_RIGHT)
+        infoGridSizer.Add(
+            StaticText(parent=infoTxt, id=wx.ID_ANY, label="%s:" % _("Build Date")),
+            pos=(row, 0),
+            flag=wx.ALIGN_RIGHT,
+        )
 
 
         infoGridSizer.Add(
         infoGridSizer.Add(
             StaticText(
             StaticText(
-                parent=infoTxt, id=wx.ID_ANY, label=vInfo.get(
-                    'build_date', '?')), pos=(
-                row, 1), flag=wx.ALIGN_LEFT)
+                parent=infoTxt, id=wx.ID_ANY, label=vInfo.get("build_date", "?")
+            ),
+            pos=(row, 1),
+            flag=wx.ALIGN_LEFT,
+        )
 
 
         # show only basic info
         # show only basic info
         # row += 1
         # row += 1
@@ -195,48 +200,55 @@ class AboutWindow(wx.Frame):
         #                   flag = wx.ALIGN_LEFT)
         #                   flag = wx.ALIGN_LEFT)
 
 
         row += 2
         row += 2
-        infoGridSizer.Add(StaticText(parent=infoTxt, id=wx.ID_ANY,
-                                     label='Python:'),
-                          pos=(row, 0),
-                          flag=wx.ALIGN_RIGHT)
+        infoGridSizer.Add(
+            StaticText(parent=infoTxt, id=wx.ID_ANY, label="Python:"),
+            pos=(row, 0),
+            flag=wx.ALIGN_RIGHT,
+        )
 
 
-        infoGridSizer.Add(StaticText(parent=infoTxt, id=wx.ID_ANY,
-                                     label=platform.python_version()),
-                          pos=(row, 1),
-                          flag=wx.ALIGN_LEFT)
+        infoGridSizer.Add(
+            StaticText(parent=infoTxt, id=wx.ID_ANY, label=platform.python_version()),
+            pos=(row, 1),
+            flag=wx.ALIGN_LEFT,
+        )
 
 
         row += 1
         row += 1
-        infoGridSizer.Add(StaticText(parent=infoTxt, id=wx.ID_ANY,
-                                     label='wxPython:'),
-                          pos=(row, 0),
-                          flag=wx.ALIGN_RIGHT)
+        infoGridSizer.Add(
+            StaticText(parent=infoTxt, id=wx.ID_ANY, label="wxPython:"),
+            pos=(row, 0),
+            flag=wx.ALIGN_RIGHT,
+        )
 
 
-        infoGridSizer.Add(StaticText(parent=infoTxt, id=wx.ID_ANY,
-                                     label=wx.__version__),
-                          pos=(row, 1),
-                          flag=wx.ALIGN_LEFT)
+        infoGridSizer.Add(
+            StaticText(parent=infoTxt, id=wx.ID_ANY, label=wx.__version__),
+            pos=(row, 1),
+            flag=wx.ALIGN_LEFT,
+        )
 
 
         infoGridSizer.AddGrowableCol(0)
         infoGridSizer.AddGrowableCol(0)
         infoGridSizer.AddGrowableCol(1)
         infoGridSizer.AddGrowableCol(1)
         infoSizer.Add(infoGridSizer, proportion=1, flag=wx.EXPAND)
         infoSizer.Add(infoGridSizer, proportion=1, flag=wx.EXPAND)
 
 
         row += 2
         row += 2
-        infoGridSizer.Add(StaticText(parent=infoTxt, id=wx.ID_ANY,
-                                     label="%s:" % _('Language')),
-                          pos=(row, 0),
-                          flag=wx.ALIGN_RIGHT)
-        self.langUsed = grass.gisenv().get('LANG', None)
+        infoGridSizer.Add(
+            StaticText(parent=infoTxt, id=wx.ID_ANY, label="%s:" % _("Language")),
+            pos=(row, 0),
+            flag=wx.ALIGN_RIGHT,
+        )
+        self.langUsed = grass.gisenv().get("LANG", None)
         if not self.langUsed:
         if not self.langUsed:
             import locale
             import locale
+
             loc = locale.getdefaultlocale()
             loc = locale.getdefaultlocale()
             if loc == (None, None):
             if loc == (None, None):
-                self.langUsed = _('unknown')
+                self.langUsed = _("unknown")
             else:
             else:
-                self.langUsed = u'%s.%s' % (loc[0], loc[1])
-        infoGridSizer.Add(StaticText(parent=infoTxt, id=wx.ID_ANY,
-                                     label=self.langUsed),
-                          pos=(row, 1),
-                          flag=wx.ALIGN_LEFT)
+                self.langUsed = "%s.%s" % (loc[0], loc[1])
+        infoGridSizer.Add(
+            StaticText(parent=infoTxt, id=wx.ID_ANY, label=self.langUsed),
+            pos=(row, 1),
+            flag=wx.ALIGN_LEFT,
+        )
 
 
         infoTxt.SetSizer(infoSizer)
         infoTxt.SetSizer(infoSizer)
         infoSizer.Fit(infoTxt)
         infoSizer.Fit(infoTxt)
@@ -247,21 +259,25 @@ class AboutWindow(wx.Frame):
         """Copyright information"""
         """Copyright information"""
         copyfile = os.path.join(os.getenv("GISBASE"), "COPYING")
         copyfile = os.path.join(os.getenv("GISBASE"), "COPYING")
         if os.path.exists(copyfile):
         if os.path.exists(copyfile):
-            copyrightFile = open(copyfile, 'r')
+            copyrightFile = open(copyfile, "r")
             copytext = copyrightFile.read()
             copytext = copyrightFile.read()
             copyrightFile.close()
             copyrightFile.close()
         else:
         else:
-            copytext = _('%s file missing') % 'COPYING'
+            copytext = _("%s file missing") % "COPYING"
 
 
         # put text into a scrolling panel
         # put text into a scrolling panel
         copyrightwin = ScrolledPanel(self.aboutNotebook)
         copyrightwin = ScrolledPanel(self.aboutNotebook)
         copyrighttxt = TextCtrl(
         copyrighttxt = TextCtrl(
-            copyrightwin, id=wx.ID_ANY, value=copytext,
-            style=wx.TE_MULTILINE | wx.TE_READONLY)
+            copyrightwin,
+            id=wx.ID_ANY,
+            value=copytext,
+            style=wx.TE_MULTILINE | wx.TE_READONLY,
+        )
         copyrightwin.SetAutoLayout(True)
         copyrightwin.SetAutoLayout(True)
         copyrightwin.sizer = wx.BoxSizer(wx.VERTICAL)
         copyrightwin.sizer = wx.BoxSizer(wx.VERTICAL)
-        copyrightwin.sizer.Add(copyrighttxt, proportion=1,
-                               flag=wx.EXPAND | wx.ALL, border=3)
+        copyrightwin.sizer.Add(
+            copyrighttxt, proportion=1, flag=wx.EXPAND | wx.ALL, border=3
+        )
         copyrightwin.SetSizer(copyrightwin.sizer)
         copyrightwin.SetSizer(copyrightwin.sizer)
         copyrightwin.Layout()
         copyrightwin.Layout()
         copyrightwin.SetupScrolling()
         copyrightwin.SetupScrolling()
@@ -272,20 +288,24 @@ class AboutWindow(wx.Frame):
         """Licence about"""
         """Licence about"""
         licfile = os.path.join(os.getenv("GISBASE"), "GPL.TXT")
         licfile = os.path.join(os.getenv("GISBASE"), "GPL.TXT")
         if os.path.exists(licfile):
         if os.path.exists(licfile):
-            licenceFile = open(licfile, 'r')
-            license = ''.join(licenceFile.readlines())
+            licenceFile = open(licfile, "r")
+            license = "".join(licenceFile.readlines())
             licenceFile.close()
             licenceFile.close()
         else:
         else:
-            license = _('%s file missing') % 'GPL.TXT'
+            license = _("%s file missing") % "GPL.TXT"
         # put text into a scrolling panel
         # put text into a scrolling panel
         licensewin = ScrolledPanel(self.aboutNotebook)
         licensewin = ScrolledPanel(self.aboutNotebook)
         licensetxt = TextCtrl(
         licensetxt = TextCtrl(
-            licensewin, id=wx.ID_ANY, value=license,
-            style=wx.TE_MULTILINE | wx.TE_READONLY)
+            licensewin,
+            id=wx.ID_ANY,
+            value=license,
+            style=wx.TE_MULTILINE | wx.TE_READONLY,
+        )
         licensewin.SetAutoLayout(True)
         licensewin.SetAutoLayout(True)
         licensewin.sizer = wx.BoxSizer(wx.VERTICAL)
         licensewin.sizer = wx.BoxSizer(wx.VERTICAL)
-        licensewin.sizer.Add(licensetxt, proportion=1,
-                             flag=wx.EXPAND | wx.ALL, border=3)
+        licensewin.sizer.Add(
+            licensetxt, proportion=1, flag=wx.EXPAND | wx.ALL, border=3
+        )
         licensewin.SetSizer(licensewin.sizer)
         licensewin.SetSizer(licensewin.sizer)
         licensewin.Layout()
         licensewin.Layout()
         licensewin.SetupScrolling()
         licensewin.SetupScrolling()
@@ -297,21 +317,23 @@ class AboutWindow(wx.Frame):
         try:
         try:
             # import only when needed
             # import only when needed
             import grass.script as gscript
             import grass.script as gscript
-            text = gscript.read_command('g.version', flags='x')
+
+            text = gscript.read_command("g.version", flags="x")
         except CalledModuleError as error:
         except CalledModuleError as error:
-            text = _("Unable to provide citation suggestion,"
-                     " see GRASS GIS website instead."
-                     " The error was: {0}").format(error)
+            text = _(
+                "Unable to provide citation suggestion,"
+                " see GRASS GIS website instead."
+                " The error was: {0}"
+            ).format(error)
 
 
         # put text into a scrolling panel
         # put text into a scrolling panel
         window = ScrolledPanel(self.aboutNotebook)
         window = ScrolledPanel(self.aboutNotebook)
         stat_text = TextCtrl(
         stat_text = TextCtrl(
-            window, id=wx.ID_ANY, value=text,
-            style=wx.TE_MULTILINE | wx.TE_READONLY)
+            window, id=wx.ID_ANY, value=text, style=wx.TE_MULTILINE | wx.TE_READONLY
+        )
         window.SetAutoLayout(True)
         window.SetAutoLayout(True)
         window.sizer = wx.BoxSizer(wx.VERTICAL)
         window.sizer = wx.BoxSizer(wx.VERTICAL)
-        window.sizer.Add(stat_text, proportion=1,
-                         flag=wx.EXPAND | wx.ALL, border=3)
+        window.sizer.Add(stat_text, proportion=1, flag=wx.EXPAND | wx.ALL, border=3)
         window.SetSizer(window.sizer)
         window.SetSizer(window.sizer)
         window.Layout()
         window.Layout()
         window.SetupScrolling()
         window.SetupScrolling()
@@ -323,19 +345,21 @@ class AboutWindow(wx.Frame):
         # credits
         # credits
         authfile = os.path.join(os.getenv("GISBASE"), "AUTHORS")
         authfile = os.path.join(os.getenv("GISBASE"), "AUTHORS")
         if os.path.exists(authfile):
         if os.path.exists(authfile):
-            with codecs.open(authfile, encoding='utf-8', mode='r') as authorsFile:
-                authors = ''.join(authorsFile.readlines())
+            with codecs.open(authfile, encoding="utf-8", mode="r") as authorsFile:
+                authors = "".join(authorsFile.readlines())
         else:
         else:
-            authors = _('%s file missing') % 'AUTHORS'
+            authors = _("%s file missing") % "AUTHORS"
         authorwin = ScrolledPanel(self.aboutNotebook)
         authorwin = ScrolledPanel(self.aboutNotebook)
         authortxt = TextCtrl(
         authortxt = TextCtrl(
-            authorwin, id=wx.ID_ANY, value=authors,
-            style=wx.TE_MULTILINE | wx.TE_READONLY)
+            authorwin,
+            id=wx.ID_ANY,
+            value=authors,
+            style=wx.TE_MULTILINE | wx.TE_READONLY,
+        )
         authorwin.SetAutoLayout(True)
         authorwin.SetAutoLayout(True)
         authorwin.SetupScrolling()
         authorwin.SetupScrolling()
         authorwin.sizer = wx.BoxSizer(wx.VERTICAL)
         authorwin.sizer = wx.BoxSizer(wx.VERTICAL)
-        authorwin.sizer.Add(authortxt, proportion=1,
-                            flag=wx.EXPAND | wx.ALL, border=3)
+        authorwin.sizer.Add(authortxt, proportion=1, flag=wx.EXPAND | wx.ALL, border=3)
         authorwin.SetSizer(authorwin.sizer)
         authorwin.SetSizer(authorwin.sizer)
         authorwin.Layout()
         authorwin.Layout()
 
 
@@ -344,25 +368,27 @@ class AboutWindow(wx.Frame):
     def _pageContributors(self, extra=False):
     def _pageContributors(self, extra=False):
         """Contributors info"""
         """Contributors info"""
         if extra:
         if extra:
-            contribfile = os.path.join(
-                os.getenv("GISBASE"),
-                "contributors_extra.csv")
+            contribfile = os.path.join(os.getenv("GISBASE"), "contributors_extra.csv")
         else:
         else:
-            contribfile = os.path.join(
-                os.getenv("GISBASE"),
-                "contributors.csv")
+            contribfile = os.path.join(os.getenv("GISBASE"), "contributors.csv")
         if os.path.exists(contribfile):
         if os.path.exists(contribfile):
-            contribFile = codecs.open(contribfile, encoding='utf-8', mode='r')
+            contribFile = codecs.open(contribfile, encoding="utf-8", mode="r")
             contribs = list()
             contribs = list()
             errLines = list()
             errLines = list()
             for line in contribFile.readlines()[1:]:
             for line in contribFile.readlines()[1:]:
-                line = line.rstrip('\n')
+                line = line.rstrip("\n")
                 try:
                 try:
                     if extra:
                     if extra:
-                        name, email, country, rfc2_agreed = line.split(',')
+                        name, email, country, rfc2_agreed = line.split(",")
                     else:
                     else:
-                        cvs_id, name, email, country, osgeo_id, rfc2_agreed = line.split(
-                            ',')
+                        (
+                            cvs_id,
+                            name,
+                            email,
+                            country,
+                            osgeo_id,
+                            rfc2_agreed,
+                        ) = line.split(",")
                 except ValueError:
                 except ValueError:
                     errLines.append(line)
                     errLines.append(line)
                     continue
                     continue
@@ -374,9 +400,13 @@ class AboutWindow(wx.Frame):
             contribFile.close()
             contribFile.close()
 
 
             if errLines:
             if errLines:
-                GError(parent=self, message=_("Error when reading file '%s'.") %
-                       contribfile + "\n\n" + _("Lines:") + " %s" %
-                       os.linesep.join(map(DecodeString, errLines)))
+                GError(
+                    parent=self,
+                    message=_("Error when reading file '%s'.") % contribfile
+                    + "\n\n"
+                    + _("Lines:")
+                    + " %s" % os.linesep.join(map(DecodeString, errLines)),
+                )
         else:
         else:
             contribs = None
             contribs = None
 
 
@@ -387,39 +417,29 @@ class AboutWindow(wx.Frame):
 
 
         if not contribs:
         if not contribs:
             contribtxt = StaticText(
             contribtxt = StaticText(
-                contribwin,
-                id=wx.ID_ANY,
-                label=_('%s file missing') %
-                contribfile)
-            contribwin.sizer.Add(contribtxt, proportion=1,
-                                 flag=wx.EXPAND | wx.ALL, border=3)
+                contribwin, id=wx.ID_ANY, label=_("%s file missing") % contribfile
+            )
+            contribwin.sizer.Add(
+                contribtxt, proportion=1, flag=wx.EXPAND | wx.ALL, border=3
+            )
         else:
         else:
             if extra:
             if extra:
-                items = (_('Name'), _('E-mail'), _('Country'))
+                items = (_("Name"), _("E-mail"), _("Country"))
             else:
             else:
-                items = (_('Name'), _('E-mail'), _('Country'), _('OSGeo_ID'))
+                items = (_("Name"), _("E-mail"), _("Country"), _("OSGeo_ID"))
             contribBox = wx.FlexGridSizer(cols=len(items), vgap=5, hgap=5)
             contribBox = wx.FlexGridSizer(cols=len(items), vgap=5, hgap=5)
             for item in items:
             for item in items:
-                text = StaticText(parent=contribwin, id=wx.ID_ANY,
-                                  label=item)
-                text.SetFont(
-                    wx.Font(
-                        10,
-                        wx.DEFAULT,
-                        wx.NORMAL,
-                        wx.BOLD,
-                        0,
-                        ""))
+                text = StaticText(parent=contribwin, id=wx.ID_ANY, label=item)
+                text.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
                 contribBox.Add(text)
                 contribBox.Add(text)
             for vals in sorted(contribs, key=lambda x: x[0]):
             for vals in sorted(contribs, key=lambda x: x[0]):
                 for item in vals:
                 for item in vals:
                     contribBox.Add(
                     contribBox.Add(
-                        StaticText(
-                            parent=contribwin,
-                            id=wx.ID_ANY,
-                            label=item))
-            contribwin.sizer.Add(contribBox, proportion=1,
-                                 flag=wx.EXPAND | wx.ALL, border=3)
+                        StaticText(parent=contribwin, id=wx.ID_ANY, label=item)
+                    )
+            contribwin.sizer.Add(
+                contribBox, proportion=1, flag=wx.EXPAND | wx.ALL, border=3
+            )
 
 
         contribwin.SetSizer(contribwin.sizer)
         contribwin.SetSizer(contribwin.sizer)
         contribwin.Layout()
         contribwin.Layout()
@@ -430,26 +450,30 @@ class AboutWindow(wx.Frame):
         """Translators info"""
         """Translators info"""
         translatorsfile = os.path.join(os.getenv("GISBASE"), "translators.csv")
         translatorsfile = os.path.join(os.getenv("GISBASE"), "translators.csv")
         if os.path.exists(translatorsfile):
         if os.path.exists(translatorsfile):
-            translatorsFile = codecs.open(translatorsfile, encoding='utf-8', mode='r')
+            translatorsFile = codecs.open(translatorsfile, encoding="utf-8", mode="r")
             translators = dict()
             translators = dict()
             errLines = list()
             errLines = list()
             for line in translatorsFile.readlines()[1:]:
             for line in translatorsFile.readlines()[1:]:
-                line = line.rstrip('\n')
+                line = line.rstrip("\n")
                 try:
                 try:
-                    name, email, languages = line.split(',')
+                    name, email, languages = line.split(",")
                 except ValueError:
                 except ValueError:
                     errLines.append(line)
                     errLines.append(line)
                     continue
                     continue
-                for language in languages.split(' '):
+                for language in languages.split(" "):
                     if language not in translators:
                     if language not in translators:
                         translators[language] = list()
                         translators[language] = list()
                     translators[language].append((name, email))
                     translators[language].append((name, email))
             translatorsFile.close()
             translatorsFile.close()
 
 
             if errLines:
             if errLines:
-                GError(parent=self, message=_("Error when reading file '%s'.") %
-                       translatorsfile + "\n\n" + _("Lines:") + " %s" %
-                       os.linesep.join(map(DecodeString, errLines)))
+                GError(
+                    parent=self,
+                    message=_("Error when reading file '%s'.") % translatorsfile
+                    + "\n\n"
+                    + _("Lines:")
+                    + " %s" % os.linesep.join(map(DecodeString, errLines)),
+                )
         else:
         else:
             translators = None
             translators = None
 
 
@@ -462,63 +486,56 @@ class AboutWindow(wx.Frame):
             translatorstxt = StaticText(
             translatorstxt = StaticText(
                 translatorswin,
                 translatorswin,
                 id=wx.ID_ANY,
                 id=wx.ID_ANY,
-                label=_('%s file missing') %
-                'translators.csv')
-            translatorswin.sizer.Add(translatorstxt, proportion=1,
-                                     flag=wx.EXPAND | wx.ALL, border=3)
+                label=_("%s file missing") % "translators.csv",
+            )
+            translatorswin.sizer.Add(
+                translatorstxt, proportion=1, flag=wx.EXPAND | wx.ALL, border=3
+            )
         else:
         else:
             translatorsBox = wx.FlexGridSizer(cols=4, vgap=5, hgap=5)
             translatorsBox = wx.FlexGridSizer(cols=4, vgap=5, hgap=5)
             languages = sorted(translators.keys())
             languages = sorted(translators.keys())
-            tname = StaticText(parent=translatorswin, id=wx.ID_ANY,
-                               label=_('Name'))
+            tname = StaticText(parent=translatorswin, id=wx.ID_ANY, label=_("Name"))
             tname.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
             tname.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
             translatorsBox.Add(tname)
             translatorsBox.Add(tname)
-            temail = StaticText(parent=translatorswin, id=wx.ID_ANY,
-                                label=_('E-mail'))
+            temail = StaticText(parent=translatorswin, id=wx.ID_ANY, label=_("E-mail"))
             temail.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
             temail.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
             translatorsBox.Add(temail)
             translatorsBox.Add(temail)
-            tlang = StaticText(parent=translatorswin, id=wx.ID_ANY,
-                               label=_('Language'))
+            tlang = StaticText(parent=translatorswin, id=wx.ID_ANY, label=_("Language"))
             tlang.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
             tlang.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
             translatorsBox.Add(tlang)
             translatorsBox.Add(tlang)
-            tnat = StaticText(parent=translatorswin, id=wx.ID_ANY,
-                              label=_('Nation'))
+            tnat = StaticText(parent=translatorswin, id=wx.ID_ANY, label=_("Nation"))
             tnat.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
             tnat.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
             translatorsBox.Add(tnat)
             translatorsBox.Add(tnat)
             for lang in languages:
             for lang in languages:
                 for translator in translators[lang]:
                 for translator in translators[lang]:
                     name, email = translator
                     name, email = translator
                     translatorsBox.Add(
                     translatorsBox.Add(
-                        StaticText(
-                            parent=translatorswin,
-                            id=wx.ID_ANY,
-                            label=name))
+                        StaticText(parent=translatorswin, id=wx.ID_ANY, label=name)
+                    )
                     translatorsBox.Add(
                     translatorsBox.Add(
-                        StaticText(
-                            parent=translatorswin,
-                            id=wx.ID_ANY,
-                            label=email))
+                        StaticText(parent=translatorswin, id=wx.ID_ANY, label=email)
+                    )
                     translatorsBox.Add(
                     translatorsBox.Add(
-                        StaticText(
-                            parent=translatorswin,
-                            id=wx.ID_ANY,
-                            label=lang))
+                        StaticText(parent=translatorswin, id=wx.ID_ANY, label=lang)
+                    )
                     flag = os.path.join(
                     flag = os.path.join(
-                        globalvar.ICONDIR, "flags", "%s.png" %
-                        lang.lower())
+                        globalvar.ICONDIR, "flags", "%s.png" % lang.lower()
+                    )
                     if os.path.exists(flag):
                     if os.path.exists(flag):
-                        flagBitmap = wx.StaticBitmap(translatorswin, wx.ID_ANY, wx.Bitmap(
-                                                     name=flag, type=wx.BITMAP_TYPE_PNG))
+                        flagBitmap = wx.StaticBitmap(
+                            translatorswin,
+                            wx.ID_ANY,
+                            wx.Bitmap(name=flag, type=wx.BITMAP_TYPE_PNG),
+                        )
                         translatorsBox.Add(flagBitmap)
                         translatorsBox.Add(flagBitmap)
                     else:
                     else:
                         translatorsBox.Add(
                         translatorsBox.Add(
-                            StaticText(
-                                parent=translatorswin,
-                                id=wx.ID_ANY,
-                                label=lang))
+                            StaticText(parent=translatorswin, id=wx.ID_ANY, label=lang)
+                        )
 
 
-            translatorswin.sizer.Add(translatorsBox, proportion=1,
-                                     flag=wx.EXPAND | wx.ALL, border=3)
+            translatorswin.sizer.Add(
+                translatorsBox, proportion=1, flag=wx.EXPAND | wx.ALL, border=3
+            )
 
 
         translatorswin.SetSizer(translatorswin.sizer)
         translatorswin.SetSizer(translatorswin.sizer)
         translatorswin.Layout()
         translatorswin.Layout()
@@ -529,15 +546,15 @@ class AboutWindow(wx.Frame):
         """Return string for the status of translation"""
         """Return string for the status of translation"""
         allStr = "%s :" % k.upper()
         allStr = "%s :" % k.upper()
         try:
         try:
-            allStr += _("   %d translated" % v['good'])
+            allStr += _("   %d translated" % v["good"])
         except:
         except:
             pass
             pass
         try:
         try:
-            allStr += _("   %d fuzzy" % v['fuzzy'])
+            allStr += _("   %d fuzzy" % v["fuzzy"])
         except:
         except:
             pass
             pass
         try:
         try:
-            allStr += _("   %d untranslated" % v['bad'])
+            allStr += _("   %d untranslated" % v["bad"])
         except:
         except:
             pass
             pass
         return allStr
         return allStr
@@ -545,43 +562,46 @@ class AboutWindow(wx.Frame):
     def _langBox(self, par, k, v):
     def _langBox(self, par, k, v):
         """Return box"""
         """Return box"""
         langBox = wx.FlexGridSizer(cols=4, vgap=5, hgap=5)
         langBox = wx.FlexGridSizer(cols=4, vgap=5, hgap=5)
-        tkey = StaticText(parent=par, id=wx.ID_ANY,
-                          label=k.upper())
+        tkey = StaticText(parent=par, id=wx.ID_ANY, label=k.upper())
         langBox.Add(tkey)
         langBox.Add(tkey)
         try:
         try:
-            tgood = StaticText(parent=par, id=wx.ID_ANY,
-                               label=_("%d translated" % v['good']))
+            tgood = StaticText(
+                parent=par, id=wx.ID_ANY, label=_("%d translated" % v["good"])
+            )
             tgood.SetForegroundColour(wx.Colour(35, 142, 35))
             tgood.SetForegroundColour(wx.Colour(35, 142, 35))
             langBox.Add(tgood)
             langBox.Add(tgood)
         except:
         except:
-            tgood = StaticText(parent=par, id=wx.ID_ANY,
-                               label="")
+            tgood = StaticText(parent=par, id=wx.ID_ANY, label="")
             langBox.Add(tgood)
             langBox.Add(tgood)
         try:
         try:
-            tfuzzy = StaticText(parent=par, id=wx.ID_ANY,
-                                label=_("   %d fuzzy" % v['fuzzy']))
+            tfuzzy = StaticText(
+                parent=par, id=wx.ID_ANY, label=_("   %d fuzzy" % v["fuzzy"])
+            )
             tfuzzy.SetForegroundColour(wx.Colour(255, 142, 0))
             tfuzzy.SetForegroundColour(wx.Colour(255, 142, 0))
             langBox.Add(tfuzzy)
             langBox.Add(tfuzzy)
         except:
         except:
-            tfuzzy = StaticText(parent=par, id=wx.ID_ANY,
-                                label="")
+            tfuzzy = StaticText(parent=par, id=wx.ID_ANY, label="")
             langBox.Add(tfuzzy)
             langBox.Add(tfuzzy)
         try:
         try:
-            tbad = StaticText(parent=par, id=wx.ID_ANY,
-                              label=_("   %d untranslated" % v['bad']))
+            tbad = StaticText(
+                parent=par, id=wx.ID_ANY, label=_("   %d untranslated" % v["bad"])
+            )
             tbad.SetForegroundColour(wx.Colour(255, 0, 0))
             tbad.SetForegroundColour(wx.Colour(255, 0, 0))
             langBox.Add(tbad)
             langBox.Add(tbad)
         except:
         except:
-            tbad = StaticText(parent=par, id=wx.ID_ANY,
-                              label="")
+            tbad = StaticText(parent=par, id=wx.ID_ANY, label="")
             langBox.Add(tbad)
             langBox.Add(tbad)
         return langBox
         return langBox
 
 
     def _langPanel(self, lang, js):
     def _langPanel(self, lang, js):
         """Create panel for each languages"""
         """Create panel for each languages"""
-        text = self._langString(lang, js['total'])
+        text = self._langString(lang, js["total"])
         panel = wx.CollapsiblePane(
         panel = wx.CollapsiblePane(
-            self.statswin, -1, label=text, style=wx.CP_DEFAULT_STYLE | wx.CP_NO_TLW_RESIZE)
+            self.statswin,
+            -1,
+            label=text,
+            style=wx.CP_DEFAULT_STYLE | wx.CP_NO_TLW_RESIZE,
+        )
         panel.Bind(wx.EVT_COLLAPSIBLEPANE_CHANGED, self.OnPaneChanged)
         panel.Bind(wx.EVT_COLLAPSIBLEPANE_CHANGED, self.OnPaneChanged)
         win = panel.GetPane()
         win = panel.GetPane()
         # TODO IT DOESN'T WORK
         # TODO IT DOESN'T WORK
@@ -592,10 +612,9 @@ class AboutWindow(wx.Frame):
         # panel.Collapse(True)
         # panel.Collapse(True)
         pageSizer = wx.BoxSizer(wx.VERTICAL)
         pageSizer = wx.BoxSizer(wx.VERTICAL)
         for k, v in six.iteritems(js):
         for k, v in six.iteritems(js):
-            if k != 'total' and k != 'name':
+            if k != "total" and k != "name":
                 box = self._langBox(win, k, v)
                 box = self._langBox(win, k, v)
-                pageSizer.Add(box, proportion=1,
-                              flag=wx.EXPAND | wx.ALL, border=3)
+                pageSizer.Add(box, proportion=1, flag=wx.EXPAND | wx.ALL, border=3)
 
 
         win.SetSizer(pageSizer)
         win.SetSizer(pageSizer)
         pageSizer.SetSizeHints(win)
         pageSizer.SetSizeHints(win)
@@ -614,6 +633,7 @@ class AboutWindow(wx.Frame):
         if os.path.exists(statsfile):
         if os.path.exists(statsfile):
             statsFile = open(statsfile)
             statsFile = open(statsfile)
             import json
             import json
+
             jsStats = json.load(statsFile)
             jsStats = json.load(statsFile)
         else:
         else:
             jsStats = None
             jsStats = None
@@ -623,16 +643,16 @@ class AboutWindow(wx.Frame):
         if not jsStats:
         if not jsStats:
             Debug.msg(5, _("File <%s> not found") % fname)
             Debug.msg(5, _("File <%s> not found") % fname)
             statsSizer = wx.BoxSizer(wx.VERTICAL)
             statsSizer = wx.BoxSizer(wx.VERTICAL)
-            statstext = StaticText(self.statswin, id=wx.ID_ANY,
-                                   label=_('%s file missing') % fname)
-            statsSizer.Add(statstext, proportion=1,
-                           flag=wx.EXPAND | wx.ALL, border=3)
+            statstext = StaticText(
+                self.statswin, id=wx.ID_ANY, label=_("%s file missing") % fname
+            )
+            statsSizer.Add(statstext, proportion=1, flag=wx.EXPAND | wx.ALL, border=3)
         else:
         else:
-            languages = sorted(jsStats['langs'].keys())
+            languages = sorted(jsStats["langs"].keys())
 
 
             statsSizer = wx.BoxSizer(wx.VERTICAL)
             statsSizer = wx.BoxSizer(wx.VERTICAL)
             for lang in languages:
             for lang in languages:
-                v = jsStats['langs'][lang]
+                v = jsStats["langs"][lang]
                 panel = self._langPanel(lang, v)
                 panel = self._langPanel(lang, v)
                 statsSizer.Add(panel)
                 statsSizer.Add(panel)
 
 
@@ -661,8 +681,13 @@ class HelpFrame(wx.Dialog):
 
 
     def __init__(self, parent, id, title, size, file):
     def __init__(self, parent, id, title, size, file):
         wx.Dialog.__init__(
         wx.Dialog.__init__(
-            self, parent=parent, id=id, title=title, size=size,
-            style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER | wx.MINIMIZE_BOX)
+            self,
+            parent=parent,
+            id=id,
+            title=title,
+            size=size,
+            style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER | wx.MINIMIZE_BOX,
+        )
 
 
         sizer = wx.BoxSizer(wx.VERTICAL)
         sizer = wx.BoxSizer(wx.VERTICAL)
 
 
@@ -685,8 +710,7 @@ class HelpWindow(HtmlWindow):
     be integrated into the cmdPanel and options are obvious there.
     be integrated into the cmdPanel and options are obvious there.
     """
     """
 
 
-    def __init__(self, parent, command, text, skipDescription,
-                 **kwargs):
+    def __init__(self, parent, command, text, skipDescription, **kwargs):
         """If command is given, the corresponding HTML help
         """If command is given, the corresponding HTML help
         file will be presented, with all links pointing to absolute
         file will be presented, with all links pointing to absolute
         paths of local files.
         paths of local files.
@@ -712,8 +736,7 @@ class HelpWindow(HtmlWindow):
         if text is None:
         if text is None:
             if skipDescription:
             if skipDescription:
                 url = os.path.join(self.fspath, command + ".html")
                 url = os.path.join(self.fspath, command + ".html")
-                self.fillContentsFromFile(url,
-                                          skipDescription=skipDescription)
+                self.fillContentsFromFile(url, skipDescription=skipDescription)
                 self.history.append(url)
                 self.history.append(url)
                 self.loaded = True
                 self.loaded = True
             else:
             else:
@@ -726,7 +749,7 @@ class HelpWindow(HtmlWindow):
 
 
     def OnLinkClicked(self, linkinfo):
     def OnLinkClicked(self, linkinfo):
         url = linkinfo.GetHref()
         url = linkinfo.GetHref()
-        if url[:4] != 'http':
+        if url[:4] != "http":
             url = os.path.join(self.fspath, url)
             url = os.path.join(self.fspath, url)
         self.history.append(url)
         self.history.append(url)
         self.historyIdx += 1
         self.historyIdx += 1
@@ -761,20 +784,20 @@ class HelpWindow(HtmlWindow):
                         if findALink is not None:
                         if findALink is not None:
                             contents.append(
                             contents.append(
                                 aLink.sub(
                                 aLink.sub(
-                                    findALink.group(1) +
-                                    self.fspath +
-                                    findALink.group(2),
-                                    line
+                                    findALink.group(1)
+                                    + self.fspath
+                                    + findALink.group(2),
+                                    line,
                                 )
                                 )
                             )
                             )
                         findImgLink = imgLink.search(line)
                         findImgLink = imgLink.search(line)
                         if findImgLink is not None:
                         if findImgLink is not None:
                             contents.append(
                             contents.append(
                                 imgLink.sub(
                                 imgLink.sub(
-                                    findImgLink.group(1) +
-                                    self.fspath +
-                                    findImgLink.group(2),
-                                    line
+                                    findImgLink.group(1)
+                                    + self.fspath
+                                    + findImgLink.group(2),
+                                    line,
                                 )
                                 )
                             )
                             )
 
 
@@ -787,19 +810,17 @@ class HelpWindow(HtmlWindow):
 
 
 
 
 class HelpPanel(wx.Panel):
 class HelpPanel(wx.Panel):
-
-    def __init__(self, parent, command="index", text=None,
-                 skipDescription=False, **kwargs):
+    def __init__(
+        self, parent, command="index", text=None, skipDescription=False, **kwargs
+    ):
         self.command = command
         self.command = command
         wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY)
         wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY)
 
 
         self.content = HelpWindow(self, command, text, skipDescription)
         self.content = HelpWindow(self, command, text, skipDescription)
 
 
-        self.btnNext = Button(parent=self, id=wx.ID_ANY,
-                                 label=_("&Next"))
+        self.btnNext = Button(parent=self, id=wx.ID_ANY, label=_("&Next"))
         self.btnNext.Enable(False)
         self.btnNext.Enable(False)
-        self.btnPrev = Button(parent=self, id=wx.ID_ANY,
-                                 label=_("&Previous"))
+        self.btnPrev = Button(parent=self, id=wx.ID_ANY, label=_("&Previous"))
         self.btnPrev.Enable(False)
         self.btnPrev.Enable(False)
 
 
         self.btnNext.Bind(wx.EVT_BUTTON, self.OnNext)
         self.btnNext.Bind(wx.EVT_BUTTON, self.OnNext)
@@ -812,16 +833,12 @@ class HelpPanel(wx.Panel):
         sizer = wx.BoxSizer(wx.VERTICAL)
         sizer = wx.BoxSizer(wx.VERTICAL)
         btnSizer = wx.BoxSizer(wx.HORIZONTAL)
         btnSizer = wx.BoxSizer(wx.HORIZONTAL)
 
 
-        btnSizer.Add(self.btnPrev, proportion=0,
-                     flag=wx.ALL, border=5)
+        btnSizer.Add(self.btnPrev, proportion=0, flag=wx.ALL, border=5)
         btnSizer.Add(wx.Size(1, 1), proportion=1)
         btnSizer.Add(wx.Size(1, 1), proportion=1)
-        btnSizer.Add(self.btnNext, proportion=0,
-                     flag=wx.ALL, border=5)
+        btnSizer.Add(self.btnNext, proportion=0, flag=wx.ALL, border=5)
 
 
-        sizer.Add(self.content, proportion=1,
-                  flag=wx.EXPAND)
-        sizer.Add(btnSizer, proportion=0,
-                  flag=wx.EXPAND)
+        sizer.Add(self.content, proportion=1, flag=wx.EXPAND)
+        sizer.Add(btnSizer, proportion=0, flag=wx.EXPAND)
 
 
         self.SetSizer(sizer)
         self.SetSizer(sizer)
         sizer.Fit(self)
         sizer.Fit(self)
@@ -840,10 +857,10 @@ class HelpPanel(wx.Panel):
             return fMan
             return fMan
 
 
         # check also addons
         # check also addons
-        faMan = os.path.join(os.getenv('GRASS_ADDON_BASE'), "docs", "html",
-                             self.command + ".html")
-        if os.getenv('GRASS_ADDON_BASE') and \
-                os.path.isfile(faMan):
+        faMan = os.path.join(
+            os.getenv("GRASS_ADDON_BASE"), "docs", "html", self.command + ".html"
+        )
+        if os.getenv("GRASS_ADDON_BASE") and os.path.isfile(faMan):
             return faMan
             return faMan
 
 
         return None
         return None
@@ -894,47 +911,55 @@ def ShowAboutDialog(prgName, startYear):
     info = AboutDialogInfo()
     info = AboutDialogInfo()
 
 
     info.SetIcon(
     info.SetIcon(
-        wx.Icon(
-            os.path.join(
-                globalvar.ICONDIR,
-                'grass.ico'),
-            wx.BITMAP_TYPE_ICO))
+        wx.Icon(os.path.join(globalvar.ICONDIR, "grass.ico"), wx.BITMAP_TYPE_ICO)
+    )
     info.SetName(prgName)
     info.SetName(prgName)
-    info.SetWebSite('https://grass.osgeo.org')
+    info.SetWebSite("https://grass.osgeo.org")
     info.SetDescription(
     info.SetDescription(
-        _grassDevTeam(startYear) +
-        '\n\n' +
-        '\n'.join(
+        _grassDevTeam(startYear)
+        + "\n\n"
+        + "\n".join(
             textwrap.wrap(
             textwrap.wrap(
-                'This program is free software under the GNU General Public License'
-                '(>=v2). Read the file COPYING that comes with GRASS for details.',
-                75)))
+                "This program is free software under the GNU General Public License"
+                "(>=v2). Read the file COPYING that comes with GRASS for details.",
+                75,
+            )
+        )
+    )
 
 
     AboutBox(info)
     AboutBox(info)
 
 
 
 
 def _grassDevTeam(start):
 def _grassDevTeam(start):
     try:
     try:
-        end = grass.version()['date']
+        end = grass.version()["date"]
     except KeyError:
     except KeyError:
         sys.stderr.write(_("Unable to get GRASS version\n"))
         sys.stderr.write(_("Unable to get GRASS version\n"))
 
 
         from datetime import date
         from datetime import date
+
         end = date.today().year
         end = date.today().year
 
 
-    return '%(c)s %(start)s-%(end)s by the GRASS Development Team' % {
-        'c': chr(169), 'start': start, 'end': end}
+    return "%(c)s %(start)s-%(end)s by the GRASS Development Team" % {
+        "c": chr(169),
+        "start": start,
+        "end": end,
+    }
 
 
 
 
 def main():
 def main():
     """Test application (potentially useful as g.gui.gmanual)"""
     """Test application (potentially useful as g.gui.gmanual)"""
     app = wx.App()
     app = wx.App()
-    frame = HelpFrame(parent=None, id=wx.ID_ANY,
-                      title="Test help application",
-                      size=(600, 800), file=sys.argv[1])
+    frame = HelpFrame(
+        parent=None,
+        id=wx.ID_ANY,
+        title="Test help application",
+        size=(600, 800),
+        file=sys.argv[1],
+    )
     frame.Show()
     frame.Show()
     app.MainLoop()
     app.MainLoop()
 
 
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     main()
     main()

+ 194 - 148
gui/wxpython/gui_core/goutput.py

@@ -27,18 +27,23 @@ from wx import stc
 from grass.pydispatch.signal import Signal
 from grass.pydispatch.signal import Signal
 
 
 # needed just for testing
 # needed just for testing
-if __name__ == '__main__':
+if __name__ == "__main__":
     from grass.script.setup import set_gui_path
     from grass.script.setup import set_gui_path
+
     set_gui_path()
     set_gui_path()
 
 
 from core.gcmd import GError
 from core.gcmd import GError
-from core.gconsole   import GConsole, \
-    EVT_CMD_OUTPUT, EVT_CMD_PROGRESS, EVT_CMD_RUN, EVT_CMD_DONE, \
-    Notification
+from core.gconsole import (
+    GConsole,
+    EVT_CMD_OUTPUT,
+    EVT_CMD_PROGRESS,
+    EVT_CMD_RUN,
+    EVT_CMD_DONE,
+    Notification,
+)
 from core.globalvar import CheckWxVersion, wxPythonPhoenix
 from core.globalvar import CheckWxVersion, wxPythonPhoenix
 from gui_core.prompt import GPromptSTC
 from gui_core.prompt import GPromptSTC
-from gui_core.wrap import Button, ClearButton, ToggleButton, StaticText, \
-    StaticBox
+from gui_core.wrap import Button, ClearButton, ToggleButton, StaticText, StaticBox
 from core.settings import UserSettings
 from core.settings import UserSettings
 
 
 
 
@@ -47,13 +52,19 @@ GC_PROMPT = 1
 
 
 
 
 class GConsoleWindow(wx.SplitterWindow):
 class GConsoleWindow(wx.SplitterWindow):
-    """Create and manage output console for commands run by GUI.
-    """
-
-    def __init__(self, parent, giface, gconsole, menuModel=None, margin=False,
-                 style=wx.TAB_TRAVERSAL | wx.FULL_REPAINT_ON_RESIZE,
-                 gcstyle=GC_EMPTY,
-                 **kwargs):
+    """Create and manage output console for commands run by GUI."""
+
+    def __init__(
+        self,
+        parent,
+        giface,
+        gconsole,
+        menuModel=None,
+        margin=False,
+        style=wx.TAB_TRAVERSAL | wx.FULL_REPAINT_ON_RESIZE,
+        gcstyle=GC_EMPTY,
+        **kwargs,
+    ):
         """
         """
         :param parent: gui parent
         :param parent: gui parent
         :param gconsole: console logic
         :param gconsole: console logic
@@ -63,15 +74,13 @@ class GConsoleWindow(wx.SplitterWindow):
         :param gcstyle: GConsole style
         :param gcstyle: GConsole style
                         (GC_EMPTY, GC_PROMPT to show command prompt)
                         (GC_EMPTY, GC_PROMPT to show command prompt)
         """
         """
-        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.SetName("GConsole")
 
 
         self.panelOutput = wx.Panel(parent=self, id=wx.ID_ANY)
         self.panelOutput = wx.Panel(parent=self, id=wx.ID_ANY)
         self.panelProgress = wx.Panel(
         self.panelProgress = wx.Panel(
-            parent=self.panelOutput,
-            id=wx.ID_ANY,
-            name='progressPanel')
+            parent=self.panelOutput, id=wx.ID_ANY, name="progressPanel"
+        )
         self.panelPrompt = wx.Panel(parent=self, id=wx.ID_ANY)
         self.panelPrompt = wx.Panel(parent=self, id=wx.ID_ANY)
         # initialize variables
         # initialize variables
         self.parent = parent  # GMFrame | CmdPanel | ?
         self.parent = parent  # GMFrame | CmdPanel | ?
@@ -89,9 +98,14 @@ class GConsoleWindow(wx.SplitterWindow):
         self.contentChanged = Signal("GConsoleWindow.contentChanged")
         self.contentChanged = Signal("GConsoleWindow.contentChanged")
 
 
         # progress bar
         # 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_PROGRESS, self.OnCmdProgress)
         self._gconsole.Bind(EVT_CMD_OUTPUT, self.OnCmdOutput)
         self._gconsole.Bind(EVT_CMD_OUTPUT, self.OnCmdOutput)
         self._gconsole.Bind(EVT_CMD_RUN, self.OnCmdRun)
         self._gconsole.Bind(EVT_CMD_RUN, self.OnCmdRun)
@@ -104,10 +118,8 @@ class GConsoleWindow(wx.SplitterWindow):
 
 
         # text control for command output
         # text control for command output
         self.cmdOutput = GStc(
         self.cmdOutput = GStc(
-            parent=self.panelOutput,
-            id=wx.ID_ANY,
-            margin=margin,
-            wrap=None)
+            parent=self.panelOutput, id=wx.ID_ANY, margin=margin, wrap=None
+        )
 
 
         # command prompt
         # command prompt
         # move to the if below
         # move to the if below
@@ -115,8 +127,9 @@ class GConsoleWindow(wx.SplitterWindow):
         self.cmdPrompt = GPromptSTC(
         self.cmdPrompt = GPromptSTC(
             parent=self, giface=giface, menuModel=self._menuModel
             parent=self, giface=giface, menuModel=self._menuModel
         )
         )
-        self.cmdPrompt.promptRunCmd.connect(lambda cmd:
-                                            self._gconsole.RunCmd(command=cmd))
+        self.cmdPrompt.promptRunCmd.connect(
+            lambda cmd: self._gconsole.RunCmd(command=cmd)
+        )
         self.cmdPrompt.showNotification.connect(self.showNotification)
         self.cmdPrompt.showNotification.connect(self.showNotification)
 
 
         if not self._gcstyle & GC_PROMPT:
         if not self._gcstyle & GC_PROMPT:
@@ -125,13 +138,12 @@ class GConsoleWindow(wx.SplitterWindow):
         if self._gcstyle & GC_PROMPT:
         if self._gcstyle & GC_PROMPT:
             cmdLabel = _("Command prompt")
             cmdLabel = _("Command prompt")
             self.outputBox = StaticBox(
             self.outputBox = StaticBox(
-                parent=self.panelOutput,
-                id=wx.ID_ANY,
-                label=" %s " %
-                _("Output window"))
+                parent=self.panelOutput, id=wx.ID_ANY, label=" %s " % _("Output window")
+            )
 
 
-            self.cmdBox = StaticBox(parent=self.panelOutput, id=wx.ID_ANY,
-                                    label=" %s " % cmdLabel)
+            self.cmdBox = StaticBox(
+                parent=self.panelOutput, id=wx.ID_ANY, label=" %s " % cmdLabel
+            )
 
 
         # buttons
         # buttons
         self.btnOutputClear = ClearButton(parent=self.panelOutput)
         self.btnOutputClear = ClearButton(parent=self.panelOutput)
@@ -139,17 +151,21 @@ class GConsoleWindow(wx.SplitterWindow):
         self.btnCmdClear = ClearButton(parent=self.panelOutput)
         self.btnCmdClear = ClearButton(parent=self.panelOutput)
         self.btnCmdClear.SetToolTip(_("Clear command prompt content"))
         self.btnCmdClear.SetToolTip(_("Clear command prompt content"))
         self.btnOutputSave = Button(parent=self.panelOutput, id=wx.ID_SAVE)
         self.btnOutputSave = Button(parent=self.panelOutput, id=wx.ID_SAVE)
-        self.btnOutputSave.SetToolTip(
-            _("Save output window content to the file"))
+        self.btnOutputSave.SetToolTip(_("Save output window content to the file"))
         self.btnCmdAbort = Button(parent=self.panelProgress, id=wx.ID_STOP)
         self.btnCmdAbort = Button(parent=self.panelProgress, id=wx.ID_STOP)
         self.btnCmdAbort.SetToolTip(_("Abort running command"))
         self.btnCmdAbort.SetToolTip(_("Abort running command"))
         self.btnCmdProtocol = ToggleButton(
         self.btnCmdProtocol = ToggleButton(
             parent=self.panelOutput,
             parent=self.panelOutput,
             id=wx.ID_ANY,
             id=wx.ID_ANY,
             label=_("&Log file"),
             label=_("&Log file"),
-            size=self.btnCmdClear.GetSize())
-        self.btnCmdProtocol.SetToolTip(_("Toggle to save list of executed commands into "
-                                         "a file; content saved when switching off."))
+            size=self.btnCmdClear.GetSize(),
+        )
+        self.btnCmdProtocol.SetToolTip(
+            _(
+                "Toggle to save list of executed commands into "
+                "a file; content saved when switching off."
+            )
+        )
         self.cmdFileProtocol = None
         self.cmdFileProtocol = None
 
 
         if not self._gcstyle & GC_PROMPT:
         if not self._gcstyle & GC_PROMPT:
@@ -178,20 +194,25 @@ class GConsoleWindow(wx.SplitterWindow):
 
 
         if self._gcstyle & GC_PROMPT:
         if self._gcstyle & GC_PROMPT:
             promptSizer = wx.BoxSizer(wx.VERTICAL)
             promptSizer = wx.BoxSizer(wx.VERTICAL)
-            promptSizer.Add(self.cmdPrompt, proportion=1,
-                            flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP,
-                            border=3)
+            promptSizer.Add(
+                self.cmdPrompt,
+                proportion=1,
+                flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP,
+                border=3,
+            )
             helpText = StaticText(
             helpText = StaticText(
-                self.panelPrompt, id=wx.ID_ANY,
-                label="Press Tab to display command help, Ctrl+Space to autocomplete")
+                self.panelPrompt,
+                id=wx.ID_ANY,
+                label="Press Tab to display command help, Ctrl+Space to autocomplete",
+            )
             helpText.SetForegroundColour(
             helpText.SetForegroundColour(
-                wx.SystemSettings.GetColour(
-                    wx.SYS_COLOUR_GRAYTEXT))
-            promptSizer.Add(helpText,
-                            proportion=0, flag=wx.EXPAND | wx.LEFT, border=5)
+                wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)
+            )
+            promptSizer.Add(helpText, proportion=0, flag=wx.EXPAND | wx.LEFT, border=5)
 
 
-        self.outputSizer.Add(self.cmdOutput, proportion=1,
-                             flag=wx.EXPAND | wx.ALL, border=3)
+        self.outputSizer.Add(
+            self.cmdOutput, proportion=1, flag=wx.EXPAND | wx.ALL, border=3
+        )
         if self._gcstyle & GC_PROMPT:
         if self._gcstyle & GC_PROMPT:
             proportion = 1
             proportion = 1
         else:
         else:
@@ -202,40 +223,54 @@ class GConsoleWindow(wx.SplitterWindow):
             self.btnOutputClear,
             self.btnOutputClear,
             proportion=proportion,
             proportion=proportion,
             flag=wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.BOTTOM,
             flag=wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.BOTTOM,
-            border=5)
+            border=5,
+        )
 
 
-        outBtnSizer.Add(self.btnOutputSave, proportion=proportion,
-                        flag=wx.RIGHT | wx.BOTTOM, border=5)
+        outBtnSizer.Add(
+            self.btnOutputSave,
+            proportion=proportion,
+            flag=wx.RIGHT | wx.BOTTOM,
+            border=5,
+        )
 
 
         cmdBtnSizer.Add(
         cmdBtnSizer.Add(
             self.btnCmdProtocol,
             self.btnCmdProtocol,
             proportion=1,
             proportion=1,
-            flag=wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT | wx.BOTTOM,
-            border=5)
-        cmdBtnSizer.Add(self.btnCmdClear, proportion=1,
-                        flag=wx.ALIGN_CENTER | wx.RIGHT | wx.BOTTOM, border=5)
-        progressSizer.Add(self.btnCmdAbort, proportion=0,
-                          flag=wx.ALL | wx.ALIGN_CENTER, border=5)
+            flag=wx.ALIGN_CENTER
+            | wx.ALIGN_CENTER_VERTICAL
+            | wx.LEFT
+            | wx.RIGHT
+            | wx.BOTTOM,
+            border=5,
+        )
+        cmdBtnSizer.Add(
+            self.btnCmdClear,
+            proportion=1,
+            flag=wx.ALIGN_CENTER | wx.RIGHT | wx.BOTTOM,
+            border=5,
+        )
+        progressSizer.Add(
+            self.btnCmdAbort, proportion=0, flag=wx.ALL | wx.ALIGN_CENTER, border=5
+        )
         progressSizer.Add(
         progressSizer.Add(
             self.progressbar,
             self.progressbar,
             proportion=1,
             proportion=1,
             flag=wx.ALIGN_CENTER | wx.RIGHT | wx.TOP | wx.BOTTOM,
             flag=wx.ALIGN_CENTER | wx.RIGHT | wx.TOP | wx.BOTTOM,
-            border=5)
+            border=5,
+        )
 
 
         self.panelProgress.SetSizer(progressSizer)
         self.panelProgress.SetSizer(progressSizer)
         progressSizer.Fit(self.panelProgress)
         progressSizer.Fit(self.panelProgress)
 
 
-        btnSizer.Add(outBtnSizer, proportion=1,
-                     flag=wx.ALL | wx.ALIGN_CENTER, border=5)
+        btnSizer.Add(outBtnSizer, proportion=1, flag=wx.ALL | wx.ALIGN_CENTER, border=5)
         btnSizer.Add(
         btnSizer.Add(
             cmdBtnSizer,
             cmdBtnSizer,
             proportion=1,
             proportion=1,
             flag=wx.ALIGN_CENTER | wx.TOP | wx.BOTTOM | wx.RIGHT,
             flag=wx.ALIGN_CENTER | wx.TOP | wx.BOTTOM | wx.RIGHT,
-            border=5)
-        self.outputSizer.Add(self.panelProgress, proportion=0,
-                             flag=wx.EXPAND)
-        self.outputSizer.Add(btnSizer, proportion=0,
-                             flag=wx.EXPAND)
+            border=5,
+        )
+        self.outputSizer.Add(self.panelProgress, proportion=0, flag=wx.EXPAND)
+        self.outputSizer.Add(btnSizer, proportion=0, flag=wx.EXPAND)
 
 
         self.outputSizer.Fit(self)
         self.outputSizer.Fit(self)
         self.outputSizer.SetSizeHints(self)
         self.outputSizer.SetSizeHints(self)
@@ -273,8 +308,9 @@ class GConsoleWindow(wx.SplitterWindow):
 
 
         return self.panelOutput
         return self.panelOutput
 
 
-    def WriteLog(self, text, style=None, wrap=None,
-                 notification=Notification.HIGHLIGHT):
+    def WriteLog(
+        self, text, style=None, wrap=None, notification=Notification.HIGHLIGHT
+    ):
         """Generic method for writing log message in
         """Generic method for writing log message in
         given style.
         given style.
 
 
@@ -304,7 +340,7 @@ class GConsoleWindow(wx.SplitterWindow):
             # fill space
             # fill space
             if len(line) < self.lineWidth:
             if len(line) < self.lineWidth:
                 diff = self.lineWidth - len(line)
                 diff = self.lineWidth - len(line)
-                line += diff * ' '
+                line += diff * " "
 
 
             self.cmdOutput.AddTextWrapped(line, wrap=wrap)  # adds '\n'
             self.cmdOutput.AddTextWrapped(line, wrap=wrap)  # adds '\n'
 
 
@@ -314,15 +350,14 @@ class GConsoleWindow(wx.SplitterWindow):
             try:
             try:
                 self.cmdOutput.StartStyling(p1)
                 self.cmdOutput.StartStyling(p1)
             except TypeError:
             except TypeError:
-                self.cmdOutput.StartStyling(p1, 0xff)
+                self.cmdOutput.StartStyling(p1, 0xFF)
             self.cmdOutput.SetStyling(p2 - p1, style)
             self.cmdOutput.SetStyling(p2 - p1, style)
 
 
         self.cmdOutput.EnsureCaretVisible()
         self.cmdOutput.EnsureCaretVisible()
 
 
         self.contentChanged.emit(notification=notification)
         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
         """Write message in selected style
 
 
         :param text: message to be printed
         :param text: message to be printed
@@ -330,21 +365,26 @@ class GConsoleWindow(wx.SplitterWindow):
         :param switchPage: True to switch page
         :param switchPage: True to switch page
         """
         """
         if pid:
         if pid:
-            text = '(' + str(pid) + ') ' + text
+            text = "(" + str(pid) + ") " + text
         self.WriteLog(
         self.WriteLog(
-            text,
-            style=self.cmdOutput.StyleCommand,
-            notification=notification)
+            text, style=self.cmdOutput.StyleCommand, notification=notification
+        )
 
 
     def WriteWarning(self, text):
     def WriteWarning(self, text):
         """Write message in warning style"""
         """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):
     def WriteError(self, text):
         """Write message in error style"""
         """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):
     def OnOutputClear(self, event):
         """Clear content of output window"""
         """Clear content of output window"""
@@ -364,16 +404,17 @@ class GConsoleWindow(wx.SplitterWindow):
             text = self.cmdOutput.GetText()
             text = self.cmdOutput.GetText()
 
 
         # add newline if needed
         # add newline if needed
-        if len(text) > 0 and text[-1] != '\n':
-            text += '\n'
+        if len(text) > 0 and text[-1] != "\n":
+            text += "\n"
 
 
         dlg = wx.FileDialog(
         dlg = wx.FileDialog(
-            self, message=_("Save file as..."),
+            self,
+            message=_("Save file as..."),
             defaultFile="grass_cmd_output.txt",
             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)
+            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,
         # Show the dialog and retrieve the user response. If it is the OK response,
         # process the data.
         # process the data.
@@ -385,9 +426,9 @@ class GConsoleWindow(wx.SplitterWindow):
                 output.write(text)
                 output.write(text)
             except IOError as e:
             except IOError as e:
                 GError(
                 GError(
-                    _("Unable to write file '%(path)s'.\n\nDetails: %(error)s") % {
-                        'path': path,
-                        'error': e})
+                    _("Unable to write file '%(path)s'.\n\nDetails: %(error)s")
+                    % {"path": path, "error": e}
+                )
             finally:
             finally:
                 output.close()
                 output.close()
             message = _("Command output saved into '%s'") % path
             message = _("Command output saved into '%s'") % path
@@ -403,11 +444,11 @@ class GConsoleWindow(wx.SplitterWindow):
         """
         """
         if copy:
         if copy:
             self.cmdPrompt.Bind(
             self.cmdPrompt.Bind(
-                stc.EVT_STC_PAINTED,
-                self.cmdPrompt.OnTextSelectionChanged)
+                stc.EVT_STC_PAINTED, self.cmdPrompt.OnTextSelectionChanged
+            )
             self.cmdOutput.Bind(
             self.cmdOutput.Bind(
-                stc.EVT_STC_PAINTED,
-                self.cmdOutput.OnTextSelectionChanged)
+                stc.EVT_STC_PAINTED, self.cmdOutput.OnTextSelectionChanged
+            )
         else:
         else:
             self.cmdPrompt.Unbind(stc.EVT_STC_PAINTED)
             self.cmdPrompt.Unbind(stc.EVT_STC_PAINTED)
             self.cmdOutput.Unbind(stc.EVT_STC_PAINTED)
             self.cmdOutput.Unbind(stc.EVT_STC_PAINTED)
@@ -422,7 +463,7 @@ class GConsoleWindow(wx.SplitterWindow):
 
 
         self.cmdOutput.AddStyledMessage(message, type)
         self.cmdOutput.AddStyledMessage(message, type)
 
 
-        if event.type in ('warning', 'error'):
+        if event.type in ("warning", "error"):
             self.contentChanged.emit(notification=Notification.MAKE_VISIBLE)
             self.contentChanged.emit(notification=Notification.MAKE_VISIBLE)
         else:
         else:
             self.contentChanged.emit(notification=Notification.HIGHLIGHT)
             self.contentChanged.emit(notification=Notification.HIGHLIGHT)
@@ -440,12 +481,15 @@ class GConsoleWindow(wx.SplitterWindow):
         try:
         try:
             with open(self.cmdFileProtocol, "a") as output:
             with open(self.cmdFileProtocol, "a") as output:
                 cmds = self.cmdPrompt.GetCommands()
                 cmds = self.cmdPrompt.GetCommands()
-                output.write('\n'.join(cmds))
+                output.write("\n".join(cmds))
                 if len(cmds) > 0:
                 if len(cmds) > 0:
-                    output.write('\n')
+                    output.write("\n")
         except IOError as e:
         except IOError as e:
-            GError(_("Unable to write file '{filePath}'.\n\nDetails: {error}").format(
-                filePath=self.cmdFileProtocol, error=e))
+            GError(
+                _("Unable to write file '{filePath}'.\n\nDetails: {error}").format(
+                    filePath=self.cmdFileProtocol, error=e
+                )
+            )
 
 
         self.showNotification.emit(
         self.showNotification.emit(
             message=_("Command log saved to '{}'".format(self.cmdFileProtocol))
             message=_("Command log saved to '{}'".format(self.cmdFileProtocol))
@@ -463,12 +507,13 @@ class GConsoleWindow(wx.SplitterWindow):
             self.cmdPrompt.ClearCommands()
             self.cmdPrompt.ClearCommands()
             # ask for the file
             # ask for the file
             dlg = wx.FileDialog(
             dlg = wx.FileDialog(
-                self, message=_("Save file as..."),
+                self,
+                message=_("Save file as..."),
                 defaultFile="grass_cmd_log.txt",
                 defaultFile="grass_cmd_log.txt",
-                wildcard=_("%(txt)s (*.txt)|*.txt|%(files)s (*)|*") %
-                {'txt': _("Text files"),
-                 'files': _("Files")},
-                style=wx.FD_SAVE)
+                wildcard=_("%(txt)s (*.txt)|*.txt|%(files)s (*)|*")
+                % {"txt": _("Text files"), "files": _("Files")},
+                style=wx.FD_SAVE,
+            )
             if dlg.ShowModal() == wx.ID_OK:
             if dlg.ShowModal() == wx.ID_OK:
                 self.cmdFileProtocol = dlg.GetPath()
                 self.cmdFileProtocol = dlg.GetPath()
             else:
             else:
@@ -485,8 +530,7 @@ class GConsoleWindow(wx.SplitterWindow):
         event.Skip()
         event.Skip()
 
 
     def OnCmdDone(self, event):
     def OnCmdDone(self, event):
-        """Command done (or aborted)
-        """
+        """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)
         wx.CallLater(100, self._hideProgress)
         event.Skip()
         event.Skip()
@@ -549,8 +593,9 @@ class GStc(stc.StyledTextCtrl):
         self.SetTabWidth(4)
         self.SetTabWidth(4)
         self.SetUseTabs(False)
         self.SetUseTabs(False)
         self.UsePopUp(True)
         self.UsePopUp(True)
-        self.SetSelBackground(True,
-            wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT))
+        self.SetSelBackground(
+            True, wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT)
+        )
         self.SetUseHorizontalScrollBar(True)
         self.SetUseHorizontalScrollBar(True)
 
 
         #
         #
@@ -569,17 +614,11 @@ class GStc(stc.StyledTextCtrl):
         """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)"""
         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 == "":
         if typeface == "":
             typeface = "Courier New"
             typeface = "Courier New"
 
 
-        typesize = UserSettings.Get(
-            group='appearance',
-            key='outputfont',
-            subkey='size')
+        typesize = UserSettings.Get(group="appearance", key="outputfont", subkey="size")
         if typesize is None or int(typesize) <= 0:
         if typesize is None or int(typesize) <= 0:
             typesize = 10
             typesize = 10
         typesize = float(typesize)
         typesize = float(typesize)
@@ -654,14 +693,14 @@ class GStc(stc.StyledTextCtrl):
         self.SetReadOnly(False)
         self.SetReadOnly(False)
 
 
         if wrap:
         if wrap:
-            txt = textwrap.fill(txt, wrap) + '\n'
+            txt = textwrap.fill(txt, wrap) + "\n"
         else:
         else:
-            if txt[-1] != '\n':
-                txt += '\n'
+            if txt[-1] != "\n":
+                txt += "\n"
 
 
-        if '\r' in txt:
+        if "\r" in txt:
             self.linePos = -1
             self.linePos = -1
-            for seg in txt.split('\r'):
+            for seg in txt.split("\r"):
                 if self.linePos > -1:
                 if self.linePos > -1:
                     self.SetCurrentPos(self.linePos)
                     self.SetCurrentPos(self.linePos)
                     self.ReplaceSelection(seg)
                     self.ReplaceSelection(seg)
@@ -685,38 +724,38 @@ class GStc(stc.StyledTextCtrl):
                       'warning', 'error' or None
                       'warning', 'error' or None
         """
         """
         # message prefix
         # message prefix
-        if style == 'warning':
-            message = 'WARNING: ' + message
-        elif style == 'error':
-            message = 'ERROR: ' + message
+        if style == "warning":
+            message = "WARNING: " + message
+        elif style == "error":
+            message = "ERROR: " + message
 
 
         p1 = self.GetEndStyled()
         p1 = self.GetEndStyled()
         self.GotoPos(p1)
         self.GotoPos(p1)
 
 
         # is this still needed?
         # is this still needed?
-        if '\b' in message:
+        if "\b" in message:
             if self.linePos < 0:
             if self.linePos < 0:
                 self.linePos = p1
                 self.linePos = p1
-            last_c = ''
+            last_c = ""
             for c in message:
             for c in message:
-                if c == '\b':
+                if c == "\b":
                     self.linePos -= 1
                     self.linePos -= 1
                 else:
                 else:
-                    if c == '\r':
+                    if c == "\r":
                         pos = self.GetCurLine()[1]
                         pos = self.GetCurLine()[1]
                         # self.SetCurrentPos(pos)
                         # self.SetCurrentPos(pos)
                     else:
                     else:
                         self.SetCurrentPos(self.linePos)
                         self.SetCurrentPos(self.linePos)
                     self.ReplaceSelection(c)
                     self.ReplaceSelection(c)
                     self.linePos = self.GetCurrentPos()
                     self.linePos = self.GetCurrentPos()
-                    if c != ' ':
+                    if c != " ":
                         last_c = c
                         last_c = c
-            if last_c not in ('0123456789'):
-                self.AddTextWrapped('\n', wrap=None)
+            if last_c not in ("0123456789"):
+                self.AddTextWrapped("\n", wrap=None)
                 self.linePos = -1
                 self.linePos = -1
         else:
         else:
             self.linePos = -1  # don't force position
             self.linePos = -1  # don't force position
-            if '\n' not in message:
+            if "\n" not in message:
                 self.AddTextWrapped(message, wrap=60)
                 self.AddTextWrapped(message, wrap=60)
             else:
             else:
                 self.AddTextWrapped(message, wrap=None)
                 self.AddTextWrapped(message, wrap=None)
@@ -726,13 +765,13 @@ class GStc(stc.StyledTextCtrl):
             try:
             try:
                 self.StartStyling(p1)
                 self.StartStyling(p1)
             except TypeError:
             except TypeError:
-                self.StartStyling(p1, 0xff)
+                self.StartStyling(p1, 0xFF)
 
 
-            if style == 'error':
+            if style == "error":
                 self.SetStyling(p2 - p1, self.StyleError)
                 self.SetStyling(p2 - p1, self.StyleError)
-            elif style == 'warning':
+            elif style == "warning":
                 self.SetStyling(p2 - p1, self.StyleWarning)
                 self.SetStyling(p2 - p1, self.StyleWarning)
-            elif style == 'message':
+            elif style == "message":
                 self.SetStyling(p2 - p1, self.StyleMessage)
                 self.SetStyling(p2 - p1, self.StyleMessage)
             else:  # unknown
             else:  # unknown
                 self.SetStyling(p2 - p1, self.StyleUnknown)
                 self.SetStyling(p2 - p1, self.StyleUnknown)
@@ -743,25 +782,31 @@ class GStc(stc.StyledTextCtrl):
 class GConsoleFrame(wx.Frame):
 class GConsoleFrame(wx.Frame):
     """Standalone GConsole for testing only"""
     """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):
+    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)
         wx.Frame.__init__(self, parent=parent, id=id, title=title, style=style)
 
 
         panel = wx.Panel(self, id=wx.ID_ANY)
         panel = wx.Panel(self, id=wx.ID_ANY)
 
 
         from lmgr.menudata import LayerManagerMenuData
         from lmgr.menudata import LayerManagerMenuData
+
         menuTreeBuilder = LayerManagerMenuData()
         menuTreeBuilder = LayerManagerMenuData()
         self.gconsole = GConsole(guiparent=self)
         self.gconsole = GConsole(guiparent=self)
-        self.goutput = GConsoleWindow(parent=panel, gconsole=self.gconsole,
-                                      menuModel=menuTreeBuilder.GetModel(),
-                                      gcstyle=GC_PROMPT)
+        self.goutput = GConsoleWindow(
+            parent=panel,
+            gconsole=self.gconsole,
+            menuModel=menuTreeBuilder.GetModel(),
+            gcstyle=GC_PROMPT,
+        )
 
 
         mainSizer = wx.BoxSizer(wx.VERTICAL)
         mainSizer = wx.BoxSizer(wx.VERTICAL)
-        mainSizer.Add(
-            self.goutput,
-            proportion=1,
-            flag=wx.EXPAND,
-            border=0)
+        mainSizer.Add(self.goutput, proportion=1, flag=wx.EXPAND, border=0)
 
 
         panel.SetSizer(mainSizer)
         panel.SetSizer(mainSizer)
         mainSizer.Fit(panel)
         mainSizer.Fit(panel)
@@ -774,5 +819,6 @@ def testGConsole():
     frame.Show()
     frame.Show()
     app.MainLoop()
     app.MainLoop()
 
 
-if __name__ == '__main__':
+
+if __name__ == "__main__":
     testGConsole()
     testGConsole()

Plik diff jest za duży
+ 960 - 855
gui/wxpython/gui_core/gselect.py


+ 9 - 4
gui/wxpython/gui_core/infobar.py

@@ -19,6 +19,7 @@ This program is free software under the GNU General Public License
 import sys
 import sys
 import wx
 import wx
 import wx.aui
 import wx.aui
+
 try:
 try:
     import wx.lib.agw.infobar as IB
     import wx.lib.agw.infobar as IB
 except ImportError:
 except ImportError:
@@ -30,14 +31,16 @@ def GetCloseButtonBitmap(win, size, colBg, flags=0):
     of wx.RendererNative in certain wx versions.
     of wx.RendererNative in certain wx versions.
     See https://github.com/wxWidgets/Phoenix/issues/1425."""
     See https://github.com/wxWidgets/Phoenix/issues/1425."""
     renderer = wx.RendererNative.Get()
     renderer = wx.RendererNative.Get()
-    if hasattr(renderer, 'DrawTitleBarBitmap'):
+    if hasattr(renderer, "DrawTitleBarBitmap"):
         bmp = wx.Bitmap(*size)
         bmp = wx.Bitmap(*size)
         dc = wx.MemoryDC()
         dc = wx.MemoryDC()
         dc.SelectObject(bmp)
         dc.SelectObject(bmp)
         dc.SetBackground(wx.Brush(colBg))
         dc.SetBackground(wx.Brush(colBg))
         dc.Clear()
         dc.Clear()
 
 
-        wx.RendererNative.Get().DrawTitleBarBitmap(win, dc, wx.Rect(size), wx.TITLEBAR_BUTTON_CLOSE, flags)
+        wx.RendererNative.Get().DrawTitleBarBitmap(
+            win, dc, wx.Rect(size), wx.TITLEBAR_BUTTON_CLOSE, flags
+        )
         dc.SelectObject(wx.NullBitmap)
         dc.SelectObject(wx.NullBitmap)
     else:
     else:
         bmp = wx.ArtProvider.GetBitmap(wx.ART_CLOSE, wx.ART_BUTTON)
         bmp = wx.ArtProvider.GetBitmap(wx.ART_CLOSE, wx.ART_BUTTON)
@@ -122,7 +125,7 @@ class InfoBar(IB.InfoBar):
         button.SetBackgroundColour(self._background_color)
         button.SetBackgroundColour(self._background_color)
         button.SetForegroundColour(self._foreground_color)
         button.SetForegroundColour(self._foreground_color)
 
 
-        if wx.Platform == '__WXMAC__':
+        if wx.Platform == "__WXMAC__":
             # smaller buttons look better in the(narrow)info bar under OS X
             # smaller buttons look better in the(narrow)info bar under OS X
             button.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
             button.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
 
 
@@ -132,7 +135,9 @@ class InfoBar(IB.InfoBar):
             self.subSizerButtons.Add(self._button, wx.SizerFlags().Centre().Border())
             self.subSizerButtons.Add(self._button, wx.SizerFlags().Centre().Border())
             self._button.Show()
             self._button.Show()
         else:
         else:
-            self.subSizerButtons.Insert(num_items - 1, button, wx.SizerFlags().Centre().Border())
+            self.subSizerButtons.Insert(
+                num_items - 1, button, wx.SizerFlags().Centre().Border()
+            )
 
 
         if self.IsShown():
         if self.IsShown():
             self.UpdateParent()
             self.UpdateParent()

+ 142 - 121
gui/wxpython/gui_core/mapdisp.py

@@ -57,9 +57,16 @@ class MapFrameBase(wx.Frame):
     AUI manager is stored in \c self._mgr.
     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::
         .. warning::
@@ -77,14 +84,7 @@ class MapFrameBase(wx.Frame):
 
 
         self.parent = parent
         self.parent = parent
 
 
-        wx.Frame.__init__(
-            self,
-            parent,
-            id,
-            title,
-            style=style,
-            name=name,
-            **kwargs)
+        wx.Frame.__init__(self, parent, id, title, style=style, name=name, **kwargs)
 
 
         #
         #
         # set the size & system icon
         # set the size & system icon
@@ -94,10 +94,9 @@ class MapFrameBase(wx.Frame):
 
 
         self.SetIcon(
         self.SetIcon(
             wx.Icon(
             wx.Icon(
-                os.path.join(
-                    globalvar.ICONDIR,
-                    'grass_map.ico'),
-                wx.BITMAP_TYPE_ICO))
+                os.path.join(globalvar.ICONDIR, "grass_map.ico"), wx.BITMAP_TYPE_ICO
+            )
+        )
 
 
         # toolbars
         # toolbars
         self.toolbars = {}
         self.toolbars = {}
@@ -107,6 +106,7 @@ class MapFrameBase(wx.Frame):
         #
         #
         if auimgr is None:
         if auimgr is None:
             from wx.aui import AuiManager
             from wx.aui import AuiManager
+
             self._mgr = AuiManager(self)
             self._mgr = AuiManager(self)
         else:
         else:
             self._mgr = auimgr
             self._mgr = auimgr
@@ -122,8 +122,8 @@ class MapFrameBase(wx.Frame):
         # set accelerator table (fullscreen, close window)
         # set accelerator table (fullscreen, close window)
         shortcuts_table = (
         shortcuts_table = (
             (self.OnFullScreen, wx.ACCEL_NORMAL, wx.WXK_F11),
             (self.OnFullScreen, wx.ACCEL_NORMAL, wx.WXK_F11),
-            (self.OnCloseWindow, wx.ACCEL_CTRL, ord('W')),
-            (self.OnRender, wx.ACCEL_CTRL, ord('R')),
+            (self.OnCloseWindow, wx.ACCEL_CTRL, ord("W")),
+            (self.OnRender, wx.ACCEL_CTRL, ord("R")),
             (self.OnRender, wx.ACCEL_NORMAL, wx.WXK_F5),
             (self.OnRender, wx.ACCEL_NORMAL, wx.WXK_F5),
         )
         )
         accelTable = []
         accelTable = []
@@ -135,11 +135,12 @@ class MapFrameBase(wx.Frame):
         self.SetAcceleratorTable(wx.AcceleratorTable(accelTable))
         self.SetAcceleratorTable(wx.AcceleratorTable(accelTable))
 
 
     def _initMap(self, Map):
     def _initMap(self, Map):
-        """Initialize map display, set dimensions and map region
-        """
-        if not grass.find_program('g.region', '--help'):
-            sys.exit(_("GRASS module '%s' not found. Unable to start map "
-                       "display window.") % 'g.region')
+        """Initialize map display, set dimensions and map region"""
+        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():")
         Debug.msg(2, "MapFrame._initMap():")
         Map.ChangeMapSize(self.GetClientSize())
         Map.ChangeMapSize(self.GetClientSize())
@@ -155,7 +156,7 @@ class MapFrameBase(wx.Frame):
         self.SetSize((wf + dw, hf + dh))
         self.SetSize((wf + dw, hf + dh))
 
 
     def _onToggleTool(self, id):
     def _onToggleTool(self, id):
-        if self._toolSwitcher.IsToolInGroup(id, 'mouseUse'):
+        if self._toolSwitcher.IsToolInGroup(id, "mouseUse"):
             self.GetWindow().UnregisterAllHandlers()
             self.GetWindow().UnregisterAllHandlers()
 
 
     def OnSize(self, event):
     def OnSize(self, event):
@@ -205,23 +206,34 @@ class MapFrameBase(wx.Frame):
         # screen X region problem
         # screen X region problem
         # user should specify ppm
         # user should specify ppm
         dc = wx.ScreenDC()
         dc = wx.ScreenDC()
-        dpSizePx = wx.DisplaySize()   # display size in pixels
+        dpSizePx = wx.DisplaySize()  # display size in pixels
         dpSizeMM = wx.DisplaySizeMM()  # display size in mm (system)
         dpSizeMM = wx.DisplaySizeMM()  # display size in mm (system)
         dpSizeIn = (dpSizeMM[0] / 25.4, dpSizeMM[1] / 25.4)  # inches
         dpSizeIn = (dpSizeMM[0] / 25.4, dpSizeMM[1] / 25.4)  # inches
         sysPpi = dc.GetPPI()
         sysPpi = dc.GetPPI()
-        comPpi = (dpSizePx[0] / dpSizeIn[0],
-                  dpSizePx[1] / dpSizeIn[1])
+        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)
+        ppi = comPpi  # pixel per inch
+        ppm = ((ppi[0] / 2.54) * 100, (ppi[1] / 2.54) * 100)  # pixel per meter
 
 
-        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" %
-                  (dpSizePx[0], dpSizePx[1], dpSizeMM[0], dpSizeMM[1],
-                   dpSizeIn[0], dpSizeIn[1],
-                   sysPpi[0], sysPpi[1], comPpi[0], comPpi[1],
-                   ppm[0], ppm[1]))
+        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"
+            % (
+                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
         return ppm
 
 
@@ -235,16 +247,15 @@ class MapFrameBase(wx.Frame):
             map = self.Map
             map = self.Map
 
 
         region = self.Map.region
         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.
+        dEW = value * (region["cols"] / self.GetPPM()[0])
+        dNS = value * (region["rows"] / self.GetPPM()[1])
+        region["n"] = region["center_northing"] + dNS / 2.0
+        region["s"] = region["center_northing"] - dNS / 2.0
+        region["w"] = region["center_easting"] - dEW / 2.0
+        region["e"] = region["center_easting"] + dEW / 2.0
 
 
         # add to zoom history
         # add to zoom history
-        self.GetWindow().ZoomHistory(region['n'], region['s'],
-                                     region['e'], region['w'])
+        self.GetWindow().ZoomHistory(region["n"], region["s"], region["e"], region["w"])
 
 
     def GetMapScale(self, map=None):
     def GetMapScale(self, map=None):
         """Get current map scale
         """Get current map scale
@@ -257,19 +268,22 @@ class MapFrameBase(wx.Frame):
         region = map.region
         region = map.region
         ppm = self.GetPPM()
         ppm = self.GetPPM()
 
 
-        heightCm = region['rows'] / ppm[1] * 100
-        widthCm = region['cols'] / ppm[0] * 100
+        heightCm = region["rows"] / ppm[1] * 100
+        widthCm = region["cols"] / ppm[0] * 100
 
 
-        Debug.msg(4, "MapFrame.GetMapScale(): width_cm=%f, height_cm=%f" %
-                  (widthCm, heightCm))
+        Debug.msg(
+            4, "MapFrame.GetMapScale(): width_cm=%f, height_cm=%f" % (widthCm, heightCm)
+        )
 
 
-        xscale = (region['e'] - region['w']) / (region['cols'] / ppm[0])
-        yscale = (region['n'] - region['s']) / (region['rows'] / ppm[1])
-        scale = (xscale + yscale) / 2.
+        xscale = (region["e"] - region["w"]) / (region["cols"] / ppm[0])
+        yscale = (region["n"] - region["s"]) / (region["rows"] / ppm[1])
+        scale = (xscale + yscale) / 2.0
 
 
         Debug.msg(
         Debug.msg(
-            3, "MapFrame.GetMapScale(): xscale=%f, yscale=%f -> scale=%f" %
-            (xscale, yscale, scale))
+            3,
+            "MapFrame.GetMapScale(): xscale=%f, yscale=%f -> scale=%f"
+            % (xscale, yscale, scale),
+        )
 
 
         return scale
         return scale
 
 
@@ -297,8 +311,7 @@ class MapFrameBase(wx.Frame):
         raise NotImplementedError("GetMapToolbar")
         raise NotImplementedError("GetMapToolbar")
 
 
     def GetToolbar(self, name):
     def GetToolbar(self, name):
-        """Returns toolbar if exists and is active, else None.
-        """
+        """Returns toolbar if exists and is active, else None."""
         if name in self.toolbars and self.toolbars[name].IsShown():
         if name in self.toolbars and self.toolbars[name].IsShown():
             return self.toolbars[name]
             return self.toolbars[name]
 
 
@@ -319,13 +332,12 @@ class MapFrameBase(wx.Frame):
         return self.mapWindowProperties.autoRender
         return self.mapWindowProperties.autoRender
 
 
     def CoordinatesChanged(self):
     def CoordinatesChanged(self):
-        """Shows current coordinates on statusbar.
-        """
+        """Shows current coordinates on statusbar."""
         # assuming that the first mode is coordinates
         # assuming that the first mode is coordinates
         # probably shold not be here but good solution is not available now
         # probably shold not be here but good solution is not available now
         if self.statusbarManager:
         if self.statusbarManager:
             if self.statusbarManager.GetMode() == 0:
             if self.statusbarManager.GetMode() == 0:
-                self.statusbarManager.ShowItem('coordinates')
+                self.statusbarManager.ShowItem("coordinates")
 
 
     def StatusbarReposition(self):
     def StatusbarReposition(self):
         """Reposition items in statusbar"""
         """Reposition items in statusbar"""
@@ -342,18 +354,15 @@ class MapFrameBase(wx.Frame):
         raise NotImplementedError("IsStandalone")
         raise NotImplementedError("IsStandalone")
 
 
     def OnRender(self, event):
     def OnRender(self, event):
-        """Re-render map composition (each map layer)
-        """
+        """Re-render map composition (each map layer)"""
         raise NotImplementedError("OnRender")
         raise NotImplementedError("OnRender")
 
 
     def OnDraw(self, event):
     def OnDraw(self, event):
-        """Re-display current map composition
-        """
+        """Re-display current map composition"""
         self.MapWindow.UpdateMap(render=False)
         self.MapWindow.UpdateMap(render=False)
 
 
     def OnErase(self, event):
     def OnErase(self, event):
-        """Erase the canvas
-        """
+        """Erase the canvas"""
         self.MapWindow.EraseMap()
         self.MapWindow.EraseMap()
 
 
     def OnZoomIn(self, event):
     def OnZoomIn(self, event):
@@ -369,11 +378,11 @@ class MapFrameBase(wx.Frame):
         # enable or disable zoom history tool
         # enable or disable zoom history tool
         if self.GetMapToolbar():
         if self.GetMapToolbar():
             mapWindow.zoomHistoryAvailable.connect(
             mapWindow.zoomHistoryAvailable.connect(
-                lambda:
-                self.GetMapToolbar().Enable('zoomBack', enable=True))
+                lambda: self.GetMapToolbar().Enable("zoomBack", enable=True)
+            )
             mapWindow.zoomHistoryUnavailable.connect(
             mapWindow.zoomHistoryUnavailable.connect(
-                lambda:
-                self.GetMapToolbar().Enable('zoomBack', enable=False))
+                lambda: self.GetMapToolbar().Enable("zoomBack", enable=False)
+            )
         mapWindow.mouseMoving.connect(self.CoordinatesChanged)
         mapWindow.mouseMoving.connect(self.CoordinatesChanged)
 
 
     def OnPointer(self, event):
     def OnPointer(self, event):
@@ -381,13 +390,11 @@ class MapFrameBase(wx.Frame):
         self.MapWindow.SetModePointer()
         self.MapWindow.SetModePointer()
 
 
     def OnPan(self, event):
     def OnPan(self, event):
-        """Panning, set mouse to drag
-        """
+        """Panning, set mouse to drag"""
         self.MapWindow.SetModePan()
         self.MapWindow.SetModePan()
 
 
     def OnZoomBack(self, event):
     def OnZoomBack(self, event):
-        """Zoom last (previously stored position)
-        """
+        """Zoom last (previously stored position)"""
         self.MapWindow.ZoomBack()
         self.MapWindow.ZoomBack()
 
 
     def OnZoomToMap(self, event):
     def OnZoomToMap(self, event):
@@ -404,8 +411,7 @@ class MapFrameBase(wx.Frame):
         self.MapWindow.ZoomToWind()
         self.MapWindow.ZoomToWind()
 
 
     def OnZoomToDefault(self, event):
     def OnZoomToDefault(self, event):
-        """Set display geometry to match default region settings
-        """
+        """Set display geometry to match default region settings"""
         self.MapWindow.ZoomToDefault()
         self.MapWindow.ZoomToDefault()
 
 
 
 
@@ -421,10 +427,18 @@ class SingleMapFrame(MapFrameBase):
     (when using class or when writing class itself).
     (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 parent: gui parent
@@ -436,11 +450,18 @@ class SingleMapFrame(MapFrameBase):
         :param kwargs: arguments passed to 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
+        self.Map = Map  # instance of render.Map
 
 
         #
         #
         # initialize region values
         # initialize region values
@@ -461,8 +482,7 @@ class SingleMapFrame(MapFrameBase):
         return [self.MapWindow]
         return [self.MapWindow]
 
 
     def OnRender(self, event):
     def OnRender(self, event):
-        """Re-render map composition (each map layer)
-        """
+        """Re-render map composition (each map layer)"""
         self.GetWindow().UpdateMap(render=True, renderVector=True)
         self.GetWindow().UpdateMap(render=True, renderVector=True)
 
 
         # update statusbar
         # update statusbar
@@ -490,10 +510,18 @@ class DoubleMapFrame(MapFrameBase):
         and GCP MapFrame will be necessary).
         and GCP MapFrame will be necessary).
     """
     """
 
 
-    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).
         \a firstMap is set as active (by assign it to \c self.Map).
@@ -508,9 +536,16 @@ class DoubleMapFrame(MapFrameBase):
         :param kwargs: arguments passed to 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.firstMap = firstMap
         self.firstMap = firstMap
         self.secondMap = secondMap
         self.secondMap = secondMap
@@ -528,18 +563,16 @@ class DoubleMapFrame(MapFrameBase):
         self.GetSecondWindow().Bind(wx.EVT_ENTER_WINDOW, self.ActivateSecondMap)
         self.GetSecondWindow().Bind(wx.EVT_ENTER_WINDOW, self.ActivateSecondMap)
 
 
     def _onToggleTool(self, id):
     def _onToggleTool(self, id):
-        if self._toolSwitcher.IsToolInGroup(id, 'mouseUse'):
+        if self._toolSwitcher.IsToolInGroup(id, "mouseUse"):
             self.GetFirstWindow().UnregisterAllHandlers()
             self.GetFirstWindow().UnregisterAllHandlers()
             self.GetSecondWindow().UnregisterAllHandlers()
             self.GetSecondWindow().UnregisterAllHandlers()
 
 
     def GetFirstMap(self):
     def GetFirstMap(self):
-        """Returns first Map instance
-        """
+        """Returns first Map instance"""
         return self.firstMap
         return self.firstMap
 
 
     def GetSecondMap(self):
     def GetSecondMap(self):
-        """Returns second Map instance
-        """
+        """Returns second Map instance"""
         return self.secondMap
         return self.secondMap
 
 
     def GetFirstWindow(self):
     def GetFirstWindow(self):
@@ -582,8 +615,7 @@ class DoubleMapFrame(MapFrameBase):
         # bind/unbind regions
         # bind/unbind regions
         if self._bindRegions:
         if self._bindRegions:
             self.firstMapWindow.zoomChanged.connect(self.OnZoomChangedFirstMap)
             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."""
         """Make second Map and MapWindow active and (un)bind regions of the two Maps."""
@@ -595,10 +627,8 @@ class DoubleMapFrame(MapFrameBase):
         self.GetMapToolbar().SetActiveMap(1)
         self.GetMapToolbar().SetActiveMap(1)
 
 
         if self._bindRegions:
         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):
     def SetBindRegions(self, on):
         """Set or unset binding display regions."""
         """Set or unset binding display regions."""
@@ -606,18 +636,14 @@ class DoubleMapFrame(MapFrameBase):
 
 
         if on:
         if on:
             if self.MapWindow == self.firstMapWindow:
             if self.MapWindow == self.firstMapWindow:
-                self.firstMapWindow.zoomChanged.connect(
-                    self.OnZoomChangedFirstMap)
+                self.firstMapWindow.zoomChanged.connect(self.OnZoomChangedFirstMap)
             else:
             else:
-                self.secondMapWindow.zoomChanged.connect(
-                    self.OnZoomChangedSecondMap)
+                self.secondMapWindow.zoomChanged.connect(self.OnZoomChangedSecondMap)
         else:
         else:
             if self.MapWindow == self.firstMapWindow:
             if self.MapWindow == self.firstMapWindow:
-                self.firstMapWindow.zoomChanged.disconnect(
-                    self.OnZoomChangedFirstMap)
+                self.firstMapWindow.zoomChanged.disconnect(self.OnZoomChangedFirstMap)
             else:
             else:
-                self.secondMapWindow.zoomChanged.disconnect(
-                    self.OnZoomChangedSecondMap)
+                self.secondMapWindow.zoomChanged.disconnect(self.OnZoomChangedSecondMap)
 
 
     def OnZoomChangedFirstMap(self):
     def OnZoomChangedFirstMap(self):
         """Display region of the first window (Map) changed.
         """Display region of the first window (Map) changed.
@@ -665,38 +691,33 @@ class DoubleMapFrame(MapFrameBase):
         self.GetSecondWindow().SetModeQuery()
         self.GetSecondWindow().SetModeQuery()
 
 
     def OnRender(self, event):
     def OnRender(self, event):
-        """Re-render map composition (each map layer)
-        """
+        """Re-render map composition (each map layer)"""
         self.Render(mapToRender=self.GetFirstWindow())
         self.Render(mapToRender=self.GetFirstWindow())
         self.Render(mapToRender=self.GetSecondWindow())
         self.Render(mapToRender=self.GetSecondWindow())
 
 
     def Render(self, mapToRender):
     def Render(self, mapToRender):
         """Re-render map composition"""
         """Re-render map composition"""
         mapToRender.UpdateMap(
         mapToRender.UpdateMap(
-            render=True,
-            renderVector=mapToRender == self.GetFirstWindow())
+            render=True, renderVector=mapToRender == self.GetFirstWindow()
+        )
 
 
         # update statusbar
         # update statusbar
         self.StatusbarUpdate()
         self.StatusbarUpdate()
 
 
     def OnErase(self, event):
     def OnErase(self, event):
-        """Erase the canvas
-        """
+        """Erase the canvas"""
         self.Erase(mapToErase=self.GetFirstWindow())
         self.Erase(mapToErase=self.GetFirstWindow())
         self.Erase(mapToErase=self.GetSecondWindow())
         self.Erase(mapToErase=self.GetSecondWindow())
 
 
     def Erase(self, mapToErase):
     def Erase(self, mapToErase):
-        """Erase the canvas
-        """
+        """Erase the canvas"""
         mapToErase.EraseMap()
         mapToErase.EraseMap()
 
 
     def OnDraw(self, event):
     def OnDraw(self, event):
-        """Re-display current map composition
-        """
+        """Re-display current map composition"""
         self.Draw(mapToDraw=self.GetFirstWindow())
         self.Draw(mapToDraw=self.GetFirstWindow())
         self.Draw(mapToDraw=self.GetSecondWindow())
         self.Draw(mapToDraw=self.GetSecondWindow())
 
 
     def Draw(self, mapToDraw):
     def Draw(self, mapToDraw):
-        """Re-display current map composition
-        """
+        """Re-display current map composition"""
         mapToDraw.UpdateMap(render=False)
         mapToDraw.UpdateMap(render=False)

+ 71 - 59
gui/wxpython/gui_core/menu.py

@@ -35,7 +35,6 @@ from grass.pydispatch.signal import Signal
 
 
 
 
 class Menu(wx.MenuBar):
 class Menu(wx.MenuBar):
-
     def __init__(self, parent, model):
     def __init__(self, parent, model):
         """Creates menubar"""
         """Creates menubar"""
         wx.MenuBar.__init__(self)
         wx.MenuBar.__init__(self)
@@ -57,7 +56,7 @@ class Menu(wx.MenuBar):
                 menu.AppendMenu(wx.ID_ANY, label, subMenu)
                 menu.AppendMenu(wx.ID_ANY, label, subMenu)
             else:
             else:
                 data = child.data.copy()
                 data = child.data.copy()
-                data.pop('label')
+                data.pop("label")
 
 
                 self._createMenuItem(menu, label=child.label, **data)
                 self._createMenuItem(menu, label=child.label, **data)
 
 
@@ -66,8 +65,18 @@ class Menu(wx.MenuBar):
         return menu
         return menu
 
 
     def _createMenuItem(
     def _createMenuItem(
-            self, menu, label, description, handler, command, keywords,
-            shortcut='', icon='', wxId=wx.ID_ANY, kind=wx.ITEM_NORMAL):
+        self,
+        menu,
+        label,
+        description,
+        handler,
+        command,
+        keywords,
+        shortcut="",
+        icon="",
+        wxId=wx.ID_ANY,
+        kind=wx.ITEM_NORMAL,
+    ):
         """Creates menu items
         """Creates menu items
         There are three menu styles (menu item text styles).
         There are three menu styles (menu item text styles).
         1 -- label only, 2 -- label and cmd name, 3 -- cmd name only
         1 -- label only, 2 -- label and cmd name, 3 -- cmd name only
@@ -77,12 +86,12 @@ class Menu(wx.MenuBar):
             return
             return
 
 
         if command:
         if command:
-            helpString = command + ' -- ' + description
+            helpString = command + " -- " + description
         else:
         else:
             helpString = description
             helpString = description
 
 
         if shortcut:
         if shortcut:
-            label += '\t' + shortcut
+            label += "\t" + shortcut
 
 
         menuItem = wx.MenuItem(menu, wxId, label, helpString, kind)
         menuItem = wx.MenuItem(menu, wxId, label, helpString, kind)
         if icon:
         if icon:
@@ -98,11 +107,14 @@ class Menu(wx.MenuBar):
                 cmd = utils.split(EncodeString((command)))
                 cmd = utils.split(EncodeString((command)))
             # disable only grass commands which are not present (e.g.
             # disable only grass commands which are not present (e.g.
             # r.in.lidar)
             # r.in.lidar)
-            if cmd and cmd[0] not in globalvar.grassCmd and \
-               re.match('[rvdipmgt][3bs]?\.([a-z0-9\.])+', cmd[0]):
+            if (
+                cmd
+                and cmd[0] not in globalvar.grassCmd
+                and re.match("[rvdipmgt][3bs]?\.([a-z0-9\.])+", cmd[0])
+            ):
                 menuItem.Enable(False)
                 menuItem.Enable(False)
 
 
-        rhandler = eval('self.parent.' + handler)
+        rhandler = eval("self.parent." + handler)
         self.parent.Bind(wx.EVT_MENU, rhandler, menuItem)
         self.parent.Bind(wx.EVT_MENU, rhandler, menuItem)
 
 
     def GetData(self):
     def GetData(self):
@@ -137,44 +149,41 @@ class SearchModuleWindow(wx.Panel):
         showNotification - attribute 'message'
         showNotification - attribute 'message'
     """
     """
 
 
-    def __init__(self, parent, handlerObj, giface, model, id=wx.ID_ANY,
-                 **kwargs):
+    def __init__(self, parent, handlerObj, giface, model, id=wx.ID_ANY, **kwargs):
         self.parent = parent
         self.parent = parent
         self._handlerObj = handlerObj
         self._handlerObj = handlerObj
         self._giface = giface
         self._giface = giface
         self._model = model
         self._model = model
 
 
-        self.showNotification = Signal('SearchModuleWindow.showNotification')
+        self.showNotification = Signal("SearchModuleWindow.showNotification")
         wx.Panel.__init__(self, parent=parent, id=id, **kwargs)
         wx.Panel.__init__(self, parent=parent, id=id, **kwargs)
 
 
         # search widget
         # search widget
         self._search = SearchCtrl(self)
         self._search = SearchCtrl(self)
-        self._search.SetDescriptiveText(_('Search'))
+        self._search.SetDescriptiveText(_("Search"))
         self._search.ShowCancelButton(True)
         self._search.ShowCancelButton(True)
-        self._btnAdvancedSearch = Button(self, id=wx.ID_ANY,
-                                         label=_("Adva&nced search..."))
+        self._btnAdvancedSearch = Button(
+            self, id=wx.ID_ANY, label=_("Adva&nced search...")
+        )
         self._btnAdvancedSearch.SetToolTip(
         self._btnAdvancedSearch.SetToolTip(
-            _("Do advanced search using %s module") % 'g.search.module')
+            _("Do advanced search using %s module") % "g.search.module"
+        )
         # tree
         # tree
         self._tree = CTreeView(model=model, parent=self)
         self._tree = CTreeView(model=model, parent=self)
-        self._tree.SetToolTip(
-            _("Double-click to run selected module"))
+        self._tree.SetToolTip(_("Double-click to run selected module"))
 
 
         # buttons
         # buttons
         self._btnRun = Button(self, id=wx.ID_OK, label=_("&Run..."))
         self._btnRun = Button(self, id=wx.ID_OK, label=_("&Run..."))
         self._btnRun.SetToolTip(_("Run selected module from the tree"))
         self._btnRun.SetToolTip(_("Run selected module from the tree"))
         self._btnHelp = Button(self, id=wx.ID_ANY, label=_("H&elp"))
         self._btnHelp = Button(self, id=wx.ID_ANY, label=_("H&elp"))
-        self._btnHelp.SetToolTip(
-            _("Show manual for selected module from the tree"))
+        self._btnHelp.SetToolTip(_("Show manual for selected module from the tree"))
 
 
         # bindings
         # bindings
         self._search.Bind(wx.EVT_TEXT, lambda evt: self.Filter(evt.GetString()))
         self._search.Bind(wx.EVT_TEXT, lambda evt: self.Filter(evt.GetString()))
-        self._search.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN,
-                          lambda evt: self.Filter(''))
+        self._search.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN, lambda evt: self.Filter(""))
         self._btnRun.Bind(wx.EVT_BUTTON, lambda evt: self.Run())
         self._btnRun.Bind(wx.EVT_BUTTON, lambda evt: self.Run())
         self._btnHelp.Bind(wx.EVT_BUTTON, lambda evt: self.Help())
         self._btnHelp.Bind(wx.EVT_BUTTON, lambda evt: self.Help())
-        self._btnAdvancedSearch.Bind(wx.EVT_BUTTON,
-                                     lambda evt: self.AdvancedSearch())
+        self._btnAdvancedSearch.Bind(wx.EVT_BUTTON, lambda evt: self.AdvancedSearch())
 
 
         self._tree.selectionChanged.connect(self.OnItemSelected)
         self._tree.selectionChanged.connect(self.OnItemSelected)
         self._tree.itemActivated.connect(lambda node: self.Run(node))
         self._tree.itemActivated.connect(lambda node: self.Run(node))
@@ -189,25 +198,21 @@ class SearchModuleWindow(wx.Panel):
 
 
         # search
         # search
         searchSizer = wx.BoxSizer(wx.HORIZONTAL)
         searchSizer = wx.BoxSizer(wx.HORIZONTAL)
-        searchSizer.Add(self._search, proportion=1,
-                        flag=wx.EXPAND | wx.RIGHT, border=5)
-        searchSizer.Add(self._btnAdvancedSearch, proportion=0,
-                        flag=wx.EXPAND)
-        sizer.Add(searchSizer, proportion=0,
-                  flag=wx.EXPAND | wx.ALL, border=5)
+        searchSizer.Add(self._search, proportion=1, flag=wx.EXPAND | wx.RIGHT, border=5)
+        searchSizer.Add(self._btnAdvancedSearch, proportion=0, flag=wx.EXPAND)
+        sizer.Add(searchSizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
         # body
         # body
-        sizer.Add(self._tree, proportion=1,
-                  flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=5)
+        sizer.Add(
+            self._tree, proportion=1, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=5
+        )
 
 
         # buttons
         # buttons
         btnSizer = wx.BoxSizer(wx.HORIZONTAL)
         btnSizer = wx.BoxSizer(wx.HORIZONTAL)
         btnSizer.AddStretchSpacer()
         btnSizer.AddStretchSpacer()
-        btnSizer.Add(self._btnHelp, proportion=0,
-                     flag=wx.EXPAND | wx.RIGHT, border=5)
+        btnSizer.Add(self._btnHelp, proportion=0, flag=wx.EXPAND | wx.RIGHT, border=5)
         btnSizer.Add(self._btnRun, proportion=0)
         btnSizer.Add(self._btnRun, proportion=0)
 
 
-        sizer.Add(btnSizer, proportion=0,
-                  flag=wx.EXPAND | wx.ALL, border=5)
+        sizer.Add(btnSizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
 
 
         self.SetSizerAndFit(sizer)
         self.SetSizerAndFit(sizer)
         self.SetAutoLayout(True)
         self.SetAutoLayout(True)
@@ -215,8 +220,9 @@ class SearchModuleWindow(wx.Panel):
 
 
     def Filter(self, text):
     def Filter(self, text):
         if text:
         if text:
-            model = self._model.Filtered(key=['command', 'keywords', 'description'],
-                                         value=text)
+            model = self._model.Filtered(
+                key=["command", "keywords", "description"], value=text
+            )
             self._tree.SetModel(model)
             self._tree.SetModel(model)
             self._tree.ExpandAll()
             self._tree.ExpandAll()
         else:
         else:
@@ -249,10 +255,10 @@ class SearchModuleWindow(wx.Panel):
             return
             return
 
 
         # extract name of the handler and create a new call
         # extract name of the handler and create a new call
-        handler = 'self._handlerObj.' + data['handler'].lstrip('self.')
+        handler = "self._handlerObj." + data["handler"].lstrip("self.")
 
 
-        if data['command']:
-            eval(handler)(event=None, cmd=data['command'].split())
+        if data["command"]:
+            eval(handler)(event=None, cmd=data["command"].split())
         else:
         else:
             eval(handler)(event=None)
             eval(handler)(event=None)
 
 
@@ -268,32 +274,32 @@ class SearchModuleWindow(wx.Panel):
         if not data:
         if not data:
             return
             return
 
 
-        if not data['command']:
+        if not data["command"]:
             # showing nothing for non-modules
             # showing nothing for non-modules
             return
             return
         # strip parameters from command if present
         # strip parameters from command if present
-        name = data['command'].split()[0]
+        name = data["command"].split()[0]
         self._giface.Help(name)
         self._giface.Help(name)
         self.showNotification.emit(
         self.showNotification.emit(
-            message=_("Documentation for %s is now open in the web browser")
-            % name)
+            message=_("Documentation for %s is now open in the web browser") % name
+        )
 
 
     def AdvancedSearch(self):
     def AdvancedSearch(self):
         """Show advanced search window"""
         """Show advanced search window"""
-        self._handlerObj.RunMenuCmd(cmd=['g.search.modules'])
+        self._handlerObj.RunMenuCmd(cmd=["g.search.modules"])
 
 
     def OnItemSelected(self, node):
     def OnItemSelected(self, node):
         """Item selected"""
         """Item selected"""
         data = node.data
         data = node.data
-        if not data or 'command' not in data:
+        if not data or "command" not in data:
             return
             return
 
 
-        if data['command']:
-            label = data['command']
-            if data['description']:
-                label += ' -- ' + data['description']
+        if data["command"]:
+            label = data["command"]
+            if data["description"]:
+                label += " -- " + data["description"]
         else:
         else:
-            label = data['description']
+            label = data["description"]
 
 
         self.showNotification.emit(message=label)
         self.showNotification.emit(message=label)
 
 
@@ -318,14 +324,14 @@ class RecentFilesMenu:
     into the .recent_files file to app name group
     into the .recent_files file to app name group
     """
     """
 
 
-    recent_files = '.recent_files'
+    recent_files = ".recent_files"
 
 
     def __init__(self, app_name, parent_menu, pos, history_len=10):
     def __init__(self, app_name, parent_menu, pos, history_len=10):
         self._history_len = history_len
         self._history_len = history_len
         self._parent_menu = parent_menu
         self._parent_menu = parent_menu
         self._pos = pos
         self._pos = pos
 
 
-        self.file_requested = Signal('RecentFilesMenu.FileRequested')
+        self.file_requested = Signal("RecentFilesMenu.FileRequested")
 
 
         self._filehistory = wx.FileHistory(maxFiles=history_len)
         self._filehistory = wx.FileHistory(maxFiles=history_len)
         # Recent files path stored in GRASS GIS config dir in the
         # Recent files path stored in GRASS GIS config dir in the
@@ -333,7 +339,8 @@ class RecentFilesMenu:
         self._config = wx.FileConfig(
         self._config = wx.FileConfig(
             style=wx.CONFIG_USE_LOCAL_FILE,
             style=wx.CONFIG_USE_LOCAL_FILE,
             localFilename=os.path.join(
             localFilename=os.path.join(
-                utils.GetSettingsPath(), self.recent_files,
+                utils.GetSettingsPath(),
+                self.recent_files,
             ),
             ),
         )
         )
         self._config.SetPath(strPath=app_name)
         self._config.SetPath(strPath=app_name)
@@ -353,12 +360,16 @@ class RecentFilesMenu:
         specified position if count of menu items > 0"""
         specified position if count of menu items > 0"""
 
 
         self._parent_menu.Insert(
         self._parent_menu.Insert(
-            pos=self._pos, id=wx.ID_ANY, text=_('&Recent Files'),
+            pos=self._pos,
+            id=wx.ID_ANY,
+            text=_("&Recent Files"),
             submenu=self.recent,
             submenu=self.recent,
         )
         )
         self.recent.Bind(
         self.recent.Bind(
-            wx.EVT_MENU_RANGE, self._onFileHistory,
-            id=wx.ID_FILE1, id2=wx.ID_FILE + self._history_len,
+            wx.EVT_MENU_RANGE,
+            self._onFileHistory,
+            id=wx.ID_FILE1,
+            id2=wx.ID_FILE + self._history_len,
         )
         )
 
 
     def _onFileHistory(self, event):
     def _onFileHistory(self, event):
@@ -372,7 +383,8 @@ class RecentFilesMenu:
             self.RemoveFileFromHistory(file_index)
             self.RemoveFileFromHistory(file_index)
             file_exists = False
             file_exists = False
         self.file_requested.emit(
         self.file_requested.emit(
-            path=path, file_exists=file_exists,
+            path=path,
+            file_exists=file_exists,
             file_history=self._filehistory,
             file_history=self._filehistory,
         )
         )
 
 

Plik diff jest za duży
+ 1028 - 1096
gui/wxpython/gui_core/preferences.py


+ 154 - 147
gui/wxpython/gui_core/prompt.py

@@ -45,10 +45,10 @@ class GPrompt(object):
     """
     """
 
 
     def __init__(self, parent, giface, menuModel):
     def __init__(self, parent, giface, menuModel):
-        self.parent = parent                 # GConsole
+        self.parent = parent  # GConsole
         self.panel = self.parent.GetPanel()
         self.panel = self.parent.GetPanel()
 
 
-        self.promptRunCmd = Signal('GPrompt.promptRunCmd')
+        self.promptRunCmd = Signal("GPrompt.promptRunCmd")
 
 
         # probably only subclasses need this
         # probably only subclasses need this
         self._menuModel = menuModel
         self._menuModel = menuModel
@@ -77,19 +77,21 @@ class GPrompt(object):
         try:
         try:
             fileHistory = codecs.open(
             fileHistory = codecs.open(
                 os.path.join(
                 os.path.join(
-                    env['GISDBASE'],
-                    env['LOCATION_NAME'],
-                    env['MAPSET'],
-                    '.bash_history'),
-                encoding='utf-8',
-                mode='r',
-                errors='replace')
+                    env["GISDBASE"],
+                    env["LOCATION_NAME"],
+                    env["MAPSET"],
+                    ".bash_history",
+                ),
+                encoding="utf-8",
+                mode="r",
+                errors="replace",
+            )
         except IOError:
         except IOError:
             return hist
             return hist
 
 
         try:
         try:
             for line in fileHistory.readlines():
             for line in fileHistory.readlines():
-                hist.append(line.replace('\n', ''))
+                hist.append(line.replace("\n", ""))
         finally:
         finally:
             fileHistory.close()
             fileHistory.close()
 
 
@@ -103,8 +105,8 @@ class GPrompt(object):
     def _getListOfMaps(self):
     def _getListOfMaps(self):
         """Get list of maps"""
         """Get list of maps"""
         result = dict()
         result = dict()
-        result['raster'] = grass.list_strings('raster')
-        result['vector'] = grass.list_strings('vector')
+        result["raster"] = grass.list_strings("raster")
+        result["vector"] = grass.list_strings("vector")
 
 
         return result
         return result
 
 
@@ -126,7 +128,7 @@ class GPrompt(object):
         self.promptRunCmd.emit(cmd=cmd)
         self.promptRunCmd.emit(cmd=cmd)
 
 
         self.OnCmdErase(None)
         self.OnCmdErase(None)
-        self.ShowStatusText('')
+        self.ShowStatusText("")
 
 
     def GetCommands(self):
     def GetCommands(self):
         """Get list of launched commands"""
         """Get list of launched commands"""
@@ -193,14 +195,14 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
         self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
         self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
         self.Bind(wx.stc.EVT_STC_AUTOCOMP_SELECTION, self.OnItemSelected)
         self.Bind(wx.stc.EVT_STC_AUTOCOMP_SELECTION, self.OnItemSelected)
         self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemChanged)
         self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemChanged)
-        if sys.platform != 'darwin':  # unstable on Mac with wxPython 3
+        if sys.platform != "darwin":  # unstable on Mac with wxPython 3
             self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
             self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
 
 
         # signal which requests showing of a notification
         # signal which requests showing of a notification
-        self.showNotification = Signal('GPromptSTC.showNotification')
+        self.showNotification = Signal("GPromptSTC.showNotification")
 
 
         # signal to notify selected command
         # signal to notify selected command
-        self.commandSelected = Signal('GPromptSTC.commandSelected')
+        self.commandSelected = Signal("GPromptSTC.commandSelected")
 
 
     def OnTextSelectionChanged(self, event):
     def OnTextSelectionChanged(self, event):
         """Copy selected text to clipboard and skip event.
         """Copy selected text to clipboard and skip event.
@@ -213,48 +215,50 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
         """Change text in statusbar
         """Change text in statusbar
         if the item selection in the auto-completion list is changed"""
         if the item selection in the auto-completion list is changed"""
         # list of commands
         # list of commands
-        if self.toComplete['entity'] == 'command':
-            item = self.toComplete['cmd'].rpartition(
-                '.')[0] + '.' + self.autoCompList[event.GetIndex()]
+        if self.toComplete["entity"] == "command":
+            item = (
+                self.toComplete["cmd"].rpartition(".")[0]
+                + "."
+                + self.autoCompList[event.GetIndex()]
+            )
             try:
             try:
-                nodes = self._menuModel.SearchNodes(key='command', value=item)
-                desc = ''
+                nodes = self._menuModel.SearchNodes(key="command", value=item)
+                desc = ""
                 if nodes:
                 if nodes:
                     self.commandSelected.emit(command=item)
                     self.commandSelected.emit(command=item)
-                    desc = nodes[0].data['description']
+                    desc = nodes[0].data["description"]
             except KeyError:
             except KeyError:
-                desc = ''
+                desc = ""
             self.ShowStatusText(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']
+        elif self.toComplete["entity"] == "flags":
+            desc = self.cmdDesc.get_flag(self.autoCompList[event.GetIndex()])[
+                "description"
+            ]
             self.ShowStatusText(desc)
             self.ShowStatusText(desc)
         # list of parameters
         # list of parameters
-        elif self.toComplete['entity'] == 'params':
+        elif self.toComplete["entity"] == "params":
             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 + ']'
-            desc += ': ' + item['description']
+            desc = item["name"] + "=" + item["type"]
+            if not item["required"]:
+                desc = "[" + desc + "]"
+            desc += ": " + item["description"]
             self.ShowStatusText(desc)
             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] == '-':
+        elif self.toComplete["entity"] == "params+flags":
+            if self.autoCompList[event.GetIndex()][0] == "-":
                 desc = self.cmdDesc.get_flag(
                 desc = self.cmdDesc.get_flag(
-                    self.autoCompList[
-                        event.GetIndex()].strip('-'))['description']
+                    self.autoCompList[event.GetIndex()].strip("-")
+                )["description"]
             else:
             else:
-                item = self.cmdDesc.get_param(
-                    self.autoCompList[event.GetIndex()])
-                desc = item['name'] + '=' + item['type']
-                if not item['required']:
-                    desc = '[' + desc + ']'
-                desc += ': ' + item['description']
+                item = self.cmdDesc.get_param(self.autoCompList[event.GetIndex()])
+                desc = item["name"] + "=" + item["type"]
+                if not item["required"]:
+                    desc = "[" + desc + "]"
+                desc += ": " + item["description"]
             self.ShowStatusText(desc)
             self.ShowStatusText(desc)
         else:
         else:
-            self.ShowStatusText('')
+            self.ShowStatusText("")
 
 
     def OnItemSelected(self, event):
     def OnItemSelected(self, event):
         """Item selected from the list"""
         """Item selected from the list"""
@@ -262,16 +266,15 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
         # to insert selection correctly if selected word partly matches written
         # to insert selection correctly if selected word partly matches written
         # text
         # text
         match = difflib.SequenceMatcher(None, event.GetText(), lastWord)
         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]:]
+        compl = event.GetText()[matchTuple[2] :]
         text = self.GetTextLeft() + compl
         text = self.GetTextLeft() + compl
         # add space or '=' at the end
         # add space or '=' at the end
-        end = '='
-        for char in ('.', '-', '='):
-            if text.split(' ')[-1].find(char) >= 0:
-                end = ' '
+        end = "="
+        for char in (".", "-", "="):
+            if text.split(" ")[-1].find(char) >= 0:
+                end = " "
 
 
         compl += end
         compl += end
         text += end
         text += end
@@ -280,7 +283,7 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
         pos = len(text)
         pos = len(text)
         self.SetCurrentPos(pos)
         self.SetCurrentPos(pos)
 
 
-        cmd = text.strip().split(' ')[0]
+        cmd = text.strip().split(" ")[0]
 
 
         if not self.cmdDesc or cmd != self.cmdDesc.get_name():
         if not self.cmdDesc or cmd != self.cmdDesc.get_name():
             try:
             try:
@@ -333,23 +336,24 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
         except ValueError:  # No closing quotation error
         except ValueError:  # No closing quotation error
             return toComplete
             return toComplete
         if len(splitted) > 0 and cmd in globalvar.grassCmd:
         if len(splitted) > 0 and cmd in globalvar.grassCmd:
-            toComplete['cmd'] = cmd
-            if entry[-1] == ' ':
-                words = entry.split(' ')
-                if any(word.startswith('-') for word in words):
-                    toComplete['entity'] = 'params'
+            toComplete["cmd"] = cmd
+            if entry[-1] == " ":
+                words = entry.split(" ")
+                if any(word.startswith("-") for word in words):
+                    toComplete["entity"] = "params"
                 else:
                 else:
-                    toComplete['entity'] = 'params+flags'
+                    toComplete["entity"] = "params+flags"
             else:
             else:
                 # get word left from current position
                 # 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] == '=':
+                if word[0] == "=" and word[-1] == "@":
+                    toComplete["entity"] = "mapsets"
+                elif word[0] == "=":
                     # get name of parameter
                     # get name of parameter
                     paramName = self.GetWordLeft(
                     paramName = self.GetWordLeft(
-                        withDelimiter=False, ignoredDelimiter='=').strip('=')
+                        withDelimiter=False, ignoredDelimiter="="
+                    ).strip("=")
                     if paramName:
                     if paramName:
                         try:
                         try:
                             param = self.cmdDesc.get_param(paramName)
                             param = self.cmdDesc.get_param(paramName)
@@ -358,19 +362,19 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
                     else:
                     else:
                         return toComplete
                         return toComplete
 
 
-                    if param['values']:
-                        toComplete['entity'] = 'param values'
-                    elif param['prompt'] == 'raster' and param['element'] == 'cell':
-                        toComplete['entity'] = 'raster map'
-                    elif param['prompt'] == 'vector' and param['element'] == 'vector':
-                        toComplete['entity'] = 'vector map'
-                elif word[0] == '-':
-                    toComplete['entity'] = 'flags'
-                elif word[0] == ' ':
-                    toComplete['entity'] = 'params'
+                    if param["values"]:
+                        toComplete["entity"] = "param values"
+                    elif param["prompt"] == "raster" and param["element"] == "cell":
+                        toComplete["entity"] = "raster map"
+                    elif param["prompt"] == "vector" and param["element"] == "vector":
+                        toComplete["entity"] = "vector map"
+                elif word[0] == "-":
+                    toComplete["entity"] = "flags"
+                elif word[0] == " ":
+                    toComplete["entity"] = "params"
         else:
         else:
-            toComplete['entity'] = 'command'
-            toComplete['cmd'] = cmd
+            toComplete["entity"] = "command"
+            toComplete["cmd"] = cmd
 
 
         return toComplete
         return toComplete
 
 
@@ -385,11 +389,11 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
 
 
         parts = list()
         parts = list()
         if ignoredDelimiter is None:
         if ignoredDelimiter is None:
-            ignoredDelimiter = ''
+            ignoredDelimiter = ""
 
 
-        for char in set(' .,-=') - set(ignoredDelimiter):
+        for char in set(" .,-=") - set(ignoredDelimiter):
             if not withDelimiter:
             if not withDelimiter:
-                delimiter = ''
+                delimiter = ""
             else:
             else:
                 delimiter = char
                 delimiter = char
             parts.append(delimiter + textLeft.rpartition(char)[2])
             parts.append(delimiter + textLeft.rpartition(char)[2])
@@ -399,7 +403,7 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
         """Show sorted auto-completion list if it is not empty"""
         """Show sorted auto-completion list if it is not empty"""
         if len(self.autoCompList) > 0:
         if len(self.autoCompList) > 0:
             self.autoCompList.sort()
             self.autoCompList.sort()
-            self.AutoCompShow(0, itemList=' '.join(self.autoCompList))
+            self.AutoCompShow(0, itemList=" ".join(self.autoCompList))
 
 
     def OnKeyPressed(self, event):
     def OnKeyPressed(self, event):
         """Key pressed capture special treatment for tabulator to show help"""
         """Key pressed capture special treatment for tabulator to show help"""
@@ -410,7 +414,7 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
             try:
             try:
                 cmd = entry.split()[0].strip()
                 cmd = entry.split()[0].strip()
             except IndexError:
             except IndexError:
-                cmd = ''
+                cmd = ""
 
 
             if cmd not in globalvar.grassCmd:
             if cmd not in globalvar.grassCmd:
                 return
                 return
@@ -419,13 +423,16 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
 
 
             self.CallTipSetBackground("#f4f4d1")
             self.CallTipSetBackground("#f4f4d1")
             self.CallTipSetForeground("BLACK")
             self.CallTipSetForeground("BLACK")
-            self.CallTipShow(pos, info['usage'] + '\n\n' + info['description'])
-        elif event.GetKeyCode() in (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER) and \
-                not self.AutoCompActive():
+            self.CallTipShow(pos, info["usage"] + "\n\n" + info["description"])
+        elif (
+            event.GetKeyCode() in (wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER)
+            and not self.AutoCompActive()
+        ):
             # run command on line when <return> is pressed
             # run command on line when <return> is pressed
             self._runCmd(self.GetCurLine()[0].strip())
             self._runCmd(self.GetCurLine()[0].strip())
-        elif event.GetKeyCode() in [wx.WXK_UP, wx.WXK_DOWN] and \
-                not self.AutoCompActive():
+        elif (
+            event.GetKeyCode() in [wx.WXK_UP, wx.WXK_DOWN] and not self.AutoCompActive()
+        ):
             # Command history using up and down
             # Command history using up and down
             if len(self.cmdbuffer) < 1:
             if len(self.cmdbuffer) < 1:
                 return
                 return
@@ -446,7 +453,7 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
                 # without strip causes problem on windows
                 # without strip causes problem on windows
                 txt = self.cmdbuffer[self.cmdindex].strip()
                 txt = self.cmdbuffer[self.cmdindex].strip()
             except KeyError:
             except KeyError:
-                txt = ''
+                txt = ""
 
 
             # clear current line and insert command history
             # clear current line and insert command history
             self.DelLineLeft()
             self.DelLineLeft()
@@ -455,7 +462,7 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
             self.InsertText(pos, txt)
             self.InsertText(pos, txt)
             self.LineEnd()
             self.LineEnd()
 
 
-            self.ShowStatusText('')
+            self.ShowStatusText("")
         else:
         else:
             event.Skip()
             event.Skip()
 
 
@@ -471,71 +478,72 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
         if event.GetKeyCode() == 46:
         if event.GetKeyCode() == 46:
             self.autoCompList = list()
             self.autoCompList = list()
             entry = self.GetTextLeft()
             entry = self.GetTextLeft()
-            self.InsertText(pos, '.')
+            self.InsertText(pos, ".")
             self.CharRight()
             self.CharRight()
             self.toComplete = self.EntityToComplete()
             self.toComplete = self.EntityToComplete()
             try:
             try:
-                if self.toComplete['entity'] == 'command':
+                if self.toComplete["entity"] == "command":
                     for command in globalvar.grassCmd:
                     for command in globalvar.grassCmd:
                         try:
                         try:
-                            if command.find(self.toComplete['cmd']) == 0:
-                                dotNumber = list(
-                                    self.toComplete['cmd']).count('.')
+                            if command.find(self.toComplete["cmd"]) == 0:
+                                dotNumber = list(self.toComplete["cmd"]).count(".")
                                 self.autoCompList.append(
                                 self.autoCompList.append(
-                                    command.split('.', dotNumber)[-1])
+                                    command.split(".", dotNumber)[-1]
+                                )
                         except UnicodeDecodeError as error:
                         except UnicodeDecodeError as error:
-                            sys.stderr.write(
-                                DecodeString(command) + ": " + str(error))
+                            sys.stderr.write(DecodeString(command) + ": " + str(error))
 
 
             except (KeyError, TypeError):
             except (KeyError, TypeError):
                 return
                 return
             self.ShowList()
             self.ShowList()
 
 
         # complete flags after pressing '-'
         # complete flags after pressing '-'
-        elif (event.GetKeyCode() == 45) \
-                or event.GetKeyCode() == wx.WXK_NUMPAD_SUBTRACT \
-                or event.GetKeyCode() == wx.WXK_SUBTRACT:
+        elif (
+            (event.GetKeyCode() == 45)
+            or event.GetKeyCode() == wx.WXK_NUMPAD_SUBTRACT
+            or event.GetKeyCode() == wx.WXK_SUBTRACT
+        ):
             self.autoCompList = list()
             self.autoCompList = list()
             entry = self.GetTextLeft()
             entry = self.GetTextLeft()
-            self.InsertText(pos, '-')
+            self.InsertText(pos, "-")
             self.CharRight()
             self.CharRight()
             self.toComplete = self.EntityToComplete()
             self.toComplete = self.EntityToComplete()
-            if self.toComplete['entity'] == 'flags' and self.cmdDesc:
-                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'])
+            if self.toComplete["entity"] == "flags" and self.cmdDesc:
+                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:
                 else:
-                    for flag in self.cmdDesc.get_options()['flags']:
-                        if len(flag['name']) > 1:
-                            self.autoCompList.append(flag['name'])
+                    for flag in self.cmdDesc.get_options()["flags"]:
+                        if len(flag["name"]) > 1:
+                            self.autoCompList.append(flag["name"])
             self.ShowList()
             self.ShowList()
 
 
         # complete map or values after parameter
         # complete map or values after parameter
         elif event.GetKeyCode() == 61:
         elif event.GetKeyCode() == 61:
             self.autoCompList = list()
             self.autoCompList = list()
-            self.InsertText(pos, '=')
+            self.InsertText(pos, "=")
             self.CharRight()
             self.CharRight()
             self.toComplete = self.EntityToComplete()
             self.toComplete = self.EntityToComplete()
-            if self.toComplete['entity'] == 'raster map':
-                self.autoCompList = self.mapList['raster']
-            elif self.toComplete['entity'] == 'vector map':
-                self.autoCompList = self.mapList['vector']
-            elif self.toComplete['entity'] == 'param values':
+            if self.toComplete["entity"] == "raster map":
+                self.autoCompList = self.mapList["raster"]
+            elif self.toComplete["entity"] == "vector map":
+                self.autoCompList = self.mapList["vector"]
+            elif self.toComplete["entity"] == "param values":
                 param = self.GetWordLeft(
                 param = self.GetWordLeft(
-                    withDelimiter=False,
-                    ignoredDelimiter='=').strip(' =')
-                self.autoCompList = self.cmdDesc.get_param(param)['values']
+                    withDelimiter=False, ignoredDelimiter="="
+                ).strip(" =")
+                self.autoCompList = self.cmdDesc.get_param(param)["values"]
             self.ShowList()
             self.ShowList()
 
 
         # complete mapset ('@')
         # complete mapset ('@')
         elif event.GetKeyCode() == 64:
         elif event.GetKeyCode() == 64:
             self.autoCompList = list()
             self.autoCompList = list()
-            self.InsertText(pos, '@')
+            self.InsertText(pos, "@")
             self.CharRight()
             self.CharRight()
             self.toComplete = self.EntityToComplete()
             self.toComplete = self.EntityToComplete()
 
 
-            if self.toComplete['entity'] == 'mapsets':
+            if self.toComplete["entity"] == "mapsets":
                 self.autoCompList = self.mapsetList
                 self.autoCompList = self.mapsetList
             self.ShowList()
             self.ShowList()
 
 
@@ -545,61 +553,59 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
             self.toComplete = self.EntityToComplete()
             self.toComplete = self.EntityToComplete()
 
 
             # complete command
             # complete command
-            if self.toComplete['entity'] == 'command':
+            if self.toComplete["entity"] == "command":
                 for command in globalvar.grassCmd:
                 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])
+                    if command.find(self.toComplete["cmd"]) == 0:
+                        dotNumber = list(self.toComplete["cmd"]).count(".")
+                        self.autoCompList.append(command.split(".", dotNumber)[-1])
 
 
             # complete flags in such situations (| is cursor):
             # complete flags in such situations (| is cursor):
             # r.colors -| ...w, q, l
             # 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'])
+            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):
             # complete parameters in such situations (| is cursor):
             # r.colors -w | ...color, map, rast, rules
             # r.colors -w | ...color, map, rast, rules
             # r.colors col| ...color
             # 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'])
+            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"])
 
 
             # complete flags or parameters in such situations (| is cursor):
             # complete flags or parameters in such situations (| is cursor):
             # r.colors | ...-w, -q, -l, color, map, rast, rules
             # r.colors | ...-w, -q, -l, color, map, rast, rules
             # r.colors color=grey | ...-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:
+            elif self.toComplete["entity"] == "params+flags" and self.cmdDesc:
                 self.autoCompList = list()
                 self.autoCompList = list()
 
 
-                for param in self.cmdDesc.get_options()['params']:
-                    self.autoCompList.append(param['name'])
-                for flag in self.cmdDesc.get_options()['flags']:
-                    if len(flag['name']) == 1:
-                        self.autoCompList.append('-' + flag['name'])
+                for param in self.cmdDesc.get_options()["params"]:
+                    self.autoCompList.append(param["name"])
+                for flag in self.cmdDesc.get_options()["flags"]:
+                    if len(flag["name"]) == 1:
+                        self.autoCompList.append("-" + flag["name"])
                     else:
                     else:
-                        self.autoCompList.append('--' + flag['name'])
+                        self.autoCompList.append("--" + flag["name"])
 
 
                 self.ShowList()
                 self.ShowList()
 
 
             # complete map or values after parameter
             # complete map or values after parameter
             # r.buffer input=| ...list of raster maps
             # r.buffer input=| ...list of raster maps
             # r.buffer units=| ... feet, kilometers, ...
             # r.buffer units=| ... feet, kilometers, ...
-            elif self.toComplete['entity'] == 'raster map':
+            elif self.toComplete["entity"] == "raster map":
                 self.autoCompList = list()
                 self.autoCompList = list()
-                self.autoCompList = self.mapList['raster']
-            elif self.toComplete['entity'] == 'vector map':
+                self.autoCompList = self.mapList["raster"]
+            elif self.toComplete["entity"] == "vector map":
                 self.autoCompList = list()
                 self.autoCompList = list()
-                self.autoCompList = self.mapList['vector']
-            elif self.toComplete['entity'] == 'param values':
+                self.autoCompList = self.mapList["vector"]
+            elif self.toComplete["entity"] == "param values":
                 self.autoCompList = list()
                 self.autoCompList = list()
                 param = self.GetWordLeft(
                 param = self.GetWordLeft(
-                    withDelimiter=False,
-                    ignoredDelimiter='=').strip(' =')
-                self.autoCompList = self.cmdDesc.get_param(param)['values']
+                    withDelimiter=False, ignoredDelimiter="="
+                ).strip(" =")
+                self.autoCompList = self.cmdDesc.get_param(param)["values"]
 
 
             self.ShowList()
             self.ShowList()
 
 
@@ -607,8 +613,9 @@ class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
             items = self.GetTextLeft().split()
             items = self.GetTextLeft().split()
             if len(items) == 1:
             if len(items) == 1:
                 cmd = items[0].strip()
                 cmd = items[0].strip()
-                if cmd in globalvar.grassCmd and \
-                        (not self.cmdDesc or cmd != self.cmdDesc.get_name()):
+                if cmd in globalvar.grassCmd and (
+                    not self.cmdDesc or cmd != self.cmdDesc.get_name()
+                ):
                     try:
                     try:
                         self.cmdDesc = gtask.parse_interface(cmd)
                         self.cmdDesc = gtask.parse_interface(cmd)
                     except IOError:
                     except IOError:

+ 152 - 118
gui/wxpython/gui_core/pyedit.py

@@ -13,6 +13,7 @@ for details.
 import sys
 import sys
 import os
 import os
 import stat
 import stat
+
 try:
 try:
     from StringIO import StringIO
     from StringIO import StringIO
 except ImportError:
 except ImportError:
@@ -25,8 +26,9 @@ import grass.script as gscript
 from grass.script.utils import try_remove
 from grass.script.utils import try_remove
 
 
 # needed just for testing
 # needed just for testing
-if __name__ == '__main__':
+if __name__ == "__main__":
     from grass.script.setup import set_gui_path
     from grass.script.setup import set_gui_path
+
     set_gui_path()
     set_gui_path()
 
 
 from core.gcmd import GError
 from core.gcmd import GError
@@ -66,12 +68,13 @@ if __name__ == '__main__':
 def module_template():
 def module_template():
     """Template from which to start writing GRASS module"""
     """Template from which to start writing GRASS module"""
     import getpass
     import getpass
+
     author = getpass.getuser()
     author = getpass.getuser()
 
 
     properties = {}
     properties = {}
-    properties['name'] = 'module name'
-    properties['author'] = author
-    properties['description'] = 'Module description'
+    properties["name"] = "module name"
+    properties["author"] = author
+    properties["description"] = "Module description"
 
 
     output = StringIO()
     output = StringIO()
     # header
     # header
@@ -89,12 +92,16 @@ def module_template():
 # DATE:         %s
 # DATE:         %s
 #
 #
 #%s
 #%s
-""" % ('#' * 72,
-            properties['name'],
-            properties['author'],
-            '\n# '.join(properties['description'].splitlines()),
+"""
+        % (
+            "#" * 72,
+            properties["name"],
+            properties["author"],
+            "\n# ".join(properties["description"].splitlines()),
             time.asctime(),
             time.asctime(),
-            '#' * 72))
+            "#" * 72,
+        )
+    )
 
 
     # UI
     # UI
     output.write(
     output.write(
@@ -102,7 +109,9 @@ def module_template():
 # %%module
 # %%module
 # %% description: %s
 # %% description: %s
 # %%end
 # %%end
-""" % (' '.join(properties['description'].splitlines())))
+"""
+        % (" ".join(properties["description"].splitlines()))
+    )
 
 
     # import modules
     # import modules
     output.write(
     output.write(
@@ -112,7 +121,8 @@ import os
 import atexit
 import atexit
 
 
 import grass.script as gs
 import grass.script as gs
-""")
+"""
+    )
 
 
     # cleanup()
     # cleanup()
     output.write(
     output.write(
@@ -120,17 +130,20 @@ import grass.script as gs
 RAST_REMOVE = []
 RAST_REMOVE = []
 
 
 def cleanup():
 def cleanup():
-""")
+"""
+    )
     output.write(
     output.write(
         r"""    gs.run_command('g.remove', flags='f', type='raster',
         r"""    gs.run_command('g.remove', flags='f', type='raster',
                    name=RAST_REMOVE)
                    name=RAST_REMOVE)
-""")
+"""
+    )
     output.write("\ndef main():\n")
     output.write("\ndef main():\n")
     output.write(
     output.write(
         r"""    options, flags = gs.parser()
         r"""    options, flags = gs.parser()
     gs.run_command('g.remove', flags='f', type='raster',
     gs.run_command('g.remove', flags='f', type='raster',
                    name=RAST_REMOVE)
                    name=RAST_REMOVE)
-""")
+"""
+    )
 
 
     output.write("\n    return 0\n")
     output.write("\n    return 0\n")
 
 
@@ -139,7 +152,8 @@ def cleanup():
 if __name__ == "__main__":
 if __name__ == "__main__":
     atexit.register(cleanup)
     atexit.register(cleanup)
     sys.exit(main())
     sys.exit(main())
-""")
+"""
+    )
     return output.getvalue()
     return output.getvalue()
 
 
 
 
@@ -253,6 +267,7 @@ if __name__ == "__main__":
 
 
 def open_url(url):
 def open_url(url):
     import webbrowser
     import webbrowser
+
     webbrowser.open(url)
     webbrowser.open(url)
 
 
 
 
@@ -273,8 +288,10 @@ class PyEditController(object):
         # Get first (File) menu
         # Get first (File) menu
         menu = guiparent.menubar.GetMenu(0)
         menu = guiparent.menubar.GetMenu(0)
         self.recent_files = RecentFilesMenu(
         self.recent_files = RecentFilesMenu(
-            app_name='pyedit', parent_menu=menu, pos=1,
-        ) # pos=1 recent files menu position (index) in the parent (File) menu
+            app_name="pyedit",
+            parent_menu=menu,
+            pos=1,
+        )  # pos=1 recent files menu position (index) in the parent (File) menu
 
 
         self.recent_files.file_requested.connect(self.OpenRecentFile)
         self.recent_files.file_requested.connect(self.OpenRecentFile)
 
 
@@ -286,7 +303,7 @@ class PyEditController(object):
         :return str or None: file content or None
         :return str or None: file content or None
         """
         """
         try:
         try:
-            with open(file_path, 'r') as f:
+            with open(file_path, "r") as f:
                 content = f.read()
                 content = f.read()
                 return content
                 return content
         except PermissionError:
         except PermissionError:
@@ -304,7 +321,7 @@ class PyEditController(object):
                 parent=self.guiparent,
                 parent=self.guiparent,
             )
             )
 
 
-    def _writeFile(self, file_path, content, additional_err_message=''):
+    def _writeFile(self, file_path, content, additional_err_message=""):
         """Try open file and write content
         """Try open file and write content
 
 
         :param str file_path: file path
         :param str file_path: file path
@@ -314,7 +331,7 @@ class PyEditController(object):
         :return None or True: file written or None
         :return None or True: file written or None
         """
         """
         try:
         try:
-            with open(file_path, 'w') as f:
+            with open(file_path, "w") as f:
                 f.write(content)
                 f.write(content)
                 return True
                 return True
         except PermissionError:
         except PermissionError:
@@ -322,7 +339,8 @@ class PyEditController(object):
                 message=_(
                 message=_(
                     "Permission denied <{}>. Please change file "
                     "Permission denied <{}>. Please change file "
                     "permission for writting.{}".format(
                     "permission for writting.{}".format(
-                        file_path, additional_err_message,
+                        file_path,
+                        additional_err_message,
                     ),
                     ),
                 ),
                 ),
                 parent=self.guiparent,
                 parent=self.guiparent,
@@ -331,8 +349,9 @@ class PyEditController(object):
         except IOError:
         except IOError:
             GError(
             GError(
                 message=_(
                 message=_(
-                    "Couldn't write file <{}>.{}".
-                    format(file_path, additional_err_message),
+                    "Couldn't write file <{}>.{}".format(
+                        file_path, additional_err_message
+                    ),
                 ),
                 ),
                 parent=self.guiparent,
                 parent=self.guiparent,
             )
             )
@@ -340,12 +359,12 @@ class PyEditController(object):
     def OnRun(self, event):
     def OnRun(self, event):
         """Run Python script"""
         """Run Python script"""
         if not self.filename:
         if not self.filename:
-            self.filename = gscript.tempfile() + '.py'
+            self.filename = gscript.tempfile() + ".py"
             self.tempfile = True
             self.tempfile = True
             file_is_written = self._writeFile(
             file_is_written = self._writeFile(
-                file_path=self.filename, content=self.body.GetText(),
+                file_path=self.filename,
+                content=self.body.GetText(),
                 additional_err_message=" Unable to launch Python script.",
                 additional_err_message=" Unable to launch Python script.",
-
             )
             )
             if file_is_written:
             if file_is_written:
                 mode = stat.S_IMODE(os.lstat(self.filename)[stat.ST_MODE])
                 mode = stat.S_IMODE(os.lstat(self.filename)[stat.ST_MODE])
@@ -353,7 +372,8 @@ class PyEditController(object):
         else:
         else:
             # always save automatically before running
             # always save automatically before running
             file_is_written = self._writeFile(
             file_is_written = self._writeFile(
-                file_path=self.filename, content=self.body.GetText(),
+                file_path=self.filename,
+                content=self.body.GetText(),
                 additional_err_message=" Unable to launch Python script.",
                 additional_err_message=" Unable to launch Python script.",
             )
             )
             if file_is_written:
             if file_is_written:
@@ -366,7 +386,7 @@ class PyEditController(object):
             # carries variables over to the next execution
             # carries variables over to the next execution
             env = os.environ.copy()
             env = os.environ.copy()
             if self.overwrite:
             if self.overwrite:
-                env['GRASS_OVERWRITE'] = '1'
+                env["GRASS_OVERWRITE"] = "1"
             cmd = [self.filename]
             cmd = [self.filename]
             if self.parameters:
             if self.parameters:
                 cmd.extend(self.parameters)
                 cmd.extend(self.parameters)
@@ -379,11 +399,13 @@ class PyEditController(object):
             self.tempfile = False
             self.tempfile = False
 
 
         filename = None
         filename = None
-        dlg = wx.FileDialog(parent=self.guiparent,
-                            message=_("Choose file to save"),
-                            defaultDir=os.getcwd(),
-                            wildcard=_("Python script (*.py)|*.py"),
-                            style=wx.FD_SAVE)
+        dlg = wx.FileDialog(
+            parent=self.guiparent,
+            message=_("Choose file to save"),
+            defaultDir=os.getcwd(),
+            wildcard=_("Python script (*.py)|*.py"),
+            style=wx.FD_SAVE,
+        )
 
 
         if dlg.ShowModal() == wx.ID_OK:
         if dlg.ShowModal() == wx.ID_OK:
             filename = dlg.GetPath()
             filename = dlg.GetPath()
@@ -398,10 +420,13 @@ class PyEditController(object):
         if os.path.exists(filename):
         if os.path.exists(filename):
             dlg = wx.MessageDialog(
             dlg = wx.MessageDialog(
                 parent=self.guiparent,
                 parent=self.guiparent,
-                message=_("File <%s> already exists. "
-                          "Do you want to overwrite this file?") % filename,
+                message=_(
+                    "File <%s> already exists. " "Do you want to overwrite this file?"
+                )
+                % filename,
                 caption=_("Save file"),
                 caption=_("Save file"),
-                style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
+                style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION,
+            )
             if dlg.ShowModal() == wx.ID_NO:
             if dlg.ShowModal() == wx.ID_NO:
                 dlg.Destroy()
                 dlg.Destroy()
                 return
                 return
@@ -416,8 +441,9 @@ class PyEditController(object):
         """Save current content to a file and set executable permissions"""
         """Save current content to a file and set executable permissions"""
         assert self.filename
         assert self.filename
         file_is_written = self._writeFile(
         file_is_written = self._writeFile(
-            file_path=self.filename, content=self.body.GetText(),
-            )
+            file_path=self.filename,
+            content=self.body.GetText(),
+        )
         if file_is_written:
         if file_is_written:
             # executable file
             # executable file
             os.chmod(self.filename, stat.S_IRWXU | stat.S_IWUSR)
             os.chmod(self.filename, stat.S_IRWXU | stat.S_IWUSR)
@@ -443,12 +469,14 @@ class PyEditController(object):
 
 
     def Open(self):
     def Open(self):
         """Ask for a filename and load its content"""
         """Ask for a filename and load its content"""
-        filename = ''
-        dlg = wx.FileDialog(parent=self.guiparent,
-                            message=_("Open file"),
-                            defaultDir=os.getcwd(),
-                            wildcard=_("Python script (*.py)|*.py"),
-                            style=wx.FD_OPEN)
+        filename = ""
+        dlg = wx.FileDialog(
+            parent=self.guiparent,
+            message=_("Open file"),
+            defaultDir=os.getcwd(),
+            wildcard=_("Python script (*.py)|*.py"),
+            style=wx.FD_OPEN,
+        )
 
 
         if dlg.ShowModal() == wx.ID_OK:
         if dlg.ShowModal() == wx.ID_OK:
             filename = dlg.GetPath()
             filename = dlg.GetPath()
@@ -467,7 +495,7 @@ class PyEditController(object):
 
 
     def OnOpen(self, event):
     def OnOpen(self, event):
         """Handle open event but ask about replacing content first"""
         """Handle open event but ask about replacing content first"""
-        if self.CanReplaceContent('file'):
+        if self.CanReplaceContent("file"):
             self.Open()
             self.Open()
             if self.filename:
             if self.filename:
                 self.recent_files.AddFileToHistory(
                 self.recent_files.AddFileToHistory(
@@ -492,7 +520,7 @@ class PyEditController(object):
                 parent=self.guiparent,
                 parent=self.guiparent,
             )
             )
         else:
         else:
-            if self.CanReplaceContent(by_message='file'):
+            if self.CanReplaceContent(by_message="file"):
                 self.filename = path
                 self.filename = path
                 content = self._openFile(file_path=path)
                 content = self._openFile(file_path=path)
                 if content:
                 if content:
@@ -510,32 +538,35 @@ class PyEditController(object):
         Used for example to check if content should be saved before closing.
         Used for example to check if content should be saved before closing.
         The content is not valuable for example if it already saved in a file.
         The content is not valuable for example if it already saved in a file.
         """
         """
-        Debug.msg(2, "pyedit IsContentValuable? empty=%s, modified=%s" % (
-                  self.IsEmpty(), self.IsModified()))
+        Debug.msg(
+            2,
+            "pyedit IsContentValuable? empty=%s, modified=%s"
+            % (self.IsEmpty(), self.IsModified()),
+        )
         return not self.IsEmpty() and self.IsModified()
         return not self.IsEmpty() and self.IsModified()
 
 
     def SetScriptTemplate(self, event):
     def SetScriptTemplate(self, event):
-        if self.CanReplaceContent('template'):
+        if self.CanReplaceContent("template"):
             self.body.SetText(script_template())
             self.body.SetText(script_template())
             self.filename = None
             self.filename = None
 
 
     def SetModuleTemplate(self, event):
     def SetModuleTemplate(self, event):
-        if self.CanReplaceContent('template'):
+        if self.CanReplaceContent("template"):
             self.body.SetText(module_template())
             self.body.SetText(module_template())
             self.filename = None
             self.filename = None
 
 
     def SetScriptExample(self, event):
     def SetScriptExample(self, event):
-        if self.CanReplaceContent('example'):
+        if self.CanReplaceContent("example"):
             self.body.SetText(script_example())
             self.body.SetText(script_example())
             self.filename = None
             self.filename = None
 
 
     def SetModuleExample(self, event):
     def SetModuleExample(self, event):
-        if self.CanReplaceContent('example'):
+        if self.CanReplaceContent("example"):
             self.body.SetText(module_example())
             self.body.SetText(module_example())
             self.filename = None
             self.filename = None
 
 
     def SetModuleErrorHandlingExample(self, event):
     def SetModuleErrorHandlingExample(self, event):
-        if self.CanReplaceContent('example'):
+        if self.CanReplaceContent("example"):
             self.body.SetText(module_error_handling_example())
             self.body.SetText(module_error_handling_example())
             self.filename = None
             self.filename = None
 
 
@@ -550,19 +581,21 @@ class PyEditController(object):
             'example' and 'file' which will use predefined messages, otherwise
             'example' and 'file' which will use predefined messages, otherwise
             a translatable, user visible string should be used.
             a translatable, user visible string should be used.
         """
         """
-        if by_message == 'template':
+        if by_message == "template":
             message = _("Replace the content by the template?")
             message = _("Replace the content by the template?")
-        elif by_message == 'example':
+        elif by_message == "example":
             message = _("Replace the content by the example?")
             message = _("Replace the content by the example?")
-        elif by_message == 'file':
+        elif by_message == "file":
             message = _("Replace the current content by the file content?")
             message = _("Replace the current content by the file content?")
         else:
         else:
             message = by_message
             message = by_message
         if self.IsContentValuable():
         if self.IsContentValuable():
             dlg = wx.MessageDialog(
             dlg = wx.MessageDialog(
-                parent=self.guiparent, message=message,
+                parent=self.guiparent,
+                message=message,
                 caption=_("Replace content"),
                 caption=_("Replace content"),
-                style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
+                style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION,
+            )
             if dlg.ShowModal() == wx.ID_NO:
             if dlg.ShowModal() == wx.ID_NO:
                 dlg.Destroy()
                 dlg.Destroy()
                 return False
                 return False
@@ -574,7 +607,9 @@ class PyEditController(object):
         dlg = wx.TextEntryDialog(
         dlg = wx.TextEntryDialog(
             parent=self.guiparent,
             parent=self.guiparent,
             caption=_("Set parameters for the script"),
             caption=_("Set parameters for the script"),
-            message=_("Specify command line parameters for the script separated by spaces:"),
+            message=_(
+                "Specify command line parameters for the script separated by spaces:"
+            ),
         )
         )
         if self.parameters:
         if self.parameters:
             dlg.SetValue(" ".join(self.parameters))
             dlg.SetValue(" ".join(self.parameters))
@@ -590,27 +625,26 @@ class PyEditController(object):
     def OnHelp(self, event):
     def OnHelp(self, event):
         # inspired by g.manual but simple not using GRASS_HTML_BROWSER
         # inspired by g.manual but simple not using GRASS_HTML_BROWSER
         # not using g.manual because it does not show
         # not using g.manual because it does not show
-        entry = 'libpython/script_intro.html'
-        major, minor, patch = gscript.version()['version'].split('.')
-        url = 'https://grass.osgeo.org/grass%s%s/manuals/%s' % (
-            major, minor, entry)
+        entry = "libpython/script_intro.html"
+        major, minor, patch = gscript.version()["version"].split(".")
+        url = "https://grass.osgeo.org/grass%s%s/manuals/%s" % (major, minor, entry)
         open_url(url)
         open_url(url)
 
 
     def OnPythonHelp(self, event):
     def OnPythonHelp(self, event):
-        url = 'https://docs.python.org/%s/tutorial/' % sys.version_info[0]
+        url = "https://docs.python.org/%s/tutorial/" % sys.version_info[0]
         open_url(url)
         open_url(url)
 
 
     def OnModulesHelp(self, event):
     def OnModulesHelp(self, event):
-        self.giface.Help('full_index')
+        self.giface.Help("full_index")
 
 
     def OnSubmittingHelp(self, event):
     def OnSubmittingHelp(self, event):
-        open_url('https://trac.osgeo.org/grass/wiki/Submitting/Python')
+        open_url("https://trac.osgeo.org/grass/wiki/Submitting/Python")
 
 
     def OnAddonsHelp(self, event):
     def OnAddonsHelp(self, event):
-        open_url('https://grass.osgeo.org/development/code-submission/')
+        open_url("https://grass.osgeo.org/development/code-submission/")
 
 
     def OnSupport(self, event):
     def OnSupport(self, event):
-        open_url('https://grass.osgeo.org/support/')
+        open_url("https://grass.osgeo.org/support/")
 
 
 
 
 class PyEditToolbar(BaseToolbar):
 class PyEditToolbar(BaseToolbar):
@@ -623,23 +657,17 @@ class PyEditToolbar(BaseToolbar):
         BaseToolbar.__init__(self, parent)
         BaseToolbar.__init__(self, parent)
 
 
         self.icons = {
         self.icons = {
-            'open': MetaIcon(img='open',
-                             label=_('Open (Ctrl+O)')),
-            'save': MetaIcon(img='save',
-                             label=_('Save (Ctrl+S)')),
-            'run': MetaIcon(img='execute',
-                            label=_('Run (Ctrl+R)')),
+            "open": MetaIcon(img="open", label=_("Open (Ctrl+O)")),
+            "save": MetaIcon(img="save", label=_("Save (Ctrl+S)")),
+            "run": MetaIcon(img="execute", label=_("Run (Ctrl+R)")),
             # TODO: better icons for overwrite modes
             # TODO: better icons for overwrite modes
-            'overwriteTrue': MetaIcon(img='locked',
-                                      label=_('Activate overwrite')),
-            'overwriteFalse': MetaIcon(img='unlocked',
-                                       label=_('Deactive overwrite')),
-            'quit': MetaIcon(img='quit',
-                             label=_('Quit Simple Python Editor')),
+            "overwriteTrue": MetaIcon(img="locked", label=_("Activate overwrite")),
+            "overwriteFalse": MetaIcon(img="unlocked", label=_("Deactive overwrite")),
+            "quit": MetaIcon(img="quit", label=_("Quit Simple Python Editor")),
         }
         }
 
 
         # workaround for http://trac.wxwidgets.org/ticket/13888
         # workaround for http://trac.wxwidgets.org/ticket/13888
-        if sys.platform == 'darwin':
+        if sys.platform == "darwin":
             parent.SetToolBar(self)
             parent.SetToolBar(self)
 
 
         self.InitToolbar(self._toolbarData())
         self.InitToolbar(self._toolbarData())
@@ -649,35 +677,41 @@ class PyEditToolbar(BaseToolbar):
 
 
     def _toolbarData(self):
     def _toolbarData(self):
         """Toolbar data"""
         """Toolbar data"""
-        return self._getToolbarData((('open', self.icons['open'],
-                                      self.parent.OnOpen),
-                                     ('save', self.icons['save'],
-                                      self.parent.OnSave),
-                                     (None, ),
-                                     ('run', self.icons['run'],
-                                      self.parent.OnRun),
-                                     ('overwrite', self.icons['overwriteTrue'],
-                                      self.OnSetOverwrite, wx.ITEM_CHECK),
-                                     (None, ),
-                                     ("help", BaseIcons['help'],
-                                      self.parent.OnHelp),
-                                     ('quit', self.icons['quit'],
-                                      self.parent.OnClose),
-                                     ))
+        return self._getToolbarData(
+            (
+                ("open", self.icons["open"], self.parent.OnOpen),
+                ("save", self.icons["save"], self.parent.OnSave),
+                (None,),
+                ("run", self.icons["run"], self.parent.OnRun),
+                (
+                    "overwrite",
+                    self.icons["overwriteTrue"],
+                    self.OnSetOverwrite,
+                    wx.ITEM_CHECK,
+                ),
+                (None,),
+                ("help", BaseIcons["help"], self.parent.OnHelp),
+                ("quit", self.icons["quit"], self.parent.OnClose),
+            )
+        )
 
 
     # TODO: add overwrite also to the menu and sync with toolbar
     # TODO: add overwrite also to the menu and sync with toolbar
     def OnSetOverwrite(self, event):
     def OnSetOverwrite(self, event):
         if self.GetToolState(self.overwrite):
         if self.GetToolState(self.overwrite):
-            self.SetToolNormalBitmap(self.overwrite,
-                                     self.icons['overwriteFalse'].GetBitmap())
-            self.SetToolShortHelp(self.overwrite,
-                                  self.icons['overwriteFalse'].GetLabel())
+            self.SetToolNormalBitmap(
+                self.overwrite, self.icons["overwriteFalse"].GetBitmap()
+            )
+            self.SetToolShortHelp(
+                self.overwrite, self.icons["overwriteFalse"].GetLabel()
+            )
             self.parent.overwrite = True
             self.parent.overwrite = True
         else:
         else:
-            self.SetToolNormalBitmap(self.overwrite,
-                                     self.icons['overwriteTrue'].GetBitmap())
-            self.SetToolShortHelp(self.overwrite,
-                                  self.icons['overwriteTrue'].GetLabel())
+            self.SetToolNormalBitmap(
+                self.overwrite, self.icons["overwriteTrue"].GetBitmap()
+            )
+            self.SetToolShortHelp(
+                self.overwrite, self.icons["overwriteTrue"].GetLabel()
+            )
             self.parent.overwrite = False
             self.parent.overwrite = False
 
 
 
 
@@ -687,37 +721,36 @@ class PyEditFrame(wx.Frame):
     # pylint: disable=too-many-public-methods
     # pylint: disable=too-many-public-methods
     # pylint: disable=invalid-name
     # pylint: disable=invalid-name
 
 
-    def __init__(self, parent, giface, id=wx.ID_ANY,
-                 title=_("Simple Python Editor"),
-                 **kwargs):
+    def __init__(
+        self, parent, giface, id=wx.ID_ANY, title=_("Simple Python Editor"), **kwargs
+    ):
         wx.Frame.__init__(self, parent=parent, id=id, title=title, **kwargs)
         wx.Frame.__init__(self, parent=parent, id=id, title=title, **kwargs)
         self.parent = parent
         self.parent = parent
 
 
-        filename = os.path.join(
-            globalvar.WXGUIDIR, 'xml', 'menudata_pyedit.xml')
+        filename = os.path.join(globalvar.WXGUIDIR, "xml", "menudata_pyedit.xml")
         self.menubar = Menu(
         self.menubar = Menu(
-            parent=self,
-            model=MenuTreeModelBuilder(filename).GetModel(separators=True))
+            parent=self, model=MenuTreeModelBuilder(filename).GetModel(separators=True)
+        )
         self.SetMenuBar(self.menubar)
         self.SetMenuBar(self.menubar)
 
 
         self.toolbar = PyEditToolbar(parent=self)
         self.toolbar = PyEditToolbar(parent=self)
         # workaround for http://trac.wxwidgets.org/ticket/13888
         # workaround for http://trac.wxwidgets.org/ticket/13888
         # TODO: toolbar is set in toolbar and here
         # TODO: toolbar is set in toolbar and here
-        if sys.platform != 'darwin':
+        if sys.platform != "darwin":
             self.SetToolBar(self.toolbar)
             self.SetToolBar(self.toolbar)
 
 
         self.panel = PyStc(parent=self)
         self.panel = PyStc(parent=self)
         if IsDark():
         if IsDark():
             SetDarkMode(self.panel)
             SetDarkMode(self.panel)
         self.controller = PyEditController(
         self.controller = PyEditController(
-            panel=self.panel, guiparent=self, giface=giface)
+            panel=self.panel, guiparent=self, giface=giface
+        )
 
 
         # don't start with an empty page
         # don't start with an empty page
         self.panel.SetText(script_template())
         self.panel.SetText(script_template())
 
 
         sizer = wx.BoxSizer(wx.VERTICAL)
         sizer = wx.BoxSizer(wx.VERTICAL)
-        sizer.Add(self.panel, proportion=1,
-                  flag=wx.EXPAND)
+        sizer.Add(self.panel, proportion=1, flag=wx.EXPAND)
         sizer.Fit(self)
         sizer.Fit(self)
         sizer.SetSizeHints(self)
         sizer.SetSizeHints(self)
         self.SetSizer(sizer)
         self.SetSizer(sizer)
@@ -785,8 +818,9 @@ class PyEditFrame(wx.Frame):
     def _set_overwrite(self, overwrite):
     def _set_overwrite(self, overwrite):
         self.controller.overwrite = overwrite
         self.controller.overwrite = overwrite
 
 
-    overwrite = property(_get_overwrite, _set_overwrite,
-                         doc="Tells if overwrite should be used")
+    overwrite = property(
+        _get_overwrite, _set_overwrite, doc="Tells if overwrite should be used"
+    )
 
 
     def OnSetParameters(self, *args, **kwargs):
     def OnSetParameters(self, *args, **kwargs):
         self.controller.OnSetParameters(*args, **kwargs)
         self.controller.OnSetParameters(*args, **kwargs)
@@ -804,5 +838,5 @@ def main():
     app.MainLoop()
     app.MainLoop()
 
 
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     main()
     main()

+ 78 - 107
gui/wxpython/gui_core/pystc.py

@@ -93,25 +93,24 @@ class PyStc(stc.StyledTextCtrl):
 
 
         # this is supposed to get monospace
         # this is supposed to get monospace
         font = wx.Font(
         font = wx.Font(
-            9,
-            wx.FONTFAMILY_MODERN,
-            wx.FONTSTYLE_NORMAL,
-            wx.FONTWEIGHT_NORMAL)
+            9, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL
+        )
         face = font.GetFaceName()
         face = font.GetFaceName()
         size = font.GetPointSize()
         size = font.GetPointSize()
 
 
         # setting the monospace here to not mess with the rest of the code
         # setting the monospace here to not mess with the rest of the code
         # TODO: review the whole styling
         # TODO: review the whole styling
-        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.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.SetLexer(stc.STC_LEX_PYTHON)
         self.SetKeyWords(0, " ".join(keyword.kwlist))
         self.SetKeyWords(0, " ".join(keyword.kwlist))
@@ -138,40 +137,29 @@ class PyStc(stc.StyledTextCtrl):
 
 
         # like a flattened tree control using square headers
         # like a flattened tree control using square headers
         self.MarkerDefine(
         self.MarkerDefine(
-            stc.STC_MARKNUM_FOLDEROPEN,
-            stc.STC_MARK_BOXMINUS,
-            "white",
-            "#808080")
+            stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, "white", "#808080"
+        )
         self.MarkerDefine(
         self.MarkerDefine(
-            stc.STC_MARKNUM_FOLDER,
-            stc.STC_MARK_BOXPLUS,
-            "white",
-            "#808080")
+            stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, "white", "#808080"
+        )
         self.MarkerDefine(
         self.MarkerDefine(
-            stc.STC_MARKNUM_FOLDERSUB,
-            stc.STC_MARK_VLINE,
-            "white",
-            "#808080")
+            stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#808080"
+        )
         self.MarkerDefine(
         self.MarkerDefine(
-            stc.STC_MARKNUM_FOLDERTAIL,
-            stc.STC_MARK_LCORNER,
-            "white",
-            "#808080")
+            stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER, "white", "#808080"
+        )
         self.MarkerDefine(
         self.MarkerDefine(
-            stc.STC_MARKNUM_FOLDEREND,
-            stc.STC_MARK_BOXPLUSCONNECTED,
-            "white",
-            "#808080")
+            stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "#808080"
+        )
         self.MarkerDefine(
         self.MarkerDefine(
             stc.STC_MARKNUM_FOLDEROPENMID,
             stc.STC_MARKNUM_FOLDEROPENMID,
             stc.STC_MARK_BOXMINUSCONNECTED,
             stc.STC_MARK_BOXMINUSCONNECTED,
             "white",
             "white",
-            "#808080")
+            "#808080",
+        )
         self.MarkerDefine(
         self.MarkerDefine(
-            stc.STC_MARKNUM_FOLDERMIDTAIL,
-            stc.STC_MARK_TCORNER,
-            "white",
-            "#808080")
+            stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "#808080"
+        )
 
 
         self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
         self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
         self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
         self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
@@ -188,102 +176,77 @@ class PyStc(stc.StyledTextCtrl):
 
 
         # global default styles for all languages
         # global default styles for all languages
         self.StyleSetSpec(
         self.StyleSetSpec(
-            stc.STC_STYLE_DEFAULT,
-            "face:%(helv)s,size:%(size)d" %
-            self.faces)
+            stc.STC_STYLE_DEFAULT, "face:%(helv)s,size:%(size)d" % self.faces
+        )
         self.StyleClearAll()  # reset all to be like the default
         self.StyleClearAll()  # reset all to be like the default
 
 
         # global default styles for all languages
         # global default styles for all languages
         self.StyleSetSpec(
         self.StyleSetSpec(
-            stc.STC_STYLE_DEFAULT,
-            "face:%(helv)s,size:%(size)d" %
-            self.faces)
+            stc.STC_STYLE_DEFAULT, "face:%(helv)s,size:%(size)d" % self.faces
+        )
         self.StyleSetSpec(
         self.StyleSetSpec(
             stc.STC_STYLE_LINENUMBER,
             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")
+            "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
         # Python styles
         # Default
         # Default
         self.StyleSetSpec(
         self.StyleSetSpec(
-            stc.STC_P_DEFAULT,
-            "fore:#000000,face:%(helv)s,size:%(size)d" %
-            self.faces)
+            stc.STC_P_DEFAULT, "fore:#000000,face:%(helv)s,size:%(size)d" % self.faces
+        )
         # Comments
         # Comments
         self.StyleSetSpec(
         self.StyleSetSpec(
             stc.STC_P_COMMENTLINE,
             stc.STC_P_COMMENTLINE,
-            "fore:#007F00,face:%(other)s,size:%(size)d" %
-            self.faces)
+            "fore:#007F00,face:%(other)s,size:%(size)d" % self.faces,
+        )
         # Number
         # 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
         # String
         self.StyleSetSpec(
         self.StyleSetSpec(
-            stc.STC_P_STRING,
-            "fore:#7F007F,face:%(helv)s,size:%(size)d" %
-            self.faces)
+            stc.STC_P_STRING, "fore:#7F007F,face:%(helv)s,size:%(size)d" % self.faces
+        )
         # Single quoted string
         # Single quoted string
         self.StyleSetSpec(
         self.StyleSetSpec(
-            stc.STC_P_CHARACTER,
-            "fore:#7F007F,face:%(helv)s,size:%(size)d" %
-            self.faces)
+            stc.STC_P_CHARACTER, "fore:#7F007F,face:%(helv)s,size:%(size)d" % self.faces
+        )
         # Keyword
         # Keyword
         self.StyleSetSpec(
         self.StyleSetSpec(
-            stc.STC_P_WORD,
-            "fore:#00007F,bold,size:%(size)d" %
-            self.faces)
+            stc.STC_P_WORD, "fore:#00007F,bold,size:%(size)d" % self.faces
+        )
         # Triple quotes
         # 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
         # Triple double quotes
         self.StyleSetSpec(
         self.StyleSetSpec(
-            stc.STC_P_TRIPLEDOUBLE,
-            "fore:#7F0000,size:%(size)d" %
-            self.faces)
+            stc.STC_P_TRIPLEDOUBLE, "fore:#7F0000,size:%(size)d" % self.faces
+        )
         # Class name definition
         # Class name definition
         self.StyleSetSpec(
         self.StyleSetSpec(
             stc.STC_P_CLASSNAME,
             stc.STC_P_CLASSNAME,
-            "fore:#0000FF,bold,underline,size:%(size)d" %
-            self.faces)
+            "fore:#0000FF,bold,underline,size:%(size)d" % self.faces,
+        )
         # Function or method name definition
         # Function or method name definition
         self.StyleSetSpec(
         self.StyleSetSpec(
-            stc.STC_P_DEFNAME,
-            "fore:#007F7F,bold,size:%(size)d" %
-            self.faces)
+            stc.STC_P_DEFNAME, "fore:#007F7F,bold,size:%(size)d" % self.faces
+        )
         # Operators
         # 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
         # Identifiers
         self.StyleSetSpec(
         self.StyleSetSpec(
             stc.STC_P_IDENTIFIER,
             stc.STC_P_IDENTIFIER,
-            "fore:#000000,face:%(helv)s,size:%(size)d" %
-            self.faces)
+            "fore:#000000,face:%(helv)s,size:%(size)d" % self.faces,
+        )
         # Comment-blocks
         # Comment-blocks
         self.StyleSetSpec(
         self.StyleSetSpec(
-            stc.STC_P_COMMENTBLOCK,
-            "fore:#7F7F7F,size:%(size)d" %
-            self.faces)
+            stc.STC_P_COMMENTBLOCK, "fore:#7F7F7F,size:%(size)d" % self.faces
+        )
         # End of line where string is not closed
         # End of line where string is not closed
         self.StyleSetSpec(
         self.StyleSetSpec(
             stc.STC_P_STRINGEOL,
             stc.STC_P_STRINGEOL,
-            "fore:#000000,face:%(mono)s,back:#E0C0E0,eol,size:%(size)d" %
-            self.faces)
+            "fore:#000000,face:%(mono)s,back:#E0C0E0,eol,size:%(size)d" % self.faces,
+        )
 
 
         self.SetCaretForeground("BLUE")
         self.SetCaretForeground("BLUE")
 
 
@@ -297,7 +260,8 @@ class PyStc(stc.StyledTextCtrl):
             self.modified = True
             self.modified = True
             if self.statusbar:
             if self.statusbar:
                 self.statusbar.SetStatusText(
                 self.statusbar.SetStatusText(
-                    _('Python script contains local modifications'), 0)
+                    _("Python script contains local modifications"), 0
+                )
 
 
         event.Skip()
         event.Skip()
 
 
@@ -313,8 +277,11 @@ class PyStc(stc.StyledTextCtrl):
             styleBefore = self.GetStyleAt(caretPos - 1)
             styleBefore = self.GetStyleAt(caretPos - 1)
 
 
         # check before
         # 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
             braceAtCaret = caretPos - 1
 
 
         # check after
         # check after
@@ -322,8 +289,11 @@ class PyStc(stc.StyledTextCtrl):
             charAfter = self.GetCharAt(caretPos)
             charAfter = self.GetCharAt(caretPos)
             styleAfter = self.GetStyleAt(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
                 braceAtCaret = caretPos
 
 
         if braceAtCaret >= 0:
         if braceAtCaret >= 0:
@@ -342,8 +312,7 @@ class PyStc(stc.StyledTextCtrl):
             else:
             else:
                 lineClicked = self.LineFromPosition(evt.GetPosition())
                 lineClicked = self.LineFromPosition(evt.GetPosition())
 
 
-                if self.GetFoldLevel(
-                        lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
+                if self.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
                     if evt.GetShift():
                     if evt.GetShift():
                         self.SetFoldExpanded(lineClicked, True)
                         self.SetFoldExpanded(lineClicked, True)
                         self.Expand(lineClicked, True, True, 1)
                         self.Expand(lineClicked, True, True, 1)
@@ -370,8 +339,10 @@ class PyStc(stc.StyledTextCtrl):
         lineNum = 0
         lineNum = 0
         while lineNum < lineCount:
         while lineNum < lineCount:
             level = self.GetFoldLevel(lineNum)
             level = self.GetFoldLevel(lineNum)
-            if level & stc.STC_FOLDLEVELHEADERFLAG and \
-               (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
+            if (
+                level & stc.STC_FOLDLEVELHEADERFLAG
+                and (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE
+            ):
 
 
                 if expanding:
                 if expanding:
                     self.SetFoldExpanded(lineNum, True)
                     self.SetFoldExpanded(lineNum, True)

+ 72 - 85
gui/wxpython/gui_core/query.py

@@ -24,75 +24,70 @@ from grass.pydispatch.signal import Signal
 
 
 
 
 class QueryDialog(wx.Dialog):
 class QueryDialog(wx.Dialog):
-
     def __init__(self, parent, data=None):
     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)
+        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
         # send query output to console
-        self.redirectOutput = Signal('QueryDialog.redirectOutput')
+        self.redirectOutput = Signal("QueryDialog.redirectOutput")
 
 
         self.data = data
         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)
         self.mainSizer = wx.BoxSizer(wx.VERTICAL)
 
 
-        helpText = StaticText(self.panel, wx.ID_ANY, label=_(
-            "Right click to copy selected values to clipboard."))
+        helpText = StaticText(
+            self.panel,
+            wx.ID_ANY,
+            label=_("Right click to copy selected values to clipboard."),
+        )
         helpText.SetForegroundColour(
         helpText.SetForegroundColour(
-            wx.SystemSettings.GetColour(
-                wx.SYS_COLOUR_GRAYTEXT))
+            wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)
+        )
         self.mainSizer.Add(helpText, proportion=0, flag=wx.ALL, border=5)
         self.mainSizer.Add(helpText, proportion=0, flag=wx.ALL, border=5)
 
 
         self._colNames = [_("Feature"), _("Value")]
         self._colNames = [_("Feature"), _("Value")]
         self._model = QueryTreeBuilder(self.data, column=self._colNames[1])
         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 | wx.TR_HIDE_ROOT |
-                                 wx.TR_FULL_ROW_HIGHLIGHT | wx.TR_MULTIPLE)
+        self.tree = TreeListView(
+            model=self._model,
+            parent=self.panel,
+            columns=self._colNames,
+            style=wx.TR_DEFAULT_STYLE
+            | wx.TR_HIDE_ROOT
+            | wx.TR_FULL_ROW_HIGHLIGHT
+            | wx.TR_MULTIPLE,
+        )
 
 
         self.tree.SetColumnWidth(0, 220)
         self.tree.SetColumnWidth(0, 220)
         self.tree.SetColumnWidth(1, 1000)
         self.tree.SetColumnWidth(1, 1000)
         self.tree.ExpandAll()
         self.tree.ExpandAll()
         self.tree.RefreshItems()
         self.tree.RefreshItems()
         self.tree.contextMenu.connect(self.ShowContextMenu)
         self.tree.contextMenu.connect(self.ShowContextMenu)
-        self.mainSizer.Add(
-            self.tree,
-            proportion=1,
-            flag=wx.EXPAND | wx.ALL,
-            border=5)
+        self.mainSizer.Add(self.tree, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
 
 
         close = Button(self.panel, id=wx.ID_CLOSE)
         close = Button(self.panel, id=wx.ID_CLOSE)
         close.Bind(wx.EVT_BUTTON, lambda event: self.Close())
         close.Bind(wx.EVT_BUTTON, lambda event: self.Close())
-        copy = Button(
-            self.panel,
-            id=wx.ID_ANY,
-            label=_("Copy all to clipboard"))
+        copy = Button(self.panel, id=wx.ID_ANY, label=_("Copy all to clipboard"))
         copy.Bind(wx.EVT_BUTTON, self.Copy)
         copy.Bind(wx.EVT_BUTTON, self.Copy)
         self.Bind(wx.EVT_CLOSE, self.OnClose)
         self.Bind(wx.EVT_CLOSE, self.OnClose)
         self.redirect = wx.CheckBox(self.panel, label=_("Redirect to console"))
         self.redirect = wx.CheckBox(self.panel, label=_("Redirect to console"))
         self.redirect.SetValue(False)
         self.redirect.SetValue(False)
         self.redirect.Bind(
         self.redirect.Bind(
-            wx.EVT_CHECKBOX,
-            lambda evt: self._onRedirect(
-                evt.IsChecked()))
+            wx.EVT_CHECKBOX, lambda evt: self._onRedirect(evt.IsChecked())
+        )
 
 
         hbox = wx.BoxSizer(wx.HORIZONTAL)
         hbox = wx.BoxSizer(wx.HORIZONTAL)
-        hbox.Add(
-            self.redirect,
-            proportion=0,
-            flag=wx.EXPAND | wx.RIGHT,
-            border=5)
+        hbox.Add(self.redirect, proportion=0, flag=wx.EXPAND | wx.RIGHT, border=5)
         hbox.AddStretchSpacer(1)
         hbox.AddStretchSpacer(1)
         hbox.Add(copy, proportion=0, flag=wx.EXPAND | wx.RIGHT, border=5)
         hbox.Add(copy, proportion=0, flag=wx.EXPAND | wx.RIGHT, border=5)
         hbox.Add(close, proportion=0, flag=wx.EXPAND | wx.ALL, border=0)
         hbox.Add(close, proportion=0, flag=wx.EXPAND | wx.ALL, border=0)
 
 
-        self.mainSizer.Add(
-            hbox,
-            proportion=0,
-            flag=wx.EXPAND | wx.ALL,
-            border=5)
+        self.mainSizer.Add(hbox, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
         self.panel.SetSizer(self.mainSizer)
         self.panel.SetSizer(self.mainSizer)
         self.mainSizer.Fit(self.panel)
         self.mainSizer.Fit(self.panel)
         # for Windows
         # for Windows
@@ -127,39 +122,29 @@ class QueryDialog(wx.Dialog):
             values = []
             values = []
             for node in nodes:
             for node in nodes:
                 values.append(
                 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))
+                    (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 selected lines"), table))
             texts.append((_("Copy selected lines"), table))
         else:
         else:
             label1 = nodes[0].label
             label1 = nodes[0].label
             texts.append((_("Copy '%s'" % self._cutLabel(label1)), label1))
             texts.append((_("Copy '%s'" % self._cutLabel(label1)), label1))
             if nodes[0].data and nodes[0].data[self._colNames[1]]:
             if nodes[0].data and nodes[0].data[self._colNames[1]]:
                 label2 = nodes[0].data[self._colNames[1]]
                 label2 = nodes[0].data[self._colNames[1]]
-                texts.insert(
-                    0, (_(
-                        "Copy '%s'" %
-                        self._cutLabel(label2)), label2))
-                texts.append((_("Copy line"), label1 + ': ' + label2))
+                texts.insert(0, (_("Copy '%s'" % self._cutLabel(label2)), label2))
+                texts.append((_("Copy line"), label1 + ": " + label2))
 
 
         ids = []
         ids = []
         for text in texts:
         for text in texts:
             id = NewId()
             id = NewId()
             ids.append(id)
             ids.append(id)
             self.Bind(
             self.Bind(
-                wx.EVT_MENU,
-                lambda evt,
-                t=text[1],
-                id=id: self._copyText(t),
-                id=id)
+                wx.EVT_MENU, lambda evt, t=text[1], id=id: self._copyText(t), id=id
+            )
 
 
             menu.Append(id, text[0])
             menu.Append(id, text[0])
 
 
@@ -175,20 +160,20 @@ class QueryDialog(wx.Dialog):
         :param redirect: True to start redirecting, False to stop
         :param redirect: True to start redirecting, False to stop
         """
         """
         if redirect:
         if redirect:
-            self.redirectOutput.emit(output=_("Query results:"), style='cmd')
+            self.redirectOutput.emit(output=_("Query results:"), style="cmd")
             self.redirectOutput.emit(output=self._textToRedirect())
             self.redirectOutput.emit(output=self._textToRedirect())
         else:
         else:
-            self.redirectOutput.emit(output=_(" "), style='cmd')
+            self.redirectOutput.emit(output=_(" "), style="cmd")
 
 
     def _textToRedirect(self):
     def _textToRedirect(self):
         text = printResults(self._model, self._colNames[1])
         text = printResults(self._model, self._colNames[1])
-        text += '\n' + "-" * 50 + '\n'
+        text += "\n" + "-" * 50 + "\n"
         return text
         return text
 
 
     def _cutLabel(self, label):
     def _cutLabel(self, label):
         limit = 15
         limit = 15
         if len(label) > limit:
         if len(label) > limit:
-            return label[:limit] + '...'
+            return label[:limit] + "..."
 
 
         return label
         return label
 
 
@@ -215,6 +200,7 @@ def QueryTreeBuilder(data, column):
 
 
     :return: tree model
     :return: tree model
     """
     """
+
     def addNode(parent, data, model):
     def addNode(parent, data, model):
         for k, v in six.iteritems(data):
         for k, v in six.iteritems(data):
             if isinstance(v, dict):
             if isinstance(v, dict):
@@ -223,8 +209,7 @@ def QueryTreeBuilder(data, column):
             else:
             else:
                 if not isinstance(v, six.string_types):
                 if not isinstance(v, six.string_types):
                     v = str(v)
                     v = str(v)
-                node = model.AppendNode(parent=parent,
-                                        data={"label": k, column: v})
+                node = model.AppendNode(parent=parent, data={"label": k, column: v})
 
 
     model = TreeModel(DictNode)
     model = TreeModel(DictNode)
     for part in data:
     for part in data:
@@ -239,21 +224,21 @@ def printResults(model, valueCol):
     :param model: results tree model
     :param model: results tree model
     :param valueCol: column name with value to be printed
     :param valueCol: column name with value to be printed
     """
     """
+
     def printTree(node, textList, valueCol, indent=0):
     def printTree(node, textList, valueCol, indent=0):
-        if node.data.get(valueCol, '') or node.children:
+        if node.data.get(valueCol, "") or node.children:
             textList.append(
             textList.append(
-                indent * ' ' + node.label + ': ' + node.data.get(valueCol, ''))
+                indent * " " + node.label + ": " + node.data.get(valueCol, "")
+            )
         for child in node.children:
         for child in node.children:
             printTree(
             printTree(
-                node=child,
-                textList=textList,
-                valueCol=valueCol,
-                indent=indent + 2)
+                node=child, textList=textList, valueCol=valueCol, indent=indent + 2
+            )
 
 
     textList = []
     textList = []
     for child in model.root.children:
     for child in model.root.children:
         printTree(node=child, textList=textList, valueCol=valueCol)
         printTree(node=child, textList=textList, valueCol=valueCol)
-    return '\n'.join(textList)
+    return "\n".join(textList)
 
 
 
 
 def PrepareQueryResults(coordinates, result):
 def PrepareQueryResults(coordinates, result):
@@ -264,12 +249,12 @@ def PrepareQueryResults(coordinates, result):
     data = []
     data = []
     data.append({_("east, north"): ", ".join(map(str, coordinates))})
     data.append({_("east, north"): ", ".join(map(str, coordinates))})
     for part in result:
     for part in result:
-        if 'Map' in part:
-            itemText = part['Map']
-            if 'Mapset' in part:
-                itemText += '@' + part['Mapset']
-                del part['Mapset']
-            del part['Map']
+        if "Map" in part:
+            itemText = part["Map"]
+            if "Mapset" in part:
+                itemText += "@" + part["Mapset"]
+                del part["Mapset"]
+            del part["Map"]
             if part:
             if part:
                 data.append({itemText: part})
                 data.append({itemText: part})
             else:
             else:
@@ -283,26 +268,28 @@ def test():
     app = wx.App()
     app = wx.App()
     from grass.script import vector as gvect
     from grass.script import vector as gvect
     from grass.script import raster as grast
     from grass.script import raster as grast
+
     testdata1 = grast.raster_what(
     testdata1 = grast.raster_what(
-        map=('elevation_shade@PERMANENT', 'landclass96'),
+        map=("elevation_shade@PERMANENT", "landclass96"),
         coord=[(638509.051416, 224742.348346)],
         coord=[(638509.051416, 224742.348346)],
-        localized=True)
+        localized=True,
+    )
 
 
     testdata2 = gvect.vector_what(
     testdata2 = gvect.vector_what(
-        map=(
-            'firestations', 'bridges'), coord=(
-            633177.897487, 221352.921257), distance=10)
+        map=("firestations", "bridges"),
+        coord=(633177.897487, 221352.921257),
+        distance=10,
+    )
 
 
     testdata = testdata1 + testdata2
     testdata = testdata1 + testdata2
     data = PrepareQueryResults(
     data = PrepareQueryResults(
-        coordinates=(
-            638509.051416,
-            224742.348346),
-        result=testdata)
+        coordinates=(638509.051416, 224742.348346), result=testdata
+    )
     frame = QueryDialog(parent=None, data=data)
     frame = QueryDialog(parent=None, data=data)
     frame.ShowModal()
     frame.ShowModal()
     frame.Destroy()
     frame.Destroy()
     app.MainLoop()
     app.MainLoop()
 
 
+
 if __name__ == "__main__":
 if __name__ == "__main__":
     test()
     test()

+ 132 - 126
gui/wxpython/gui_core/simplelmgr.py

@@ -21,8 +21,9 @@ import wx.aui
 from grass.pydispatch.signal import Signal
 from grass.pydispatch.signal import Signal
 
 
 # needed just for testing
 # needed just for testing
-if __name__ == '__main__':
+if __name__ == "__main__":
     from grass.script.setup import set_gui_path
     from grass.script.setup import set_gui_path
+
     set_gui_path()
     set_gui_path()
 
 
 from gui_core.toolbars import BaseToolbar, BaseIcons
 from gui_core.toolbars import BaseToolbar, BaseIcons
@@ -50,10 +51,14 @@ class SimpleLayerManager(wx.Panel):
     Layertree, but it's just list, not tree."""
     Layertree, but it's just list, not tree."""
 
 
     def __init__(
     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,
+        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
         self._style = lmgrStyle
         self._layerList = layerList
         self._layerList = layerList
@@ -72,41 +77,45 @@ class SimpleLayerManager(wx.Panel):
         # needed in order not to change selection when moving layers
         # needed in order not to change selection when moving layers
         self._blockSelectionChanged = False
         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_CHECKLISTBOX, self.OnLayerChecked)
         self._checkList.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)
         self._checkList.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)
 
 
         # signal emitted when somethin in layer list changes
         # signal emitted when somethin in layer list changes
-        self.opacityChanged = Signal('SimpleLayerManager.opacityChanged')
-        self.cmdChanged = Signal('SimpleLayerManager.cmdChanged')
-        self.layerAdded = Signal('SimpleLayerManager.layerAdded')
-        self.layerRemoved = Signal('SimpleLayerManager.layerRemoved')
-        self.layerActivated = Signal('SimpleLayerManager.layerActivated')
-        self.layerMovedUp = Signal('SimpleLayerManager.layerMovedUp')
-        self.layerMovedDown = Signal('SimpleLayerManager.layerMovedDown')
+        self.opacityChanged = Signal("SimpleLayerManager.opacityChanged")
+        self.cmdChanged = Signal("SimpleLayerManager.cmdChanged")
+        self.layerAdded = Signal("SimpleLayerManager.layerAdded")
+        self.layerRemoved = Signal("SimpleLayerManager.layerRemoved")
+        self.layerActivated = Signal("SimpleLayerManager.layerActivated")
+        self.layerMovedUp = Signal("SimpleLayerManager.layerMovedUp")
+        self.layerMovedDown = Signal("SimpleLayerManager.layerMovedDown")
         # emitted by any change (e.g. for rerendering)
         # emitted by any change (e.g. for rerendering)
-        self.anyChange = Signal('SimpleLayerManager.layerChange')
+        self.anyChange = Signal("SimpleLayerManager.layerChange")
 
 
         self._layout()
         self._layout()
         self.SetMinSize((200, -1))
         self.SetMinSize((200, -1))
         self._update()
         self._update()
 
 
     def _layout(self):
     def _layout(self):
-        self._auimgr.AddPane(self._checkList,
-                             wx.aui.AuiPaneInfo().
-                             Name("checklist").
-                             CenterPane().
-                             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()))
+        self._auimgr.AddPane(
+            self._checkList,
+            wx.aui.AuiPaneInfo()
+            .Name("checklist")
+            .CenterPane()
+            .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()))
+        )
         if self._style & SIMPLE_LMGR_TB_LEFT:
         if self._style & SIMPLE_LMGR_TB_LEFT:
             paneInfo.Left()
             paneInfo.Left()
         elif self._style & SIMPLE_LMGR_TB_RIGHT:
         elif self._style & SIMPLE_LMGR_TB_RIGHT:
@@ -143,17 +152,14 @@ class SimpleLayerManager(wx.Panel):
 
 
         menu = Menu()
         menu = Menu()
         llist = [layer.name for layer in self._layerList]
         llist = [layer.name for layer in self._layerList]
-        texts = [','.join(llist), ','.join(reversed(llist))]
-        labels = [_("Copy map names to clipboard (top to bottom)"),
-                  _("Copy map names to clipboard (bottom to top)")]
+        texts = [",".join(llist), ",".join(reversed(llist))]
+        labels = [
+            _("Copy map names to clipboard (top to bottom)"),
+            _("Copy map names to clipboard (bottom to top)"),
+        ]
         for label, text in zip(labels, texts):
         for label, text in zip(labels, texts):
             id = NewId()
             id = 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)
             menu.Append(id, label)
 
 
@@ -189,38 +195,42 @@ class SimpleLayerManager(wx.Panel):
     def OnAddRaster(self, event):
     def OnAddRaster(self, event):
         """Opens d.rast dialog and adds layer.
         """Opens d.rast dialog and adds layer.
         Dummy layer is added first."""
         Dummy layer is added first."""
-        cmd = ['d.rast']
-        layer = self.AddRaster(name='', cmd=cmd, hidden=True, dialog=None)
+        cmd = ["d.rast"]
+        layer = self.AddRaster(name="", cmd=cmd, hidden=True, dialog=None)
         GUI(parent=self, giface=None, modal=self._modal).ParseCommand(
         GUI(parent=self, giface=None, modal=self._modal).ParseCommand(
-            cmd=cmd, completed=(self.GetOptData, layer, ''))
+            cmd=cmd, completed=(self.GetOptData, layer, "")
+        )
         event.Skip()
         event.Skip()
 
 
     def OnAddVector(self, event):
     def OnAddVector(self, event):
         """Opens d.vect dialog and adds layer.
         """Opens d.vect dialog and adds layer.
         Dummy layer is added first."""
         Dummy layer is added first."""
-        cmd = ['d.vect']
+        cmd = ["d.vect"]
 
 
-        layer = self.AddVector(name='', cmd=cmd, hidden=True, dialog=None)
+        layer = self.AddVector(name="", cmd=cmd, hidden=True, dialog=None)
         GUI(parent=self, giface=None, modal=self._modal).ParseCommand(
         GUI(parent=self, giface=None, modal=self._modal).ParseCommand(
-            cmd=cmd, completed=(self.GetOptData, layer, ''))
+            cmd=cmd, completed=(self.GetOptData, layer, "")
+        )
         event.Skip()
         event.Skip()
 
 
     def OnAddRast3d(self, event):
     def OnAddRast3d(self, event):
         """Opens d.rast3d dialog and adds layer.
         """Opens d.rast3d dialog and adds layer.
         Dummy layer is added first."""
         Dummy layer is added first."""
-        cmd = ['d.rast3d']
-        layer = self.AddRast3d(name='', cmd=cmd, hidden=True, dialog=None)
+        cmd = ["d.rast3d"]
+        layer = self.AddRast3d(name="", cmd=cmd, hidden=True, dialog=None)
         GUI(parent=self, giface=None, modal=self._modal).ParseCommand(
         GUI(parent=self, giface=None, modal=self._modal).ParseCommand(
-            cmd=cmd, completed=(self.GetOptData, layer, ''))
+            cmd=cmd, completed=(self.GetOptData, layer, "")
+        )
         event.Skip()
         event.Skip()
 
 
     def OnAddRGB(self, event):
     def OnAddRGB(self, event):
         """Opens d.rgb dialog and adds layer.
         """Opens d.rgb dialog and adds layer.
         Dummy layer is added first."""
         Dummy layer is added first."""
-        cmd = ['d.rgb']
-        layer = self.AddRGB(name='', cmd=cmd, hidden=True, dialog=None)
+        cmd = ["d.rgb"]
+        layer = self.AddRGB(name="", cmd=cmd, hidden=True, dialog=None)
         GUI(parent=self, giface=None, modal=self._modal).ParseCommand(
         GUI(parent=self, giface=None, modal=self._modal).ParseCommand(
-            cmd=cmd, completed=(self.GetOptData, layer, ''))
+            cmd=cmd, completed=(self.GetOptData, layer, "")
+        )
         event.Skip()
         event.Skip()
 
 
     def OnRemove(self, event):
     def OnRemove(self, event):
@@ -228,7 +238,8 @@ class SimpleLayerManager(wx.Panel):
         layers = self._layerList.GetSelectedLayers(activeOnly=False)
         layers = self._layerList.GetSelectedLayers(activeOnly=False)
         for layer in layers:
         for layer in layers:
             self.layerRemoved.emit(
             self.layerRemoved.emit(
-                index=self._layerList.GetLayerIndex(layer), layer=layer)
+                index=self._layerList.GetLayerIndex(layer), layer=layer
+            )
             self._layerList.RemoveLayer(layer)
             self._layerList.RemoveLayer(layer)
         self._update()
         self._update()
         self.anyChange.emit()
         self.anyChange.emit()
@@ -260,7 +271,8 @@ class SimpleLayerManager(wx.Panel):
             idx = self._layerList.GetLayerIndex(layer)
             idx = self._layerList.GetLayerIndex(layer)
             if idx < len(self._layerList) - 1:
             if idx < len(self._layerList) - 1:
                 self.layerMovedDown.emit(
                 self.layerMovedDown.emit(
-                    index=self._layerList.GetLayerIndex(layer), layer=layer)
+                    index=self._layerList.GetLayerIndex(layer), layer=layer
+                )
                 self._layerList.MoveLayerDown(layer)
                 self._layerList.MoveLayerDown(layer)
         self._update()
         self._update()
         self._blockSelectionChanged = False
         self._blockSelectionChanged = False
@@ -278,7 +290,8 @@ class SimpleLayerManager(wx.Panel):
     def _layerChangeProperties(self, layer):
     def _layerChangeProperties(self, layer):
         """Opens new module dialog or recycles it."""
         """Opens new module dialog or recycles it."""
         GUI(parent=self, giface=None, modal=self._modal).ParseCommand(
         GUI(parent=self, giface=None, modal=self._modal).ParseCommand(
-            cmd=layer.cmd, completed=(self.GetOptData, layer, ''))
+            cmd=layer.cmd, completed=(self.GetOptData, layer, "")
+        )
 
 
     def OnLayerChangeOpacity(self, event):
     def OnLayerChangeOpacity(self, event):
         """Opacity of a layer is changing."""
         """Opacity of a layer is changing."""
@@ -286,10 +299,10 @@ class SimpleLayerManager(wx.Panel):
         if not layers or len(layers) > 1:
         if not layers or len(layers) > 1:
             return
             return
         layer = layers[0]
         layer = layers[0]
-        dlg = SetOpacityDialog(self, opacity=layer.opacity,
-                               title=_("Set opacity of <%s>") % layer.name)
-        dlg.applyOpacity.connect(lambda value:
-                                 self._setLayerOpacity(layer, value))
+        dlg = SetOpacityDialog(
+            self, opacity=layer.opacity, title=_("Set opacity of <%s>") % layer.name
+        )
+        dlg.applyOpacity.connect(lambda value: self._setLayerOpacity(layer, value))
         dlg.CentreOnParent()
         dlg.CentreOnParent()
 
 
         if dlg.ShowModal() == wx.ID_OK:
         if dlg.ShowModal() == wx.ID_OK:
@@ -302,8 +315,8 @@ class SimpleLayerManager(wx.Panel):
         layer.opacity = value
         layer.opacity = value
         self._update()
         self._update()
         self.opacityChanged.emit(
         self.opacityChanged.emit(
-            index=self._layerList.GetLayerIndex(layer),
-            layer=layer)
+            index=self._layerList.GetLayerIndex(layer), layer=layer
+        )
         self.anyChange.emit()
         self.anyChange.emit()
 
 
     def _update(self):
     def _update(self):
@@ -321,8 +334,9 @@ class SimpleLayerManager(wx.Panel):
             if layer.opacity < 1:
             if layer.opacity < 1:
                 items.append(
                 items.append(
                     "{name} (opacity {opacity}%)".format(
                     "{name} (opacity {opacity}%)".format(
-                        name=layer.name, opacity=int(
-                            layer.opacity * 100)))
+                        name=layer.name, opacity=int(layer.opacity * 100)
+                    )
+                )
             else:
             else:
                 items.append(layer.name)
                 items.append(layer.name)
             active.append(layer.IsActive())
             active.append(layer.IsActive())
@@ -353,44 +367,40 @@ class SimpleLayerManager(wx.Panel):
                         signal = self.cmdChanged
                         signal = self.cmdChanged
 
 
                     layer.name = mapName
                     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:
                 except ValueError as e:
                     self._layerList.RemoveLayer(layer)
                     self._layerList.RemoveLayer(layer)
-                    GError(parent=self,
-                           message=str(e),
-                           showTraceback=False)
+                    GError(parent=self, message=str(e), showTraceback=False)
 
 
             self._update()
             self._update()
             self.anyChange.emit()
             self.anyChange.emit()
 
 
     def AddRaster(self, name, cmd, hidden, dialog):
     def AddRaster(self, name, cmd, hidden, dialog):
         """Ads new raster layer."""
         """Ads new raster layer."""
-        layer = self._layerList.AddNewLayer(name=name, mapType='raster',
-                                            active=True,
-                                            cmd=cmd, hidden=hidden)
+        layer = self._layerList.AddNewLayer(
+            name=name, mapType="raster", active=True, cmd=cmd, hidden=hidden
+        )
         return layer
         return layer
 
 
     def AddRast3d(self, name, cmd, hidden, dialog):
     def AddRast3d(self, name, cmd, hidden, dialog):
         """Ads new raster3d layer."""
         """Ads new raster3d layer."""
-        layer = self._layerList.AddNewLayer(name=name, mapType='raster_3d',
-                                            active=True,
-                                            cmd=cmd, hidden=hidden)
+        layer = self._layerList.AddNewLayer(
+            name=name, mapType="raster_3d", active=True, cmd=cmd, hidden=hidden
+        )
         return layer
         return layer
 
 
     def AddVector(self, name, cmd, hidden, dialog):
     def AddVector(self, name, cmd, hidden, dialog):
         """Ads new vector layer."""
         """Ads new vector layer."""
-        layer = self._layerList.AddNewLayer(name=name, mapType='vector',
-                                            active=True,
-                                            cmd=cmd, hidden=hidden)
+        layer = self._layerList.AddNewLayer(
+            name=name, mapType="vector", active=True, cmd=cmd, hidden=hidden
+        )
         return layer
         return layer
 
 
     def AddRGB(self, name, cmd, hidden, dialog):
     def AddRGB(self, name, cmd, hidden, dialog):
         """Ads new vector layer."""
         """Ads new vector layer."""
-        layer = self._layerList.AddNewLayer(name=name, mapType='rgb',
-                                            active=True,
-                                            cmd=cmd, hidden=hidden)
+        layer = self._layerList.AddNewLayer(
+            name=name, mapType="rgb", active=True, cmd=cmd, hidden=hidden
+        )
         return layer
         return layer
 
 
     def GetLayerInfo(self, layer, key):
     def GetLayerInfo(self, layer, key):
@@ -398,7 +408,7 @@ class SimpleLayerManager(wx.Panel):
         value = getattr(layer, key)
         value = getattr(layer, key)
         # hack to return empty list, required in OnCancel in forms
         # hack to return empty list, required in OnCancel in forms
         # not sure why it should be empty
         # not sure why it should be empty
-        if key == 'cmd' and len(value) == 1:
+        if key == "cmd" and len(value) == 1:
             return []
             return []
         return value
         return value
 
 
@@ -415,8 +425,7 @@ class SimpleLmgrToolbar(BaseToolbar):
     """
     """
 
 
     def __init__(self, parent, lmgrStyle):
     def __init__(self, parent, lmgrStyle):
-        """Toolbar constructor
-        """
+        """Toolbar constructor"""
         self._style = lmgrStyle
         self._style = lmgrStyle
         if lmgrStyle & (SIMPLE_LMGR_TB_LEFT | SIMPLE_LMGR_TB_RIGHT):
         if lmgrStyle & (SIMPLE_LMGR_TB_LEFT | SIMPLE_LMGR_TB_RIGHT):
             direction = wx.TB_VERTICAL
             direction = wx.TB_VERTICAL
@@ -431,63 +440,59 @@ class SimpleLmgrToolbar(BaseToolbar):
 
 
     def _toolbarData(self):
     def _toolbarData(self):
         """Toolbar data"""
         """Toolbar data"""
-        data = [('edit', icons['edit'],
-                 self.parent.OnLayerChangeProperties),
-                ('remove', icons['remove'],
-                 self.parent.OnRemove),
-                (None, ),
-                ('up', icons['up'],
-                 self.parent.OnLayerUp),
-                ('down', icons['down'],
-                 self.parent.OnLayerDown),
-                (None, ),
-                ('opacity', icons['opacity'],
-                 self.parent.OnLayerChangeOpacity),
-                ]
+        data = [
+            ("edit", icons["edit"], self.parent.OnLayerChangeProperties),
+            ("remove", icons["remove"], self.parent.OnRemove),
+            (None,),
+            ("up", icons["up"], self.parent.OnLayerUp),
+            ("down", icons["down"], self.parent.OnLayerDown),
+            (None,),
+            ("opacity", icons["opacity"], self.parent.OnLayerChangeOpacity),
+        ]
         if self._style & SIMPLE_LMGR_RASTER3D:
         if self._style & SIMPLE_LMGR_RASTER3D:
-            data.insert(0, ('addRaster3d', icons['addRast3d'],
-                            self.parent.OnAddRast3d))
+            data.insert(0, ("addRaster3d", icons["addRast3d"], self.parent.OnAddRast3d))
         if self._style & SIMPLE_LMGR_RGB:
         if self._style & SIMPLE_LMGR_RGB:
-            data.insert(0, ('addRGB', icons['addRGB'],
-                            self.parent.OnAddRGB))
+            data.insert(0, ("addRGB", icons["addRGB"], self.parent.OnAddRGB))
         if self._style & SIMPLE_LMGR_VECTOR:
         if self._style & SIMPLE_LMGR_VECTOR:
-            data.insert(0, ('addVector', BaseIcons['addVect'],
-                            self.parent.OnAddVector))
+            data.insert(0, ("addVector", BaseIcons["addVect"], self.parent.OnAddVector))
         if self._style & SIMPLE_LMGR_RASTER:
         if self._style & SIMPLE_LMGR_RASTER:
-            data.insert(0, ('addRaster', BaseIcons['addRast'],
-                            self.parent.OnAddRaster))
+            data.insert(0, ("addRaster", BaseIcons["addRast"], self.parent.OnAddRaster))
 
 
         return data
         return data
 
 
 
 
 icons = {
 icons = {
-    'remove': MetaIcon(img='layer-remove',
-                       label=_("Remove"),
-                       desc=_("Remove selected map(s) from list")),
-    'up': MetaIcon(img='layer-up',
-                   label=_("Layer up"),
-                   desc=_("Move selected layer(s) up")),
-    'down': MetaIcon(img='layer-down',
-                     label=_("Layer down"),
-                     desc=_("Move selected layer(s) down")),
-    'edit': MetaIcon(img='layer-edit',
-                     label=_("Edit layer properties"),
-                     desc=_("Edit layer properties")),
-    'opacity': MetaIcon(img='layer-opacity',
-                        label=_("Change opacity"),
-                        desc=_("Change layer opacity")),
-    'addRast3d': MetaIcon(img='layer-raster3d-add',
-                          label=_("Add 3D raster map layer"),
-                          desc=_("Add 3D raster map layer")),
-    'addRGB': MetaIcon(img='layer-rgb-add', label=_('Add RGB map layer'))
+    "remove": MetaIcon(
+        img="layer-remove",
+        label=_("Remove"),
+        desc=_("Remove selected map(s) from list"),
+    ),
+    "up": MetaIcon(
+        img="layer-up", label=_("Layer up"), desc=_("Move selected layer(s) up")
+    ),
+    "down": MetaIcon(
+        img="layer-down", label=_("Layer down"), desc=_("Move selected layer(s) down")
+    ),
+    "edit": MetaIcon(
+        img="layer-edit",
+        label=_("Edit layer properties"),
+        desc=_("Edit layer properties"),
+    ),
+    "opacity": MetaIcon(
+        img="layer-opacity", label=_("Change opacity"), desc=_("Change layer opacity")
+    ),
+    "addRast3d": MetaIcon(
+        img="layer-raster3d-add",
+        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):
 class TestFrame(wx.Frame):
-
     def __init__(self, parent):
     def __init__(self, parent):
-        wx.Frame.__init__(self, parent=parent,
-                          title="Simple layer manager test")
+        wx.Frame.__init__(self, parent=parent, title="Simple layer manager test")
         SimpleLayerManager(parent=self, layerList=LayerList())
         SimpleLayerManager(parent=self, layerList=LayerList())
 
 
 
 
@@ -497,5 +502,6 @@ def test():
     frame.Show()
     frame.Show()
     app.MainLoop()
     app.MainLoop()
 
 
-if __name__ == '__main__':
+
+if __name__ == "__main__":
     test()
     test()

+ 98 - 90
gui/wxpython/gui_core/toolbars.py

@@ -32,56 +32,53 @@ from grass.pydispatch.signal import Signal
 
 
 
 
 BaseIcons = {
 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")),
 }
 }
 
 
 
 
@@ -104,11 +101,11 @@ class BaseToolbar(ToolBar):
 
 
     """
     """
 
 
-    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
         self.parent = parent
-        wx.ToolBar.__init__(self, parent=self.parent, id=wx.ID_ANY,
-                            style=style)
+        wx.ToolBar.__init__(self, parent=self.parent, id=wx.ID_ANY, style=style)
 
 
         self._default = None
         self._default = None
         self.SetToolBitmapSize(globalvar.toolbarSize)
         self.SetToolBitmapSize(globalvar.toolbarSize)
@@ -117,8 +114,7 @@ class BaseToolbar(ToolBar):
         self.handlers = {}
         self.handlers = {}
 
 
     def InitToolbar(self, toolData):
     def InitToolbar(self, toolData):
-        """Initialize toolbar, add tools to the toolbar
-        """
+        """Initialize toolbar, add tools to the toolbar"""
         for tool in toolData:
         for tool in toolData:
             self.CreateTool(*tool)
             self.CreateTool(*tool)
 
 
@@ -128,8 +124,7 @@ class BaseToolbar(ToolBar):
         """Toolbar data (virtual)"""
         """Toolbar data (virtual)"""
         return None
         return None
 
 
-    def CreateTool(self, label, bitmap, kind,
-                   shortHelp, longHelp, handler, pos=-1):
+    def CreateTool(self, label, bitmap, kind, shortHelp, longHelp, handler, pos=-1):
         """Add tool to the toolbar
         """Add tool to the toolbar
 
 
         :param pos: if -1 add tool, if > 0 insert at given pos
         :param pos: if -1 add tool, if > 0 insert at given pos
@@ -139,16 +134,17 @@ class BaseToolbar(ToolBar):
         tool = -1
         tool = -1
         if label:
         if label:
             tool = vars(self)[label] = NewId()
             tool = vars(self)[label] = 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:
             if pos < 0:
-                toolWin = self.AddLabelTool(tool, label, bitmap,
-                                            bmpDisabled, kind,
-                                            shortHelp, longHelp)
+                toolWin = self.AddLabelTool(
+                    tool, label, bitmap, bmpDisabled, kind, shortHelp, longHelp
+                )
             else:
             else:
-                toolWin = self.InsertLabelTool(pos, tool, label, bitmap,
-                                               bmpDisabled, kind,
-                                               shortHelp, longHelp)
+                toolWin = self.InsertLabelTool(
+                    pos, tool, label, bitmap, bmpDisabled, kind, shortHelp, longHelp
+                )
             self.handlers[tool] = handler
             self.handlers[tool] = handler
             self.Bind(wx.EVT_TOOL, handler, toolWin)
             self.Bind(wx.EVT_TOOL, handler, toolWin)
             self.Bind(wx.EVT_TOOL, self.OnTool, toolWin)
             self.Bind(wx.EVT_TOOL, self.OnTool, toolWin)
@@ -163,7 +159,7 @@ class BaseToolbar(ToolBar):
         :param enable: True for enable otherwise disable
         :param enable: True for enable otherwise disable
         """
         """
         for tool in self._data:
         for tool in self._data:
-            if tool[0] == '':  # separator
+            if tool[0] == "":  # separator
                 continue
                 continue
 
 
             if enable:
             if enable:
@@ -172,8 +168,7 @@ class BaseToolbar(ToolBar):
                 self.SetToolLongHelp(vars(self)[tool[0]], "")
                 self.SetToolLongHelp(vars(self)[tool[0]], "")
 
 
     def OnTool(self, event):
     def OnTool(self, event):
-        """Tool selected
-        """
+        """Tool selected"""
         if self.toolSwitcher:
         if self.toolSwitcher:
             Debug.msg(3, "BaseToolbar.OnTool(): id = %s" % event.GetId())
             Debug.msg(3, "BaseToolbar.OnTool(): id = %s" % event.GetId())
             self.toolSwitcher.ToolChanged(event.GetId())
             self.toolSwitcher.ToolChanged(event.GetId())
@@ -195,7 +190,7 @@ class BaseToolbar(ToolBar):
         .. todo::
         .. todo::
             Determine why combobox causes problems here
             Determine why combobox causes problems here
         """
         """
-        if platform.system() == 'Windows':
+        if platform.system() == "Windows":
             size = self.GetBestSize()
             size = self.GetBestSize()
             self.SetSize((size[0] + width, size[1]))
             self.SetSize((size[0] + width, size[1]))
 
 
@@ -226,21 +221,26 @@ class BaseToolbar(ToolBar):
             self.Enable(item[0], enable)
             self.Enable(item[0], enable)
 
 
     def _getToolbarData(self, data):
     def _getToolbarData(self, data):
-        """Define tool
-        """
+        """Define tool"""
         retData = list()
         retData = list()
         for args in data:
         for args in data:
             retData.append(self._defineTool(*args))
             retData.append(self._defineTool(*args))
         return retData
         return retData
 
 
-    def _defineTool(self, name=None, icon=None, handler=None,
-                    item=wx.ITEM_NORMAL, pos=-1):
-        """Define tool
-        """
+    def _defineTool(
+        self, name=None, icon=None, handler=None, item=wx.ITEM_NORMAL, pos=-1
+    ):
+        """Define tool"""
         if name:
         if name:
-            return (name, icon.GetBitmap(),
-                    item, icon.GetLabel(), icon.GetDesc(),
-                    handler, pos)
+            return (
+                name,
+                icon.GetBitmap(),
+                item,
+                icon.GetLabel(),
+                icon.GetDesc(),
+                handler,
+                pos,
+            )
         return ("", "", "", "", "", "")  # separator
         return ("", "", "", "", "", "")  # separator
 
 
     def _onMenu(self, data):
     def _onMenu(self, data):
@@ -261,14 +261,20 @@ class BaseToolbar(ToolBar):
 
 
         Button must be custom (not toolbar tool) to set smaller width.
         Button must be custom (not toolbar tool) to set smaller width.
         """
         """
-        arrowPath = os.path.join(IMGDIR, 'small_down_arrow.png')
+        arrowPath = os.path.join(IMGDIR, "small_down_arrow.png")
         if os.path.isfile(arrowPath) and os.path.getsize(arrowPath):
         if os.path.isfile(arrowPath) and os.path.getsize(arrowPath):
             bitmap = wx.Bitmap(name=arrowPath)
             bitmap = wx.Bitmap(name=arrowPath)
         else:
         else:
             bitmap = wx.ArtProvider.GetBitmap(
             bitmap = wx.ArtProvider.GetBitmap(
-                id=wx.ART_MISSING_IMAGE, client=wx.ART_TOOLBAR)
-        button = BitmapButton(parent=self, id=wx.ID_ANY, size=(
-            (-1, self.GetToolSize()[1])), bitmap=bitmap, style=wx.NO_BORDER)
+                id=wx.ART_MISSING_IMAGE, client=wx.ART_TOOLBAR
+            )
+        button = BitmapButton(
+            parent=self,
+            id=wx.ID_ANY,
+            size=((-1, self.GetToolSize()[1])),
+            bitmap=bitmap,
+            style=wx.NO_BORDER,
+        )
         button.SetToolTip(tooltip)
         button.SetToolTip(tooltip)
 
 
         return button
         return button
@@ -282,7 +288,7 @@ class ToolSwitcher:
         self._toolsGroups = defaultdict(list)
         self._toolsGroups = defaultdict(list)
 
 
         # emitted when tool is changed
         # emitted when tool is changed
-        self.toggleToolChanged = Signal('ToolSwitcher.toggleToolChanged')
+        self.toggleToolChanged = Signal("ToolSwitcher.toggleToolChanged")
 
 
     def AddToolToGroup(self, group, toolbar, tool):
     def AddToolToGroup(self, group, toolbar, tool):
         """Adds tool from toolbar to group of exclusive tools.
         """Adds tool from toolbar to group of exclusive tools.
@@ -301,7 +307,7 @@ class ToolSwitcher:
         :param btnId: id of a tool (typically button)
         :param btnId: id of a tool (typically button)
         :param toggleHandler: handler to be called to switch the button
         :param toggleHandler: handler to be called to switch the button
         """
         """
-        self._groups[group]['custom'].append((btnId, toggleHandler))
+        self._groups[group]["custom"].append((btnId, toggleHandler))
         self._toolsGroups[btnId].append(group)
         self._toolsGroups[btnId].append(group)
 
 
     def RemoveCustomToolFromGroup(self, tool):
     def RemoveCustomToolFromGroup(self, tool):
@@ -312,9 +318,11 @@ class ToolSwitcher:
         if tool not in self._toolsGroups:
         if tool not in self._toolsGroups:
             return
             return
         for group in self._toolsGroups[tool]:
         for group in self._toolsGroups[tool]:
-            self._groups[group]['custom'] = \
-                [(bid, hdlr) for (bid, hdlr)
-                 in self._groups[group]['custom'] if bid != tool]
+            self._groups[group]["custom"] = [
+                (bid, hdlr)
+                for (bid, hdlr) in self._groups[group]["custom"]
+                if bid != tool
+            ]
 
 
     def RemoveToolbarFromGroup(self, group, toolbar):
     def RemoveToolbarFromGroup(self, group, toolbar):
         """Removes toolbar from group.
         """Removes toolbar from group.
@@ -338,7 +346,7 @@ class ToolSwitcher:
         """
         """
         for group in self._toolsGroups[tool]:
         for group in self._toolsGroups[tool]:
             for tb in self._groups[group]:
             for tb in self._groups[group]:
-                if tb == 'custom':
+                if tb == "custom":
                     for bid, handler in self._groups[group][tb]:
                     for bid, handler in self._groups[group][tb]:
                         if tool == bid:
                         if tool == bid:
                             return True
                             return True
@@ -353,7 +361,7 @@ class ToolSwitcher:
         """
         """
         for group in self._toolsGroups[tool]:
         for group in self._toolsGroups[tool]:
             for tb in self._groups[group]:
             for tb in self._groups[group]:
-                if tb == 'custom':
+                if tb == "custom":
                     for btnId, handler in self._groups[group][tb]:
                     for btnId, handler in self._groups[group][tb]:
                         if btnId != tool:
                         if btnId != tool:
                             handler(False)
                             handler(False)

+ 58 - 41
gui/wxpython/gui_core/treeview.py

@@ -19,6 +19,7 @@ from __future__ import print_function
 import wx
 import wx
 from wx.lib.mixins.treemixin import VirtualTree, ExpansionState
 from wx.lib.mixins.treemixin import VirtualTree, ExpansionState
 from core.globalvar import hasAgw, wxPythonPhoenix
 from core.globalvar import hasAgw, wxPythonPhoenix
+
 try:
 try:
     import wx.lib.agw.customtreectrl as CT
     import wx.lib.agw.customtreectrl as CT
 except ImportError:
 except ImportError:
@@ -26,14 +27,15 @@ except ImportError:
 if wxPythonPhoenix:
 if wxPythonPhoenix:
     try:
     try:
         from agw.hypertreelist import HyperTreeList as TreeListCtrl
         from agw.hypertreelist import HyperTreeList as TreeListCtrl
-    except ImportError: # if it's not there locally, try the wxPython lib.
+    except ImportError:  # if it's not there locally, try the wxPython lib.
         from wx.lib.agw.hypertreelist import HyperTreeList as TreeListCtrl
         from wx.lib.agw.hypertreelist import HyperTreeList as TreeListCtrl
 else:
 else:
     from wx.gizmos import TreeListCtrl
     from wx.gizmos import TreeListCtrl
 
 
 # needed just for testing
 # needed just for testing
-if __name__ == '__main__':
+if __name__ == "__main__":
     from grass.script.setup import set_gui_path
     from grass.script.setup import set_gui_path
+
     set_gui_path()
     set_gui_path()
 
 
 from core.treemodel import TreeModel, DictNode
 from core.treemodel import TreeModel, DictNode
@@ -58,16 +60,22 @@ class AbstractTreeViewMixin(VirtualTree):
         self._model = model
         self._model = model
         super(AbstractTreeViewMixin, self).__init__(parent=parent, *args, **kw)
         super(AbstractTreeViewMixin, self).__init__(parent=parent, *args, **kw)
 
 
-        self.selectionChanged = Signal('TreeView.selectionChanged')
-        self.itemActivated = Signal('TreeView.itemActivated')
-        self.contextMenu = Signal('TreeView.contextMenu')
-
-        self.Bind(wx.EVT_TREE_SEL_CHANGED, lambda evt:
-                  self._emitSignal(evt.GetItem(), self.selectionChanged))
-        self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, lambda evt:
-                  self._emitSignal(evt.GetItem(), self.itemActivated))
-        self.Bind(wx.EVT_TREE_ITEM_MENU, lambda evt:
-                  self._emitSignal(evt.GetItem(), self.contextMenu))
+        self.selectionChanged = Signal("TreeView.selectionChanged")
+        self.itemActivated = Signal("TreeView.itemActivated")
+        self.contextMenu = Signal("TreeView.contextMenu")
+
+        self.Bind(
+            wx.EVT_TREE_SEL_CHANGED,
+            lambda evt: self._emitSignal(evt.GetItem(), self.selectionChanged),
+        )
+        self.Bind(
+            wx.EVT_TREE_ITEM_ACTIVATED,
+            lambda evt: self._emitSignal(evt.GetItem(), self.itemActivated),
+        )
+        self.Bind(
+            wx.EVT_TREE_ITEM_MENU,
+            lambda evt: self._emitSignal(evt.GetItem(), self.contextMenu),
+        )
 
 
     def SetModel(self, model):
     def SetModel(self, model):
         """Set tree model and refresh.
         """Set tree model and refresh.
@@ -85,7 +93,7 @@ class AbstractTreeViewMixin(VirtualTree):
         """
         """
         node = self._model.GetNodeByIndex(index)
         node = self._model.GetNodeByIndex(index)
         # remove & because of & needed in menu (&Files)
         # remove & because of & needed in menu (&Files)
-        label = node.label.replace('&', '')
+        label = node.label.replace("&", "")
         return label
         return label
 
 
     def OnGetChildrenCount(self, index):
     def OnGetChildrenCount(self, index):
@@ -134,8 +142,8 @@ class AbstractTreeViewMixin(VirtualTree):
         self.EnsureVisible(item)
         self.EnsureVisible(item)
 
 
     def ExpandAll(self):
     def ExpandAll(self):
-        """Expand all items.
-        """
+        """Expand all items."""
+
         def _expand(item, root=False):
         def _expand(item, root=False):
             if not root:
             if not root:
                 self.Expand(item)
                 self.Expand(item)
@@ -205,35 +213,40 @@ class CTreeView(AbstractTreeViewMixin, CustomTreeCtrl):
 
 
     def __init__(self, model, parent, **kw):
     def __init__(self, model, parent, **kw):
         if hasAgw:
         if hasAgw:
-            style = 'agwStyle'
+            style = "agwStyle"
         else:
         else:
-            style = 'style'
+            style = "style"
 
 
         if style not in kw:
         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
+            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)
         super(CTreeView, self).__init__(parent=parent, model=model, **kw)
-        self.SetBackgroundColour(
-            wx.SystemSettings().GetColour(wx.SYS_COLOUR_WINDOW))
+        self.SetBackgroundColour(wx.SystemSettings().GetColour(wx.SYS_COLOUR_WINDOW))
         self.RefreshItems()
         self.RefreshItems()
 
 
 
 
 class TreeListView(AbstractTreeViewMixin, ExpansionState, TreeListCtrl):
 class TreeListView(AbstractTreeViewMixin, ExpansionState, TreeListCtrl):
-
     def __init__(self, model, parent, columns, **kw):
     def __init__(self, model, parent, columns, **kw):
         self._columns = columns
         self._columns = columns
-        if wxPythonPhoenix and 'style' in kw:
-            flags = kw['style']
-            kw['agwStyle'] = flags
-            del kw['style']
+        if wxPythonPhoenix and "style" in kw:
+            flags = kw["style"]
+            kw["agwStyle"] = flags
+            del kw["style"]
         super(TreeListView, self).__init__(parent=parent, model=model, **kw)
         super(TreeListView, self).__init__(parent=parent, model=model, **kw)
         for column in columns:
         for column in columns:
             self.AddColumn(column)
             self.AddColumn(column)
         self.SetMainColumn(0)
         self.SetMainColumn(0)
         self.RefreshItems()
         self.RefreshItems()
         # to solve events inconsitency
         # 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)
         self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnRightClick)
 
 
     def OnGetItemText(self, index, column=0):
     def OnGetItemText(self, index, column=0):
@@ -245,9 +258,9 @@ class TreeListView(AbstractTreeViewMixin, ExpansionState, TreeListCtrl):
         node = self._model.GetNodeByIndex(index)
         node = self._model.GetNodeByIndex(index)
         # remove & because of & needed in menu (&Files)
         # remove & because of & needed in menu (&Files)
         if column > 0:
         if column > 0:
-            return node.data.get(self._columns[column], '')
+            return node.data.get(self._columns[column], "")
         else:
         else:
-            label = node.label.replace('&', '')
+            label = node.label.replace("&", "")
             return label
             return label
 
 
     def OnRightClick(self, event):
     def OnRightClick(self, event):
@@ -265,11 +278,11 @@ class TreeFrame(wx.Frame):
     """Frame for testing purposes only."""
     """Frame for testing purposes only."""
 
 
     def __init__(self, model=None):
     def __init__(self, model=None):
-        wx.Frame.__init__(self, None, title='Test tree')
+        wx.Frame.__init__(self, None, title="Test tree")
 
 
         panel = wx.Panel(self)
         panel = wx.Panel(self)
-#        self.tree = TreeListView(model=model, parent=panel, columns=['col1', 'xxx'])
-#        self.tree = TreeView(model=model, parent=panel)
+        #        self.tree = TreeListView(model=model, parent=panel, columns=['col1', 'xxx'])
+        #        self.tree = TreeView(model=model, parent=panel)
         self.tree = CTreeView(model=model, parent=panel)
         self.tree = CTreeView(model=model, parent=panel)
         self.tree.selectionChanged.connect(self.OnSelChanged)
         self.tree.selectionChanged.connect(self.OnSelChanged)
         self.tree.itemActivated.connect(self.OnItemActivated)
         self.tree.itemActivated.connect(self.OnItemActivated)
@@ -281,11 +294,12 @@ class TreeFrame(wx.Frame):
         szr.SetSizeHints(self)
         szr.SetSizeHints(self)
 
 
     def OnSelChanged(self):
     def OnSelChanged(self):
-        print('selected items: ' +
-              str([node.label for node in self.tree.GetSelected()]))
+        print(
+            "selected items: " + str([node.label for node in self.tree.GetSelected()])
+        )
 
 
     def OnItemActivated(self, node):
     def OnItemActivated(self, node):
-        print('activated: ' + node.label)
+        print("activated: " + node.label)
 
 
 
 
 def main():
 def main():
@@ -296,18 +310,21 @@ def main():
     n3 = tree.AppendNode(parent=root, data={"label": "node3"})  # pylint: disable=W0612
     n3 = tree.AppendNode(parent=root, data={"label": "node3"})  # pylint: disable=W0612
     n11 = tree.AppendNode(parent=n1, data={"label": "node11", "xxx": "A"})
     n11 = tree.AppendNode(parent=n1, data={"label": "node11", "xxx": "A"})
     n12 = tree.AppendNode(
     n12 = tree.AppendNode(
-        parent=n1, data={"label": "node12", "xxx": "B"})  # pylint: disable=W0612
+        parent=n1, data={"label": "node12", "xxx": "B"}
+    )  # pylint: disable=W0612
     n21 = tree.AppendNode(
     n21 = tree.AppendNode(
-        parent=n2, data={"label": "node21", "xxx": "A"})  # pylint: disable=W0612
+        parent=n2, data={"label": "node21", "xxx": "A"}
+    )  # pylint: disable=W0612
     n111 = tree.AppendNode(
     n111 = tree.AppendNode(
-        parent=n11, data={"label": "node111", "xxx": "A"})  # pylint: disable=W0612
+        parent=n11, data={"label": "node111", "xxx": "A"}
+    )  # pylint: disable=W0612
 
 
     app = wx.App()
     app = wx.App()
     frame = TreeFrame(model=tree)
     frame = TreeFrame(model=tree)
-#    frame.tree.Select(n111)
+    #    frame.tree.Select(n111)
     frame.Show()
     frame.Show()
     app.MainLoop()
     app.MainLoop()
 
 
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     main()
     main()

+ 103 - 86
gui/wxpython/gui_core/vselect.py

@@ -34,19 +34,16 @@ from grass.pydispatch.signal import Signal
 
 
 
 
 class VectorSelectList(ListCtrl, listmix.ListCtrlAutoWidthMixin):
 class VectorSelectList(ListCtrl, listmix.ListCtrlAutoWidthMixin):
-    """Widget for managing vector features selected from map display
-    """
+    """Widget for managing vector features selected from map display"""
 
 
     def __init__(self, parent):
     def __init__(self, parent):
         ListCtrl.__init__(
         ListCtrl.__init__(
-            self,
-            parent=parent,
-            id=wx.ID_ANY,
-            style=wx.LC_REPORT | wx.BORDER_SUNKEN)
+            self, parent=parent, id=wx.ID_ANY, style=wx.LC_REPORT | wx.BORDER_SUNKEN
+        )
         listmix.ListCtrlAutoWidthMixin.__init__(self)
         listmix.ListCtrlAutoWidthMixin.__init__(self)
 
 
-        self.InsertColumn(col=0, heading=_('category'))
-        self.InsertColumn(col=1, heading=_('type'))
+        self.InsertColumn(col=0, heading=_("category"))
+        self.InsertColumn(col=1, heading=_("type"))
         self.SetColumnWidth(0, 100)
         self.SetColumnWidth(0, 100)
         self.SetColumnWidth(1, 100)
         self.SetColumnWidth(1, 100)
 
 
@@ -54,15 +51,15 @@ class VectorSelectList(ListCtrl, listmix.ListCtrlAutoWidthMixin):
         self.dictIndex = {}
         self.dictIndex = {}
 
 
     def AddItem(self, item):
     def AddItem(self, item):
-        if 'Category' not in item:
+        if "Category" not in item:
             return
             return
 
 
-        pos = self.InsertItem(0, str(item['Category']))
-        self.SetItem(pos, 1, str(item['Type']))
-        self.dictIndex[str(item['Category'])] = pos
+        pos = self.InsertItem(0, str(item["Category"]))
+        self.SetItem(pos, 1, str(item["Type"]))
+        self.dictIndex[str(item["Category"])] = pos
 
 
     def RemoveItem(self, item):
     def RemoveItem(self, item):
-        index = self.dictIndex.get(str(item['Category']), -1)
+        index = self.dictIndex.get(str(item["Category"]), -1)
         if index > -1:
         if index > -1:
             self.DeleteItem(index)
             self.DeleteItem(index)
 
 
@@ -77,7 +74,8 @@ class VectorSelectDialog(wx.Dialog):
             id=wx.ID_ANY,
             id=wx.ID_ANY,
             title=title,
             title=title,
             size=size,
             size=size,
-            style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
+            style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
+        )
 
 
         self._layout()
         self._layout()
 
 
@@ -92,7 +90,7 @@ class VectorSelectDialog(wx.Dialog):
         self.Show()
         self.Show()
 
 
 
 
-class VectorSelectBase():
+class VectorSelectBase:
     """@brief Main class of vector selection function
     """@brief Main class of vector selection function
 
 
     It allows selecting vector features from map display and to export
     It allows selecting vector features from map display and to export
@@ -117,7 +115,7 @@ class VectorSelectBase():
         self._dialog = None
         self._dialog = None
         self.onCloseDialog = None
         self.onCloseDialog = None
 
 
-        self.updateLayer = Signal('VectorSelectBase.updateLayer')
+        self.updateLayer = Signal("VectorSelectBase.updateLayer")
 
 
         self.painter = VectorSelectHighlighter(self.mapDisp, giface)
         self.painter = VectorSelectHighlighter(self.mapDisp, giface)
 
 
@@ -132,8 +130,7 @@ class VectorSelectBase():
         self._dialog = VectorSelectDialog(parent=self.parent)
         self._dialog = VectorSelectDialog(parent=self.parent)
         self._dialog.Bind(wx.EVT_CLOSE, self.OnCloseDialog)
         self._dialog.Bind(wx.EVT_CLOSE, self.OnCloseDialog)
         if createButton:
         if createButton:
-            createMap = Button(
-                self._dialog, wx.ID_ANY, _("Create a new map"))
+            createMap = Button(self._dialog, wx.ID_ANY, _("Create a new map"))
             createMap.Bind(wx.EVT_BUTTON, self.OnExportMap)
             createMap.Bind(wx.EVT_BUTTON, self.OnExportMap)
             self._dialog.AddWidget(createMap, proportion=0.1)
             self._dialog.AddWidget(createMap, proportion=0.1)
         self.slist = VectorSelectList(self._dialog)
         self.slist = VectorSelectList(self._dialog)
@@ -141,41 +138,40 @@ class VectorSelectBase():
         self.slist.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnDeleteRow)
         self.slist.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnDeleteRow)
         self._dialog.AddWidget(self.slist)
         self._dialog.AddWidget(self.slist)
 
 
-        self.onCloseDialog = Signal('VectorSelectBase.onCloseDialog')
+        self.onCloseDialog = Signal("VectorSelectBase.onCloseDialog")
 
 
     def OnDeleteRow(self, event=None):
     def OnDeleteRow(self, event=None):
-        """Delete row in widget
-        """
+        """Delete row in widget"""
         index = self.slist.GetFocusedItem()
         index = self.slist.GetFocusedItem()
         if index < 0:
         if index < 0:
             return
             return
         category = self.slist.GetItemText(index)
         category = self.slist.GetItemText(index)
         for item in self.selectedFeatures:
         for item in self.selectedFeatures:
-            if int(item['Category']) == int(category):
+            if int(item["Category"]) == int(category):
                 self.selectedFeatures.remove(item)
                 self.selectedFeatures.remove(item)
                 break
                 break
         self.slist.DeleteItem(index)
         self.slist.DeleteItem(index)
         self._draw()
         self._draw()
 
 
     def OnDelete(self, event):
     def OnDelete(self, event):
-        """Delete row in widget by press key(delete)
-        """
+        """Delete row in widget by press key(delete)"""
         keycode = event.GetKeyCode()
         keycode = event.GetKeyCode()
         if keycode == wx.WXK_DELETE:
         if keycode == wx.WXK_DELETE:
             self.OnDeleteRow()
             self.OnDeleteRow()
 
 
     def RegisterMapEvtHandler(self):
     def RegisterMapEvtHandler(self):
         if not self.register:
         if not self.register:
-            self.mapWin.RegisterMouseEventHandler(wx.EVT_LEFT_DOWN,
-                                                  self._onMapClickHandler,
-                                                  'cross')
+            self.mapWin.RegisterMouseEventHandler(
+                wx.EVT_LEFT_DOWN, self._onMapClickHandler, "cross"
+            )
         self.register = True
         self.register = True
 
 
     def UnregisterMapEvtHandler(self):
     def UnregisterMapEvtHandler(self):
         """Unregistrates _onMapClickHandler from mapWin"""
         """Unregistrates _onMapClickHandler from mapWin"""
         if self.register:
         if self.register:
-            self.mapWin.UnregisterMouseEventHandler(wx.EVT_LEFT_DOWN,
-                                                    self._onMapClickHandler)
+            self.mapWin.UnregisterMouseEventHandler(
+                wx.EVT_LEFT_DOWN, self._onMapClickHandler
+            )
         self.register = False
         self.register = False
 
 
     def OnClose(self):
     def OnClose(self):
@@ -202,12 +198,11 @@ class VectorSelectBase():
         self.RegisterMapEvtHandler()
         self.RegisterMapEvtHandler()
 
 
     def _onMapClickHandler(self, event):
     def _onMapClickHandler(self, event):
-        """Registred handler for clicking on grass disp
-        """
+        """Registred handler for clicking on grass disp"""
         if event == "unregistered":
         if event == "unregistered":
             return
             return
         vWhatDic = self.QuerySelectedMap()
         vWhatDic = self.QuerySelectedMap()
-        if 'Category' in vWhatDic:
+        if "Category" in vWhatDic:
             self.AddVecInfo(vWhatDic)
             self.AddVecInfo(vWhatDic)
             self._draw()
             self._draw()
             if self._dialog:
             if self._dialog:
@@ -221,8 +216,9 @@ class VectorSelectBase():
         """
         """
         if len(self.selectedFeatures) > 0:
         if len(self.selectedFeatures) > 0:
             for sel in self.selectedFeatures:
             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)
                     self.selectedFeatures.remove(sel)
                     if self._dialog:  # if dialog initilized->update dialog
                     if self._dialog:  # if dialog initilized->update dialog
                         self.slist.RemoveItem(vInfoDictTMP)
                         self.slist.RemoveItem(vInfoDictTMP)
@@ -245,13 +241,15 @@ class VectorSelectBase():
         """Call class 'VectorSelectHighlighter' to draw selected features"""
         """Call class 'VectorSelectHighlighter' to draw selected features"""
         self.updateLayer.emit()
         self.updateLayer.emit()
         if len(self.selectedFeatures) > 0:
         if len(self.selectedFeatures) > 0:
-            self.painter.SetLayer(self.selectedFeatures[0]['Layer'])
+            self.painter.SetLayer(self.selectedFeatures[0]["Layer"])
             self.painter.SetMap(
             self.painter.SetMap(
-                self.selectedFeatures[0]['Map'] + '@' + self.selectedFeatures[0]['Mapset']
+                self.selectedFeatures[0]["Map"]
+                + "@"
+                + self.selectedFeatures[0]["Mapset"]
             )
             )
             tmp = list()
             tmp = list()
             for i in self.selectedFeatures:
             for i in self.selectedFeatures:
-                tmp.append(i['Category'])
+                tmp.append(i["Category"])
 
 
             self.painter.SetCats(tmp)
             self.painter.SetCats(tmp)
             self.painter.DrawSelected()
             self.painter.DrawSelected()
@@ -266,12 +264,18 @@ class VectorSelectBase():
             return None
             return None
 
 
         if not layerSelected.maplayer.IsActive():
         if not layerSelected.maplayer.IsActive():
-            GWarning(_("Selected map <%s> has been disabled for rendering. "
-                       "Operation canceled.") % str(layerSelected), parent=self.mapWin)
+            GWarning(
+                _(
+                    "Selected map <%s> has been disabled for rendering. "
+                    "Operation canceled."
+                )
+                % str(layerSelected),
+                parent=self.mapWin,
+            )
             return None
             return None
 
 
         if layerSelected:
         if layerSelected:
-            if layerSelected.type != 'vector':
+            if layerSelected.type != "vector":
                 mapName = None
                 mapName = None
                 self.UnregisterMapEvtHandler()
                 self.UnregisterMapEvtHandler()
                 GError(_("No vector map layer selected. Operation canceled."))
                 GError(_("No vector map layer selected. Operation canceled."))
@@ -287,37 +291,37 @@ class VectorSelectBase():
         return mapName
         return mapName
 
 
     def QuerySelectedMap(self):
     def QuerySelectedMap(self):
-        """Return w.what info from last clicked coords on display
-
-        """
+        """Return w.what info from last clicked coords on display"""
         self.mapName = self.GetSelectedMap()
         self.mapName = self.GetSelectedMap()
         if not self.mapName:
         if not self.mapName:
             return {}
             return {}
 
 
         mapInfo = self.mapWin.GetMap()
         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:
         try:
-            query = grass.vector_what(map=[self.mapName],
-                                      coord=self.mapWin.GetLastEN(),
-                                      distance=threshold, skip_attributes=True)
+            query = grass.vector_what(
+                map=[self.mapName],
+                coord=self.mapWin.GetLastEN(),
+                distance=threshold,
+                skip_attributes=True,
+            )
         except grass.ScriptError:
         except grass.ScriptError:
-            GError(parent=self,
-                   message=_("Failed to query vector map(s) <%s>.") % self.map)
+            GError(
+                parent=self, message=_("Failed to query vector map(s) <%s>.") % self.map
+            )
             return None
             return None
 
 
         return query[0]
         return query[0]
 
 
     def GetLineStringSelectedCats(self):
     def GetLineStringSelectedCats(self):
         """Return line of categories separated by comma"""
         """Return line of categories separated by comma"""
-        strTMP = ''
+        strTMP = ""
         for cat in self.selectedFeatures:
         for cat in self.selectedFeatures:
-            strTMP += str(cat['Category']) + ','
+            strTMP += str(cat["Category"]) + ","
         return strTMP[:-1]
         return strTMP[:-1]
 
 
-    def _id_generator(self, size=6,
-                      chars=string.ascii_uppercase + string.digits):
-        return ''.join(random.choice(chars) for _ in range(size))
+    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):
     def OnExportMap(self, event):
         """Export selected features to a new map
         """Export selected features to a new map
@@ -328,31 +332,43 @@ class VectorSelectBase():
         """
         """
 
 
         if len(self.selectedFeatures) == 0:
         if len(self.selectedFeatures) == 0:
-            GMessage(_('No features selected'))
+            GMessage(_("No features selected"))
             return
             return
-        lst = ''
-        for cat in self.selectedFeatures:  # build text string of categories for v.extract input
-            lst += str(cat['Category']) + ','
+        lst = ""
+        for (
+            cat
+        ) in (
+            self.selectedFeatures
+        ):  # build text string of categories for v.extract input
+            lst += str(cat["Category"]) + ","
         lst = lst[:-1]
         lst = lst[:-1]
-        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'],
-                              output=outMap,
-                              cats=lst,
-                              getErrorMsg=True)
+        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"],
+            output=outMap,
+            cats=lst,
+            getErrorMsg=True,
+        )
         if ret == 0:
         if ret == 0:
             tree = self._giface.GetLayerTree()
             tree = self._giface.GetLayerTree()
             if tree:
             if tree:
-                tree.AddLayer(ltype='vector', lname=outMap,
-                              lcmd=['d.vect', 'map=%s' % outMap],
-                              lchecked=True)
+                tree.AddLayer(
+                    ltype="vector",
+                    lname=outMap,
+                    lcmd=["d.vect", "map=%s" % outMap],
+                    lchecked=True,
+                )
 
 
                 # TODO colorize new map
                 # TODO colorize new map
                 self.Reset()
                 self.Reset()
             else:
             else:
-                GMessage(_('Vector map <%s> was created') % outMap)
+                GMessage(_("Vector map <%s> was created") % outMap)
                 self.Reset()
                 self.Reset()
         else:
         else:
             GError(_("Unable to create a new vector map.\n\nReason: %s") % err)
             GError(_("Unable to create a new vector map.\n\nReason: %s") % err)
@@ -376,7 +392,7 @@ class VectorSelectBase():
     """
     """
 
 
 
 
-class VectorSelectHighlighter():
+class VectorSelectHighlighter:
     """Class for highlighting selected features on display
     """Class for highlighting selected features on display
 
 
     :param mapdisp: Map display frame
     :param mapdisp: Map display frame
@@ -388,29 +404,29 @@ class VectorSelectHighlighter():
         self.giface = giface
         self.giface = giface
         self.layerCat = {}
         self.layerCat = {}
         self.data = {}
         self.data = {}
-        self.data['Category'] = list()
-        self.data['Map'] = None
-        self.data['Layer'] = None
+        self.data["Category"] = list()
+        self.data["Map"] = None
+        self.data["Layer"] = None
 
 
     def SetMap(self, map):
     def SetMap(self, map):
-        self.data['Map'] = map
+        self.data["Map"] = map
 
 
     def SetLayer(self, layer):
     def SetLayer(self, layer):
-        self.data['Layer'] = layer
+        self.data["Layer"] = layer
 
 
     def SetCats(self, cats):
     def SetCats(self, cats):
-        self.data['Category'] = cats
+        self.data["Category"] = cats
 
 
     def Clear(self):
     def Clear(self):
-        self.data['Category'] = list()
-        self.data['Map'] = None
-        self.data['Layer'] = None
+        self.data["Category"] = list()
+        self.data["Map"] = None
+        self.data["Layer"] = None
         self.mapdisp.RemoveQueryLayer()
         self.mapdisp.RemoveQueryLayer()
         self.giface.GetMapWindow().UpdateMap(render=False)
         self.giface.GetMapWindow().UpdateMap(render=False)
 
 
     def DrawSelected(self):
     def DrawSelected(self):
         """Highlight selected features"""
         """Highlight selected features"""
-        self.layerCat[int(self.data['Layer'])] = self.data['Category']
+        self.layerCat[int(self.data["Layer"])] = self.data["Category"]
 
 
         # add map layer with higlighted vector features
         # add map layer with higlighted vector features
         self.AddQueryMapLayer()  # -> self.qlayer
         self.AddQueryMapLayer()  # -> self.qlayer
@@ -428,11 +444,12 @@ class VectorSelectHighlighter():
         if self.qlayer:
         if self.qlayer:
             self.qlayer.SetCmd(
             self.qlayer.SetCmd(
                 self.mapdisp.AddTmpVectorMapLayer(
                 self.mapdisp.AddTmpVectorMapLayer(
-                    self.data['Map'],
-                    self.layerCat,
-                    addLayer=False))
+                    self.data["Map"], self.layerCat, addLayer=False
+                )
+            )
         else:
         else:
             self.qlayer = self.mapdisp.AddTmpVectorMapLayer(
             self.qlayer = self.mapdisp.AddTmpVectorMapLayer(
-                self.data['Map'], self.layerCat)
+                self.data["Map"], self.layerCat
+            )
 
 
         return self.qlayer
         return self.qlayer

Plik diff jest za duży
+ 213 - 236
gui/wxpython/gui_core/widgets.py


+ 142 - 42
gui/wxpython/gui_core/wrap.py

@@ -23,6 +23,7 @@ import wx.lib.filebrowsebutton as filebrowse
 import wx.lib.scrolledpanel as scrolled
 import wx.lib.scrolledpanel as scrolled
 from wx.lib import expando
 from wx.lib import expando
 from wx.lib import buttons
 from wx.lib import buttons
+
 try:
 try:
     import wx.lib.agw.customtreectrl as CT
     import wx.lib.agw.customtreectrl as CT
 except ImportError:
 except ImportError:
@@ -37,6 +38,7 @@ if wxPythonPhoenix:
     from wx.adv import BitmapComboBox as BitmapComboBox_
     from wx.adv import BitmapComboBox as BitmapComboBox_
     from wx.adv import HyperlinkCtrl as HyperlinkCtrl_
     from wx.adv import HyperlinkCtrl as HyperlinkCtrl_
     from wx.adv import HL_ALIGN_LEFT, HL_CONTEXTMENU
     from wx.adv import HL_ALIGN_LEFT, HL_CONTEXTMENU
+
     ComboPopup = wx.ComboPopup
     ComboPopup = wx.ComboPopup
     wxComboCtrl = wx.ComboCtrl
     wxComboCtrl = wx.ComboCtrl
 else:
 else:
@@ -46,6 +48,7 @@ else:
     from wx.combo import BitmapComboBox as BitmapComboBox_
     from wx.combo import BitmapComboBox as BitmapComboBox_
     from wx import HyperlinkCtrl as HyperlinkCtrl_
     from wx import HyperlinkCtrl as HyperlinkCtrl_
     from wx import HL_ALIGN_LEFT, HL_CONTEXTMENU
     from wx import HL_ALIGN_LEFT, HL_CONTEXTMENU
+
     ComboPopup = wx.combo.ComboPopup
     ComboPopup = wx.combo.ComboPopup
     wxComboCtrl = wx.combo.ComboCtrl
     wxComboCtrl = wx.combo.ComboCtrl
 
 
@@ -58,10 +61,11 @@ else:
 def IsDark():
 def IsDark():
     """Detects if used theme is dark.
     """Detects if used theme is dark.
     Wraps wx method for different versions."""
     Wraps wx method for different versions."""
+
     def luminance(c):
     def luminance(c):
         return (0.299 * c.Red() + 0.587 * c.Green() + 0.114 * c.Blue()) / 255
         return (0.299 * c.Red() + 0.587 * c.Green() + 0.114 * c.Blue()) / 255
 
 
-    if hasattr(wx.SystemSettings, 'GetAppearance'):
+    if hasattr(wx.SystemSettings, "GetAppearance"):
         return wx.SystemSettings.GetAppearance().IsDark()
         return wx.SystemSettings.GetAppearance().IsDark()
 
 
     # for older wx
     # for older wx
@@ -147,10 +151,12 @@ class SpinCtrl(wx.SpinCtrl):
 
 
     def __init__(self, *args, **kwargs):
     def __init__(self, *args, **kwargs):
         if gtk3:
         if gtk3:
-            if 'size' in kwargs:
-                kwargs['size'] = wx.Size(max(self.gtk3MinSize, kwargs['size'][0]), kwargs['size'][1])
+            if "size" in kwargs:
+                kwargs["size"] = wx.Size(
+                    max(self.gtk3MinSize, kwargs["size"][0]), kwargs["size"][1]
+                )
             else:
             else:
-                kwargs['size'] = wx.Size(self.gtk3MinSize, -1)
+                kwargs["size"] = wx.Size(self.gtk3MinSize, -1)
 
 
         wx.SpinCtrl.__init__(self, *args, **kwargs)
         wx.SpinCtrl.__init__(self, *args, **kwargs)
 
 
@@ -169,10 +175,12 @@ class FloatSpin(fs.FloatSpin):
 
 
     def __init__(self, *args, **kwargs):
     def __init__(self, *args, **kwargs):
         if gtk3:
         if gtk3:
-            if 'size' in kwargs:
-                kwargs['size'] = wx.Size(max(self.gtk3MinSize, kwargs['size'][0]), kwargs['size'][1])
+            if "size" in kwargs:
+                kwargs["size"] = wx.Size(
+                    max(self.gtk3MinSize, kwargs["size"][0]), kwargs["size"][1]
+                )
             else:
             else:
-                kwargs['size'] = wx.Size(self.gtk3MinSize, -1)
+                kwargs["size"] = wx.Size(self.gtk3MinSize, -1)
 
 
         fs.FloatSpin.__init__(self, *args, **kwargs)
         fs.FloatSpin.__init__(self, *args, **kwargs)
 
 
@@ -222,6 +230,7 @@ class CancelButton(Button):
         else:
         else:
             self.SetLabel(_("&Cancel"))
             self.SetLabel(_("&Cancel"))
 
 
+
 class CloseButton(Button):
 class CloseButton(Button):
     """Wrapper around a Close labeled Button with stock id wx.ID_CANCEL
     """Wrapper around a Close labeled Button with stock id wx.ID_CANCEL
     to disable default key binding on certain platforms/wxpython versions"""
     to disable default key binding on certain platforms/wxpython versions"""
@@ -234,6 +243,7 @@ class CloseButton(Button):
         else:
         else:
             self.SetLabel(_("&Close"))
             self.SetLabel(_("&Close"))
 
 
+
 class ApplyButton(Button):
 class ApplyButton(Button):
     """Wrapper around a Button with stock id wx.ID_APPLY,
     """Wrapper around a Button with stock id wx.ID_APPLY,
     to disable default key binding on certain platforms"""
     to disable default key binding on certain platforms"""
@@ -382,39 +392,50 @@ class ListCtrl(wx.ListCtrl):
 
 
     def InsertItem(self, index, label, imageIndex=-1):
     def InsertItem(self, index, label, imageIndex=-1):
         if wxPythonPhoenix:
         if wxPythonPhoenix:
-            return wx.ListCtrl.InsertItem(self, index=index, label=label, imageIndex=imageIndex)
+            return wx.ListCtrl.InsertItem(
+                self, index=index, label=label, imageIndex=imageIndex
+            )
         else:
         else:
-            return wx.ListCtrl.InsertStringItem(self, index=index, label=label, imageIndex=imageIndex)
+            return wx.ListCtrl.InsertStringItem(
+                self, index=index, label=label, imageIndex=imageIndex
+            )
 
 
     def SetItem(self, index, column, label, imageId=-1):
     def SetItem(self, index, column, label, imageId=-1):
         if wxPythonPhoenix:
         if wxPythonPhoenix:
-            return wx.ListCtrl.SetItem(self, index=index, column=column, label=label, imageId=imageId)
+            return wx.ListCtrl.SetItem(
+                self, index=index, column=column, label=label, imageId=imageId
+            )
         else:
         else:
-            return wx.ListCtrl.SetStringItem(self, index=index, col=column, label=label, imageId=imageId)
+            return wx.ListCtrl.SetStringItem(
+                self, index=index, col=column, label=label, imageId=imageId
+            )
 
 
     def CheckItem(self, item, check=True):
     def CheckItem(self, item, check=True):
         """Uses either deprecated listmix.CheckListCtrlMixin
         """Uses either deprecated listmix.CheckListCtrlMixin
         or new checkbox implementation in wx.ListCtrl since 4.1.0"""
         or new checkbox implementation in wx.ListCtrl since 4.1.0"""
-        if hasattr(self, 'HasCheckBoxes'):
+        if hasattr(self, "HasCheckBoxes"):
             wx.ListCtrl.CheckItem(self, item, check)
             wx.ListCtrl.CheckItem(self, item, check)
         else:
         else:
             super(ListCtrl, self).CheckItem(item, check)
             super(ListCtrl, self).CheckItem(item, check)
 
 
     def IsItemChecked(self, item):
     def IsItemChecked(self, item):
-        if hasattr(self, 'HasCheckBoxes'):
+        if hasattr(self, "HasCheckBoxes"):
             return wx.ListCtrl.IsItemChecked(self, item)
             return wx.ListCtrl.IsItemChecked(self, item)
         else:
         else:
             return super(ListCtrl, self).IsChecked(item)
             return super(ListCtrl, self).IsChecked(item)
 
 
 
 
 if CheckWxVersion([4, 1, 0]):
 if CheckWxVersion([4, 1, 0]):
-    class CheckListCtrlMixin():
+
+    class CheckListCtrlMixin:
         """This class pretends to be deprecated CheckListCtrlMixin mixin and
         """This class pretends to be deprecated CheckListCtrlMixin mixin and
         only enables checkboxes in new versions of ListCtrl"""
         only enables checkboxes in new versions of ListCtrl"""
 
 
         def __init__(self):
         def __init__(self):
             self.EnableCheckBoxes(True)
             self.EnableCheckBoxes(True)
             self.AssignImageList(wx.ImageList(16, 16), wx.IMAGE_LIST_SMALL)
             self.AssignImageList(wx.ImageList(16, 16), wx.IMAGE_LIST_SMALL)
+
+
 else:
 else:
     import wx.lib.mixins.listctrl as listmix
     import wx.lib.mixins.listctrl as listmix
 
 
@@ -436,7 +457,9 @@ class TreeCtrl(wx.TreeCtrl):
         if wxPythonPhoenix:
         if wxPythonPhoenix:
             return wx.TreeCtrl.AppendItem(self, parent, text, image, selImage, data)
             return wx.TreeCtrl.AppendItem(self, parent, text, image, selImage, data)
         else:
         else:
-            return wx.TreeCtrl.AppendItem(self, parent, text, image, selImage, wx.TreeItemData(data))
+            return wx.TreeCtrl.AppendItem(
+                self, parent, text, image, selImage, wx.TreeItemData(data)
+            )
 
 
     def GetItemData(self, item):
     def GetItemData(self, item):
         if wxPythonPhoenix:
         if wxPythonPhoenix:
@@ -466,25 +489,80 @@ class ToolBar(wx.ToolBar):
     def __init__(self, *args, **kwargs):
     def __init__(self, *args, **kwargs):
         wx.ToolBar.__init__(self, *args, **kwargs)
         wx.ToolBar.__init__(self, *args, **kwargs)
 
 
-    def AddLabelTool(self, toolId, label, bitmap, bmpDisabled=wx.NullBitmap, kind=0,
-                     shortHelpString='', longHelpString='', clientData=None):
-        if wxPythonPhoenix:
-            return wx.ToolBar.AddTool(self, toolId=toolId, label=label, bitmap=bitmap, bmpDisabled=bmpDisabled,
-                                      kind=kind, shortHelp=shortHelpString, longHelp=longHelpString,
-                                      clientData=clientData)
-        else:
-            return wx.ToolBar.AddLabelTool(self, toolId, label, bitmap, bmpDisabled, kind,
-                                           shortHelpString, longHelpString, clientData)
-
-    def InsertLabelTool(self, pos, toolId, label, bitmap, bmpDisabled=wx.NullBitmap, kind=0,
-                        shortHelpString='', longHelpString='', clientData=None):
-        if wxPythonPhoenix:
-            return wx.ToolBar.InsertTool(self, pos, toolId=toolId, label=label, bitmap=bitmap, bmpDisabled=bmpDisabled,
-                                         kind=kind, shortHelp=shortHelpString, longHelp=longHelpString,
-                                         clientData=clientData)
-        else:
-            return wx.ToolBar.InsertLabelTool(self, pos, toolId, label, bitmap, bmpDisabled, kind,
-                                              shortHelpString, longHelpString, clientData)
+    def AddLabelTool(
+        self,
+        toolId,
+        label,
+        bitmap,
+        bmpDisabled=wx.NullBitmap,
+        kind=0,
+        shortHelpString="",
+        longHelpString="",
+        clientData=None,
+    ):
+        if wxPythonPhoenix:
+            return wx.ToolBar.AddTool(
+                self,
+                toolId=toolId,
+                label=label,
+                bitmap=bitmap,
+                bmpDisabled=bmpDisabled,
+                kind=kind,
+                shortHelp=shortHelpString,
+                longHelp=longHelpString,
+                clientData=clientData,
+            )
+        else:
+            return wx.ToolBar.AddLabelTool(
+                self,
+                toolId,
+                label,
+                bitmap,
+                bmpDisabled,
+                kind,
+                shortHelpString,
+                longHelpString,
+                clientData,
+            )
+
+    def InsertLabelTool(
+        self,
+        pos,
+        toolId,
+        label,
+        bitmap,
+        bmpDisabled=wx.NullBitmap,
+        kind=0,
+        shortHelpString="",
+        longHelpString="",
+        clientData=None,
+    ):
+        if wxPythonPhoenix:
+            return wx.ToolBar.InsertTool(
+                self,
+                pos,
+                toolId=toolId,
+                label=label,
+                bitmap=bitmap,
+                bmpDisabled=bmpDisabled,
+                kind=kind,
+                shortHelp=shortHelpString,
+                longHelp=longHelpString,
+                clientData=clientData,
+            )
+        else:
+            return wx.ToolBar.InsertLabelTool(
+                self,
+                pos,
+                toolId,
+                label,
+                bitmap,
+                bmpDisabled,
+                kind,
+                shortHelpString,
+                longHelpString,
+                clientData,
+            )
 
 
 
 
 class Menu(wx.Menu):
 class Menu(wx.Menu):
@@ -615,14 +693,33 @@ class TextEntryDialog(wx.TextEntryDialog):
     """Wrapper around wx.TextEntryDialog to have more control
     """Wrapper around wx.TextEntryDialog to have more control
     over the widget on different platforms/wxpython versions"""
     over the widget on different platforms/wxpython versions"""
 
 
-    def __init__(self, parent, message, caption="Please enter text", value="",
-                 style=wx.OK | wx.CANCEL | wx.CENTRE, pos=wx.DefaultPosition):
-        if wxPythonPhoenix:
-            super(TextEntryDialog, self).__init__(parent=parent, message=message, caption=caption,
-                                                  value=value, style=style, pos=pos)
-        else:
-            super(TextEntryDialog, self).__init__(parent=parent, message=message, caption=caption,
-                                                  defaultValue=value, style=style, pos=pos)
+    def __init__(
+        self,
+        parent,
+        message,
+        caption="Please enter text",
+        value="",
+        style=wx.OK | wx.CANCEL | wx.CENTRE,
+        pos=wx.DefaultPosition,
+    ):
+        if wxPythonPhoenix:
+            super(TextEntryDialog, self).__init__(
+                parent=parent,
+                message=message,
+                caption=caption,
+                value=value,
+                style=style,
+                pos=pos,
+            )
+        else:
+            super(TextEntryDialog, self).__init__(
+                parent=parent,
+                message=message,
+                caption=caption,
+                defaultValue=value,
+                style=style,
+                pos=pos,
+            )
 
 
 
 
 class ColourSelect(csel.ColourSelect):
 class ColourSelect(csel.ColourSelect):
@@ -669,6 +766,7 @@ class Notebook(wx.Notebook):
 class OwnerDrawnComboBox(OwnerDrawnComboBox_):
 class OwnerDrawnComboBox(OwnerDrawnComboBox_):
     """Wrapper around OwnerDrawnComboBox to have more control
     """Wrapper around OwnerDrawnComboBox to have more control
     over the widget on different platforms/wxpython versions"""
     over the widget on different platforms/wxpython versions"""
+
     ODCB_PAINTING_CONTROL = ODCB_PAINTING_CONTROL
     ODCB_PAINTING_CONTROL = ODCB_PAINTING_CONTROL
     ODCB_PAINTING_SELECTED = ODCB_PAINTING_SELECTED
     ODCB_PAINTING_SELECTED = ODCB_PAINTING_SELECTED
 
 
@@ -729,6 +827,7 @@ class DirBrowseButton(filebrowse.DirBrowseButton):
 class ExpandoTextCtrl(expando.ExpandoTextCtrl):
 class ExpandoTextCtrl(expando.ExpandoTextCtrl):
     """Wrapper around expando.ExpandoTextCtrl to have more control
     """Wrapper around expando.ExpandoTextCtrl to have more control
     over the widget on different platforms/wxpython versions"""
     over the widget on different platforms/wxpython versions"""
+
     EVT_ETC_LAYOUT_NEEDED = expando.EVT_ETC_LAYOUT_NEEDED
     EVT_ETC_LAYOUT_NEEDED = expando.EVT_ETC_LAYOUT_NEEDED
 
 
     def __init__(self, *args, **kwargs):
     def __init__(self, *args, **kwargs):
@@ -760,6 +859,7 @@ class ListBox(wx.ListBox):
 class HyperlinkCtrl(HyperlinkCtrl_):
 class HyperlinkCtrl(HyperlinkCtrl_):
     """Wrapper around HyperlinkCtrl to have more control
     """Wrapper around HyperlinkCtrl to have more control
     over the widget on different platforms/wxpython versions"""
     over the widget on different platforms/wxpython versions"""
+
     HL_ALIGN_LEFT = HL_ALIGN_LEFT
     HL_ALIGN_LEFT = HL_ALIGN_LEFT
     HL_CONTEXTMENU = HL_CONTEXTMENU
     HL_CONTEXTMENU = HL_CONTEXTMENU
 
 

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

@@ -1,9 +1,9 @@
 all = [
 all = [
-    'digit',
-    'plots',
-    'dialogs',
-    'g.gui.iclass',
-    'toolbars',
-    'statistics',
-    'frame',
+    "digit",
+    "plots",
+    "dialogs",
+    "g.gui.iclass",
+    "toolbars",
+    "statistics",
+    "frame",
 ]
 ]

+ 191 - 175
gui/wxpython/iclass/dialogs.py

@@ -31,8 +31,16 @@ from core.gcmd import GError, RunCommand, GMessage
 from gui_core.dialogs import SimpleDialog, GroupDialog
 from gui_core.dialogs import SimpleDialog, GroupDialog
 from gui_core import gselect
 from gui_core import gselect
 from gui_core.widgets import SimpleValidator
 from gui_core.widgets import SimpleValidator
-from gui_core.wrap import CheckBox, Button, StaticText, \
-    StaticBox, TextCtrl, Menu, NewId, ListCtrl
+from gui_core.wrap import (
+    CheckBox,
+    Button,
+    StaticText,
+    StaticBox,
+    TextCtrl,
+    Menu,
+    NewId,
+    ListCtrl,
+)
 
 
 import grass.script as grass
 import grass.script as grass
 
 
@@ -40,8 +48,14 @@ import grass.script as grass
 class IClassGroupDialog(SimpleDialog):
 class IClassGroupDialog(SimpleDialog):
     """Dialog for imagery group selection"""
     """Dialog for imagery group selection"""
 
 
-    def __init__(self, parent, group=None, subgroup=None,
-                 title=_("Select imagery group"), id=wx.ID_ANY):
+    def __init__(
+        self,
+        parent,
+        group=None,
+        subgroup=None,
+        title=_("Select imagery group"),
+        id=wx.ID_ANY,
+    ):
         """
         """
         Does post init and layout.
         Does post init and layout.
 
 
@@ -55,12 +69,11 @@ class IClassGroupDialog(SimpleDialog):
 
 
         self.groupSelect = gselect.Select(
         self.groupSelect = gselect.Select(
             parent=self.panel,
             parent=self.panel,
-            type='group',
-            mapsets=[
-                grass.gisenv()['MAPSET']],
+            type="group",
+            mapsets=[grass.gisenv()["MAPSET"]],
             size=globalvar.DIALOG_GSELECT_SIZE,
             size=globalvar.DIALOG_GSELECT_SIZE,
-            validator=SimpleValidator(
-                callback=self.ValidatorCallback))
+            validator=SimpleValidator(callback=self.ValidatorCallback),
+        )
 
 
         # TODO use when subgroup will be optional
         # TODO use when subgroup will be optional
         # self.subg_chbox = wx.CheckBox(parent = self.panel, id = wx.ID_ANY,
         # self.subg_chbox = wx.CheckBox(parent = self.panel, id = wx.ID_ANY,
@@ -74,13 +87,14 @@ class IClassGroupDialog(SimpleDialog):
         if subgroup:
         if subgroup:
             self.subGroupSelect.SetValue(subgroup)
             self.subGroupSelect.SetValue(subgroup)
 
 
-        self.editGroup = Button(parent=self.panel, id=wx.ID_ANY,
-                                   label=_("Create/edit group..."))
+        self.editGroup = Button(
+            parent=self.panel, id=wx.ID_ANY, label=_("Create/edit group...")
+        )
 
 
         self.editGroup.Bind(wx.EVT_BUTTON, self.OnEditGroup)
         self.editGroup.Bind(wx.EVT_BUTTON, self.OnEditGroup)
         self.groupSelect.GetTextCtrl().Bind(
         self.groupSelect.GetTextCtrl().Bind(
-            wx.EVT_TEXT, lambda event: wx.CallAfter(
-                self.GroupSelected))
+            wx.EVT_TEXT, lambda event: wx.CallAfter(self.GroupSelected)
+        )
 
 
         self.warning = _("Name of imagery group is missing.")
         self.warning = _("Name of imagery group is missing.")
         self._layout()
         self._layout()
@@ -88,38 +102,38 @@ class IClassGroupDialog(SimpleDialog):
 
 
     def _layout(self):
     def _layout(self):
         """Do layout"""
         """Do layout"""
-        self.dataSizer.Add(StaticText(self.panel, id=wx.ID_ANY,
-                                      label=_("Name of imagery group:")),
-                           proportion=0,
-                           flag=wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT,
-                           border=5)
-        self.dataSizer.Add(self.groupSelect, proportion=0,
-                           flag=wx.EXPAND | wx.ALL, border=5)
+        self.dataSizer.Add(
+            StaticText(self.panel, id=wx.ID_ANY, label=_("Name of imagery group:")),
+            proportion=0,
+            flag=wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT,
+            border=5,
+        )
+        self.dataSizer.Add(
+            self.groupSelect, proportion=0, flag=wx.EXPAND | wx.ALL, border=5
+        )
 
 
         # TODO use when subgroup will be optional
         # TODO use when subgroup will be optional
         # self.dataSizer.Add(self.subg_chbox, proportion = 0,
         # self.dataSizer.Add(self.subg_chbox, proportion = 0,
         # flag = wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, border = 5)
         # flag = wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, border = 5)
 
 
         self.dataSizer.Add(
         self.dataSizer.Add(
-            StaticText(
-                self.panel,
-                id=wx.ID_ANY,
-                label=_("Name of imagery subgroup:")),
+            StaticText(self.panel, id=wx.ID_ANY, label=_("Name of imagery subgroup:")),
             proportion=0,
             proportion=0,
             flag=wx.EXPAND | wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT,
             flag=wx.EXPAND | wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT,
-            border=5)
-        self.dataSizer.Add(self.subGroupSelect, proportion=0,
-                           flag=wx.EXPAND | wx.ALL, border=5)
+            border=5,
+        )
+        self.dataSizer.Add(
+            self.subGroupSelect, proportion=0, flag=wx.EXPAND | wx.ALL, border=5
+        )
 
 
-        self.dataSizer.Add(self.editGroup, proportion=0,
-                           flag=wx.ALL, border=5)
+        self.dataSizer.Add(self.editGroup, proportion=0, flag=wx.ALL, border=5)
 
 
         self.panel.SetSizer(self.sizer)
         self.panel.SetSizer(self.sizer)
         self.sizer.Fit(self)
         self.sizer.Fit(self)
 
 
         # TODO use when subgroup will be optional
         # TODO use when subgroup will be optional
         # self.subg_panel.Show(False)
         # self.subg_panel.Show(False)
-        #self.subg_chbox.Bind(wx.EVT_CHECKBOX, self.OnSubgChbox)
+        # self.subg_chbox.Bind(wx.EVT_CHECKBOX, self.OnSubgChbox)
 
 
     def OnSubgChbox(self, event):
     def OnSubgChbox(self, event):
         self.use_subg = self.subg_chbox.GetValue()
         self.use_subg = self.subg_chbox.GetValue()
@@ -162,42 +176,43 @@ class IClassGroupDialog(SimpleDialog):
 
 
     def GetSelectedGroup(self):
     def GetSelectedGroup(self):
         """Return currently selected group (without mapset)"""
         """Return currently selected group (without mapset)"""
-        return self.groupSelect.GetValue().split('@')[0]
+        return self.groupSelect.GetValue().split("@")[0]
 
 
     def GetGroupBandsErr(self, parent):
     def GetGroupBandsErr(self, parent):
         """Get list of raster bands which are in the soubgroup of group with both having same name.
         """Get list of raster bands which are in the soubgroup of group with both having same name.
-           If the group does not exists or it does not contain any bands in subgoup with same name,
-           error dialog is shown.
+        If the group does not exists or it does not contain any bands in subgoup with same name,
+        error dialog is shown.
         """
         """
         gr, s = self.GetData()
         gr, s = self.GetData()
 
 
-        group = grass.find_file(name=gr, element='group')
+        group = grass.find_file(name=gr, element="group")
 
 
         bands = []
         bands = []
-        g = group['name']
+        g = group["name"]
 
 
         if g:
         if g:
             if self.use_subg:
             if self.use_subg:
-                if s == '':
+                if s == "":
                     GError(_("Please choose a subgroup."), parent=parent)
                     GError(_("Please choose a subgroup."), parent=parent)
                     return bands
                     return bands
                 if s not in self.GetSubgroups(g):
                 if s not in self.GetSubgroups(g):
                     GError(
                     GError(
-                        _("Subgroup <%s> not found in group <%s>") %
-                        (s, g), parent=parent)
+                        _("Subgroup <%s> not found in group <%s>") % (s, g),
+                        parent=parent,
+                    )
                     return bands
                     return bands
 
 
             bands = self.GetGroupBands(g, s)
             bands = self.GetGroupBands(g, s)
             if not bands:
             if not bands:
                 if self.use_subg:
                 if self.use_subg:
-                    GError(_("No data found in subgroup <%s> of group <%s>.\n"
-                             ".")
-                           % (s, g), parent=parent)
+                    GError(
+                        _("No data found in subgroup <%s> of group <%s>.\n" ".")
+                        % (s, g),
+                        parent=parent,
+                    )
 
 
                 else:
                 else:
-                    GError(_("No data found in group <%s>.\n"
-                             ".")
-                           % g, parent=parent)
+                    GError(_("No data found in group <%s>.\n" ".") % g, parent=parent)
         else:
         else:
             GError(_("Group <%s> not found") % gr, parent=parent)
             GError(_("Group <%s> not found") % gr, parent=parent)
 
 
@@ -208,21 +223,17 @@ class IClassGroupDialog(SimpleDialog):
 
 
         kwargs = {}
         kwargs = {}
         if subgroup:
         if subgroup:
-            kwargs['subgroup'] = subgroup
+            kwargs["subgroup"] = subgroup
 
 
-        res = RunCommand('i.group',
-                         flags='g',
-                         group=group,
-                         read=True, **kwargs).strip()
+        res = RunCommand("i.group", flags="g", group=group, read=True, **kwargs).strip()
         bands = None
         bands = None
-        if res.split('\n')[0]:
-            bands = res.split('\n')
+        if res.split("\n")[0]:
+            bands = res.split("\n")
 
 
         return bands
         return bands
 
 
     def GetSubgroups(self, group):
     def GetSubgroups(self, group):
-        return RunCommand('i.group', group=group,
-                          read=True, flags='sg').splitlines()
+        return RunCommand("i.group", group=group, read=True, flags="sg").splitlines()
 
 
 
 
 class IClassMapDialog(SimpleDialog):
 class IClassMapDialog(SimpleDialog):
@@ -243,8 +254,8 @@ class IClassMapDialog(SimpleDialog):
             parent=self.panel,
             parent=self.panel,
             type=element,
             type=element,
             size=globalvar.DIALOG_GSELECT_SIZE,
             size=globalvar.DIALOG_GSELECT_SIZE,
-            validator=SimpleValidator(
-                callback=self.ValidatorCallback))
+            validator=SimpleValidator(callback=self.ValidatorCallback),
+        )
         self.element.SetFocus()
         self.element.SetFocus()
 
 
         self.warning = _("Name of map is missing.")
         self.warning = _("Name of map is missing.")
@@ -253,15 +264,19 @@ class IClassMapDialog(SimpleDialog):
 
 
     def _layout(self):
     def _layout(self):
         """Do layout"""
         """Do layout"""
-        if self.elementType == 'raster':
+        if self.elementType == "raster":
             label = _("Name of raster map:")
             label = _("Name of raster map:")
-        elif self.elementType == 'vector':
+        elif self.elementType == "vector":
             label = _("Name of vector map:")
             label = _("Name of vector map:")
-        self.dataSizer.Add(StaticText(self.panel, id=wx.ID_ANY,
-                                      label=label),
-                           proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
-        self.dataSizer.Add(self.element, proportion=0,
-                           flag=wx.EXPAND | wx.ALL, border=5)
+        self.dataSizer.Add(
+            StaticText(self.panel, id=wx.ID_ANY, label=label),
+            proportion=0,
+            flag=wx.EXPAND | wx.ALL,
+            border=5,
+        )
+        self.dataSizer.Add(
+            self.element, proportion=0, flag=wx.EXPAND | wx.ALL, border=5
+        )
 
 
         self.panel.SetSizer(self.sizer)
         self.panel.SetSizer(self.sizer)
         self.sizer.Fit(self)
         self.sizer.Fit(self)
@@ -291,44 +306,29 @@ class IClassCategoryManagerDialog(wx.Dialog):
         panel = wx.Panel(parent=self, id=wx.ID_ANY)
         panel = wx.Panel(parent=self, id=wx.ID_ANY)
 
 
         mainSizer = wx.BoxSizer(wx.VERTICAL)
         mainSizer = wx.BoxSizer(wx.VERTICAL)
-        box = StaticBox(panel, id=wx.ID_ANY,
-                        label=" %s " % _("Classes"))
+        box = StaticBox(panel, id=wx.ID_ANY, label=" %s " % _("Classes"))
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
         gridSizer = wx.GridBagSizer(hgap=5, vgap=5)
         gridSizer = wx.GridBagSizer(hgap=5, vgap=5)
-        self.catList = CategoryListCtrl(panel, mapwindow=parent,
-                                        stats_data=parent.stats_data)
+        self.catList = CategoryListCtrl(
+            panel, mapwindow=parent, stats_data=parent.stats_data
+        )
         addButton = Button(panel, id=wx.ID_ADD)
         addButton = Button(panel, id=wx.ID_ADD)
         deleteButton = Button(panel, id=wx.ID_DELETE)
         deleteButton = Button(panel, id=wx.ID_DELETE)
 
 
-        gridSizer.Add(
-            self.catList, pos=(
-                0, 0), span=(
-                3, 1), flag=wx.EXPAND)
+        gridSizer.Add(self.catList, pos=(0, 0), span=(3, 1), flag=wx.EXPAND)
         gridSizer.Add(addButton, pos=(0, 1), flag=wx.EXPAND)
         gridSizer.Add(addButton, pos=(0, 1), flag=wx.EXPAND)
         gridSizer.Add(deleteButton, pos=(1, 1), flag=wx.EXPAND)
         gridSizer.Add(deleteButton, pos=(1, 1), flag=wx.EXPAND)
 
 
         gridSizer.AddGrowableCol(0)
         gridSizer.AddGrowableCol(0)
         gridSizer.AddGrowableRow(2)
         gridSizer.AddGrowableRow(2)
-        sizer.Add(
-            gridSizer,
-            proportion=1,
-            flag=wx.EXPAND | wx.ALL,
-            border=5)
-        mainSizer.Add(
-            sizer,
-            proportion=1,
-            flag=wx.EXPAND | wx.ALL,
-            border=5)
+        sizer.Add(gridSizer, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
+        mainSizer.Add(sizer, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
 
 
         btnSizer = wx.BoxSizer(wx.HORIZONTAL)
         btnSizer = wx.BoxSizer(wx.HORIZONTAL)
         closeButton = Button(panel, id=wx.ID_CLOSE)
         closeButton = Button(panel, id=wx.ID_CLOSE)
         btnSizer.Add(wx.Size(-1, -1), proportion=1, flag=wx.EXPAND)
         btnSizer.Add(wx.Size(-1, -1), proportion=1, flag=wx.EXPAND)
         btnSizer.Add(closeButton, proportion=0)
         btnSizer.Add(closeButton, proportion=0)
-        mainSizer.Add(
-            btnSizer,
-            proportion=0,
-            flag=wx.EXPAND | wx.ALL,
-            border=5)
+        mainSizer.Add(btnSizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
 
 
         addButton.Bind(wx.EVT_BUTTON, self.OnAddCategory)
         addButton.Bind(wx.EVT_BUTTON, self.OnAddCategory)
         deleteButton.Bind(wx.EVT_BUTTON, self.OnDeleteCategory)
         deleteButton.Bind(wx.EVT_BUTTON, self.OnDeleteCategory)
@@ -348,8 +348,8 @@ class IClassCategoryManagerDialog(wx.Dialog):
         else:
         else:
             cat = 1
             cat = 1
         # intentionally not translatable
         # intentionally not translatable
-        defaultName = 'class' + '_' + str(cat)
-        defaultColor = '0:0:0'
+        defaultName = "class" + "_" + str(cat)
+        defaultColor = "0:0:0"
         self.catList.AddCategory(cat=cat, name=defaultName, color=defaultColor)
         self.catList.AddCategory(cat=cat, name=defaultName, color=defaultColor)
 
 
     def OnDeleteCategory(self, event):
     def OnDeleteCategory(self, event):
@@ -369,9 +369,7 @@ class IClassCategoryManagerDialog(wx.Dialog):
         return self.catList
         return self.catList
 
 
 
 
-class CategoryListCtrl(ListCtrl,
-                       listmix.ListCtrlAutoWidthMixin,
-                       listmix.TextEditMixin):
+class CategoryListCtrl(ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.TextEditMixin):
     """Widget for controlling list of classes (categories).
     """Widget for controlling list of classes (categories).
 
 
     CategoryListCtrl updates choice in mapwindow and removes raster map
     CategoryListCtrl updates choice in mapwindow and removes raster map
@@ -390,10 +388,12 @@ class CategoryListCtrl(ListCtrl,
         :param id: wx id
         :param id: wx id
         """
         """
         ListCtrl.__init__(
         ListCtrl.__init__(
-            self, parent, id, style=wx.LC_REPORT | wx.LC_VIRTUAL | wx.LC_HRULES |
-            wx.LC_VRULES)
-        self.columns = ((_('Class name'), 'name'),
-                        (_('Color'), 'color'))
+            self,
+            parent,
+            id,
+            style=wx.LC_REPORT | wx.LC_VIRTUAL | wx.LC_HRULES | wx.LC_VRULES,
+        )
+        self.columns = ((_("Class name"), "name"), (_("Color"), "color"))
         self.Populate(columns=self.columns)
         self.Populate(columns=self.columns)
         self.mapWindow = mapwindow
         self.mapWindow = mapwindow
         self.stats_data = stats_data
         self.stats_data = stats_data
@@ -421,24 +421,22 @@ class CategoryListCtrl(ListCtrl,
 
 
     def SetVirtualData(self, row, column, text):
     def SetVirtualData(self, row, column, text):
         attr = self.columns[column][1]
         attr = self.columns[column][1]
-        if attr == 'name':
+        if attr == "name":
             try:
             try:
-                text.encode('ascii')
+                text.encode("ascii")
             except UnicodeEncodeError:
             except UnicodeEncodeError:
-                GMessage(parent=self, message=_(
-                    "Please use only ASCII characters."))
+                GMessage(parent=self, message=_("Please use only ASCII characters."))
                 return
                 return
 
 
         cat = self.stats_data.GetCategories()[row]
         cat = self.stats_data.GetCategories()[row]
         self.stats_data.GetStatistics(cat).SetStatistics(stats={attr: text})
         self.stats_data.GetStatistics(cat).SetStatistics(stats={attr: text})
 
 
-        toolbar = self.mapWindow.toolbars['iClass']
+        toolbar = self.mapWindow.toolbars["iClass"]
         toolbar.choice.SetSelection(row)
         toolbar.choice.SetSelection(row)
         self.Select(row)
         self.Select(row)
 
 
-        if attr == 'name':
-            self.mapWindow.UpdateRasterName(
-                text, toolbar.GetSelectedCategoryIdx())
+        if attr == "name":
+            self.mapWindow.UpdateRasterName(text, toolbar.GetSelectedCategoryIdx())
 
 
         self.mapWindow.UpdateChangeState(changes=True)
         self.mapWindow.UpdateChangeState(changes=True)
 
 
@@ -496,7 +494,7 @@ class CategoryListCtrl(ListCtrl,
         currentCol = event.GetColumn()
         currentCol = event.GetColumn()
         if currentCol == 1:
         if currentCol == 1:
             col = self.OnGetItemText(currentItem, currentCol)
             col = self.OnGetItemText(currentItem, currentCol)
-            col = map(int, col.split(':'))
+            col = map(int, col.split(":"))
 
 
             col_data = wx.ColourData()
             col_data = wx.ColourData()
             col_data.SetColour(wx.Colour(*col))
             col_data.SetColour(wx.Colour(*col))
@@ -506,7 +504,7 @@ class CategoryListCtrl(ListCtrl,
 
 
             if dlg.ShowModal() == wx.ID_OK:
             if dlg.ShowModal() == wx.ID_OK:
                 color = dlg.GetColourData().GetColour().Get()
                 color = dlg.GetColourData().GetColour().Get()
-                color = ':'.join(map(str, color))
+                color = ":".join(map(str, color))
                 self.SetVirtualData(currentItem, currentCol, color)
                 self.SetVirtualData(currentItem, currentCol, color)
             dlg.Destroy()
             dlg.Destroy()
             wx.CallAfter(self.SetFocus)
             wx.CallAfter(self.SetFocus)
@@ -533,16 +531,13 @@ class CategoryListCtrl(ListCtrl,
 
 
         if not hasattr(self, "popupZoomtoAreas"):
         if not hasattr(self, "popupZoomtoAreas"):
             self.popupZoomtoAreas = NewId()
             self.popupZoomtoAreas = NewId()
-            self.Bind(
-                wx.EVT_MENU,
-                self.OnZoomToAreasByCat,
-                id=self.popupZoomtoAreas)
+            self.Bind(wx.EVT_MENU, self.OnZoomToAreasByCat, id=self.popupZoomtoAreas)
 
 
         # generate popup-menu
         # generate popup-menu
         menu = Menu()
         menu = Menu()
         menu.Append(
         menu.Append(
-            self.popupZoomtoAreas,
-            _("Zoom to training areas of selected class"))
+            self.popupZoomtoAreas, _("Zoom to training areas of selected class")
+        )
 
 
         self.PopupMenu(menu)
         self.PopupMenu(menu)
         menu.Destroy()
         menu.Destroy()
@@ -571,7 +566,7 @@ class CategoryListCtrl(ListCtrl,
 
 
     def OnGetItemAttr(self, item):
     def OnGetItemAttr(self, item):
         """Set correct class color for a item"""
         """Set correct class color for a item"""
-        back_c = wx.Colour(*map(int, self.OnGetItemText(item, 1).split(':')))
+        back_c = wx.Colour(*map(int, self.OnGetItemText(item, 1).split(":")))
         text_c = wx.Colour(*ContrastColor(back_c))
         text_c = wx.Colour(*ContrastColor(back_c))
 
 
         # 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
@@ -601,11 +596,17 @@ def ContrastColor(color):
 
 
 
 
 class IClassSignatureFileDialog(wx.Dialog):
 class IClassSignatureFileDialog(wx.Dialog):
-
-    def __init__(self, parent, group, subgroup,
-                 file=None, title=_("Save signature file"), id=wx.ID_ANY,
-                 style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
-                 **kwargs):
+    def __init__(
+        self,
+        parent,
+        group,
+        subgroup,
+        file=None,
+        title=_("Save signature file"),
+        id=wx.ID_ANY,
+        style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
+        **kwargs,
+    ):
         """Dialog for saving signature file
         """Dialog for saving signature file
 
 
         :param parent: window
         :param parent: window
@@ -622,12 +623,16 @@ class IClassSignatureFileDialog(wx.Dialog):
         # inconsistent group and subgroup name
         # inconsistent group and subgroup name
         # path:
         # path:
         # grassdata/nc_spm_08/landsat/group/test_group/subgroup/test_group/sig/sigFile
         # grassdata/nc_spm_08/landsat/group/test_group/subgroup/test_group/sig/sigFile
-        self.baseFilePath = os.path.join(env['GISDBASE'],
-                                         env['LOCATION_NAME'],
-                                         env['MAPSET'],
-                                         'group', group,
-                                         'subgroup', subgroup,
-                                         'sig')
+        self.baseFilePath = os.path.join(
+            env["GISDBASE"],
+            env["LOCATION_NAME"],
+            env["MAPSET"],
+            "group",
+            group,
+            "subgroup",
+            subgroup,
+            "sig",
+        )
         self.panel = wx.Panel(parent=self, id=wx.ID_ANY)
         self.panel = wx.Panel(parent=self, id=wx.ID_ANY)
 
 
         self.btnCancel = Button(parent=self.panel, id=wx.ID_CANCEL)
         self.btnCancel = Button(parent=self.panel, id=wx.ID_CANCEL)
@@ -664,35 +669,40 @@ class IClassSignatureFileDialog(wx.Dialog):
             StaticText(
             StaticText(
                 parent=self.panel,
                 parent=self.panel,
                 id=wx.ID_ANY,
                 id=wx.ID_ANY,
-                label=_("Enter name of signature file:")),
+                label=_("Enter name of signature file:"),
+            ),
             proportion=0,
             proportion=0,
             flag=wx.ALL,
             flag=wx.ALL,
-            border=3)
-        self.fileNameCtrl = TextCtrl(
-            parent=self.panel, id=wx.ID_ANY, size=(400, -1))
+            border=3,
+        )
+        self.fileNameCtrl = TextCtrl(parent=self.panel, id=wx.ID_ANY, size=(400, -1))
         if self.fileName:
         if self.fileName:
             self.fileNameCtrl.SetValue(self.fileName)
             self.fileNameCtrl.SetValue(self.fileName)
-        dataSizer.Add(self.fileNameCtrl,
-                      proportion=0, flag=wx.ALL | wx.EXPAND, border=3)
+        dataSizer.Add(
+            self.fileNameCtrl, proportion=0, flag=wx.ALL | wx.EXPAND, border=3
+        )
 
 
-        dataSizer.Add(StaticText(parent=self.panel, id=wx.ID_ANY,
-                                 label=_("Signature file path:")),
-                      proportion=0, flag=wx.ALL, border=3)
+        dataSizer.Add(
+            StaticText(
+                parent=self.panel, id=wx.ID_ANY, label=_("Signature file path:")
+            ),
+            proportion=0,
+            flag=wx.ALL,
+            border=3,
+        )
 
 
         self.pathPanel = scrolled.ScrolledPanel(self.panel, size=(-1, 40))
         self.pathPanel = scrolled.ScrolledPanel(self.panel, size=(-1, 40))
         pathSizer = wx.BoxSizer()
         pathSizer = wx.BoxSizer()
-        self.filePathText = StaticText(parent=self.pathPanel, id=wx.ID_ANY,
-                                       label=self.baseFilePath)
+        self.filePathText = StaticText(
+            parent=self.pathPanel, id=wx.ID_ANY, label=self.baseFilePath
+        )
         pathSizer.Add(
         pathSizer.Add(
-            self.filePathText,
-            proportion=1,
-            flag=wx.ALL | wx.EXPAND,
-            border=1)
+            self.filePathText, proportion=1, flag=wx.ALL | wx.EXPAND, border=1
+        )
         self.pathPanel.SetupScrolling(scroll_x=True, scroll_y=False)
         self.pathPanel.SetupScrolling(scroll_x=True, scroll_y=False)
         self.pathPanel.SetSizer(pathSizer)
         self.pathPanel.SetSizer(pathSizer)
 
 
-        dataSizer.Add(self.pathPanel,
-                      proportion=0, flag=wx.ALL | wx.EXPAND, border=3)
+        dataSizer.Add(self.pathPanel, proportion=0, flag=wx.ALL | wx.EXPAND, border=3)
 
 
         # buttons
         # buttons
         btnSizer = wx.StdDialogButtonSizer()
         btnSizer = wx.StdDialogButtonSizer()
@@ -700,11 +710,9 @@ class IClassSignatureFileDialog(wx.Dialog):
         btnSizer.AddButton(self.btnOK)
         btnSizer.AddButton(self.btnOK)
         btnSizer.Realize()
         btnSizer.Realize()
 
 
-        sizer.Add(dataSizer, proportion=1,
-                  flag=wx.EXPAND | wx.ALL, border=5)
+        sizer.Add(dataSizer, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
 
 
-        sizer.Add(btnSizer, proportion=0,
-                  flag=wx.EXPAND | wx.ALL, border=5)
+        sizer.Add(btnSizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
 
 
         self.panel.SetSizer(sizer)
         self.panel.SetSizer(sizer)
         sizer.Fit(self)
         sizer.Fit(self)
@@ -717,18 +725,21 @@ class IClassSignatureFileDialog(wx.Dialog):
         :param fullPath: return full path of sig. file
         :param fullPath: return full path of sig. file
         """
         """
         if fullPath:
         if fullPath:
-            return os.path.join(self.baseFilePath,
-                                self.fileNameCtrl.GetValue())
+            return os.path.join(self.baseFilePath, self.fileNameCtrl.GetValue())
 
 
         return self.fileNameCtrl.GetValue()
         return self.fileNameCtrl.GetValue()
 
 
 
 
 class IClassExportAreasDialog(wx.Dialog):
 class IClassExportAreasDialog(wx.Dialog):
-
-    def __init__(self, parent, vectorName=None,
-                 title=_("Export training areas"),
-                 id=wx.ID_ANY, style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
-                 **kwargs):
+    def __init__(
+        self,
+        parent,
+        vectorName=None,
+        title=_("Export training areas"),
+        id=wx.ID_ANY,
+        style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
+        **kwargs,
+    ):
         """Dialog for export of training areas to vector layer
         """Dialog for export of training areas to vector layer
 
 
         :param parent: window
         :param parent: window
@@ -773,26 +784,32 @@ class IClassExportAreasDialog(wx.Dialog):
             StaticText(
             StaticText(
                 parent=self.panel,
                 parent=self.panel,
                 id=wx.ID_ANY,
                 id=wx.ID_ANY,
-                label=_("Enter name of new vector map:")),
+                label=_("Enter name of new vector map:"),
+            ),
             proportion=0,
             proportion=0,
             flag=wx.ALL,
             flag=wx.ALL,
-            border=3)
+            border=3,
+        )
         self.vectorNameCtrl = gselect.Select(
         self.vectorNameCtrl = gselect.Select(
-            parent=self.panel, type='vector',
-            mapsets=[grass.gisenv()['MAPSET']],
-            size=globalvar.DIALOG_GSELECT_SIZE)
+            parent=self.panel,
+            type="vector",
+            mapsets=[grass.gisenv()["MAPSET"]],
+            size=globalvar.DIALOG_GSELECT_SIZE,
+        )
         if self.vectorName:
         if self.vectorName:
             self.vectorNameCtrl.SetValue(self.vectorName)
             self.vectorNameCtrl.SetValue(self.vectorName)
-        dataSizer.Add(self.vectorNameCtrl,
-                      proportion=0, flag=wx.ALL | wx.EXPAND, border=3)
-        self.withTableCtrl = CheckBox(parent=self.panel, id=wx.ID_ANY,
-                                         label=_("Export attribute table"))
+        dataSizer.Add(
+            self.vectorNameCtrl, proportion=0, flag=wx.ALL | wx.EXPAND, border=3
+        )
+        self.withTableCtrl = CheckBox(
+            parent=self.panel, id=wx.ID_ANY, label=_("Export attribute table")
+        )
         self.withTableCtrl.SetValue(True)
         self.withTableCtrl.SetValue(True)
         self.withTableCtrl.SetToolTip(
         self.withTableCtrl.SetToolTip(
-            _("Export attribute table containing" " computed statistical data"))
+            _("Export attribute table containing" " computed statistical data")
+        )
 
 
-        dataSizer.Add(self.withTableCtrl,
-                      proportion=0, flag=wx.ALL, border=3)
+        dataSizer.Add(self.withTableCtrl, proportion=0, flag=wx.ALL, border=3)
 
 
         # buttons
         # buttons
         btnSizer = wx.StdDialogButtonSizer()
         btnSizer = wx.StdDialogButtonSizer()
@@ -800,11 +817,9 @@ class IClassExportAreasDialog(wx.Dialog):
         btnSizer.AddButton(self.btnOK)
         btnSizer.AddButton(self.btnOK)
         btnSizer.Realize()
         btnSizer.Realize()
 
 
-        sizer.Add(dataSizer, proportion=1,
-                  flag=wx.EXPAND | wx.ALL, border=5)
+        sizer.Add(dataSizer, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
 
 
-        sizer.Add(btnSizer, proportion=0,
-                  flag=wx.EXPAND | wx.ALL, border=5)
+        sizer.Add(btnSizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
 
 
         self.panel.SetSizer(sizer)
         self.panel.SetSizer(sizer)
         sizer.Fit(self)
         sizer.Fit(self)
@@ -821,18 +836,19 @@ class IClassExportAreasDialog(wx.Dialog):
 
 
     def OnOK(self, event):
     def OnOK(self, event):
         """Checks if map exists and can be overwritten."""
         """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")
         vName = self.GetVectorName()
         vName = self.GetVectorName()
-        res = grass.find_file(vName, element='vector')
-        if res['fullname'] and overwrite is False:
+        res = grass.find_file(vName, element="vector")
+        if res["fullname"] and overwrite is False:
             qdlg = wx.MessageDialog(
             qdlg = wx.MessageDialog(
-                parent=self, message=_(
+                parent=self,
+                message=_(
                     "Vector map <%s> already exists."
                     "Vector map <%s> already exists."
-                    " Do you want to overwrite it?" %
-                    vName), caption=_(
-                    "Vector <%s> exists" %
-                    vName), style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION | wx.CENTRE)
+                    " Do you want to overwrite it?" % vName
+                ),
+                caption=_("Vector <%s> exists" % vName),
+                style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION | wx.CENTRE,
+            )
             if qdlg.ShowModal() == wx.ID_YES:
             if qdlg.ShowModal() == wx.ID_YES:
                 event.Skip()
                 event.Skip()
             qdlg.Destroy()
             qdlg.Destroy()

+ 21 - 20
gui/wxpython/iclass/digit.py

@@ -22,6 +22,7 @@ from vdigit.mapwindow import VDigitWindow
 from vdigit.wxdigit import IVDigit
 from vdigit.wxdigit import IVDigit
 from vdigit.wxdisplay import DisplayDriver, TYPE_AREA
 from vdigit.wxdisplay import DisplayDriver, TYPE_AREA
 from core.gcmd import GWarning
 from core.gcmd import GWarning
+
 try:
 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.vector import *
@@ -43,8 +44,9 @@ class IClassVDigitWindow(VDigitWindow):
         :param parent: gui parent
         :param parent: gui parent
         :param map: map renderer instance
         :param map: map renderer instance
         """
         """
-        VDigitWindow.__init__(self, parent=parent, giface=giface,
-                              Map=map, properties=properties)
+        VDigitWindow.__init__(
+            self, parent=parent, giface=giface, Map=map, properties=properties
+        )
 
 
     def _onLeftDown(self, event):
     def _onLeftDown(self, event):
         action = self.toolbar.GetAction()
         action = self.toolbar.GetAction()
@@ -53,13 +55,17 @@ class IClassVDigitWindow(VDigitWindow):
 
 
         region = grass.region()
         region = grass.region()
         e, n = self.Pixel2Cell(event.GetPosition())
         e, n = self.Pixel2Cell(event.GetPosition())
-        if not((region['s'] <= n <= region['n'])
-               and(region['w'] <= e <= region['e'])):
+        if not (
+            (region["s"] <= n <= region["n"]) and (region["w"] <= e <= region["e"])
+        ):
             GWarning(
             GWarning(
-                parent=self.parent, message=_(
+                parent=self.parent,
+                message=_(
                     "You are trying to create a training area "
                     "You are trying to create a training area "
                     "outside the computational region. "
                     "outside the computational region. "
-                    "Please, use g.region to set the appropriate region first."))
+                    "Please, use g.region to set the appropriate region first."
+                ),
+            )
             return
             return
 
 
         cat = self.GetCurrentCategory()
         cat = self.GetCurrentCategory()
@@ -71,9 +77,11 @@ class IClassVDigitWindow(VDigitWindow):
                     "In order to create a training area, "
                     "In order to create a training area, "
                     "you have to select class first.\n\n"
                     "you have to select class first.\n\n"
                     "There is no class yet, "
                     "There is no class yet, "
-                    "do you want to create one?"),
+                    "do you want to create one?"
+                ),
                 caption=_("No class selected"),
                 caption=_("No class selected"),
-                style=wx.YES_NO)
+                style=wx.YES_NO,
+            )
             if dlg.ShowModal() == wx.ID_YES:
             if dlg.ShowModal() == wx.ID_YES:
                 self.parent.OnCategoryManager(None)
                 self.parent.OnCategoryManager(None)
 
 
@@ -103,7 +111,7 @@ class IClassVDigitWindow(VDigitWindow):
 
 
     def GetCategoryColor(self, cat):
     def GetCategoryColor(self, cat):
         """Get color associated with given category"""
         """Get color associated with given category"""
-        r, g, b = [int(x) for x in self.parent.GetClassColor(cat).split(':')][:3]
+        r, g, b = [int(x) for x in self.parent.GetClassColor(cat).split(":")][:3]
         return wx.Colour(r, g, b)
         return wx.Colour(r, g, b)
 
 
 
 
@@ -112,7 +120,7 @@ class IClassVDigit(IVDigit):
 
 
     def __init__(self, mapwindow):
     def __init__(self, mapwindow):
         IVDigit.__init__(self, mapwindow, driver=IClassDisplayDriver)
         IVDigit.__init__(self, mapwindow, driver=IClassDisplayDriver)
-        self._settings['closeBoundary'] = True  # snap to the first node
+        self._settings["closeBoundary"] = True  # snap to the first node
 
 
     def _getNewFeaturesLayer(self):
     def _getNewFeaturesLayer(self):
         return 1
         return 1
@@ -160,7 +168,7 @@ class IClassVDigit(IVDigit):
                 open_fn = Vect_open_tmp_new
                 open_fn = Vect_open_tmp_new
 
 
         if update:
         if update:
-            if open_fn(poMapInfoNew, name, '') == -1:
+            if open_fn(poMapInfoNew, name, "") == -1:
                 return -1
                 return -1
         else:
         else:
             is3D = bool(Vect_is_3d(self.poMapInfo))
             is3D = bool(Vect_is_3d(self.poMapInfo))
@@ -168,7 +176,7 @@ class IClassVDigit(IVDigit):
                 return -1
                 return -1
 
 
         verbose = G_verbose()
         verbose = G_verbose()
-        G_set_verbose(-1)      # be silent
+        G_set_verbose(-1)  # be silent
 
 
         if Vect_copy_map_lines(self.poMapInfo, poMapInfoNew) == 1:
         if Vect_copy_map_lines(self.poMapInfo, poMapInfoNew) == 1:
             G_set_verbose(verbose)
             G_set_verbose(verbose)
@@ -195,14 +203,7 @@ class IClassDisplayDriver(DisplayDriver):
     """
     """
 
 
     def __init__(self, device, deviceTmp, mapObj, window, 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
         self._cat = -1
 
 
     def _drawObject(self, robj):
     def _drawObject(self, robj):

Plik diff jest za duży
+ 485 - 360
gui/wxpython/iclass/frame.py


+ 28 - 29
gui/wxpython/iclass/g.gui.iclass.py

@@ -60,6 +60,7 @@ def main():
     import wx
     import wx
 
 
     from grass.script.setup import set_gui_path
     from grass.script.setup import set_gui_path
+
     set_gui_path()
     set_gui_path()
 
 
     from core.settings import UserSettings
     from core.settings import UserSettings
@@ -68,40 +69,37 @@ def main():
 
 
     group_name = subgroup_name = map_name = trainingmap_name = None
     group_name = subgroup_name = map_name = trainingmap_name = None
 
 
-    if options['group']:
-        if not options['subgroup']:
+    if options["group"]:
+        if not options["subgroup"]:
             gscript.fatal(_("Name of subgroup required"))
             gscript.fatal(_("Name of subgroup required"))
-        group_name = gscript.find_file(name=options['group'],
-                                       element='group')['name']
+        group_name = gscript.find_file(name=options["group"], element="group")["name"]
         if not group_name:
         if not group_name:
-            gscript.fatal(_("Group <%s> not found") % options['group'])
-        subgroups = gscript.read_command('i.group',
-                                         group=group_name,
-                                         flags='sg').splitlines()
-        if options['subgroup'] not in subgroups:
-            gscript.fatal(_("Subgroup <%s> not found") % options['subgroup'])
-        subgroup_name = options['subgroup']
-
-    if options['map']:
-        map_name = gscript.find_file(name=options['map'],
-                                     element='cell')['fullname']
+            gscript.fatal(_("Group <%s> not found") % options["group"])
+        subgroups = gscript.read_command(
+            "i.group", group=group_name, flags="sg"
+        ).splitlines()
+        if options["subgroup"] not in subgroups:
+            gscript.fatal(_("Subgroup <%s> not found") % options["subgroup"])
+        subgroup_name = options["subgroup"]
+
+    if options["map"]:
+        map_name = gscript.find_file(name=options["map"], element="cell")["fullname"]
         if not map_name:
         if not map_name:
-            gscript.fatal(_("Raster map <%s> not found") % options['map'])
+            gscript.fatal(_("Raster map <%s> not found") % options["map"])
 
 
-    if options['trainingmap']:
-        trainingmap_name = gscript.find_file(name=options['trainingmap'],
-                                             element='vector')['fullname']
+    if options["trainingmap"]:
+        trainingmap_name = gscript.find_file(
+            name=options["trainingmap"], element="vector"
+        )["fullname"]
         if not trainingmap_name:
         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
     # define display driver
-    driver = UserSettings.Get(group='display', key='driver', subkey='type')
-    if driver == 'png':
-        os.environ['GRASS_RENDER_IMMEDIATE'] = 'png'
+    driver = UserSettings.Get(group="display", key="driver", subkey="type")
+    if driver == "png":
+        os.environ["GRASS_RENDER_IMMEDIATE"] = "png"
     else:
     else:
-        os.environ['GRASS_RENDER_IMMEDIATE'] = 'cairo'
+        os.environ["GRASS_RENDER_IMMEDIATE"] = "cairo"
 
 
     # launch application
     # launch application
     app = wx.App()
     app = wx.App()
@@ -113,7 +111,7 @@ def main():
         giface=giface,
         giface=giface,
         title=_("Supervised Classification Tool - GRASS GIS"),
         title=_("Supervised Classification Tool - GRASS GIS"),
     )
     )
-    if not flags['m']:
+    if not flags["m"]:
         frame.CenterOnScreen()
         frame.CenterOnScreen()
     if group_name:
     if group_name:
         frame.SetGroup(group_name, subgroup_name)
         frame.SetGroup(group_name, subgroup_name)
@@ -125,9 +123,10 @@ def main():
         frame.ImportAreas(trainingmap_name)
         frame.ImportAreas(trainingmap_name)
 
 
     frame.Show()
     frame.Show()
-    if flags['m']:
+    if flags["m"]:
         frame.Maximize()
         frame.Maximize()
     app.MainLoop()
     app.MainLoop()
 
 
-if __name__ == '__main__':
+
+if __name__ == "__main__":
     main()
     main()

+ 36 - 52
gui/wxpython/iclass/plots.py

@@ -59,50 +59,41 @@ class PlotPanel(scrolled.ScrolledPanel):
     def _createPlotPanel(self):
     def _createPlotPanel(self):
 
 
         self.canvasPanel = wx.Panel(parent=self)
         self.canvasPanel = wx.Panel(parent=self)
-        self.mainSizer.Add(
-            self.canvasPanel,
-            proportion=1,
-            flag=wx.EXPAND,
-            border=0)
+        self.mainSizer.Add(self.canvasPanel, proportion=1, flag=wx.EXPAND, border=0)
         self.canvasSizer = wx.BoxSizer(wx.VERTICAL)
         self.canvasSizer = wx.BoxSizer(wx.VERTICAL)
         self.canvasPanel.SetSizer(self.canvasSizer)
         self.canvasPanel.SetSizer(self.canvasSizer)
 
 
     def _createControlPanel(self):
     def _createControlPanel(self):
-        self.plotSwitch = wx.Choice(self, id=wx.ID_ANY,
-                                    choices=[_("Histograms"),
-                                             _("Coincident plots"),
-                                             _("Scatter plots")])
+        self.plotSwitch = wx.Choice(
+            self,
+            id=wx.ID_ANY,
+            choices=[_("Histograms"), _("Coincident plots"), _("Scatter plots")],
+        )
         self.mainSizer.Add(
         self.mainSizer.Add(
-            self.plotSwitch,
-            proportion=0,
-            flag=wx.EXPAND | wx.ALL,
-            border=5)
+            self.plotSwitch, proportion=0, flag=wx.EXPAND | wx.ALL, border=5
+        )
         self.plotSwitch.Bind(wx.EVT_CHOICE, self.OnPlotTypeSelected)
         self.plotSwitch.Bind(wx.EVT_CHOICE, self.OnPlotTypeSelected)
 
 
     def _createScatterPlotPanel(self):
     def _createScatterPlotPanel(self):
-        """Init interactive scatter plot tool
-        """
+        """Init interactive scatter plot tool"""
         try:
         try:
             from iscatt.frame import IClassIScattPanel
             from iscatt.frame import IClassIScattPanel
+
             self.iscatt_panel = IClassIScattPanel(
             self.iscatt_panel = IClassIScattPanel(
-                parent=self, giface=self._giface,
-                iclass_mapwin=self.parent.GetFirstWindow())
+                parent=self,
+                giface=self._giface,
+                iclass_mapwin=self.parent.GetFirstWindow(),
+            )
             self.mainSizer.Add(
             self.mainSizer.Add(
-                self.iscatt_panel,
-                proportion=1,
-                flag=wx.EXPAND,
-                border=0)
+                self.iscatt_panel, proportion=1, flag=wx.EXPAND, border=0
+            )
             self.iscatt_panel.Hide()
             self.iscatt_panel.Hide()
         except ImportError as e:
         except ImportError as e:
             self.scatt_error = _(
             self.scatt_error = _(
                 "Scatter plot functionality is disabled.\n\nReason: "
                 "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)
+                "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
             self.iscatt_panel = None
 
 
     def OnPlotTypeSelected(self, event):
     def OnPlotTypeSelected(self, event):
@@ -148,7 +139,7 @@ class PlotPanel(scrolled.ScrolledPanel):
         for canvas in self.canvasList:
         for canvas in self.canvasList:
             canvas.enableZoom = enable
             canvas.enableZoom = enable
 
 
-        #canvas.zoom = type
+        # canvas.zoom = type
 
 
     def EnablePan(self, enable=True):
     def EnablePan(self, enable=True):
         for canvas in self.canvasList:
         for canvas in self.canvasList:
@@ -181,11 +172,7 @@ class PlotPanel(scrolled.ScrolledPanel):
             canvas.fontSizeAxis = 8
             canvas.fontSizeAxis = 8
             self.canvasList.append(canvas)
             self.canvasList.append(canvas)
 
 
-            self.canvasSizer.Add(
-                canvas,
-                proportion=1,
-                flag=wx.EXPAND,
-                border=0)
+            self.canvasSizer.Add(canvas, proportion=1, flag=wx.EXPAND, border=0)
 
 
         self.SetVirtualSize(self.GetBestVirtualSize())
         self.SetVirtualSize(self.GetBestVirtualSize())
         self.Layout()
         self.Layout()
@@ -218,7 +205,7 @@ class PlotPanel(scrolled.ScrolledPanel):
     def DrawCoincidencePlots(self):
     def DrawCoincidencePlots(self):
         """Draw coincidence plots"""
         """Draw coincidence plots"""
         for bandIdx in range(len(self.bandList)):
         for bandIdx in range(len(self.bandList)):
-            self.canvasList[bandIdx].ySpec = 'none'
+            self.canvasList[bandIdx].ySpec = "none"
             lines = []
             lines = []
             level = 0.5
             level = 0.5
             lines.append(self.DrawInvisibleLine(level))
             lines.append(self.DrawInvisibleLine(level))
@@ -230,8 +217,7 @@ class PlotPanel(scrolled.ScrolledPanel):
                     continue
                     continue
                 color = stat.color
                 color = stat.color
                 level = i + 1
                 level = i + 1
-                line = self.DrawCoincidenceLine(
-                    level, color, stat.bands[bandIdx])
+                line = self.DrawCoincidenceLine(level, color, stat.bands[bandIdx])
                 lines.append(line)
                 lines.append(line)
 
 
             # invisible
             # invisible
@@ -251,7 +237,7 @@ class PlotPanel(scrolled.ScrolledPanel):
         minim = bandValues.min
         minim = bandValues.min
         maxim = bandValues.max
         maxim = bandValues.max
         points = [(minim, level), (maxim, level)]
         points = [(minim, level), (maxim, level)]
-        color = wx.Colour(*map(int, color.split(':')))
+        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):
     def DrawInvisibleLine(self, level):
@@ -267,9 +253,10 @@ class PlotPanel(scrolled.ScrolledPanel):
         self.histogramLines = []
         self.histogramLines = []
         for bandIdx in range(len(self.bandList)):
         for bandIdx in range(len(self.bandList)):
             self.canvasList[bandIdx].Clear()
             self.canvasList[bandIdx].Clear()
-            self.canvasList[bandIdx].ySpec = 'auto'
+            self.canvasList[bandIdx].ySpec = "auto"
             histgramLine = self.CreateHistogramLine(
             histgramLine = self.CreateHistogramLine(
-                bandValues=statistics.bands[bandIdx])
+                bandValues=statistics.bands[bandIdx]
+            )
 
 
             meanLine = self.CreateMean(bandValues=statistics.bands[bandIdx])
             meanLine = self.CreateMean(bandValues=statistics.bands[bandIdx])
 
 
@@ -277,17 +264,15 @@ class PlotPanel(scrolled.ScrolledPanel):
 
 
             maxLine = self.CreateMax(bandValues=statistics.bands[bandIdx])
             maxLine = self.CreateMax(bandValues=statistics.bands[bandIdx])
 
 
-            self.histogramLines.append(
-                [histgramLine, meanLine, minLine, maxLine])
+            self.histogramLines.append([histgramLine, meanLine, minLine, maxLine])
 
 
-            maxRangeLine = self.CreateMaxRange(
-                bandValues=statistics.bands[bandIdx])
-            minRangeLine = self.CreateMinRange(
-                bandValues=statistics.bands[bandIdx])
+            maxRangeLine = self.CreateMaxRange(bandValues=statistics.bands[bandIdx])
+            minRangeLine = self.CreateMinRange(bandValues=statistics.bands[bandIdx])
 
 
             plotGraph = plot.PlotGraphics(
             plotGraph = plot.PlotGraphics(
                 self.histogramLines[bandIdx] + [minRangeLine, maxRangeLine],
                 self.histogramLines[bandIdx] + [minRangeLine, maxRangeLine],
-                title=self.bandList[bandIdx])
+                title=self.bandList[bandIdx],
+            )
             self.canvasList[bandIdx].Draw(plotGraph)
             self.canvasList[bandIdx].Draw(plotGraph)
 
 
     def CreateMinRange(self, bandValues):
     def CreateMinRange(self, bandValues):
@@ -344,12 +329,11 @@ class PlotPanel(scrolled.ScrolledPanel):
         """
         """
         for bandIdx in range(len(self.bandList)):
         for bandIdx in range(len(self.bandList)):
             self.canvasList[bandIdx].Clear()
             self.canvasList[bandIdx].Clear()
-            maxRangeLine = self.CreateMaxRange(
-                bandValues=statistics.bands[bandIdx])
-            minRangeLine = self.CreateMinRange(
-                bandValues=statistics.bands[bandIdx])
+            maxRangeLine = self.CreateMaxRange(bandValues=statistics.bands[bandIdx])
+            minRangeLine = self.CreateMinRange(bandValues=statistics.bands[bandIdx])
 
 
             plotGraph = plot.PlotGraphics(
             plotGraph = plot.PlotGraphics(
                 self.histogramLines[bandIdx] + [minRangeLine, maxRangeLine],
                 self.histogramLines[bandIdx] + [minRangeLine, maxRangeLine],
-                title=self.bandList[bandIdx])
+                title=self.bandList[bandIdx],
+            )
             self.canvasList[bandIdx].Draw(plotGraph)
             self.canvasList[bandIdx].Draw(plotGraph)

+ 6 - 8
gui/wxpython/iclass/statistics.py

@@ -32,8 +32,7 @@ from grass.pydispatch.signal import Signal
 
 
 
 
 class StatisticsData:
 class StatisticsData:
-    """Stores all statistics.
-    """
+    """Stores all statistics."""
 
 
     def __init__(self):
     def __init__(self):
         self.statisticsDict = {}
         self.statisticsDict = {}
@@ -41,8 +40,7 @@ class StatisticsData:
 
 
         self.statisticsAdded = Signal("StatisticsData.statisticsAdded")
         self.statisticsAdded = Signal("StatisticsData.statisticsAdded")
         self.statisticsDeleted = Signal("StatisticsData.statisticsDeleted")
         self.statisticsDeleted = Signal("StatisticsData.statisticsDeleted")
-        self.allStatisticsDeleted = Signal(
-            "StatisticsData.allStatisticsDeleted")
+        self.allStatisticsDeleted = Signal("StatisticsData.allStatisticsDeleted")
 
 
         self.statisticsSet = Signal("StatisticsData.statisticsSet")
         self.statisticsSet = Signal("StatisticsData.statisticsSet")
 
 
@@ -53,8 +51,8 @@ class StatisticsData:
         st = Statistics()
         st = Statistics()
         st.SetBaseStatistics(cat=cat, name=name, color=color)
         st.SetBaseStatistics(cat=cat, name=name, color=color)
         st.statisticsSet.connect(
         st.statisticsSet.connect(
-            lambda stats: self.statisticsSet.emit(
-                cat=cat, stats=stats))
+            lambda stats: self.statisticsSet.emit(cat=cat, stats=stats)
+        )
 
 
         self.statisticsDict[cat] = st
         self.statisticsDict[cat] = st
         self.statisticsList.append(cat)
         self.statisticsList.append(cat)
@@ -118,8 +116,8 @@ class Statistics:
         self.color = color
         self.color = color
 
 
         rasterPath = grass.tempfile(create=False)
         rasterPath = grass.tempfile(create=False)
-        name = name.replace(' ', '_')
-        self.rasterName = name + '_' + os.path.basename(rasterPath)
+        name = name.replace(" ", "_")
+        self.rasterName = name + "_" + os.path.basename(rasterPath)
 
 
     def SetFromcStatistics(self, cStatistics):
     def SetFromcStatistics(self, cStatistics):
         """Sets all statistical values.
         """Sets all statistical values.

+ 98 - 127
gui/wxpython/iclass/toolbars.py

@@ -31,62 +31,53 @@ from gui_core.wrap import StaticText
 import grass.script as grass
 import grass.script as grass
 
 
 iClassIcons = {
 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):
 class IClassMapToolbar(BaseToolbar):
-    """IClass Map toolbar
-    """
+    """IClass Map toolbar"""
 
 
     def __init__(self, parent, toolSwitcher):
     def __init__(self, parent, toolSwitcher):
-        """IClass Map toolbar constructor
-        """
+        """IClass Map toolbar constructor"""
         BaseToolbar.__init__(self, parent, toolSwitcher)
         BaseToolbar.__init__(self, parent, toolSwitcher)
 
 
         self.InitToolbar(self._toolbarData())
         self.InitToolbar(self._toolbarData())
         self._default = self.pan
         self._default = self.pan
 
 
         # add tool to toggle active map window
         # add tool to toggle active map window
-        self.togglemap = wx.Choice(parent=self, id=wx.ID_ANY,
-                                   choices=[_('Training'), _('Preview')])
+        self.togglemap = wx.Choice(
+            parent=self, id=wx.ID_ANY, choices=[_("Training"), _("Preview")]
+        )
 
 
         self.InsertControl(9, self.togglemap)
         self.InsertControl(9, self.togglemap)
 
 
         self.SetToolShortHelp(
         self.SetToolShortHelp(
-            self.togglemap.GetId(), '%s %s %s' %
-            (_('Set map canvas for '),
-             BaseIcons["zoomBack"].GetLabel(),
-             _('/ Zoom to map')))
+            self.togglemap.GetId(),
+            "%s %s %s"
+            % (
+                _("Set map canvas for "),
+                BaseIcons["zoomBack"].GetLabel(),
+                _("/ Zoom to map"),
+            ),
+        )
 
 
         for tool in (self.pan, self.zoomIn, self.zoomOut):
         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
         # realize the toolbar
         self.Realize()
         self.Realize()
 
 
@@ -107,41 +98,29 @@ class IClassMapToolbar(BaseToolbar):
     def _toolbarData(self):
     def _toolbarData(self):
         """Toolbar data"""
         """Toolbar data"""
         icons = BaseIcons
         icons = BaseIcons
-        return self._getToolbarData((("displaymap", icons["display"],
-                                      self.parent.OnDraw),
-                                     ("rendermap", icons["render"],
-                                      self.parent.OnRender),
-                                     ("erase", icons["erase"],
-                                      self.parent.OnErase),
-                                     (None, ),
-                                     ("pan", icons["pan"],
-                                      self.parent.OnPan,
-                                      wx.ITEM_CHECK),
-                                     ("zoomIn", icons["zoomIn"],
-                                      self.parent.OnZoomIn,
-                                      wx.ITEM_CHECK),
-                                     ("zoomOut", icons["zoomOut"],
-                                      self.parent.OnZoomOut,
-                                      wx.ITEM_CHECK),
-                                     ("zoomRegion", icons["zoomRegion"],
-                                      self.parent.OnZoomToWind),
-                                     ("zoomMenu", icons["zoomMenu"],
-                                      self.parent.OnZoomMenu),
-                                     (None, ),
-                                     ("zoomBack", icons["zoomBack"],
-                                      self.parent.OnZoomBack),
-                                     ("zoomToMap", icons["zoomExtent"],
-                                      self.parent.OnZoomToMap)
-                                     ))
+        return self._getToolbarData(
+            (
+                ("displaymap", icons["display"], self.parent.OnDraw),
+                ("rendermap", icons["render"], self.parent.OnRender),
+                ("erase", icons["erase"], self.parent.OnErase),
+                (None,),
+                ("pan", icons["pan"], self.parent.OnPan, wx.ITEM_CHECK),
+                ("zoomIn", icons["zoomIn"], self.parent.OnZoomIn, wx.ITEM_CHECK),
+                ("zoomOut", icons["zoomOut"], self.parent.OnZoomOut, wx.ITEM_CHECK),
+                ("zoomRegion", icons["zoomRegion"], self.parent.OnZoomToWind),
+                ("zoomMenu", icons["zoomMenu"], self.parent.OnZoomMenu),
+                (None,),
+                ("zoomBack", icons["zoomBack"], self.parent.OnZoomBack),
+                ("zoomToMap", icons["zoomExtent"], self.parent.OnZoomToMap),
+            )
+        )
 
 
 
 
 class IClassToolbar(BaseToolbar):
 class IClassToolbar(BaseToolbar):
-    """IClass toolbar
-    """
+    """IClass toolbar"""
 
 
     def __init__(self, parent, stats_data):
     def __init__(self, parent, stats_data):
-        """IClass toolbar constructor
-        """
+        """IClass toolbar constructor"""
         self.stats_data = stats_data
         self.stats_data = stats_data
 
 
         BaseToolbar.__init__(self, parent)
         BaseToolbar.__init__(self, parent)
@@ -153,10 +132,11 @@ class IClassToolbar(BaseToolbar):
         self.choice.Bind(wx.EVT_CHOICE, self.OnSelectCategory)
         self.choice.Bind(wx.EVT_CHOICE, self.OnSelectCategory)
 
 
         # stupid workaround to insert small space between controls
         # stupid workaround to insert small space between controls
-        self.InsertControl(4, StaticText(self, id=wx.ID_ANY, label=' '))
+        self.InsertControl(4, 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.combo = wx.ComboBox(
+            self, id=wx.ID_ANY, size=(130, -1), style=wx.TE_PROCESS_ENTER
+        )
         self.InitStddev()
         self.InitStddev()
         self.InsertControl(5, self.combo)
         self.InsertControl(5, self.combo)
 
 
@@ -176,22 +156,23 @@ class IClassToolbar(BaseToolbar):
     def _toolbarData(self):
     def _toolbarData(self):
         """Toolbar data"""
         """Toolbar data"""
         icons = iClassIcons
         icons = iClassIcons
-        return self._getToolbarData((("selectGroup", icons['selectGroup'],
-                                      lambda event: self.parent.AddBands()),
-                                     (None, ),
-                                     ("classManager", icons['classManager'],
-                                      self.parent.OnCategoryManager),
-                                     (None, ),
-                                     ("runAnalysis", icons['run'],
-                                      self.parent.OnRunAnalysis),
-                                     (None, ),
-                                     ("importAreas", icons['importAreas'],
-                                      self.parent.OnImportAreas),
-                                     ("exportAreas", icons['exportAreas'],
-                                      self.parent.OnExportAreas),
-                                     ("sigFile", icons['sigFile'],
-                                      self.parent.OnSaveSigFile),
-                                     ))
+        return self._getToolbarData(
+            (
+                (
+                    "selectGroup",
+                    icons["selectGroup"],
+                    lambda event: self.parent.AddBands(),
+                ),
+                (None,),
+                ("classManager", icons["classManager"], self.parent.OnCategoryManager),
+                (None,),
+                ("runAnalysis", icons["run"], self.parent.OnRunAnalysis),
+                (None,),
+                ("importAreas", icons["importAreas"], self.parent.OnImportAreas),
+                ("exportAreas", icons["exportAreas"], self.parent.OnExportAreas),
+                ("sigFile", icons["sigFile"], self.parent.OnSaveSigFile),
+            )
+        )
 
 
     def OnMotion(self, event):
     def OnMotion(self, event):
         print(self.choice.GetStringSelection())
         print(self.choice.GetStringSelection())
@@ -207,7 +188,7 @@ class IClassToolbar(BaseToolbar):
 
 
         if cat:
         if cat:
             stat = self.stats_data.GetStatistics(cat)
             stat = self.stats_data.GetStatistics(cat)
-            back_c = wx.Colour([int(x) for x in stat.color.split(':')])
+            back_c = wx.Colour([int(x) for x in stat.color.split(":")])
             text_c = wx.Colour(*ContrastColor(back_c))
             text_c = wx.Colour(*ContrastColor(back_c))
         else:
         else:
             back_c = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND)
             back_c = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND)
@@ -258,17 +239,14 @@ class IClassToolbar(BaseToolbar):
         self.parent.StddevChanged(cat=idx, nstd=nstd)
         self.parent.StddevChanged(cat=idx, nstd=nstd)
 
 
     def UpdateStddev(self, nstd):
     def UpdateStddev(self, nstd):
-        self.combo.SetValue(' '.join(("%.2f" % nstd, _('std dev'))))
+        self.combo.SetValue(" ".join(("%.2f" % nstd, _("std dev"))))
 
 
     def InitStddev(self):
     def InitStddev(self):
         for nstd in range(50, 250, 25):
         for nstd in range(50, 250, 25):
-            nstd /= 100.
+            nstd /= 100.0
             self.combo.Append(
             self.combo.Append(
-                item=' '.join(
-                    ("%.2f" %
-                     nstd,
-                     _('std dev'))),
-                clientData=nstd)
+                item=" ".join(("%.2f" % nstd, _("std dev"))), clientData=nstd
+            )
         self.combo.SetSelection(4)  # 1.5
         self.combo.SetSelection(4)  # 1.5
 
 
     def EnableControls(self, enable=True):
     def EnableControls(self, enable=True):
@@ -304,12 +282,10 @@ class IClassToolbar(BaseToolbar):
 
 
 
 
 class IClassMapManagerToolbar(BaseToolbar):
 class IClassMapManagerToolbar(BaseToolbar):
-    """IClass toolbar
-    """
+    """IClass toolbar"""
 
 
     def __init__(self, parent, mapManager):
     def __init__(self, parent, mapManager):
-        """IClass toolbar constructor
-        """
+        """IClass toolbar constructor"""
         BaseToolbar.__init__(self, parent)
         BaseToolbar.__init__(self, parent)
 
 
         self.InitToolbar(self._toolbarData())
         self.InitToolbar(self._toolbarData())
@@ -325,35 +301,31 @@ class IClassMapManagerToolbar(BaseToolbar):
 
 
     def _toolbarData(self):
     def _toolbarData(self):
         """Toolbar data"""
         """Toolbar data"""
-        return self._getToolbarData((("addRast", BaseIcons['addRast'],
-                                      self.OnAddRast),
-                                     ('addRgb', iClassIcons['addRgb'],
-                                      self.OnAddRGB),
-                                     ("delRast", iClassIcons['delCmd'],
-                                      self.OnDelRast),
-                                     ("setOpacity", iClassIcons['opacity'],
-                                      self.OnSetOpacity),
-                                     ))
+        return self._getToolbarData(
+            (
+                ("addRast", BaseIcons["addRast"], self.OnAddRast),
+                ("addRgb", iClassIcons["addRgb"], self.OnAddRGB),
+                ("delRast", iClassIcons["delCmd"], self.OnDelRast),
+                ("setOpacity", iClassIcons["opacity"], self.OnSetOpacity),
+            )
+        )
 
 
     def OnSelectLayer(self, event):
     def OnSelectLayer(self, event):
         layer = self.choice.GetStringSelection()
         layer = self.choice.GetStringSelection()
         self.mapManager.SelectLayer(name=layer)
         self.mapManager.SelectLayer(name=layer)
 
 
     def OnAddRast(self, event):
     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:
         if dlg.ShowModal() == wx.ID_OK:
-            raster = grass.find_file(name=dlg.GetMap(), element='cell')
-            if raster['fullname']:
-                self.mapManager.AddLayer(name=raster['fullname'])
+            raster = grass.find_file(name=dlg.GetMap(), element="cell")
+            if raster["fullname"]:
+                self.mapManager.AddLayer(name=raster["fullname"])
 
 
         dlg.Destroy()
         dlg.Destroy()
 
 
     def OnAddRGB(self, event):
     def OnAddRGB(self, event):
-        cmd = ['d.rgb']
-        GUI(parent=self.parent).ParseCommand(
-            cmd, completed=(self.GetOptData, '', ''))
+        cmd = ["d.rgb"]
+        GUI(parent=self.parent).ParseCommand(cmd, completed=(self.GetOptData, "", ""))
 
 
     def GetOptData(self, dcmd, layer, params, propwin):
     def GetOptData(self, dcmd, layer, params, propwin):
         if dcmd:
         if dcmd:
@@ -375,12 +347,10 @@ class IClassMapManagerToolbar(BaseToolbar):
 
 
 
 
 class IClassMiscToolbar(BaseToolbar):
 class IClassMiscToolbar(BaseToolbar):
-    """IClass toolbar
-    """
+    """IClass toolbar"""
 
 
     def __init__(self, parent):
     def __init__(self, parent):
-        """IClass toolbar constructor
-        """
+        """IClass toolbar constructor"""
         BaseToolbar.__init__(self, parent)
         BaseToolbar.__init__(self, parent)
 
 
         self.InitToolbar(self._toolbarData())
         self.InitToolbar(self._toolbarData())
@@ -390,8 +360,9 @@ class IClassMiscToolbar(BaseToolbar):
     def _toolbarData(self):
     def _toolbarData(self):
         """Toolbar data"""
         """Toolbar data"""
         icons = BaseIcons
         icons = BaseIcons
-        return self._getToolbarData((("help", icons['help'],
-                                      self.parent.OnHelp),
-                                     ("quit", icons['quit'],
-                                      self.parent.OnCloseWindow),
-                                     ))
+        return self._getToolbarData(
+            (
+                ("help", icons["help"], self.parent.OnHelp),
+                ("quit", icons["quit"], self.parent.OnCloseWindow),
+            )
+        )

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

@@ -15,6 +15,6 @@ iconSet = dict()
 
 
 for icon in os.listdir(iconPath):
 for icon in os.listdir(iconPath):
     name, ext = os.path.splitext(icon)
     name, ext = os.path.splitext(icon)
-    if ext != '.png':
+    if ext != ".png":
         continue
         continue
     iconSet[name] = icon
     iconSet[name] = icon

+ 18 - 24
gui/wxpython/icons/icon.py

@@ -27,17 +27,15 @@ from core.settings import UserSettings
 # default icon set
 # default icon set
 from .grass_icons import iconSet as g_iconSet
 from .grass_icons import iconSet as g_iconSet
 from .grass_icons import iconPath as g_iconPath
 from .grass_icons import iconPath as g_iconPath
+
 iconSetDefault = g_iconSet
 iconSetDefault = g_iconSet
 iconPathDefault = g_iconPath
 iconPathDefault = g_iconPath
 
 
-iconTheme = UserSettings.Get(
-    group='appearance',
-    key='iconTheme',
-    subkey='type')
-if iconTheme != 'grass':
+iconTheme = UserSettings.Get(group="appearance", key="iconTheme", subkey="type")
+if iconTheme != "grass":
     sys.stderr.write(
     sys.stderr.write(
-        _("Unknown iconset '%s', using default 'grass'...\n") %
-        (iconTheme))
+        _("Unknown iconset '%s', using default 'grass'...\n") % (iconTheme)
+    )
 
 
 iconSet = iconSetDefault
 iconSet = iconSetDefault
 iconPath = iconPathDefault
 iconPath = iconPathDefault
@@ -48,8 +46,7 @@ try:
         raise OSError
         raise OSError
 
 
     for key, img in six.iteritems(iconSet):
     for key, img in six.iteritems(iconSet):
-        if key not in iconSet or \
-                iconSet[key] is None:  # add key
+        if key not in iconSet or iconSet[key] is None:  # add key
             iconSet[key] = img
             iconSet[key] = img
 
 
         iconSet[key] = os.path.join(iconPath, iconSet[key])
         iconSet[key] = os.path.join(iconPath, iconSet[key])
@@ -58,40 +55,37 @@ except Exception as e:
 
 
 
 
 class MetaIcon:
 class MetaIcon:
-    """Handle icon metadata (image path, tooltip, ...)
-    """
+    """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)
         self.imagepath = iconSet.get(img, wx.ART_MISSING_IMAGE)
         if not self.imagepath:
         if not self.imagepath:
-            self.type = 'unknown'
+            self.type = "unknown"
         else:
         else:
-            if self.imagepath.find('wxART_') > -1:
-                self.type = 'wx'
+            if self.imagepath.find("wxART_") > -1:
+                self.type = "wx"
             else:
             else:
-                self.type = 'img'
+                self.type = "img"
 
 
         self.label = label
         self.label = label
 
 
         if desc:
         if desc:
             self.description = desc
             self.description = desc
         else:
         else:
-            self.description = ''
+            self.description = ""
 
 
     def __str__(self):
     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
         bmp = None
 
 
-        if self.type == 'wx':
+        if self.type == "wx":
             bmp = wx.ArtProvider.GetBitmap(
             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):
+                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 size and len(size) == 2:
                 if size and len(size) == 2:
                     image = wx.Image(name=self.imagepath)
                     image = wx.Image(name=self.imagepath)
                     image.Rescale(size[0], size[1])
                     image.Rescale(size[0], size[1])

+ 3 - 3
gui/wxpython/image2target/__init__.py

@@ -1,5 +1,5 @@
 all = [
 all = [
-    'ii2t_manager',
-    'ii2t_mapdisplay',
-    'ii2t_toolbars',
+    "ii2t_manager",
+    "ii2t_mapdisplay",
+    "ii2t_toolbars",
 ]
 ]

+ 50 - 49
gui/wxpython/image2target/g.gui.image2target.py

@@ -116,67 +116,68 @@ def main():
     import wx
     import wx
 
 
     from grass.script.setup import set_gui_path
     from grass.script.setup import set_gui_path
+
     set_gui_path()
     set_gui_path()
 
 
     from core.settings import UserSettings
     from core.settings import UserSettings
     from core.giface import StandaloneGrassInterface
     from core.giface import StandaloneGrassInterface
     from image2target.ii2t_manager import GCPWizard
     from image2target.ii2t_manager import GCPWizard
 
 
-    driver = UserSettings.Get(group='display', key='driver', subkey='type')
-    if driver == 'png':
-        os.environ['GRASS_RENDER_IMMEDIATE'] = 'png'
+    driver = UserSettings.Get(group="display", key="driver", subkey="type")
+    if driver == "png":
+        os.environ["GRASS_RENDER_IMMEDIATE"] = "png"
     else:
     else:
-        os.environ['GRASS_RENDER_IMMEDIATE'] = 'cairo'
-
-#    if options['source_location']:
-#        src_loc = options['source_location']
-#    else:
-#        gscript.fatal(_("No georeferenced source location provided"))
-
-#    if options['source_mapset']:
-#        src_mpt = options['source_mapset']
-#    else:
-#        gscript.fatal(_("No georeferenced source mapset provided"))
-
-#    if options['source_group']:
-#        src_grp = options['source_group']
-#    else:
-#        gscript.fatal(_("Please provide a source group name to process"))
-
-#    if options['source_image']:
-#        src_ras = options['source_image']
-#    else:
-#        gscript.fatal(_("Please provide a source image map name to process"))
-
-#    if options['target_image']:
-#        tgt_ras = options['target_image']
-#    else:
-#        gscript.fatal(_("No georeferenced target map provided"))
-
-#    if options['camera']:
-#        camera = options['camera']
-#    else:
-#        gscript.fatal(_("Please provide a camera name (generated by i.ortho.camera)"))
-
-#    if options['order']:
-#        order = options['order']
-#    else:
-#        gscript.fatal(_("Please provive an order value"))
-
-#    if options['extension']:
-#        extension = options['extension']
-#    else:
-#        gscript.fatal(_("Please provide an output file extension"))
-
+        os.environ["GRASS_RENDER_IMMEDIATE"] = "cairo"
+
+    #    if options['source_location']:
+    #        src_loc = options['source_location']
+    #    else:
+    #        gscript.fatal(_("No georeferenced source location provided"))
+
+    #    if options['source_mapset']:
+    #        src_mpt = options['source_mapset']
+    #    else:
+    #        gscript.fatal(_("No georeferenced source mapset provided"))
+
+    #    if options['source_group']:
+    #        src_grp = options['source_group']
+    #    else:
+    #        gscript.fatal(_("Please provide a source group name to process"))
+
+    #    if options['source_image']:
+    #        src_ras = options['source_image']
+    #    else:
+    #        gscript.fatal(_("Please provide a source image map name to process"))
+
+    #    if options['target_image']:
+    #        tgt_ras = options['target_image']
+    #    else:
+    #        gscript.fatal(_("No georeferenced target map provided"))
+
+    #    if options['camera']:
+    #        camera = options['camera']
+    #    else:
+    #        gscript.fatal(_("Please provide a camera name (generated by i.ortho.camera)"))
+
+    #    if options['order']:
+    #        order = options['order']
+    #    else:
+    #        gscript.fatal(_("Please provive an order value"))
+
+    #    if options['extension']:
+    #        extension = options['extension']
+    #    else:
+    #        gscript.fatal(_("Please provide an output file extension"))
 
 
     app = wx.App()
     app = wx.App()
 
 
-#    wizard = GCPWizard(parent=None, giface=StandaloneGrassInterface(),
-#            srcloc=src_loc,srcmpt=src_mpt,srcgrp=src_grp,srcras=src_ras,
-#            tgtras=tgt_ras,camera=camera, order=order, extension=extension)
+    #    wizard = GCPWizard(parent=None, giface=StandaloneGrassInterface(),
+    #            srcloc=src_loc,srcmpt=src_mpt,srcgrp=src_grp,srcras=src_ras,
+    #            tgtras=tgt_ras,camera=camera, order=order, extension=extension)
 
 
     wizard = GCPWizard(parent=None, giface=StandaloneGrassInterface())
     wizard = GCPWizard(parent=None, giface=StandaloneGrassInterface())
     app.MainLoop()
     app.MainLoop()
 
 
-if __name__ == '__main__':
+
+if __name__ == "__main__":
     main()
     main()

Plik diff jest za duży
+ 465 - 356
gui/wxpython/image2target/ii2t_gis_set.py


+ 3 - 4
gui/wxpython/image2target/ii2t_gis_set_error.py

@@ -22,15 +22,14 @@ def main():
     if len(sys.argv) == 1:
     if len(sys.argv) == 1:
         msg = "Unknown reason"
         msg = "Unknown reason"
     else:
     else:
-        msg = ''
+        msg = ""
         for m in sys.argv[1:]:
         for m in sys.argv[1:]:
             msg += m
             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()
     app.MainLoop()
 
 
+
 if __name__ == "__main__":
 if __name__ == "__main__":
     main()
     main()

Plik diff jest za duży
+ 1226 - 1069
gui/wxpython/image2target/ii2t_manager.py


+ 196 - 130
gui/wxpython/image2target/ii2t_mapdisplay.py

@@ -44,10 +44,17 @@ class MapFrame(SingleMapFrame):
     child double buffered drawing window.
     child double buffered drawing window.
     """
     """
 
 
-    def __init__(self, parent, giface,
-                 title=_("GRASS GIS Manage Ground Control Points"),
-                 toolbars=["gcpdisp"], Map=None, auimgr=None,
-                 name='GCPMapWindow', **kwargs):
+    def __init__(
+        self,
+        parent,
+        giface,
+        title=_("GRASS GIS Manage Ground Control Points"),
+        toolbars=["gcpdisp"],
+        Map=None,
+        auimgr=None,
+        name="GCPMapWindow",
+        **kwargs,
+    ):
         """Main map display window with toolbars, statusbar and
         """Main map display window with toolbars, statusbar and
         DrawWindow
         DrawWindow
 
 
@@ -67,7 +74,8 @@ class MapFrame(SingleMapFrame):
             Map=Map,
             Map=Map,
             auimgr=auimgr,
             auimgr=auimgr,
             name=name,
             name=name,
-            **kwargs)
+            **kwargs,
+        )
 
 
         self._giface = giface
         self._giface = giface
         # properties are shared in other objects, so defining here
         # properties are shared in other objects, so defining here
@@ -81,11 +89,11 @@ class MapFrame(SingleMapFrame):
         for toolb in toolbars:
         for toolb in toolbars:
             self.AddToolbar(toolb)
             self.AddToolbar(toolb)
 
 
-        self.activemap = self.toolbars['gcpdisp'].togglemap
+        self.activemap = self.toolbars["gcpdisp"].togglemap
         self.activemap.SetSelection(0)
         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)
         self._mgr.SetDockSizeConstraint(0.5, 0.5)
 
 
         #
         #
@@ -93,58 +101,70 @@ class MapFrame(SingleMapFrame):
         #
         #
 
 
         # items for choice
         # items for choice
-        self.statusbarItems = [sb.SbCoordinates,
-                               sb.SbRegionExtent,
-                               sb.SbCompRegionExtent,
-                               sb.SbShowRegion,
-                               sb.SbResolution,
-                               sb.SbDisplayGeometry,
-                               sb.SbMapScale,
-                               sb.SbProjection,
-                               sbgcp.SbGoToGCP,
-                               sbgcp.SbRMSError]
+        self.statusbarItems = [
+            sb.SbCoordinates,
+            sb.SbRegionExtent,
+            sb.SbCompRegionExtent,
+            sb.SbShowRegion,
+            sb.SbResolution,
+            sb.SbDisplayGeometry,
+            sb.SbMapScale,
+            sb.SbProjection,
+            sbgcp.SbGoToGCP,
+            sbgcp.SbRMSError,
+        ]
 
 
         # create statusbar and its manager
         # 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])
         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
         # fill statusbar manager
         self.statusbarManager.AddStatusbarItemsByClass(
         self.statusbarManager.AddStatusbarItemsByClass(
-            self.statusbarItems, mapframe=self, statusbar=statusbar)
+            self.statusbarItems, mapframe=self, statusbar=statusbar
+        )
         self.statusbarManager.AddStatusbarItem(
         self.statusbarManager.AddStatusbarItem(
-            sb.SbMask(self, statusbar=statusbar, position=2))
+            sb.SbMask(self, statusbar=statusbar, position=2)
+        )
         self.statusbarManager.AddStatusbarItem(
         self.statusbarManager.AddStatusbarItem(
-            sb.SbRender(self, statusbar=statusbar, position=3))
+            sb.SbRender(self, statusbar=statusbar, position=3)
+        )
 
 
         self.statusbarManager.SetMode(8)  # goto GCP
         self.statusbarManager.SetMode(8)  # goto GCP
 
 
         #
         #
         # Init map display (buffered DC & set default cursor)
         # Init map display (buffered DC & set default cursor)
         #
         #
-        self.grwiz.SwitchEnv('source')
+        self.grwiz.SwitchEnv("source")
         self.SrcMapWindow = BufferedMapWindow(
         self.SrcMapWindow = BufferedMapWindow(
-            parent=self, giface=self._giface, id=wx.ID_ANY,
-            properties=self.mapWindowProperties, Map=self.SrcMap)
-
-        self.grwiz.SwitchEnv('target')
+            parent=self,
+            giface=self._giface,
+            id=wx.ID_ANY,
+            properties=self.mapWindowProperties,
+            Map=self.SrcMap,
+        )
+
+        self.grwiz.SwitchEnv("target")
         self.TgtMapWindow = BufferedMapWindow(
         self.TgtMapWindow = BufferedMapWindow(
-            parent=self, giface=self._giface, id=wx.ID_ANY,
-            properties=self.mapWindowProperties, Map=self.TgtMap)
+            parent=self,
+            giface=self._giface,
+            id=wx.ID_ANY,
+            properties=self.mapWindowProperties,
+            Map=self.TgtMap,
+        )
         self.MapWindow = self.SrcMapWindow
         self.MapWindow = self.SrcMapWindow
         self.Map = self.SrcMap
         self.Map = self.SrcMap
         self._setUpMapWindow(self.SrcMapWindow)
         self._setUpMapWindow(self.SrcMapWindow)
         self._setUpMapWindow(self.TgtMapWindow)
         self._setUpMapWindow(self.TgtMapWindow)
-        self.SrcMapWindow.SetNamedCursor('cross')
-        self.TgtMapWindow.SetNamedCursor('cross')
+        self.SrcMapWindow.SetNamedCursor("cross")
+        self.TgtMapWindow.SetNamedCursor("cross")
         # used to switch current map (combo box in toolbar)
         # used to switch current map (combo box in toolbar)
         self.SrcMapWindow.mouseEntered.connect(
         self.SrcMapWindow.mouseEntered.connect(
-            lambda:
-            self._setActiveMapWindow(self.SrcMapWindow))
+            lambda: self._setActiveMapWindow(self.SrcMapWindow)
+        )
         self.TgtMapWindow.mouseEntered.connect(
         self.TgtMapWindow.mouseEntered.connect(
-            lambda:
-            self._setActiveMapWindow(self.TgtMapWindow))
+            lambda: self._setActiveMapWindow(self.TgtMapWindow)
+        )
 
 
         #
         #
         # initialize region values
         # initialize region values
@@ -167,22 +187,47 @@ class MapFrame(SingleMapFrame):
         # windows
         # windows
         self.list = self.CreateGCPList()
         self.list = self.CreateGCPList()
 
 
-        #self.SrcMapWindow.SetSize((300, 300))
-        #self.TgtMapWindow.SetSize((300, 300))
+        # self.SrcMapWindow.SetSize((300, 300))
+        # self.TgtMapWindow.SetSize((300, 300))
         self.list.SetSize((100, 150))
         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)))
-        self._mgr.AddPane(self.SrcMapWindow, wx.aui.AuiPaneInfo().
-                          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))
+        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)),
+        )
+        self._mgr.AddPane(
+            self.SrcMapWindow,
+            wx.aui.AuiPaneInfo()
+            .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),
+        )
 
 
         srcwidth, srcheight = self.SrcMapWindow.GetSize()
         srcwidth, srcheight = self.SrcMapWindow.GetSize()
         tgtwidth, tgtheight = self.TgtMapWindow.GetSize()
         tgtwidth, tgtheight = self.TgtMapWindow.GetSize()
@@ -196,7 +241,7 @@ class MapFrame(SingleMapFrame):
         else:
         else:
             self.activemap.Enable(False)
             self.activemap.Enable(False)
         # needed by Mac OS, does not harm on Linux, breaks display on Windows
         # needed by Mac OS, does not harm on Linux, breaks display on Windows
-        if platform.system() != 'Windows':
+        if platform.system() != "Windows":
             self._mgr.Update()
             self._mgr.Update()
 
 
         #
         #
@@ -219,10 +264,10 @@ class MapFrame(SingleMapFrame):
         # Re-use dialogs
         # Re-use dialogs
         #
         #
         self.dialogs = {}
         self.dialogs = {}
-        self.dialogs['attributes'] = None
-        self.dialogs['category'] = None
-        self.dialogs['barscale'] = None
-        self.dialogs['legend'] = None
+        self.dialogs["attributes"] = None
+        self.dialogs["category"] = None
+        self.dialogs["barscale"] = None
+        self.dialogs["legend"] = None
 
 
         self.decorationDialog = None  # decoration/overlays
         self.decorationDialog = None  # decoration/overlays
 
 
@@ -233,11 +278,11 @@ class MapFrame(SingleMapFrame):
         # TODO: almost the same implementation as for MapFrameBase (only names differ)
         # TODO: almost the same implementation as for MapFrameBase (only names differ)
         # enable or disable zoom history tool
         # enable or disable zoom history tool
         mapWindow.zoomHistoryAvailable.connect(
         mapWindow.zoomHistoryAvailable.connect(
-            lambda:
-            self.GetMapToolbar().Enable('zoomback', enable=True))
+            lambda: self.GetMapToolbar().Enable("zoomback", enable=True)
+        )
         mapWindow.zoomHistoryUnavailable.connect(
         mapWindow.zoomHistoryUnavailable.connect(
-            lambda:
-            self.GetMapToolbar().Enable('zoomback', enable=False))
+            lambda: self.GetMapToolbar().Enable("zoomback", enable=False)
+        )
         mapWindow.mouseMoving.connect(self.CoordinatesChanged)
         mapWindow.mouseMoving.connect(self.CoordinatesChanged)
 
 
     def AddToolbar(self, name):
     def AddToolbar(self, name):
@@ -252,42 +297,63 @@ class MapFrame(SingleMapFrame):
         """
         """
         # default toolbar
         # default toolbar
         if name == "map":
         if name == "map":
-            self.toolbars['map'] = MapToolbar(self, self._toolSwitcher)
-
-            self._mgr.AddPane(self.toolbars['map'],
-                              wx.aui.AuiPaneInfo().
-                              Name("maptoolbar").Caption(_("Map Toolbar")).
-                              ToolbarPane().Top().
-                              LeftDockable(False).RightDockable(False).
-                              BottomDockable(False).TopDockable(True).
-                              CloseButton(False).Layer(2).
-                              BestSize((self.toolbars['map'].GetSize())))
+            self.toolbars["map"] = MapToolbar(self, self._toolSwitcher)
+
+            self._mgr.AddPane(
+                self.toolbars["map"],
+                wx.aui.AuiPaneInfo()
+                .Name("maptoolbar")
+                .Caption(_("Map Toolbar"))
+                .ToolbarPane()
+                .Top()
+                .LeftDockable(False)
+                .RightDockable(False)
+                .BottomDockable(False)
+                .TopDockable(True)
+                .CloseButton(False)
+                .Layer(2)
+                .BestSize((self.toolbars["map"].GetSize())),
+            )
 
 
         # GCP display
         # GCP display
         elif name == "gcpdisp":
         elif name == "gcpdisp":
-            self.toolbars['gcpdisp'] = GCPDisplayToolbar(
-                self, self._toolSwitcher)
-
-            self._mgr.AddPane(self.toolbars['gcpdisp'],
-                              wx.aui.AuiPaneInfo().
-                              Name("gcpdisplaytoolbar").Caption(_("GCP Display toolbar")).
-                              ToolbarPane().Top().
-                              LeftDockable(False).RightDockable(False).
-                              BottomDockable(False).TopDockable(True).
-                              CloseButton(False).Layer(2))
+            self.toolbars["gcpdisp"] = GCPDisplayToolbar(self, self._toolSwitcher)
+
+            self._mgr.AddPane(
+                self.toolbars["gcpdisp"],
+                wx.aui.AuiPaneInfo()
+                .Name("gcpdisplaytoolbar")
+                .Caption(_("GCP Display toolbar"))
+                .ToolbarPane()
+                .Top()
+                .LeftDockable(False)
+                .RightDockable(False)
+                .BottomDockable(False)
+                .TopDockable(True)
+                .CloseButton(False)
+                .Layer(2),
+            )
 
 
             if not self.show_target:
             if not self.show_target:
-                self.toolbars['gcpdisp'].Enable('zoommenu', enable=False)
-
-            self.toolbars['gcpman'] = GCPManToolbar(self)
-
-            self._mgr.AddPane(self.toolbars['gcpman'],
-                              wx.aui.AuiPaneInfo().
-                              Name("gcpmanagertoolbar").Caption(_("GCP Manager toolbar")).
-                              ToolbarPane().Top().Row(1).
-                              LeftDockable(False).RightDockable(False).
-                              BottomDockable(False).TopDockable(True).
-                              CloseButton(False).Layer(2))
+                self.toolbars["gcpdisp"].Enable("zoommenu", enable=False)
+
+            self.toolbars["gcpman"] = GCPManToolbar(self)
+
+            self._mgr.AddPane(
+                self.toolbars["gcpman"],
+                wx.aui.AuiPaneInfo()
+                .Name("gcpmanagertoolbar")
+                .Caption(_("GCP Manager toolbar"))
+                .ToolbarPane()
+                .Top()
+                .Row(1)
+                .LeftDockable(False)
+                .RightDockable(False)
+                .BottomDockable(False)
+                .TopDockable(True)
+                .CloseButton(False)
+                .Layer(2),
+            )
 
 
         self._mgr.Update()
         self._mgr.Update()
 
 
@@ -314,13 +380,11 @@ class MapFrame(SingleMapFrame):
         event.Skip()
         event.Skip()
 
 
     def OnDraw(self, event):
     def OnDraw(self, event):
-        """Re-display current map composition
-        """
+        """Re-display current map composition"""
         self.MapWindow.UpdateMap(render=False)
         self.MapWindow.UpdateMap(render=False)
 
 
     def OnRender(self, event):
     def OnRender(self, event):
-        """Re-render map composition (each map layer)
-        """
+        """Re-render map composition (each map layer)"""
         # FIXME: remove qlayer code or use RemoveQueryLayer() now in mapdisp.frame
         # FIXME: remove qlayer code or use RemoveQueryLayer() now in mapdisp.frame
         # delete tmp map layers (queries)
         # delete tmp map layers (queries)
         qlayer = self.Map.GetListOfLayers(name=globalvar.QUERYLAYER)
         qlayer = self.Map.GetListOfLayers(name=globalvar.QUERYLAYER)
@@ -335,13 +399,12 @@ class MapFrame(SingleMapFrame):
         self.StatusbarUpdate()
         self.StatusbarUpdate()
 
 
     def OnPointer(self, event):
     def OnPointer(self, event):
-        """Pointer button clicked
-        """
+        """Pointer button clicked"""
         self.SrcMapWindow.SetModePointer()
         self.SrcMapWindow.SetModePointer()
         self.TgtMapWindow.SetModePointer()
         self.TgtMapWindow.SetModePointer()
         # change the default cursor
         # change the default cursor
-        self.SrcMapWindow.SetNamedCursor('cross')
-        self.TgtMapWindow.SetNamedCursor('cross')
+        self.SrcMapWindow.SetNamedCursor("cross")
+        self.TgtMapWindow.SetNamedCursor("cross")
 
 
     def OnZoomIn(self, event):
     def OnZoomIn(self, event):
         """Zoom in the map."""
         """Zoom in the map."""
@@ -372,12 +435,13 @@ class MapFrame(SingleMapFrame):
         win.EraseMap()
         win.EraseMap()
 
 
     def SaveToFile(self, event):
     def SaveToFile(self, event):
-        """Save map to image
-        """
+        """Save map to image"""
         img = self.MapWindow.img
         img = self.MapWindow.img
         if not 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
             return
         filetype, ltype = GetImageHandlers(img)
         filetype, ltype = GetImageHandlers(img)
 
 
@@ -391,11 +455,14 @@ class MapFrame(SingleMapFrame):
         dlg.Destroy()
         dlg.Destroy()
 
 
         # get filename
         # get filename
-        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)
+        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:
         if dlg.ShowModal() == wx.ID_OK:
             path = dlg.GetPath()
             path = dlg.GetPath()
@@ -404,13 +471,12 @@ class MapFrame(SingleMapFrame):
                 return
                 return
 
 
             base, ext = os.path.splitext(path)
             base, ext = os.path.splitext(path)
-            fileType = ltype[dlg.GetFilterIndex()]['type']
-            extType = ltype[dlg.GetFilterIndex()]['ext']
+            fileType = ltype[dlg.GetFilterIndex()]["type"]
+            extType = ltype[dlg.GetFilterIndex()]["ext"]
             if ext != extType:
             if ext != extType:
-                path = base + '.' + extType
+                path = base + "." + extType
 
 
-            self.MapWindow.SaveToFile(path, fileType,
-                                      width, height)
+            self.MapWindow.SaveToFile(path, fileType, width, height)
 
 
         dlg.Destroy()
         dlg.Destroy()
 
 
@@ -421,15 +487,15 @@ class MapFrame(SingleMapFrame):
         point = wx.GetMousePosition()
         point = wx.GetMousePosition()
         printmenu = Menu()
         printmenu = Menu()
         # Add items to the menu
         # Add items to the menu
-        setup = wx.MenuItem(printmenu, wx.ID_ANY, _('Page setup'))
+        setup = wx.MenuItem(printmenu, wx.ID_ANY, _("Page setup"))
         printmenu.AppendItem(setup)
         printmenu.AppendItem(setup)
         self.Bind(wx.EVT_MENU, self.printopt.OnPageSetup, setup)
         self.Bind(wx.EVT_MENU, self.printopt.OnPageSetup, setup)
 
 
-        preview = wx.MenuItem(printmenu, wx.ID_ANY, _('Print preview'))
+        preview = wx.MenuItem(printmenu, wx.ID_ANY, _("Print preview"))
         printmenu.AppendItem(preview)
         printmenu.AppendItem(preview)
         self.Bind(wx.EVT_MENU, self.printopt.OnPrintPreview, preview)
         self.Bind(wx.EVT_MENU, self.printopt.OnPrintPreview, preview)
 
 
-        doprint = wx.MenuItem(printmenu, wx.ID_ANY, _('Print display'))
+        doprint = wx.MenuItem(printmenu, wx.ID_ANY, _("Print display"))
         printmenu.AppendItem(doprint)
         printmenu.AppendItem(doprint)
         self.Bind(wx.EVT_MENU, self.printopt.OnDoPrint, doprint)
         self.Bind(wx.EVT_MENU, self.printopt.OnDoPrint, doprint)
 
 
@@ -457,38 +523,38 @@ class MapFrame(SingleMapFrame):
         self.MapWindow.DisplayToWind()
         self.MapWindow.DisplayToWind()
 
 
     def SaveDisplayRegion(self, event):
     def SaveDisplayRegion(self, event):
-        """Save display extents to named region file.
-        """
+        """Save display extents to named region file."""
         self.MapWindow.SaveDisplayRegion()
         self.MapWindow.SaveDisplayRegion()
 
 
     def OnZoomMenu(self, event):
     def OnZoomMenu(self, event):
-        """Popup Zoom menu
-        """
+        """Popup Zoom menu"""
         point = wx.GetMousePosition()
         point = wx.GetMousePosition()
         zoommenu = Menu()
         zoommenu = Menu()
         # Add items to the 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)
         zoommenu.AppendItem(zoomwind)
         self.Bind(wx.EVT_MENU, self.OnZoomToWind, 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)
         zoommenu.AppendItem(zoomdefault)
         self.Bind(wx.EVT_MENU, self.OnZoomToDefault, zoomdefault)
         self.Bind(wx.EVT_MENU, self.OnZoomToDefault, zoomdefault)
 
 
-        zoomsaved = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to saved region'))
+        zoomsaved = wx.MenuItem(zoommenu, wx.ID_ANY, _("Zoom to saved region"))
         zoommenu.AppendItem(zoomsaved)
         zoommenu.AppendItem(zoomsaved)
         self.Bind(wx.EVT_MENU, self.OnZoomToSaved, 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)
         zoommenu.AppendItem(savewind)
         self.Bind(wx.EVT_MENU, self.OnDisplayToWind, 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)
         zoommenu.AppendItem(savezoom)
         self.Bind(wx.EVT_MENU, self.SaveDisplayRegion, savezoom)
         self.Bind(wx.EVT_MENU, self.SaveDisplayRegion, savezoom)
 
 
@@ -520,7 +586,7 @@ class MapFrame(SingleMapFrame):
 
 
     def GetMapToolbar(self):
     def GetMapToolbar(self):
         """Returns toolbar with zooming tools"""
         """Returns toolbar with zooming tools"""
-        return self.toolbars['gcpdisp']
+        return self.toolbars["gcpdisp"]
 
 
     def _setActiveMapWindow(self, mapWindow):
     def _setActiveMapWindow(self, mapWindow):
         if not self.MapWindow == mapWindow:
         if not self.MapWindow == mapWindow:

+ 0 - 0
gui/wxpython/image2target/ii2t_statusbar.py


Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików