[GRASS-SVN] r44943 - grass/trunk/gui/wxpython/gui_modules

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Jan 10 14:06:52 EST 2011


Author: martinl
Date: 2011-01-10 11:06:52 -0800 (Mon, 10 Jan 2011)
New Revision: 44943

Modified:
   grass/trunk/gui/wxpython/gui_modules/layertree.py
   grass/trunk/gui/wxpython/gui_modules/mapdisp_window.py
   grass/trunk/gui/wxpython/gui_modules/wxvdigit.py
   grass/trunk/gui/wxpython/gui_modules/wxvdriver.py
Log:
wxGUI/vdigit pythonization in progress


Modified: grass/trunk/gui/wxpython/gui_modules/layertree.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/layertree.py	2011-01-10 15:53:26 UTC (rev 44942)
+++ grass/trunk/gui/wxpython/gui_modules/layertree.py	2011-01-10 19:06:52 UTC (rev 44943)
@@ -8,7 +8,7 @@
  - Layer
  - LayerTree
 
-(C) 2007-2010 by the GRASS Development Team
+(C) 2007-2011 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.
@@ -64,7 +64,7 @@
     """!Creates layer tree structure
     """
     def __init__(self, parent,
-                 id = wx.ID_ANY, style=wx.SUNKEN_BORDER,
+                 id = wx.ID_ANY, style = wx.SUNKEN_BORDER,
                  ctstyle = CT.TR_HAS_BUTTONS | CT.TR_HAS_VARIABLE_ROW_HEIGHT |
                  CT.TR_HIDE_ROOT | CT.TR_ROW_LINES | CT.TR_FULL_ROW_HIGHLIGHT |
                  CT.TR_MULTIPLE, **kwargs):
@@ -105,18 +105,17 @@
         # self.SetAutoLayout(True)
         self.SetGradientStyle(1)
         self.EnableSelectionGradient(True)
-        self.SetFirstGradientColour(wx.Colour(100, 100, 100))
-        self.SetSecondGradientColour(wx.Colour(150, 150, 150))
+        self._setGradient()
         
         # init associated map display
         pos = wx.Point((self.disp_idx + 1) * 25, (self.disp_idx + 1) * 25)
         self.mapdisplay = mapdisp.MapFrame(self,
-                                           id=wx.ID_ANY, pos=pos,
-                                           size=globalvar.MAP_WINDOW_SIZE,
-                                           style=wx.DEFAULT_FRAME_STYLE,
-                                           tree=self, notebook=self.notebook,
-                                           lmgr=self.lmgr, page=self.treepg,
-                                           Map=self.Map, auimgr=self.auimgr)
+                                           id = wx.ID_ANY, pos = pos,
+                                           size = globalvar.MAP_WINDOW_SIZE,
+                                           style = wx.DEFAULT_FRAME_STYLE,
+                                           tree = self, notebook = self.notebook,
+                                           lmgr = self.lmgr, page = self.treepg,
+                                           Map = self.Map, auimgr = self.auimgr)
         
         # title
         self.mapdisplay.SetTitle(_("GRASS GIS Map Display: %(id)d  - Location: %(loc)s") % \
@@ -133,7 +132,7 @@
         self.SetPyData(self.root, (None, None))
         
         #create image list to use with layer tree
-        il = wx.ImageList(16, 16, mask=False)
+        il = wx.ImageList(16, 16, mask = False)
         
         trart = wx.ArtProvider.GetBitmap(wx.ART_FOLDER_OPEN, wx.ART_OTHER, (16, 16))
         self.folder_open = il.Add(trart)
@@ -199,6 +198,21 @@
         self.Bind(wx.EVT_TREE_END_LABEL_EDIT,   self.OnRenamed)
         self.Bind(wx.EVT_KEY_UP,                self.OnKeyUp)
         self.Bind(wx.EVT_IDLE,                  self.OnIdle)
+
+    def _setGradient(self, iType = None):
+        """!Set gradient for items
+
+        @param iType bgmap, vdigit or None
+        """
+        if iType == 'bgmap':
+            self.SetFirstGradientColour(wx.Colour(0, 100, 0))
+            self.SetSecondGradientColour(wx.Colour(0, 150, 0))
+        elif iType == 'vdigit':
+            self.SetFirstGradientColour(wx.Colour(100, 0, 0))
+            self.SetSecondGradientColour(wx.Colour(150, 0, 0))
+        else:
+            self.SetFirstGradientColour(wx.Colour(100, 100, 100))
+            self.SetSecondGradientColour(wx.Colour(150, 150, 150))
         
     def GetMap(self):
         """!Get map instace"""
@@ -215,7 +229,7 @@
         """
         if self.rerender:
             if self.mapdisplay.statusbarWin['render'].GetValue():
-                self.mapdisplay.MapWindow.UpdateMap(render=True)
+                self.mapdisplay.MapWindow.UpdateMap(render = True)
 
         event.Skip()
         
@@ -263,12 +277,12 @@
         numSelected = len(self.GetSelections())
         
         # general item
-        self.popupMenu.Append(self.popupID1, text=_("Remove"))
-        self.Bind(wx.EVT_MENU, self.lmgr.OnDeleteLayer, id=self.popupID1)
+        self.popupMenu.Append(self.popupID1, text = _("Remove"))
+        self.Bind(wx.EVT_MENU, self.lmgr.OnDeleteLayer, id = self.popupID1)
 
         if ltype != "command": # rename
-            self.popupMenu.Append(self.popupID2, text=_("Rename"))
-            self.Bind(wx.EVT_MENU, self.OnRenameLayer, id=self.popupID2)
+            self.popupMenu.Append(self.popupID2, text = _("Rename"))
+            self.Bind(wx.EVT_MENU, self.OnRenameLayer, id = self.popupID2)
             if numSelected > 1:
                 self.popupMenu.Enable(self.popupID2, False)
             
@@ -276,20 +290,20 @@
         if ltype != "group" and \
                 ltype != "command":
             self.popupMenu.AppendSeparator()
-            self.popupMenu.Append(self.popupID8, text=_("Change opacity level"))
-            self.Bind(wx.EVT_MENU, self.OnPopupOpacityLevel, id=self.popupID8)
-            self.popupMenu.Append(self.popupID3, text=_("Properties"))
-            self.Bind(wx.EVT_MENU, self.OnPopupProperties, id=self.popupID3)
+            self.popupMenu.Append(self.popupID8, text = _("Change opacity level"))
+            self.Bind(wx.EVT_MENU, self.OnPopupOpacityLevel, id = self.popupID8)
+            self.popupMenu.Append(self.popupID3, text = _("Properties"))
+            self.Bind(wx.EVT_MENU, self.OnPopupProperties, id = self.popupID3)
             
             if ltype in ('raster', 'vector', '3d-raster') and self.mapdisplay.toolbars['nviz']:
                 self.popupMenu.Append(self.popupID11, _("3D view properties"))
-                self.Bind (wx.EVT_MENU, self.OnNvizProperties, id=self.popupID11)
+                self.Bind (wx.EVT_MENU, self.OnNvizProperties, id = self.popupID11)
             
             if ltype in ('raster', 'vector', 'rgb'):
-                self.popupMenu.Append(self.popupID9, text=_("Zoom to selected map(s)"))
-                self.Bind(wx.EVT_MENU, self.mapdisplay.OnZoomToMap, id=self.popupID9)
-                self.popupMenu.Append(self.popupID10, text=_("Set computational region from selected map(s)"))
-                self.Bind(wx.EVT_MENU, self.OnSetCompRegFromMap, id=self.popupID10)
+                self.popupMenu.Append(self.popupID9, text = _("Zoom to selected map(s)"))
+                self.Bind(wx.EVT_MENU, self.mapdisplay.OnZoomToMap, id = self.popupID9)
+                self.popupMenu.Append(self.popupID10, text = _("Set computational region from selected map(s)"))
+                self.Bind(wx.EVT_MENU, self.OnSetCompRegFromMap, id = self.popupID10)
             if numSelected > 1:
                 self.popupMenu.Enable(self.popupID8, False)
                 self.popupMenu.Enable(self.popupID3, False)
@@ -304,14 +318,14 @@
         #
         if mltype and mltype == "vector":
             self.popupMenu.AppendSeparator()
-            self.popupMenu.Append(self.popupID4, text=_("Show attribute data"))
-            self.Bind (wx.EVT_MENU, self.lmgr.OnShowAttributeTable, id=self.popupID4)
+            self.popupMenu.Append(self.popupID4, text = _("Show attribute data"))
+            self.Bind (wx.EVT_MENU, self.lmgr.OnShowAttributeTable, id = self.popupID4)
 
-            self.popupMenu.Append(self.popupID5, text=_("Start editing"))
-            self.popupMenu.Append(self.popupID6, text=_("Stop editing"))
+            self.popupMenu.Append(self.popupID5, text = _("Start editing"))
+            self.popupMenu.Append(self.popupID6, text = _("Stop editing"))
             self.popupMenu.Enable(self.popupID6, False)
-            self.Bind (wx.EVT_MENU, self.OnStartEditing, id=self.popupID5)
-            self.Bind (wx.EVT_MENU, self.OnStopEditing,  id=self.popupID6)
+            self.Bind (wx.EVT_MENU, self.OnStartEditing, id = self.popupID5)
+            self.Bind (wx.EVT_MENU, self.OnStopEditing,  id = self.popupID6)
 
             layer = self.GetPyData(self.layer_selected)[0]['maplayer']
             # enable editing only for vector map layers available in the current mapset
@@ -319,15 +333,15 @@
             if digitToolbar:
                 # background vector map
                 self.popupMenu.Append(self.popupID14,
-                                      text=_("Use as background vector map"),
-                                      kind=wx.ITEM_CHECK)
-                self.Bind(wx.EVT_MENU, self.OnSetBgMap, id=self.popupID14)
-                if UserSettings.Get(group='vdigit', key='bgmap', subkey='value',
-                                    internal=True) == layer.GetName():
+                                      text = _("Use as background vector map for digitizer"),
+                                      kind = wx.ITEM_CHECK)
+                self.Bind(wx.EVT_MENU, self.OnSetBgMap, id = self.popupID14)
+                if UserSettings.Get(group = 'vdigit', key = 'bgmap', subkey = 'value',
+                                    internal = True) == layer.GetName():
                     self.popupMenu.Check(self.popupID14, True)
             
-            self.popupMenu.Append(self.popupID16, text=_("Rebuild topology"))
-            self.Bind(wx.EVT_MENU, self.OnTopology, id=self.popupID16)
+            self.popupMenu.Append(self.popupID16, text = _("Rebuild topology"))
+            self.Bind(wx.EVT_MENU, self.OnTopology, id = self.popupID16)
 
             if layer.GetMapset() != grass.gisenv()['MAPSET']:
                 # only vector map in current mapset can be edited
@@ -357,7 +371,7 @@
                     self.popupMenu.Enable(self.popupID14, True)
             
             self.popupMenu.Append(self.popupID7, _("Metadata"))
-            self.Bind (wx.EVT_MENU, self.OnMetadata, id=self.popupID7)
+            self.Bind (wx.EVT_MENU, self.OnMetadata, id = self.popupID7)
             if numSelected > 1:
                 self.popupMenu.Enable(self.popupID4, False)
                 self.popupMenu.Enable(self.popupID5, False)
@@ -369,19 +383,19 @@
         # raster layers (specific items)
         #
         elif mltype and mltype == "raster":
-            self.popupMenu.Append(self.popupID12, text=_("Zoom to selected map(s) (ignore NULLs)"))
-            self.Bind(wx.EVT_MENU, self.mapdisplay.OnZoomToRaster, id=self.popupID12)
-            self.popupMenu.Append(self.popupID13, text=_("Set computational region from selected map(s) (ignore NULLs)"))
-            self.Bind(wx.EVT_MENU, self.OnSetCompRegFromRaster, id=self.popupID13)
+            self.popupMenu.Append(self.popupID12, text = _("Zoom to selected map(s) (ignore NULLs)"))
+            self.Bind(wx.EVT_MENU, self.mapdisplay.OnZoomToRaster, id = self.popupID12)
+            self.popupMenu.Append(self.popupID13, text = _("Set computational region from selected map(s) (ignore NULLs)"))
+            self.Bind(wx.EVT_MENU, self.OnSetCompRegFromRaster, id = self.popupID13)
             self.popupMenu.AppendSeparator()
             self.popupMenu.Append(self.popupID15, _("Set color table"))
-            self.Bind (wx.EVT_MENU, self.OnColorTable, id=self.popupID15)
+            self.Bind (wx.EVT_MENU, self.OnColorTable, id = self.popupID15)
             self.popupMenu.Append(self.popupID4, _("Histogram"))
-            self.Bind (wx.EVT_MENU, self.OnHistogram, id=self.popupID4)
+            self.Bind (wx.EVT_MENU, self.OnHistogram, id = self.popupID4)
             self.popupMenu.Append(self.popupID5, _("Profile"))
-            self.Bind (wx.EVT_MENU, self.OnProfile, id=self.popupID5)
+            self.Bind (wx.EVT_MENU, self.OnProfile, id = self.popupID5)
             self.popupMenu.Append(self.popupID6, _("Metadata"))
-            self.Bind (wx.EVT_MENU, self.OnMetadata, id=self.popupID6)
+            self.Bind (wx.EVT_MENU, self.OnMetadata, id = self.popupID6)
             
             if numSelected > 1:
                 self.popupMenu.Enable(self.popupID12, False)
@@ -417,7 +431,7 @@
         cmd.append('map=%s' % mapLayer.GetName())
 
         # print output to command log area
-        self.lmgr.goutput.RunCmd(cmd, switchPage=True)
+        self.lmgr.goutput.RunCmd(cmd, switchPage = True)
 
     def OnSetCompRegFromRaster(self, event):
         """!Set computational region from selected raster map (ignore NULLs)"""
@@ -466,10 +480,10 @@
         """!Plot profile of given raster map layer"""
         mapLayer = self.GetPyData(self.layer_selected)[0]['maplayer']
         if not mapLayer.GetName():
-            wx.MessageBox(parent=self,
-                          message=_("Unable to create profile of "
+            wx.MessageBox(parent = self,
+                          message = _("Unable to create profile of "
                                     "raster map."),
-                          caption=_("Error"), style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
+                          caption = _("Error"), style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
             return False
 
         if not hasattr (self, "profileFrame"):
@@ -480,8 +494,8 @@
 
         if not self.profileFrame:
             self.profileFrame = profile.ProfileFrame(self.mapdisplay,
-                                                     id=wx.ID_ANY, pos=wx.DefaultPosition, size=(700,300),
-                                                     style=wx.DEFAULT_FRAME_STYLE, rasterList=[mapLayer.GetName()])
+                                                     id = wx.ID_ANY, pos = wx.DefaultPosition, size = (700,300),
+                                                     style = wx.DEFAULT_FRAME_STYLE, rasterList = [mapLayer.GetName()])
             # show new display
             self.profileFrame.Show()
         
@@ -499,10 +513,10 @@
         """
         mapLayer = self.GetPyData(self.layer_selected)[0]['maplayer']
         if not mapLayer.GetName():
-            wx.MessageBox(parent=self,
-                          message=_("Unable to display histogram of "
+            wx.MessageBox(parent = self,
+                          message = _("Unable to display histogram of "
                                     "raster map."),
-                          caption=_("Error"), style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
+                          caption = _("Error"), style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
             return False
 
         if not hasattr (self, "histogramFrame"):
@@ -513,9 +527,9 @@
 
         if not self.histogramFrame:
             self.histogramFrame = histogram.HistFrame(self,
-                                                      id=wx.ID_ANY,
-                                                      pos=wx.DefaultPosition, size=globalvar.HIST_WINDOW_SIZE,
-                                                      style=wx.DEFAULT_FRAME_STYLE)
+                                                      id = wx.ID_ANY,
+                                                      pos = wx.DefaultPosition, size = globalvar.HIST_WINDOW_SIZE,
+                                                      style = wx.DEFAULT_FRAME_STYLE)
             self.histogramFrame.CentreOnScreen()
             # show new display
             self.histogramFrame.Show()
@@ -549,7 +563,7 @@
                                    style = wx.YES_NO | wx.CENTRE)
             if dlg.ShowModal() == wx.ID_YES:
                 self.lmgr.goutput.RunCmd(['v.digit', 'map=%s' % maplayer.GetName()],
-                                         switchPage=False)
+                                         switchPage = False)
             
             dlg.Destroy()
             return
@@ -560,27 +574,38 @@
             pass
 
         # mark layer as 'edited'
-        self.mapdisplay.toolbars['vdigit'].StartEditing (maplayer)
-
+        self.mapdisplay.toolbars['vdigit'].StartEditing(maplayer)
+        
+        self._setGradient('vdigit')
+        self.RefreshLine(self.layer_selected)
+        
     def OnStopEditing(self, event):
+        """!Stop editing the current vector map layer
         """
-        Stop editing the current vector map layer
-        """
         maplayer = self.GetPyData(self.layer_selected)[0]['maplayer']
         
         self.mapdisplay.toolbars['vdigit'].OnExit()
         self.mapdisplay.imgVectorMap = None
         
+        self._setGradient()
+        self.RefreshLine(self.layer_selected)
+        
     def OnSetBgMap(self, event):
         """!Set background vector map for editing sesstion"""
         if event.IsChecked():
             mapName = self.GetPyData(self.layer_selected)[0]['maplayer'].GetName()
-            UserSettings.Set(group='vdigit', key='bgmap', subkey='value',
-                             value=str(mapName), internal=True)
+            UserSettings.Set(group = 'vdigit', key = 'bgmap', subkey = 'value',
+                             value = str(mapName), internal = True)
+            self.mapdisplay.digit.OpenBackgroundMap(mapName)
+            self._setGradient('bgmap')
         else:
-            UserSettings.Set(group='vdigit', key='bgmap', subkey='value',
-                             value='', internal=True)
+            UserSettings.Set(group = 'vdigit', key = 'bgmap', subkey = 'value',
+                             value = '', internal = True)
+            self.mapdisplay.digit.CloseBackgroundMap()
+            self._setGradient()
         
+        self.RefreshLine(self.layer_selected)
+
     def OnPopupProperties (self, event):
         """!Popup properties dialog"""
         self.PropertiesDialog(self.layer_selected)
@@ -593,8 +618,8 @@
         maplayer = self.GetPyData(self.layer_selected)[0]['maplayer']
         current_opacity = maplayer.GetOpacity()
         
-        dlg = gdialogs.SetOpacityDialog(self, opacity=current_opacity,
-                                        title=_("Set opacity <%s>") % maplayer.GetName())
+        dlg = gdialogs.SetOpacityDialog(self, opacity = current_opacity,
+                                        title = _("Set opacity <%s>") % maplayer.GetName())
         dlg.CentreOnParent()
 
         if dlg.ShowModal() == wx.ID_OK:
@@ -641,8 +666,8 @@
         
         event.Skip()
 
-    def AddLayer(self, ltype, lname=None, lchecked=None,
-                 lopacity=1.0, lcmd=None, lgroup=None, lvdigit=None, lnviz=None, multiple = True):
+    def AddLayer(self, ltype, lname = None, lchecked = None,
+                 lopacity = 1.0, lcmd = None, lgroup = None, lvdigit = None, lnviz = None, multiple = True):
         """!Add new item to the layer tree, create corresponding MapLayer instance.
         Launch property dialog if needed (raster, vector, etc.)
 
@@ -671,16 +696,16 @@
 
         # deselect active item
         if self.layer_selected:
-            self.SelectItem(self.layer_selected, select=False)
+            self.SelectItem(self.layer_selected, select = False)
         
         Debug.msg (3, "LayerTree().AddLayer(): ltype=%s" % (ltype))
         
         if ltype == 'command':
             # generic command item
-            ctrl = wx.TextCtrl(self, id=wx.ID_ANY, value='',
-                               pos=wx.DefaultPosition, size=(self.GetSize()[0]-100,25),
-                               # style=wx.TE_MULTILINE|wx.TE_WORDWRAP)
-                               style=wx.TE_PROCESS_ENTER | wx.TE_DONTWRAP)
+            ctrl = wx.TextCtrl(self, id = wx.ID_ANY, value = '',
+                               pos = wx.DefaultPosition, size = (self.GetSize()[0]-100,25),
+                               # style = wx.TE_MULTILINE|wx.TE_WORDWRAP)
+                               style = wx.TE_PROCESS_ENTER | wx.TE_DONTWRAP)
             ctrl.Bind(wx.EVT_TEXT_ENTER, self.OnCmdChanged)
             # ctrl.Bind(wx.EVT_TEXT,       self.OnCmdChanged)
         elif ltype == 'group':
@@ -690,7 +715,7 @@
             self.groupnode += 1
         else:
             btnbmp = Icons["layeropts"].GetBitmap((16,16))
-            ctrl = buttons.GenBitmapButton(self, id=wx.ID_ANY, bitmap=btnbmp, size=(24,24))
+            ctrl = buttons.GenBitmapButton(self, id = wx.ID_ANY, bitmap = btnbmp, size = (24,24))
             ctrl.SetToolTipString(_("Click to edit layer settings"))
             self.Bind(wx.EVT_BUTTON, self.OnLayerContextMenu, ctrl)
         # add layer to the layer tree
@@ -698,29 +723,29 @@
             if self.GetPyData(self.layer_selected)[0]['type'] == 'group' \
                 and self.IsExpanded(self.layer_selected):
                 # add to group (first child of self.layer_selected) if group expanded
-                layer = self.PrependItem(parent=self.layer_selected,
-                                         text='', ct_type=1, wnd=ctrl)
+                layer = self.PrependItem(parent = self.layer_selected,
+                                         text = '', ct_type = 1, wnd = ctrl)
             else:
                 # prepend to individual layer or non-expanded group
                 if lgroup == -1:
                     # -> last child of root (loading from workspace)
-                    layer = self.AppendItem(parentId=self.root,
-                                            text='', ct_type=1, wnd=ctrl)
+                    layer = self.AppendItem(parentId = self.root,
+                                            text = '', ct_type = 1, wnd = ctrl)
                 elif lgroup > -1:
                     # -> last child of group (loading from workspace)
                     parent = self.FindItemByIndex(index = lgroup)
                     if not parent:
                         parent = self.root
-                    layer = self.AppendItem(parentId=parent,
-                                            text='', ct_type=1, wnd=ctrl)
+                    layer = self.AppendItem(parentId = parent,
+                                            text = '', ct_type = 1, wnd = ctrl)
                 elif lgroup is None:
                     # -> previous sibling of selected layer
                     parent = self.GetItemParent(self.layer_selected)
-                    layer = self.InsertItem(parentId=parent,
-                                            input=self.GetPrevSibling(self.layer_selected),
-                                            text='', ct_type=1, wnd=ctrl)
+                    layer = self.InsertItem(parentId = parent,
+                                            input = self.GetPrevSibling(self.layer_selected),
+                                            text = '', ct_type = 1, wnd = ctrl)
         else: # add first layer to the layer tree (first child of root)
-            layer = self.PrependItem(parent=self.root, text='', ct_type=1, wnd=ctrl)
+            layer = self.PrependItem(parent = self.root, text = '', ct_type = 1, wnd = ctrl)
 
         # layer is initially unchecked as inactive (beside 'command')
         # use predefined value if given
@@ -729,10 +754,10 @@
         else:
             checked = True
 
-        self.CheckItem(layer, checked=checked)
+        self.CheckItem(layer, checked = checked)
 
         # select new item
-        self.SelectItem(layer, select=True)
+        self.SelectItem(layer, select = True)
         self.layer_selected = layer
         
         # add text and icons for each layer ltype
@@ -831,15 +856,15 @@
                 else: 
                     pos = -1
             
-            maplayer = self.Map.AddLayer(pos=pos,
-                                         type=ltype, command=self.GetPyData(layer)[0]['cmd'], name=name,
-                                         l_active=checked, l_hidden=False,
-                                         l_opacity=lopacity, l_render=render)
+            maplayer = self.Map.AddLayer(pos = pos,
+                                         type = ltype, command = self.GetPyData(layer)[0]['cmd'], name = name,
+                                         l_active = checked, l_hidden = False,
+                                         l_opacity = lopacity, l_render = render)
             self.GetPyData(layer)[0]['maplayer'] = maplayer
 
             # run properties dialog if no properties given
             if len(cmd) == 0:
-                self.PropertiesDialog(layer, show=True)
+                self.PropertiesDialog(layer, show = True)
         
         else: # group
             self.SetPyData(layer, ({'cmd'      : None,
@@ -861,11 +886,11 @@
         
         # updated progress bar range (mapwindow statusbar)
         if checked is True:
-            self.mapdisplay.statusbarWin['progress'].SetRange(len(self.Map.GetListOfLayers(l_active=True)))
+            self.mapdisplay.statusbarWin['progress'].SetRange(len(self.Map.GetListOfLayers(l_active = True)))
             
         return layer
 
-    def PropertiesDialog (self, layer, show=True):
+    def PropertiesDialog (self, layer, show = True):
         """!Launch the properties dialog"""
         if self.GetPyData(layer)[0].has_key('propwin') and \
                 self.GetPyData(layer)[0]['propwin'] is not None:
@@ -890,68 +915,68 @@
         if self.GetPyData(layer)[0]['cmd']:
             module = menuform.GUI()
             module.ParseCommand(self.GetPyData(layer)[0]['cmd'],
-                                completed=(self.GetOptData,layer,params),
-                                parentframe=self, show=show, centreOnParent = False)
+                                completed = (self.GetOptData,layer,params),
+                                parentframe = self, show = show, centreOnParent = False)
             
             self.GetPyData(layer)[0]['cmd'] = module.GetCmd()
         elif ltype == 'raster':
             cmd = ['d.rast']
             
-            if UserSettings.Get(group='cmd', key='rasterOpaque', subkey='enabled'):
+            if UserSettings.Get(group = 'cmd', key = 'rasterOpaque', subkey = 'enabled'):
                 cmd.append('-n')
-            menuform.GUI().ParseCommand(cmd, completed=(self.GetOptData,layer,params),
-                                        parentframe=self, centreOnParent = False)
+            menuform.GUI().ParseCommand(cmd, completed = (self.GetOptData,layer,params),
+                                        parentframe = self, centreOnParent = False)
         elif ltype == '3d-raster':
             cmd = ['d.rast3d']
-            menuform.GUI().ParseCommand(cmd, completed=(self.GetOptData,layer,params),
-                                        parentframe=self, centreOnParent = False)
+            menuform.GUI().ParseCommand(cmd, completed = (self.GetOptData,layer,params),
+                                        parentframe = self, centreOnParent = False)
         elif ltype == 'rgb':
-            menuform.GUI().ParseCommand(['d.rgb'], completed=(self.GetOptData,layer,params),
-                                        parentframe=self, centreOnParent = False)
+            menuform.GUI().ParseCommand(['d.rgb'], completed = (self.GetOptData,layer,params),
+                                        parentframe = self, centreOnParent = False)
         elif ltype == 'his':
-            menuform.GUI().ParseCommand(['d.his'], completed=(self.GetOptData,layer,params),
-                                        parentframe=self, centreOnParent = False)
+            menuform.GUI().ParseCommand(['d.his'], completed = (self.GetOptData,layer,params),
+                                        parentframe = self, centreOnParent = False)
         elif ltype == 'shaded':
-            menuform.GUI().ParseCommand(['d.shadedmap'], completed=(self.GetOptData,layer,params),
-                                        parentframe=self, centreOnParent = False)
+            menuform.GUI().ParseCommand(['d.shadedmap'], completed = (self.GetOptData,layer,params),
+                                        parentframe = self, centreOnParent = False)
         elif ltype == 'rastarrow':
-            menuform.GUI().ParseCommand(['d.rast.arrow'], completed=(self.GetOptData,layer,params),
-                                        parentframe=self, centreOnParent = False)
+            menuform.GUI().ParseCommand(['d.rast.arrow'], completed = (self.GetOptData,layer,params),
+                                        parentframe = self, centreOnParent = False)
         elif ltype == 'rastnum':
-            menuform.GUI().ParseCommand(['d.rast.num'], completed=(self.GetOptData,layer,params),
-                                        parentframe=self, centreOnParent = False)
+            menuform.GUI().ParseCommand(['d.rast.num'], completed = (self.GetOptData,layer,params),
+                                        parentframe = self, centreOnParent = False)
         elif ltype == 'vector':
             types = ''
-            for type in UserSettings.Get(group='cmd', key='showType').keys():
-                if UserSettings.Get(group='cmd', key='showType', subkey=[type, 'enabled']):
+            for type in UserSettings.Get(group = 'cmd', key = 'showType').keys():
+                if UserSettings.Get(group = 'cmd', key = 'showType', subkey = [type, 'enabled']):
                     types += type + ','
             types = types.rstrip(',')
             
             menuform.GUI().ParseCommand(['d.vect', 'type=%s' % types],
-                                         completed=(self.GetOptData,layer,params),
-                                         parentframe=self, centreOnParent = False)
+                                         completed = (self.GetOptData,layer,params),
+                                         parentframe = self, centreOnParent = False)
         elif ltype == 'thememap':
             # -s flag requested, otherwise only first thematic category is displayed
             # should be fixed by C-based d.thematic.* modules
             menuform.GUI().ParseCommand(['d.thematic.area'], 
-                                        completed=(self.GetOptData,layer,params),
-                                        parentframe=self, centreOnParent = False)
+                                        completed = (self.GetOptData,layer,params),
+                                        parentframe = self, centreOnParent = False)
         elif ltype == 'themechart':
             menuform.GUI().ParseCommand(['d.vect.chart'],
-                                        completed=(self.GetOptData,layer,params),
-                                        parentframe=self, centreOnParent = False)
+                                        completed = (self.GetOptData,layer,params),
+                                        parentframe = self, centreOnParent = False)
         elif ltype == 'grid':
-            menuform.GUI().ParseCommand(['d.grid'], completed=(self.GetOptData,layer,params),
-                                        parentframe=self, centreOnParent = False)
+            menuform.GUI().ParseCommand(['d.grid'], completed = (self.GetOptData,layer,params),
+                                        parentframe = self, centreOnParent = False)
         elif ltype == 'geodesic':
-            menuform.GUI().ParseCommand(['d.geodesic'], completed=(self.GetOptData,layer,params),
-                                        parentframe=self, centreOnParent = False)
+            menuform.GUI().ParseCommand(['d.geodesic'], completed = (self.GetOptData,layer,params),
+                                        parentframe = self, centreOnParent = False)
         elif ltype == 'rhumb':
-            menuform.GUI().ParseCommand(['d.rhumbline'], completed=(self.GetOptData,layer,params),
-                                        parentframe=self, centreOnParent = False)
+            menuform.GUI().ParseCommand(['d.rhumbline'], completed = (self.GetOptData,layer,params),
+                                        parentframe = self, centreOnParent = False)
         elif ltype == 'labels':
-            menuform.GUI().ParseCommand(['d.labels'], completed=(self.GetOptData,layer,params),
-                                        parentframe=self, centreOnParent = False)
+            menuform.GUI().ParseCommand(['d.labels'], completed = (self.GetOptData,layer,params),
+                                        parentframe = self, centreOnParent = False)
         elif ltype == 'cmdlayer':
             pass
         elif ltype == 'group':
@@ -1004,10 +1029,10 @@
         self.reorder = True
         
         if self.mapdisplay.toolbars['vdigit']:
-            self.mapdisplay.toolbars['vdigit'].UpdateListOfLayers (updateTool=True)
+            self.mapdisplay.toolbars['vdigit'].UpdateListOfLayers (updateTool = True)
 
         # update progress bar range (mapwindow statusbar)
-        self.mapdisplay.statusbarWin['progress'].SetRange(len(self.Map.GetListOfLayers(l_active=True)))
+        self.mapdisplay.statusbarWin['progress'].SetRange(len(self.Map.GetListOfLayers(l_active = True)))
 
         event.Skip()
 
@@ -1041,7 +1066,7 @@
         #
         # update progress bar range (mapwindow statusbar)
         #
-        self.mapdisplay.statusbarWin['progress'].SetRange(len(self.Map.GetListOfLayers(l_active=True)))
+        self.mapdisplay.statusbarWin['progress'].SetRange(len(self.Map.GetListOfLayers(l_active = True)))
 
         #
         # nviz
@@ -1103,6 +1128,17 @@
             event.Veto()
             return
         
+        digitToolbar = self.mapdisplay.toolbars['vdigit']
+        mapLayer = self.GetPyData(layer)[0]['maplayer']
+        bgmap = UserSettings.Get(group = 'vdigit', key = 'bgmap', subkey = 'value',
+                                 internal = True)
+        if digitToolbar and digitToolbar.GetLayer() == mapLayer:
+            self._setGradient('vdigit')
+        elif bgmap == mapLayer.GetName():
+            self._setGradient('bgmap')
+        else:
+            self._setGradient()
+        
         self.layer_selected = layer
         
         try:
@@ -1117,21 +1153,21 @@
                 self.SetItemWindowEnabled(layer, False)
         except:
             pass
-
+        
         try:
             self.RefreshLine(oldlayer)
             self.RefreshLine(layer)
         except:
             pass
-
+        
         #
         # update statusbar -> show command string
         #
         if self.GetPyData(layer) and self.GetPyData(layer)[0]['maplayer']:
-            cmd = self.GetPyData(layer)[0]['maplayer'].GetCmd(string=True)
+            cmd = self.GetPyData(layer)[0]['maplayer'].GetCmd(string = True)
             if len(cmd) > 0:
                 self.lmgr.SetStatusText(cmd)
-
+        
         # set region if auto-zooming is enabled
         if self.GetPyData(layer) and self.GetPyData(layer)[0]['cmd'] and \
                UserSettings.Get(group = 'display', key = 'autoZooming', subkey = 'enabled'):
@@ -1203,7 +1239,7 @@
             (child, cookie) = self.GetFirstChild(dragItem)
             if child:
                 while child:
-                    self.RecreateItem(child, dropTarget, parent=newItem)
+                    self.RecreateItem(child, dropTarget, parent = newItem)
                     self.Delete(child)
                     child = self.GetNextChild(old, cookie)[0]
             #self.Expand(newItem)
@@ -1225,7 +1261,7 @@
         # select new item
         self.SelectItem(newItem)
         
-    def RecreateItem (self, dragItem, dropTarget, parent=None):
+    def RecreateItem (self, dragItem, dropTarget, parent = None):
         """!Recreate item (needed for OnEndDrag())
         """
         Debug.msg (4, "LayerTree.RecreateItem(): layer=%s" % \
@@ -1238,7 +1274,7 @@
         if self.GetPyData(dragItem)[0]['ctrl']:
             # recreate data layer
             btnbmp = Icons["layeropts"].GetBitmap((16,16))
-            newctrl = buttons.GenBitmapButton(self, id=wx.ID_ANY, bitmap=btnbmp, size=(24, 24))
+            newctrl = buttons.GenBitmapButton(self, id = wx.ID_ANY, bitmap = btnbmp, size = (24, 24))
             newctrl.SetToolTipString(_("Click to edit layer settings"))
             self.Bind(wx.EVT_BUTTON, self.OnLayerContextMenu, newctrl)
             data    = self.GetPyData(dragItem)
@@ -1246,11 +1282,11 @@
         elif self.GetPyData(dragItem)[0]['type'] == 'command':
             # recreate command layer
             oldctrl = None
-            newctrl = wx.TextCtrl(self, id=wx.ID_ANY, value='',
-                                  pos=wx.DefaultPosition, size=(250,25),
-                                  style=wx.TE_MULTILINE|wx.TE_WORDWRAP)
+            newctrl = wx.TextCtrl(self, id = wx.ID_ANY, value = '',
+                                  pos = wx.DefaultPosition, size = (250,25),
+                                  style = wx.TE_MULTILINE|wx.TE_WORDWRAP)
             try:
-                newctrl.SetValue(self.GetPyData(dragItem)[0]['maplayer'].GetCmd(string=True))
+                newctrl.SetValue(self.GetPyData(dragItem)[0]['maplayer'].GetCmd(string = True))
             except:
                 pass
             newctrl.Bind(wx.EVT_TEXT_ENTER, self.OnCmdChanged)
@@ -1273,27 +1309,27 @@
 
             # dragItem dropped on group
             if  self.GetPyData(afteritem)[0]['type'] == 'group':
-                newItem = self.PrependItem(afteritem, text=text, \
-                                      ct_type=1, wnd=newctrl, image=image, \
-                                      data=data)
+                newItem = self.PrependItem(afteritem, text = text, \
+                                      ct_type = 1, wnd = newctrl, image = image, \
+                                      data = data)
                 self.Expand(afteritem)
             else:
                 #dragItem dropped on single layer
                 newparent = self.GetItemParent(afteritem)
                 newItem = self.InsertItem(newparent, self.GetPrevSibling(afteritem), \
-                                       text=text, ct_type=1, wnd=newctrl, \
-                                       image=image, data=data)
+                                       text = text, ct_type = 1, wnd = newctrl, \
+                                       image = image, data = data)
         else:
             # if dragItem not dropped on a layer or group, append or prepend it to the layer tree
             if self.flag & wx.TREE_HITTEST_ABOVE:
-                newItem = self.PrependItem(self.root, text=text, \
-                                      ct_type=1, wnd=newctrl, image=image, \
-                                      data=data)
+                newItem = self.PrependItem(self.root, text = text, \
+                                      ct_type = 1, wnd = newctrl, image = image, \
+                                      data = data)
             elif (self.flag &  wx.TREE_HITTEST_BELOW) or (self.flag & wx.TREE_HITTEST_NOWHERE) \
                      or (self.flag & wx.TREE_HITTEST_TOLEFT) or (self.flag & wx.TREE_HITTEST_TORIGHT):
-                newItem = self.AppendItem(self.root, text=text, \
-                                      ct_type=1, wnd=newctrl, image=image, \
-                                      data=data)
+                newItem = self.AppendItem(self.root, text = text, \
+                                      ct_type = 1, wnd = newctrl, image = image, \
+                                      data = data)
 
         #update new layer 
         self.SetPyData(newItem, self.GetPyData(dragItem))
@@ -1302,7 +1338,7 @@
         else:
             self.GetPyData(newItem)[0]['ctrl'] = None
             
-        self.CheckItem(newItem, checked=checked) # causes a new render
+        self.CheckItem(newItem, checked = checked) # causes a new render
 
         # newItem.SetHeight(TREE_ITEM_HEIGHT)
 
@@ -1386,8 +1422,8 @@
                     mapWin.LoadVector(layer)
 
                 # reset view when first layer loaded
-                nlayers = len(mapWin.Map.GetListOfLayers(l_type=('raster', 'vector'),
-                                                         l_active=True))
+                nlayers = len(mapWin.Map.GetListOfLayers(l_type = ('raster', 'vector'),
+                                                         l_active = True))
                 if nlayers < 2:
                     mapWin.ResetView()
         
@@ -1442,23 +1478,23 @@
         elif type != 'group':
             if self.GetPyData(item)[0] is not None:
                 cmdlist = self.GetPyData(item)[0]['cmd']
-                opac = self.GetPyData(item)[0]['maplayer'].GetOpacity(float=True)
+                opac = self.GetPyData(item)[0]['maplayer'].GetOpacity(float = True)
                 chk = self.IsItemChecked(item)
                 hidden = not self.IsVisible(item)
                 # determine layer name
-                layerName = utils.GetLayerNameFromCmd(cmdlist, fullyQualified=True)
+                layerName = utils.GetLayerNameFromCmd(cmdlist, fullyQualified = True)
                 if not layerName:
                     layerName = self.GetItemText(item)
         
-        maplayer = self.Map.ChangeLayer(layer=self.GetPyData(item)[0]['maplayer'], type=type,
-                                        command=cmdlist, name=layerName,
-                                        l_active=chk, l_hidden=hidden, l_opacity=opac, l_render=False)
+        maplayer = self.Map.ChangeLayer(layer = self.GetPyData(item)[0]['maplayer'], type = type,
+                                        command = cmdlist, name = layerName,
+                                        l_active = chk, l_hidden = hidden, l_opacity = opac, l_render = False)
         
         self.GetPyData(item)[0]['maplayer'] = maplayer
         
         # if digitization tool enabled -> update list of available vector map layers
         if self.mapdisplay.toolbars['vdigit']:
-            self.mapdisplay.toolbars['vdigit'].UpdateListOfLayers(updateTool=True)
+            self.mapdisplay.toolbars['vdigit'].UpdateListOfLayers(updateTool = True)
         
         # redraw map if auto-rendering is enabled
         self.rerender = True
@@ -1494,7 +1530,7 @@
         
         return None
     
-    def EnableItemType(self, type, enable=True):
+    def EnableItemType(self, type, enable = True):
         """!Enable/disable items in layer tree"""
         item = self.GetFirstChild(self.root)[0]
         while item and item.IsOk():

Modified: grass/trunk/gui/wxpython/gui_modules/mapdisp_window.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/mapdisp_window.py	2011-01-10 15:53:26 UTC (rev 44942)
+++ grass/trunk/gui/wxpython/gui_modules/mapdisp_window.py	2011-01-10 19:06:52 UTC (rev 44943)
@@ -1654,7 +1654,7 @@
         if digitToolbar.GetAction() in ("moveVertex",
                                         "editLine"):
             if len(digitClass.GetDisplay().GetSelected()) == 0:
-                nselected = digitClass.GetDisplay().SelectLineByPoint(pos1)
+                nselected = digitClass.GetDisplay().SelectLineByPoint(pos1)['point']
                 
                 if digitToolbar.GetAction() == "editLine":
                     try:
@@ -1688,7 +1688,7 @@
                                           "copyAttrs"):
             if not hasattr(self, "copyCatsIds"):
                 # 'from' -> select by point
-                nselected = digitClass.GetDisplay().SelectLineByPoint(pos1)
+                nselected = digitClass.GetDisplay().SelectLineByPoint(pos1)['point']
                 if nselected:
                     self.copyCatsList = digitClass.GetDisplay().GetSelected()
             else:
@@ -1776,7 +1776,7 @@
         
         pos1 = self.Pixel2Cell(self.mouse['begin'])
         
-        pointOnLine = digitClass.GetDisplay().SelectLineByPoint(pos1)
+        pointOnLine = digitClass.GetDisplay().SelectLineByPoint(pos1)['point']
         if not pointOnLine:
             return
 
@@ -1824,7 +1824,7 @@
                 self.UpdateMap(render = False, renderVector = False)
         else:
             # copy features from background map
-            self.copyIds += digitClass.SelectLinesFromBackgroundMap(pos1, pos2)
+            self.copyIds += digitClass.SelectLinesFromBackgroundMap(bbox = (pos1, pos2))
             if len(self.copyIds) > 0:
                 color = UserSettings.Get(group = 'vdigit', key = 'symbol',
                                          subkey = ['highlight', 'color'])

Modified: grass/trunk/gui/wxpython/gui_modules/wxvdigit.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/wxvdigit.py	2011-01-10 15:53:26 UTC (rev 44942)
+++ grass/trunk/gui/wxpython/gui_modules/wxvdigit.py	2011-01-10 19:06:52 UTC (rev 44943)
@@ -112,6 +112,10 @@
         """
         self.poMapInfo   = None      # pointer to Map_info
         self.mapWindow = mapwindow
+
+        # background map
+        self.bgMapInfo   = Map_info()
+        self.poBgMapInfo = self.popoBgMapInfo = None
         
         if not mapwindow.parent.IsStandalone():
             goutput = mapwindow.parent.GetLayerManager().GetLogWindow()
@@ -162,10 +166,20 @@
         Vect_destroy_cats_struct(self.poCats)
         self.poCats = None
         
-    def _setCategory(self):
-        pass
-    
-    def _openBackgroundMap(self, bgmap):
+        if self.poBgMapInfo:
+            Vect_close(self.poBgMapInfo)
+            self.poBgMapInfo = self.popoBgMapInfo = None
+            del self.bgMapInfo
+        
+    def CloseBackgroundMap(self):
+        """!Close background vector map"""
+        if not self.poBgMapInfo:
+            return
+        
+        Vect_close(self.poBgMapInfo)
+        self.poBgMapInfo = self.popoBgMapInfo = None
+        
+    def OpenBackgroundMap(self, bgmap):
         """!Open background vector map
 
         @todo support more background maps then only one
@@ -175,25 +189,28 @@
         @return pointer to map_info
         @return None on error
         """
-        name = c_char()
-        mapset = c_char()
-        if not G__name_is_fully_qualified(bgmap, byref(name), byref(mapset)):
-            name = bgmap
-            mapset = G_find_vector2(bgmap, '')
+        name   = create_string_buffer(GNAME_MAX)
+        mapset = create_string_buffer(GMAPSET_MAX)
+        if not G_name_is_fully_qualified(bgmap, name, mapset):
+            name   = str(bgmap)
+            mapset = str(G_find_vector2(bgmap, ''))
         else:
-            name = name.value
-            mapset = mapset.value
-
+            name   = str(name.value)
+            mapset = str(mapset.value)
+        
         if (name == Vect_get_name(self.poMapInfo) and \
                 mapset == Vect_get_mapset(self.poMapInfo)):
-            return None
-
-        bgMapInfo = map_info()
-	if Vect_open_old(byref(bgMapInfo), name, mapset) == -1:
-            return None
+            self.poBgMapInfo = self.popoBgMapInfo = None
+            self._error.NoMap(bgmap)
+            return
         
-        return pointer(bgMapInfo)
-
+        self.poBgMapInfo = pointer(self.bgMapInfo)
+        self.popoBgMapInfo = pointer(self.poBgMapInfo)
+	if Vect_open_old(self.poBgMapInfo, name, mapset) == -1:
+            self.poBgMapInfo = self.popoBgMapInfo = None
+            self._error.NoMap(bgmap)
+            return
+        
     def _getSnapMode(self):
         """!Get snapping mode
 
@@ -226,6 +243,51 @@
                 self._addActionToChangeset(changeset, line, add = False)
         
         return changeset
+
+    def _applyChangeset(self, changeset, undo):
+        """!Apply changeset (undo/redo changeset)
+        
+        @param changeset changeset id
+        @param undo True for undo otherwise redo
+
+        @return 1 changeset applied
+        @return 0 changeset not applied
+        @return -1 on error
+        """
+        if changeset < 0 or changeset > len(self.changesets.keys()):
+            return -1
+        
+        if self.changesetEnd < 0:
+            self.changesetEnd = changeset
+            
+        ret = 0
+        actions = self.changesets[changeset]
+        for action in actions: 
+            add = action['add']
+            line = action['line']
+            if (undo and add) or \
+                    (not undo and not add):
+                if Vect_line_alive(self.poMapInfo, line):
+                    Debug.msg(3, "IVDigit._applyChangeset(): changeset=%d, action=add, line=%d -> deleted",
+                              changeset, line)
+                    Vect_delete_line(self.poMapInfo, line)
+                    ret = 1
+                else:
+                    Debug.msg(3, "Digit.ApplyChangeset(): changeset=%d, action=add, line=%d dead",
+                              changeset, line)
+            else: # delete
+                offset = action['offset']
+                if not Vect_line_alive(self.poMapInfo, line):
+                    Debug.msg(3, "Digit.ApplyChangeset(): changeset=%d, action=delete, line=%d -> added",
+                              changeset, line)
+                    if Vect_restore_line(self.poMapInfo, line, offset) < 0:
+                        return -1
+                    ret = 1
+                else:
+                    Debug.msg(3, "Digit.ApplyChangeset(): changeset=%d, action=delete, line=%d alive",
+                              changeset, line)
+        
+        return ret
     
     def _addActionsAfter(self, changeset, nlines):
         """!Register action after operation
@@ -260,16 +322,13 @@
             self.changesets[changeset] = list()
             self.changesetCurrent = changeset
         
-        self.changesets[changeset].append({ 'type'   : type,
+        self.changesets[changeset].append({ 'add'    : add,
                                             'line'   : line,
                                             'offset' : offset })
         
         Debug.msg(3, "IVDigit._addActionToChangeset(): changeset=%d, type=%d, line=%d, offset=%d",
                   changeset, type, line, offset)
         
-    def _applyChangeset(self):
-        pass
-
     def _removeActionFromChangeset(self, changeset, line, add):
         """!Remove action from changeset
         
@@ -285,7 +344,7 @@
         
         alist = self.changesets[changeset] 
         for action in alist:
-            if action['type'] == type and action['line'] == line:
+            if action['add'] == add and action['line'] == line:
                 alist.remove(action)
         
         return len(alist)
@@ -305,9 +364,6 @@
             layer = UserSettings.Get(group = 'vdigit', key = "layer", subkey = 'value')
             cat   = self.cats.get(layer, 1)
         
-        bgmap = str(UserSettings.Get(group = 'vdigit', key = 'bgmap',
-                                     subkey = 'value', internal = True))
-        
         if ftype == 'point':
             vtype = GV_POINT
         elif ftype == 'line':
@@ -329,7 +385,7 @@
         self.toolbar.EnableUndo()
         
         return self._addFeature(vtype, points, layer, cat,
-                                bgmap, self._getSnapMode(), self._display.GetThreshold())
+                                self._getSnapMode(), self._display.GetThreshold())
     
     def DeleteSelectedLines(self):
         """!Delete selected features
@@ -432,25 +488,13 @@
         thresh = self._display.GetThreshold()
         snap   = self._getSnapMode()
         
-        bgmap = str(UserSettings.Get(group='vdigit', key="bgmap",
-                                     subkey='value', internal=True))
-        
-        poBgMapInfo = None
-        nbgmaps     = 0
-        if bgmap:
-            poBgMapInfo = self._openBackgroundMap(bgmap)
-            if not pobgMapInfo:
-                self._error.NoMap(bgmap)
-                return -1
-            nbgmaps = 1
-        
         nlines = Vect_get_num_lines(self.poMapInfo)
         
         # register changeset
         changeset = self._addActionsBefore()
         
         poList = self._display.GetSelectedIList()
-        nlines = Vedit_move_lines(self.poMapInfo, poBgMapInfo, nbgmaps,
+        nlines = Vedit_move_lines(self.poMapInfo, self.popoBgMapInfo, int(self.poBgMapInfo is not None),
                                   poList,
                                   move[0], move[1], 0,
                                   snap, thresh)
@@ -465,9 +509,6 @@
             for i in range(1, nlines):
                 self._breakLineAtIntersection(nlines + i, None, changeset)
         
-        if poBgMapInfo:
-            Vect_close(poBgMapInfo)
-        
         if nlines > 0:
             self.toolbar.EnableUndo()
         
@@ -488,20 +529,7 @@
         
         if len(self._display.selected['ids']) != 1:
             return -1
-                
-        bgmap = str(UserSettings.Get(group='vdigit', key="bgmap",
-                                     subkey='value', internal=True))
         
-        # try to open background map if asked
-        poBgMapInfo = None
-        nbgmaps     = 0
-        if bgmap:
-            poBgMapInfo = self._openBackgroundMap(bgmap)
-            if not poBgMapInfo:
-                self._error.NoMap(bgmap)
-                return -1
-            nbgmaps = 1
-        
         Vect_reset_line(self.poPoints)
         Vect_append_point(self.poPoints, point[0], point[1], 0.0)
         
@@ -511,7 +539,7 @@
         
         # move only first found vertex in bbox 
         poList = self._display.GetSelectedIList()
-        moved = Vedit_move_vertex(self.poMapInfo, poBgMapInfo, nbgmaps,
+        moved = Vedit_move_vertex(self.poMapInfo, self.popoBgMapInfo, int(self.poBgMapInfo is not None),
                                   poList, self.poPoints,
                                   self._display.GetThreshold(type = 'selectThresh'),
                                   self._display.GetThreshold(),
@@ -528,9 +556,6 @@
             self._breakLineAtIntersection(Vect_get_num_lines(self.poMapInfo),
                                           None, changeset)
         
-        if poBgMapInfo:
-            Vect_close(poBgMapInfo)
-        
         if moved > 0:
             self.toolbar.EnableUndo()
         
@@ -623,9 +648,6 @@
             self.DeleteSelectedLines()
             return 0
         
-        bgmap = str(UserSettings.Get(group='vdigit', key="bgmap",
-                                     subkey='value', internal=True))
-        
         ret = self.digit.RewriteLine(lineid, listCoords,
                                      bgmap, self._getSnapMode(),
                                      self._display.GetThreshold())
@@ -764,7 +786,7 @@
         
         return ret
         
-    def CopyLine(self, ids=[]):
+    def CopyLine(self, ids = []):
         """!Copy features from (background) vector map
 
         @param ids list of line ids to be copied
@@ -772,17 +794,28 @@
         @return number of copied features
         @return -1 on error
         """
-        bgmap = str(UserSettings.Get(group='vdigit', key='bgmap',
-                                     subkey='value', internal=True))
+        if not self._checkMap():
+            return -1
         
-        if len(bgmap) > 0:
-            ret = self.digit.CopyLines(ids, bgmap)
-        else:
-            ret = self.digit.CopyLines(ids, None)
-
+        nlines = Vect_get_num_lines(self.poMapInfo)
+        
+        poList = self._display.GetSelectedIList(ids)
+        ret = Vedit_copy_lines(self.poMapInfo, self.poBgMapInfo,
+                               poList)
+        Vect_destroy_list(poList)
+        
         if ret > 0:
+            changeset = len(self.changesets)
+            for line in (range(nlines + 1, Vect_get_num_lines(self.poMapInfo))):
+                self._addActionToChangeset(changeset, line, add = True)
             self.toolbar.EnableUndo()
+        else:
+            del self.changesets[changeset]
 
+        if ret > 0 and self.poBgMapInfo and self.settings['breakLines']:
+            for i in range(1, ret):
+                self._breakLineAtIntersection(nlines + i, None, changeset)
+        
         return ret
 
     def CopyCats(self, fromId, toId, copyAttrb=False):
@@ -977,17 +1010,47 @@
 
         @return id of current changeset
         """
-        try:
-            ret = self.digit.Undo(level)
-        except SystemExit:
-            ret = -2
+        changesetLast = len(self.changesets.keys()) - 1
 
-        if ret == -2:
-            raise gcmd.GException(_("Undo failed, data corrupted."))
+        if changesetLast < 0:
+            return changesetLast
+        
+        if self.changesetCurrent == -2: # value uninitialized 
+            self.changesetCurrent = changesetLast
+            
+        if level > 0 and self.changesetCurrent < 0:
+            self.changesetCurrent = 0
+        
+        if level == 0:
+            # 0 -> undo all
+            level = -1 * changesetLast + 1
 
-        self.mapWindow.UpdateMap(render=False)
+        Debug.msg(2, "Digit.Undo(): changeset_last=%d, changeset_current=%d, level=%d",
+                  changesetLast, self.changesetCurrent, level)
+    
+        if level < 0: # undo
+            if self.changesetCurrent + level < -1:
+                return changesetCurrent;
+            for changeset in range(self.changesetCurrent, self.changesetCurrent + level, -1):
+                self._applyChangeset(changeset, undo = True)
+        elif level > 0: # redo 
+            if self.changesetCurrent + level > len(self.changesets.keys()):
+                return self.changesetCurrent
+            for changeset in range(self.changesetCurrent, self.changesetCurrent + level):
+                self._applyChangeset(changeset, undo = False)
         
-        if ret < 0: # disable undo tool
+        self.changesetCurrent += level
+
+        Debug.msg(2, "Digit.Undo(): changeset_current=%d, changeset_last=%d, changeset_end=%d",
+                  self.changesetCurrent, changesetLast, self.changesetEnd)
+        
+        if self.changesetCurrent == self.changesetEnd:
+            self.changesetEnd = changesetLast
+            return -1
+        
+        self.mapWindow.UpdateMap(render = False)
+        
+        if self.changesetCurrent < 0: # disable undo tool
             self.toolbar.EnableUndo(False)
 
     def ZBulkLines(self, pos1, pos2, start, step):
@@ -1104,14 +1167,13 @@
         
         return True
 
-    def _addFeature(self, type, coords, layer, cat, bgmap, snap, threshold):
+    def _addFeature(self, type, coords, layer, cat, snap, threshold):
         """!Add new feature to the vector map
 
         @param type feature type (GV_POINT, GV_LINE, GV_BOUNDARY, ...)
         @coords tuple of coordinates ((x, y), (x, y), ...)
         @param layer layer number (-1 for no cat)
         @param cat category number
-        @param bgmap name of background vector map (None for no background) to be used for snapping
         @param snap snap to node/vertex
         @param threshold threshold for snapping
         
@@ -1129,16 +1191,6 @@
         if not (type & (GV_POINTS | GV_LINES)): # TODO: 3D
             return -1
         
-        # try to open background map if asked
-        poBgMapInfo = None
-        nbgmaps     = 0
-        if bgmap:
-            poBgMapInfo = self._openBackgroundMap(bgmap)
-            if not poBgMapInfo:
-                self._error.NoMap(bgmap)
-                return -1
-            nbgmaps = 1
-        
         # set category
         Vect_reset_cats(self.poCats)
         if layer > 0 and \
@@ -1166,7 +1218,7 @@
         if snap != NO_SNAP and (type & (GV_POINT | GV_LINES)):
             # apply snapping (node or vertex)
             modeSnap = not (snap == SNAP)
-            Vedit_snap_line(self.poMapInfo, poBgMapInfo, nbgmaps,
+            Vedit_snap_line(self.poMapInfo, self.popoBgMapInfo, int(self.poBgMapInfo is not None),
                             -1, self.poPoints, threshold, modeSnap)
         
         newline = Vect_write_line(self.poMapInfo, type, self.poPoints, self.poCats)
@@ -1223,53 +1275,13 @@
         if self.settings['breakLines']:
             self._breakLineAtIntersection(newline, self.poPoints, changeset)
         
-        # close background map if opened
-        if poBgMapInfo:
-            Vect_close(poBgMapInfo)
-        
         if type & GV_BOUNDARY and \
                 not self.settings['catBoundary'] and \
         	left < 1 and right < 1:
             newline = None # ?
         
         return newline
-
-    def RewriteLine(self):
-        pass
     
-    def DeleteLines(self):
-        pass
-
-    def MoveLines(self):
-        pass
-
-    def FlipLines(self):
-        pass
-
-    def MergeLines(self):
-        pass
-
-    def BreakLines(self):
-        pass
-
-    def SnapLines(self):
-        pass
-
-    def ConnectLines(self):
-        pass
-
-    def TypeConvLines(self):
-        pass
-
-    def ZBulkLabeling(self):
-        pass
-
-    def CopyLines(self):
-        pass
-
-    def MoveVertex(self):
-        pass
-
     def _ModifyLineVertex(self, coords, add = True):
         """!Add or remove vertex
         
@@ -1317,18 +1329,6 @@
                 
         return nlines + 1 # feature is write at the end of the file
     
-    def GetLineLength(self):
-        pass
-
-    def GetAreaSize(self):
-        pass
-
-    def GetAreaPerimeter(self):
-        pass
-
-    def CopyCats(self):
-        pass
-    
     def GetLineCats(self, line):
         """!Get list of layer/category(ies) for selected feature.
 
@@ -1363,9 +1363,6 @@
         
         return ret
 
-    def SetLineCats(self):
-        pass
-    
     def GetLayers(self):
         """!Get list of layers
         
@@ -1375,12 +1372,6 @@
         """
         return self.cats.keys()
     
-    def Undo(self):
-        pass
-
-    def GetUndoLevel(self):
-        pass
-
     def UpdateSettings(self, breakLines, addCentroid, catBoundary):
         """!Update digit settings
         
@@ -1411,4 +1402,27 @@
         cat += 1
         UserSettings.Set(group = 'vdigit', key = 'category', subkey = 'value',
                          value = cat)
+
+    def SelectLinesFromBackgroundMap(self, bbox):
+        """!Select features from background map
+
+        @param bbox bounding box definition
         
+        @return list of selected feature ids
+        """
+        ret = list()
+        
+        # try select features by Box
+        ids = self._display.SelectLinesByBox(bbox, poMapInfo = self.poBgMapInfo)
+        if not ids:
+            ids = [self._display.SelectLineByPoint(bbox[0], poMapInfo = self.poBgMapInfo)['line'], ]
+        
+        return ids
+
+    def GetUndoLevel(self):
+        """!Get undo level (number of active changesets)
+        
+        Note: Changesets starts wiht 0
+        """
+        return self.changesetCurrent
+    

Modified: grass/trunk/gui/wxpython/gui_modules/wxvdriver.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/wxvdriver.py	2011-01-10 15:53:26 UTC (rev 44942)
+++ grass/trunk/gui/wxpython/gui_modules/wxvdriver.py	2011-01-10 19:06:52 UTC (rev 44943)
@@ -140,8 +140,6 @@
         
         self.UpdateSettings()
         
-        Vect_set_fatal_error(GV_FATAL_PRINT)
-        
     def __del__(self):
         """!Close currently open vector map"""
         G_unset_error_routine()
@@ -463,7 +461,20 @@
         
         return ftype
 
-    def SelectLinesByBox(self, bbox, drawSeg = False):
+    def _validLine(self, line):
+        """!Check if feature id is valid
+
+        @param line feature id
+
+        @return True valid feature id
+        @return False invalid
+        """
+        if line > 0 and line <= Vect_get_num_lines(self.poMapInfo):
+            return True
+        
+        return False
+    
+    def SelectLinesByBox(self, bbox, drawSeg = False, poMapInfo = None):
         """!Select vector objects by given bounding box
         
         If line id is already in the list of selected lines, then it will
@@ -471,30 +482,41 @@
         
         @param bbox bounding box definition
         @param drawSeg True to draw segments of line
-        
+        @param poMapInfo use external Map_info, None for self.poMapInfo
+
         @return number of selected features
-        @return -1 on error
+        @return None on error
         """
-        if not self.poMapInfo:
-            return -1
+        thisMapInfo = poMapInfo is None
+        if not poMapInfo:
+            poMapInfo = self.poMapInfo
         
-        self.drawSegments = drawSeg
-        self.drawSelected = True
+        if not poMapInfo:
+            return None
         
-        # select by ids
-        self.selected['cats'] = list()
+        if thisMapInfo:
+            self.drawSegments = drawSeg
+            self.drawSelected = True
         
+            # select by ids
+            self.selected['cats'] = list()
+        
+        if thisMapInfo:
+            selected = self.selected['ids']
+        else:
+            selected = list()
+        
         poList = Vect_new_list()
-        poBbox = Vect_new_line_struct()
         x1, y1 = bbox[0]
         x2, y2 = bbox[1]
+        poBbox = Vect_new_line_struct()
         Vect_append_point(poBbox, x1, y1, 0.0)
         Vect_append_point(poBbox, x2, y1, 0.0)
         Vect_append_point(poBbox, x2, y2, 0.0)
         Vect_append_point(poBbox, x1, y2, 0.0)
         Vect_append_point(poBbox, x1, y1, 0.0)
         
-        Vect_select_lines_by_polygon(self.poMapInfo, poBbox,
+        Vect_select_lines_by_polygon(poMapInfo, poBbox,
                                      0, None, # isles
                                      self._getSelectType(), poList)
         
@@ -505,28 +527,30 @@
             if UserSettings.Get(group = 'vdigit', key = 'selectInside',
                                 subkey = 'enabled'):
                 inside = True
-                Vect_read_line(self.poMapInfo, self.poPoints, None, line)
-                points = poPoints.contents
+                if not self._validLine(line):
+                    return None
+                Vect_read_line(poMapInfo, self.poPoints, None, line)
+                points = self.poPoints.contents
                 for p in range(points.n_points):
                     if not Vect_point_in_poly(points.x[p], points.y[p],
-                                              byref(bbox)):
+                                              poBbox):
                         inside = False
                         break
                     
                 if not inside:
                     continue # skip lines just overlapping bbox
-        
+            
             if not self._isSelected(line):
-                self.selected['ids'].append(line)
+                selected.append(line)
             else:
-                self.selected['ids'].remove(line)
+                del selected[line]
         
         Vect_destroy_line_struct(poBbox)
         Vect_destroy_list(poList)
         
-        return nlines
+        return len(selected)
 
-    def SelectLineByPoint(self, point):
+    def SelectLineByPoint(self, point, poMapInfo = None):
         """!Select vector feature by given point in given
         threshold
    
@@ -534,29 +558,46 @@
         all segments are stores.
         
         @param point points coordinates (x, y)
-        
-        @return point on line if line found
+        @param poMapInfo use external Map_info, None for self.poMapInfo
+
+        @return dict {'line' : feature id, 'point' : point on line}
+        @return None nothing found
         """
-        self.drawSelected = True
+        thisMapInfo = poMapInfo is None
+        if not poMapInfo:
+            poMapInfo = self.poMapInfo
         
+        if not poMapInfo:
+            return None
+
+        if thisMapInfo:
+            self.drawSelected = True
+            # select by ids 
+            self.selected['cats'] = list()
+        
+        if thisMapInfo:
+            selected = self.selected['ids']
+        else:
+            selected = list()
+        
         poFound = Vect_new_list()
-        # select by ids 
-        self.selected['cats'] = list()
         
-        line_nearest = Vect_find_line_list(self.poMapInfo, point[0], point[1], 0,
+        line_nearest = Vect_find_line_list(poMapInfo, point[0], point[1], 0,
                                            self._getSelectType(), self.GetThreshold(), self.is3D,
                                            None, poFound)
         
         if line_nearest > 0:
             if not self._isSelected(line_nearest):
-                self.selected['ids'].append(line_nearest)
+                selected.append(line_nearest)
             else:
-                self.selected['ids'].remove(line_nearest)
+                del selected[line_nearest]
         
         px = c_double()
         py = c_double()
         pz = c_double()
-	ftype = Vect_read_line(self.poMapInfo, self.poPoints, self.poCats, line_nearest)
+        if not self._validLine(line_nearest):
+            return None
+	ftype = Vect_read_line(poMapInfo, self.poPoints, self.poCats, line_nearest)
 	Vect_line_distance (self.poPoints, point[0], point[1], 0.0, self.is3D,
 			    byref(px), byref(py), byref(pz),
 			    None, None, None)
@@ -567,22 +608,24 @@
 	    for i in range(found.n_values):
 		line = found.value[i]
 		if line != line_nearest:
-                    self.selected['ids'].append(line)
+                    selected.append(line)
 	    
             self.getDuplicates()
 	    
 	    for i in range(found.n_values):
 		line = found.value[i]
 		if line != line_nearest and not self._isDuplicated(line):
-                    self.selected['ids'].remove(line)
+                    del selected[line]
         
         Vect_destroy_list(poFound)
         
-        # drawing segments can be very expensive
-        # only one features selected
-        self.drawSegments = True
+        if thisMapInfo:
+            # drawing segments can be very expensive
+            # only one features selected
+            self.drawSegments = True
         
-        return (px.value, py.value, pz.value)
+        return { 'line'  : line_nearest,
+                 'point' : (px.value, py.value, pz.value) }
     
     def _listToIList(self, plist):
         """!Generate from list struct_ilist
@@ -593,13 +636,16 @@
         
         return ilist
         
-    def GetSelectedIList(self):
+    def GetSelectedIList(self, ilist = None):
         """!Get list of selected objects as struct_ilist
 
         Returned IList must be freed by Vect_destroy_list().
         
         @return struct_ilist
         """
+        if ilist:
+            return self._listToIList(ilist)
+        
         return self._listToIList(self.selected['ids'])
         
     def GetSelected(self, grassId = True):
@@ -670,6 +716,8 @@
         startId = 1
         line = self.selected['ids'][0]
         
+        if not self._validLine(line):
+            return -1
         ftype = Vect_read_line(self.poMapInfo, self.poPoints, self.poCats, line)
         
         minDist = 0.0
@@ -756,12 +804,8 @@
             self.mapInfo = Map_info()
             self.poMapInfo = pointer(self.mapInfo)
         
-        # avoid GUI crash when G_fatal_error() is called (opening the vector map)
-        Vect_set_fatal_error(GV_FATAL_PRINT)
-        
         # open existing map
         if update:
-            print >> sys.stderr, name, mapset
             ret = Vect_open_update(self.poMapInfo, name, mapset)
         else:
             ret = Vect_open_old(self.poMapInfo, name, mapset)



More information about the grass-commit mailing list