[GRASS-SVN] r62792 - in grass/trunk/gui/wxpython: . core gui_core mapdisp mapwin rdigit vdigit

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Nov 17 20:00:51 PST 2014


Author: annakrat
Date: 2014-11-17 20:00:51 -0800 (Mon, 17 Nov 2014)
New Revision: 62792

Added:
   grass/trunk/gui/wxpython/rdigit/
   grass/trunk/gui/wxpython/rdigit/__init__.py
   grass/trunk/gui/wxpython/rdigit/controller.py
   grass/trunk/gui/wxpython/rdigit/dialogs.py
   grass/trunk/gui/wxpython/rdigit/toolbars.py
Modified:
   grass/trunk/gui/wxpython/Makefile
   grass/trunk/gui/wxpython/core/render.py
   grass/trunk/gui/wxpython/gui_core/toolbars.py
   grass/trunk/gui/wxpython/mapdisp/frame.py
   grass/trunk/gui/wxpython/mapdisp/toolbars.py
   grass/trunk/gui/wxpython/mapwin/buffered.py
   grass/trunk/gui/wxpython/mapwin/graphics.py
   grass/trunk/gui/wxpython/vdigit/toolbars.py
Log:
wxGUI: raster digitizer added, enables drawing areas, lines, points and setting buffer for individual features [news]

Modified: grass/trunk/gui/wxpython/Makefile
===================================================================
--- grass/trunk/gui/wxpython/Makefile	2014-11-18 03:24:44 UTC (rev 62791)
+++ grass/trunk/gui/wxpython/Makefile	2014-11-18 04:00:51 UTC (rev 62792)
@@ -11,7 +11,7 @@
 SRCFILES := $(wildcard icons/*.py scripts/*.py xml/*) \
 	$(wildcard animation/* core/*.py dbmgr/* gcp/*.py gmodeler/* \
 	gui_core/*.py iclass/* lmgr/*.py location_wizard/*.py mapwin/*.py mapdisp/*.py \
-	mapswipe/* modules/*.py nviz/*.py psmap/* rlisetup/* timeline/* vdigit/* \
+	mapswipe/* modules/*.py nviz/*.py psmap/* rdigit/* rlisetup/* timeline/* vdigit/* \
 	vnet/*.py web_services/*.py wxplot/*.py iscatt/*.py tplot/*) \
 	gis_set.py gis_set_error.py wxgui.py README
 
@@ -20,7 +20,7 @@
 
 PYDSTDIRS := $(patsubst %,$(DSTDIR)/%,animation core dbmgr gcp gmodeler \
 	gui_core iclass lmgr location_wizard mapwin mapdisp modules nviz psmap \
-	mapswipe vdigit wxplot web_services rlisetup vnet timeline iscatt tplot)
+	mapswipe vdigit wxplot web_services rdigit rlisetup vnet timeline iscatt tplot)
 
 
 DSTDIRS := $(patsubst %,$(DSTDIR)/%,icons scripts xml)

Modified: grass/trunk/gui/wxpython/core/render.py
===================================================================
--- grass/trunk/gui/wxpython/core/render.py	2014-11-18 03:24:44 UTC (rev 62791)
+++ grass/trunk/gui/wxpython/core/render.py	2014-11-18 04:00:51 UTC (rev 62792)
@@ -430,6 +430,8 @@
 
         self.layerChanged = Signal('Map.layerChanged')
         self.updateProgress = Signal('Map.updateProgress')
+        self.layerRemoved = Signal('Map:layerRemoved')
+        self.layerAdded = Signal('Map:layerAdded')
 
     def GetProjInfo(self):
         """Get projection info"""
@@ -1034,6 +1036,8 @@
 
         wx.EndBusyCursor()
 
+        self.layerAdded.emit(layer=layer)
+
         return layer
 
     def DeleteAllLayers(self, overlay = False):
@@ -1072,6 +1076,7 @@
                     os.remove(f)
             list.remove(layer)
 
+            self.layerRemoved.emit(layer=layer)
             return layer
 
         return None
@@ -1123,6 +1128,7 @@
             raise GException(_("Unable to render map layer <%s>.") %
                              layer.GetName())
 
+        self.layerChanged(layer=layer)
         return layer
 
     def ChangeOpacity(self, layer, opacity):

Modified: grass/trunk/gui/wxpython/gui_core/toolbars.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/toolbars.py	2014-11-18 03:24:44 UTC (rev 62791)
+++ grass/trunk/gui/wxpython/gui_core/toolbars.py	2014-11-18 04:00:51 UTC (rev 62792)
@@ -324,6 +324,18 @@
                 del self._groups[group][tb]
                 break
 
+    def IsToolInGroup(self, tool, group):
+        """Checks whether a tool is in a specified group.
+
+        :param tool: tool id
+        :param group: name of group (e.g. 'mouseUse')
+        """
+        for group in self._toolsGroups[tool]:
+            for tb in self._groups[group]:
+                if tb.FindById(tool):
+                    return True
+        return False
+
     def ToolChanged(self, tool):
         """When any tool/button is pressed, other tools from group must be unchecked.
         

Modified: grass/trunk/gui/wxpython/mapdisp/frame.py
===================================================================
--- grass/trunk/gui/wxpython/mapdisp/frame.py	2014-11-18 03:24:44 UTC (rev 62791)
+++ grass/trunk/gui/wxpython/mapdisp/frame.py	2014-11-18 04:00:51 UTC (rev 62792)
@@ -343,7 +343,6 @@
                                           self.OnFlyThrough, wx.ITEM_CHECK, 8),))
         self._toolSwitcher.AddToolToGroup(group='mouseUse', toolbar=self.toolbars['map'],
                                           tool=self.toolbars['map'].flyThrough)
-        self.toolbars['map'].ChangeToolsDesc(mode2d = False)
         # update status bar
         
         self.statusbarManager.HideStatusbarChoiceItemsByClass(self.statusbarItemsHiddenInNviz)
@@ -477,7 +476,7 @@
             
         # vector digitizer
         elif name == "vdigit":
-            self.toolbars['map'].combo.SetValue(_("Digitize"))
+            self.toolbars['map'].combo.SetValue(_("Vector digitizer"))
             self._addToolbarVDigit()
         
         if fixed:
@@ -504,8 +503,7 @@
             self._mgr.GetPane('vdigit').Hide()
             self._mgr.GetPane('2d').Show()
             self._switchMapWindow(self.MapWindow2D)
-            
-        self.toolbars['map'].combo.SetValue(_("2D view"))
+
         self.toolbars['map'].Enable2D(True)
         
         self._mgr.Update()
@@ -772,7 +770,9 @@
                 self.toolbars['vdigit'].OnExit()
         if self.IsPaneShown('3d'):
             self.RemoveNviz()
-        
+        if hasattr(self, 'rdigit') and self.rdigit:
+            self.rdigit.CleanUp()
+
         if not self._layerManager:
             self.Destroy()
         elif self.page:
@@ -1435,3 +1435,58 @@
         map_win.ActivateWin()
 
         self.MapWindow = map_win
+
+    def AddRDigit(self):
+        """Adds raster digitizer: creates toolbar and digitizer controller,
+        binds events and signals."""
+        from rdigit.controller import RDigitController, EVT_UPDATE_PROGRESS
+        from rdigit.toolbars import RDigitToolbar
+
+        self.rdigit = RDigitController(self._giface,
+                                       mapWindow=self.GetMapWindow())
+        self.toolbars['rdigit'] = RDigitToolbar(parent=self, controller=self.rdigit,
+                                                toolSwitcher=self._toolSwitcher)
+        # connect signals
+        self.rdigit.newRasterCreated.connect(self.toolbars['rdigit'].NewRasterAdded)
+        self.rdigit.newRasterCreated.connect(lambda name: self._giface.mapCreated.emit(name=name, ltype='raster'))
+        self.rdigit.newFeatureCreated.connect(self.toolbars['rdigit'].UpdateCellValues)
+        self.rdigit.uploadMapCategories.connect(self.toolbars['rdigit'].UpdateCellValues)
+        self.rdigit.showNotification.connect(lambda text: self.SetStatusText(text, 0))
+        self.rdigit.quitDigitizer.connect(self.QuitRDigit)
+        self.rdigit.Bind(EVT_UPDATE_PROGRESS,
+                         lambda evt: self.statusbarManager.SetProgress(evt.range, evt.value, evt.text))
+        rasters = self.GetMap().GetListOfLayers(ltype='raster', mapset=grass.gisenv()['MAPSET'])
+        self.toolbars['rdigit'].UpdateRasterLayers(rasters)
+        self.toolbars['rdigit'].SelectDefault()
+
+        self.GetMap().layerAdded.connect(self._updateRDigitLayers)
+        self.GetMap().layerRemoved.connect(self._updateRDigitLayers)
+        self.GetMap().layerChanged.connect(self._updateRDigitLayers)
+        self._mgr.AddPane(self.toolbars['rdigit'],
+                          wx.aui.AuiPaneInfo().
+                          Name("rdigit toolbar").Caption(_("Raster Digitizer Toolbar")).
+                          ToolbarPane().Top().Row(1).
+                          LeftDockable(False).RightDockable(False).
+                          BottomDockable(False).TopDockable(True).Floatable().
+                          CloseButton(False).Layer(2).DestroyOnClose().
+                          BestSize((self.toolbars['rdigit'].GetBestSize())))
+        self._mgr.Update()
+
+        self.rdigit.Start()
+
+    def _updateRDigitLayers(self, layer):
+        mapset = grass.gisenv()['MAPSET']
+        self.toolbars['rdigit'].UpdateRasterLayers(
+            rasters=self.GetMap().GetListOfLayers(ltype='raster', mapset=mapset))
+
+    def QuitRDigit(self):
+        """Calls digitizer cleanup, removes digitizer object and disconnects
+        signals from Map."""
+        self.rdigit.CleanUp()
+        # disconnect updating layers
+        self.GetMap().layerAdded.disconnect(self._updateRDigitLayers)
+        self.GetMap().layerRemoved.disconnect(self._updateRDigitLayers)
+        self.GetMap().layerChanged.disconnect(self._updateRDigitLayers)
+
+        self.RemoveToolbar('rdigit')
+        self.rdigit = None

Modified: grass/trunk/gui/wxpython/mapdisp/toolbars.py
===================================================================
--- grass/trunk/gui/wxpython/mapdisp/toolbars.py	2014-11-18 03:24:44 UTC (rev 62791)
+++ grass/trunk/gui/wxpython/mapdisp/toolbars.py	2014-11-18 04:00:51 UTC (rev 62792)
@@ -79,28 +79,29 @@
         self._default = self.pointer
         
         # optional tools
+        toolNum = 0
         choices = [ _('2D view'), ]
-        self.toolId = { '2d' : 0 }
+        self.toolId = { '2d' : toolNum }
+        toolNum += 1
         if self.parent.GetLayerManager():
             log = self.parent.GetLayerManager().GetLogWindow()
         
         if haveNviz:
             choices.append(_('3D view'))
-            self.toolId['3d'] = 1
+            self.toolId['3d'] = toolNum
+            toolNum += 1
         else:
             from nviz.main import errorMsg
             if self.parent.GetLayerManager():
-              log.WriteCmdLog(_('3D view mode not available'))
-              log.WriteWarning(_('Reason: %s') % str(errorMsg))
+                log.WriteCmdLog(_('3D view mode not available'))
+                log.WriteWarning(_('Reason: %s') % str(errorMsg))
             
             self.toolId['3d'] = -1
 
         if haveVDigit:
-            choices.append(_('Digitize'))
-            if self.toolId['3d'] > -1:
-                self.toolId['vdigit'] = 2
-            else:
-                self.toolId['vdigit'] = 1
+            choices.append(_("Vector digitizer"))
+            self.toolId['vdigit'] = toolNum
+            toolNum += 1
         else:
             from vdigit.main import errorMsg
             if self.parent.GetLayerManager():
@@ -112,7 +113,9 @@
                              'In the meantime you can use "v.digit" from the Develop Vector menu.'), wrap = 60)
             
             self.toolId['vdigit'] = -1
-        
+        choices.append(_("Raster digitizer"))
+        self.toolId['rdigit'] = toolNum
+
         self.combo = wx.ComboBox(parent = self, id = wx.ID_ANY,
                                  choices = choices,
                                  style = wx.CB_READONLY, size = (110, -1))
@@ -218,11 +221,10 @@
         """Select / enable tool available in tools list
         """
         tool =  event.GetSelection()
-        
+
         if tool == self.toolId['2d']:
             self.ExitToolbars()
-            self.Enable2D(True)
-            self.ChangeToolsDesc(mode2d = True)            
+            self.Enable2D(True)         
         
         elif tool == self.toolId['3d'] and \
                 not (self.parent.MapWindow3D and self.parent.IsPaneShown('3d')):
@@ -235,6 +237,10 @@
             self.parent.AddToolbar("vdigit")
             self.parent.MapWindow.SetFocus()
 
+        elif tool == self.toolId['rdigit']:
+            self.ExitToolbars()
+            self.parent.AddRDigit()
+
     def OnAnalyze(self, event):
         """Analysis tools menu
         """
@@ -261,7 +267,9 @@
         if self.parent.GetLayerManager() and \
                 self.parent.GetLayerManager().IsPaneShown('toolbarNviz'):
             self.parent.RemoveNviz()
-        
+        if self.parent.GetToolbar('rdigit'):
+            self.parent.QuitRDigit()
+
     def Enable2D(self, enabled):
         """Enable/Disable 2D display mode specific tools"""
         for tool in (self.zoomRegion,
@@ -269,3 +277,6 @@
                      self.analyze,
                      self.printMap):
             self.EnableTool(tool, enabled)
+        self.ChangeToolsDesc(enabled)
+        if enabled:
+            self.combo.SetValue(_("2D view"))

Modified: grass/trunk/gui/wxpython/mapwin/buffered.py
===================================================================
--- grass/trunk/gui/wxpython/mapwin/buffered.py	2014-11-18 03:24:44 UTC (rev 62791)
+++ grass/trunk/gui/wxpython/mapwin/buffered.py	2014-11-18 04:00:51 UTC (rev 62792)
@@ -128,6 +128,8 @@
         self.mouseLeftUpPointer = Signal('BufferedWindow.mouseLeftUpPointer')
         # Emitted when left mouse button is released
         self.mouseLeftUp = Signal('BufferedWindow.mouseLeftUp')
+        # Emitted when right mouse button is released
+        self.mouseRightUp = Signal('BufferedWindow.mouseRightUp')
         # Emitted when left mouse button was pressed
         self.mouseLeftDown = Signal('BufferedWindow.mouseLeftDown')
         # Emitted after double-click
@@ -250,7 +252,8 @@
         self.PopupMenu(menu)
         menu.Destroy()
 
-    def Draw(self, pdc, img = None, drawid = None, pdctype = 'image', coords = [0, 0, 0, 0], pen = None):
+    def Draw(self, pdc, img=None, drawid=None, pdctype='image',
+             coords=[0, 0, 0, 0], pen=None, brush=None):
         """Draws map and overlay decorations
         """
         if drawid is None:
@@ -307,7 +310,9 @@
 
         elif pdctype == 'box': # draw a box on top of the map
             if pen:
-                pdc.SetBrush(wx.Brush(wx.CYAN, wx.TRANSPARENT))
+                if not brush:
+                    brush = wx.Brush(wx.CYAN, wx.TRANSPARENT)
+                pdc.SetBrush(brush)
                 pdc.SetPen(pen)
                 x2 = max(coords[0],coords[2])
                 x1 = min(coords[0],coords[2])
@@ -367,7 +372,9 @@
         elif pdctype == 'polygon':
             if pen:
                 pdc.SetPen(pen)
-                pdc.SetBrush(wx.TRANSPARENT_BRUSH)
+                if not brush:
+                    brush = wx.TRANSPARENT_BRUSH
+                pdc.SetBrush(brush)
                 pdc.DrawPolygon(points=coords)
                 x = min(coords, key=lambda x: x[0])[0]
                 y = min(coords, key=lambda x: x[1])[1]
@@ -378,7 +385,9 @@
         elif pdctype == 'circle': # draw circle
             if pen:
                 pdc.SetPen(pen)
-                pdc.SetBrush(wx.TRANSPARENT_BRUSH)
+                if not brush:
+                    brush = wx.TRANSPARENT_BRUSH
+                pdc.SetBrush(brush)
                 radius = abs(coords[2] - coords[0]) / 2
                 pdc.DrawCircle(max(coords[0], coords[2]) - radius,
                                max(coords[1], coords[3]) - radius, radius=radius)
@@ -540,11 +549,15 @@
         except NotImplementedError as e:
             print >> sys.stderr, e
             self.pdcDec.DrawToDC(dc)
-
         # draw temporary object on the foreground
-        ### self.pdcTmp.DrawToDCClipped(dc, rgn)
-        self.pdcTmp.DrawToDC(dc)
+        try:
+            gcdc = wx.GCDC(dc)
+            self.pdcTmp.DrawToDC(gcdc)
+        except NotImplementedError as e:
+            print >> sys.stderr, e
+            self.pdcTmp.DrawToDC(dc)
 
+
         if switchDraw:
             self.redrawAll = False
 
@@ -1125,7 +1138,7 @@
 
         return self.lineid
 
-    def DrawRectangle(self, pdc, point1, point2, pen, drawid=None):
+    def DrawRectangle(self, pdc, point1, point2, pen, brush=None, drawid=None):
         """Draw rectangle (not filled) in PseudoDC
 
         :param pdc: PseudoDC
@@ -1137,10 +1150,11 @@
         Debug.msg(4, "BufferedWindow.DrawRectangle(): pdc=%s, point1=%s, point2=%s" % \
                   (pdc, point1, point2))
         coords = [point1[0], point1[1], point2[0], point2[1]]
-        self.lineid = self.Draw(pdc, drawid=drawid, pdctype='box', coords=coords, pen=pen)
+        self.lineid = self.Draw(pdc, drawid=drawid, pdctype='box', coords=coords,
+                                pen=pen, brush=brush)
         return self.lineid
 
-    def DrawCircle(self, pdc, coords, radius, pen, drawid=None):
+    def DrawCircle(self, pdc, coords, radius, pen, brush=None, drawid=None):
         """Draw circle (not filled) in PseudoDC
 
         :param pdc: PseudoDC
@@ -1153,10 +1167,11 @@
                   (pdc, coords, radius))
         newcoords = [coords[0] - radius, coords[1] - radius,
                      coords[0] + radius, coords[1] + radius]
-        self.lineid = self.Draw(pdc, drawid=drawid, pdctype='circle', coords=newcoords, pen=pen)
+        self.lineid = self.Draw(pdc, drawid=drawid, pdctype='circle', coords=newcoords,
+                                pen=pen, brush=brush)
         return self.lineid
 
-    def DrawPolygon(self, pdc, coords, pen, drawid=None):
+    def DrawPolygon(self, pdc, coords, pen, brush=None, drawid=None):
         """Draws polygon from a list of points (do not append the first point)
 
         :param pdc: PseudoDC
@@ -1164,8 +1179,11 @@
         :param pen: pen
         :param drawid: id of the drawn object (used by PseudoDC)
         """
+        # avid wx.GCDC assert
+        if len(coords) <= 1:
+            return None
         self.lineid = self.Draw(pdc, drawid=drawid, pdctype='polygon',
-                                coords=coords, pen=pen)
+                                coords=coords, pen=pen, brush=brush)
         return self.lineid
 
     def _computeZoomToPointAndRecenter(self, position, zoomtype):
@@ -1469,6 +1487,9 @@
         self.redrawAll = True
         self.Refresh()
 
+        coords = self.Pixel2Cell(event.GetPosition())
+        self.mouseRightUp.emit(x=coords[0], y=coords[1])
+
         event.Skip()
 
     def OnMiddleDown(self, event):

Modified: grass/trunk/gui/wxpython/mapwin/graphics.py
===================================================================
--- grass/trunk/gui/wxpython/mapwin/graphics.py	2014-11-18 03:24:44 UTC (rev 62791)
+++ grass/trunk/gui/wxpython/mapwin/graphics.py	2014-11-18 04:00:51 UTC (rev 62792)
@@ -37,6 +37,9 @@
             "unused":  wx.Pen(colour=wx.LIGHT_GREY, width=2, style=wx.SOLID),
             "highest":  wx.Pen(colour=wx.RED, width=2, style=wx.SOLID)
         }
+        self.brushes = {
+            'default': wx.TRANSPARENT_BRUSH
+        }
 
         # list contains instances of GraphicsSetItem
         self.itemsList = []
@@ -132,12 +135,16 @@
                     pen = self.pens[item.GetPropertyVal("penName")]
                 else:
                     pen = self.pens["default"]
+                if item.GetPropertyVal("brushName"):
+                    brush = self.brushes[item.GetPropertyVal("brushName")]
+                else:
+                    brush = self.brushes["default"]
                 if self.mapCoords:
                     coords = [self.parentMapWin.Cell2Pixel(coords) for coords in item.GetCoords()]
                 else:
                     coords = item.GetCoords()
 
-                self.drawFunc(pdc=pdc, pen=pen, drawid=item.GetId(),
+                self.drawFunc(pdc=pdc, pen=pen, brush=brush, drawid=item.GetId(),
                               point1=coords[0],
                               point2=coords[1])
 
@@ -146,12 +153,16 @@
                     pen = self.pens[item.GetPropertyVal("penName")]
                 else:
                     pen = self.pens["default"]
+                if item.GetPropertyVal("brushName"):
+                    brush = self.brushes[item.GetPropertyVal("brushName")]
+                else:
+                    brush = self.brushes["default"]
                 if self.mapCoords:
                     coords = [self.parentMapWin.Cell2Pixel(coords) for coords in item.GetCoords()]
                 else:
                     coords = item.GetCoords()
 
-                self.drawFunc(pdc=pdc, pen=pen,
+                self.drawFunc(pdc=pdc, pen=pen, brush=brush,
                               coords=coords, drawid=item.GetId())
             itemOrderNum += 1
 
@@ -218,10 +229,7 @@
         :return: instance of GraphicsSetItem which is drawn in drawNum order
         :return: False if drawNum was out of range
         """
-        if drawNum < len(self.itemsList) and drawNum >= 0:
-            return self.itemsList[drawNum]
-        else:
-            return False
+        return self.itemsList[drawNum]
 
     def SetPropertyVal(self, propName, propVal):
         """Set property value
@@ -288,6 +296,37 @@
 
         return None
 
+    def AddBrush(self, brushName, brush):
+        """Add brush
+
+        :param brushName: name of added brush
+        :type brushName: str
+        :param brush: added brush
+        :type brush: wx.Brush
+
+        :return: True - if brush was added
+        :return: False - if brush already exists
+        """
+        if brushName in self.brushes:
+            return False
+
+        self.brushes[brushName] = brush
+        return True
+
+    def GetBrush(self, brushName):
+        """Get existing brush
+
+        :param brushName: name of brush
+        :type brushName: str
+
+        :return: wx.Brush reference if is found
+        :return: None if brushName was not found
+        """
+        if brushName in self.brushes:
+            return self.brushes[brushName]
+
+        return None
+
     def SetItemDrawOrder(self, item, drawNum):
         """Set draw order for item
 
@@ -328,7 +367,7 @@
 
 class GraphicsSetItem:
 
-    def __init__(self, coords, penName=None, label=None, hide=False):
+    def __init__(self, coords, penName=None, brushName=None, label=None, hide=False):
         """Could be point or line according to graphicsType in
         GraphicsSet class
 
@@ -338,6 +377,8 @@
                                 rectangle: [[10, 12], [33, 45]]
         :param penName: if it is not defined 'default' pen is used
         :type penName: str
+        :param brushName: if it is not defined 'default' brush is used
+        :type brushName: str
         :param label: label, which will be drawn with point. It is
                       relevant just for 'point' type
         :type label: str
@@ -348,15 +389,26 @@
         self.coords = coords
 
         self.properties = {"penName": penName,
+                           "brushName": brushName,
                            "hide": hide,
                            "label": label}
         self.id = wx.NewId()
 
+    def AddProperty(self, propName):
+        """Adds new property, to set it, call SetPropertyVal afterwards.
+
+        :param propName - name of the newly defined property
+        :type propName: str
+        """
+        if not propName in self.properties:
+            self.properties[propName] = None
+
     def SetPropertyVal(self, propName, propVal):
         """Set property value
 
         :param propName: - property name: "penName", "hide" or "label"
                          - property "label" is relevant just for 'point' type
+                         - or newly defined property name
         :type propName: str
         :param propVal: property value to be set
 

Added: grass/trunk/gui/wxpython/rdigit/__init__.py
===================================================================
--- grass/trunk/gui/wxpython/rdigit/__init__.py	                        (rev 0)
+++ grass/trunk/gui/wxpython/rdigit/__init__.py	2014-11-18 04:00:51 UTC (rev 62792)
@@ -0,0 +1,4 @@
+all = [
+    'controller',
+    'toolbars'
+    ]


Property changes on: grass/trunk/gui/wxpython/rdigit/__init__.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Added: grass/trunk/gui/wxpython/rdigit/controller.py
===================================================================
--- grass/trunk/gui/wxpython/rdigit/controller.py	                        (rev 0)
+++ grass/trunk/gui/wxpython/rdigit/controller.py	2014-11-18 04:00:51 UTC (rev 62792)
@@ -0,0 +1,510 @@
+# -*- coding: utf-8 -*-
+"""
+ at package rdigit.controller
+
+ at brief rdigit controller for drawing and rasterizing
+
+Classes:
+ - controller::RDigitController
+
+(C) 2014 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.
+
+ at author Anna Petrasova <kratochanna gmail.com>
+"""
+import os
+import tempfile
+import wx
+import uuid
+from wx.lib.newevent import NewEvent
+
+from grass.script import core as gcore
+from grass.script import raster as grast
+from grass.exceptions import CalledModuleError, ScriptError
+from grass.pydispatch.signal import Signal
+
+from core.gcmd import GError, GMessage
+from core.settings import UserSettings
+from core.gthread import gThread
+from rdigit.dialogs import NewRasterDialog
+
+updateProgress, EVT_UPDATE_PROGRESS = NewEvent()
+
+
+class RDigitController(wx.EvtHandler):
+    """Controller object for raster digitizer.
+    Inherits from EvtHandler to be able to send wx events from thraed.
+    """
+    def __init__(self, giface, mapWindow):
+        """Constructs controller
+
+        :param giface: grass interface object
+        :param mapWindow: instance of BufferedMapWindow
+        """
+        wx.EvtHandler.__init__(self)
+        self._giface = giface
+        self._mapWindow = mapWindow
+
+        # thread for running rasterization process
+        self._thread = gThread()
+        # name of raster map which is edited (also new one)
+        self._editedRaster = None
+        # name of optional background raster
+        self._backgroundRaster = None
+        # name of temporary raster used to backup original state
+        self._backupRasterName = None
+        # GraphicsSet for drawing areas, lines, points
+        self._areas = None
+        self._lines = None
+        self._points = None
+        # list of all GraphicsItems in the order of drawing
+        self._all = []
+        # if in state of drawing lin or area
+        self._drawing = False
+        # if running digitizing process in thread (to block drawing)
+        self._running = False
+        # color used to draw (should be moved to settings)
+        self._drawColor = wx.GREEN
+        # transparency used to draw (should be moved to settings)
+        self._drawTransparency = 100
+        # current selected drawing method
+        self._graphicsType = 'area'
+        # last edited cell value
+        self._currentCellValue = None
+        # last edited buffer value
+        self._currentWidthValue = None
+
+        self._oldMouseUse = None
+        self._oldCursor = None
+
+        # signal to add new raster to toolbar items
+        self.newRasterCreated = Signal('RDigitController:newRasterCreated')
+        # signal to add just used cell value in toolbar combo
+        self.newFeatureCreated = Signal('RDigitController:newFeatureCreated')
+        # signal to upload unique categories of background map into toolbar combo
+        self.uploadMapCategories = Signal('RDigitController:uploadMapCategories')
+        self.quitDigitizer = Signal('RDigitController:quitDigitizer')
+        self.showNotification = Signal('RDigitController:showNotification')
+
+    def _connectAll(self):
+        self._mapWindow.mouseLeftDown.connect(self._start)
+        self._mapWindow.mouseLeftUp.connect(self._addPoint)
+        self._mapWindow.mouseRightUp.connect(self._finish)
+        self._mapWindow.Unbind(wx.EVT_CONTEXT_MENU)
+
+    def _disconnectAll(self):
+        self._mapWindow.mouseLeftDown.disconnect(self._start)
+        self._mapWindow.mouseLeftUp.disconnect(self._addPoint)
+        self._mapWindow.mouseRightUp.connect(self._finish)
+        self._mapWindow.Bind(wx.EVT_CONTEXT_MENU, self._mapWindow.OnContextMenu)
+
+    def _start(self, x, y):
+        """Start digitizing a new object.
+        :param x: x coordinate in map units
+        :param y: y coordinate in map units
+        """
+        if self._running:
+            return
+
+        if not self._editedRaster:
+            GMessage(parent=self._mapWindow, message=_("Please select first the raster map"))
+            return
+        if not self._drawing:
+            if self._graphicsType == 'area':
+                item = self._areas.AddItem(coords=[])
+                item.SetPropertyVal('penName', 'pen1')
+                self._all.append(item)
+            elif self._graphicsType == 'line':
+                item = self._lines.AddItem(coords=[])
+                item.SetPropertyVal('penName', 'pen1')
+                self._all.append(item)
+            elif self._graphicsType == 'point':
+                item = self._points.AddItem(coords=[])
+                item.SetPropertyVal('penName', 'pen1')
+                self._all.append(item)
+            self._drawing = True
+
+    def _addPoint(self, x, y):
+        """Add point to an object.
+        :param x: x coordinate in map units
+        :param y: y coordinate in map units
+        """
+        if self._running:
+            return
+
+        if not self._drawing:
+            return
+
+        if self._graphicsType == 'area':
+            area = self._areas.GetItem(-1)
+            coords = area.GetCoords() + [[x, y]]
+            area.SetCoords(coords)
+            self.showNotification.emit(text=_("Right click to finish area"))
+        elif self._graphicsType == 'line':
+            line = self._lines.GetItem(-1)
+            coords = line.GetCoords() + [[x, y]]
+            line.SetCoords(coords)
+            self.showNotification.emit(text=_("Right click to finish line"))
+        elif self._graphicsType == 'point':
+            point = self._points.GetItem(-1)
+            point.SetCoords([x, y])
+            self._finish(x, y)
+        # draw
+        self._mapWindow.ClearLines()
+        self._lines.Draw(pdc=self._mapWindow.pdcTmp)
+        self._areas.Draw(pdc=self._mapWindow.pdcTmp)
+        self._points.Draw(pdc=self._mapWindow.pdcTmp)
+        self._mapWindow.Refresh()
+
+    def _finish(self, x, y):
+        """Finish digitizing a new object and redraws.
+        Saves current cell value and buffer width for that object.
+
+        :param x: x coordinate in map units
+        :param y: y coordinate in map units
+        """
+        if self._running:
+            return
+
+        if self._graphicsType == 'point':
+            item = self._points.GetItem(-1)
+        elif self._graphicsType == 'area':
+            item = self._areas.GetItem(-1)
+        elif self._graphicsType == 'line':
+            item = self._lines.GetItem(-1)
+        else:
+            return
+
+        self._drawing = False
+        item.SetPropertyVal('brushName', 'done')
+        item.AddProperty('cellValue')
+        item.AddProperty('widthValue')
+        item.SetPropertyVal('cellValue', self._currentCellValue)
+        item.SetPropertyVal('widthValue', self._currentWidthValue)
+        self.newFeatureCreated.emit()
+
+        self._mapWindow.ClearLines()
+        self._points.Draw(pdc=self._mapWindow.pdcTmp)
+        self._areas.Draw(pdc=self._mapWindow.pdcTmp)
+        self._lines.Draw(pdc=self._mapWindow.pdcTmp)
+
+        self._mapWindow.Refresh()
+
+    def SelectType(self, drawingType):
+        """Selects method (area/line/point) for drawing.
+        Connects and disconnects signal to allow other tools
+        in map toolbar to work.
+        """
+        if self._graphicsType and not drawingType:
+            self._mapWindow.ClearLines(pdc=self._mapWindow.pdcTmp)
+            self._mapWindow.mouse['end'] = self._mapWindow.mouse['begin']
+            # disconnect mouse events
+            self._disconnectAll()
+            self._mapWindow.SetNamedCursor(self._oldCursor)
+            self._mapWindow.mouse['use'] = self._oldMouseUse
+        elif self._graphicsType is None and drawingType:
+            self._connectAll()
+            # change mouse['box'] and pen to draw line during dragging
+            # TODO: better solution for drawing this line
+            self._mapWindow.mouse['use'] = None
+            self._mapWindow.mouse['box'] = "line"
+            self._mapWindow.pen = wx.Pen(colour='red', width=2, style=wx.SHORT_DASH)
+             # change the cursor
+            self._mapWindow.SetNamedCursor('pencil')
+
+        self._graphicsType = drawingType
+
+    def SetCellValue(self, value):
+        self._currentCellValue = value
+
+    def SetWidthValue(self, value):
+        self._currentWidthValue = value
+
+    def ChangeDrawColor(self, color):
+        self._drawColor = color[:3] + (self._drawTransparency,)
+        for each in (self._areas, self._lines, self._points):
+            each.GetPen('pen1').SetColour(self._drawColor)
+            each.GetBrush('done').SetColour(self._drawColor)
+        self._mapWindow.UpdateMap(render=False)
+
+    def Start(self):
+        """Registers graphics to map window,
+        connect required mouse signals.
+        """
+        self._oldMouseUse = self._mapWindow.mouse['use']
+        self._oldCursor = self._mapWindow.GetNamedCursor()
+
+        self._connectAll()
+
+        # change mouse['box'] and pen to draw line during dragging
+        # TODO: better solution for drawing this line
+        self._mapWindow.mouse['use'] = None
+        self._mapWindow.mouse['box'] = "line"
+        self._mapWindow.pen = wx.Pen(colour='red', width=2, style=wx.SHORT_DASH)
+
+        color = self._drawColor[:3] + (self._drawTransparency,)
+        self._areas = self._mapWindow.RegisterGraphicsToDraw(graphicsType='polygon',
+                                                             mapCoords=True)
+        self._areas.AddPen('pen1', wx.Pen(colour=color, width=2, style=wx.SOLID))
+        self._areas.AddBrush('done', wx.Brush(colour=color, style=wx.SOLID))
+
+        self._lines = self._mapWindow.RegisterGraphicsToDraw(graphicsType='line',
+                                                             mapCoords=True)
+        self._lines.AddPen('pen1', wx.Pen(colour=color, width=2, style=wx.SOLID))
+        self._lines.AddBrush('done', wx.Brush(colour=color, style=wx.SOLID))
+
+        self._points = self._mapWindow.RegisterGraphicsToDraw(graphicsType='point',
+                                                              mapCoords=True)
+        self._points.AddPen('pen1', wx.Pen(colour=color, width=2, style=wx.SOLID))
+        self._points.AddBrush('done', wx.Brush(colour=color, style=wx.SOLID))
+
+        # change the cursor
+        self._mapWindow.SetNamedCursor('pencil')
+
+    def Stop(self):
+        """Before stopping digitizer, asks to save edits"""
+        dlg = wx.MessageDialog(self._mapWindow, _("Do you want to save changes?"),
+                               _("Save raster map changes"), wx.YES_NO)
+        if dlg.ShowModal() == wx.ID_YES:
+            self._running = True
+            self._thread.Run(callable=self._exportRaster,
+                             ondone=lambda event: self._updateAndQuit())
+        else:
+            self.quitDigitizer.emit()
+
+    def Save(self):
+        """Saves current edits to a raster map"""
+        self._thread.Run(callable=self._exportRaster,
+                         ondone=lambda event: self._update())
+
+    def Undo(self):
+        """Undo a change, goes object back (finished or not finished)"""
+        if len(self._all):
+            removed = self._all.pop(-1)
+            # try to remove from each, it fails quietly when theitem is not there
+            self._areas.DeleteItem(removed)
+            self._lines.DeleteItem(removed)
+            self._points.DeleteItem(removed)
+            self._drawing = False
+            self._mapWindow.UpdateMap(render=False)
+
+    def CleanUp(self, restore=True):
+        """Cleans up drawing, temporary maps.
+        :param restore: if restore previous cursor, mouse['use']
+        """
+        try:
+            gcore.run_command('g.remove', type='rast', flags='f', name=self._backupRasterName, quiet=True)
+        except CalledModuleError:
+            pass
+
+        self._mapWindow.ClearLines(pdc=self._mapWindow.pdcTmp)
+        self._mapWindow.mouse['end'] = self._mapWindow.mouse['begin']
+        # disconnect mouse events
+        if self._graphicsType:
+            self._disconnectAll()
+        # unregister
+        self._mapWindow.UnregisterGraphicsToDraw(self._areas)
+        self._mapWindow.UnregisterGraphicsToDraw(self._lines)
+        self._mapWindow.UnregisterGraphicsToDraw(self._points)
+        #self._registeredGraphics = None
+        self._mapWindow.UpdateMap(render=False)
+
+        if restore:
+            # restore mouse['use'] and cursor to the state before measuring starts
+            self._mapWindow.SetNamedCursor(self._oldCursor)
+            self._mapWindow.mouse['use'] = self._oldMouseUse
+
+    def _updateAndQuit(self):
+        """Called when thread is done. Updates map and calls to quits digitizer."""
+        self._running = False
+        self._mapWindow.UpdateMap(render=True)
+        self.quitDigitizer.emit()
+
+    def _update(self):
+        """Called when thread is done. Updates map."""
+        self._running = False
+        self._mapWindow.UpdateMap(render=True)
+
+    def SelectOldMap(self, name):
+        """After selecting old raster, creates a backup copy for editing."""
+        try:
+            self._backupRaster(name)
+        except ScriptError:
+            GError(parent=self._mapWindow, message=_("Failed to create backup copy of edited raster map."))
+            return False
+        self._editedRaster = name
+        return True
+
+    def SelectNewMap(self):
+        """After selecting new raster, shows dialog to choose name,
+        background map and type of the new map."""
+        dlg = NewRasterDialog(parent=self._mapWindow)
+        if dlg.ShowModal() == wx.ID_OK:
+            try:
+                self._createNewMap(mapName=dlg.GetMapName(),
+                                   backgroundMap=dlg.GetBackgroundMapName(),
+                                   mapType=dlg.GetMapType())
+            except ScriptError:
+                GError(parent=self._mapWindow, message=_("Failed to create new raster map."))
+                return False
+            finally:
+                dlg.Destroy()
+            return True
+        else:
+            dlg.Destroy()
+            return False
+
+    def _createNewMap(self, mapName, backgroundMap, mapType):
+        """Creates a new raster map based on specified background and type."""
+        name = mapName.split('@')[0]
+        background = backgroundMap.split('@')[0]
+        types = {'CELL': 'int', 'FCELL': 'float', 'DCELL': 'double'}
+        if background:
+            back = background
+        else:
+            back = 'null()'
+        try:
+            grast.mapcalc(exp="{name} = {mtype}({back})".format(name=name, mtype=types[mapType],
+                                                                back=back),
+                          overwrite=True, quiet=True)
+            if background:
+                self._backgroundRaster = backgroundMap
+                gcore.run_command('r.colors', map=name, raster=self._backgroundRaster, quiet=True)
+                if mapType == 'CELL':
+                    values = gcore.read_command('r.describe', flags='1n',
+                                                map=backgroundMap, quiet=True).strip()
+                    if values:
+                        self.uploadMapCategories.emit(values=values.split('\n'))
+        except CalledModuleError:
+            raise ScriptError
+        self._backupRaster(name)
+
+        name = name + '@' + gcore.gisenv()['MAPSET']
+        self._editedRaster = name
+        self.newRasterCreated.emit(name=name)
+
+    def _backupRaster(self, name):
+        """Creates a temporary backup raster necessary for undo behavior.
+
+        :param str name: name of raster map for which we create backup
+        """
+        name = name.split('@')[0]
+        backup = name + '_backupcopy_' + str(os.getpid())
+        try:
+            gcore.run_command('g.copy', rast=[name, backup], quiet=True)
+        except CalledModuleError:
+            raise ScriptError
+
+        self._backupRasterName = backup
+
+    def _exportRaster(self):
+        """Rasterizes digitized features.
+
+        Uses r.in.poly and r.grow for buffering features. Creates separate raster
+        maps depending on common cell values and buffering width necessary to
+        keep the order of editing. These rasters are then patched together.
+        Sets default color table for the newly digitized raster.
+        """
+        if not self._editedRaster:
+            return
+
+        if len(self._all) < 1:
+            return
+        tempRaster = 'tmp_rdigit_rast_' + str(os.getpid())
+        text = []
+        rastersToPatch = []
+        i = 0
+        lastCellValue = lastWidthValue = None
+        evt = updateProgress(range=len(self._all), value=0, text=_("Rasterizing..."))
+        wx.PostEvent(self, evt)
+        lastCellValue = self._all[0].GetPropertyVal('cellValue')
+        lastWidthValue = self._all[0].GetPropertyVal('widthValue')
+        for item in self._all:
+            if item.GetPropertyVal('widthValue') and \
+                (lastCellValue != item.GetPropertyVal('cellValue') or
+                lastWidthValue != item.GetPropertyVal('widthValue')):
+                if text:
+                    out = self._rasterize(text, lastWidthValue, tempRaster)
+                    rastersToPatch.append(out)
+                    text = []
+                self._writeItem(item, text)
+                out = self._rasterize(text, item.GetPropertyVal('widthValue'),
+                                      tempRaster)
+                rastersToPatch.append(out)
+                text = []
+            else:
+                self._writeItem(item, text)
+            lastCellValue = item.GetPropertyVal('cellValue')
+            lastWidthValue = item.GetPropertyVal('widthValue')
+
+            i += 1
+            evt = updateProgress(range=len(self._all), value=i, text=_("Rasterizing..."))
+            wx.PostEvent(self, evt)
+        if text:
+            out = self._rasterize(text, item.GetPropertyVal('widthValue'),
+                                  tempRaster)
+            rastersToPatch.append(out)
+
+        gcore.run_command('r.patch', input=sorted(rastersToPatch, reverse=True) + [self._backupRasterName],
+                          output=self._editedRaster, overwrite=True, quiet=True)
+        gcore.run_command('g.remove', type='rast', flags='f', name=rastersToPatch + [tempRaster],
+                          quiet=True)
+        try:
+            if not self._backgroundRaster:
+                table = UserSettings.Get(group='rasterLayer', key='colorTable', subkey='selection')
+                gcore.run_command('r.colors', color=table, map=self._editedRaster, quiet=True)
+            else:
+                gcore.run_command('r.colors', map=self._editedRaster,
+                                  raster=self._backgroundRaster, quiet=True)
+        except CalledModuleError:
+            GError(parent=self._mapWindow,
+                   message=_("Failed to set default color table for edited raster map"))
+
+    def _writeFeature(self, item, vtype, text):
+        """Writes digitized features in r.in.poly format."""
+        coords = item.GetCoords()
+        if vtype == 'P':
+            coords = [coords]
+        cellValue = item.GetPropertyVal('cellValue')
+        record = '{vtype}\n'.format(vtype=vtype)
+        for coord in coords:
+            record += ' '.join([str(c) for c in coord])
+            record += '\n'
+        record += '= {cellValue}\n'.format(cellValue=cellValue)
+
+        text.append(record)
+
+    def _writeItem(self, item, text):
+        if item in self._areas.GetAllItems():
+            self._writeFeature(item, vtype='A', text=text)
+        elif item in self._lines.GetAllItems():
+            self._writeFeature(item, vtype='L', text=text)
+        elif item in self._points.GetAllItems():
+            self._writeFeature(item, vtype='P', text=text)
+
+    def _rasterize(self, text, bufferDist, tempRaster):
+        """Performs the actual rasterization using r.in.poly
+        and buffering with r.grow if required.
+
+        :param str text: string in r.in.poly format
+        :param float bufferDist: buffer distance in map units
+        :param str tempRaster: name of temporary raster used in computation
+
+        :return: output raster map name as a result of digitization
+        """
+        output = 'x' + str(uuid.uuid4())[:8]
+        asciiFile = tempfile.NamedTemporaryFile(delete=False)
+        asciiFile.write('\n'.join(text))
+        asciiFile.close()
+        if bufferDist:
+            gcore.run_command('r.in.poly', input=asciiFile.name, output=tempRaster,
+                              overwrite=True, quiet=True)
+            gcore.run_command('r.grow', input=tempRaster, output=output,
+                              flags='m', radius=bufferDist, quiet=True)
+        else:
+            gcore.run_command('r.in.poly', input=asciiFile.name, output=output,
+                              quiet=True)
+        os.unlink(asciiFile.name)
+        return output


Property changes on: grass/trunk/gui/wxpython/rdigit/controller.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Added: grass/trunk/gui/wxpython/rdigit/dialogs.py
===================================================================
--- grass/trunk/gui/wxpython/rdigit/dialogs.py	                        (rev 0)
+++ grass/trunk/gui/wxpython/rdigit/dialogs.py	2014-11-18 04:00:51 UTC (rev 62792)
@@ -0,0 +1,119 @@
+"""
+ at package rdigit.dialogs
+
+ at brief rdigit dialog for craeting new map.
+
+Classes:
+ - rdigit:NewRasterDialog
+
+(C) 2014 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.
+
+ at author Anna Petrasova <kratochanna gmail.com>
+"""
+
+import wx
+
+from core.utils import _
+from gui_core.gselect import Select
+from core.gcmd import GWarning
+
+import grass.script.core as gcore
+import grass.script.raster as grast
+from grass.exceptions import CalledModuleError
+
+
+class NewRasterDialog(wx.Dialog):
+    """Dialog for new raster map name and type selection
+    and selection of optional background map."""
+    def __init__(self, parent):
+        wx.Dialog.__init__(self, parent)
+        self.SetTitle(_("Create new raster map"))
+        self._name = None
+        self._type = None
+
+        # create widgets
+        self._mapSelect = Select(parent=self, type='rast')
+        self._backgroundSelect = Select(parent=self, type='rast')
+        self._typeChoice = wx.Choice(self, choices=['CELL', 'FCELL', 'DCELL'])
+        self._typeChoice.SetSelection(0)
+        self._mapSelect.SetFocus()
+
+        btnCancel = wx.Button(parent=self, id=wx.ID_CANCEL)
+        btnOK = wx.Button(parent=self, id=wx.ID_OK)
+        btnOK.SetDefault()
+        btnOK.Bind(wx.EVT_BUTTON, self.OnOK)
+
+        # do layout
+        mainSizer = wx.BoxSizer(wx.VERTICAL)
+        sizer = wx.GridBagSizer(hgap=10, vgap=10)
+        sizer.Add(wx.StaticText(self, label=_("Name for new raster map:")),
+                  pos=(0, 0), span=(1, 2), flag=wx.ALIGN_CENTER_VERTICAL)
+        sizer.Add(self._mapSelect, pos=(1, 0), span=(1, 2))
+        sizer.Add(wx.StaticText(self, label=_("Optionally select background raster map:")),
+                  pos=(2, 0), span=(1, 2), flag=wx.ALIGN_CENTER_VERTICAL)
+        sizer.Add(self._backgroundSelect, pos=(3, 0), span=(1, 2))
+        sizer.Add(wx.StaticText(self, label=_("New raster map type:")),
+                  pos=(4, 0), flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL)
+        sizer.Add(self._typeChoice, pos=(4, 1), flag=wx.EXPAND)
+
+        mainSizer.Add(sizer, proportion=1, flag=wx.EXPAND | wx.ALL, border=10)
+
+        btnSizer = wx.StdDialogButtonSizer()
+        btnSizer.AddButton(btnCancel)
+        btnSizer.AddButton(btnOK)
+        btnSizer.Realize()
+
+        mainSizer.Add(btnSizer, flag=wx.EXPAND | wx.ALL, border=10)
+
+        self._backgroundSelect.Bind(wx.EVT_TEXT, self.OnBackgroundMap)
+
+        self.SetSizer(mainSizer)
+        mainSizer.Fit(self)
+
+    def OnBackgroundMap(self, event):
+        value = self._backgroundSelect.GetValue()
+        try:
+            ret = grast.raster_info(value)
+            self._typeChoice.SetStringSelection(ret['datatype'])
+        except CalledModuleError:
+            return
+
+    def OnOK(self, event):
+        mapName = self.GetMapName()
+        if not mapName:
+            GWarning(parent=self.GetParent(), message=_("Please specify name for a new raster map"))
+        else:
+            found = gcore.find_file(name=mapName, mapset=gcore.gisenv()['MAPSET'])
+            if found and found['mapset'] == gcore.gisenv()['MAPSET']:
+                dlgOverwrite = wx.MessageDialog(
+                    self.GetParent(), message=_("Raster map <%s> already exists "
+                                                "in the current mapset. "
+                                                "Do you want to overwrite it?") % mapName,
+                    caption=_("Overwrite?"), style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
+                if not dlgOverwrite.ShowModal() == wx.ID_YES:
+                    dlgOverwrite.Destroy()
+                    return
+                else:
+                    dlgOverwrite.Destroy()
+                    self.EndModal(wx.ID_OK)
+            else:
+                self.EndModal(wx.ID_OK)
+
+    def GetMapName(self):
+        return self._mapSelect.GetValue()
+
+    def GetBackgroundMapName(self):
+        return self._backgroundSelect.GetValue()
+
+    def GetMapType(self):
+        return self._typeChoice.GetStringSelection()
+
+
+if __name__ == '__main__':
+    app = wx.App()
+    dlg = NewRasterDialog(None)
+    dlg.Show()
+    app.MainLoop()


Property changes on: grass/trunk/gui/wxpython/rdigit/dialogs.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Added: grass/trunk/gui/wxpython/rdigit/toolbars.py
===================================================================
--- grass/trunk/gui/wxpython/rdigit/toolbars.py	                        (rev 0)
+++ grass/trunk/gui/wxpython/rdigit/toolbars.py	2014-11-18 04:00:51 UTC (rev 62792)
@@ -0,0 +1,173 @@
+"""
+ at package rdigit.toolbars
+
+ at brief rdigit toolbars and icons.
+
+Classes:
+ - toolbars::RDigitToolbar
+
+(C) 2014 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.
+
+ at author Anna Petrasova <kratochanna gmail.com>
+"""
+
+import wx
+
+from core.utils import _
+from gui_core.toolbars import BaseToolbar
+from icons.icon import MetaIcon
+from gui_core.widgets import FloatValidator
+import wx.lib.colourselect as csel
+
+
+rdigitIcons = {'area': MetaIcon(img='polygon-create',
+                                label=_('Digitize area')),
+               'line': MetaIcon(img='line-create',
+                                label=_('Digitize line')),
+               'point': MetaIcon(img='point-create',
+                                 label=_('Digitize point')),
+               'save': MetaIcon(img='save', label=_("Save raster map")),
+               'undo': MetaIcon(img='undo', label=_("Undo")),
+               'quit': MetaIcon(img='quit', label=_("Quit raster digitizer"))}
+
+
+class RDigitToolbar(BaseToolbar):
+    """RDigit toolbar
+    """
+    def __init__(self, parent, controller, toolSwitcher):
+        """RDigit toolbar constructor
+        """
+        BaseToolbar.__init__(self, parent, toolSwitcher)
+        self._controller = controller
+        self.InitToolbar(self._toolbarData())
+
+        self._mapSelectionComboId = wx.NewId()
+        self._mapSelectionCombo = wx.ComboBox(self, id=self._mapSelectionComboId,
+                                              value=_("Select raster map"),
+                                              choices=[], size=(120, -1))
+        self._mapSelectionCombo.Bind(wx.EVT_COMBOBOX, self.OnMapSelection)
+        self._mapSelectionCombo.SetEditable(False)
+        self.InsertControl(0, self._mapSelectionCombo)
+        self._previousMap = self._mapSelectionCombo.GetValue()
+
+        self._colorId = wx.NewId()
+        self._color = csel.ColourSelect(parent=self, colour=wx.GREEN,
+                                        size=(30, 30))
+        self._color.Bind(csel.EVT_COLOURSELECT, lambda evt: self._changeDrawColor())
+        self._color.SetToolTipString(_("Set drawing color (not raster cell color)"))
+        self.InsertControl(4, self._color)
+
+        self._cellValues = set(['1'])
+        self._valueComboId = wx.NewId()
+        # validator does not work with combobox, SetBackgroundColor is not working
+        self._valueCombo = wx.ComboBox(self, id=self._valueComboId,
+                                       choices=list(self._cellValues), size=(80, -1),
+                                       validator=FloatValidator())
+        self._valueCombo.Bind(wx.EVT_COMBOBOX, lambda evt: self._cellValueChanged())
+        self._valueCombo.Bind(wx.EVT_TEXT, lambda evt: self._cellValueChanged())
+        self._valueCombo.SetSelection(0)
+        self._cellValueChanged()
+        self.InsertControl(6, wx.StaticText(self, label=" %s" % _("Cell value:")))
+        self.InsertControl(7, self._valueCombo)
+
+        self._widthValueId = wx.NewId()
+        # validator does not work with combobox, SetBackgroundColor is not working
+        self._widthValue = wx.TextCtrl(self, id=self._widthValueId, value='0',
+                                       size=(80, -1), validator=FloatValidator())
+        self._widthValue.Bind(wx.EVT_TEXT, lambda evt: self._widthValueChanged())
+        self._widthValueChanged()
+        self._widthValue.SetToolTipString(_("Width of currently digitized line/point in map units."))
+        self.InsertControl(8, wx.StaticText(self, label=" %s" % _("Width:")))
+        self.InsertControl(9, self._widthValue)
+
+        for tool in (self.area, self.line, self.point):
+            self.toolSwitcher.AddToolToGroup(group='mouseUse', toolbar=self, tool=tool)
+        self.toolSwitcher.toggleToolChanged.connect(self.CheckSelectedTool)
+        self._default = self.area
+        # realize the toolbar
+        self.Realize()
+
+    def _toolbarData(self):
+        """Toolbar data"""
+        return self._getToolbarData((('area', rdigitIcons['area'],
+                                      lambda event: self._controller.SelectType('area'),
+                                      wx.ITEM_CHECK),
+                                     ('line', rdigitIcons['line'],
+                                      lambda event: self._controller.SelectType('line'),
+                                      wx.ITEM_CHECK),
+                                     ('point', rdigitIcons['point'],
+                                      lambda event: self._controller.SelectType('point'),
+                                      wx.ITEM_CHECK),
+                                     (None, ),
+                                     (None, ),
+                                     ('undo', rdigitIcons['undo'],
+                                      lambda event: self._controller.Undo()),
+                                     ('save', rdigitIcons['save'],
+                                      lambda event: self._controller.Save()),
+                                     ('quit', rdigitIcons['quit'],
+                                      lambda event: self._controller.Stop())))
+
+    def CheckSelectedTool(self, id):
+        print self.toolSwitcher.IsToolInGroup(tool=id, group='mouseUse')
+        if self.toolSwitcher.IsToolInGroup(tool=id, group='mouseUse') \
+                and id not in (self.area, self.line, self.point):
+            self._controller.SelectType(None)
+
+    def UpdateRasterLayers(self, rasters):
+        new = _("New raster map")
+        items = [raster.name for raster in rasters if raster.name is not None]
+        items.insert(0, new)
+        self._mapSelectionCombo.SetItems(items)
+
+    def OnMapSelection(self, event):
+        """!Either map to edit or create new map selected."""
+        idx = self._mapSelectionCombo.GetSelection()
+        if idx == 0:
+            ret = self._controller.SelectNewMap()
+        else:
+            ret = self._controller.SelectOldMap(self._mapSelectionCombo.GetString(idx))
+        if not ret:
+            # in wxpython 3 we can't set value which is not in the items
+            # when not editable
+            self._mapSelectionCombo.SetEditable(True)
+            self._mapSelectionCombo.SetValue(self._previousMap)
+            self._mapSelectionCombo.SetEditable(False)
+        # we need to get back to previous
+        self._previousMap = self._mapSelectionCombo.GetValue()
+
+    def NewRasterAdded(self, name):
+        idx = self._mapSelectionCombo.Append(name)
+        self._mapSelectionCombo.SetSelection(idx)
+
+    def UpdateCellValues(self, values=None):
+        if not values:
+            values = [self._valueCombo.GetValue()]
+        for value in values:
+            self._cellValues.add(str(value))
+
+        valList = sorted(list(self._cellValues), key=float)
+        self._valueCombo.SetItems(valList)
+
+    def _cellValueChanged(self):
+        value = self._valueCombo.GetValue()
+        try:
+            value = float(value)
+            self._controller.SetCellValue(value)
+        except ValueError:
+            return
+
+    def _widthValueChanged(self):
+        value = self._widthValue.GetValue()
+        try:
+            value = float(value)
+            self._controller.SetWidthValue(value)
+        except ValueError:
+            self._controller.SetWidthValue(0)
+            return
+
+    def _changeDrawColor(self):
+        color = self._color.GetColour()
+        self._controller.ChangeDrawColor(color=color)


Property changes on: grass/trunk/gui/wxpython/rdigit/toolbars.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Modified: grass/trunk/gui/wxpython/vdigit/toolbars.py
===================================================================
--- grass/trunk/gui/wxpython/vdigit/toolbars.py	2014-11-18 03:24:44 UTC (rev 62791)
+++ grass/trunk/gui/wxpython/vdigit/toolbars.py	2014-11-18 04:00:51 UTC (rev 62792)
@@ -913,7 +913,7 @@
         if self.combo:
             self.combo.SetValue(mapLayer.GetName())
         if 'map' in self.parent.toolbars:
-            self.parent.toolbars['map'].combo.SetValue (_('Digitize'))
+            self.parent.toolbars['map'].combo.SetValue (_('Vector digitizer'))
         
         # here was dead code to enable vdigit button in toolbar
         # with if to ignore iclass



More information about the grass-commit mailing list