[GRASS-SVN] r45931 - in grass/branches/releasebranch_6_4: gui/icons gui/icons/grass2 gui/images gui/scripts gui/tcltk/gis.m gui/wxpython gui/wxpython/docs gui/wxpython/gui_modules gui/wxpython/icons gui/wxpython/scripts gui/wxpython/support gui/wxpython/xml lib/init

svn_grass at osgeo.org svn_grass at osgeo.org
Wed Apr 13 05:30:47 EDT 2011


Author: martinl
Date: 2011-04-13 02:30:47 -0700 (Wed, 13 Apr 2011)
New Revision: 45931

Added:
   grass/branches/releasebranch_6_4/gui/icons/grass.menu
   grass/branches/releasebranch_6_4/gui/icons/grass.xpm
   grass/branches/releasebranch_6_4/gui/icons/grass2/boundary-create.png
   grass/branches/releasebranch_6_4/gui/icons/grass2/edit.png
   grass/branches/releasebranch_6_4/gui/icons/grass2/map-info.png
   grass/branches/releasebranch_6_4/gui/icons/grass2/map-settings.png
   grass/branches/releasebranch_6_4/gui/icons/grass2/page-settings.png
   grass/branches/releasebranch_6_4/gui/icons/grass2/ps-export.png
   grass/branches/releasebranch_6_4/gui/icons/grass2/script-load.png
   grass/branches/releasebranch_6_4/gui/icons/grass2/script-save.png
   grass/branches/releasebranch_6_4/gui/images/grass_form.png
   grass/branches/releasebranch_6_4/gui/images/loc_wizard.png
   grass/branches/releasebranch_6_4/gui/images/loc_wizard_qgis.png
   grass/branches/releasebranch_6_4/gui/images/qgis_world.png
   grass/branches/releasebranch_6_4/gui/images/silesia_splash.png
   grass/branches/releasebranch_6_4/gui/images/small_down_arrow.png
   grass/branches/releasebranch_6_4/gui/images/small_up_arrow.png
   grass/branches/releasebranch_6_4/gui/images/startup_banner.gif
   grass/branches/releasebranch_6_4/gui/scripts/g.extension.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/mapdisp_vdigit.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/wxvdigit.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/wxvdriver.py
Removed:
   grass/branches/releasebranch_6_4/gui/images/gintro.gif
   grass/branches/releasebranch_6_4/gui/wxpython/images/
   grass/branches/releasebranch_6_4/gui/wxpython/vdigit/
Modified:
   grass/branches/releasebranch_6_4/gui/images/Makefile
   grass/branches/releasebranch_6_4/gui/scripts/r.recode.file
   grass/branches/releasebranch_6_4/gui/tcltk/gis.m/gm.tcl
   grass/branches/releasebranch_6_4/gui/tcltk/gis.m/gmmenu.tcl
   grass/branches/releasebranch_6_4/gui/tcltk/gis.m/vector.tcl
   grass/branches/releasebranch_6_4/gui/wxpython/Makefile
   grass/branches/releasebranch_6_4/gui/wxpython/README
   grass/branches/releasebranch_6_4/gui/wxpython/docs/Makefile
   grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI.GCP_Manager.html
   grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI.Vector_Digitizer.html
   grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI.html
   grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI_layer_manager.jpg
   grass/branches/releasebranch_6_4/gui/wxpython/gis_set.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/__init__.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/dbm.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/dbm_base.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/dbm_dialogs.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/debug.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gcmd.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gcpmanager.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gcpmapdisp.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gdialogs.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/ghelp.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/globalvar.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gmodeler.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/goutput.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gselect.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/histogram.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/layertree.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/location_wizard.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/mapdisp.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/mapdisp_window.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/menu.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/menudata.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/menuform.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/nviz_mapdisp.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/nviz_tools.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/ogc_services.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/preferences.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/profile.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/prompt.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/render.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/toolbars.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/utils.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/vdigit.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/workspace.py
   grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/wxnviz.py
   grass/branches/releasebranch_6_4/gui/wxpython/icons/grass2_icons.py
   grass/branches/releasebranch_6_4/gui/wxpython/icons/grass_icons.py
   grass/branches/releasebranch_6_4/gui/wxpython/icons/icon.py
   grass/branches/releasebranch_6_4/gui/wxpython/icons/silk_icons.py
   grass/branches/releasebranch_6_4/gui/wxpython/scripts/Makefile
   grass/branches/releasebranch_6_4/gui/wxpython/support/update_menudata.py
   grass/branches/releasebranch_6_4/gui/wxpython/wxgui.py
   grass/branches/releasebranch_6_4/gui/wxpython/wxpythonlib.dox
   grass/branches/releasebranch_6_4/gui/wxpython/xml/menudata.xml
   grass/branches/releasebranch_6_4/lib/init/gis_set.tcl
Log:
wxGUI: major update for 6.4.2 (backport from devbr6)


Added: grass/branches/releasebranch_6_4/gui/icons/grass.menu
===================================================================
--- grass/branches/releasebranch_6_4/gui/icons/grass.menu	                        (rev 0)
+++ grass/branches/releasebranch_6_4/gui/icons/grass.menu	2011-04-13 09:30:47 UTC (rev 45931)
@@ -0,0 +1,5 @@
+?package(grass):needs="text"\
+  section="Applications/Science/Geoscience"\
+  title="GRASS GIS"\
+  command="/usr/bin/grass64"\
+  icon="grass.xpm"

Added: grass/branches/releasebranch_6_4/gui/icons/grass.xpm
===================================================================
(Binary files differ)


Property changes on: grass/branches/releasebranch_6_4/gui/icons/grass.xpm
___________________________________________________________________
Added: svn:mime-type
   + image/xpm

Added: grass/branches/releasebranch_6_4/gui/icons/grass2/boundary-create.png
===================================================================
(Binary files differ)


Property changes on: grass/branches/releasebranch_6_4/gui/icons/grass2/boundary-create.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass/branches/releasebranch_6_4/gui/icons/grass2/edit.png
===================================================================
(Binary files differ)


Property changes on: grass/branches/releasebranch_6_4/gui/icons/grass2/edit.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass/branches/releasebranch_6_4/gui/icons/grass2/map-info.png
===================================================================
(Binary files differ)


Property changes on: grass/branches/releasebranch_6_4/gui/icons/grass2/map-info.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass/branches/releasebranch_6_4/gui/icons/grass2/map-settings.png
===================================================================
(Binary files differ)


Property changes on: grass/branches/releasebranch_6_4/gui/icons/grass2/map-settings.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass/branches/releasebranch_6_4/gui/icons/grass2/page-settings.png
===================================================================
(Binary files differ)


Property changes on: grass/branches/releasebranch_6_4/gui/icons/grass2/page-settings.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass/branches/releasebranch_6_4/gui/icons/grass2/ps-export.png
===================================================================
(Binary files differ)


Property changes on: grass/branches/releasebranch_6_4/gui/icons/grass2/ps-export.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass/branches/releasebranch_6_4/gui/icons/grass2/script-load.png
===================================================================
(Binary files differ)


Property changes on: grass/branches/releasebranch_6_4/gui/icons/grass2/script-load.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass/branches/releasebranch_6_4/gui/icons/grass2/script-save.png
===================================================================
(Binary files differ)


Property changes on: grass/branches/releasebranch_6_4/gui/icons/grass2/script-save.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Modified: grass/branches/releasebranch_6_4/gui/images/Makefile
===================================================================
--- grass/branches/releasebranch_6_4/gui/images/Makefile	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/images/Makefile	2011-04-13 09:30:47 UTC (rev 45931)
@@ -1,9 +1,21 @@
 MODULE_TOPDIR = ../..
 
-include $(MODULE_TOPDIR)/include/Make/Dir.make
+include $(MODULE_TOPDIR)/include/Make/Platform.make
+include $(MODULE_TOPDIR)/include/Make/Grass.make
+include $(MODULE_TOPDIR)/include/Make/Rules.make
 
-default:
-	if [ ! -d $(ETC)/gui ] ; then $(MKDIR) $(ETC)/gui ; fi
-	if [ ! -d $(ETC)/gui/images ] ; then $(MKDIR) $(ETC)/gui/images ; fi
-	$(INSTALL_DATA) gintro.gif $(ETC)/gui/images/gintro.gif
+ETCDIR = $(ETC)/gui/images
 
+FILES := $(wildcard *.png)
+FILES += $(wildcard *.gif)
+
+default: $(patsubst %,$(ETCDIR)/%,$(FILES))
+
+$(ETCDIR)/%.png: %.png | $(ETCDIR)
+	$(INSTALL_DATA) $< $@
+
+$(ETCDIR)/%.gif: %.gif | $(ETCDIR)
+	$(INSTALL_DATA) $< $@
+
+$(ETCDIR):
+	$(MKDIR) $@

Deleted: grass/branches/releasebranch_6_4/gui/images/gintro.gif
===================================================================
(Binary files differ)

Added: grass/branches/releasebranch_6_4/gui/images/grass_form.png
===================================================================
(Binary files differ)


Property changes on: grass/branches/releasebranch_6_4/gui/images/grass_form.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass/branches/releasebranch_6_4/gui/images/loc_wizard.png
===================================================================
(Binary files differ)


Property changes on: grass/branches/releasebranch_6_4/gui/images/loc_wizard.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass/branches/releasebranch_6_4/gui/images/loc_wizard_qgis.png
===================================================================
(Binary files differ)


Property changes on: grass/branches/releasebranch_6_4/gui/images/loc_wizard_qgis.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass/branches/releasebranch_6_4/gui/images/qgis_world.png
===================================================================
(Binary files differ)


Property changes on: grass/branches/releasebranch_6_4/gui/images/qgis_world.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass/branches/releasebranch_6_4/gui/images/silesia_splash.png
===================================================================
(Binary files differ)


Property changes on: grass/branches/releasebranch_6_4/gui/images/silesia_splash.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass/branches/releasebranch_6_4/gui/images/small_down_arrow.png
===================================================================
(Binary files differ)


Property changes on: grass/branches/releasebranch_6_4/gui/images/small_down_arrow.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass/branches/releasebranch_6_4/gui/images/small_up_arrow.png
===================================================================
(Binary files differ)


Property changes on: grass/branches/releasebranch_6_4/gui/images/small_up_arrow.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: grass/branches/releasebranch_6_4/gui/images/startup_banner.gif
===================================================================
(Binary files differ)


Property changes on: grass/branches/releasebranch_6_4/gui/images/startup_banner.gif
___________________________________________________________________
Added: svn:mime-type
   + image/gif

Added: grass/branches/releasebranch_6_4/gui/scripts/g.extension.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/scripts/g.extension.py	                        (rev 0)
+++ grass/branches/releasebranch_6_4/gui/scripts/g.extension.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -0,0 +1,436 @@
+#!/usr/bin/env python
+
+############################################################################
+#
+# MODULE:       g.extension
+# AUTHOR(S):   	Markus Neteler
+#               Pythonized by Martin Landa
+# PURPOSE:      Tool to download and install extensions from GRASS Addons SVN into 
+#               local GRASS installation
+# COPYRIGHT:    (C) 2009-2011 by Markus Neteler, and 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.
+#
+# TODO: add sudo support where needed (i.e. check first permission to write into
+#       $GISBASE directory)
+#############################################################################
+
+#%module
+#% label: Tool to maintain the extensions in local GRASS installation.
+#% description: Downloads, installs extensions from GRASS Addons SVN repository into local GRASS installation or removes installed extensions.
+#% keywords: general
+#% keywords: installation
+#% keywords: extensions
+#%end
+
+#%option
+#% key: extension
+#% type: string
+#% key_desc: name
+#% description: Name of extension to install/remove
+#% required: no
+#%end
+#%option
+#% key: operation
+#% type: string
+#% description: Operation to be performed
+#% required: no
+#% options: add,remove
+#% answer: add
+#%end
+#%option
+#% key: svnurl
+#% type: string
+#% key_desc: url
+#% description: SVN Addons repository URL
+#% required: yes
+#% answer: https://svn.osgeo.org/grass/grass-addons
+#%end
+#%option
+#% key: prefix
+#% type: string
+#% key_desc: path
+#% description: Prefix where to install extension (ignored when flag -s is given)
+#% answer: $GRASS_ADDON_PATH
+#% required: yes
+#%end
+
+#%flag
+#% key: l
+#% description: List available modules in the GRASS Addons SVN repository
+#% guisection: Print
+#%end
+#%flag
+#% key: f
+#% description: List available modules in the GRASS Addons SVN repository including modules description
+#% guisection: Print
+#%end
+#%flag
+#% key: g
+#% description: List available modules in the GRASS Addons SVN repository (shell script style)
+#% guisection: Print
+#%end
+#%flag
+#% key: s
+#% description: Install system-wide (may need system administrator rights)
+#%end
+#%flag
+#% key: d
+#% description: Don't delete downloaded source code when installing new extension
+#%end
+#%flag
+#% key: i
+#% description: Don't install new extension, just compile it
+#%end
+
+import os
+import sys
+import re
+import atexit
+
+import urllib
+
+from grass.script import core as grass
+
+# temp dir
+remove_tmpdir = True
+tmpdir = grass.tempdir()
+
+def check():
+    for prog in ('svn', 'make', 'install', 'gcc'):
+        if not grass.find_program(prog, ['--help']):
+            grass.fatal(_("%s required. Please install '%s' first.") % (prog, prog))
+    
+def expand_module_class_name(c):
+    name = { 'd'   : 'display',
+             'db'  : 'database',
+             'g'   : 'general',
+             'i'   : 'imagery',
+             'm'   : 'misc',
+             'ps'  : 'postscript',
+             'p'   : 'paint',
+             'r'   : 'raster',
+             'r3'  : 'raster3D',
+             's'   : 'sites',
+             'v'   : 'vector',
+             'gui' : 'gui/wxpython' }
+    
+    if name.has_key(c):
+        return name[c]
+    
+    return c
+
+def list_available_modules(svnurl, full = False, shell = False):
+    mlist = list()
+    grass.message(_('Fetching list of modules from GRASS-Addons SVN (be patient)...'))
+    pattern = re.compile(r'(<li><a href=".+">)(.+)(</a></li>)', re.IGNORECASE)
+    i = 0
+    prefix = ['d', 'db', 'g', 'i', 'm', 'ps',
+              'p', 'r', 'r3', 's', 'v']
+    nprefix = len(prefix)
+    for d in prefix:
+        if shell:
+            grass.percent(i, nprefix, 1)
+            i += 1
+        
+        modclass = expand_module_class_name(d)
+        grass.verbose(_("Checking for '%s' modules...") % modclass)
+        
+        url = '%s/%s' % (svnurl, modclass)
+        grass.debug("url = %s" % url, debug = 2)
+        f = urllib.urlopen(url)
+        if not f:
+            grass.warning(_("Unable to fetch '%s'") % url)
+            continue
+        
+        for line in f.readlines():
+            # list modules
+            sline = pattern.search(line)
+            if not sline:
+                continue
+            name = sline.group(2).rstrip('/')
+            if name.split('.', 1)[0] == d:
+                print_module_desc(name, url, full, shell)
+                mlist.append(name)
+    
+    mlist += list_wxgui_extensions(svnurl, full, shell)
+    
+    if shell:
+        grass.percent(1, 1, 1)
+    
+    return mlist
+
+def list_wxgui_extensions(svnurl, full = False, shell = False, print_module = True):
+    mlist = list()
+    grass.debug('Fetching list of wxGUI extensions from GRASS-Addons SVN (be patient)...')
+    pattern = re.compile(r'(<li><a href=".+">)(.+)(</a></li>)', re.IGNORECASE)
+    grass.verbose(_("Checking for '%s' modules...") % 'gui/wxpython')
+    
+    url = '%s/%s' % (svnurl, 'gui/wxpython')
+    grass.debug("url = %s" % url, debug = 2)
+    f = urllib.urlopen(url)
+    if not f:
+        grass.warning(_("Unable to fetch '%s'") % url)
+        return
+        
+    for line in f.readlines():
+        # list modules
+        sline = pattern.search(line)
+        if not sline:
+            continue
+        name = sline.group(2).rstrip('/')
+        if name not in ('..', 'Makefile'):
+            if print_module:
+                print_module_desc(name, url, full, shell)
+            mlist.append(name)
+    
+    return mlist
+
+def print_module_desc(name, url, full = False, shell = False):
+    if not full and not shell:
+        print name
+        return
+    
+    if shell:
+        print 'name=' + name
+    
+    # check main.c first
+    desc = get_module_desc(url + '/' + name + '/' + name)
+    if not desc:
+        desc = get_module_desc(url + '/' + name + '/main.c', script = False)
+    if not desc:
+        if not shell:
+            print name + '-'
+            return
+    
+    if shell:
+        print 'description=' + desc.get('description', '')
+        print 'keywords=' + ','.join(desc.get('keywords', list()))
+    else:
+        print name + ' - ' + desc.get('description', '')
+    
+def get_module_desc(url, script = True):
+    grass.debug('url=%s' % url)
+    f = urllib.urlopen(url)
+    if script:
+        ret = get_module_script(f)
+    else:
+        ret = get_module_main(f)
+        
+    return ret
+
+def get_module_main(f):
+    if not f:
+        return dict()
+    
+    ret = { 'keyword' : list() }
+    
+    pattern = re.compile(r'(module.*->)(.+)(=)(.*)', re.IGNORECASE)
+    keyword = re.compile(r'(G_add_keyword\()(.+)(\);)', re.IGNORECASE)
+    
+    key   = ''
+    value = ''
+    for line in f.readlines():
+        line = line.strip()
+        find = pattern.search(line)
+        if find:
+            key = find.group(2).strip()
+            line = find.group(4).strip()
+        else:
+            find = keyword.search(line)
+            if find:
+                ret['keyword'].append(find.group(2).replace('"', '').replace('_(', '').replace(')', ''))
+        if key:
+            value += line
+            if line[-2:] == ');':
+                value = value.replace('"', '').replace('_(', '').replace(');', '')
+                if key == 'keywords':
+                    ret[key] = map(lambda x: x.strip(), value.split(','))
+                else:
+                    ret[key] = value
+                
+                key = value = ''
+    
+    return ret
+
+def get_module_script(f):
+    ret = dict()
+    if not f:
+        return ret
+    
+    begin = re.compile(r'#%.*module', re.IGNORECASE)
+    end   = re.compile(r'#%.*end', re.IGNORECASE)
+    mline = None
+    for line in f.readlines():
+        if not mline:
+            mline = begin.search(line)
+        if mline:
+            if end.search(line):
+                break
+            try:
+                key, value = line.split(':', 1)
+                key = key.replace('#%', '').strip()
+                value = value.strip()
+                if key == 'keywords':
+                    ret[key] = map(lambda x: x.strip(), value.split(','))
+                else:
+                    ret[key] = value
+            except ValueError:
+                pass
+    
+    return ret
+
+def cleanup():
+    global tmpdir, remove_tmpdir
+    if remove_tmpdir:
+        grass.try_rmdir(tmpdir)
+    else:
+        grass.info(_("Path to the source code: '%s'") % tmpdir)
+                        
+def install_extension(svnurl, prefix, module, no_install):
+    gisbase = os.getenv('GISBASE')
+    if not gisbase:
+        grass.fatal(_('$GISBASE not defined'))
+    
+    if grass.find_program(module):
+        grass.warning(_("Extension '%s' already installed. Will be updated...") % module)
+    
+    gui_list = list_wxgui_extensions(svnurl, print_module = False)
+
+    if module not in gui_list:
+        classchar = module.split('.', 1)[0]
+        moduleclass = expand_module_class_name(classchar)
+        url = svnurl + '/' + moduleclass + '/' + module
+    else:
+        url = svnurl + '/gui/wxpython/' + module
+        if not flags['s']:
+            grass.fatal(_("Installation of wxGUI extension requires -%s flag.") % 's')
+        
+    grass.message(_("Fetching '%s' from GRASS-Addons SVN (be patient)...") % module)
+    global tmpdir
+    os.chdir(tmpdir)
+    if grass.verbosity() == 0:
+        outdev = open(os.devnull, 'w')
+    else:
+        outdev = sys.stdout
+    
+    if grass.call(['svn', 'checkout',
+                   url], stdout = outdev) != 0:
+        grass.fatal(_("GRASS Addons '%s' not found in repository") % module)
+    
+    os.chdir(os.path.join(tmpdir, module))
+
+    grass.message(_("Compiling '%s'...") % module)    
+    if module not in gui_list:
+        bin_dir  = os.path.join(tmpdir, module, 'bin')
+        docs_dir = os.path.join(tmpdir, module, 'docs')
+        html_dir = os.path.join(docs_dir, 'html')
+        man_dir  = os.path.join(tmpdir, module, 'man')
+        man1_dir = os.path.join(man_dir, 'man1')
+        for d in (bin_dir, docs_dir, html_dir, man_dir, man1_dir):
+            os.mkdir(d)
+    
+        ret = grass.call(['make',
+                          'MODULE_TOPDIR=%s' % gisbase.replace(' ', '\ '),
+                          'BIN=%s' % bin_dir,
+                          'HTMLDIR=%s' % html_dir,
+                          'MANDIR=%s' % man1_dir],
+                         stdout = outdev)
+    else:
+        ret = grass.call(['make',
+                          'MODULE_TOPDIR=%s' % gisbase.replace(' ', '\ ')],
+                         stdout = outdev)
+    
+    if ret != 0:
+        grass.fatal(_('Compilation failed, sorry. Please check above error messages.'))
+    
+    if no_install or module in gui_list:
+        return
+    
+    grass.message(_("Installing '%s'...") % module)
+    
+    ret = grass.call(['make',
+                      'MODULE_TOPDIR=%s' % gisbase,
+                      'ARCH_DISTDIR=%s' % os.path.join(tmpdir, module),
+                      'INST_DIR=%s' % prefix,
+                      'install'],
+                     stdout = outdev)
+    
+    if ret != 0:
+        grass.warning(_('Installation failed, sorry. Please check above error messages.'))
+    else:
+        grass.message(_("Installation of '%s' successfully finished.") % module)
+
+def remove_extension(prefix, module):
+    # is module available?
+    if not os.path.exists(os.path.join(prefix, 'bin', module)):
+        grass.fatal(_("Module '%s' not found") % module)
+    
+    for file in [os.path.join(prefix, 'bin', module),
+                 os.path.join(prefix, 'scripts', module),
+                 os.path.join(prefix, 'docs', 'html', module + '.html')]:
+        if os.path.isfile(file):
+            os.remove(file)
+                    
+    grass.message(_("'%s' successfully uninstalled.") % module)
+
+def create_dir(path):
+    if os.path.isdir(path):
+        return
+    
+    try:
+        os.makedirs(path)
+    except OSError, e:
+        grass.fatal(_("Unable to create '%s': %s") % (path, e))
+    
+    grass.debug("'%s' created" % path)
+    
+def check_dirs():
+    create_dir(os.path.join(options['prefix'], 'bin'))
+    create_dir(os.path.join(options['prefix'], 'docs', 'html'))
+    create_dir(os.path.join(options['prefix'], 'man', 'man1'))
+
+def main():
+    # check dependecies
+    check()
+    
+    # list available modules
+    if flags['l'] or flags['f'] or flags['g']:
+        list_available_modules(options['svnurl'], full = flags['f'], shell = flags['g'])
+        return 0
+    else:
+        if not options['extension']:
+            grass.fatal(_('You need to define an extension name or use -l'))
+    
+    # define path
+    if flags['s']:
+        options['prefix'] = os.environ['GISBASE']
+    if options['prefix'] == '$GRASS_ADDON_PATH':
+        if not os.environ.has_key('GRASS_ADDON_PATH') or \
+                not os.environ['GRASS_ADDON_PATH']:
+            grass.warning(_("GRASS_ADDON_PATH is not defined, installing to ~/.grass7/addons/"))
+            options['prefix'] = os.path.join(os.environ['HOME'], '.grass7', 'addons')
+    
+    # check dirs
+    check_dirs()
+    
+    if flags['d']:
+        if options['operation'] != 'add':
+            grass.warning(_("Flag 'd' is relevant only to 'operation=add'. Ignoring this flag."))
+        else:
+            global remove_tmpdir
+            remove_tmpdir = False
+    
+    if options['operation'] == 'add':
+        install_extension(options['svnurl'], options['prefix'], options['extension'], flags['i'])
+    else: # remove
+        remove_extension(options['prefix'], options['extension'])
+    
+    return 0
+
+if __name__ == "__main__":
+    options, flags = grass.parser()
+    atexit.register(cleanup)
+    sys.exit(main())


Property changes on: grass/branches/releasebranch_6_4/gui/scripts/g.extension.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Modified: grass/branches/releasebranch_6_4/gui/scripts/r.recode.file
===================================================================
--- grass/branches/releasebranch_6_4/gui/scripts/r.recode.file	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/scripts/r.recode.file	2011-04-13 09:30:47 UTC (rev 45931)
@@ -15,7 +15,8 @@
 
 
 #%Module
-#%  description: r.recode.rules - Use ascii rules file to recode categories in raster map
+#%  description: r.recode.file - Use ascii rules file to recode categories in raster map
+#%  keywords: raster, recode
 #%End
 #%option
 #% key: input

Modified: grass/branches/releasebranch_6_4/gui/tcltk/gis.m/gm.tcl
===================================================================
--- grass/branches/releasebranch_6_4/gui/tcltk/gis.m/gm.tcl	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/tcltk/gis.m/gm.tcl	2011-04-13 09:30:47 UTC (rev 45931)
@@ -531,9 +531,28 @@
 }
 
 # Provides exit from gis.m. May also do some clean-up, save-settings et.al.
-proc Gm::quit { } {
+proc Gm::quit { {full_exit false} } {
 	global env
 	
+	if { $full_exit } {
+		if { [catch {set spid $env(GRASS_SHELL_PID)}] == 0 } {
+			set leave [tk_dialog .leave [G_msg "End current GRASS session"] \
+			[G_msg "Do You really want to terminate current\
+GRASS session?\n\nThis action will colse all sessions gis.m instances.\n\nIf You have running some \
+GRASS module from comandline, GRASS will terminate after it\
+finishes to run."] warning 1 [G_msg "Terminate current GRASS sesion"] [G_msg "Cancel"]]
+			if { $leave == 0 } { 
+				exec kill -SIGQUIT $env(GRASS_SHELL_PID)
+			} else { 
+				return
+			}
+		} else {
+			tk_messageBox -type ok -title [G_msg "Not supported"] -message \
+			[G_msg "We sorry. Your shell does not support this feature. \n\
+You have to type 'exit' in terminal manualy."]
+		}
+	}
+
 	# It's unsafe to call exit during Destroy event
 	after idle [list destroy .]
 }

Modified: grass/branches/releasebranch_6_4/gui/tcltk/gis.m/gmmenu.tcl
===================================================================
--- grass/branches/releasebranch_6_4/gui/tcltk/gis.m/gmmenu.tcl	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/tcltk/gis.m/gmmenu.tcl	2011-04-13 09:30:47 UTC (rev 45931)
@@ -202,6 +202,7 @@
 	}}
 	{command {[G_msg "PostScript plot"]} {} "ps.map: Create cartographic PostScript plot" {} -command { execute ps.map }}
 	{separator}
+	{command {[G_msg "Exit &GRASS"]} {} "End current GRASS session" {} -command { Gm::quit true } }
 	{command {[G_msg "&Quit GIS Manager"]} {} "Exit GIS Manager" {} -accelerator $keyctrl-Q -command { Gm::quit } }
  }
  {[G_msg "&Config"]} all options $tmenu {

Modified: grass/branches/releasebranch_6_4/gui/tcltk/gis.m/vector.tcl
===================================================================
--- grass/branches/releasebranch_6_4/gui/tcltk/gis.m/vector.tcl	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/tcltk/gis.m/vector.tcl	2011-04-13 09:30:47 UTC (rev 45931)
@@ -153,6 +153,8 @@
     set opt($count,1,symdir) "basic"
     set opt($count,1,icon) "basic/circle"
     set opt($count,1,size) 5 
+    set opt($count,1,sizecol) "" 
+    set opt($count,1,rotcol) "" 
 
     set opt($count,1,layer) 1 
     set opt($count,1,lfield) 1 
@@ -178,7 +180,7 @@
     			display_topo display_dir display_attr type_point \
 			type_line type_boundary type_centroid type_area \
 			type_face color _use_color fcolor _use_fcolor lcolor \
-			rdmcolor sqlcolor icon size lwidth \
+			rdmcolor sqlcolor icon size sizecol rotcol lwidth \
 			layer lfield attribute xref yref lsize cat where \
 			_use_where qmap qsave qoverwrite minreg maxreg }
                   
@@ -417,6 +419,15 @@
     pack $row.a $row.b $row.c $row.d $row.e -side left
     pack $row -side top -fill both -expand yes
 
+    set row [ frame $frm.icon_extra ]
+    LabelEntry $row.a -label [G_msg "Attribute column for size"] \
+		-textvariable GmVector::opt($id,1,sizecol) -width 25
+    LabelEntry $row.b -label [G_msg "Attribute column for rotation"] \
+		-textvariable GmVector::opt($id,1,rotcol) -width 23
+    pack $row.a $row.b -side top
+    pack $row -side top -fill both -expand yes
+
+
     # lines
     set row [ frame $frm.color ]
     Label $row.a -text [G_msg "Draw lines:"] 
@@ -694,6 +705,12 @@
     append cmd2 " type=$type"
 
     append cmd " icon=$opt($id,1,icon) size=$opt($id,1,size)" 
+    if { $opt($id,1,sizecol) != "" } {
+        append cmd " {size_column=$opt($id,1,sizecol)}"
+    }
+    if { $opt($id,1,rotcol) != "" } {
+        append cmd " {rot_column=$opt($id,1,rotcol)}"
+    }
 
     if { $opt($id,1,lwidth) != 1 } { 
         append cmd " width=$opt($id,1,lwidth)" 
@@ -840,7 +857,7 @@
 			display_dir display_attr type_point type_line \
 			type_boundary type_centroid type_area type_face \
 			color _use_color fcolor _use_fcolor lcolor rdmcolor \
-			sqlcolor icon size lwidth layer \
+			sqlcolor icon size sizecol rotcol lwidth layer \
 			lfield attribute xref yref lsize cat where \
 			_use_where qmap qsave qoverwrite minreg maxreg \
 			minreg maxreg }

Modified: grass/branches/releasebranch_6_4/gui/wxpython/Makefile
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/Makefile	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/Makefile	2011-04-13 09:30:47 UTC (rev 45931)
@@ -10,7 +10,7 @@
 
 ETCDIR = $(ETC)/wxpython
 
-SRCFILES := $(wildcard compat/* gui_modules/* icons/*.* icons/silk/* images/* xml/*) gis_set.py wxgui.py README
+SRCFILES := $(wildcard compat/* gui_modules/* icons/*.* icons/silk/* xml/*) gis_set.py wxgui.py README
 DSTFILES := $(patsubst %,$(ETCDIR)/%,$(SRCFILES)) $(patsubst %.py,$(ETCDIR)/%.pyc,$(filter %.py,$(SRCFILES)))
 
 default: install_scripts
@@ -19,7 +19,7 @@
 clean: cleansubdirs
 
 install_scripts:
-	-for dir in '' compat gui_modules icons icons/silk images xml; do \
+	-for dir in '' compat gui_modules icons icons/silk xml; do \
 	if [ ! -d $(ETCDIR)/$$dir ] ; then $(MKDIR) $(ETCDIR)/$$dir ; fi ; \
 	done
 	$(MAKE) $(DSTFILES)

Modified: grass/branches/releasebranch_6_4/gui/wxpython/README
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/README	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/README	2011-04-13 09:30:47 UTC (rev 45931)
@@ -1,22 +1,19 @@
-wxPython GRASS Graphical User Interface (wxGUI)
-===============================================
+GRASS GIS - wxPython Graphical User Interface (wxGUI)
+=====================================================
 
 $Date$
 
 1 - REQUIREMENTS
 
- GRASS GIS >= 6.3
- Python >= 2.4 (Python 3 not supported)
- 	Python ElementTree (only for Python <= 2.4)
- wxPython >= 2.8.1.1 (wxPython <= 2.8.9.2 requires swig <= 1.3.36)
- swig >= 1.3.31 (required for vector digitizer and nviz extension)
- NumPy >= 1.0.4
+ GRASS GIS >= 6.4
+ Python    >= 2.4 (Python 3 not supported)
+ 	Python ElementTree (only for Python 2.4)
+ wxPython  >= 2.8.1.1
+ NumPy     >= 1.0.4
  
  Get wxPython 2.8.x packages from:
  * Source: http://www.wxpython.org/download.php
  * Debian GNU/Linux: http://wiki.wxpython.org/InstallingOnUbuntuOrDebian
-		     [ deb http://apt.wxwidgets.org/ etch-wx main ]
-	             http://www.bitpim.org/developer.html -> "Install wxPython"
  * Fedora: http://www.wxpython.org/download.php
  * Mandriva: included in main distribution
  * OpenSuSe: http://download.opensuse.org/repositories/Application:/Geo/
@@ -55,20 +52,12 @@
 
 2 - STARTUP WITH GRASS INITIALIZATION
 
-If you want to launch wxPython GUI automatically when you start
-GRASS, edit your .grassrc6 file to replace
+If you want to launch wxPython GUI automatically, start GRASS with
+`-gui` parameter
 
-GRASS_GUI: tcltk (or whatever you have here)
+$ grass65 -gui
 
-with
 
-GRASS_GUI: wxpython
-
-or easier start new GRASS session with -wxpython switch.
-
-$ grass65 -wxpython
-
-
 3 - STARTUP FROM GRASS TERMINAL
 
 Simply run
@@ -82,8 +71,16 @@
 $ g.gui gui=wxpython workspace=myworkspace.gxw
 
 
-4 - CLI Display scripts
+4 - DEBUGGING
 
+To enable GUI debug messages on given level set WX_DEBUG environment
+variable, e.g.
+
+$ g.gisenv set="WX_DEBUG=3"
+
+
+5 - CLI Display scripts
+
 Note: This section is out-dated!
 
 This is going to be replacement for command line tools like d.rast and
@@ -128,22 +125,3 @@
 You should be able to zoom && pan through the map, once the layers are
 displayed. You should be also able to store the display content as well as
 clear the display and start from scratch.
-
-
-5 - DEBUGGING
-
-To enable GUI debug messages on given level set GRASS_DEBUG_WX
-environment variable, e.g.
-
-$ export GRASS_WX_DEBUG=3
-
-
-6 - VECTOR DIGITIZER
-
-To enable digitizer you need to compile 'vdigit' component. Note that
-you must configure GRASS with C++ (--with-cxx), Python (--with-python)
-and wxWidgets (--with-wxwidgets) support.
-
-$ cd gui/wxpython/vdigit
-$ make
-$ make install

Modified: grass/branches/releasebranch_6_4/gui/wxpython/docs/Makefile
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/docs/Makefile	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/docs/Makefile	2011-04-13 09:30:47 UTC (rev 45931)
@@ -1,12 +1,8 @@
 MODULE_TOPDIR = ../../..
 
-FILES = wxGUI \
-	wxGUI.Vector_Digitizer \
-	wxGUI.Attribute_Table_Manager \
-	wxGUI.Nviz \
-	wxGUI.Icons \
-	wxGUI.Modeler \
-	wxGUI.GCP_Manager
+HTML_SOURCES := $(wildcard *.html)
+HTML_FILES := $(filter-out $(wildcard *.tmp.html),$(HTML_SOURCES))
+FILES := $(subst .html,,$(HTML_FILES))
 
 include $(MODULE_TOPDIR)/include/Make/Platform.make
 include $(MODULE_TOPDIR)/include/Make/Grass.make

Modified: grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI.GCP_Manager.html
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI.GCP_Manager.html	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI.GCP_Manager.html	2011-04-13 09:30:47 UTC (rev 45931)
@@ -225,7 +225,7 @@
   </dl><br>
 </dd>
 
-<dt>
+<dt><img src="icons/grass2/help.png">&nbsp;
 <em>Show Help</em></dt>
 <dd>Show help page for the GCP Manager.
 

Modified: grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI.Vector_Digitizer.html
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI.Vector_Digitizer.html	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI.Vector_Digitizer.html	2011-04-13 09:30:47 UTC (rev 45931)
@@ -194,8 +194,8 @@
 <h2>NOTES</h2>
 
 <dl><dt><b>Mouse button Functions:</b><dd>
-	<dt><i>Left</i>    - select/deselect features</dt>
-	<dt><i>Middle</i> - cancel action</dt>
+	<dt><i>Left</i>   - select/deselect features</dt>
+	<dt><i>Control+Left</i> - cancel action/undo vertex</dt>
 	<dt><i>Right</i>  - confirm action</dt>
 </dl>
 

Modified: grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI.html
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI.html	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI.html	2011-04-13 09:30:47 UTC (rev 45931)
@@ -293,8 +293,15 @@
 
 <h4>Key shortcuts</h4>
 
-<b>Menu</b>
 <dl>
+  <dt>Ctrl+Tab</dt>
+  <dd>Switch 'Map layers' and 'Command output' tab</dd>
+  <dt>Ctrl+Q</dt>
+  <dd>Exit GUI</dd>
+</dl>
+
+<b>Worspace</b>
+<dl>
   <dt>Ctrl+N</dt>
   <dd>Create new workspace</dd>
   <dt>Ctrl+O</dt>
@@ -303,20 +310,12 @@
   <dd>Close workspace</dd>
   <dt>Ctrl+L</dt>
   <dd>Load map layers</dd>
-  <dt>Ctrl+W</dt>
-  <dd>Exit GUI</dd>
-  <dt>Ctrl+Q</dt>
-  <dd>Quit GRASS</dd>
-</dl>
-
-<b>Global</b>
-<dl>
-  <dt>Ctrl+Tab</dt>
-  <dd>Switch 'Map layers' and 'Command output' tab</dd>
   <dt>Ctrl+R</dt>
   <dd>Add raster map layer</dd>
   <dt>Ctrl+V</dt>
   <dd>Add vector map layer</dd>
+  <dt>Ctrl+W</dt>
+  <dd>Close current map display</dd>
 </dl>
 
 <b>Command line prompt</b>

Modified: grass/branches/releasebranch_6_4/gui/wxpython/docs/wxGUI_layer_manager.jpg
===================================================================
(Binary files differ)

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gis_set.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gis_set.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gis_set.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -26,6 +26,7 @@
 import shutil
 import copy
 import platform
+import codecs
 
 ### i18N
 import gettext
@@ -46,6 +47,8 @@
 import wx.lib.mixins.listctrl as listmix
 import wx.lib.scrolledpanel as scrolled
 
+sys.stderr = codecs.getwriter('utf8')(sys.stderr)
+
 class GRASSStartup(wx.Frame):
     """!GRASS start-up screen"""
     def __init__(self, parent = None, id = wx.ID_ANY, style = wx.DEFAULT_FRAME_STYLE):
@@ -54,7 +57,7 @@
         # GRASS variables
         #
         self.gisbase  = os.getenv("GISBASE")
-        self.grassrc  = self._read_grassrc()
+        self.grassrc  = self._readGisRC()
         self.gisdbase = self.GetRCValue("GISDBASE")
 
         #
@@ -79,7 +82,7 @@
         #
         # image
         try:
-            name = os.path.join(globalvar.ETCDIR, "gui", "images", "gintro.gif")
+            name = os.path.join(globalvar.ETCIMGDIR, "startup_banner.gif")
             self.hbitmap = wx.StaticBitmap(self.panel, wx.ID_ANY,
                                            wx.Bitmap(name = name,
                                                      type = wx.BITMAP_TYPE_GIF))
@@ -376,34 +379,34 @@
 
         self.Layout()
 
-    def _read_grassrc(self):
+    def _readGisRC(self):
         """
         Read variables from $HOME/.grassrc6 file
         """
 
         grassrc = {}
-
+        
         gisrc = os.getenv("GISRC")
-
+        
         if gisrc and os.path.isfile(gisrc):
             try:
                 rc = open(gisrc, "r")
                 for line in rc.readlines():
                     key, val = line.split(":", 1)
-                    grassrc[key.strip()] = val.strip()
+                    grassrc[key.strip()] = utils.DecodeString(val.strip())
             finally:
                 rc.close()
         
         return grassrc
 
     def GetRCValue(self, value):
-        "Return GRASS variable (read from GISRC)"""
-
+        """!Return GRASS variable (read from GISRC)
+        """
         if self.grassrc.has_key(value):
             return self.grassrc[value]
         else:
             return None
-
+        
     def OnWizard(self, event):
         """!Location wizard started"""
         from gui_modules import location_wizard
@@ -585,10 +588,10 @@
     def UpdateMapsets(self, location):
         """!Update list of mapsets"""
         self.FormerMapsetSelection = wx.NOT_FOUND # for non-selectable item
-
+        
         self.listOfMapsetsSelectable = list()
         self.listOfMapsets = utils.GetListOfMapsets(self.gisdbase, location)
-         
+        
         self.lbmapsets.Clear()
 
         # disable mapset with denied permission
@@ -602,10 +605,10 @@
                                   gisdbase = self.gisdbase)
             
             if not ret:
-                raise gcmd.CmdError("")
+                raise gcmd.GError(_("No mapsets available in location <%s>") % locationName)
             
             for line in ret.splitlines():
-                self.listOfMapsetsSelectable +=  line.split(' ')
+                self.listOfMapsetsSelectable += line.split(' ')
         except:
             gcmd.RunCommand("g.gisenv",
                             set = "GISDBASE=%s" % self.gisdbase)
@@ -619,7 +622,6 @@
         disabled = []
         idx = 0
         for mapset in self.listOfMapsets:
-            mapset = utils.UnicodeString(mapset)
             if mapset not in self.listOfMapsetsSelectable or \
                     os.path.isfile(os.path.join(self.gisdbase,
                                                 locationName,
@@ -641,7 +643,7 @@
                                             self.listOfLocations[self.lblocations.GetSelection()]))
         else:
             self.listOfMapsets = []
-
+        
         disabled = []
         idx = 0
         try:

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/__init__.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/__init__.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/__init__.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -40,4 +40,6 @@
     "vdigit.py",
     "workspace.py",
     "wxnviz.py",
+    "wxvdriver.py",
+    "wxvdigit.py",
 ]

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/dbm.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/dbm.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/dbm.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -826,7 +826,7 @@
             if onlyLayer > 0 and layer != onlyLayer:
                 continue
             
-            if not self.layerPage.has_key(layer):
+            if not layer in self.layerPage:
                 continue
             
             panel = wx.Panel(parent=self.manageTablePage, id=wx.ID_ANY)
@@ -1887,8 +1887,7 @@
             sqlFile = tempfile.NamedTemporaryFile(mode="wt")
             for sql in self.listOfSQLStatements:
                 enc = UserSettings.Get(group='atm', key='encoding', subkey='value')
-                if not enc and \
-                        os.environ.has_key('GRASS_DB_ENCODING'):
+                if not enc and 'GRASS_DB_ENCODING' in os.environ:
                     enc = os.environ['GRASS_DB_ENCODING']
                 if enc:
                     sqlFile.file.write(sql.encode(enc) + ';')
@@ -2568,10 +2567,10 @@
     def __createDeletePage(self):
         """!Delete layer"""
         self.deletePanel = wx.Panel(parent=self, id=wx.ID_ANY)
-        self.AddPage(page=self.deletePanel, text=_("Delete layer"))
+        self.AddPage(page=self.deletePanel, text=_("Remove layer"))
 
         label = wx.StaticText(parent=self.deletePanel, id=wx.ID_ANY,
-                              label='%s:' % _("Layer to detele"))
+                              label='%s:' % _("Layer to remove"))
 
         self.deleteLayer = wx.ComboBox(parent=self.deletePanel, id=wx.ID_ANY, size=(100, -1),
                                        style=wx.CB_SIMPLE | wx.CB_READONLY,
@@ -2592,7 +2591,7 @@
             self.deleteLayer.Enable(False)
             self.deleteTable.Enable(False)
             
-        btnDelete   = wx.Button(self.deletePanel, wx.ID_DELETE, _("&Delete layer"),
+        btnDelete   = wx.Button(self.deletePanel, wx.ID_DELETE, _("&Remove layer"),
                                 size=(125,-1))
         btnDelete.Bind(wx.EVT_BUTTON, self.OnDeleteLayer)
 

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/dbm_base.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/dbm_base.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/dbm_base.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -31,7 +31,7 @@
     enc = UserSettings.Get(group = 'atm', key = 'encoding', subkey = 'value')
     if enc:
         value = unicode(value, enc)
-    elif os.environ.has_key('GRASS_DB_ENCODING'):
+    elif 'GRASS_DB_ENCODING' in os.environ:
         value = unicode(value, os.environ['GRASS_DB_ENCODING'])
     else:
         try:

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/dbm_dialogs.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/dbm_dialogs.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/dbm_dialogs.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -1,4 +1,4 @@
-"""
+"""!
 @package dbm_dialogs.py
 
 @brief DBM-related dialogs
@@ -7,7 +7,7 @@
  - DisplayAttributesDialog
  - ModifyTableRecord
 
-(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
@@ -31,27 +31,26 @@
 from dbm_base    import VectorDBInfo
 
 class DisplayAttributesDialog(wx.Dialog):
-    """
-    Standard dialog used to add/update/display attributes linked
-    to the vector map.
-
-    Attribute data can be selected based on layer and category number
-    or coordinates.
-
-    @param parent
-    @param map vector map
-    @param query query coordinates and distance (used for v.edit)
-    @param cats {layer: cats}
-    @param line feature id (requested for cats)
-    @param style
-    @param pos
-    @param action (add, update, display)
-    """
     def __init__(self, parent, map,
                  query=None, cats=None, line=None,
                  style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
                  pos=wx.DefaultPosition,
                  action="add"):
+        """!Standard dialog used to add/update/display attributes linked
+        to the vector map.
+        
+        Attribute data can be selected based on layer and category number
+        or coordinates.
+        
+        @param parent
+        @param map vector map
+        @param query query coordinates and distance (used for v.edit)
+        @param cats {layer: cats}
+        @param line feature id (requested for cats)
+        @param style
+        @param pos
+        @param action (add, update, display)
+        """
         self.parent = parent # mapdisplay.BufferedWindow
         self.map    = map
         self.action = action
@@ -109,7 +108,7 @@
         if self.action == "update":
             self.SetTitle(_("Update attributes"))
         elif self.action == "add":
-            self.SetTitle(_("Add attributes"))
+            self.SetTitle(_("Define attributes"))
         else:
             self.SetTitle(_("Display attributes"))
 
@@ -268,22 +267,22 @@
                         self.FindWindowById(id).SetValue(str(value))
 
     def OnCancel(self, event):
-        """!Cancel button pressed"""
+        """!Cancel button pressed
+        """
         self.parent.parent.dialogs['attributes'] = None
-        if self.parent.parent.digit:
-            self.parent.parent.digit.driver.SetSelected([])
-            self.parent.UpdateMap(render=False)
+        if self.parent.digit:
+            self.parent.digit.GetDisplay().SetSelected([])
+            self.parent.UpdateMap(render = False)
         else:
             self.parent.parent.OnRender(None)
-
+        
         self.Close()
 
     def OnSubmit(self, event):
         """!Submit records"""
         for sql in self.GetSQLString(updateValues=True):
             enc = UserSettings.Get(group='atm', key='encoding', subkey='value')
-            if not enc and \
-                    os.environ.has_key('GRASS_DB_ENCODING'):
+            if not enc and 'GRASS_DB_ENCODING' in os.environ:
                 enc = os.environ['GRASS_DB_ENCODING']
             if enc:
                 sql = sql.encode(enc)
@@ -335,17 +334,17 @@
             data = self.mapDBInfo.SelectByPoint(query[0],
                                                 query[1])
             self.cats = {}
-            if data and data.has_key('Layer'):
+            if data and 'Layer' in data:
                 idx = 0
                 for layer in data['Layer']:
                     layer = int(layer)
-                    if data.has_key('Id'):
+                    if 'Id' in data:
                         tfid = int(data['Id'][idx])
                     else:
                         tfid = 0 # Area / Volume
-                    if not self.cats.has_key(tfid):
+                    if not tfid in self.cats:
                         self.cats[tfid] = {}
-                    if not self.cats[tfid].has_key(layer):
+                    if not layer in self.cats[tfid]:
                         self.cats[tfid][layer] = []
                     cat = int(data['Category'][idx])
                     self.cats[tfid][layer].append(cat)
@@ -381,7 +380,7 @@
 
         for layer in layers: # for each layer
             if not query: # select by layer/cat
-                if self.fid > 0 and self.cats[self.fid].has_key(layer): 
+                if self.fid > 0 and layer in self.cats[self.fid]:
                     for cat in self.cats[self.fid][layer]:
                         nselected = self.mapDBInfo.SelectFromTable(layer,
                                                                    where="%s=%d" % \
@@ -395,7 +394,7 @@
 
             if self.action == "add":
                 if nselected <= 0:
-                    if self.cats[self.fid].has_key(layer):
+                    if layer in self.cats[self.fid]:
                         table = self.mapDBInfo.layers[layer]["table"]
                         key = self.mapDBInfo.layers[layer]["key"]
                         columns = self.mapDBInfo.tables[table]
@@ -501,15 +500,16 @@
                 break
         
 class ModifyTableRecord(wx.Dialog):
-    """!Dialog for inserting/updating table record"""
     def __init__(self, parent, id, title, data, keyEditable=(-1, True),
                 style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
-        """
+        """!Dialog for inserting/updating table record
+
         Notes:
-         'Data' is a list: [(column, value)]
-         'KeyEditable' (id, editable?) indicates if textarea for key column
-          is editable(True) or not.
+        'Data' is a list: [(column, value)]
+        'KeyEditable' (id, editable?) indicates if textarea for key column
+        is editable(True) or not.
         """
+        # parent -> VDigitWindow
         wx.Dialog.__init__(self, parent, id, title, style=style)
         
         self.CenterOnParent()

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/debug.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/debug.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/debug.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -11,7 +11,7 @@
 Debug.msg (3, 'debug message')
 @endcode
          
-COPYRIGHT: (C) 2007-2009 by the GRASS Development Team
+COPYRIGHT: (C) 2007-2009, 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.
 
@@ -23,47 +23,47 @@
 
 import globalvar
 
+import grass.script as grass
+
 class DebugMsg:
-    """!
-    wxGUI debugging
+    """!wxGUI debugging
 
     @code
-    export GRASS_WX_DEBUG=[0-5]
+    g.gisenv set=WX_DEBUG=[0-5]
     @endcode
     """
     def __init__(self):
         # default level
         self.debuglevel = 0
-        # update level
-        self._update_level()
+        
+        self.SetLevel()
 
-    def _update_level(self):
-        debug = os.getenv("GRASS_WX_DEBUG")
-        if debug is not None:
-            try:
-                # only GUI debug messages [GUI:level]
-                level = int (debug[-1])
-            except:
-                level = self.debuglevel
-                
-            if self.debuglevel != level:
-                self.debuglevel = level
+    def SetLevel(self):
+        """!Initialize gui debug level
+        """
+        self.debuglevel = int(grass.gisenv().get('WX_DEBUG', 0))
         
-    def msg (self, level, message, *args):
-        self._update_level()
+    def msg(self, level, message, *args):
+        """!Print debug message
+
+        @param level debug level (0-5)
+        @param message message to be printed
+        @param *args formatting params
+        """
+        # self.SetLevel()
         if self.debuglevel > 0 and level > 0 and level <= self.debuglevel:
             if args:
-                print >> sys.stderr, "GUI D%d/%d: " % (level, self.debuglevel) + \
-                    message % args
+                sys.stderr.write("GUI D%d/%d: " % (level, self.debuglevel) + \
+                    message % args + os.linesep)
             else:
-                print >> sys.stderr, "GUI D%d/%d: " % (level, self.debuglevel) + \
-                    message
+                sys.stderr.write("GUI D%d/%d: " % (level, self.debuglevel) + \
+                                     message + os.linesep)
             sys.stderr.flush() # force flush (required for MS Windows)
         
-    def get_level(self):
+    def GetLevel(self):
         """!Return current GUI debug level"""
         return self.debuglevel
-    
+
 # Debug instance
 Debug = DebugMsg()
 
@@ -75,4 +75,3 @@
                 
     for level in range (4):
         Debug.msg (level, "message level=%d" % level)
-    

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gcmd.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gcmd.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gcmd.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -15,7 +15,7 @@
 Functions:
  - RunCommand
 
-(C) 2007-2008, 2010 by the GRASS Development Team
+(C) 2007-2008, 2010-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.
@@ -31,6 +31,7 @@
 import signal
 import locale
 import traceback
+import types
 
 import wx
 
@@ -58,18 +59,19 @@
 from debug import Debug as Debug
 
 class GError:
-    def __init__(self, message, parent = None):
-        caption = _('Error')
+    def __init__(self, message, parent = None, caption = None, showTraceback = True):
+        if not caption:
+            caption = _('Error')
         style = wx.OK | wx.ICON_ERROR | wx.CENTRE
         exc_type, exc_value, exc_traceback = sys.exc_info()
         if exc_traceback:
             exception = traceback.format_exc()
             reason = exception.splitlines()[-1].split(':', 1)[-1].strip()
         
-        if Debug.get_level() > 0 and exc_traceback:
+        if Debug.GetLevel() > 0 and exc_traceback:
             sys.stderr.write(exception)
         
-        if exc_traceback:
+        if showTraceback and exc_traceback:
             wx.MessageBox(parent = parent,
                           message = message + '\n\n%s: %s\n\n%s' % \
                               (_('Reason'),
@@ -121,13 +123,13 @@
         
         subprocess.Popen.__init__(self, *args, **kwargs)
         
-    def recv(self, maxsize=None):
+    def recv(self, maxsize = None):
         return self._recv('stdout', maxsize)
     
-    def recv_err(self, maxsize=None):
+    def recv_err(self, maxsize = None):
         return self._recv('stderr', maxsize)
 
-    def send_recv(self, input='', maxsize=None):
+    def send_recv(self, input = '', maxsize = None):
         return self.send(input), self.recv(maxsize), self.recv_err(maxsize)
 
     def get_conn_maxsize(self, which, maxsize):
@@ -237,7 +239,7 @@
 
 message = "Other end disconnected!"
 
-def recv_some(p, t=.1, e=1, tr=5, stderr=0):
+def recv_some(p, t = .1, e = 1, tr = 5, stderr = 0):
     if tr < 1:
         tr = 1
     x = time.time()+t
@@ -294,9 +296,9 @@
     @param stdout  redirect standard output or None
     @param stderr  redirect standard error output or None
     """
-    def __init__ (self, cmd, stdin=None,
-                  verbose=None, wait=True, rerr=False,
-                  stdout=None, stderr=None):
+    def __init__ (self, cmd, stdin = None,
+                  verbose = None, wait = True, rerr = False,
+                  stdout = None, stderr = None):
         Debug.msg(1, "gcmd.Command(): %s" % ' '.join(cmd))
         self.cmd = cmd
         self.stderr = stderr
@@ -359,7 +361,7 @@
 
         if verbose_orig:
             os.environ["GRASS_VERBOSE"] = verbose_orig
-        elif os.environ.has_key("GRASS_VERBOSE"):
+        elif "GRASS_VERBOSE" in os.environ:
             del os.environ["GRASS_VERBOSE"]
             
     def __ReadOutput(self, stream):
@@ -439,8 +441,8 @@
 class CommandThread(Thread):
     """!Create separate thread for command. Used for commands launched
     on the background."""
-    def __init__ (self, cmd, stdin=None,
-                  stdout=sys.stdout, stderr=sys.stderr):
+    def __init__ (self, cmd, stdin = None,
+                  stdout = sys.stdout, stderr = sys.stderr):
         """
         @param cmd command (given as list)
         @param stdin standard input stream 
@@ -448,7 +450,7 @@
         @param stderr redirect standard error output or None
         """
         Thread.__init__(self)
-
+        
         self.cmd    = cmd
         self.stdin  = stdin
         self.stdout = stdout
@@ -477,13 +479,15 @@
         if len(self.cmd) == 0:
             return
 
+        Debug.msg(1, "gcmd.CommandThread(): %s" % ' '.join(self.cmd))
+
         self.startTime = time.time()
         try:
             self.module = Popen(self.cmd,
-                                stdin=subprocess.PIPE,
-                                stdout=subprocess.PIPE,
-                                stderr=subprocess.PIPE,
-                                shell=sys.platform=="win32")
+                                stdin = subprocess.PIPE,
+                                stdout = subprocess.PIPE,
+                                stderr = subprocess.PIPE,
+                                shell = sys.platform == "win32")
         except OSError, e:
             self.error = str(e)
             return 1
@@ -493,10 +497,9 @@
             self.module.stdin.close()
             
         # redirect standard outputs...
-        if self.stdout or self.stderr:
-            self.__redirect_stream()
-
-    def __redirect_stream(self):
+        self._redirect_stream()
+        
+    def _redirect_stream(self):
         """!Redirect stream"""
         if self.stdout:
             # make module stdout/stderr non-blocking
@@ -519,20 +522,20 @@
                 self.aborted = True
                 return 
             if self.stdout:
-                line = recv_some(self.module, e=0, stderr=0)
+                line = recv_some(self.module, e = 0, stderr = 0)
                 self.stdout.write(line)
             if self.stderr:
-                line = recv_some(self.module, e=0, stderr=1)
+                line = recv_some(self.module, e = 0, stderr = 1)
                 self.stderr.write(line)
                 if len(line) > 0:
                     self.error = line
 
         # get the last output
         if self.stdout:
-            line = recv_some(self.module, e=0, stderr=0)
+            line = recv_some(self.module, e = 0, stderr = 0)
             self.stdout.write(line)
         if self.stderr:
-            line = recv_some(self.module, e=0, stderr=1)
+            line = recv_some(self.module, e = 0, stderr = 1)
             self.stderr.write(line)
             if len(line) > 0:
                 self.error = line
@@ -541,9 +544,45 @@
         """!Abort running process, used by main thread to signal an abort"""
         self._want_abort = True
     
+def _formatMsg(text):
+    """!Format error messages for dialogs
+    """
+    message = ''
+    for line in text.splitlines():
+        if len(line) == 0:
+            continue
+        elif 'GRASS_INFO_MESSAGE' in line:
+            message += line.split(':', 1)[1].strip() + '\n'
+        elif 'GRASS_INFO_WARNING' in line:
+            message += line.split(':', 1)[1].strip() + '\n'
+        elif 'GRASS_INFO_ERROR' in line:
+            message += line.split(':', 1)[1].strip() + '\n'
+        elif 'GRASS_INFO_END' in line:
+            return message
+        else:
+            message += line.strip() + '\n'
+    
+    return message
+
 def RunCommand(prog, flags = "", overwrite = False, quiet = False, verbose = False,
                parent = None, read = False, stdin = None, getErrorMsg = False, **kwargs):
-    """!Run GRASS command"""
+    """!Run GRASS command
+
+    @param prog program to run
+    @param flags flags given as a string
+    @param overwrite, quiet, verbose flags
+    @param parent parent window for error messages
+    @param read fetch stdout
+    @param stdin stdin or None
+    @param getErrorMsg get error messages on failure
+    @param kwargs program parameters
+    
+    @return returncode (read == False and getErrorMsg == False)
+    @return returncode, messages (read == False and getErrorMsg == True)
+    @return stdout (read == True and getErrorMsg == False)
+    @return returncode, stdout, messages (read == True and getErrorMsg == True)
+    @return stdout, stderr
+    """
     Debug.msg(1, "gcmd.RunCommand(): %s" % ' '.join(grass.make_command(prog, flags, overwrite,
                                                                        quiet, verbose, **kwargs)))
     
@@ -562,7 +601,7 @@
         ps.stdin.close()
         ps.stdin = None
     
-    stdout, stderr = ps.communicate()
+    stdout, stderr = map(lambda x: utils.DecodeString(x) if type(x) is types.StringType else x, ps.communicate())
     
     ret = ps.returncode
         
@@ -574,12 +613,12 @@
         if not getErrorMsg:
             return ret
         else:
-            return ret, stderr
+            return ret, _formatMsg(stderr)
 
     if not getErrorMsg:
         return stdout
     
     if read and getErrorMsg:
-        return ret, stdout, stderr
+        return ret, stdout, _formatMsg(stderr)
     
-    return stdout, stderr
+    return stdout, _formatMsg(stderr)

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gcpmanager.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gcpmanager.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gcpmanager.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -59,11 +59,8 @@
     sys.path.append(CompatPath)
     from compat import subprocess
 
-gmpath = os.path.join(globalvar.ETCWXDIR, "icons")
-sys.path.append(gmpath)
+sys.path.append(os.path.join(globalvar.ETCWXDIR, "icons"))
 
-imgpath = os.path.join(globalvar.ETCWXDIR, "images")
-
 #
 # global variables
 #
@@ -76,7 +73,7 @@
 maptype = 'cell'
 
 def getSmallUpArrowImage():
-    stream = open(os.path.join(imgpath, 'small_up_arrow.png'), 'rb')
+    stream = open(os.path.join(globalvar.ETCIMGDIR, 'small_up_arrow.png'), 'rb')
     try:
         img = wx.ImageFromStream(stream)
     finally:
@@ -84,7 +81,7 @@
     return img
 
 def getSmallDnArrowImage():
-    stream = open(os.path.join(imgpath, 'small_down_arrow.png'), 'rb')
+    stream = open(os.path.join(globalvar.ETCIMGDIR, 'small_down_arrow.png'), 'rb')
     try:
         img = wx.ImageFromStream(stream)
     finally:
@@ -502,10 +499,9 @@
         
     def OnMkGroup(self, event):
         """!Create new group in source location/mapset"""
-        menuform.GUI().ParseCommand(['i.group'],
-                                    completed=(self.GetOptData, None, ''),
-                                    parentframe=self.parent.parent, modal=True)
-
+        menuform.GUI(parent = self.parent.parent, modal = True).ParseCommand(['i.group'],
+                                                                             completed = (self.GetOptData, None, ''))
+        
     def OnVGroup(self, event):
         """!Add vector maps to group"""
         dlg = VectGroup(parent = self,
@@ -802,6 +798,8 @@
 
         # polynomial order transformation for georectification
         self.gr_order = 1 
+        # interpolation method for georectification
+        self.gr_method = 'nearest'
         # region clipping for georectified map
         self.clip_to_region = False
         # number of GCPs selected to be used for georectification (checked)
@@ -1348,6 +1346,7 @@
                                   group = self.xygroup,
                                   extension = self.extension,
                                   order = self.gr_order,
+                                  method=self.gr_method,
                                   flags = flags)
 
             busy.Destroy()
@@ -1393,48 +1392,46 @@
                 msg = err = ''
 
                 ret, out, err = gcmd.RunCommand('v.transform',
-                           flags = '-o',
-                           input=vect,
-                           output=self.outname,
-                           pointsfile=self.file['points'],
-                           getErrorMsg=True, read=True) 
-                
-                    
+                                                flags = 'o',
+                                                input = vect,
+                                                output = self.outname,
+                                                pointsfile = self.file['points'],
+                                                getErrorMsg = True, read = True) 
+                                    
                 if ret == 0:
                     self.VectGRList.append(self.outname)
-                    print err
                     # note: WriteLog doesn't handle GRASS_INFO_PERCENT well, so using a print here
-#                    self.parent.goutput.WriteLog(text = _(err), switchPage = True)
-                    self.parent.goutput.WriteLog(text = _(out), switchPage = True)
+                    # self.parent.goutput.WriteLog(text = _(err), switchPage = True)
+                    self.parent.goutput.WriteLog(text = out, switchPage = True)
                 else:
                     self.parent.goutput.WriteError(_('Georectification of vector map <%s> failed') %
-                                                           self.outname)
-                    self.parent.goutput.WriteError(_(err))
-
+                                                   self.outname)
+                    self.parent.goutput.WriteError(err)
+                    
                 # FIXME
                 # Copying database information not working. 
                 # Does not copy from xy location to current location
                 # TODO: replace $GISDBASE etc with real paths
-#                xyLayer = []
-#                for layer in grass.vector_db(map = vect).itervalues():
-#                    xyLayer.append((layer['driver'],
-#                                    layer['database'],
-#                                    layer['table']))
+                #                xyLayer = []
+                #                for layer in grass.vector_db(map = vect).itervalues():
+                #                    xyLayer.append((layer['driver'],
+                #                                    layer['database'],
+                #                                    layer['table']))
+                    
+                    
+                    #                dbConnect = grass.db_connection()
+                    #                print 'db connection =', dbConnect
+                    #                for layer in xyLayer:     
+                    #                    self.parent.goutput.RunCmd(['db.copy',
+                    #                                                '--q',
+                    #                                                '--o',
+                    #                                                'from_driver=%s' % layer[0],
+                    #                                                'from_database=%s' % layer[1],
+                    #                                                'from_table=%s' % layer[2],
+                    #                                                'to_driver=%s' % dbConnect['driver'],
+                    #                                                'to_database=%s' % dbConnect['database'],
+                    #                                                'to_table=%s' % layer[2] + '_' + self.extension])
 
-                        
-#                dbConnect = grass.db_connection()
-#                print 'db connection =', dbConnect
-#                for layer in xyLayer:     
-#                    self.parent.goutput.RunCmd(['db.copy',
-#                                                '--q',
-#                                                '--o',
-#                                                'from_driver=%s' % layer[0],
-#                                                'from_database=%s' % layer[1],
-#                                                'from_table=%s' % layer[2],
-#                                                'to_driver=%s' % dbConnect['driver'],
-#                                                'to_database=%s' % dbConnect['database'],
-#                                                'to_table=%s' % layer[2] + '_' + self.extension])
-
             # copy all georectified vectors from source location to current location
             for name in self.VectGRList:
                 xyvpath = os.path.join(self.grassdatabase,
@@ -2358,6 +2355,12 @@
         self.sdfactor = 0
 
         self.symbol = {}
+        
+        self.methods = ["nearest",
+                        "bilinear",
+                        "bilinear_f",
+                        "cubic", 
+                        "cubic_f"]
 
         # notebook
         notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
@@ -2592,14 +2595,26 @@
         sizer = wx.BoxSizer(wx.VERTICAL)
 
         # transformation order
-        self.rb_grmethod = wx.RadioBox(parent=panel, id=wx.ID_ANY,
-                                       label=" %s " % _("Select rectification method for rasters"),
+        self.rb_grorder = wx.RadioBox(parent=panel, id=wx.ID_ANY,
+                                       label=" %s " % _("Select rectification order"),
                                        choices=[_('1st order'), _('2nd order'), _('3rd order')],
                                        majorDimension=wx.RA_SPECIFY_COLS)
-        sizer.Add(item=self.rb_grmethod, proportion=0,
+        sizer.Add(item=self.rb_grorder, proportion=0,
                        flag=wx.EXPAND | wx.ALL, border=5)
-        self.rb_grmethod.SetSelection(self.parent.gr_order - 1)
+        self.rb_grorder.SetSelection(self.parent.gr_order - 1)
 
+        # interpolation method
+        gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
+        gridSizer.AddGrowableCol(1)
+        gridSizer.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY, label=_('Select interpolation method:')),
+                       pos=(0,0), flag=wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
+        self.grmethod = wx.Choice(parent=panel, id=wx.ID_ANY,
+                                  choices = self.methods)
+        gridSizer.Add(item=self.grmethod, pos=(0,1),
+                       flag=wx.ALIGN_RIGHT, border=5)
+        self.grmethod.SetStringSelection(self.parent.gr_method)
+        sizer.Add(item=gridSizer, flag=wx.EXPAND | wx.ALL, border=5)
+
         # clip to region
         self.check = wx.CheckBox(parent=panel, id=wx.ID_ANY,
                                 label=_("clip to computational region in target location"))
@@ -2617,7 +2632,8 @@
 
         # bindings
         self.ext_txt.Bind(wx.EVT_TEXT, self.OnExtension)
-        self.Bind(wx.EVT_RADIOBOX, self.parent.OnGROrder, self.rb_grmethod)
+        self.Bind(wx.EVT_RADIOBOX, self.parent.OnGROrder, self.rb_grorder)
+        self.Bind(wx.EVT_CHOICE, self.OnMethod, self.grmethod)
         self.Bind(wx.EVT_CHECKBOX, self.OnClipRegion, self.check)
 
         panel.SetSizer(sizer)
@@ -2668,6 +2684,9 @@
         if not tmp_map == tgt_map:
             self.new_tgt_map = tmp_map
 
+    def OnMethod(self, event):
+        self.parent.gr_method = self.methods[event.GetSelection()]
+
     def OnClipRegion(self, event):
         self.parent.clip_to_region = event.IsChecked()
         

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gcpmapdisp.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gcpmapdisp.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gcpmapdisp.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -63,13 +63,6 @@
 from mapdisp_command import Command
 from mapdisp_window import BufferedWindow
 
-import images
-imagepath = images.__path__[0]
-sys.path.append(imagepath)
-
-###
-### global variables
-###
 # for standalone app
 cmdfilename = None
 
@@ -77,7 +70,7 @@
     """!Main frame for map display window. Drawing takes place in
     child double buffered drawing window.
     """
-    def __init__(self, parent=None, id=wx.ID_ANY, title=_("Manage Ground Control Points"),
+    def __init__(self, parent=None, id=wx.ID_ANY, title=_("GRASS GIS Manage Ground Control Points"),
                  style=wx.DEFAULT_FRAME_STYLE, toolbars=["gcpdisp"],
                  tree=None, notebook=None, lmgr=None, page=None,
                  Map=None, auimgr=None, **kwargs):
@@ -100,7 +93,7 @@
         self.layerbook  = notebook  # Layer Manager layer tree notebook
         self.parent     = parent
         
-        if not kwargs.has_key('name'):
+        if 'name' not in kwargs:
             kwargs['name'] = 'GCPMapWindow'
         wx.Frame.__init__(self, parent, id, title, style = style, **kwargs)
         

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gdialogs.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gdialogs.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gdialogs.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -465,9 +465,9 @@
             mapName, found = utils.GetLayerNameFromCmd(self.parent.MapWindow.overlays[self.ovlId]['cmd'])
             if self.parent.MapWindow.overlays[self.ovlId]['propwin'] is None and mapName:
                 # build properties dialog
-                menuform.GUI().ParseCommand(cmd=self.cmd,
-                                            completed=(self.GetOptData, self.name, ''),
-                                            parentframe=self.parent, show=False)
+                menuform.GUI(parent = self.parent, show = False).ParseCommand(cmd=self.cmd,
+                                                                              completed=(self.GetOptData, self.name, ''))
+                
             if found:
                 # enable 'OK' button
                 self.btnOK.Enable()
@@ -504,9 +504,9 @@
         """
         if self.parent.MapWindow.overlays[self.ovlId]['propwin'] is None:
             # build properties dialog
-            menuform.GUI().ParseCommand(cmd=self.cmd,
-                                        completed=(self.GetOptData, self.name, ''),
-                                        parentframe=self.parent)
+            menuform.GUI(parent = self.parent).ParseCommand(cmd=self.cmd,
+                                                            completed=(self.GetOptData, self.name, ''))
+            
         else:
             if self.parent.MapWindow.overlays[self.ovlId]['propwin'].IsShown():
                 self.parent.MapWindow.overlays[self.ovlId]['propwin'].SetFocus()
@@ -954,7 +954,7 @@
         self.list.LoadData()
 
         self.optionBox = wx.StaticBox(parent=self.panel, id=wx.ID_ANY,
-                                      label=_(" Options "))
+                                      label="%s" % _("Options"))
         
         cmd = self._getCommand()
         task = menuform.GUI().ParseInterface(cmd = [cmd])
@@ -1219,7 +1219,7 @@
                 cmd.append('--overwrite')
             
             # run in Layer Manager
-            self.parent.goutput.RunCmd(cmd, switchPage=True,
+            self.parent.goutput.RunCmd(cmd, switchPage = True,
                                        onDone = self.AddLayers)
         
         self.OnCancel()
@@ -1242,9 +1242,8 @@
     def OnCmdDialog(self, event):
         """!Show command dialog"""
         name = self._getCommand()
-        menuform.GUI().ParseCommand(cmd = [name],
-                                    parentframe = self, modal = True)
-        
+        menuform.GUI(parentframe = self, modal = True).ParseCommand(cmd = [name])
+                
 class DxfImportDialog(ImportDialog):
     """!Dialog for bulk import of DXF layers""" 
     def __init__(self, parent):
@@ -1330,9 +1329,8 @@
 
     def OnCmdDialog(self, event):
         """!Show command dialog"""
-        menuform.GUI().ParseCommand(cmd = ['v.in.dxf'],
-                                    parentframe = self, modal = True)
-        
+        menuform.GUI(parent = self, modal = True).ParseCommand(cmd = ['v.in.dxf'])
+                
 class LayersList(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin,
                  listmix.CheckListCtrlMixin, listmix.TextEditMixin):
     """!List of layers to be imported (dxf, shp...)"""

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/ghelp.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/ghelp.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/ghelp.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -39,6 +39,7 @@
 import globalvar
 import gdialogs
 import utils
+import menuform
 
 class HelpFrame(wx.Frame):
     """!GRASS Quickstart help window"""
@@ -170,7 +171,7 @@
                 except ValueError:
                     continue # TODO
                 
-                if not modules.has_key(group):
+                if group not in modules:
                     modules[group] = list()
                 modules[group].append(name)
                 
@@ -304,7 +305,7 @@
             return
         
         data = self.tree.GetPyData(item)
-        if not data or not data.has_key('command'):
+        if not data or 'command' not in data:
             return
         
         self.tree.itemSelected = item
@@ -318,7 +319,7 @@
             return
         
         data = self.tree.GetPyData(item)
-        if not data or not data.has_key('command'):
+        if not data or 'command' not in data:
             return
         
         if data['command']:
@@ -387,7 +388,7 @@
                 self._processItem(subItem, element, value, listOfItems)
             data = self.GetPyData(item)
             
-            if data and data.has_key(element) and \
+            if data and element in data and \
                     value.lower() in data[element].lower():
                 listOfItems.append(item)
             
@@ -665,7 +666,7 @@
         contribfile = os.path.join(os.getenv("GISBASE"), "contributors.csv")
         if os.path.exists(contribfile):
             contribFile = open(contribfile, 'r')
-            contribs = list()
+            contribs = dict()
             errLines = list()
             for line in contribFile.readlines():
                 line = line.rstrip('\n')
@@ -674,8 +675,7 @@
                 except ValueError:
                     errLines.append(line)
                     continue
-                contribs.append((name, email, country, osgeo_id))
-            contribs[0] = (_('Name'), _('E-mail'), _('Country'), _('OSGeo_ID'))
+                contribs[osgeo_id] = [name, email, country]
             contribFile.close()
             
             if errLines:
@@ -698,8 +698,11 @@
                                  flag = wx.EXPAND | wx.ALL, border = 3)
         else:
             contribBox = wx.FlexGridSizer(cols = 4, vgap = 5, hgap = 5)
-            for developer in contribs:
-                for item in developer:
+            for item in (_('Name'), _('E-mail'), _('Country'), _('OSGeo_ID')):
+                contribBox.Add(item = wx.StaticText(parent = contribwin, id = wx.ID_ANY,
+                                                    label = item))
+            for osgeo_id in sorted(contribs.keys()):
+                for item in contribs[osgeo_id] + [osgeo_id]:
                     contribBox.Add(item = wx.StaticText(parent = contribwin, id = wx.ID_ANY,
                                                         label = item))
             contribwin.sizer.Add(item = contribBox, proportion = 1,
@@ -725,7 +728,7 @@
                     errLines.append(line)
                     continue
                 for language in languages.split(' '):
-                    if not translators.has_key(language):
+                    if language not in translators:
                         translators[language] = list()
                     translators[language].append((name, email))
             translatorsFile.close()
@@ -782,8 +785,9 @@
 
 class InstallExtensionWindow(wx.Frame):
     def __init__(self, parent, id = wx.ID_ANY,
-                 title = _("Fetch & install new extension from GRASS Addons"), **kwargs):
+                 title = _("Fetch & install extension from GRASS Addons"), **kwargs):
         self.parent = parent
+        self.options = dict() # list of options
         
         wx.Frame.__init__(self, parent = parent, id = id, title = title, **kwargs)
         
@@ -805,6 +809,21 @@
         
         self.tree   = ExtensionTree(parent = self.panel, log = parent.GetLogWindow())
         
+        self.optionBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
+                                      label = " %s " % _("Options"))
+        task = menuform.GUI().ParseInterface(cmd = ['g.extension.py'])
+        for f in task.get_options()['flags']:
+            name = f.get('name', '')
+            desc = f.get('label', '')
+            if not desc:
+                desc = f.get('description', '')
+            if not name and not desc:
+                continue
+            if name in ('l', 'f', 'g'):
+                continue
+            self.options[name] = wx.CheckBox(parent = self.panel, id = wx.ID_ANY,
+                                             label = desc)
+        
         self.statusbar = self.CreateStatusBar(0)
         
         self.btnFetch = wx.Button(parent = self.panel, id = wx.ID_ANY,
@@ -845,6 +864,11 @@
         treeSizer = wx.StaticBoxSizer(self.treeBox, wx.HORIZONTAL)
         treeSizer.Add(item = self.tree, proportion = 1,
                       flag = wx.ALL | wx.EXPAND, border = 1)
+
+        # options
+        optionSizer = wx.StaticBoxSizer(self.optionBox, wx.VERTICAL)
+        for key in self.options.keys():
+            optionSizer.Add(item = self.options[key], proportion = 0)
         
         btnSizer = wx.BoxSizer(wx.HORIZONTAL)
         btnSizer.Add(item = self.btnClose, proportion = 0,
@@ -857,6 +881,8 @@
                   flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
         sizer.Add(item = treeSizer, proportion = 1,
                   flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
+        sizer.Add(item = optionSizer, proportion = 0,
+                        flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
         sizer.Add(item = btnSizer, proportion = 0,
                   flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
         
@@ -869,8 +895,13 @@
         if not name:
             return
         log = self.parent.GetLogWindow()
-        log.RunCmd(['g.extension', 'extension=' + name,
-                    'svnurl=' + self.repo.GetValue().strip()])
+        flags = list()
+        for key in self.options.keys():
+            if self.options[key].IsChecked():
+                flags.append('-%s' % key)
+        
+        log.RunCmd(['g.extension.py'] + flags + ['extension=' + name,
+                                                 'svnurl=' + self.repo.GetValue().strip()])
         self.OnCloseWindow(None)
         
     def OnUpdateStatusBar(self, event):
@@ -904,7 +935,7 @@
     def OnItemActivated(self, event):
         item = event.GetItem()
         data = self.tree.GetPyData(item)
-        if data and data.has_key('command'):
+        if data and 'command' in data:
             self._install(data['command'])
             
     def OnInstall(self, event):
@@ -951,7 +982,7 @@
         for prefix in ('display', 'database',
                        'general', 'imagery',
                        'misc', 'postscript', 'paint',
-                       'raster', 'raster3D', 'sites', 'vector'):
+                       'raster', 'raster3D', 'sites', 'vector', 'wxGUI'):
             self.AppendItem(parentId = self.root,
                             text = prefix)
         self._loaded = False
@@ -967,9 +998,10 @@
                  'r'  : 'raster',
                  'r3' : 'raster3D',
                  's'  : 'sites',
-                 'v'  : 'vector' }
+                 'v'  : 'vector',
+                 'wx' : 'wxGUI' }
         
-        if name.has_key(c):
+        if c in name:
             return name[c]
         
         return c
@@ -995,7 +1027,7 @@
             flags = 'g'
         else:
             flags = 'l'
-        ret = gcmd.RunCommand('g.extension', read = True,
+        ret = gcmd.RunCommand('g.extension.py', read = True,
                               svnurl = url,
                               flags = flags, quiet = True)
         if not ret:
@@ -1007,16 +1039,24 @@
                 key, value = line.split('=', 1)
                 if key == 'name':
                     prefix, name = value.split('.', 1)
-                    if not mdict.has_key(prefix):
+                    if prefix not in mdict:
                         mdict[prefix] = dict()
                     mdict[prefix][name] = dict()
                 else:
                     mdict[prefix][name][key] = value
             else:
-                prefix, name = line.strip().split('.', 1)
-                if not mdict.has_key(prefix):
+                try:
+                    prefix, name = line.strip().split('.', 1)
+                except:
+                    prefix = 'unknown'
+                    name = line.strip()
+                
+                if self._expandPrefix(prefix) == prefix:
+                    prefix = 'unknown'
+                    
+                if prefix not in mdict:
                     mdict[prefix] = dict()
-                
+                    
                 mdict[prefix][name] = { 'command' : prefix + '.' + name }
         
         for prefix in mdict.keys():

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/globalvar.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/globalvar.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/globalvar.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -28,6 +28,7 @@
 ETCDIR = os.path.join(os.getenv("GISBASE"), "etc")
 ETCICONDIR = os.path.join(os.getenv("GISBASE"), "etc", "gui", "icons")
 ETCWXDIR = os.path.join(ETCDIR, "wxpython")
+ETCIMGDIR = os.path.join(ETCDIR, "gui", "images")
 
 sys.path.append(os.path.join(ETCDIR, "python"))
 import grass.script as grass

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gmodeler.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gmodeler.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gmodeler.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -41,7 +41,6 @@
 
 import os
 import sys
-import shlex
 import time
 import traceback
 import getpass
@@ -379,10 +378,9 @@
         error string"""
         errList = list()
         for action in self.GetItems(objType = ModelAction):
-            task = menuform.GUI().ParseCommand(cmd = action.GetLog(string = False),
-                                               show = None)
+            task = menuform.GUI(show = None).ParseCommand(cmd = action.GetLog(string = False))
             errList += task.getCmdError()
-
+        
         return errList
 
     def Run(self, log, onDone):
@@ -498,14 +496,14 @@
             params = action.GetParams()
             for f in params['flags']:
                 if f.get('parameterized', False):
-                    if not result.has_key(name):
+                    if name not in result:
                         result[name] = { 'flags' : list(),
                                          'params': list(),
                                          'idx'   : idx }
                     result[name]['flags'].append(f)
             for p in params['params']:
                 if p.get('parameterized', False):
-                    if not result.has_key(name):
+                    if name not in result:
                         result[name] = { 'flags' : list(),
                                          'params': list(),
                                          'idx'   : idx }
@@ -981,7 +979,7 @@
     def _runAction(self, item, params):
         """!Run given action"""
         name = item.GetName()
-        if params.has_key(name):
+        if name in params:
             paramsOrig = item.GetParams(dcopy = True)
             item.MergeParams(params[name])
             
@@ -989,7 +987,7 @@
         self.goutput.RunCmd(command = item.GetLog(string = False),
                             onDone = self.OnDone)
             
-        if params.has_key(name):
+        if name in params:
             item.SetParams(paramsOrig)
         
     def OnDone(self, cmd, returncode):
@@ -1206,9 +1204,8 @@
         # show properties dialog
         win = action.GetPropDialog()
         if not win and action.GetLog(string = False):
-            module = menuform.GUI().ParseCommand(action.GetLog(string = False),
-                                                 completed = (self.GetOptData, action, action.GetParams()),
-                                                 parentframe = self, show = True)
+            module = menuform.GUI(parent = self, show = True).ParseCommand(action.GetLog(string = False),
+                                                                           completed = (self.GetOptData, action, action.GetParams()))
         elif win and not win.IsShown():
             win.Show()
         
@@ -1673,8 +1670,7 @@
             height = UserSettings.Get(group='modeler', key='action', subkey=('size', 'height'))
         
         if cmd:
-            self.task = menuform.GUI().ParseCommand(cmd = cmd,
-                                                    show = None)
+            self.task = menuform.GUI(show = None).ParseCommand(cmd = cmd)
         else:
             if task:
                 self.task = task
@@ -1814,11 +1810,11 @@
         
     def MergeParams(self, params):
         """!Merge dictionary of parameters"""
-        if params.has_key('flags'):
+        if 'flags' in params:
             for f in params['flags']:
                 self.task.set_flag(f['name'],
                                    f.get('value', False))
-        if params.has_key('params'):
+        if 'params' in params:
             for p in params['params']:
                 self.task.set_param(p['name'],
                                     p.get('value', ''))
@@ -1950,8 +1946,7 @@
                 else:
                     action = rel.GetFrom()
                 
-                task = menuform.GUI().ParseCommand(cmd = action.GetLog(string = False),
-                                                   show = None)
+                task = menuform.GUI(show = None).ParseCommand(cmd = action.GetLog(string = False))
                 task.set_param(rel.GetName(), self.value)
                 action.SetParams(params = task.get_options())
         
@@ -2139,9 +2134,8 @@
         self.frame.ModelChanged()
         shape = self.GetShape()
         if isinstance(shape, ModelAction):
-            module = menuform.GUI().ParseCommand(shape.GetLog(string = False),
-                                                 completed = (self.frame.GetOptData, shape, shape.GetParams()),
-                                                 parentframe = self.frame, show = True)
+            module = menuform.GUI(parent = self.frame, show = True).ParseCommand(shape.GetLog(string = False),
+                                                                                 completed = (self.frame.GetOptData, shape, shape.GetParams()))
         
         elif isinstance(shape, ModelData):
             dlg = ModelDataDialog(parent = self.frame, shape = shape)
@@ -2401,9 +2395,9 @@
             list()
         
         try:
-            cmd = shlex.split(str(line))
+            cmd = utils.split(str(line))
         except UnicodeError:
-            cmd = shlex.split(utils.EncodeString((line)))
+            cmd = utils.split(utils.EncodeString((line)))
             
         return cmd
     
@@ -2726,8 +2720,7 @@
             cmd.append('%s=%s' % (name,
                                   self._filterValue(self._getNodeText(p, 'value'))))
         
-        task, err = menuform.GUI().ParseCommand(cmd = cmd,
-                                                show = None, checkError = True)
+        task, err = menuform.GUI(show = None, checkError = True).ParseCommand(cmd = cmd)
         if err:
             GWarning(os.linesep.join(err))
         
@@ -2849,7 +2842,7 @@
         if self.properties['author']:
             self.fd.write('%s<author>%s</author>\n' % (' ' * self.indent, self.properties['author']))
         
-        if self.properties.has_key('overwrite') and \
+        if 'overwrite' in self.properties and \
                 self.properties['overwrite']:
             self.fd.write('%s<flag name="overwrite" />\n' % (' ' * self.indent))
         self.indent -= 4
@@ -2865,10 +2858,10 @@
             self.fd.write('%s<variable name="%s" type="%s">\n' % \
                               (' ' * self.indent, name, values['type']))
             self.indent += 4
-            if values.has_key('value'):
+            if 'value' in values:
                 self.fd.write('%s<value>%s</value>\n' % \
                                   (' ' * self.indent, values['value']))
-            if values.has_key('description'):
+            if 'description' in values:
                 self.fd.write('%s<description>%s</description>\n' % \
                                   (' ' * self.indent, values['description']))
             self.indent -= 4
@@ -3406,7 +3399,7 @@
         self.name.SetValue(prop['name'])
         self.desc.SetValue(prop['description'])
         self.author.SetValue(prop['author'])
-        if prop.has_key('overwrite'):
+        if 'overwrite' in prop:
             self.overwrite.SetValue(prop['overwrite'])
 
 class ModelParamDialog(wx.Dialog):
@@ -4482,8 +4475,7 @@
         
     def _writePythonAction(self, item):
         """!Write model action to Python file"""
-        task = menuform.GUI().ParseCommand(cmd = item.GetLog(string = False),
-                                           show = None)
+        task = menuform.GUI(show = None).ParseCommand(cmd = item.GetLog(string = False))
         opts = task.get_options()
         flags = ''
         params = list()

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/goutput.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/goutput.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/goutput.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -24,6 +24,7 @@
 import time
 import threading
 import Queue
+import codecs
 
 import wx
 import wx.stc
@@ -48,10 +49,10 @@
 wxCmdDone,     EVT_CMD_DONE     = NewEvent()
 wxCmdAbort,    EVT_CMD_ABORT    = NewEvent()
 
-def GrassCmd(cmd, stdout, stderr):
+def GrassCmd(cmd, stdout = None, stderr = None):
     """!Return GRASS command thread"""
     return gcmd.CommandThread(cmd,
-                              stdout=stdout, stderr=stderr)
+                              stdout = stdout, stderr = stderr)
 
 class CmdThread(threading.Thread):
     """!Thread for GRASS commands"""
@@ -69,11 +70,11 @@
 
         self.start()
 
-    def RunCmd(self, callable, onDone, *args, **kwds):
+    def RunCmd(self, *args, **kwds):
         CmdThread.requestId += 1
 
         self.requestCmd = None
-        self.requestQ.put((CmdThread.requestId, callable, onDone, args, kwds))
+        self.requestQ.put((CmdThread.requestId, args, kwds))
         
         return CmdThread.requestId
 
@@ -84,23 +85,31 @@
     def run(self):
         os.environ['GRASS_MESSAGE_FORMAT'] = 'gui'
         while True:
-            requestId, callable, onDone, args, kwds = self.requestQ.get()
+            requestId, args, kwds = self.requestQ.get()
+            for key in ('callable', 'onDone', 'userData'):
+                if key in kwds:
+                    vars()[key] = kwds[key]
+                    del kwds[key]
+                else:
+                    vars()[key] = None
             
+            if not vars()['callable']:
+                vars()['callable'] = GrassCmd
+            
             requestTime = time.time()
-            event = wxCmdRun(cmd=args[0],
-                             pid=requestId)
+            event = wxCmdRun(cmd = args[0],
+                             pid = requestId)
             wx.PostEvent(self.parent, event)
             
             time.sleep(.1)
-            
-            self.requestCmd = callable(*args, **kwds)
+            self.requestCmd = vars()['callable'](*args, **kwds)
             if self._want_abort_all:
                 self.requestCmd.abort()
                 if self.requestQ.empty():
                     self._want_abort_all = False
             
             self.resultQ.put((requestId, self.requestCmd.run()))
-
+            
             try:
                 returncode = self.requestCmd.module.returncode
             except AttributeError:
@@ -124,7 +133,7 @@
                     except KeyError:
                         pass
                 else:
-                    moduleInterface = menuform.GUI().ParseCommand(args[0], show = None)
+                    moduleInterface = menuform.GUI(show = None).ParseCommand(args[0])
                     outputParam = moduleInterface.get_param(value = 'output', raiseError = False)
                     if outputParam and outputParam['prompt'] == 'raster':
                         mapName = outputParam['value']
@@ -134,7 +143,7 @@
                     argsColor[0] = [ 'r.colors',
                                      'map=%s' % mapName,
                                      'color=%s' % colorTable ]
-                    self.requestCmdColor = callable(*argsColor, **kwds)
+                    self.requestCmdColor = vars()['callable'](*argsColor, **kwds)
                     self.resultQ.put((requestId, self.requestCmdColor.run()))
             
             event = wxCmdDone(cmd = args[0],
@@ -142,7 +151,8 @@
                               returncode = returncode,
                               time = requestTime,
                               pid = requestId,
-                              onDone = onDone)
+                              onDone = vars()['onDone'],
+                              userData = vars()['userData'])
             
             # send event
             wx.PostEvent(self.parent, event)
@@ -345,18 +355,19 @@
         return self.panelOutput
     
     def Redirect(self):
-        """!Redirect stderr
-
+        """!Redirect stdout/stderr
+        
         @return True redirected
         @return False failed
         """
-        if Debug.get_level() == 0 and int(grass.gisenv().get('DEBUG', 0)) == 0:
+        if Debug.GetLevel() == 0 and int(grass.gisenv().get('DEBUG', 0)) == 0:
             # don't redirect when debugging is enabled
             sys.stdout = self.cmd_stdout
             sys.stderr = self.cmd_stderr
-            
             return True
-
+        else:
+            sys.stdout = sys.__stdout__
+            sys.stderr = sys.__stderr__
         return False
 
     def WriteLog(self, text, style = None, wrap = None,
@@ -410,7 +421,7 @@
 
     def WriteError(self, line):
         """!Write message in error style"""
-        self.WriteLog(line, style=self.cmd_output.StyleError, switchPage = True)
+        self.WriteLog(line, style = self.cmd_output.StyleError, switchPage = True)
 
     def RunCmd(self, command, compReg = True, switchPage = False,
                onDone = None):
@@ -421,7 +432,7 @@
         display widget that currently has the focus (as indicted by
         mdidx).
         
-        @param command command given as a list (produced e.g. by shlex.split())
+        @param command command given as a list (produced e.g. by utils.split())
         @param compReg True use computation region
         @param switchPage switch to output page
         @param onDone function to be called when command is finished
@@ -433,10 +444,13 @@
         # update history file
         env = grass.gisenv()
         try:
-            fileHistory = open(os.path.join(env['GISDBASE'], env['LOCATION_NAME'], env['MAPSET'],
-                                            '.bash_history'), 'a')
+            fileHistory = codecs.open(os.path.join(env['GISDBASE'],
+                                                   env['LOCATION_NAME'],
+                                                   env['MAPSET'],
+                                                   '.bash_history'),
+                                      encoding = 'utf-8', mode = 'a')
         except IOError, e:
-            self.WriteError(str(e))
+            self.WriteError(e)
             fileHistory = None
         
         if fileHistory:
@@ -508,7 +522,7 @@
                 # for all non-display commands.
                 if compReg:
                     tmpreg = os.getenv("GRASS_REGION")
-                    if os.environ.has_key("GRASS_REGION"):
+                    if "GRASS_REGION" in os.environ:
                         del os.environ["GRASS_REGION"]
                 
                 if len(command) == 1:
@@ -521,13 +535,11 @@
                 
                 if task and command[0] not in ('v.krige.py'):
                     # process GRASS command without argument
-                    menuform.GUI().ParseCommand(command, parentframe = self)
+                    menuform.GUI(parent = self).ParseCommand(command)
                 else:
                     # process GRASS command with argument
-                    self.cmdThread.RunCmd(GrassCmd,
-                                          onDone,
-                                          command,
-                                          self.cmd_stdout, self.cmd_stderr)                                          
+                    self.cmdThread.RunCmd(command, stdout = self.cmd_stdout, stderr = self.cmd_stderr,
+                                          onDone = onDone)
                     self.cmd_output_timer.Start(50)
                     
                     return None
@@ -544,19 +556,15 @@
                     task = menuform.GUI().ParseInterface(command)
                 except:
                     task = None
-                # if not task.has_required():
-                # task = None # run command
             else:
                 task = None
                 
             if task:
                 # process GRASS command without argument
-                menuform.GUI().ParseCommand(command, parentframe = self)
+                menuform.GUI(parent = self).ParseCommand(command)
             else:
-                self.cmdThread.RunCmd(GrassCmd,
-                                      onDone,
-                                      command,
-                                      self.cmd_stdout, self.cmd_stderr)                                         
+                self.cmdThread.RunCmd(command, stdout = self.cmd_stdout, stderr = self.cmd_stderr,
+                                      onDone = onDone)
             self.cmd_output_timer.Start(50)
         
         return None
@@ -568,6 +576,20 @@
         self.cmd_output.SetReadOnly(True)
         self.console_progressbar.SetValue(0)
 
+    def GetProgressBar(self):
+        """!Return progress bar widget"""
+        return self.console_progressbar
+    
+    def GetLog(self, err = False):
+        """!Get widget used for logging
+
+        @param err True to get stderr widget
+        """
+        if err:
+            return self.cmd_stderr
+        
+        return self.cmd_stdout
+    
     def SaveHistory(self, event):
         """!Save history of commands"""
         self.history = self.cmd_output.GetSelectedText()
@@ -711,7 +733,7 @@
             except KeyError:
                 # stopped deamon
                 pass
-            
+
             self.btn_abort.Enable(False)
         
         if event.onDone:
@@ -721,11 +743,16 @@
 
         self.cmd_output_timer.Stop()
 
+        if event.cmd[0] == 'g.gisenv':
+            Debug.SetLevel()
+            self.Redirect()
+        
         if self.parent.GetName() == "LayerManager":
             self.btn_abort.Enable(False)
             if event.cmd[0] not in globalvar.grassCmd['all'] or \
                     event.cmd[0] == 'r.mapcalc':
                 return
+            
             display = self.parent.GetLayerTree().GetMapDisplay()
             if not display or not display.IsAutoRendered():
                 return
@@ -734,7 +761,7 @@
                             display.GetRender().GetListOfLayers(l_type = 'vector'))
             
             try:
-                task = menuform.GUI().ParseCommand(event.cmd, show = None)
+                task = menuform.GUI(show = None).ParseCommand(event.cmd)
             except gcmd.GException:
                 task = None
                 return
@@ -1046,11 +1073,11 @@
                 enc = UserSettings.Get(group='atm', key='encoding', subkey='value')
                 if enc:
                     txt = unicode(txt, enc)
-                elif os.environ.has_key('GRASS_DB_ENCODING'):
+                elif 'GRASS_DB_ENCODING' in os.environ:
                     txt = unicode(txt, os.environ['GRASS_DB_ENCODING'])
                 else:
-                    txt = _('Unable to encode text. Please set encoding in GUI preferences.') + '\n'
-                    
+                    txt = utils.EncodeString(txt)
+                
                 self.AddText(txt)
         
         # reset output window to read only

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gselect.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gselect.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/gselect.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -317,19 +317,21 @@
         else:
             filesdict = grass.list_grouped(elementdict[element])
         
-        first_dir = None
-        for dir in mapsets:
-            dir_node = self.AddItem('Mapset: ' + dir)
-            if not first_dir:
-                first_dir = dir_node
+        first_mapset = None
+        for mapset in mapsets:
+            mapset_node = self.AddItem('Mapset: ' + mapset)
+            if not first_mapset:
+                first_mapset = mapset_node
             
-            self.seltree.SetItemTextColour(dir_node, wx.Colour(50, 50, 200))
+            self.seltree.SetItemTextColour(mapset_node, wx.Colour(50, 50, 200))
+            if mapset not in filesdict:
+                continue
             try:
-                elem_list = filesdict[dir]
-                elem_list.sort(key=str.lower)
+                elem_list = filesdict[mapset]
+                elem_list.sort()
                 for elem in elem_list:
                     if elem != '':
-                        fullqElem = elem + '@' + dir
+                        fullqElem = elem + '@' + mapset
                         if elements:
                             if (exclude and fullqElem in elements) or \
                                     (not exclude and fullqElem not in elements):
@@ -337,25 +339,26 @@
                         
                         if self.filterElements:
                             if self.filterElements(fullqElem):
-                                self.AddItem(elem, parent=dir_node)
+                                self.AddItem(elem, parent=mapset_node)
                         else:
-                            self.AddItem(elem, parent=dir_node)
-            except:
+                            self.AddItem(elem, parent=mapset_node)
+            except StandardError, e:
+                sys.stderr.write(_("GSelect: invalid item: %s") % e)
                 continue
-
-            if self.seltree.ItemHasChildren(dir_node):
+            
+            if self.seltree.ItemHasChildren(mapset_node):
                 sel = UserSettings.Get(group='general', key='elementListExpand',
                                        subkey='selection')
                 collapse = True
 
                 if sel == 0: # collapse all except PERMANENT and current
-                    if dir in ('PERMANENT', curr_mapset):
+                    if mapset in ('PERMANENT', curr_mapset):
                         collapse = False
                 elif sel == 1: # collapse all except PERMANENT
-                    if dir == 'PERMANENT':
+                    if mapset == 'PERMANENT':
                         collapse = False
                 elif sel == 2: # collapse all except current
-                    if dir == curr_mapset:
+                    if mapset == curr_mapset:
                         collapse = False
                 elif sel == 3: # collapse all
                     pass
@@ -363,13 +366,13 @@
                     collapse = False
                 
                 if collapse:
-                    self.seltree.Collapse(dir_node)
+                    self.seltree.Collapse(mapset_node)
                 else:
-                    self.seltree.Expand(dir_node)
+                    self.seltree.Expand(mapset_node)
         
-        if first_dir:
+        if first_mapset:
             # select first mapset (MSW hack)
-            self.seltree.SelectItem(first_dir)
+            self.seltree.SelectItem(first_mapset)
     
     # helpers
     def FindItem(self, parentItem, text, startLetters = False):
@@ -493,15 +496,15 @@
 
     def SetData(self, **kargs):
         """!Set object properties"""
-        if kargs.has_key('type'):
+        if 'type' in kargs:
             self.type = kargs['type']
-        if kargs.has_key('mapsets'):
+        if 'mapsets' in kargs:
             self.mapsets = kargs['mapsets']
-        if kargs.has_key('multiple'):
+        if 'multiple' in kargs:
             self.multiple = kargs['multiple']
-        if kargs.has_key('updateOnPopup'):
+        if 'updateOnPopup' in kargs:
             self.updateOnPopup = kargs['updateOnPopup']
-        if kargs.has_key('onPopup'):
+        if 'onPopup' in kargs:
             self.onPopup = kargs['onPopup']
         
 class VectorDBInfo:
@@ -1071,9 +1074,11 @@
         
         # dsn widgets
         if not ogr:
-            filemask = 'GeoTIFF (%s)|%s' % (self._getExtPattern('tif'), self._getExtPattern('tif'))
+            filemask = 'GeoTIFF (%s)|%s|%s (*.*)|*.*' % \
+                (self._getExtPattern('tif'), self._getExtPattern('tif'), _('All files'))
         else:
-            filemask = 'ESRI Shapefile (%s)|%s' % (self._getExtPattern('shp'), self._getExtPattern('shp'))
+            filemask = 'ESRI Shapefile (%s)|%s|%s (*.*)|*.*' % \
+                (self._getExtPattern('shp'), self._getExtPattern('shp'), _('All files'))
         
         dsnFile = filebrowse.FileBrowseButton(parent=self, id=wx.ID_ANY, 
                                               size=globalvar.DIALOG_GSELECT_SIZE, labelText = '',
@@ -1223,7 +1228,7 @@
     def OnSettingsLoad(self, event):
         """!Load named settings"""
         name = event.GetString()
-        if not self._settings.has_key(name):
+        if name not in self._settings:
             gcmd.GError(parent = self,
                         message = _("Settings named '%s' not found") % name)
             return
@@ -1303,9 +1308,10 @@
                 ext = self.format.GetExtension(format)
                 if not ext:
                     raise KeyError
-                format += ' (%s)|%s' % (self._getExtPattern(ext), self._getExtPattern(ext))
+                format += ' (%s)|%s|%s (*.*)|*.*' % \
+                    (self._getExtPattern(ext), self._getExtPattern(ext), _('All files'))
             except KeyError:
-                format += ' (*.*)|*.*'
+                format += '%s (*.*)|*.*' % _('All files')
             
             win = filebrowse.FileBrowseButton(parent=self, id=wx.ID_ANY, 
                                               size=globalvar.DIALOG_GSELECT_SIZE, labelText='',
@@ -1337,9 +1343,9 @@
             win.Show()
             
             if not self.ogr:
-                self.format.SetStringSelection('GeoTIFF')
+                self.OnSetFormat(event = None, format = 'GeoTIFF')
             else:
-                self.format.SetStringSelection('ESRI Shapefile')
+                self.OnSetFormat(event = None, format = 'ESRI Shapefile')
         elif sel == self.sourceMap['pro']:
             win = self.input[self.dsnType][1]
             self.dsnSizer.Add(item=self.input[self.dsnType][1],
@@ -1427,7 +1433,7 @@
         
     def OnSetFormat(self, event, format = None):
         """!Format changed"""
-        if self.dsnType not in ['file', 'db']:
+        if self.dsnType not in ['file', 'dir', 'db']:
             return
         
         win = self.input[self.dsnType][1]
@@ -1448,9 +1454,10 @@
                 ext = self.format.GetExtension(format)
                 if not ext:
                     raise KeyError
-                format += ' (%s)|%s' % (self._getExtPattern(ext), self._getExtPattern(ext))
+                format += ' (%s)|%s|%s (*.*)|*.*' % \
+                    (self._getExtPattern(ext), self._getExtPattern(ext), _('All files'))
             except KeyError:
-                format += ' (*.*)|*.*'
+                format += '%s (*.*)|*.*' % _('All files')
             
             win = filebrowse.FileBrowseButton(parent=self, id=wx.ID_ANY, 
                                               size=globalvar.DIALOG_GSELECT_SIZE, labelText='',
@@ -1459,6 +1466,8 @@
                                               startDirectory=os.getcwd(),
                                               changeCallback=self.OnSetDsn,
                                               fileMask = format)
+        elif self.dsnType == 'dir':
+            pass
         else: # database
             if format == 'SQLite' or format == 'Rasterlite':
                 win = self.input['db-win']['file']

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/histogram.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/histogram.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/histogram.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -317,9 +317,8 @@
         if self.mapname != '':
             cmd.append('map=%s' % self.mapname)
         
-        menuform.GUI().ParseCommand(cmd,
-                                    completed = (self.GetOptData, None, self.params),
-                                    parentframe = self)
+        menuform.GUI(parent = self).ParseCommand(cmd,
+                                                 completed = (self.GetOptData, None, self.params))
         
     def GetOptData(self, dcmd, layer, params, propwin):
         """!Callback method for histogram command generated by dialog

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/layertree.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/layertree.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/layertree.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -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):
@@ -94,6 +94,11 @@
         self.rerender = False                # layer change requires a rerendering if auto render
         self.reorder = False                 # layer change requires a reordering
         
+        try:
+            ctstyle |= CT.TR_ALIGN_WINDOWS
+        except AttributeError:
+            pass
+        
         if globalvar.hasAgw:
             super(LayerTree, self).__init__(parent, id, agwStyle = ctstyle, **kwargs)
         else:
@@ -105,18 +110,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 +137,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)
@@ -141,49 +145,50 @@
         self.folder = il.Add(trart)
         
         bmpsize = (16, 16)
-        trgif = Icons["addrast"].GetBitmap(bmpsize)
+        icons = Icons['layerManager']
+        trgif = icons["addRast"].GetBitmap(bmpsize)
         self.rast_icon = il.Add(trgif)
         
-        trgif = Icons["addrast3d"].GetBitmap(bmpsize)
+        trgif = icons["addRast3d"].GetBitmap(bmpsize)
         self.rast3d_icon = il.Add(trgif)
         
-        trgif = Icons["addrgb"].GetBitmap(bmpsize)
+        trgif = icons["addRgb"].GetBitmap(bmpsize)
         self.rgb_icon = il.Add(trgif)
         
-        trgif = Icons["addhis"].GetBitmap(bmpsize)
+        trgif = icons["addHis"].GetBitmap(bmpsize)
         self.his_icon = il.Add(trgif)
         
-        trgif = Icons["addshaded"].GetBitmap(bmpsize)
+        trgif = icons["addShaded"].GetBitmap(bmpsize)
         self.shaded_icon = il.Add(trgif)
         
-        trgif = Icons["addrarrow"].GetBitmap(bmpsize)
+        trgif = icons["addRArrow"].GetBitmap(bmpsize)
         self.rarrow_icon = il.Add(trgif)
         
-        trgif = Icons["addrnum"].GetBitmap(bmpsize)
+        trgif = icons["addRNum"].GetBitmap(bmpsize)
         self.rnum_icon = il.Add(trgif)
         
-        trgif = Icons["addvect"].GetBitmap(bmpsize)
+        trgif = icons["addVect"].GetBitmap(bmpsize)
         self.vect_icon = il.Add(trgif)
         
-        trgif = Icons["addthematic"].GetBitmap(bmpsize)
+        trgif = icons["addThematic"].GetBitmap(bmpsize)
         self.theme_icon = il.Add(trgif)
         
-        trgif = Icons["addchart"].GetBitmap(bmpsize)
+        trgif = icons["addChart"].GetBitmap(bmpsize)
         self.chart_icon = il.Add(trgif)
         
-        trgif = Icons["addgrid"].GetBitmap(bmpsize)
+        trgif = icons["addGrid"].GetBitmap(bmpsize)
         self.grid_icon = il.Add(trgif)
         
-        trgif = Icons["addgeodesic"].GetBitmap(bmpsize)
+        trgif = icons["addGeodesic"].GetBitmap(bmpsize)
         self.geodesic_icon = il.Add(trgif)
         
-        trgif = Icons["addrhumb"].GetBitmap(bmpsize)
+        trgif = icons["addRhumb"].GetBitmap(bmpsize)
         self.rhumb_icon = il.Add(trgif)
         
-        trgif = Icons["addlabels"].GetBitmap(bmpsize)
+        trgif = icons["addLabels"].GetBitmap(bmpsize)
         self.labels_icon = il.Add(trgif)
         
-        trgif = Icons["addcmd"].GetBitmap(bmpsize)
+        trgif = icons["addCmd"].GetBitmap(bmpsize)
         self.cmd_icon = il.Add(trgif)
         
         self.AssignImageList(il)
@@ -199,6 +204,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 +235,7 @@
         """
         if self.rerender:
             if self.mapdisplay.statusbarWin['render'].GetValue():
-                self.mapdisplay.MapWindow.UpdateMap(render=True)
+                self.mapdisplay.MapWindow.UpdateMap(render = True)
 
         event.Skip()
         
@@ -236,166 +256,160 @@
             return
 
         ltype = self.GetPyData(self.layer_selected)[0]['type']
-
+        mapLayer = self.GetPyData(self.layer_selected)[0]['maplayer']
+        
         Debug.msg (4, "LayerTree.OnContextMenu: layertype=%s" % \
                        ltype)
 
-        if not hasattr (self, "popupID1"):
-            self.popupID1 = wx.NewId()
-            self.popupID2 = wx.NewId()
-            self.popupID3 = wx.NewId()
-            self.popupID4 = wx.NewId()
-            self.popupID5 = wx.NewId()
-            self.popupID6 = wx.NewId()
-            self.popupID7 = wx.NewId()
-            self.popupID8 = wx.NewId()
-            self.popupID9 = wx.NewId()
-            self.popupID10 = wx.NewId()
-            self.popupID11 = wx.NewId() # nviz
-            self.popupID12 = wx.NewId()
-            self.popupID13 = wx.NewId()
-            self.popupID14 = wx.NewId()
-            self.popupID15 = wx.NewId()
-            self.popupID16 = wx.NewId()
-
+        if not hasattr (self, "popupID"):
+            self.popupID = dict()
+            for key in ('remove', 'rename', 'opacity', 'nviz', 'zoom',
+                        'region', 'export', 'attr', 'edit0', 'edit1',
+                        'bgmap', 'topo', 'meta', 'null', 'zoom1', 'region1',
+                        'color', 'hist', 'prof', 'properties'):
+                self.popupID[key] = wx.NewId()
+        
         self.popupMenu = wx.Menu()
-
+        
         numSelected = len(self.GetSelections())
         
-        # general item
-        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.popupID['remove'], text = _("Remove"))
+        self.Bind(wx.EVT_MENU, self.lmgr.OnDeleteLayer, id = self.popupID['remove'])
+        
+        if ltype != "command":
+            self.popupMenu.Append(self.popupID['rename'], text = _("Rename"))
+            self.Bind(wx.EVT_MENU, self.OnRenameLayer, id = self.popupID['rename'])
             if numSelected > 1:
-                self.popupMenu.Enable(self.popupID2, False)
-            
+                self.popupMenu.Enable(self.popupID['rename'], False)
+        
         # map layer items
-        if ltype != "group" and \
-                ltype != "command":
+        if ltype not in ("group", "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.popupID['opacity'], text = _("Change opacity level"))
+            self.Bind(wx.EVT_MENU, self.OnPopupOpacityLevel, id = self.popupID['opacity'])
+            self.popupMenu.Append(self.popupID['properties'], text = _("Properties"))
+            self.Bind(wx.EVT_MENU, self.OnPopupProperties, id = self.popupID['properties'])
             
+            if numSelected > 1:
+                self.popupMenu.Enable(self.popupID['opacity'], False)
+                self.popupMenu.Enable(self.popupID['properties'], False)
+            
             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.popupMenu.Append(self.popupID['nviz'], _("3D view properties"))
+                self.Bind (wx.EVT_MENU, self.OnNvizProperties, id = self.popupID['nviz'])
             
             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)
-            if numSelected > 1:
-                self.popupMenu.Enable(self.popupID8, False)
-                self.popupMenu.Enable(self.popupID3, False)
-            
+                self.popupMenu.Append(self.popupID['zoom'], text = _("Zoom to selected map(s)"))
+                self.Bind(wx.EVT_MENU, self.mapdisplay.OnZoomToMap, id = self.popupID['zoom'])
+                self.popupMenu.Append(self.popupID['region'], text = _("Set computational region from selected map(s)"))
+                self.Bind(wx.EVT_MENU, self.OnSetCompRegFromMap, id = self.popupID['region'])
+        
         # specific items
         try:
             mltype = self.GetPyData(self.layer_selected)[0]['type']
         except:
             mltype = None
-        #
+        
         # vector layers (specific items)
-        #
         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.popupID['export'], text = _("Export"))
+            self.Bind(wx.EVT_MENU, lambda x: self.lmgr.OnMenuCmd(cmd = ['v.out.ogr',
+                                                                        'input=%s' % mapLayer.GetName()]),
+                      id = self.popupID['export'])
+            
+            self.popupMenu.AppendSeparator()
+            self.popupMenu.Append(self.popupID['attr'], text = _("Show attribute data"))
+            self.Bind(wx.EVT_MENU, self.lmgr.OnShowAttributeTable, id = self.popupID['attr'])
 
-            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.popupMenu.Append(self.popupID['edit0'], text = _("Start editing"))
+            self.popupMenu.Append(self.popupID['edit1'], text = _("Stop editing"))
+            self.popupMenu.Enable(self.popupID['edit1'], False)
+            self.Bind (wx.EVT_MENU, self.OnStartEditing, id = self.popupID['edit0'])
+            self.Bind (wx.EVT_MENU, self.OnStopEditing,  id = self.popupID['edit1'])
+            
             layer = self.GetPyData(self.layer_selected)[0]['maplayer']
             # enable editing only for vector map layers available in the current mapset
             digitToolbar = self.mapdisplay.toolbars['vdigit']
             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():
-                    self.popupMenu.Check(self.popupID14, True)
+                self.popupMenu.Append(self.popupID['bgmap'],
+                                      text = _("Use as background vector map for digitizer"),
+                                      kind = wx.ITEM_CHECK)
+                self.Bind(wx.EVT_MENU, self.OnSetBgMap, id = self.popupID['bgmap'])
+                if UserSettings.Get(group = 'vdigit', key = 'bgmap', subkey = 'value',
+                                    internal = True) == layer.GetName():
+                    self.popupMenu.Check(self.popupID['bgmap'], True)
             
-            self.popupMenu.Append(self.popupID16, text=_("Rebuild topology"))
-            self.Bind(wx.EVT_MENU, self.OnTopology, id=self.popupID16)
-
+            self.popupMenu.Append(self.popupID['topo'], text = _("Rebuild topology"))
+            self.Bind(wx.EVT_MENU, self.OnTopology, id = self.popupID['topo'])
+            
             if layer.GetMapset() != grass.gisenv()['MAPSET']:
                 # only vector map in current mapset can be edited
-                self.popupMenu.Enable (self.popupID5, False)
-                self.popupMenu.Enable (self.popupID6, False)
-                self.popupMenu.Enable (self.popupID16, False)
+                self.popupMenu.Enable (self.popupID['edit0'], False)
+                self.popupMenu.Enable (self.popupID['edit1'], False)
+                self.popupMenu.Enable (self.popupID['topo'], False)
             elif digitToolbar and digitToolbar.GetLayer():
                 # vector map already edited
                 vdigitLayer = digitToolbar.GetLayer()
                 if vdigitLayer is layer:
-                    # disable 'start editing'
-                    self.popupMenu.Enable (self.popupID5, False)
-                    # enable 'stop editing'
-                    self.popupMenu.Enable(self.popupID6, True)
-                    # disable 'remove'
-                    self.popupMenu.Enable(self.popupID1, False)
-                    # disable 'bgmap'
-                    self.popupMenu.Enable(self.popupID14, False)
-                    # disable 'topology'
-                    self.popupMenu.Enable (self.popupID16, False)
+                    self.popupMenu.Enable(self.popupID['edit0'],  False)
+                    self.popupMenu.Enable(self.popupID['edit1'],  True)
+                    self.popupMenu.Enable(self.popupID['remove'], False)
+                    self.popupMenu.Enable(self.popupID['bgmap'],  False)
+                    self.popupMenu.Enable(self.popupID['topo'],   False)
                 else:
-                    # disable 'start editing'
-                    self.popupMenu.Enable(self.popupID5, False)
-                    # disable 'stop editing'
-                    self.popupMenu.Enable(self.popupID6, False)
-                    # enable 'bgmap'
-                    self.popupMenu.Enable(self.popupID14, True)
+                    self.popupMenu.Enable(self.popupID['edit0'], False)
+                    self.popupMenu.Enable(self.popupID['edit1'], False)
+                    self.popupMenu.Enable(self.popupID['bgmap'], True)
             
-            self.popupMenu.Append(self.popupID7, _("Metadata"))
-            self.Bind (wx.EVT_MENU, self.OnMetadata, id=self.popupID7)
+            self.popupMenu.Append(self.popupID['meta'], _("Metadata"))
+            self.Bind (wx.EVT_MENU, self.OnMetadata, id = self.popupID['meta'])
             if numSelected > 1:
-                self.popupMenu.Enable(self.popupID4, False)
-                self.popupMenu.Enable(self.popupID5, False)
-                self.popupMenu.Enable(self.popupID6, False)
-                self.popupMenu.Enable(self.popupID7, False)
-                self.popupMenu.Enable(self.popupID14, False)
+                self.popupMenu.Enable(self.popupID['attr'],   False)
+                self.popupMenu.Enable(self.popupID['edit0'],  False)
+                self.popupMenu.Enable(self.popupID['edit1'],  False)
+                self.popupMenu.Enable(self.popupID['meta'],   False)
+                self.popupMenu.Enable(self.popupID['bgmap'],  False)
+                self.popupMenu.Enable(self.popupID['topo'],   False)
+                self.popupMenu.Enable(self.popupID['export'], False)
         
-        #
         # 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.popupID['zoom1'], text = _("Zoom to selected map(s) (ignore NULLs)"))
+            self.Bind(wx.EVT_MENU, self.mapdisplay.OnZoomToRaster, id = self.popupID['zoom1'])
+            self.popupMenu.Append(self.popupID['region1'], text = _("Set computational region from selected map(s) (ignore NULLs)"))
+            self.Bind(wx.EVT_MENU, self.OnSetCompRegFromRaster, id = self.popupID['region1'])
+            
             self.popupMenu.AppendSeparator()
-            self.popupMenu.Append(self.popupID15, _("Set color table"))
-            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.popupMenu.Append(self.popupID5, _("Profile"))
-            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.popupMenu.Append(self.popupID['export'], text = _("Export"))
+            self.Bind(wx.EVT_MENU, lambda x: self.lmgr.OnMenuCmd(cmd = ['r.out.gdal',
+                                                                        'input=%s' % mapLayer.GetName()]),
+                      id = self.popupID['export'])
             
+            self.popupMenu.AppendSeparator()
+            self.popupMenu.Append(self.popupID['color'], _("Set color table"))
+            self.Bind (wx.EVT_MENU, self.OnColorTable, id = self.popupID['color'])
+            self.popupMenu.Append(self.popupID['hist'], _("Histogram"))
+            self.Bind (wx.EVT_MENU, self.OnHistogram, id = self.popupID['hist'])
+            self.popupMenu.Append(self.popupID['prof'], _("Profile"))
+            self.Bind (wx.EVT_MENU, self.OnProfile, id = self.popupID['prof'])
+            self.popupMenu.Append(self.popupID['meta'], _("Metadata"))
+            self.Bind (wx.EVT_MENU, self.OnMetadata, id = self.popupID['meta'])
+            
             if numSelected > 1:
-                self.popupMenu.Enable(self.popupID12, False)
-                self.popupMenu.Enable(self.popupID13, False)
-                self.popupMenu.Enable(self.popupID15, False)
-                self.popupMenu.Enable(self.popupID4, False)
-                self.popupMenu.Enable(self.popupID5, False)
-                self.popupMenu.Enable(self.popupID6, False)
-                self.popupMenu.Enable(self.popupID11, False)
-        
-        ## self.PopupMenu(self.popupMenu, pos)
+                self.popupMenu.Enable(self.popupID['zoom1'],   False)
+                self.popupMenu.Enable(self.popupID['region1'], False)
+                self.popupMenu.Enable(self.popupID['color'],   False)
+                self.popupMenu.Enable(self.popupID['hist'],    False)
+                self.popupMenu.Enable(self.popupID['prof'],    False)
+                self.popupMenu.Enable(self.popupID['meta'],    False)
+                self.popupMenu.Enable(self.popupID['nviz'],    False)
+                self.popupMenu.Enable(self.popupID['export'],  False)
+
         self.PopupMenu(self.popupMenu)
         self.popupMenu.Destroy()
-
+        
     def OnTopology(self, event):
         """!Rebuild topology of selected vector map"""
         mapLayer = self.GetPyData(self.layer_selected)[0]['maplayer']
@@ -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)"""
@@ -467,10 +481,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"):
@@ -481,17 +495,16 @@
 
         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()
         
     def OnColorTable(self, event):
         """!Set color table for raster map"""
         name = self.GetPyData(self.layer_selected)[0]['maplayer'].GetName()
-        menuform.GUI().ParseCommand(['r.colors',
-                                     'map=%s' % name],
-                                    parentframe=self)
+        menuform.GUI(parent = self).ParseCommand(['r.colors',
+                                                  'map=%s' % name])
         
     def OnHistogram(self, event):
         """
@@ -499,10 +512,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 +526,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)
             # show new display
             self.histogramFrame.Show()
 
@@ -538,28 +551,42 @@
         if not self.mapdisplay.toolbars['vdigit']: # enable tool
             self.mapdisplay.AddToolbar('vdigit')
         
-        if self.mapdisplay.toolbars['vdigit']:
-            self.mapdisplay.toolbars['vdigit'].StartEditing(maplayer)
+        if not self.mapdisplay.toolbars['vdigit']:
+            return
         
+        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
+        if self.lmgr:
+            self.lmgr.toolbar.Enable('vdigit', enable = True)
         
+        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)
@@ -572,8 +599,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:
@@ -620,8 +647,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.)
 
@@ -650,16 +677,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':
@@ -668,8 +695,8 @@
             grouptext = _('Layer group:') + str(self.groupnode)
             self.groupnode += 1
         else:
-            btnbmp = Icons["layeropts"].GetBitmap((16,16))
-            ctrl = buttons.GenBitmapButton(self, id=wx.ID_ANY, bitmap=btnbmp, size=(24,24))
+            btnbmp = Icons['layerManager']["layerOptions"].GetBitmap((16,16))
+            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
@@ -677,29 +704,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
@@ -708,55 +735,56 @@
         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
+        label =  _('(double click to set properties)') + ' ' * 35
         if ltype == 'raster':
             self.SetItemImage(layer, self.rast_icon)
-            self.SetItemText(layer, '%s %s' % (_('raster'), _('(double click to set properties)')))
+            self.SetItemText(layer, '%s %s' % (_('raster'), label))
         elif ltype == '3d-raster':
             self.SetItemImage(layer, self.rast3d_icon)
-            self.SetItemText(layer, '%s %s' % (_('3d raster'), _('(double click to set properties)')))
+            self.SetItemText(layer, '%s %s' % (_('3d raster'), label))
         elif ltype == 'rgb':
             self.SetItemImage(layer, self.rgb_icon)
-            self.SetItemText(layer, '%s %s' % (_('RGB'), _('(double click to set properties)')))
+            self.SetItemText(layer, '%s %s' % (_('RGB'), label))
         elif ltype == 'his':
             self.SetItemImage(layer, self.his_icon)
-            self.SetItemText(layer, '%s %s' % (_('HIS'), _('(double click to set properties)')))
+            self.SetItemText(layer, '%s %s' % (_('HIS'), label))
         elif ltype == 'shaded':
             self.SetItemImage(layer, self.shaded_icon)
-            self.SetItemText(layer, '%s %s' % (_('Shaded relief'), _('(double click to set properties)')))
+            self.SetItemText(layer, '%s %s' % (_('Shaded relief'), label))
         elif ltype == 'rastnum':
             self.SetItemImage(layer, self.rnum_icon)
-            self.SetItemText(layer, '%s %s' % (_('raster cell numbers'), _('(double click to set properties)')))
+            self.SetItemText(layer, '%s %s' % (_('raster cell numbers'), label))
         elif ltype == 'rastarrow':
             self.SetItemImage(layer, self.rarrow_icon)
-            self.SetItemText(layer, '%s %s' % (_('raster flow arrows'), _('(double click to set properties)')))
+            self.SetItemText(layer, '%s %s' % (_('raster flow arrows'), label))
         elif ltype == 'vector':
             self.SetItemImage(layer, self.vect_icon)
-            self.SetItemText(layer, '%s %s' % (_('vector'), _('(double click to set properties)')))
+            self.SetItemText(layer, '%s %s' % (_('vector'), label))
         elif ltype == 'thememap':
             self.SetItemImage(layer, self.theme_icon)
-            self.SetItemText(layer, '%s %s' % (_('thematic map'), _('(double click to set properties)')))
+            self.SetItemText(layer, '%s %s' % (_('thematic map'), label))
         elif ltype == 'themechart':
             self.SetItemImage(layer, self.chart_icon)
-            self.SetItemText(layer, '%s %s' % (_('thematic charts'), _('(double click to set properties)')))
+            self.SetItemText(layer, '%s %s' % (_('thematic charts'), label))
         elif ltype == 'grid':
             self.SetItemImage(layer, self.grid_icon)
-            self.SetItemText(layer, '%s %s' % (_('grid'), _('(double click to set properties)')))
+            self.SetItemText(layer, '%s %s' % (_('grid'), label))
         elif ltype == 'geodesic':
             self.SetItemImage(layer, self.geodesic_icon)
-            self.SetItemText(layer, '%s %s' % (_('geodesic line'), _('(double click to set properties)')))
+            self.SetItemText(layer, '%s %s' % (_('geodesic line'), label))
         elif ltype == 'rhumb':
             self.SetItemImage(layer, self.rhumb_icon)
-            self.SetItemText(layer, '%s %s' % (_('rhumbline'), _('(double click to set properties)')))
+            self.SetItemText(layer, '%s %s' % (_('rhumbline'), label))
         elif ltype == 'labels':
             self.SetItemImage(layer, self.labels_icon)
-            self.SetItemText(layer, '%s %s' % (_('vector labels'), _('(double click to set properties)')))
+            self.SetItemText(layer, '%s %s' % (_('vector labels'), label))
         elif ltype == 'command':
             self.SetItemImage(layer, self.cmd_icon)
         elif ltype == 'group':
@@ -810,15 +838,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,
@@ -840,13 +868,13 @@
         
         # 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 \
+        if 'propwin' in self.GetPyData(layer)[0] and \
                 self.GetPyData(layer)[0]['propwin'] is not None:
             # recycle GUI dialogs
             win = self.GetPyData(layer)[0]['propwin']
@@ -867,10 +895,9 @@
                    ltype)
 
         if self.GetPyData(layer)[0]['cmd']:
-            module = menuform.GUI()
+            module = menuform.GUI(parent = self, show = show, centreOnParent = False)
             module.ParseCommand(self.GetPyData(layer)[0]['cmd'],
-                                completed=(self.GetOptData,layer,params),
-                                parentframe=self, show=show)
+                                completed = (self.GetOptData,layer,params))
             
             self.GetPyData(layer)[0]['cmd'] = module.GetCmd()
         elif ltype == 'raster':
@@ -878,59 +905,70 @@
             
             if UserSettings.Get(group='cmd', key='rasterOverlay', subkey='enabled'):
                 cmd.append('-o')
-            menuform.GUI().ParseCommand(cmd, completed=(self.GetOptData,layer,params),
-                                        parentframe=self)
+            
+            menuform.GUI(parent = self, centreOnParent = False).ParseCommand(cmd,
+                                                                             completed = (self.GetOptData,layer,params))
+                         
         elif ltype == '3d-raster':
             cmd = ['d.rast3d']
-            menuform.GUI().ParseCommand(cmd, completed=(self.GetOptData,layer,params),
-                                        parentframe=self)
+            menuform.GUI(parent = self, centreOnParent = False).ParseCommand(cmd,
+                                                                             completed = (self.GetOptData,layer,params))
+                                        
         elif ltype == 'rgb':
-            menuform.GUI().ParseCommand(['d.rgb'], completed=(self.GetOptData,layer,params),
-                                        parentframe=self)
+            menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.rgb'],
+                                                                             completed = (self.GetOptData,layer,params))
+            
         elif ltype == 'his':
-            menuform.GUI().ParseCommand(['d.his'], completed=(self.GetOptData,layer,params),
-                                        parentframe=self)
+            menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.his'],
+                                                                             completed = (self.GetOptData,layer,params))
+            
         elif ltype == 'shaded':
-            menuform.GUI().ParseCommand(['d.shadedmap'], completed=(self.GetOptData,layer,params),
-                                        parentframe=self)
+            menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.shadedmap'],
+                                                                             completed = (self.GetOptData,layer,params))
+            
         elif ltype == 'rastarrow':
-            menuform.GUI().ParseCommand(['d.rast.arrow'], completed=(self.GetOptData,layer,params),
-                                        parentframe=self)
+            menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.rast.arrow'],
+                                                                             completed = (self.GetOptData,layer,params))
+            
         elif ltype == 'rastnum':
-            menuform.GUI().ParseCommand(['d.rast.num'], completed=(self.GetOptData,layer,params),
-                                        parentframe=self)
+            menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.rast.num'],
+                                                                             completed = (self.GetOptData,layer,params))
+            
         elif ltype == 'vector':
-            types = ''
-            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(',')
+            types = list()
+            for ftype in ['point', 'line', 'boundary', 'centroid', 'area', 'face']:
+                if UserSettings.Get(group = 'cmd', key = 'showType', subkey = [ftype, 'enabled']):
+                    types.append(ftype)
             
-            menuform.GUI().ParseCommand(['d.vect', 'type=%s' % types],
-                                         completed=(self.GetOptData,layer,params),
-                                         parentframe=self)
+            menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.vect', 'type=%s' % ','.join(types)],
+                                                                             completed = (self.GetOptData,layer,params))
+            
         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.vect.thematic', '-s'], 
-                                        completed=(self.GetOptData,layer,params),
-                                        parentframe=self)
+            menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.vect.thematic', '-s'], 
+                                                                             completed = (self.GetOptData,layer,params))
+            
         elif ltype == 'themechart':
-            menuform.GUI().ParseCommand(['d.vect.chart'],
-                                        completed=(self.GetOptData,layer,params),
-                                        parentframe=self)
+            menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.vect.chart'],
+                                                                             completed = (self.GetOptData,layer,params))
+            
         elif ltype == 'grid':
-            menuform.GUI().ParseCommand(['d.grid'], completed=(self.GetOptData,layer,params),
-                                        parentframe=self)
+            menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.grid'],
+                                                                             completed = (self.GetOptData,layer,params))
+            
         elif ltype == 'geodesic':
-            menuform.GUI().ParseCommand(['d.geodesic'], completed=(self.GetOptData,layer,params),
-                                        parentframe=self)
+            menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.geodesic'],
+                                                                             completed = (self.GetOptData,layer,params))
+            
         elif ltype == 'rhumb':
-            menuform.GUI().ParseCommand(['d.rhumbline'], completed=(self.GetOptData,layer,params),
-                                        parentframe=self)
+            menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.rhumbline'],
+                                                                             completed = (self.GetOptData,layer,params))
+            
         elif ltype == 'labels':
-            menuform.GUI().ParseCommand(['d.labels'], completed=(self.GetOptData,layer,params),
-                                        parentframe=self)
+            menuform.GUI(parent = self, centreOnParent = False).ParseCommand(['d.labels'],
+                                                                             completed = (self.GetOptData,layer,params))
+            
         elif ltype == 'cmdlayer':
             pass
         elif ltype == 'group':
@@ -983,10 +1021,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()
 
@@ -1020,7 +1058,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
@@ -1082,6 +1120,22 @@
             event.Veto()
             return
         
+        digitToolbar = self.mapdisplay.toolbars['vdigit']
+        if digitToolbar:
+            mapLayer = self.GetPyData(layer)[0]['maplayer']
+            bgmap = UserSettings.Get(group = 'vdigit', key = 'bgmap', subkey = 'value',
+                                     internal = True)
+            
+        if digitToolbar:
+            if digitToolbar.GetLayer() == mapLayer:
+                self._setGradient('vdigit')
+            elif bgmap == mapLayer.GetName():
+                self._setGradient('bgmap')
+            else:
+                self._setGradient()
+        else:
+            self._setGradient()
+        
         self.layer_selected = layer
         
         try:
@@ -1096,21 +1150,19 @@
                 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'):
@@ -1120,9 +1172,7 @@
                 self.mapdisplay.MapWindow.ZoomToMap(layers = [mapLayer,],
                                                     render = render)
         
-        #
         # update nviz tools
-        #
         if self.mapdisplay.toolbars['nviz'] and \
                 self.GetPyData(self.layer_selected) is not None:
             if self.layer_selected.IsChecked():
@@ -1182,21 +1232,16 @@
             (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)
-
+        
         # delete layer at original position
         try:
             self.Delete(old) # entry in render.Map layers list automatically deleted by OnDeleteLayer handler
         except AttributeError:
-            # FIXME being ugly (item.SetWindow(None))
             pass
 
-        # reorder layers in render.Map to match new order after drag and drop
-        #self.ReorderLayers()
-
         # redraw map if auto-rendering is enabled
         self.rerender = True
         self.reorder = True
@@ -1204,7 +1249,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" % \
@@ -1216,8 +1261,8 @@
         text    = self.GetItemText(dragItem)
         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))
+            btnbmp = Icons['layerManager']["layerOptions"].GetBitmap((16,16))
+            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)
@@ -1225,11 +1270,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)
@@ -1252,27 +1297,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))
@@ -1281,10 +1326,8 @@
         else:
             self.GetPyData(newItem)[0]['ctrl'] = None
             
-        self.CheckItem(newItem, checked=checked) # causes a new render
-
-        # newItem.SetHeight(TREE_ITEM_HEIGHT)
-
+        self.CheckItem(newItem, checked = checked) # causes a new render
+        
         return newItem
 
     def _getLayerName(self, item):
@@ -1359,8 +1402,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()
         
@@ -1415,7 +1458,7 @@
         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
@@ -1423,15 +1466,15 @@
                 if not found:
                     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
@@ -1467,7 +1510,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/branches/releasebranch_6_4/gui/wxpython/gui_modules/location_wizard.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/location_wizard.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/location_wizard.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -709,7 +709,7 @@
         id  = event.GetId()
         val = event.GetString()
         
-        if not self.pparam.has_key(id):
+        if id not in self.pparam:
             event.Skip()
             return
 
@@ -1729,7 +1729,7 @@
         #
         # define wizard image
         #
-        imagePath = os.path.join(globalvar.ETCWXDIR, "images", "loc_wizard_qgis.png")
+        imagePath = os.path.join(globalvar.ETCIMGDIR, "loc_wizard_qgis.png")
         wizbmp = wx.Image(imagePath, wx.BITMAP_TYPE_PNG)
         wizbmp = wizbmp.ConvertToBitmap()
         
@@ -2143,8 +2143,8 @@
         #
         # image
         #
-        self.img = wx.Image(os.path.join(globalvar.ETCWXDIR, "images",
-                                         "qgis_world.png"), wx.BITMAP_TYPE_PNG).ConvertToBitmap()
+        self.img = wx.Image(os.path.join(globalvar.ETCIMGDIR, "qgis_world.png"),
+                            wx.BITMAP_TYPE_PNG).ConvertToBitmap()
         
         #
         # set current working environment to PERMANENT mapset

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/mapdisp.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/mapdisp.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/mapdisp.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -14,7 +14,7 @@
 Usage:
 python mapdisp.py monitor-identifier /path/to/command/file
 
-(C) 2006-2010 by the GRASS Development Team
+(C) 2006-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.
@@ -71,16 +71,11 @@
 from mapdisp_command import Command
 from mapdisp_window import BufferedWindow
 
-import images
-imagepath = images.__path__[0]
-sys.path.append(imagepath)
-
-###
-### global variables
-###
 # for standalone app
 cmdfilename = None
 
+haveCtypes = False
+
 class MapFrame(wx.Frame):
     """!Main frame for map display window. Drawing takes place in
     child double buffered drawing window.
@@ -108,7 +103,7 @@
         self.layerbook  = notebook  # Layer Manager layer tree notebook
         self.parent     = parent
         
-        if not kwargs.has_key('name'):
+        if 'name' not in kwargs:
             kwargs['name'] = 'MapWindow'
         wx.Frame.__init__(self, parent, id, title, style = style, **kwargs)
         
@@ -245,13 +240,15 @@
         # default is 2D display mode
         self.MapWindow = self.MapWindow2D
         self.MapWindow.SetCursor(self.cursors["default"])
+        # used by vector digitizer
+        self.MapWindowVDigit = None
         # used by Nviz (3D display mode)
         self.MapWindow3D = None 
 
         #
         # initialize region values
         #
-        self.__InitDisplay() 
+        self._initDisplay() 
 
         #
         # Bind various events
@@ -275,11 +272,6 @@
         self.printopt = disp_print.PrintOptions(self, self.MapWindow)
         
         #
-        # Initialization of digitization tool
-        #
-        self.digit = None
-
-        #
         # Init zoom history
         #
         self.MapWindow.ZoomHistory(self.Map.region['n'],
@@ -298,6 +290,136 @@
 
         self.decorationDialog = None # decoration/overlays
 
+    def _addToolbarVDigit(self):
+        """!Add vector digitizer toolbar
+        """
+        from vdigit import haveVDigit
+        
+        if not haveVDigit:
+            from vdigit import errorMsg
+            msg = _("Unable to start wxGUI vector digitizer.\nDo you want to start "
+                    "TCL/TK digitizer (v.digit) instead?\n\n"
+                    "Details: %s" % errorMsg)
+            
+            self.toolbars['map'].combo.SetValue(_("2D view"))
+            dlg = wx.MessageDialog(parent = self,
+                                   message = msg,
+                                   caption=_("Vector digitizer failed"),
+                                   style = wx.YES_NO | wx.CENTRE)
+            if dlg.ShowModal() == wx.ID_YES:
+                mapName = self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].GetName()
+                self._layerManager.goutput.RunCmd(['v.digit', 'map=%s' % mapName],
+                                                  switchPage = False)
+            dlg.Destroy()
+            
+            self.toolbars['map'].combo.SetValue(_("2D view"))
+            return
+        
+        if self._layerManager:
+            log = self._layerManager.goutput
+        else:
+            log = None
+        
+        if not self.MapWindowVDigit:
+            from mapdisp_vdigit import VDigitWindow
+            self.MapWindowVDigit = VDigitWindow(self, id = wx.ID_ANY,
+                                                Map = self.Map, tree = self.tree,
+                                                lmgr = self._layerManager)
+            self.MapWindowVDigit.Show()
+        
+        self.MapWindow = self.MapWindowVDigit
+        
+        self._mgr.DetachPane(self.MapWindow2D)
+        self.MapWindow2D.Hide()
+        
+        self.toolbars['vdigit'] = toolbars.VDigitToolbar(parent = self, mapcontent = self.Map,
+                                                         layerTree = self.tree,
+                                                         log = log)
+        self.MapWindowVDigit.SetToolbar(self.toolbars['vdigit'])
+        
+        self._mgr.AddPane(self.MapWindowVDigit, wx.aui.AuiPaneInfo().CentrePane().
+                          Dockable(False).BestSize((-1,-1)).
+                          CloseButton(False).DestroyOnClose(True).
+                          Layer(0))
+        self._mgr.AddPane(self.toolbars['vdigit'],
+                          wx.aui.AuiPaneInfo().
+                          Name("vdigittoolbar").Caption(_("Vector digitizer toolbar")).
+                          ToolbarPane().Top().Row(1).
+                          LeftDockable(False).RightDockable(False).
+                          BottomDockable(False).TopDockable(True).
+                          CloseButton(False).Layer(2).
+                          BestSize((self.toolbars['vdigit'].GetSize())))
+        # change mouse to draw digitized line
+        self.MapWindow.mouse['box'] = "point"
+        self.MapWindow.zoomtype     = 0
+        self.MapWindow.pen          = wx.Pen(colour = 'red',   width = 2, style = wx.SOLID)
+        self.MapWindow.polypen      = wx.Pen(colour = 'green', width = 2, style = wx.SOLID)
+
+    def _addToolbarNviz(self):
+        """!Add 3D view mode toolbar
+        """
+        import nviz
+        
+        # check for GLCanvas and OpenGL
+        if not nviz.haveNviz:
+            self.toolbars['map'].combo.SetValue (_("2D view"))
+            wx.MessageBox(parent = self,
+                          message = _("Unable to switch to 3D display mode.\nThe Nviz python extension "
+                                      "was not found or loaded properly.\n"
+                                      "Switching back to 2D display mode.\n\nDetails: %s" % nviz.errorMsg),
+                          caption = _("Error"),
+                          style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
+            return
+        
+        # add Nviz toolbar and disable 2D display mode tools
+        self.toolbars['nviz'] = toolbars.NvizToolbar(self, self.Map)
+        self.toolbars['map'].Enable2D(False)
+        
+        # update status bar
+        self.statusbarWin['toggle'].Enable(False)
+        
+        # erase map window
+        self.MapWindow.EraseMap()
+        
+        self._layerManager.goutput.WriteCmdLog(_("Starting 3D view mode..."))
+        self.statusbar.SetStatusText(_("Please wait, loading data..."), 0)
+        
+        # create GL window & NVIZ toolbar
+        if not self.MapWindow3D:
+            self.MapWindow3D = nviz.GLWindow(self, id = wx.ID_ANY,
+                                             Map = self.Map, tree = self.tree, lmgr = self._layerManager)
+            self.MapWindow = self.MapWindow3D
+            self.MapWindow.SetCursor(self.cursors["default"])
+            
+                # add Nviz notebookpage
+            self._layerManager.AddNviz()
+            
+            self.MapWindow3D.OnPaint(None) # -> LoadData
+            self.MapWindow3D.Show()
+            self.MapWindow3D.UpdateView(None)
+        else:
+            self.MapWindow = self.MapWindow3D
+            # add Nviz notebookpage
+            self._layerManager.AddNviz()
+        
+        # switch from MapWindow to MapWindowGL
+        # add nviz toolbar
+        self._mgr.DetachPane(self.MapWindow2D)
+        self.MapWindow2D.Hide()
+        self._mgr.AddPane(self.MapWindow3D, wx.aui.AuiPaneInfo().CentrePane().
+                          Dockable(False).BestSize((-1,-1)).
+                          CloseButton(False).DestroyOnClose(True).
+                          Layer(0))
+        self._mgr.AddPane(self.toolbars['nviz'],
+                              wx.aui.AuiPaneInfo().
+                          Name("nviztoolbar").Caption(_("3D view toolbar")).
+                          ToolbarPane().Top().Row(1).
+                          LeftDockable(False).RightDockable(False).
+                          BottomDockable(False).TopDockable(True).
+                          CloseButton(False).Layer(2))
+        
+        self.SetStatusText("", 0)
+        
     def AddToolbar(self, name):
         """!Add defined toolbar to the window
         
@@ -311,7 +433,7 @@
         # default toolbar
         if name == "map":
             self.toolbars['map'] = toolbars.MapToolbar(self, self.Map)
-
+            
             self._mgr.AddPane(self.toolbars['map'],
                               wx.aui.AuiPaneInfo().
                               Name("maptoolbar").Caption(_("Map toolbar")).
@@ -323,53 +445,11 @@
 	
         # vector digitizer
         elif name == "vdigit":
-            from vdigit import haveVDigit
-            if not haveVDigit:
-                from vdigit import errorMsg
-                msg = _("Unable to start wxGUI vector digitizer.\nDo you want to start "
-                        "TCL/TK digitizer (v.digit) instead?\n\n"
-                        "Details: %s" % errorMsg)
-                
-                self.toolbars['map'].combo.SetValue (_("2D view"))
-                dlg = wx.MessageDialog(parent = self,
-                                       message = msg,
-                                       caption=_("Vector digitizer failed"),
-                                       style = wx.YES_NO | wx.CENTRE)
-                if dlg.ShowModal() == wx.ID_YES:
-                    mapName = self.tree.GetPyData(self.tree.layer_selected)[0]['maplayer'].GetName()
-                    self._layerManager.goutput.RunCmd(['v.digit', 'map=%s' % mapName],
-                                                      switchPage=False)
-                dlg.Destroy()
-                
-                self.toolbars['map'].combo.SetValue (_("2D view"))
-                return
-            
-            if self._layerManager:
-                log = self._layerManager.goutput
-            else:
-                log = None
-            self.toolbars['vdigit'] = toolbars.VDigitToolbar(parent = self, mapcontent = self.Map,
-                                                             layerTree = self.tree,
-                                                             log = log)
-            
-            self._mgr.AddPane(self.toolbars['vdigit'],
-                              wx.aui.AuiPaneInfo().
-                              Name("vdigittoolbar").Caption(_("Vector digitizer toolbar")).
-                              ToolbarPane().Top().Row(1).
-                              LeftDockable(False).RightDockable(False).
-                              BottomDockable(False).TopDockable(True).
-                              CloseButton(False).Layer(2).
-                              BestSize((self.toolbars['vdigit'].GetSize())))
-            
-            # change mouse to draw digitized line
-            self.MapWindow.mouse['box'] = "point"
-            self.MapWindow.zoomtype = 0
-            self.MapWindow.pen     = wx.Pen(colour = 'red',   width = 2, style = wx.SOLID)
-            self.MapWindow.polypen = wx.Pen(colour = 'green', width = 2, style = wx.SOLID)
+            self._addToolbarVDigit()
         # georectifier
         elif name == "georect":
             self.toolbars['georect'] = toolbars.GRToolbar(self, self.Map)
-
+            
             self._mgr.AddPane(self.toolbars['georect'],
                               wx.aui.AuiPaneInfo().
                               Name("georecttoolbar").Caption(_("Georectification toolbar")).
@@ -379,91 +459,36 @@
                               CloseButton(False).Layer(2))
         # nviz
         elif name == "nviz":
-            import nviz
-            
-            # check for GLCanvas and OpenGL
-            if not nviz.haveNviz:
-                self.toolbars['map'].combo.SetValue (_("2D view"))
-                wx.MessageBox(parent = self,
-                              message = _("Unable to switch to 3D display mode.\nThe Nviz python extension "
-                                          "was not found or loaded properly.\n"
-                                          "Switching back to 2D display mode.\n\nDetails: %s" % nviz.errorMsg),
-                              caption = _("Error"),
-                              style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
-                return
-            
-            # add Nviz toolbar and disable 2D display mode tools
-            self.toolbars['nviz'] = toolbars.NvizToolbar(self, self.Map)
-            self.toolbars['map'].Enable2D(False)
-            
-            # update status bar
-            self.statusbarWin['toggle'].Enable(False)
-
-            # erase map window
-            self.MapWindow.EraseMap()
-            
-            self._layerManager.goutput.WriteCmdLog(_("Starting 3D view mode..."))
-            self.statusbar.SetStatusText(_("Please wait, loading data..."), 0)
-            
-            # create GL window & NVIZ toolbar
-            if not self.MapWindow3D:
-                self.MapWindow3D = nviz.GLWindow(self, id = wx.ID_ANY,
-                                                 Map = self.Map, tree = self.tree, lmgr = self._layerManager)
-                self.MapWindow = self.MapWindow3D
-                self.MapWindow.SetCursor(self.cursors["default"])
-                
-                # add Nviz notebookpage
-                self._layerManager.AddNviz()
-                
-                self.MapWindow3D.OnPaint(None) # -> LoadData
-                self.MapWindow3D.Show()
-                self.MapWindow3D.UpdateView(None)
-            else:
-                self.MapWindow = self.MapWindow3D
-                # add Nviz notebookpage
-                self._layerManager.AddNviz()
-            
-            # switch from MapWindow to MapWindowGL
-            # add nviz toolbar
-            self._mgr.DetachPane(self.MapWindow2D)
-            self.MapWindow2D.Hide()
-            self._mgr.AddPane(self.MapWindow3D, wx.aui.AuiPaneInfo().CentrePane().
-                              Dockable(False).BestSize((-1,-1)).
-                              CloseButton(False).DestroyOnClose(True).
-                              Layer(0))
-            self._mgr.AddPane(self.toolbars['nviz'],
-                              wx.aui.AuiPaneInfo().
-                              Name("nviztoolbar").Caption(_("3D view toolbar")).
-                              ToolbarPane().Top().Row(1).
-                              LeftDockable(False).RightDockable(False).
-                              BottomDockable(False).TopDockable(True).
-                              CloseButton(False).Layer(2))
-            
-            self.SetStatusText("", 0)
-            
+            self._addToolbarNviz()
+        
         self._mgr.Update()
-
+        
     def RemoveToolbar (self, name):
-        """!Removes toolbar from the window
+        """!Removes defined toolbar from the window
 
         @todo Only hide, activate by calling AddToolbar()
         """
         # cannot hide main toolbar
         if name == "map":
             return
-        elif name == "vdigit":
-            # TODO: not destroy only hide
-            self._mgr.DetachPane(self.toolbars['vdigit'])
-            self.toolbars['vdigit'].Destroy()
-        else:
-            self._mgr.DetachPane (self.toolbars[name])
-            self.toolbars[name].Destroy()
-
+        
+        self._mgr.DetachPane(self.toolbars[name])
+        self.toolbars[name].Destroy()
         self.toolbars[name] = None
-
-        if name == 'nviz':
+        
+        if name == 'vdigit':
+            self._mgr.DetachPane(self.MapWindowVDigit)
+            self.MapWindowVDigit.Hide()
+            self.MapWindow2D.Show()
+            self._mgr.AddPane(self.MapWindow2D, wx.aui.AuiPaneInfo().CentrePane().
+                              Dockable(False).BestSize((-1,-1)).
+                              CloseButton(False).DestroyOnClose(True).
+                              Layer(0))
+            self.MapWindow = self.MapWindow2D
+        
+        elif name == 'nviz':
             # unload data
-            #            self.MapWindow3D.Reset()
+            # self.MapWindow3D.Reset()
             # switch from MapWindowGL to MapWindow
             self._mgr.DetachPane(self.MapWindow3D)
             self.MapWindow3D.Hide()
@@ -477,28 +502,30 @@
             self._layerManager.RemoveNviz()
             
             self.MapWindow.UpdateMap()
-            
-        self.toolbars['map'].combo.SetValue (_("2D view"))
+        
+        self.toolbars['map'].combo.SetValue(_("2D view"))
         self.toolbars['map'].Enable2D(True)
         self.statusbarWin['toggle'].Enable(True)
-
+        
         self._mgr.Update()
 
-    def __InitDisplay(self):
+    def _initDisplay(self):
+        """!Initialize map display, set dimensions and map region
         """
-        Initialize map display, set dimensions and map region
-        """
+        if not grass.find_program('g.region', ['--help']):
+            sys.exit(_("GRASS module '%s' not found. Unable to start map "
+                       "display window.") % 'g.region')
+        
         self.width, self.height = self.GetClientSize()
-
-        Debug.msg(2, "MapFrame.__InitDisplay():")
+        
+        Debug.msg(2, "MapFrame._initDisplay():")
         self.Map.ChangeMapSize(self.GetClientSize())
         self.Map.region = self.Map.GetRegion() # g.region -upgc
         # self.Map.SetRegion() # adjust region to match display window
 
     def OnUpdateProgress(self, event):
+        """!Update progress bar info
         """
-        Update progress bar info
-        """
         self.statusbarWin['progress'].SetValue(event.value)
         
         event.Skip()
@@ -542,8 +569,8 @@
             self.MapWindow.ClearLines()
         
         # deselect features in vdigit
-        if self.toolbars['vdigit'] and self.digit:
-            self.digit.driver.SetSelected([])
+        if self.toolbars['vdigit']:
+            self.MapWindow.display.SetSelected([])
             self.MapWindow.UpdateMap(render = True, renderVector = True)
         else:
             self.MapWindow.UpdateMap(render = True)
@@ -1169,8 +1196,7 @@
             maplayer = self.toolbars['vdigit'].GetLayer()
             if maplayer:
                 self.toolbars['vdigit'].OnExit()
-                self.imgVectorMap = None
-
+        
         if self.toolbars['nviz']:
             self.toolbars['nviz'].OnExit()
         
@@ -1349,9 +1375,9 @@
         if hasattr(self, "tmpreg"):
             if self.tmpreg:
                 os.environ["GRASS_REGION"] = self.tmpreg
-            elif os.environ.has_key('GRASS_REGION'):
+            elif 'GRASS_REGION' in os.environ:
                 del os.environ["GRASS_REGION"]
-        elif os.environ.has_key('GRASS_REGION'):
+        elif 'GRASS_REGION' in os.environ:
             del os.environ["GRASS_REGION"]
         
         if hasattr(self, "tmpreg"):
@@ -1559,19 +1585,21 @@
         """
         point = wx.GetMousePosition()
         toolsmenu = wx.Menu()
+        icons = Icons['displayWindow']
+        
         # Add items to the menu
-        measure = wx.MenuItem(toolsmenu, wx.ID_ANY, Icons["measure"].GetLabel())
-        measure.SetBitmap(Icons["measure"].GetBitmap(self.iconsize))
+        measure = wx.MenuItem(toolsmenu, wx.ID_ANY, icons["measure"].GetLabel())
+        measure.SetBitmap(icons["measure"].GetBitmap(self.iconsize))
         toolsmenu.AppendItem(measure)
         self.Bind(wx.EVT_MENU, self.OnMeasure, measure)
-
-        profile = wx.MenuItem(toolsmenu, wx.ID_ANY, Icons["profile"].GetLabel())
-        profile.SetBitmap(Icons["profile"].GetBitmap(self.iconsize))
+        
+        profile = wx.MenuItem(toolsmenu, wx.ID_ANY, icons["profile"].GetLabel())
+        profile.SetBitmap(icons["profile"].GetBitmap(self.iconsize))
         toolsmenu.AppendItem(profile)
         self.Bind(wx.EVT_MENU, self.Profile, profile)
 
-        histogram = wx.MenuItem(toolsmenu, wx.ID_ANY, Icons["histogram"].GetLabel())
-        histogram.SetBitmap(Icons["histogram"].GetBitmap(self.iconsize))
+        histogram = wx.MenuItem(toolsmenu, wx.ID_ANY, icons["histogram"].GetLabel())
+        histogram.SetBitmap(icons["histogram"].GetBitmap(self.iconsize))
         toolsmenu.AppendItem(histogram)
         self.Bind(wx.EVT_MENU, self.Histogram, histogram)
 
@@ -1585,20 +1613,20 @@
         along transect drawn on map display
         """
         self.totaldist = 0.0 # total measured distance
-
-        # switch GIS Manager to output console to show measure results
+        
+        # switch Layer Manager to output console to show measure results
         self._layerManager.notebook.SetSelection(1)
-
+        
         # change mouse to draw line for measurement
         self.MapWindow.mouse['use'] = "measure"
         self.MapWindow.mouse['box'] = "line"
         self.MapWindow.zoomtype = 0
         self.MapWindow.pen     = wx.Pen(colour = 'red', width = 2, style = wx.SHORT_DASH)
         self.MapWindow.polypen = wx.Pen(colour = 'green', width = 2, style = wx.SHORT_DASH)
-
+        
         # change the cursor
         self.MapWindow.SetCursor(self.cursors["pencil"])
-
+        
         # initiating output
         style = self._layerManager.goutput.cmd_output.StyleWarning
         self._layerManager.goutput.WriteLog(_('Click and drag with left mouse button '
@@ -1607,17 +1635,22 @@
                                                 (os.linesep), style)
         if self.Map.projinfo['proj'] != 'xy':
             units = self.Map.projinfo['units']
-            style = self._layerManager.goutput.cmd_output.StyleCommand
-            self._layerManager.goutput.WriteLog(_('Measuring distance') + ' ('
-                                                + units + '):',
-                                                style)
+            self._layerManager.goutput.WriteCmdLog(_('Measuring distance') + ' ('
+                                                   + units + '):')
         else:
-            self._layerManager.goutput.WriteLog(_('Measuring distance:'),
-                                                style)
+            self._layerManager.goutput.WriteCmdLog(_('Measuring distance:'))
+        
         if self.Map.projinfo['proj'] == 'll':
-            self._layerManager.goutput.WriteWarning(_('Geodesic distance is not yet '
-                                                      'supported by this tool.\n'
-                                                      'Check future versions of GRASS.'))
+            try:
+                import grass.lib.gis as gislib
+                global haveCtypes
+                haveCtypes = True
+
+                gislib.G_begin_distance_calculations()
+            except ImportError, e:
+                self._layerManager.goutput.WriteWarning(_('Geodesic distance is not yet '
+                                                          'supported by this tool.\n'
+                                                          'Reason: %s' % e))
         
     def MeasureDist(self, beginpt, endpt):
         """!Calculate map distance from screen distance
@@ -1641,7 +1674,7 @@
             angle = int(math.degrees(math.atan2(north,east)) + 0.5)
             angle = 180 - angle
             if angle < 0:
-                angle = 360+angle
+                angle = 360 + angle
             
             mstring = '%s = %s %s\n%s = %s %s\n%s = %d %s\n%s' \
                 % (_('segment'), strdist, dunits,
@@ -1702,12 +1735,15 @@
                 divisor = 5280.0
             else:
                 outunits = 'ft'
-        elif 'degree' in mapunits:
+        elif 'degree' in mapunits and \
+                not haveCtypes:
             if dist < 1:
                 outunits = 'min'
                 divisor = (1/60.0)
             else:
                 outunits = 'deg'
+        else:
+            outunits = 'meters'
         
         # format numbers in a nice way
         if (dist/divisor) >= 2500.0:
@@ -1739,27 +1775,29 @@
         """
         point = wx.GetMousePosition()
         decmenu = wx.Menu()
+        icons = Icons['displayWindow']
+        
         # Add items to the menu
-        AddScale = wx.MenuItem(decmenu, wx.ID_ANY, Icons["addbarscale"].GetLabel())
-        AddScale.SetBitmap(Icons["addbarscale"].GetBitmap(self.iconsize))
+        AddScale = wx.MenuItem(decmenu, wx.ID_ANY, icons["addBarscale"].GetLabel())
+        AddScale.SetBitmap(icons["addBarscale"].GetBitmap(self.iconsize))
         decmenu.AppendItem(AddScale)
         self.Bind(wx.EVT_MENU, self.OnAddBarscale, AddScale)
-
-        AddLegend = wx.MenuItem(decmenu, wx.ID_ANY, Icons["addlegend"].GetLabel())
-        AddLegend.SetBitmap(Icons["addlegend"].GetBitmap(self.iconsize))
+        
+        AddLegend = wx.MenuItem(decmenu, wx.ID_ANY, icons["addLegend"].GetLabel())
+        AddLegend.SetBitmap(icons["addLegend"].GetBitmap(self.iconsize))
         decmenu.AppendItem(AddLegend)
         self.Bind(wx.EVT_MENU, self.OnAddLegend, AddLegend)
-
-        AddText = wx.MenuItem(decmenu, wx.ID_ANY, Icons["addtext"].GetLabel())
-        AddText.SetBitmap(Icons["addtext"].GetBitmap(self.iconsize))
+        
+        AddText = wx.MenuItem(decmenu, wx.ID_ANY, icons["addText"].GetLabel())
+        AddText.SetBitmap(icons["addText"].GetBitmap(self.iconsize))
         decmenu.AppendItem(AddText)
         self.Bind(wx.EVT_MENU, self.OnAddText, AddText)
-
+        
         # Popup the menu.  If an item is selected then its handler
         # will be called before PopupMenu returns.
         self.PopupMenu(decmenu)
         decmenu.Destroy()
-
+        
     def OnAddBarscale(self, event):
         """!Handler for scale/arrow map decoration menu selection.
         """
@@ -1923,7 +1961,7 @@
         zoommenu = wx.Menu()
         # Add items to the menu
 
-        zoomwind = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to computational region'))
+        zoomwind = wx.MenuItem(zoommenu, wx.ID_ANY, _('Zoom to computational region (set with g.region)'))
         zoommenu.AppendItem(zoomwind)
         self.Bind(wx.EVT_MENU, self.OnZoomToWind, zoomwind)
 

Added: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/mapdisp_vdigit.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/mapdisp_vdigit.py	                        (rev 0)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/mapdisp_vdigit.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -0,0 +1,1062 @@
+"""!
+ at package mapdisp_vdigit.py
+
+ at brief Map display canvas extended for vector digitizer
+
+See also vdigit.py, wxvdriver.py and wxvdigit.py
+
+Classes:
+ - VDigitWindow
+
+(C) 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.
+
+ at author Martin Landa <landa.martin gmail.com>
+"""
+
+import wx
+
+import dbm_dialogs
+
+from debug import Debug
+from mapdisp_window import BufferedWindow
+from preferences import globalSettings as UserSettings
+
+from vdigit import VDigitCategoryDialog
+from vdigit import VDigitZBulkDialog
+from vdigit import VDigitDuplicatesDialog
+
+class VDigitWindow(BufferedWindow):
+    """!A Buffered window extended for vector digitizer.
+    """
+    def __init__(self, parent, id = wx.ID_ANY,
+                 Map = None, tree = None, lmgr = None,
+                 style = wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs):
+        BufferedWindow.__init__(self, parent, id, Map, tree, lmgr,
+                                style, **kwargs)
+        
+        self.pdcVector = wx.PseudoDC()
+        self.toolbar   = self.parent.toolbars['vdigit']
+        self.digit     = None
+        
+        self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+        
+    def SetToolbar(self, toolbar):
+        """!Set up related toolbar
+        """
+        self.toolbar = toolbar
+        
+    def _onMotion(self, coord, precision):
+        """!Track mouse motion and update statusbar (see self.Motion)
+
+        @parem coord easting, northing
+        @param precision formatting precision
+        """
+        e, n = coord
+        
+        if self.toolbar.GetAction() != 'addLine' or \
+                self.toolbar.GetAction('type') not in ('line', 'boundary') or \
+                len(self.polycoords) == 0:
+            return False
+        
+        # for linear feature show segment and total length
+        distance_seg = self.Distance(self.polycoords[-1],
+                                     (e, n), screen = False)[0]
+        distance_tot = distance_seg
+        for idx in range(1, len(self.polycoords)):
+            distance_tot += self.Distance(self.polycoords[idx-1],
+                                          self.polycoords[idx],
+                                          screen = False)[0]
+        self.parent.statusbar.SetStatusText("%.*f, %.*f (seg: %.*f; tot: %.*f)" % \
+                                                (precision, e, precision, n,
+                                                 precision, distance_seg,
+                                                 precision, distance_tot), 0)
+        
+        return True
+    
+    def OnKeyDown(self, event):
+        """!Key pressed"""
+        shift = event.ShiftDown()
+        kc = event.GetKeyCode()
+        
+        event = None
+        if not shift:
+            if kc == ord('P'):
+                event = wx.CommandEvent(winid = self.toolbar.addPoint)
+                tool = self.toolbar.OnAddPoint
+            elif kc == ord('L'):
+                event = wx.CommandEvent(winid = self.toolbar.addLine)
+                tool = self.toolbar.OnAddLine
+        if event:
+            self.toolbar.OnTool(event)
+            tool(event)
+        
+    def _updateMap(self):
+        if not self.toolbar or \
+                not self.toolbar.GetLayer():
+            return
+        
+        # set region
+        self.digit.GetDisplay().UpdateRegion()
+        # re-calculate threshold for digitization tool
+        # self.parent.digit.GetDisplay().GetThreshold()
+        # draw map
+        # self.pdcVector.Clear()
+        self.pdcVector.RemoveAll()
+        
+        try:
+            item = self.tree.FindItemByData('maplayer', self.toolbar.GetLayer())
+        except TypeError:
+            item = None
+        
+        if item and self.tree.IsItemChecked(item):
+            self.redrawAll = True
+            self.digit.GetDisplay().DrawMap()
+        
+        # translate tmp objects (pointer position)
+        if self.toolbar.GetAction() == 'moveLine' and \
+                hasattr(self, "moveInfo"):
+            if 'beginDiff' in self.moveInfo:
+                # move line
+                for id in self.moveInfo['id']:
+                    self.pdcTmp.TranslateId(id,
+                                            self.moveInfo['beginDiff'][0],
+                                            self.moveInfo['beginDiff'][1])
+                del self.moveInfo['beginDiff']
+        
+    def OnLeftDownAddLine(self, event):
+        """!Left mouse button pressed - add new feature
+        """
+        try:
+            mapLayer = self.toolbar.GetLayer().GetName()
+        except:
+            return
+        
+        if self.toolbar.GetAction('type') in ['point', 'centroid']:
+            # add new point / centroiud
+            east, north = self.Pixel2Cell(self.mouse['begin'])
+            nfeat, fids = self.digit.AddFeature(self.toolbar.GetAction('type'), [(east, north)])
+            if nfeat < 1:
+                return
+            
+            self.UpdateMap(render = False) # redraw map
+            
+            # add new record into atribute table
+            if UserSettings.Get(group = 'vdigit', key = "addRecord", subkey = 'enabled'):
+                # select attributes based on layer and category
+                cats = { fids[0] : {
+                        UserSettings.Get(group = 'vdigit', key = "layer", subkey = 'value') :
+                            (UserSettings.Get(group = 'vdigit', key = "category", subkey = 'value'), )
+                        }}
+                
+                posWindow = self.ClientToScreen((self.mouse['end'][0] + self.dialogOffset,
+                                                 self.mouse['end'][1] + self.dialogOffset))
+                
+                addRecordDlg = dbm_dialogs.DisplayAttributesDialog(parent = self, map = mapLayer,
+                                                                   cats = cats,
+                                                                   pos = posWindow,
+                                                                   action = "add")
+                
+                if self.toolbar.GetAction('type') == 'centroid':
+                    for fid in fids:
+                        self._geomAttrb(fid, addRecordDlg, 'area')
+                        self._geomAttrb(fid, addRecordDlg, 'perimeter')
+                
+                if addRecordDlg.mapDBInfo and \
+                        addRecordDlg.ShowModal() == wx.ID_OK:
+                    sqlfile = tempfile.NamedTemporaryFile(mode = "w")
+                    for sql in addRecordDlg.GetSQLString():
+                        sqlfile.file.write(sql + ";\n")
+                    sqlfile.file.flush()
+                    
+                    gcmd.RunCommand('db.execute',
+                                    parent = self,
+                                    quiet = True, 
+                                    input = sqlfile.name)
+                
+                if addRecordDlg.mapDBInfo:
+                    self._updateATM()
+        
+        elif self.toolbar.GetAction('type') in ["line", "boundary", "area"]:
+            # add new point to the line
+            self.polycoords.append(self.Pixel2Cell(event.GetPositionTuple()[:]))
+            self.DrawLines(pdc = self.pdcTmp)
+        
+    def _geomAttrb(self, fid, dialog, attrb):
+        """!Define geometry attributes
+        """
+        mapLayer = self.toolbar.GetLayer()
+        item = self.tree.FindItemByData('maplayer', mapLayer)
+        vdigit = self.tree.GetPyData(item)[0]['vdigit']
+        if not vdigit or \
+                'geomAttr' not in vdigit or \
+                attrb not in vdigit['geomAttr']:
+            return
+        
+        val = -1
+        if attrb == 'length':
+            val = self.digit.GetLineLength(fid)
+            type = attrb
+        elif attrb == 'area':
+            val = self.digit.GetAreaSize(fid)
+            type = attrb
+        elif attrb == 'perimeter':
+            val = self.digit.GetAreaPerimeter(fid)
+            type = 'length'
+        
+        if val > 0:
+            layer = int(UserSettings.Get(group = 'vdigit', key = "layer", subkey = 'value'))
+            column = vdigit['geomAttr'][attrb]['column']
+            val = UnitsConvertValue(val, type, vdigit['geomAttr'][attrb]['units'])
+            dialog.SetColumnValue(layer, column, val)
+            dialog.OnReset()
+        
+    def _geomAttrbUpdate(self, fids):
+        """!Update geometry atrributes of currently selected features
+        
+        @param fid list feature id
+        """
+        mapLayer = self.parent.toolbars['vdigit'].GetLayer()
+        vectorName =  mapLayer.GetName()
+        item = self.tree.FindItemByData('maplayer', mapLayer)
+        vdigit = self.tree.GetPyData(item)[0]['vdigit']
+        
+        if vdigit is None or 'geomAttr' not in vdigit:
+            return
+        
+        dbInfo = gselect.VectorDBInfo(vectorName)
+        sqlfile = tempfile.NamedTemporaryFile(mode = "w")
+        for fid in fids:
+            for layer, cats in self.digit.GetLineCats(fid).iteritems():
+                table = dbInfo.GetTable(layer)
+                for attrb, item in vdigit['geomAttr'].iteritems():
+                    val = -1
+                    if attrb == 'length':
+                        val = self.digit.GetLineLength(fid)
+                        type = attrb
+                    elif attrb == 'area':
+                        val = self.digit.GetAreaSize(fid)
+                        type = attrb
+                    elif attrb == 'perimeter':
+                        val = self.digit.GetAreaPerimeter(fid)
+                        type = 'length'
+                    
+                    if val < 0:
+                        continue
+                    val = UnitsConvertValue(val, type, item['units'])
+                    
+                    for cat in cats:
+                        sqlfile.write('UPDATE %s SET %s = %f WHERE %s = %d;\n' % \
+                                          (table, item['column'], val,
+                                           dbInfo.GetKeyColumn(layer), cat))
+            
+            sqlfile.file.flush()
+            gcmd.RunCommand('db.execute',
+                            parent = True,
+                            quiet = True,
+                            input = sqlfile.name)
+            
+    def _updateATM(self):
+        """!Update open Attribute Table Manager
+        
+        @todo: use AddDataRow() instead
+        """
+        # update ATM
+        digitVector = self.toolbar.GetLayer().GetName()
+                            
+        for atm in self.lmgr.dialogs['atm']:
+            atmVector = atm.GetVectorName()
+            if atmVector == digitVector:
+                layer = UserSettings.Get(group = 'vdigit', key = "layer", subkey = 'value')
+                # TODO: use AddDataRow instead
+                atm.LoadData(layer)
+        
+    def OnLeftDownEditLine(self, event):
+        """!Left mouse button pressed - edit linear feature - add new
+        vertex.
+        """
+        self.polycoords.append(self.Pixel2Cell(self.mouse['begin']))
+        self.moveInfo['id'].append(wx.NewId())
+        self.DrawLines(pdc = self.pdcTmp)
+        
+    def OnLeftDownMoveLine(self, event):
+        """!Left mouse button pressed - vector digitizer move
+        feature/vertex, edit linear feature
+        """
+        self.moveInfo = dict()
+        # geographic coordinates of initial position (left-down)
+        self.moveInfo['begin'] = None
+        # list of ids to modify    
+        self.moveInfo['id'] = list()
+        
+        if self.toolbar.GetAction() in ["moveVertex", "editLine"]:
+            # set pen
+            pcolor = UserSettings.Get(group = 'vdigit', key = "symbol",
+                                      subkey = ["highlight", "color"])
+            self.pen = self.polypen = wx.Pen(colour = pcolor,
+                                             width = 2, style = wx.SHORT_DASH)
+            self.pdcTmp.SetPen(self.polypen)
+        
+    def OnLeftDownDisplayCA(self, event):
+        """!Left mouse button pressed - vector digitizer display categories
+        or attributes action
+        """
+        try:
+            mapLayer = self.toolbar.GetLayer().GetName()
+        except:
+            return
+        
+        coords = self.Pixel2Cell(self.mouse['begin'])
+        
+        # unselect
+        self.digit.GetDisplay().SetSelected([])
+        
+        # select feature by point
+        cats = {}
+        if self.digit.GetDisplay().SelectLineByPoint(coords) is None:
+            return
+        
+        if UserSettings.Get(group = 'vdigit', key = 'checkForDupl',
+                            subkey = 'enabled'):
+            lines = self.digit.GetDisplay().GetSelected()
+        else:
+            lines = (self.digit.GetDisplay().GetSelected()[0],) # only first found
+                        
+        for line in lines:
+            cats[line] = self.digit.GetLineCats(line)
+        
+        posWindow = self.ClientToScreen((self.mouse['end'][0] + self.dialogOffset,
+                                         self.mouse['end'][1] + self.dialogOffset))
+        
+        if self.toolbar.GetAction() == "displayAttrs":
+            # select attributes based on coordinates (all layers)
+            if self.parent.dialogs['attributes'] is None:
+                self.parent.dialogs['attributes'] = \
+                    dbm_dialogs.DisplayAttributesDialog(parent = self, map = mapLayer,
+                                                        cats = cats,
+                                                        action = "update")
+            else:
+                # upgrade dialog
+                self.parent.dialogs['attributes'].UpdateDialog(cats = cats)
+           
+            if self.parent.dialogs['attributes']:
+                if len(cats.keys()) > 0:
+                    # highlight feature & re-draw map
+                    if not self.parent.dialogs['attributes'].IsShown():
+                        self.parent.dialogs['attributes'].Show()
+                else:
+                    if self.parent.dialogs['attributes'] and \
+                            self.parent.dialogs['attributes'].IsShown():
+                        self.parent.dialogs['attributes'].Hide()
+        
+        else: # displayCats
+            if self.parent.dialogs['category'] is None:
+                # open new dialog
+                dlg = VDigitCategoryDialog(parent = self,
+                                           map = mapLayer,
+                                           cats = cats,
+                                           pos = posWindow,
+                                           title = _("Update categories"))
+                self.parent.dialogs['category'] = dlg
+            else:
+                # update currently open dialog
+                self.parent.dialogs['category'].UpdateDialog(cats = cats)
+                
+            if self.parent.dialogs['category']:
+                if len(cats.keys()) > 0:
+                    # highlight feature & re-draw map
+                    if not self.parent.dialogs['category'].IsShown():
+                        self.parent.dialogs['category'].Show()
+                else:
+                    if self.parent.dialogs['category'].IsShown():
+                        self.parent.dialogs['category'].Hide()
+        
+        self.UpdateMap(render = False, renderVector = True)
+        
+    def OnLeftDownCopyCA(self, event):
+        """!Left mouse button pressed - vector digitizer copy
+        categories or attributes action
+        """
+        if not hasattr(self, "copyCatsList"):
+            self.copyCatsList = []
+        else:
+            self.copyCatsIds = []
+            self.mouse['box'] = 'box'
+        
+    def OnLeftDownCopyLine(self, event):
+        """!Left mouse button pressed - vector digitizer copy lines
+        action
+        """
+        if not hasattr(self, "copyIds"):
+            self.copyIds = []
+            self.layerTmp = None
+        
+    def OnLeftDownBulkLine(self, event):
+        """!Left mouse button pressed - vector digitizer label 3D
+        vector lines
+        """
+        if len(self.polycoords) > 1: # start new line
+            self.polycoords = []
+            self.ClearLines(pdc = self.pdcTmp)
+        self.polycoords.append(self.Pixel2Cell(event.GetPositionTuple()[:]))
+        if len(self.polycoords) == 1:
+            begin = self.Pixel2Cell(self.polycoords[-1])
+            end   = self.Pixel2Cell(self.mouse['end'])
+        else:
+            end   = self.Pixel2Cell(self.polycoords[-1])
+            begin = self.Pixel2Cell(self.mouse['begin'])
+            
+            self.DrawLines(self.pdcTmp, polycoords = (begin, end))
+        
+    def OnLeftDownUndo(self, event):
+        """!Left mouse button pressed with control key - vector
+        digitizer undo functionality
+        """
+        if self.mouse["use"] != "pointer" or not self.toolbar:
+            return
+        
+        if (self.toolbar.GetAction() == "addLine" and \
+                self.toolbar.GetAction('type') in ["line", "boundary", "area"]) or \
+                self.toolbar.GetAction() == "editLine":
+            # add line or boundary -> remove last point from the line
+            try:
+                removed = self.polycoords.pop()
+                Debug.msg(4, "BufferedWindow.OnMiddleDown(): polycoords_poped=%s" % \
+                              [removed,])
+                # self.mouse['begin'] = self.Cell2Pixel(self.polycoords[-1])
+            except:
+                pass
+            
+        if self.toolbar.GetAction() == "editLine":
+            # remove last vertex & line
+            if len(self.moveInfo['id']) > 1:
+                self.moveInfo['id'].pop()
+                
+            self.UpdateMap(render = False, renderVector = False)
+            
+        elif self.toolbar.GetAction() in ["deleteLine", "moveLine", "splitLine",
+                                          "addVertex", "removeVertex", "moveVertex",
+                                          "copyCats", "flipLine", "mergeLine",
+                                          "snapLine", "connectLine", "copyLine",
+                                          "queryLine", "breakLine", "typeConv"]:
+            # varios tools -> unselected selected features
+            self.digit.GetDisplay().SetSelected([])
+            if self.toolbar.GetAction() in ["moveLine", "moveVertex", "editLine"] and \
+                    hasattr(self, "moveInfo"):
+                del self.moveInfo
+                
+            elif self.toolbar.GetAction() == "copyCats":
+                try:
+                    del self.copyCatsList
+                    del self.copyCatsIds
+                except AttributeError:
+                    pass
+                
+            elif self.toolbar.GetAction() == "copyLine":
+                del self.copyIds
+                if self.layerTmp:
+                    self.Map.DeleteLayer(self.layerTmp)
+                    self.UpdateMap(render = True, renderVector = False)
+                del self.layerTmp
+
+            self.polycoords = []
+            self.UpdateMap(render = False) # render vector
+        
+        elif self.toolbar.GetAction() == "zbulkLine":
+            # reset polyline
+            self.polycoords = []
+            self.digit.GetDisplay().SetSelected([])
+            self.UpdateMap(render = False)
+        
+        self.redrawAll = True
+        self.UpdateMap(render = False, renderVector = False)
+
+    def _onLeftDown(self, event):
+        """!Left mouse button donw - vector digitizer various actions
+        """
+        try:
+            mapLayer = self.toolbar.GetLayer().GetName()
+        except:
+            wx.MessageBox(parent = self,
+                          message = _("No vector map selected for editing."),
+                          caption = _("Vector digitizer"),
+                          style = wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
+            event.Skip()
+            return
+    
+        if self.toolbar.GetAction() not in ("moveVertex",
+                                            "addVertex",
+                                            "removeVertex",
+                                            "editLine"):
+            # set pen
+            self.pen = wx.Pen(colour = 'Red', width = 2, style = wx.SHORT_DASH)
+            self.polypen = wx.Pen(colour = 'dark green', width = 2, style = wx.SOLID)
+            
+        if self.toolbar.GetAction() in ("addVertex",
+                                        "removeVertex",
+                                        "splitLines"):
+            # unselect
+            self.digit.GetDisplay().SetSelected([])
+
+        if self.toolbar.GetAction() == "addLine":
+            self.OnLeftDownAddLine(event)
+            
+        elif self.toolbar.GetAction() == "editLine" and \
+                hasattr(self, "moveInfo"):
+            self.OnLeftDownEditLine(event)
+
+        elif self.toolbar.GetAction() in ("moveLine", "moveVertex", "editLine") and \
+                not hasattr(self, "moveInfo"):
+            self.OnLeftDownMoveLine(event)
+        
+        elif self.toolbar.GetAction() in ("displayAttrs"
+                                          "displayCats"):
+            self.OnLeftDownDisplayCA(event)
+            
+        elif self.toolbar.GetAction() in ("copyCats",
+                                          "copyAttrs"):
+            self.OnLeftDownCopyCA(event)
+            
+        elif self.toolbar.GetAction() == "copyLine":
+            self.OnLeftDownCopyLine(event)
+            
+        elif self.toolbar.GetAction() == "zbulkLine":
+            self.OnLeftDownBulkLine(event)
+        
+    def _onLeftUp(self, event):
+        """!Left mouse button released - vector digitizer various
+        actions
+        """
+        pos1 = self.Pixel2Cell(self.mouse['begin'])
+        pos2 = self.Pixel2Cell(self.mouse['end'])
+        
+        nselected = 0
+        # -> delete line || move line || move vertex
+        if self.toolbar.GetAction() in ("moveVertex",
+                                        "editLine"):
+            if len(self.digit.GetDisplay().GetSelected()) == 0:
+                nselected = self.digit.GetDisplay().SelectLineByPoint(pos1)['point']
+                
+                if self.toolbar.GetAction() == "editLine":
+                    try:
+                        selVertex = self.digit.GetDisplay().GetSelectedVertex(pos1)[0]
+                    except IndexError:
+                        selVertex = None
+                        
+                    if selVertex:
+                        # self.UpdateMap(render=False)
+                        ids = self.digit.GetDisplay().GetSelected(grassId = False)
+                        # move this line to tmp layer
+                        self.polycoords = []
+                        for id in ids:
+                            if id % 2: # register only vertices
+                                e, n = self.Pixel2Cell(self.pdcVector.GetIdBounds(id)[0:2])
+                                self.polycoords.append((e, n))
+                        self.digit.GetDisplay().DrawSelected(False) 
+                                
+                        if selVertex < ids[-1] / 2:
+                            # choose first or last node of line
+                            self.moveInfo['id'].reverse()
+                            self.polycoords.reverse()
+                    else:
+                        # unselect
+                        self.digit.GetDisplay().SetSelected([])
+                        del self.moveInfo
+                
+                    self.UpdateMap(render = False)
+            
+        elif self.toolbar.GetAction() in ("copyCats",
+                                          "copyAttrs"):
+            if not hasattr(self, "copyCatsIds"):
+                # 'from' -> select by point
+                nselected = self.digit.GetDisplay().SelectLineByPoint(pos1)['point']
+                if nselected:
+                    self.copyCatsList = self.digit.GetDisplay().GetSelected()
+            else:
+                # -> 'to' -> select by bbox
+                self.digit.GetDisplay().SetSelected([])
+                # return number of selected features (by box/point)
+                nselected = self.digit.GetDisplay().SelectLinesByBox((pos1, pos2))
+                if nselected == 0:
+                    if self.digit.GetDisplay().SelectLineByPoint(pos1) is not None:
+                        nselected = 1
+                        
+                if nselected > 0:
+                    self.copyCatsIds = self.digit.GetDisplay().GetSelected()
+        
+        elif self.toolbar.GetAction() == "queryLine":
+            selected = self.digit.SelectLinesByQuery(bbox = (pos1, pos2))
+            nselected = len(selected)
+            if nselected > 0:
+                self.digit.GetDisplay().SetSelected(selected)
+        
+        else:
+            # -> moveLine || deleteLine, etc. (select by point/box)
+            if self.toolbar.GetAction() == 'moveLine' and \
+                    len(self.digit.GetDisplay().GetSelected()) > 0:
+                nselected = 0
+            else:
+                if self.toolbar.GetAction() == 'moveLine':
+                    drawSeg = True
+                else:
+                    drawSeg = False
+                
+                nselected = self.digit.GetDisplay().SelectLinesByBox(bbox = (pos1, pos2),
+                                                                     drawSeg = drawSeg)
+                if nselected == 0:
+                    if self.digit.GetDisplay().SelectLineByPoint(pos1) is not None:
+                        nselected = 1
+        
+        if nselected > 0:
+            if self.toolbar.GetAction() in ("moveLine", "moveVertex") and \
+                    hasattr(self, "moveInfo"):
+                # get pseudoDC id of objects which should be redrawn
+                if self.toolbar.GetAction() == "moveLine":
+                    # -> move line
+                    self.moveInfo['id'] = self.digit.GetDisplay().GetSelected(grassId = False)
+                else: # moveVertex
+                    self.moveInfo['id'] = self.digit.GetDisplay().GetSelectedVertex(pos1)
+                    if len(self.moveInfo['id']) == 0: # no vertex found
+                        self.digit.GetDisplay().SetSelected([])
+            
+            #
+            # check for duplicates
+            #
+            if UserSettings.Get(group = 'vdigit', key = 'checkForDupl', subkey = 'enabled'):
+                dupl = self.digit.GetDisplay().GetDuplicates()
+                self.UpdateMap(render = False)
+                    
+                if dupl:
+                    posWindow = self.ClientToScreen((self.mouse['end'][0] + self.dialogOffset,
+                                                     self.mouse['end'][1] + self.dialogOffset))
+                    
+                    dlg = VDigitDuplicatesDialog(parent = self, data = dupl, pos = posWindow)
+                    
+                    if dlg.ShowModal() == wx.ID_OK:
+                        self.digit.GetDisplay().UnSelect(dlg.GetUnSelected())
+                        # update selected
+                        self.UpdateMap(render = False)
+                
+            if self.toolbar.GetAction() != "editLine":
+                # -> move line || move vertex
+                self.UpdateMap(render = False)
+        
+        else: # no vector object found
+            if not (self.toolbar.GetAction() in ("moveLine",
+                                                 "moveVertex") and \
+                        hasattr(self, "moveInfo") and \
+                        len(self.moveInfo['id']) > 0):
+                # avoid left-click when features are already selected
+                self.UpdateMap(render = False, renderVector = False)
+        
+    def OnLeftUpModifyLine(self, event):
+        """!Left mouse button released - vector digitizer split line,
+        add/remove vertex action
+        """
+        pos1 = self.Pixel2Cell(self.mouse['begin'])
+        
+        pointOnLine = self.digit.GetDisplay().SelectLineByPoint(pos1)['point']
+        if not pointOnLine:
+            return
+        
+        if self.toolbar.GetAction() in ["splitLine", "addVertex"]:
+            self.UpdateMap(render = False) # highlight object
+            self.DrawCross(pdc = self.pdcTmp, coords = self.Cell2Pixel((pointOnLine[0], pointOnLine[1])),
+                           size = 5)
+        else: # removeVertex
+            # get only id of vertex
+            try:
+                id = self.digit.GetDisplay().GetSelectedVertex(pos1)[0]
+            except IndexError:
+                id = None
+            
+            if id:
+                x, y = self.pdcVector.GetIdBounds(id)[0:2]
+                self.pdcVector.RemoveId(id)
+                self.UpdateMap(render = False) # highlight object
+                self.DrawCross(pdc = self.pdcTmp, coords = (x, y),
+                               size = 5)
+            else:
+                # unselect
+                self.digit.GetDisplay().SetSelected([])
+                self.UpdateMap(render = False)
+        
+    def OnLeftUpCopyLine(self, event):
+        """!Left mouse button released - vector digitizer copy feature
+        action
+        """
+        pos1 = self.Pixel2Cell(self.mouse['begin'])
+        pos2 = self.Pixel2Cell(self.mouse['end'])
+        
+        if UserSettings.Get(group = 'vdigit', key = 'bgmap',
+                            subkey = 'value', internal = True) == '':
+            # no background map -> copy from current vector map layer
+            nselected = self.digit.GetDisplay().SelectLinesByBox((pos1, pos2))
+            
+            if nselected > 0:
+                # highlight selected features
+                self.UpdateMap(render = False)
+            else:
+                self.UpdateMap(render = False, renderVector = False)
+        else:
+            # copy features from background map
+            self.copyIds += self.digit.SelectLinesFromBackgroundMap(bbox = (pos1, pos2))
+            if len(self.copyIds) > 0:
+                color = UserSettings.Get(group = 'vdigit', key = 'symbol',
+                                         subkey = ['highlight', 'color'])
+                colorStr = str(color[0]) + ":" + \
+                    str(color[1]) + ":" + \
+                    str(color[2])
+                dVectTmp = ['d.vect',
+                            'map=%s' % UserSettings.Get(group = 'vdigit', key = 'bgmap',
+                                                        subkey = 'value', internal = True),
+                            'cats=%s' % utils.ListOfCatsToRange(self.copyIds),
+                            '-i',
+                            'color=%s' % colorStr,
+                            'fcolor=%s' % colorStr,
+                            'type=point,line,boundary,centroid',
+                            'width=2']
+                
+                if not self.layerTmp:
+                    self.layerTmp = self.Map.AddLayer(type = 'vector',
+                                                      name = globalvar.QUERYLAYER,
+                                                      command = dVectTmp)
+                else:
+                    self.layerTmp.SetCmd(dVectTmp)
+                
+                self.UpdateMap(render = True, renderVector = False)
+            else:
+                self.UpdateMap(render = False, renderVector = False)
+            
+            self.redrawAll = None
+            
+    def OnLeftUpBulkLine(self, event):
+        """!Left mouse button released - vector digitizer z-bulk line
+        action
+        """
+        # select lines to be labeled
+        pos1 = self.polycoords[0]
+        pos2 = self.polycoords[1]
+        nselected = self.digit.GetDisplay().SelectLinesByBox((pos1, pos2))
+        
+        if nselected > 0:
+            # highlight selected features
+            self.UpdateMap(render = False)
+            self.DrawLines(pdc = self.pdcTmp) # redraw temp line
+        else:
+            self.UpdateMap(render = False, renderVector = False)
+            
+    def OnLeftUpConnectLine(self, event):
+        """!Left mouse button released - vector digitizer connect line
+        action
+        """
+        if len(self.digit.GetDisplay().GetSelected()) > 0:
+            self.UpdateMap(render = False)
+        
+    def OnLeftUp(self, event):
+        if hasattr(self, "moveInfo"):
+            if len(self.digit.GetDisplay().GetSelected()) == 0:
+                self.moveInfo['begin'] = self.Pixel2Cell(self.mouse['begin']) # left down
+            
+            # eliminate initial mouse moving efect
+            self.mouse['begin'] = self.mouse['end'] 
+        
+        if self.toolbar.GetAction() in ("deleteLine",
+                                        "moveLine",
+                                        "moveVertex",
+                                        "copyCats",
+                                        "copyAttrs",
+                                        "editLine",
+                                        "flipLine",
+                                        "mergeLine",
+                                        "snapLine",
+                                        "queryLine",
+                                        "breakLine",
+                                        "typeConv",
+                                        "connectLine"):
+            self._onLeftUp(event)
+        
+        elif self.toolbar.GetAction() in ("splitLine",
+                                          "addVertex",
+                                          "removeVertex"):
+            self.OnLeftUpModifyLine(event)
+        
+        elif self.toolbar.GetAction() == "copyLine":
+            self.OnLeftUpCopyLine(event)
+            
+        elif self.toolbar.GetAction() == "zbulkLine" and \
+                len(self.polycoords) == 2:
+            self.OnLeftUpBulkLine(event)
+        
+        elif self.toolbar.GetAction() == "connectLine":
+            self.OnLeftUpConnectLine(event)
+        
+        if len(self.digit.GetDisplay().GetSelected()) > 0:
+            self.redrawAll = None
+        
+    def _onRightDown(self, event):
+        # digitization tool (confirm action)
+        if self.toolbar.GetAction() in ("moveLine", "moveVertex") and \
+                hasattr(self, "moveInfo"):
+            pFrom = self.moveInfo['begin']
+            pTo = self.Pixel2Cell(event.GetPositionTuple())
+            
+            move = (pTo[0] - pFrom[0],
+                    pTo[1] - pFrom[1])
+            
+            if self.toolbar.GetAction() == "moveLine":
+                # move line
+                if self.digit.MoveSelectedLines(move) < 0:
+                    return
+            elif self.toolbar.GetAction() == "moveVertex":
+                # move vertex
+                fid = self.digit.MoveSelectedVertex(pFrom, move)
+                if fid < 0:
+                    return
+                
+                self._geomAttrbUpdate([fid,])
+            
+            del self.moveInfo
+        
+    def _onRightUp(self, event):
+        """!Right mouse button released
+        """
+        # digitization tool (confirm action)
+        if self.toolbar.GetAction() == "addLine" and \
+                self.toolbar.GetAction('type') in ["line", "boundary", "area"]:
+            # -> add new line / boundary
+            try:
+                mapName = self.toolbar.GetLayer().GetName()
+            except:
+                mapName = None
+                gcmd.GError(parent = self,
+                            message = _("No vector map selected for editing."))
+                    
+            if mapName:
+                if self.toolbar.GetAction('type') == 'line':
+                    line = True
+                else:
+                    line = False
+                    
+                if len(self.polycoords) < 2: # ignore 'one-point' lines
+                    return
+                    
+                nfeat, fids = self.digit.AddFeature(self.toolbar.GetAction('type'), self.polycoords)
+                if nfeat < 0:
+                    return
+                    
+                position = self.Cell2Pixel(self.polycoords[-1])
+                self.polycoords = []
+                self.UpdateMap(render = False)
+                self.redrawAll = True
+                self.Refresh()
+                
+            # add new record into atribute table
+                if UserSettings.Get(group = 'vdigit', key = "addRecord", subkey = 'enabled') and \
+                        (line is True or \
+                             (not line and nfeat > 0)):
+                    posWindow = self.ClientToScreen((position[0] + self.dialogOffset,
+                                                     position[1] + self.dialogOffset))
+                        
+                    # select attributes based on layer and category
+                    cats = { fids[0] : {
+                            UserSettings.Get(group = 'vdigit', key = "layer", subkey = 'value') :
+                                (UserSettings.Get(group = 'vdigit', key = "category", subkey = 'value'), )
+                            }}
+                    
+                    addRecordDlg = dbm_dialogs.DisplayAttributesDialog(parent = self, map = mapName,
+                                                                       cats = cats,
+                                                                       pos = posWindow,
+                                                                       action = "add")
+                    
+                    for fid in fids:
+                        self._geomAttrb(fid, addRecordDlg, 'length')
+                        # auto-placing centroid
+                        self._geomAttrb(fid, addRecordDlg, 'area')
+                        self._geomAttrb(fid, addRecordDlg, 'perimeter')
+
+                    
+                    if addRecordDlg.mapDBInfo and \
+                            addRecordDlg.ShowModal() == wx.ID_OK:
+                        sqlfile = tempfile.NamedTemporaryFile(mode = "w")
+                        for sql in addRecordDlg.GetSQLString():
+                            sqlfile.file.write(sql + ";\n")
+                        sqlfile.file.flush()
+                        gcmd.RunCommand('db.execute',
+                                        parent = True,
+                                        quiet = True,
+                                        input = sqlfile.name)
+                        
+                    if addRecordDlg.mapDBInfo:
+                        self._updateATM()
+            
+        elif self.toolbar.GetAction() == "deleteLine":
+            # -> delete selected vector features
+            if self.digit.DeleteSelectedLines() < 0:
+                return
+            self._updateATM()
+        elif self.toolbar.GetAction() == "splitLine":
+            # split line
+            if self.digit.SplitLine(self.Pixel2Cell(self.mouse['begin'])) < 0:
+                return
+        elif self.toolbar.GetAction() == "addVertex":
+            # add vertex
+            fid = self.digit.AddVertex(self.Pixel2Cell(self.mouse['begin']))
+            if fid < 0:
+                return
+        elif self.toolbar.GetAction() == "removeVertex":
+            # remove vertex
+            fid = self.digit.RemoveVertex(self.Pixel2Cell(self.mouse['begin']))
+            if fid < 0:
+                return
+            self._geomAttrbUpdate([fid,])
+        elif self.toolbar.GetAction() in ("copyCats", "copyAttrs"):
+            try:
+                if self.toolbar.GetAction() == 'copyCats':
+                    if self.digit.CopyCats(self.copyCatsList,
+                                           self.copyCatsIds, copyAttrb = False) < 0:
+                        return
+                else:
+                    if self.digit.CopyCats(self.copyCatsList,
+                                           self.copyCatsIds, copyAttrb = True) < 0:
+                        return
+                
+                del self.copyCatsList
+                del self.copyCatsIds
+            except AttributeError:
+                pass
+            
+            self._updateATM()
+                
+        elif self.toolbar.GetAction() == "editLine" and \
+                hasattr(self, "moveInfo"):
+            line = self.digit.GetDisplay().GetSelected()
+            if self.digit.EditLine(line, self.polycoords) < 0:
+                return
+                
+            del self.moveInfo
+                
+        elif self.toolbar.GetAction() == "flipLine":
+            if self.digit.FlipLine() < 0:
+                return
+        elif self.toolbar.GetAction() == "mergeLine":
+            if self.digit.MergeLine() < 0:
+                return
+        elif self.toolbar.GetAction() == "breakLine":
+            if self.digit.BreakLine() < 0:
+                return
+        elif self.toolbar.GetAction() == "snapLine":
+            if self.digit.SnapLine() < 0:
+                return
+        elif self.toolbar.GetAction() == "connectLine":
+            if len(self.digit.GetDisplay().GetSelected()) > 1:
+                if self.digit.ConnectLine() < 0:
+                    return
+        elif self.toolbar.GetAction() == "copyLine":
+            if self.digit.CopyLine(self.copyIds) < 0:
+                return
+            del self.copyIds
+            if self.layerTmp:
+                self.Map.DeleteLayer(self.layerTmp)
+                self.UpdateMap(render = True, renderVector = False)
+            del self.layerTmp
+        
+        elif self.toolbar.GetAction() == "zbulkLine" and len(self.polycoords) == 2:
+            pos1 = self.polycoords[0]
+            pos2 = self.polycoords[1]
+            
+            selected = self.digit.GetDisplay().GetSelected()
+            dlg = VDigitZBulkDialog(parent = self, title = _("Z bulk-labeling dialog"),
+                                    nselected = len(selected))
+            if dlg.ShowModal() == wx.ID_OK:
+                if self.digit.ZBulkLines(pos1, pos2, dlg.value.GetValue(),
+                                         dlg.step.GetValue()) < 0:
+                    return
+            self.UpdateMap(render = False, renderVector = True)
+        elif self.toolbar.GetAction() == "typeConv":
+            # -> feature type conversion
+            # - point <-> centroid
+            # - line <-> boundary
+            if self.digit.TypeConvForSelectedLines() < 0:
+                return
+
+        if self.toolbar.GetAction() != "addLine":
+            # unselect and re-render
+            self.digit.GetDisplay().SetSelected([])
+            self.polycoords = []
+            self.UpdateMap(render = False)
+        
+    def _onMouseMoving(self, event):
+        self.mouse['end'] = event.GetPositionTuple()[:]
+        
+        Debug.msg (5, "BufferedWindow.OnMouseMoving(): coords=%f,%f" % \
+                       (self.mouse['end'][0], self.mouse['end'][1]))
+        
+        if self.toolbar.GetAction() == "addLine" and \
+                self.toolbar.GetAction('type') in ["line", "boundary", "area"]:
+            if len(self.polycoords) > 0:
+                self.MouseDraw(pdc = self.pdcTmp, begin = self.Cell2Pixel(self.polycoords[-1]))
+        
+        elif self.toolbar.GetAction() in ["moveLine", "moveVertex", "editLine"] \
+                and hasattr(self, "moveInfo"):
+            dx = self.mouse['end'][0] - self.mouse['begin'][0]
+            dy = self.mouse['end'][1] - self.mouse['begin'][1]
+            
+            if len(self.moveInfo['id']) > 0:
+                # draw lines on new position
+                if self.toolbar.GetAction() == "moveLine":
+                    # move line
+                    for id in self.moveInfo['id']:
+                        self.pdcTmp.TranslateId(id, dx, dy)
+                elif self.toolbar.GetAction() in ["moveVertex", "editLine"]:
+                    # move vertex ->
+                    # (vertex, left vertex, left line,
+                    # right vertex, right line)
+                    
+                    # do not draw static lines
+                    if self.toolbar.GetAction() == "moveVertex":
+                        self.polycoords = []
+                        ### self.pdcTmp.TranslateId(self.moveInfo['id'][0], dx, dy)
+                        self.pdcTmp.RemoveId(self.moveInfo['id'][0])
+                        if self.moveInfo['id'][1] > 0: # previous vertex
+                            x, y = self.Pixel2Cell(self.pdcTmp.GetIdBounds(self.moveInfo['id'][1])[0:2])
+                            self.pdcTmp.RemoveId(self.moveInfo['id'][1] + 1)
+                            self.polycoords.append((x, y))
+                        ### x, y = self.Pixel2Cell(self.pdcTmp.GetIdBounds(self.moveInfo['id'][0])[0:2])
+                        self.polycoords.append(self.Pixel2Cell(self.mouse['end']))
+                        if self.moveInfo['id'][2] > 0: # next vertex
+                            x, y = self.Pixel2Cell(self.pdcTmp.GetIdBounds(self.moveInfo['id'][2])[0:2])
+                            self.pdcTmp.RemoveId(self.moveInfo['id'][2]-1)
+                            self.polycoords.append((x, y))
+                        
+                        self.ClearLines(pdc = self.pdcTmp)
+                        self.DrawLines(pdc = self.pdcTmp)
+                        
+                    else: # edit line
+                        try:
+                            if self.moveInfo['id'][-1] > 0: # previous vertex
+                                self.MouseDraw(pdc = self.pdcTmp,
+                                               begin = self.Cell2Pixel(self.polycoords[-1]))
+                        except: # no line
+                            self.moveInfo['id'] = []
+                            self.polycoords = []
+                
+            self.Refresh() # TODO: use RefreshRect()
+            self.mouse['begin'] = self.mouse['end']
+            
+        elif self.toolbar.GetAction() == "zbulkLine":
+            if len(self.polycoords) == 1:
+                # draw mouse moving
+                self.MouseDraw(self.pdcTmp)
+                
+    def _zoom(self, event):
+        tmp1 = self.mouse['end']
+        tmp2 = self.Cell2Pixel(self.moveInfo['begin'])
+        dx = tmp1[0] - tmp2[0]
+        dy = tmp1[1] - tmp2[1]
+        self.moveInfo['beginDiff'] = (dx, dy)
+        for id in self.moveInfo['id']:
+            self.pdcTmp.RemoveId(id)
+        


Property changes on: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/mapdisp_vdigit.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/mapdisp_window.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/mapdisp_window.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/mapdisp_window.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -1,20 +1,20 @@
 """!
 @package mapdisp_window.py
 
- at brief GIS map display canvas, buffered window.
+ at brief Map display canvas - buffered window.
 
 Classes:
  - MapWindow
  - BufferedWindow
 
-(C) 2006-2010 by the GRASS Development Team
+(C) 2006-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.
 
+ at author Martin Landa <landa.martin gmail.com>
 @author Michael Barton
 @author Jachym Cepicky
- at author Martin Landa <landa.martin gmail.com>
 """
 
 import os
@@ -29,7 +29,6 @@
 import grass.script as grass
 
 import dbm
-import dbm_dialogs
 import gdialogs
 import gcmd
 import utils
@@ -38,17 +37,18 @@
 from debug import Debug
 from preferences import globalSettings as UserSettings
 from units import ConvertValue as UnitsConvertValue
-from vdigit import GV_LINES as VDigit_Lines_Type
-from vdigit import VDigitCategoryDialog
-from vdigit import VDigitZBulkDialog
-from vdigit import VDigitDuplicatesDialog
-from vdigit import PseudoDC as VDigitPseudoDC
 
-class MapWindow(object):
-    """!Abstract map window class
+try:
+    import grass.lib.gis as gislib
+    haveCtypes = True
+except ImportError:
+    haveCtypes = False
 
-    Parent for BufferedWindow class (2D display mode) and
-    GLWindow (3D display mode)
+class MapWindow(object):
+    """!Abstract map display window class
+    
+    Superclass for BufferedWindow class (2D display mode), and GLWindow
+    (3D display mode).
     """
     def __init__(self, parent, id = wx.ID_ANY,
                  Map = None, tree = None, lmgr = None, **kwargs):
@@ -65,30 +65,9 @@
             'use'  : "pointer",
             'box'  : "point"
             }
-        
-    def EraseMap(self):
-        """!Erase the canvas (virtual method)
-        """
-        pass
 
-    def UpdateMap(self):
-        """!Updates the canvas anytime there is a change to the
-        underlaying images or to the geometry of the canvas.
-        """
-        pass
-
-    def OnLeftDown(self, event):
-        pass
-
-    def OnLeftUp(self, event):
-        pass
-
-    def OnKeyDown(self, event):
-        pass
-    
     def OnMotion(self, event):
-        """!Mouse moved
-        Track mouse motion and update status bar
+        """!Track mouse motion and update statusbar
         """
         if self.parent.statusbarWin['toggle'].GetSelection() == 0: # Coordinates
             precision = int(UserSettings.Get(group = 'projection', key = 'format',
@@ -101,23 +80,11 @@
                 self.parent.statusbar.SetStatusText("", 0)
                 return
             
-            if self.parent.toolbars['vdigit'] and \
-                    self.parent.toolbars['vdigit'].GetAction() == 'addLine' and \
-                    self.parent.toolbars['vdigit'].GetAction('type') in ('line', 'boundary') and \
-                    len(self.polycoords) > 0:
-                # for linear feature show segment and total length
-                distance_seg = self.Distance(self.polycoords[-1],
-                                             (e, n), screen = False)[0]
-                distance_tot = distance_seg
-                for idx in range(1, len(self.polycoords)):
-                    distance_tot += self.Distance(self.polycoords[idx-1],
-                                                  self.polycoords[idx],
-                                                  screen = False)[0]
-                self.parent.statusbar.SetStatusText("%.*f, %.*f (seg: %.*f; tot: %.*f)" % \
-                                                 (precision, e, precision, n,
-                                                  precision, distance_seg,
-                                                  precision, distance_tot), 0)
-            else:
+            updated = False
+            if hasattr(self, "digit"):
+                updated = self._onMotion((e, n), precision)
+
+            if not updated:
                 if self.parent.statusbarWin['projection'].IsChecked():
                     if not UserSettings.Get(group = 'projection', key = 'statusbar', subkey = 'proj4'):
                         self.parent.statusbar.SetStatusText(_("Projection not defined (check the settings)"), 0)
@@ -145,14 +112,9 @@
                     else:
                         self.parent.statusbar.SetStatusText("%.*f; %.*f" % \
                                                                 (precision, e, precision, n), 0)
+        
         event.Skip()
 
-    def OnZoomToMap(self, event):
-        pass
-
-    def OnZoomToRaster(self, event):
-        pass
-    
     def GetLayerByName(self, name, mapType, dataType = 'layer'):
         """!Get layer from layer tree by nam
         
@@ -182,7 +144,7 @@
     
     def GetSelectedLayer(self, type = 'layer', multi = False):
         """!Get selected layer from layer tree
-
+        
         @param type 'item' / 'layer' / 'nviz'
         @param multi return first selected layer or all
         
@@ -227,12 +189,14 @@
         return ret
     
 class BufferedWindow(MapWindow, wx.Window):
-    """!A Buffered window class.
+    """!A Buffered window class (2D view mode)
 
+    Superclass for VDigitWindow (vector digitizer).
+    
     When the drawing needs to change, you app needs to call the
     UpdateMap() method. Since the drawing is stored in a bitmap, you
     can also save the drawing to file by calling the
-    SaveToFile(self,file_name,file_type) method.
+    SaveToFile() method.
     """
     def __init__(self, parent, id = wx.ID_ANY,
                  Map = None, tree = None, lmgr = None,
@@ -243,7 +207,7 @@
         # flags
         self.resize = False # indicates whether or not a resize event has taken place
         self.dragimg = None # initialize variable for map panning
-
+        
         # variables for drawing on DC
         self.pen = None      # pen for drawing zoom boxes, etc.
         self.polypen = None  # pen for drawing polylines (measurements, profiles, etc)
@@ -258,7 +222,6 @@
         self.Bind(wx.EVT_PAINT,        self.OnPaint)
         self.Bind(wx.EVT_SIZE,         self.OnSize)
         self.Bind(wx.EVT_IDLE,         self.OnIdle)
-        ### self.Bind(wx.EVT_MOTION,       self.MouseActions)
         self.Bind(wx.EVT_MOUSE_EVENTS, self.MouseActions)
         self.Bind(wx.EVT_MOTION,       self.OnMotion)
         
@@ -267,8 +230,6 @@
         # render output objects
         self.mapfile = None   # image file to be rendered
         self.img     = None   # wx.Image object (self.mapfile)
-        # used in digitization tool (do not redraw vector map)
-        self.imgVectorMap = None
         # decoration overlays
         self.overlays = {}
         # images and their PseudoDC ID's for painting and dragging
@@ -276,72 +237,44 @@
         self.select = {}      # selecting/unselecting decorations for dragging
         self.textdict = {}    # text, font, and color indexed by id
         self.currtxtid = None # PseudoDC id for currently selected text
-
+        
         # zoom objects
         self.zoomhistory  = [] # list of past zoom extents
         self.currzoom     = 0  # current set of extents in zoom history being used
         self.zoomtype     = 1  # 1 zoom in, 0 no zoom, -1 zoom out
         self.hitradius    = 10 # distance for selecting map decorations
         self.dialogOffset = 5  # offset for dialog (e.g. DisplayAttributesDialog)
-
+        
         # OnSize called to make sure the buffer is initialized.
         # This might result in OnSize getting called twice on some
         # platforms at initialization, but little harm done.
         ### self.OnSize(None)
-
-        self.DefinePseudoDC()
+        
+        self._definePseudoDC()
         # redraw all pdc's, pdcTmp layer is redrawn always (speed issue)
         self.redrawAll = True
-
+        
         # will store an off screen empty bitmap for saving to file
-        self._buffer = ''
-
+        self._buffer = None
+        
         self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x:None)
-        self.Bind(wx.EVT_KEY_DOWN , self.OnKeyDown)
         
         # vars for handling mouse clicks
         self.dragid   = -1
         self.lastpos  = (0, 0)
-
-    def DefinePseudoDC(self, vdigit = False):
-        """!Define PseudoDC class to use
-
-        @vdigit True to use PseudoDC from vdigit
+        
+    def _definePseudoDC(self):
+        """!Define PseudoDC objects to use
         """
         # create PseudoDC used for background map, map decorations like scales and legends
-        self.pdc = self.PseudoDC(vdigit)
+        self.pdc = wx.PseudoDC()
         # used for digitization tool
         self.pdcVector = None
         # decorations (region box, etc.)
-        self.pdcDec = self.PseudoDC(vdigit)
+        self.pdcDec = wx.PseudoDC()
         # pseudoDC for temporal objects (select box, measurement tool, etc.)
-        self.pdcTmp = self.PseudoDC(vdigit)
+        self.pdcTmp = wx.PseudoDC()
         
-    def PseudoDC(self, vdigit = False):
-        """!Create PseudoDC instance"""
-        if vdigit:
-            PseudoDC = VDigitPseudoDC
-        else:
-            PseudoDC = wx.PseudoDC
-        
-        return PseudoDC()
-    
-    def CheckPseudoDC(self):
-        """!Try to draw background
-        
-        @return True on success
-        @return False on failure
-        """
-        try:
-            self.pdc.BeginDrawing()
-            self.pdc.SetBackground(wx.Brush(self.GetBackgroundColour()))
-            self.pdc.BeginDrawing()
-        except StandardError, e:
-            traceback.print_exc(file = sys.stderr)
-            return False
-        
-        return True
-    
     def Draw(self, pdc, img = None, drawid = None, pdctype = 'image', coords = [0, 0, 0, 0]):
         """!Draws map and overlay decorations
         """
@@ -356,25 +289,23 @@
         if img and pdctype == 'image':
             # self.imagedict[img]['coords'] = coords
             self.select[self.imagedict[img]['id']] = False # ?
-
+        
         pdc.BeginDrawing()
-
+        
         if drawid != 99:
             bg = wx.TRANSPARENT_BRUSH
         else:
             bg = wx.Brush(self.GetBackgroundColour())
-
+        
         pdc.SetBackground(bg)
         
-        ### pdc.Clear()
-
         Debug.msg (5, "BufferedWindow.Draw(): id=%s, pdctype = %s, coord=%s" % \
                        (drawid, pdctype, coords))
-
+        
         # set PseudoDC id
         if drawid is not None:
             pdc.SetId(drawid)
-        
+            
         if pdctype == 'clear': # erase the display
             bg = wx.WHITE_BRUSH
             # bg = wx.Brush(self.GetBackgroundColour())
@@ -385,13 +316,13 @@
             
             self.Refresh()
             return
-
+        
         if pdctype == 'image': # draw selected image
             bitmap = wx.BitmapFromImage(img)
             w,h = bitmap.GetSize()
             pdc.DrawBitmap(bitmap, coords[0], coords[1], True) # draw the composite map
             pdc.SetIdBounds(drawid, wx.Rect(coords[0],coords[1], w, h))
-
+        
         elif pdctype == 'box': # draw a box on top of the map
             if self.pen:
                 pdc.SetBrush(wx.Brush(wx.CYAN, wx.TRANSPARENT))
@@ -412,13 +343,11 @@
                 pdc.SetPen(self.pen)
                 pdc.DrawLinePoint(wx.Point(coords[0], coords[1]),wx.Point(coords[2], coords[3]))
                 pdc.SetIdBounds(drawid, wx.Rect(coords[0], coords[1], coords[2], coords[3]))
-                # self.ovlcoords[drawid] = coords
-
+        
         elif pdctype == 'polyline': # draw a polyline on top of the map
             if self.polypen:
                 pdc.SetBrush(wx.Brush(wx.CYAN, wx.TRANSPARENT))
                 pdc.SetPen(self.polypen)
-                ### pdc.DrawLines(coords)
                 if (len(coords) < 2):
                     return
                 i = 1
@@ -426,7 +355,7 @@
                     pdc.DrawLinePoint(wx.Point(coords[i-1][0], coords[i-1][1]),
                                       wx.Point(coords[i][0], coords[i][1]))
                     i += 1
-
+                
                 # get bounding rectangle for polyline
                 xlist = []
                 ylist = []
@@ -441,7 +370,7 @@
                     y2 = max(ylist)
                     pdc.SetIdBounds(drawid, wx.Rect(x1,y1,x2,y2))
                     # self.ovlcoords[drawid] = [x1,y1,x2,y2]
-                    
+        
         elif pdctype == 'point': # draw point
             if self.pen:
                 pdc.SetPen(self.pen)
@@ -451,12 +380,11 @@
                                coords[0] + 5,
                                coords[1] + 5)
                 pdc.SetIdBounds(drawid, wx.Rect(coordsBound))
-                # self.ovlcoords[drawid] = coords
-
+        
         elif pdctype == 'text': # draw text on top of map
             if not img['active']:
-                return #only draw active text
-            if img.has_key('rotation'):
+                return # only draw active text
+            if 'rotation' in img:
                 rotation = float(img['rotation'])
             else:
                 rotation = 0.0
@@ -469,20 +397,20 @@
             else:
                 pdc.DrawRotatedText(img['text'], coords[0], coords[1], rotation)
             pdc.SetIdBounds(drawid, wx.Rect(coords[0], coords[1], w, h))
-            
+        
         pdc.EndDrawing()
         
         self.Refresh()
         
         return drawid
-
+    
     def TextBounds(self, textinfo):
         """!Return text boundary data
-
+        
         @param textinfo text metadata (text, font, color, rotation)
         @param coords reference point
         """
-        if textinfo.has_key('rotation'):
+        if 'rotation' in textinfo:
             rotation = float(textinfo['rotation'])
         else:
             rotation = 0.0
@@ -491,18 +419,17 @@
         
         Debug.msg (4, "BufferedWindow.TextBounds(): text=%s, rotation=%f" % \
                    (textinfo['text'], rotation))
-
+        
         self.Update()
-        ### self.Refresh()
-
+        
         self.SetFont(textinfo['font'])
-
+        
         w, h = self.GetTextExtent(textinfo['text'])
-
+        
         if rotation == 0:
             coords[2], coords[3] = coords[0] + w, coords[1] + h
             return coords, w, h
-
+        
         boxh = math.fabs(math.sin(math.radians(rotation)) * w) + h
         boxw = math.fabs(math.cos(math.radians(rotation)) * w) + h
         coords[2] = coords[0] + boxw
@@ -510,41 +437,14 @@
         
         return coords, boxw, boxh
 
-    def OnKeyDown(self, event):
-        """!Key pressed"""
-        shift = event.ShiftDown()
-        kc = event.GetKeyCode()
-        
-        vdigitToolbar = self.parent.toolbars['vdigit']
-        ### vdigit
-        if vdigitToolbar:
-            event = None
-            if not shift:
-                if kc == ord('P'):
-                    event = wx.CommandEvent(winid = vdigitToolbar.addPoint)
-                    tool = vdigitToolbar.OnAddPoint
-                elif kc == ord('L'):
-                    event = wx.CommandEvent(winid = vdigitToolbar.addLine)
-                    tool = vdigitToolbar.OnAddLine
-            if event:
-                vdigitToolbar.OnTool(event)
-                tool(event)
-        
     def OnPaint(self, event):
-        """!
-        Draw PseudoDC's to buffered paint DC
-
-        self.pdc for background and decorations
-        self.pdcVector for vector map which is edited
-        self.pdcTmp for temporaly drawn objects (self.polycoords)
-
+        """!Draw PseudoDC's to buffered paint DC
+        
         If self.redrawAll is False on self.pdcTmp content is re-drawn
         """
         Debug.msg(4, "BufferedWindow.OnPaint(): redrawAll=%s" % self.redrawAll)
         
         dc = wx.BufferedPaintDC(self, self.buffer)
-        
-        ### dc.SetBackground(wx.Brush("White"))
         dc.Clear()
         
         # use PrepareDC to set position correctly
@@ -565,7 +465,7 @@
             self.pdc.DrawToDCClipped(dc, rgn)
             
             # draw vector map layer
-            if self.pdcVector:
+            if hasattr(self, "digit"):
                 # decorate with GDDC (transparency)
                 try:
                     gcdc = wx.GCDC(dc)
@@ -580,7 +480,7 @@
                 # draw to the dc
                 self.pdc.DrawToDC(dc)
                 
-                if self.pdcVector:
+                if hasattr(self, "digit"):
                     # decorate with GDDC (transparency)
                     try:
                         gcdc = wx.GCDC(dc)
@@ -588,14 +488,13 @@
                     except NotImplementedError, e:
                         print >> sys.stderr, e
                         self.pdcVector.DrawToDC(dc)
-                        
+                
                 # store buffered image
                 # self.bufferLast = wx.BitmapFromImage(self.buffer.ConvertToImage())
                 self.bufferLast = dc.GetAsBitmap(wx.Rect(0, 0, self.Map.width, self.Map.height))
             
-            pdcLast = self.PseudoDC(vdigit = False)
-            pdcLast.DrawBitmap(self.bufferLast, 0, 0, False)
-            pdcLast.DrawToDC(dc)
+            self.pdc.DrawBitmap(self.bufferLast, 0, 0, False)
+            self.pdc.DrawToDC(dc)
         
         # draw decorations (e.g. region box)
         try:
@@ -636,23 +535,23 @@
             self.img = self.img.Scale(self.Map.width, self.Map.height)
             if len(self.Map.GetListOfLayers()) > 0:
                 self.UpdateMap()
-
+        
         # re-render image on idle
         self.resize = True
 
         # reposition checkbox in statusbar
         self.parent.StatusbarReposition()
-
+        
         # update statusbar
         self.parent.StatusbarUpdate()
-
+        
     def OnIdle(self, event):
         """!Only re-render a composite map image from GRASS during
         idle time instead of multiple times during resizing.
         """
         if self.resize:
             self.UpdateMap(render = True)
-
+        
         event.Skip()
 
     def SaveToFile(self, FileName, FileType, width, height):
@@ -687,11 +586,10 @@
         self.Refresh()
         
     def GetOverlay(self):
-        """!
-        Converts rendered overlay files to wx.Image
-
+        """!Converts rendered overlay files to wx.Image
+        
         Updates self.imagedict
-
+        
         @return list of images
         """
         imgs = []
@@ -703,12 +601,12 @@
                 imgs.append(img)
 
         return imgs
-
+    
     def GetImage(self):
         """!Converts redered map files to wx.Image
-
+        
         Updates self.imagedict (id=99)
-
+        
         @return wx.Image instance (map composition)
         """
         imgId = 99
@@ -723,8 +621,7 @@
         return img
 
     def UpdateMap(self, render = True, renderVector = True):
-        """!
-        Updates the canvas anytime there is a change to the
+        """!Updates the canvas anytime there is a change to the
         underlaying images or to the geometry of the canvas.
         
         @param render re-render map composition
@@ -734,16 +631,13 @@
         
         self.resize = False
         
-        # if len(self.Map.GetListOfLayers()) == 0:
-        #    return False
-        
         if self.img is None:
             render = True
         
         #
         # initialize process bar (only on 'render')
         #
-        if render is True or renderVector is True:
+        if render or renderVector:
             self.parent.statusbarWin['progress'].Show()
             if self.parent.statusbarWin['progress'].GetRange() > 0:
                 self.parent.statusbarWin['progress'].SetValue(1)
@@ -751,9 +645,8 @@
         #
         # render background image if needed
         #
-        
         # update layer dictionary if there has been a change in layers
-        if self.tree and self.tree.reorder == True:
+        if self.tree and self.tree.reorder:
             self.tree.ReorderLayers()
         
         # reset flag for auto-rendering
@@ -778,7 +671,7 @@
             self.mapfile = None
         
         self.img = self.GetImage() # id=99
-            
+        
         #
         # clear pseudoDcs
         #
@@ -798,42 +691,14 @@
                 id = self.imagedict[self.img]['id']
             except:
                 return False
-
+            
             self.Draw(self.pdc, self.img, drawid = id)
         
         #
         # render vector map layer
         #
-        digitToolbar = self.parent.toolbars['vdigit']
-        if renderVector and digitToolbar and \
-                digitToolbar.GetLayer():
-            # set region
-            self.parent.digit.driver.UpdateRegion()
-            # re-calculate threshold for digitization tool
-            self.parent.digit.driver.GetThreshold()
-            # draw map
-            if self.pdcVector:
-                self.pdcVector.Clear()
-                self.pdcVector.RemoveAll()
-            try:
-                item = self.tree.FindItemByData('maplayer', digitToolbar.GetLayer())
-            except TypeError:
-                item = None
-            
-            if item and self.tree.IsItemChecked(item):
-                self.parent.digit.driver.DrawMap()
-
-            # translate tmp objects (pointer position)
-            if digitToolbar.GetAction() == 'moveLine':
-                if  hasattr(self, "vdigitMove") and \
-                        self.vdigitMove.has_key('beginDiff'):
-                    # move line
-                    for id in self.vdigitMove['id']:
-                        self.pdcTmp.TranslateId(id,
-                                                self.vdigitMove['beginDiff'][0],
-                                                self.vdigitMove['beginDiff'][1])
-                    del self.vdigitMove['beginDiff']
-        
+        if renderVector and hasattr(self, "digit"):
+            self._updateMap()
         #
         # render overlays
         #
@@ -843,7 +708,7 @@
                 id = self.imagedict[img]['id']
                 self.Draw(self.pdc, img = img, drawid = id,
                           pdctype = self.overlays[id]['pdcType'], coords = self.overlays[id]['coords'])
-
+        
         for id in self.textdict.keys():
             self.Draw(self.pdc, img = self.textdict[id], drawid = id,
                       pdctype = 'text', coords = [10, 10, 10, 10])
@@ -906,7 +771,7 @@
         else:
             self.parent.statusbarWin['mask'].SetLabel('')
         
-        Debug.msg (2, "BufferedWindow.UpdateMap(): render=%s, renderVector=%s -> time=%g" % \
+        Debug.msg (1, "BufferedWindow.UpdateMap(): render=%s, renderVector=%s -> time=%g" % \
                    (render, renderVector, (stop-start)))
         
         return True
@@ -953,25 +818,23 @@
                 region['w'] >= refRegion['w'] and \
                 region['e'] <= refRegion['e']:
             return True
-
+        
         return False
 
     def EraseMap(self):
-        """!
-        Erase the canvas
+        """!Erase map canvas
         """
         self.Draw(self.pdc, pdctype = 'clear')
-                  
-        if self.pdcVector:
+        
+        if hasattr(self, "digit"):
             self.Draw(self.pdcVector, pdctype = 'clear')
         
         self.Draw(self.pdcDec, pdctype = 'clear')
         self.Draw(self.pdcTmp, pdctype = 'clear')
         
     def DragMap(self, moveto):
-        """!
-        Drag the entire map image for panning.
-
+        """!Drag the entire map image for panning.
+        
         @param moveto dx,dy
         """
         dc = wx.BufferedDC(wx.ClientDC(self))
@@ -987,8 +850,7 @@
         self.dragimg.EndDrag()
         
     def DragItem(self, id, event):
-        """!
-        Drag an overlay decoration item
+        """!Drag an overlay decoration item
         """
         if id == 99 or id == '' or id == None: return
         Debug.msg (5, "BufferedWindow.DragItem(): id=%d" % id)
@@ -997,7 +859,6 @@
         dy = event.GetY() - y
         self.pdc.SetBackground(wx.Brush(self.GetBackgroundColour()))
         r = self.pdc.GetIdBounds(id)
-        ### FIXME in vdigit/pseudodc.i
         if type(r) is list:
             r = wx.Rect(r[0], r[1], r[2], r[3])
         if id > 100: # text dragging
@@ -1006,7 +867,7 @@
             rleft = (r[0]-r[2],r[1],r[2],r[3])
             r = r.Union(rleft)
         self.pdc.TranslateId(id, dx, dy)
-
+        
         r2 = self.pdc.GetIdBounds(id)
         if type(r2) is list:
             r2 = wx.Rect(r[0], r[1], r[2], r[3])
@@ -1018,26 +879,22 @@
         self.lastpos = (event.GetX(), event.GetY())
                 
     def MouseDraw(self, pdc = None, begin = None, end = None):
-        """!
-        Mouse box or line from 'begin' to 'end'
-
+        """!Mouse box or line from 'begin' to 'end'
+        
         If not given from self.mouse['begin'] to self.mouse['end'].
-
         """
-#        self.redrawAll = False
-        
         if not pdc:
             return
-
+        
         if begin is None:
             begin = self.mouse['begin']
         if end is None:
             end   = self.mouse['end']
-
+        
         Debug.msg (5, "BufferedWindow.MouseDraw(): use=%s, box=%s, begin=%f,%f, end=%f,%f" % \
                        (self.mouse['use'], self.mouse['box'],
                         begin[0], begin[1], end[0], end[1]))
-
+        
         if self.mouse['box'] == "box":
             boxid = wx.ID_NEW
             mousecoords = [begin[0], begin[1],
@@ -1053,6 +910,7 @@
             self.RefreshRect(r, False)
             pdc.SetId(boxid)
             self.Draw(pdc, drawid = boxid, pdctype = 'box', coords = mousecoords)
+        
         elif self.mouse['box'] == "line" or self.mouse['box'] == 'point':
             self.lineid = wx.ID_NEW
             mousecoords = [begin[0], begin[1], \
@@ -1072,18 +930,16 @@
             self.Draw(pdc, drawid = self.lineid, pdctype = 'line', coords = mousecoords)
 
     def DrawLines(self, pdc = None, polycoords = None):
-        """!
-        Draw polyline in PseudoDC
-
+        """!Draw polyline in PseudoDC
+        
         Set self.pline to wx.NEW_ID + 1
-
+        
         polycoords - list of polyline vertices, geographical coordinates
         (if not given, self.polycoords is used)
-
         """
         if not pdc:
             pdc = self.pdcTmp
-
+        
         if not polycoords:
             polycoords = self.polycoords
         
@@ -1098,9 +954,9 @@
             
             Debug.msg (4, "BufferedWindow.DrawLines(): coords=%s, id=%s" % \
                            (coords, self.plineid))
-
+            
             return self.plineid
-
+        
         return -1
 
     def DrawCross(self, pdc, coords, size, rotation = 0,
@@ -1124,10 +980,10 @@
         self.lineid = wx.NewId()
         for lineCoords in coordsCross:
             self.Draw(pdc, drawid = self.lineid, pdctype = 'line', coords = lineCoords)
-
+        
         if not text:
             return self.lineid
-
+        
         if textAlign == 'ul':
             coord = [coords[0] - textOffset[0], coords[1] - textOffset[1], 0, 0]
         elif textAlign == 'ur':
@@ -1139,19 +995,15 @@
         
         self.Draw(pdc, img = text,
                   pdctype = 'text', coords = coord)
-
+        
         return self.lineid
 
     def MouseActions(self, event):
-        """!
-        Mouse motion and button click notifier
+        """!Mouse motion and button click notifier
         """
         if not self.processMouse:
             return
         
-        ### if self.redrawAll is False:
-        ###    self.redrawAll = True
-        
         # zoom with mouse wheel
         if event.GetWheelRotation() != 0:
             self.OnMouseWheel(event)
@@ -1159,23 +1011,23 @@
         # left mouse button pressed
         elif event.LeftDown():
             self.OnLeftDown(event)
-
+        
         # left mouse button released
         elif event.LeftUp():
             self.OnLeftUp(event)
-
+        
         # dragging
         elif event.Dragging():
             self.OnDragging(event)
-
+        
         # double click
         elif event.ButtonDClick():
             self.OnButtonDClick(event)
-
+        
         # middle mouse button pressed
         elif event.MiddleDown():
             self.OnMiddleDown(event)
-
+        
         # middle mouse button relesed
         elif event.MiddleUp():
             self.OnMiddleUp(event)
@@ -1183,22 +1035,19 @@
         # right mouse button pressed
         elif event.RightDown():
             self.OnRightDown(event)
-
+        
         # right mouse button released
         elif event.RightUp():
             self.OnRightUp(event)
-
+        
         elif event.Entering():
             self.OnMouseEnter(event)
-
+        
         elif event.Moving():
             self.OnMouseMoving(event)
-        
-        # event.Skip()
-        
+                
     def OnMouseWheel(self, event):
-        """!
-        Mouse wheel moved
+        """!Mouse wheel moved
         """
         self.processMouse = False
         current  = event.GetPositionTuple()[:]
@@ -1214,25 +1063,21 @@
             zoomtype = 1
         else:
             zoomtype = -1
-
+        
         # zoom
         self.Zoom(begin, end, zoomtype)
-
+        
         # redraw map
         self.UpdateMap()
-
-        ### self.OnPaint(None)
-
+        
         # update statusbar
         self.parent.StatusbarUpdate()
-
+        
         self.Refresh()
         self.processMouse = True
-#        event.Skip()
-
+        
     def OnDragging(self, event):
-        """!
-        Mouse dragging with left button down
+        """!Mouse dragging
         """
         Debug.msg (5, "BufferedWindow.MouseAction(): Dragging")
         current  = event.GetPositionTuple()[:]
@@ -1240,7 +1085,10 @@
         move = (current[0] - previous[0],
                 current[1] - previous[1])
         
-        digitToolbar = self.parent.toolbars['vdigit']
+        if hasattr(self, "digit"):
+            digitToolbar = self.toolbar
+        else:
+            digitToolbar = None
         
         # dragging or drawing box with left button
         if self.mouse['use'] == 'pan' or \
@@ -1256,341 +1104,22 @@
         # dragging anything else - rubber band box or line
         else:
             if (self.mouse['use'] == 'pointer' and 
-                not digitToolbar): return
+                not digitToolbar):
+                return
             self.mouse['end'] = event.GetPositionTuple()[:]
-            digitClass = self.parent.digit
             if (event.LeftIsDown() and 
                 not (digitToolbar and 
                     digitToolbar.GetAction() in ("moveLine",) and 
-                    digitClass.driver.GetSelected() > 0)):
+                    self.display.GetSelected() > 0)):
                 # draw box only when left mouse button is pressed
                 self.MouseDraw(pdc = self.pdcTmp)
         
-        # event.Skip()
-
-    def OnLeftDownVDigitAddLine(self, event):
-        """!Left mouse button down - vector digitizer add new line
-        action
-        """
-        digitToolbar = self.parent.toolbars['vdigit']
-        digitClass   = self.parent.digit
-        
-        try:
-            mapLayer = digitToolbar.GetLayer().GetName()
-        except:
-            return
-        
-        if digitToolbar.GetAction('type') in ["point", "centroid"]:
-            # add new point
-            if digitToolbar.GetAction('type') == 'point':
-                point = True
-            else:
-                point = False
-
-            east, north = self.Pixel2Cell(self.mouse['begin'])
-            fid = digitClass.AddPoint(mapLayer, point, east, north)
-            if fid < 0:
-                return
-
-            self.UpdateMap(render = False) # redraw map
-            
-            # add new record into atribute table
-            if UserSettings.Get(group = 'vdigit', key = "addRecord", subkey = 'enabled')  is True:
-                # select attributes based on layer and category
-                cats = { fid : {
-                        UserSettings.Get(group = 'vdigit', key = "layer", subkey = 'value') :
-                            (UserSettings.Get(group = 'vdigit', key = "category", subkey = 'value'), )
-                        }}
-                
-                posWindow = self.ClientToScreen((self.mouse['end'][0] + self.dialogOffset,
-                                                 self.mouse['end'][1] + self.dialogOffset))
-                
-                addRecordDlg = dbm_dialogs.DisplayAttributesDialog(parent = self, map = mapLayer,
-                                                                   cats = cats,
-                                                                   pos = posWindow,
-                                                                   action = "add")
-
-                if not point:
-                    self.__geomAttrb(fid, addRecordDlg, 'area', digitClass,
-                                     digitToolbar.GetLayer())
-                    self.__geomAttrb(fid, addRecordDlg, 'perimeter', digitClass,
-                                     digitToolbar.GetLayer())
-
-                if addRecordDlg.mapDBInfo and \
-                        addRecordDlg.ShowModal() == wx.ID_OK:
-                    sqlfile = tempfile.NamedTemporaryFile(mode = "w")
-                    for sql in addRecordDlg.GetSQLString():
-                        sqlfile.file.write(sql + ";\n")
-                    sqlfile.file.flush()
-                    
-                    gcmd.RunCommand('db.execute',
-                                    parent = self,
-                                    quiet = True, 
-                                    input = sqlfile.name)
-                
-                if addRecordDlg.mapDBInfo:
-                    self.__updateATM()
-        
-        elif digitToolbar.GetAction('type') in ["line", "boundary"]:
-            # add new point to the line
-            self.polycoords.append(self.Pixel2Cell(event.GetPositionTuple()[:]))
-            self.DrawLines(pdc = self.pdcTmp)
-    
-    def __geomAttrb(self, fid, dialog, attrb, digit, mapLayer):
-        """!Trac geometry attributes?"""
-        item = self.tree.FindItemByData('maplayer', mapLayer)
-        vdigit = self.tree.GetPyData(item)[0]['vdigit']
-        if vdigit and \
-                vdigit.has_key('geomAttr') and \
-                vdigit['geomAttr'].has_key(attrb):
-            val = -1
-            if attrb == 'length':
-                val = digit.GetLineLength(fid)
-                type = attrb
-            elif attrb == 'area':
-                val = digit.GetAreaSize(fid)
-                type = attrb
-            elif attrb == 'perimeter':
-                val = digit.GetAreaPerimeter(fid)
-                type = 'length'
-            
-            if val > 0:
-                layer = int(UserSettings.Get(group = 'vdigit', key = "layer", subkey = 'value'))
-                column = vdigit['geomAttr'][attrb]['column']
-                val = UnitsConvertValue(val, type, vdigit['geomAttr'][attrb]['units'])
-                dialog.SetColumnValue(layer, column, val)
-                dialog.OnReset()
-        
-    def __geomAttrbUpdate(self, fids):
-        """!Update geometry atrributes of currently selected features
-
-        @param fid list feature id
-        """
-        mapLayer = self.parent.toolbars['vdigit'].GetLayer()
-        vectorName =  mapLayer.GetName()
-        digit = self.parent.digit
-        item = self.tree.FindItemByData('maplayer', mapLayer)
-        vdigit = self.tree.GetPyData(item)[0]['vdigit']
-        
-        if vdigit is None or not vdigit.has_key('geomAttr'):
-            return
-        
-        dbInfo = gselect.VectorDBInfo(vectorName)
-        sqlfile = tempfile.NamedTemporaryFile(mode = "w")
-        for fid in fids:
-            for layer, cats in digit.GetLineCats(fid).iteritems():
-                table = dbInfo.GetTable(layer)
-                for attrb, item in vdigit['geomAttr'].iteritems():
-                    val = -1
-                    if attrb == 'length':
-                        val = digit.GetLineLength(fid)
-                        type = attrb
-                    elif attrb == 'area':
-                        val = digit.GetAreaSize(fid)
-                        type = attrb
-                    elif attrb == 'perimeter':
-                        val = digit.GetAreaPerimeter(fid)
-                        type = 'length'
-
-                    if val < 0:
-                        continue
-                    val = UnitsConvertValue(val, type, item['units'])
-                    
-                    for cat in cats:
-                        sqlfile.write('UPDATE %s SET %s = %f WHERE %s = %d;\n' % \
-                                          (table, item['column'], val,
-                                           dbInfo.GetKeyColumn(layer), cat))
-            sqlfile.file.flush()
-            gcmd.RunCommand('db.execute',
-                            parent = True,
-                            quiet = True,
-                            input = sqlfile.name)
-            
-    def __updateATM(self):
-        """!Update open Attribute Table Manager
-
-        @todo: use AddDataRow() instead
-        """
-        # update ATM
-        digitToolbar = self.parent.toolbars['vdigit']
-        digitVector = digitToolbar.GetLayer().GetName()
-                            
-        for atm in self.lmgr.dialogs['atm']:
-            atmVector = atm.GetVectorName()
-            if atmVector == digitVector:
-                layer = UserSettings.Get(group = 'vdigit', key = "layer", subkey = 'value')
-                # TODO: use AddDataRow instead
-                atm.LoadData(layer)
-        
-    def OnLeftDownVDigitEditLine(self, event):
-        """!
-        Left mouse button down - vector digitizer edit linear feature
-        - add new vertex.
-        """
-        digitToolbar = self.parent.toolbars['vdigit']
-        digitClass   = self.parent.digit
-        
-        self.polycoords.append(self.Pixel2Cell(self.mouse['begin']))
-        self.vdigitMove['id'].append(wx.NewId())
-        self.DrawLines(pdc = self.pdcTmp)
-
-    def OnLeftDownVDigitMoveLine(self, event):
-        """!
-        Left mouse button down - vector digitizer move feature/vertex,
-        edit linear feature
-        """
-        digitToolbar = self.parent.toolbars['vdigit']
-        digitClass   = self.parent.digit
-        
-        self.vdigitMove = {}
-        # geographic coordinates of initial position (left-down)
-        self.vdigitMove['begin'] = None
-        # list of ids to modify    
-        self.vdigitMove['id'] = []
-        # ids geographic coordinates
-        self.vdigitMove['coord'] = {}
-                
-        if digitToolbar.GetAction() in ["moveVertex", "editLine"]:
-            # set pen
-            pcolor = UserSettings.Get(group = 'vdigit', key = "symbol",
-                                      subkey = ["highlight", "color"])
-            self.pen = self.polypen = wx.Pen(colour = pcolor,
-                                             width = 2, style = wx.SHORT_DASH)
-            self.pdcTmp.SetPen(self.polypen)
-
-    def OnLeftDownVDigitDisplayCA(self, event):
-        """!
-        Left mouse button down - vector digitizer display categories
-        or attributes action
-        """
-        digitToolbar = self.parent.toolbars['vdigit']
-        digitClass   = self.parent.digit
-        
-        try:
-            mapLayer = digitToolbar.GetLayer().GetName()
-        except:
-            return
-        
-        coords = self.Pixel2Cell(self.mouse['begin'])
-        
-        # unselect
-        digitClass.driver.SetSelected([])
-        
-        # select feature by point
-        cats = {}
-        if digitClass.driver.SelectLineByPoint(coords,
-                                               digitClass.GetSelectType()) is None:
-            return
-
-        if UserSettings.Get(group = 'vdigit', key = 'checkForDupl',
-                            subkey = 'enabled'):
-            lines = digitClass.driver.GetSelected()
-        else:
-            lines = (digitClass.driver.GetSelected()[0],) # only first found
-                        
-        for line in lines:
-            cats[line] = digitClass.GetLineCats(line)
-                   
-        posWindow = self.ClientToScreen((self.mouse['end'][0] + self.dialogOffset,
-                                         self.mouse['end'][1] + self.dialogOffset))
-    
-        if digitToolbar.GetAction() == "displayAttrs":
-            # select attributes based on coordinates (all layers)
-            if self.parent.dialogs['attributes'] is None:
-                self.parent.dialogs['attributes'] = \
-                    dbm_dialogs.DisplayAttributesDialog(parent = self, map = mapLayer,
-                                                        cats = cats,
-                                                        action = "update")
-            else:
-                # upgrade dialog
-                self.parent.dialogs['attributes'].UpdateDialog(cats = cats)
-
-            if self.parent.dialogs['attributes']:
-                if len(cats.keys()) > 0:
-                    # highlight feature & re-draw map
-                    if not self.parent.dialogs['attributes'].IsShown():
-                        self.parent.dialogs['attributes'].Show()
-                else:
-                    if self.parent.dialogs['attributes'] and \
-                            self.parent.dialogs['attributes'].IsShown():
-                        self.parent.dialogs['attributes'].Hide()
-
-        else: # displayCats
-            if self.parent.dialogs['category'] is None:
-                # open new dialog
-                dlg = VDigitCategoryDialog(parent = self,
-                                           map = mapLayer,
-                                           cats = cats,
-                                           pos = posWindow,
-                                           title = _("Update categories"))
-                self.parent.dialogs['category'] = dlg
-            else:
-                # update currently open dialog
-                self.parent.dialogs['category'].UpdateDialog(cats = cats)
-                            
-            if self.parent.dialogs['category']:
-                if len(cats.keys()) > 0:
-                    # highlight feature & re-draw map
-                    if not self.parent.dialogs['category'].IsShown():
-                        self.parent.dialogs['category'].Show()
-                else:
-                    if self.parent.dialogs['category'].IsShown():
-                        self.parent.dialogs['category'].Hide()
-                
-        self.UpdateMap(render = False)
- 
-    def OnLeftDownVDigitCopyCA(self, event):
-        """!
-        Left mouse button down - vector digitizer copy categories
-        or attributes action
-        """
-        digitToolbar = self.parent.toolbars['vdigit']
-        digitClass   = self.parent.digit
-        
-        if not hasattr(self, "copyCatsList"):
-            self.copyCatsList = []
-        else:
-            self.copyCatsIds = []
-            self.mouse['box'] = 'box'
-        
-    def OnLeftDownVDigitCopyLine(self, event):
-        """!
-        Left mouse button down - vector digitizer copy lines action
-        """
-        digitToolbar = self.parent.toolbars['vdigit']
-        digitClass   = self.parent.digit
-        
-        if not hasattr(self, "copyIds"):
-            self.copyIds = []
-            self.layerTmp = None
-        
-    def OnLeftDownVDigitBulkLine(self, event):
-        """!Left mouse button down - vector digitizer label 3d vector
-        lines
-        """
-        digitToolbar = self.parent.toolbars['vdigit']
-        digitClass   = self.parent.digit
-        
-        if len(self.polycoords) > 1: # start new line
-            self.polycoords = []
-            self.ClearLines(pdc = self.pdcTmp)
-        self.polycoords.append(self.Pixel2Cell(event.GetPositionTuple()[:]))
-        if len(self.polycoords) == 1:
-            begin = self.Pixel2Cell(self.polycoords[-1])
-            end   = self.Pixel2Cell(self.mouse['end'])
-        else:
-            end   = self.Pixel2Cell(self.polycoords[-1])
-            begin = self.Pixel2Cell(self.mouse['begin'])
-            
-            self.DrawLines(self.pdcTmp, polycoords = (begin, end))
-        
     def OnLeftDown(self, event):
-        """!
-        Left mouse button pressed
+        """!Left mouse button pressed
         """
         Debug.msg (5, "BufferedWindow.OnLeftDown(): use=%s" % \
                    self.mouse["use"])
-
+        
         self.mouse['begin'] = event.GetPositionTuple()[:]
         
         if self.mouse["use"] in ["measure", "profile"]:
@@ -1601,68 +1130,18 @@
                 self.ClearLines(pdc=self.pdcTmp)
             else:
                 self.mouse['begin'] = self.mouse['end']
+        
         elif self.mouse['use'] == 'zoom':
             pass
-
-        #
+        
         # vector digizer
-        #
         elif self.mouse["use"] == "pointer" and \
-                self.parent.toolbars['vdigit']:
-            digitToolbar = self.parent.toolbars['vdigit']
-            digitClass   = self.parent.digit
-            
-            try:
-                mapLayer = digitToolbar.GetLayer().GetName()
-            except:
-                wx.MessageBox(parent = self,
-                              message = _("No vector map selected for editing."),
-                              caption = _("Vector digitizer"),
-                              style = wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
-                event.Skip()
-                return
-            
-            if digitToolbar.GetAction() not in ("moveVertex",
-                                                "addVertex",
-                                                "removeVertex",
-                                                "editLine"):
-                # set pen
-                self.pen = wx.Pen(colour = 'Red', width = 2, style = wx.SHORT_DASH)
-                self.polypen = wx.Pen(colour = 'dark green', width = 2, style = wx.SOLID)
-
-            if digitToolbar.GetAction() in ("addVertex",
-                                            "removeVertex",
-                                            "splitLines"):
-                # unselect
-                digitClass.driver.SetSelected([])
-
-            if digitToolbar.GetAction() == "addLine":
-                self.OnLeftDownVDigitAddLine(event)
-            
-            elif digitToolbar.GetAction() == "editLine" and \
-                    hasattr(self, "vdigitMove"):
-                self.OnLeftDownVDigitEditLine(event)
-
-            elif digitToolbar.GetAction() in ("moveLine", 
-                                              "moveVertex",
-                                              "editLine") and \
-                    not hasattr(self, "vdigitMove"):
-                self.OnLeftDownVDigitMoveLine(event)
-
-            elif digitToolbar.GetAction() in ("displayAttrs"
-                                              "displayCats"):
-                self.OnLeftDownVDigitDisplayCA(event)
-            
-            elif digitToolbar.GetAction() in ("copyCats",
-                                              "copyAttrs"):
-                self.OnLeftDownVDigitCopyCA(event)
-            
-            elif digitToolbar.GetAction() == "copyLine":
-                self.OnLeftDownVDigitCopyLine(event)
-            
-            elif digitToolbar.GetAction() == "zbulkLine":
-                self.OnLeftDownVDigitBulkLine(event)
-            
+                hasattr(self, "digit"):
+            if event.ControlDown():
+                self.OnLeftDownUndo(event)
+            else:
+                self._onLeftDown(event)
+        
         elif self.mouse['use'] == 'pointer':
             # get decoration or text id
             self.idlist = []
@@ -1676,264 +1155,9 @@
                 self.dragid = idlist[0] #drag whatever is on top
         else:
             pass
-
+        
         event.Skip()
-
-    def OnLeftUpVDigitVarious(self, event):
-        """!
-        Left mouse button up - vector digitizer various actions
-        """
-        digitToolbar = self.parent.toolbars['vdigit']
-        digitClass   = self.parent.digit
         
-        pos1 = self.Pixel2Cell(self.mouse['begin'])
-        pos2 = self.Pixel2Cell(self.mouse['end'])
-        
-        nselected = 0
-        # -> delete line || move line || move vertex
-        if digitToolbar.GetAction() in ("moveVertex",
-                                        "editLine"):
-            if len(digitClass.driver.GetSelected()) == 0:
-                nselected = digitClass.driver.SelectLineByPoint(pos1, type = VDigit_Lines_Type)
-                
-                if digitToolbar.GetAction() == "editLine":
-                    try:
-                        selVertex = digitClass.driver.GetSelectedVertex(pos1)[0]
-                    except IndexError:
-                        selVertex = None
-                        
-                    if selVertex:
-                        # self.UpdateMap(render=False)
-                        ids = digitClass.driver.GetSelected(grassId = False)
-                        # move this line to tmp layer
-                        self.polycoords = []
-                        for id in ids:
-                            if id % 2: # register only vertices
-                                e, n = self.Pixel2Cell(self.pdcVector.GetIdBounds(id)[0:2])
-                                self.polycoords.append((e, n))
-                        digitClass.driver.DrawSelected(False) 
-                                
-                        if selVertex < ids[-1] / 2:
-                            # choose first or last node of line
-                            self.vdigitMove['id'].reverse()
-                            self.polycoords.reverse()
-                    else:
-                        # unselect
-                        digitClass.driver.SetSelected([])
-                        del self.vdigitMove
-                
-                    self.UpdateMap(render = False)
-            
-        elif digitToolbar.GetAction() in ("copyCats",
-                                          "copyAttrs"):
-            if not hasattr(self, "copyCatsIds"):
-                # 'from' -> select by point
-                nselected = digitClass.driver.SelectLineByPoint(pos1, digitClass.GetSelectType())
-                if nselected:
-                    self.copyCatsList = digitClass.driver.GetSelected()
-            else:
-                # -> 'to' -> select by bbox
-                digitClass.driver.SetSelected([])
-                # return number of selected features (by box/point)
-                nselected = digitClass.driver.SelectLinesByBox(pos1, pos2,
-                                                               digitClass.GetSelectType())
-                if nselected == 0:
-                    if digitClass.driver.SelectLineByPoint(pos1,
-                                                           digitClass.GetSelectType()) is not None:
-                        nselected = 1
-                        
-                if nselected > 0:
-                    self.copyCatsIds = digitClass.driver.GetSelected()
-
-        elif digitToolbar.GetAction() == "queryLine":
-            selected = digitClass.SelectLinesByQuery(pos1, pos2)
-            nselected = len(selected)
-            if nselected > 0:
-                digitClass.driver.SetSelected(selected)
-
-        else:
-            # -> moveLine || deleteLine, etc. (select by point/box)
-            if digitToolbar.GetAction() == 'moveLine' and \
-                    len(digitClass.driver.GetSelected()) > 0:
-                nselected = 0
-            else:
-                if digitToolbar.GetAction() == 'moveLine':
-                    drawSeg = True
-                else:
-                    drawSeg = False
-
-                nselected = digitClass.driver.SelectLinesByBox(pos1, pos2,
-                                                               digitClass.GetSelectType(),
-                                                               drawSeg)
-                    
-                if nselected == 0:
-                    if digitClass.driver.SelectLineByPoint(pos1,
-                                                           digitClass.GetSelectType()) is not None:
-                        nselected = 1
-        
-        if nselected > 0:
-            if digitToolbar.GetAction() in ("moveLine",
-                                            "moveVertex"):
-                # get pseudoDC id of objects which should be redrawn
-                if digitToolbar.GetAction() == "moveLine":
-                    # -> move line
-                    self.vdigitMove['id'] = digitClass.driver.GetSelected(grassId = False)
-                    self.vdigitMove['coord'] = digitClass.driver.GetSelectedCoord()
-                else: # moveVertex
-                    self.vdigitMove['id'] = digitClass.driver.GetSelectedVertex(pos1)
-                    if len(self.vdigitMove['id']) == 0: # no vertex found
-                        digitClass.driver.SetSelected([])
-                
-            #
-            # check for duplicates
-            #
-            if UserSettings.Get(group = 'vdigit', key = 'checkForDupl', subkey = 'enabled') is True:
-                dupl = digitClass.driver.GetDuplicates()
-                self.UpdateMap(render = False)
-                    
-                if dupl:
-                    posWindow = self.ClientToScreen((self.mouse['end'][0] + self.dialogOffset,
-                                                     self.mouse['end'][1] + self.dialogOffset))
-                    
-                    dlg = VDigitDuplicatesDialog(parent = self, data = dupl, pos = posWindow)
-                    
-                    if dlg.ShowModal() == wx.ID_OK:
-                        digitClass.driver.UnSelect(dlg.GetUnSelected())
-                        # update selected
-                        self.UpdateMap(render = False)
-                
-            if digitToolbar.GetAction() != "editLine":
-                # -> move line || move vertex
-                self.UpdateMap(render = False)
-        
-        else: # no vector object found
-            if not (digitToolbar.GetAction() in ("moveLine",
-                                                 "moveVertex") and \
-                        len(self.vdigitMove['id']) > 0):
-                # avoid left-click when features are already selected
-                self.UpdateMap(render = False, renderVector = False)
-        
-    def OnLeftUpVDigitModifyLine(self, event):
-        """!
-        Left mouse button up - vector digitizer split line, add/remove
-        vertex action
-        """
-        digitToolbar = self.parent.toolbars['vdigit']
-        digitClass   = self.parent.digit
-        
-        pos1 = self.Pixel2Cell(self.mouse['begin'])
-        
-        pointOnLine = digitClass.driver.SelectLineByPoint(pos1,
-                                                          type = VDigit_Lines_Type)
-
-        if not pointOnLine:
-            return
-
-        if digitToolbar.GetAction() in ["splitLine", "addVertex"]:
-            self.UpdateMap(render = False) # highlight object
-            self.DrawCross(pdc = self.pdcTmp, coords = self.Cell2Pixel(pointOnLine),
-                           size = 5)
-        else: # removeVertex
-            # get only id of vertex
-            try:
-                id = digitClass.driver.GetSelectedVertex(pos1)[0]
-            except IndexError:
-                id = None
-
-            if id:
-                x, y = self.pdcVector.GetIdBounds(id)[0:2]
-                self.pdcVector.RemoveId(id)
-                self.UpdateMap(render = False) # highlight object
-                self.DrawCross(pdc = self.pdcTmp, coords = (x, y),
-                               size = 5)
-            else:
-                # unselect
-                digitClass.driver.SetSelected([])
-                self.UpdateMap(render = False)
-
-    def OnLeftUpVDigitCopyLine(self, event):
-        """!
-        Left mouse button up - vector digitizer copy feature action
-        """
-        digitToolbar = self.parent.toolbars['vdigit']
-        digitClass   = self.parent.digit
-        
-        pos1 = self.Pixel2Cell(self.mouse['begin'])
-        pos2 = self.Pixel2Cell(self.mouse['end'])
-        
-        if UserSettings.Get(group = 'vdigit', key = 'bgmap',
-                            subkey = 'value', internal = True) == '':
-            # no background map -> copy from current vector map layer
-            nselected = digitClass.driver.SelectLinesByBox(pos1, pos2,
-                                                           digitClass.GetSelectType())
-
-            if nselected > 0:
-                # highlight selected features
-                self.UpdateMap(render = False)
-            else:
-                self.UpdateMap(render = False, renderVector = False)
-        else:
-            # copy features from background map
-            self.copyIds += digitClass.SelectLinesFromBackgroundMap(pos1, pos2)
-            if len(self.copyIds) > 0:
-                color = UserSettings.Get(group = 'vdigit', key = 'symbol',
-                                         subkey = ['highlight', 'color'])
-                colorStr = str(color[0]) + ":" + \
-                    str(color[1]) + ":" + \
-                    str(color[2])
-                dVectTmp = ['d.vect',
-                            'map=%s' % UserSettings.Get(group = 'vdigit', key = 'bgmap',
-                                                        subkey = 'value', internal = True),
-                            'cats=%s' % utils.ListOfCatsToRange(self.copyIds),
-                            '-i',
-                            'color=%s' % colorStr,
-                            'fcolor=%s' % colorStr,
-                            'type=point,line,boundary,centroid',
-                            'width=2']
-                        
-                if not self.layerTmp:
-                    self.layerTmp = self.Map.AddLayer(type = 'vector',
-                                                      name = globalvar.QUERYLAYER,
-                                                      command = dVectTmp)
-                else:
-                    self.layerTmp.SetCmd(dVectTmp)
-                
-                self.UpdateMap(render = True, renderVector = False)
-            else:
-                self.UpdateMap(render = False, renderVector = False)
-            
-            self.redrawAll = None
-            
-    def OnLeftUpVDigitBulkLine(self, event):
-        """!
-        Left mouse button up - vector digitizer z-bulk line action
-        """
-        digitToolbar = self.parent.toolbars['vdigit']
-        digitClass   = self.parent.digit
-        
-        # select lines to be labeled
-        pos1 = self.polycoords[0]
-        pos2 = self.polycoords[1]
-        nselected = digitClass.driver.SelectLinesByBox(pos1, pos2,
-                                                       digitClass.GetSelectType())
-
-        if nselected > 0:
-            # highlight selected features
-            self.UpdateMap(render = False)
-            self.DrawLines(pdc = self.pdcTmp) # redraw temp line
-        else:
-            self.UpdateMap(render = False, renderVector = False)
-
-    def OnLeftUpVDigitConnectLine(self, event):
-        """!
-        Left mouse button up - vector digitizer connect line action
-        """
-        digitToolbar = self.parent.toolbars['vdigit']
-        digitClass   = self.parent.digit
-        
-        if len(digitClass.driver.GetSelected()) > 0:
-            self.UpdateMap(render = False)
-        
     def OnLeftUp(self, event):
         """!Left mouse button released
         """
@@ -1961,26 +1185,26 @@
 
             # redraw map
             self.UpdateMap(render = True)
-
+            
             # update statusbar
             self.parent.StatusbarUpdate()
-
+            
         elif self.mouse["use"] == "query":
             # querying
             self.parent.QueryMap(self.mouse['begin'][0],self.mouse['begin'][1])
-
+        
         elif self.mouse["use"] == "queryVector":
             # editable mode for vector map layers
             self.parent.QueryVector(self.mouse['begin'][0], self.mouse['begin'][1])
-
+            
             # clear temp canvas
             self.UpdateMap(render = False, renderVector = False)
-            
+        
         elif self.mouse["use"] in ["measure", "profile"]:
             # measure or profile
             if self.mouse["use"] == "measure":
                 self.parent.MeasureDist(self.mouse['begin'], self.mouse['end'])
-
+            
             self.polycoords.append(self.Pixel2Cell(self.mouse['end']))
             self.ClearLines(pdc = self.pdcTmp)
             self.DrawLines(pdc = self.pdcTmp)
@@ -1994,10 +1218,10 @@
                     coordtype = 'source'
                 else:
                     coordtype = 'target'
-
+                
                 self.parent.GetLayerManager().gcpmanagement.SetGCPData(coordtype, coord, self, confirm = True)
                 self.UpdateMap(render = False, renderVector = False)
-
+        
         elif self.mouse["use"] == "pointer" and \
                 self.parent.GetLayerManager().georectifying:
             # -> georectifying
@@ -2006,62 +1230,21 @@
                 coordtype = 'gcpcoord'
             else:
                 coordtype = 'mapcoord'
-
+            
             self.parent.GetLayerManager().georectifying.SetGCPData(coordtype, coord, self)
             self.UpdateMap(render = False, renderVector = False)
-
-        elif self.mouse["use"] == "pointer" and self.parent.toolbars['vdigit']:
-            # digitization tool active
-            digitToolbar = self.parent.toolbars['vdigit']
-            digitClass   = self.parent.digit
             
-            if hasattr(self, "vdigitMove"):
-                if len(digitClass.driver.GetSelected()) == 0:
-                    self.vdigitMove['begin'] = self.Pixel2Cell(self.mouse['begin']) # left down
-                
-                # eliminate initial mouse moving efect
-                self.mouse['begin'] = self.mouse['end'] 
-
-            if digitToolbar.GetAction() in ("deleteLine",
-                                            "moveLine",
-                                            "moveVertex",
-                                            "copyCats",
-                                            "copyAttrs",
-                                            "editLine",
-                                            "flipLine",
-                                            "mergeLine",
-                                            "snapLine",
-                                            "queryLine",
-                                            "breakLine",
-                                            "typeConv",
-                                            "connectLine"):
-                self.OnLeftUpVDigitVarious(event)
-
-            elif digitToolbar.GetAction() in ("splitLine",
-                                              "addVertex",
-                                              "removeVertex"):
-                self.OnLeftUpVDigitModifyLine(event)
-
-            elif digitToolbar.GetAction() == "copyLine":
-                self.OnLeftUpVDigitCopyLine(event)
+        elif self.mouse["use"] == "pointer" and \
+                hasattr(self, "digit"):
+            self._onLeftUp(event)
             
-            elif digitToolbar.GetAction() == "zbulkLine" and \
-                    len(self.polycoords) == 2:
-                self.OnLeftUpVDigitBulkLine(event)
-            
-            elif digitToolbar.GetAction() == "connectLine":
-                self.OnLeftUpConnectLine(event)
-            
-            if len(digitClass.driver.GetSelected()) > 0:
-                self.redrawAll = None
-            
         elif (self.mouse['use'] == 'pointer' and 
                 self.dragid >= 0):
             # end drag of overlay decoration
             
-            if self.dragid < 99 and self.overlays.has_key(self.dragid):
+            if self.dragid < 99 and self.dragid in self.overlays:
                 self.overlays[self.dragid]['coords'] = self.pdc.GetIdBounds(self.dragid)
-            elif self.dragid > 100 and self.textdict.has_key(self.dragid):
+            elif self.dragid > 100 and self.dragid in self.textdict:
                 self.textdict[self.dragid]['coords'] = self.pdc.GetIdBounds(self.dragid)
             else:
                 pass
@@ -2069,12 +1252,11 @@
             self.currtxtid = None
         
     def OnButtonDClick(self, event):
-        """!
-        Mouse button double click
+        """!Mouse button double click
         """
         Debug.msg (5, "BufferedWindow.OnButtonDClick(): use=%s" % \
                    self.mouse["use"])
-
+        
         if self.mouse["use"] == "measure":
             # measure
             self.ClearLines(pdc=self.pdcTmp)
@@ -2084,17 +1266,11 @@
             self.mouse['end'] = [0, 0]
             self.Refresh()
             self.SetCursor(self.parent.cursors["default"])
-
-        elif self.mouse["use"] == "profile":
-            pass
-
-        elif self.mouse['use'] == 'pointer' and \
-                self.parent.toolbars['vdigit']:
-            # vector digitizer
-            pass
-
-        else:
-            # select overlay decoration options dialog
+        
+        elif self.mouse["use"] != "profile" or \
+                (self.mouse['use'] != 'pointer' and \
+                     hasattr(self, "digit")):
+               # select overlay decoration options dialog
             clickposition = event.GetPositionTuple()[:]
             idlist  = self.pdc.FindObjects(clickposition[0], clickposition[1], self.hitradius)
             if idlist == []:
@@ -2111,304 +1287,46 @@
                 self.parent.OnAddLegend(None)
         
     def OnRightDown(self, event):
-        """!
-        Right mouse button pressed
+        """!Right mouse button pressed
         """
         Debug.msg (5, "BufferedWindow.OnRightDown(): use=%s" % \
                    self.mouse["use"])
-                   
-        digitToolbar = self.parent.toolbars['vdigit']
-        if digitToolbar:
-            digitClass = self.parent.digit
-            # digitization tool (confirm action)
-            if digitToolbar.GetAction() in ("moveLine",
-                                            "moveVertex") and \
-                    hasattr(self, "vdigitMove"):
-
-                pFrom = self.vdigitMove['begin']
-                pTo = self.Pixel2Cell(event.GetPositionTuple())
-                
-                move = (pTo[0] - pFrom[0],
-                        pTo[1] - pFrom[1])
-                
-                if digitToolbar.GetAction() == "moveLine":
-                    # move line
-                    if digitClass.MoveSelectedLines(move) < 0:
-                        return
-                elif digitToolbar.GetAction() == "moveVertex":
-                    # move vertex
-                    fid = digitClass.MoveSelectedVertex(pFrom, move)
-                    if fid < 0:
-                        return
-
-                    self.__geomAttrbUpdate([fid,])
-                
-                del self.vdigitMove
-                
+        
+        if hasattr(self, "digit"):
+            self._onRightDown(event)
+        
         event.Skip()
-
+        
     def OnRightUp(self, event):
-        """!
-        Right mouse button released
+        """!Right mouse button released
         """
         Debug.msg (5, "BufferedWindow.OnRightUp(): use=%s" % \
                    self.mouse["use"])
-
-        digitToolbar = self.parent.toolbars['vdigit']
-        if digitToolbar:
-            digitClass = self.parent.digit
-            # digitization tool (confirm action)
-            if digitToolbar.GetAction() == "addLine" and \
-                    digitToolbar.GetAction('type') in ["line", "boundary"]:
-                # -> add new line / boundary
-                try:
-                    map = digitToolbar.GetLayer().GetName()
-                except:
-                    map = None
-                    wx.MessageBox(parent = self,
-                                  message = _("No vector map selected for editing."),
-                                  caption = _("Error"), style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
-                    
-                if map:
-                    # mapcoords = []
-                    # xy -> EN
-                    # for coord in self.polycoords:
-                    #    mapcoords.append(self.Pixel2Cell(coord))
-                    if digitToolbar.GetAction('type') == 'line':
-                        line = True
-                    else:
-                        line = False
-
-                    if len(self.polycoords) < 2: # ignore 'one-point' lines
-                        return
-                    
-                    fid = digitClass.AddLine(map, line, self.polycoords)
-                    if fid < 0:
-                        return
-                    
-                    position = self.Cell2Pixel(self.polycoords[-1])
-                    self.polycoords = []
-                    self.UpdateMap(render = False)
-                    self.redrawAll = True
-                    self.Refresh()
-                    
-                    # add new record into atribute table
-                    if UserSettings.Get(group = 'vdigit', key = "addRecord", subkey = 'enabled') and \
-                            (line is True or \
-                                 (not line and fid > 0)):
-                        posWindow = self.ClientToScreen((position[0] + self.dialogOffset,
-                                                         position[1] + self.dialogOffset))
-
-                        # select attributes based on layer and category
-                        cats = { fid : {
-                                UserSettings.Get(group = 'vdigit', key = "layer", subkey = 'value') :
-                                    (UserSettings.Get(group = 'vdigit', key = "category", subkey = 'value'), )
-                                }}
-                        
-                        addRecordDlg = dbm_dialogs.DisplayAttributesDialog(parent = self, map = map,
-                                                                           cats = cats,
-                                                                           pos = posWindow,
-                                                                           action = "add")
-
-                        self.__geomAttrb(fid, addRecordDlg, 'length', digitClass,
-                                         digitToolbar.GetLayer())
-                        # auto-placing centroid
-                        self.__geomAttrb(fid, addRecordDlg, 'area', digitClass,
-                                         digitToolbar.GetLayer())
-                        self.__geomAttrb(fid, addRecordDlg, 'perimeter', digitClass,
-                                         digitToolbar.GetLayer())
-
-                        if addRecordDlg.mapDBInfo and \
-                               addRecordDlg.ShowModal() == wx.ID_OK:
-                            sqlfile = tempfile.NamedTemporaryFile(mode = "w")
-                            for sql in addRecordDlg.GetSQLString():
-                                sqlfile.file.write(sql + ";\n")
-                            sqlfile.file.flush()
-                            gcmd.RunCommand('db.execute',
-                                            parent = True,
-                                            quiet = True,
-                                            input = sqlfile.name)
-                        
-                        if addRecordDlg.mapDBInfo:
-                            self.__updateATM()
-            
-            elif digitToolbar.GetAction() == "deleteLine":
-                # -> delete selected vector features
-                if digitClass.DeleteSelectedLines() < 0:
-                    return
-                self.__updateATM()
-            elif digitToolbar.GetAction() == "splitLine":
-                # split line
-                if digitClass.SplitLine(self.Pixel2Cell(self.mouse['begin'])) < 0:
-                    return
-            elif digitToolbar.GetAction() == "addVertex":
-                # add vertex
-                fid = digitClass.AddVertex(self.Pixel2Cell(self.mouse['begin']))
-                if fid < 0:
-                    return
-            elif digitToolbar.GetAction() == "removeVertex":
-                # remove vertex
-                fid = digitClass.RemoveVertex(self.Pixel2Cell(self.mouse['begin']))
-                if fid < 0:
-                    return
-                self.__geomAttrbUpdate([fid,])
-            elif digitToolbar.GetAction() in ("copyCats", "copyAttrs"):
-                try:
-                    if digitToolbar.GetAction() == 'copyCats':
-                        if digitClass.CopyCats(self.copyCatsList,
-                                               self.copyCatsIds, copyAttrb = False) < 0:
-                            return
-                    else:
-                        if digitClass.CopyCats(self.copyCatsList,
-                                               self.copyCatsIds, copyAttrb = True) < 0:
-                            return
-                    
-                    del self.copyCatsList
-                    del self.copyCatsIds
-                except AttributeError:
-                    pass
-                
-                self.__updateATM()
-                
-            elif digitToolbar.GetAction() == "editLine" and \
-                    hasattr(self, "vdigitMove"):
-                line = digitClass.driver.GetSelected()
-                if digitClass.EditLine(line, self.polycoords) < 0:
-                    return
-                
-                del self.vdigitMove
-                
-            elif digitToolbar.GetAction() == "flipLine":
-                if digitClass.FlipLine() < 0:
-                    return
-            elif digitToolbar.GetAction() == "mergeLine":
-                if digitClass.MergeLine() < 0:
-                    return
-            elif digitToolbar.GetAction() == "breakLine":
-                if digitClass.BreakLine() < 0:
-                    return
-            elif digitToolbar.GetAction() == "snapLine":
-                if digitClass.SnapLine() < 0:
-                    return
-            elif digitToolbar.GetAction() == "connectLine":
-                if len(digitClass.driver.GetSelected()) > 1:
-                    if digitClass.ConnectLine() < 0:
-                        return
-            elif digitToolbar.GetAction() == "copyLine":
-                if digitClass.CopyLine(self.copyIds) < 0:
-                    return
-                del self.copyIds
-                if self.layerTmp:
-                    self.Map.DeleteLayer(self.layerTmp)
-                    self.UpdateMap(render = True, renderVector = False)
-                del self.layerTmp
-
-            elif digitToolbar.GetAction() == "zbulkLine" and len(self.polycoords) == 2:
-                pos1 = self.polycoords[0]
-                pos2 = self.polycoords[1]
-
-                selected = digitClass.driver.GetSelected()
-                dlg = VDigitZBulkDialog(parent = self, title = _("Z bulk-labeling dialog"),
-                                        nselected = len(selected))
-                if dlg.ShowModal() == wx.ID_OK:
-                    if digitClass.ZBulkLines(pos1, pos2, dlg.value.GetValue(),
-                                             dlg.step.GetValue()) < 0:
-                        return
-                self.UpdateMap(render = False, renderVector = True)
-            elif digitToolbar.GetAction() == "typeConv":
-                # -> feature type conversion
-                # - point <-> centroid
-                # - line <-> boundary
-                if digitClass.TypeConvForSelectedLines() < 0:
-                    return
-
-            if digitToolbar.GetAction() != "addLine":
-                # unselect and re-render
-                digitClass.driver.SetSelected([])
-                self.polycoords = []
-                self.UpdateMap(render = False)
-
-            self.redrawAll = True
-            self.Refresh()
-            
+        
+        if hasattr(self, "digit"):
+            self._onRightUp(event)
+        
+        self.redrawAll = True
+        self.Refresh()
+        
         event.Skip()
-
+        
     def OnMiddleDown(self, event):
-        """!
-        Middle mouse button pressed
+        """!Middle mouse button pressed
         """
+        if not event:
+            return
+        
         self.mouse['begin'] = event.GetPositionTuple()[:]
         
-        digitToolbar = self.parent.toolbars['vdigit']
-        # digitization tool
-        if self.mouse["use"] == "pointer" and digitToolbar:
-            digitClass = self.parent.digit
-            if (digitToolbar.GetAction() == "addLine" and \
-                    digitToolbar.GetAction('type') in ["line", "boundary"]) or \
-                    digitToolbar.GetAction() == "editLine":
-                # add line or boundary -> remove last point from the line
-                try:
-                    removed = self.polycoords.pop()
-                    Debug.msg(4, "BufferedWindow.OnMiddleDown(): polycoords_poped=%s" % \
-                                  [removed,])
-
-                    self.mouse['begin'] = self.Cell2Pixel(self.polycoords[-1])
-                except:
-                    pass
-
-                if digitToolbar.GetAction() == "editLine":
-                    # remove last vertex & line
-                    if len(self.vdigitMove['id']) > 1:
-                        self.vdigitMove['id'].pop()
-
-                self.UpdateMap(render = False, renderVector = False)
-
-            elif digitToolbar.GetAction() in ["deleteLine", "moveLine", "splitLine",
-                                              "addVertex", "removeVertex", "moveVertex",
-                                              "copyCats", "flipLine", "mergeLine",
-                                              "snapLine", "connectLine", "copyLine",
-                                              "queryLine", "breakLine", "typeConv"]:
-                # varios tools -> unselected selected features
-                digitClass.driver.SetSelected([])
-                if digitToolbar.GetAction() in ["moveLine", "moveVertex", "editLine"] and \
-                        hasattr(self, "vdigitMove"):
-
-                    del self.vdigitMove
-                    
-                elif digitToolbar.GetAction() == "copyCats":
-                    try:
-                        del self.copyCatsList
-                        del self.copyCatsIds
-                    except AttributeError:
-                        pass
-                
-                elif digitToolbar.GetAction() == "copyLine":
-                    del self.copyIds
-                    if self.layerTmp:
-                        self.Map.DeleteLayer(self.layerTmp)
-                        self.UpdateMap(render = True, renderVector = False)
-                    del self.layerTmp
-
-                self.polycoords = []
-                self.UpdateMap(render = False) # render vector
-
-            elif digitToolbar.GetAction() == "zbulkLine":
-                # reset polyline
-                self.polycoords = []
-                digitClass.driver.SetSelected([])
-                self.UpdateMap(render = False)
-            
-            self.redrawAll = True
-
     def OnMiddleUp(self, event):
-        """!
-        Middle mouse button released
+        """!Middle mouse button released
         """
         self.mouse['end'] = event.GetPositionTuple()[:]
         
         # set region in zoom or pan
         begin = self.mouse['begin']
-        end = self.mouse['end']
+        end   = self.mouse['end']
         
         self.Zoom(begin, end, 0) # no zoom
         
@@ -2419,8 +1337,7 @@
         self.parent.StatusbarUpdate()
         
     def OnMouseEnter(self, event):
-        """!
-        Mouse entered window and no mouse buttons were pressed
+        """!Mouse entered window and no mouse buttons were pressed
         """
         if self.parent.GetLayerManager().gcpmanagement:
             if self.parent.toolbars['gcpdisp']:
@@ -2432,74 +1349,16 @@
                     self.SetFocus()
         else:
             event.Skip()
-
+        
     def OnMouseMoving(self, event):
-        """!
-        Motion event and no mouse buttons were pressed
+        """!Motion event and no mouse buttons were pressed
         """
-        digitToolbar = self.parent.toolbars['vdigit']
-        if self.mouse["use"] == "pointer" and digitToolbar:
-            digitClass = self.parent.digit
-            self.mouse['end'] = event.GetPositionTuple()[:]
-            Debug.msg (5, "BufferedWindow.OnMouseMoving(): coords=%f,%f" % \
-                           (self.mouse['end'][0], self.mouse['end'][1]))
-            if digitToolbar.GetAction() == "addLine" and digitToolbar.GetAction('type') in ["line", "boundary"]:
-                if len(self.polycoords) > 0:
-                    self.MouseDraw(pdc = self.pdcTmp, begin = self.Cell2Pixel(self.polycoords[-1]))
-            elif digitToolbar.GetAction() in ["moveLine", "moveVertex", "editLine"] \
-                    and hasattr(self, "vdigitMove"):
-                dx = self.mouse['end'][0] - self.mouse['begin'][0]
-                dy = self.mouse['end'][1] - self.mouse['begin'][1]
-                
-                if len(self.vdigitMove['id']) > 0:
-                    # draw lines on new position
-                    if digitToolbar.GetAction() == "moveLine":
-                        # move line
-                        for id in self.vdigitMove['id']:
-                            self.pdcTmp.TranslateId(id, dx, dy)
-                    elif digitToolbar.GetAction() in ["moveVertex", "editLine"]:
-                        # move vertex ->
-                        # (vertex, left vertex, left line,
-                        # right vertex, right line)
-
-                        # do not draw static lines
-                        if digitToolbar.GetAction() == "moveVertex":
-                            self.polycoords = []
-                            ### self.pdcTmp.TranslateId(self.vdigitMove['id'][0], dx, dy)
-                            self.pdcTmp.RemoveId(self.vdigitMove['id'][0])
-                            if self.vdigitMove['id'][1] > 0: # previous vertex
-                                x, y = self.Pixel2Cell(self.pdcTmp.GetIdBounds(self.vdigitMove['id'][1])[0:2])
-                                self.pdcTmp.RemoveId(self.vdigitMove['id'][1]+1)
-                                self.polycoords.append((x, y))
-                            ### x, y = self.Pixel2Cell(self.pdcTmp.GetIdBounds(self.vdigitMove['id'][0])[0:2])
-                            self.polycoords.append(self.Pixel2Cell(self.mouse['end']))
-                            if self.vdigitMove['id'][2] > 0: # next vertex
-                                x, y = self.Pixel2Cell(self.pdcTmp.GetIdBounds(self.vdigitMove['id'][2])[0:2])
-                                self.pdcTmp.RemoveId(self.vdigitMove['id'][2]-1)
-                                self.polycoords.append((x, y))
-                            
-                            self.ClearLines(pdc = self.pdcTmp)
-                            self.DrawLines(pdc = self.pdcTmp)
-
-                        else: # edit line
-                            try:
-                                if self.vdigitMove['id'][-1] > 0: # previous vertex
-                                    self.MouseDraw(pdc = self.pdcTmp,
-                                                   begin = self.Cell2Pixel(self.polycoords[-1]))
-                            except: # no line
-                                self.vdigitMove['id'] = []
-                                self.polycoords = []
-
-                self.Refresh() # TODO: use RefreshRect()
-                self.mouse['begin'] = self.mouse['end']
-
-            elif digitToolbar.GetAction() == "zbulkLine":
-                if len(self.polycoords) == 1:
-                    # draw mouse moving
-                    self.MouseDraw(self.pdcTmp)
-
+        if self.mouse["use"] == "pointer" and \
+                hasattr(self, "digit"):
+            self._onMouseMoving(event)
+        
         event.Skip()
-
+        
     def ClearLines(self, pdc = None):
         """!Clears temporary drawn lines from PseudoDC
         """
@@ -2510,23 +1369,21 @@
             pdc.RemoveId(self.lineid)
         except:
             pass
-
+        
         try:
             pdc.ClearId(self.plineid)
             pdc.RemoveId(self.plineid)
         except:
             pass
-
+        
         Debug.msg(4, "BufferedWindow.ClearLines(): lineid=%s, plineid=%s" %
                   (self.lineid, self.plineid))
-
-        ### self.Refresh()
-
+        
         return True
 
     def Pixel2Cell(self, (x, y)):
         """!Convert image coordinates to real word coordinates
-
+        
         @param x, y image coordinates
         
         @return easting, northing
@@ -2550,7 +1407,7 @@
         north = n - y * res
         
         return (east, north)
-
+    
     def Cell2Pixel(self, (east, north)):
         """!Convert real word coordinates to image coordinates
         """
@@ -2572,7 +1429,7 @@
         y = (n - north) / res
         
         return (x, y)
-
+    
     def Zoom(self, begin, end, zoomtype):
         """!
         Calculates new region while (un)zoom/pan-ing
@@ -2580,21 +1437,20 @@
         x1, y1 = begin
         x2, y2 = end
         newreg = {}
-
+        
         # threshold - too small squares do not make sense
         # can only zoom to windows of > 5x5 screen pixels
         if abs(x2-x1) > 5 and abs(y2-y1) > 5 and zoomtype != 0:
-
             if x1 > x2:
                 x1, x2 = x2, x1
             if y1 > y2:
                 y1, y2 = y2, y1
-
+            
             # zoom in
             if zoomtype > 0:
                 newreg['w'], newreg['n'] = self.Pixel2Cell((x1, y1))
                 newreg['e'], newreg['s'] = self.Pixel2Cell((x2, y2))
-
+            
             # zoom out
             elif zoomtype < 0:
                 newreg['w'], newreg['n'] = self.Pixel2Cell((-x1 * 2, -y1 * 2))
@@ -2612,7 +1468,7 @@
             newreg['w'], newreg['n'] = self.Pixel2Cell((dx, dy))
             newreg['e'], newreg['s'] = self.Pixel2Cell((self.Map.width  + dx,
                                                         self.Map.height + dy))
-
+        
         # if new region has been calculated, set the values
         if newreg != {}:
             # LL locations
@@ -2625,33 +1481,23 @@
             ce = newreg['w'] + (newreg['e'] - newreg['w']) / 2
             cn = newreg['s'] + (newreg['n'] - newreg['s']) / 2
             
-            if hasattr(self, "vdigitMove"):
-                # xo = self.Cell2Pixel((self.Map.region['center_easting'], self.Map.region['center_northing']))
-                # xn = self.Cell2Pixel(ce, cn))
-                tmp = self.Pixel2Cell(self.mouse['end'])
-            
             # calculate new center point and display resolution
             self.Map.region['center_easting'] = ce
             self.Map.region['center_northing'] = cn
             self.Map.region["ewres"] = (newreg['e'] - newreg['w']) / self.Map.width
             self.Map.region["nsres"] = (newreg['n'] - newreg['s']) / self.Map.height
             self.Map.AlignExtentFromDisplay()
-
-            if hasattr(self, "vdigitMove"):
-                tmp1 = self.mouse['end']
-                tmp2 = self.Cell2Pixel(self.vdigitMove['begin'])
-                dx = tmp1[0] - tmp2[0]
-                dy = tmp1[1] - tmp2[1]
-                self.vdigitMove['beginDiff'] = (dx, dy)
-                for id in self.vdigitMove['id']:
-                    self.pdcTmp.RemoveId(id)
             
+            if hasattr(self, "digit") and \
+                    hasattr(self, "moveInfo"):
+                self._zoom(event)
+            
             self.ZoomHistory(self.Map.region['n'], self.Map.region['s'],
                              self.Map.region['e'], self.Map.region['w'])
-
+        
         if self.redrawAll is False:
             self.redrawAll = True
-
+        
     def ZoomBack(self):
         """!Zoom to previous extents in zoomhistory list
         """
@@ -2683,8 +1529,7 @@
         self.parent.StatusbarUpdate()
 
     def ZoomHistory(self, n, s, e, w):
-        """!
-        Manages a list of last 10 zoom extents
+        """!Manages a list of last 10 zoom extents
 
         @param n,s,e,w north, south, east, west
 
@@ -2723,8 +1568,7 @@
     def ResetZoomHistory(self):
         """!Reset zoom history"""
         self.zoomhistory = list()
-        
-        
+                
     def ZoomToMap(self, layers = None, ignoreNulls = False, render = True):
         """!Set display extents to match selected raster
         or vector map(s).
@@ -2749,9 +1593,9 @@
             if l.type == 'raster':
                 rast.append(l.GetName())
             elif l.type == 'vector':
-                digitToolbar = self.parent.toolbars['vdigit']
-                if digitToolbar and digitToolbar.GetLayer() == l:
-                    w, s, b, e, n, t = self.parent.digit.driver.GetMapBoundingBox()
+                if hasattr(self, "digit") and \
+                        self.toolbar.GetLayer() == l:
+                    w, s, b, e, n, t = self.display.GetMapBoundingBox()
                     self.Map.GetRegion(n = n, s = s, w = w, e = e,
                                        update = True)
                     updated = True
@@ -2771,7 +1615,7 @@
         
         if render:
             self.UpdateMap()
-
+        
         self.parent.StatusbarUpdate()
         
     def ZoomToWind(self):
@@ -2779,13 +1623,12 @@
         settings (set with g.region)
         """
         self.Map.region = self.Map.GetRegion()
-        ### self.Map.SetRegion(windres=True)
-
+        
         self.ZoomHistory(self.Map.region['n'], self.Map.region['s'],
                          self.Map.region['e'], self.Map.region['w'])
-
+        
         self.UpdateMap()
-
+        
         self.parent.StatusbarUpdate()
 
     def ZoomToDefault(self):
@@ -2796,9 +1639,9 @@
 
         self.ZoomHistory(self.Map.region['n'], self.Map.region['s'],
                          self.Map.region['e'], self.Map.region['w'])
-
+        
         self.UpdateMap()
-
+        
         self.parent.StatusbarUpdate()
         
     def DisplayToWind(self):
@@ -2808,7 +1651,7 @@
         tmpreg = os.getenv("GRASS_REGION")
         if tmpreg:
             del os.environ["GRASS_REGION"]
-
+        
         # We ONLY want to set extents here. Don't mess with resolution. Leave that
         # for user to set explicitly with g.region
         new = self.Map.AlignResolution()
@@ -2824,7 +1667,7 @@
         
         if tmpreg:
             os.environ["GRASS_REGION"] = tmpreg
-
+        
     def ZoomToSaved(self):
         """!Set display geometry to match extents in
         saved region file
@@ -2866,7 +1709,7 @@
         if dlg.ShowModal() == wx.ID_CANCEL or not dlg.wind:
             dlg.Destroy()
             return
-
+        
         # test to see if it already exists and ask permission to overwrite
         if grass.find_file(name = dlg.wind, element = 'windows')['name']:
             overwrite = wx.MessageBox(parent = self,
@@ -2879,14 +1722,14 @@
             self.SaveRegion(dlg.wind)
         
         dlg.Destroy()
-
+        
     def SaveRegion(self, wind):
         """!Save region settings
-
+        
         @param wind region name
         """
         new = self.Map.GetCurrentRegion()
-
+        
         tmpreg = os.getenv("GRASS_REGION")
         if tmpreg:
             del os.environ["GRASS_REGION"]
@@ -2905,14 +1748,12 @@
         
         if tmpreg:
             os.environ["GRASS_REGION"] = tmpreg
-
+        
     def Distance(self, beginpt, endpt, screen = True):
         """!Calculete distance
-
-        LL-locations not supported
-
-        @todo Use m.distance
-
+        
+        Ctypes required for LL-locations
+        
         @param beginpt first point
         @param endpt second point
         @param screen True for screen coordinates otherwise EN
@@ -2927,4 +1768,9 @@
         dEast  = (e2 - e1)
         dNorth = (n2 - n1)
         
-        return (math.sqrt(math.pow((dEast), 2) + math.pow((dNorth), 2)), (dEast, dNorth))
+        if self.parent.Map.projinfo['proj'] == 'll' and haveCtypes:
+            dist = gislib.G_distance(e1, n1, e2, n2)
+        else:
+            dist = math.sqrt(math.pow((dEast), 2) + math.pow((dNorth), 2))
+        
+        return (dist, (dEast, dNorth))

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/menu.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/menu.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/menu.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -13,11 +13,10 @@
 @author Martin Landa <landa.martin gmail.com>
 """
 
-import shlex
-
 import wx
 
 import globalvar
+import utils
 
 class Menu(wx.MenuBar):
     def __init__(self, parent, data):
@@ -69,9 +68,9 @@
         
         if gcmd: 
             try: 
-                cmd = shlex.split(str(gcmd)) 
+                cmd = utils.split(str(gcmd)) 
             except UnicodeError: 
-                cmd = shlex.split(utils.EncodeString((gcmd))) 
+                cmd = utils.split(utils.EncodeString((gcmd))) 
             if cmd and cmd[0] not in globalvar.grassCmd['all']: 
                 menuItem.Enable(False)
         

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/menudata.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/menudata.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/menudata.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -19,7 +19,7 @@
  - commands
  - dump
 
-(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.
 

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/menuform.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/menuform.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/menuform.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -13,25 +13,20 @@
  - GUI
  - FloatValidator
 
- Copyright (C) 2000-2010 by the GRASS Development Team
+This program is just a coarse approach to automatically build a GUI
+from a xml-based GRASS user interface description.
 
- This program is free software under the GPL (>=v2) Read the file
- COPYING coming with GRASS for details.
+You need to have Python 2.4, wxPython 2.8 and python-xml.
 
- This program is just a coarse approach to automatically build a GUI
- from a xml-based GRASS user interface description.
+The XML stream is read from executing the command given in the
+command line, thus you may call it for instance this way:
 
- You need to have Python 2.4, wxPython 2.8 and python-xml.
+python <this file.py> r.basins.fill
 
- The XML stream is read from executing the command given in the
- command line, thus you may call it for instance this way:
+Or you set an alias or wrap the call up in a nice shell script, GUI
+environment ... please contribute your idea.
 
- python <this file.py> r.basins.fill
-
- Or you set an alias or wrap the call up in a nice shell script, GUI
- environment ... please contribute your idea.
-
-Copyright(C) 2000-2010 by the GRASS Development Team
+Copyright(C) 2000-2011 by the GRASS Development Team
 This program is free software under the GPL(>=v2) Read the file
 COPYING coming with GRASS for details.
 
@@ -56,7 +51,6 @@
 import types
 from threading import Thread
 import Queue
-import shlex
 import tempfile
 
 ### i18N
@@ -96,8 +90,6 @@
     wxbase = os.path.join(globalvar.ETCWXDIR)
 
 sys.path.append(wxbase)
-imagepath = os.path.join(wxbase, "images")
-sys.path.append(imagepath)
 
 from grass.script import core as grass
 
@@ -135,8 +127,15 @@
 for (s,r) in str2rgb.items():
     rgb2str[ r ] = s
 
+"""!Hide some options in the GUI"""
+_blackList = {
+    'd.legend' : { 'flags' : ['m'],
+                   'params' : [] }
+}
+_ignoreBlackList = True
+
 def color_resolve(color):
-    if len(color)>0 and color[0] in "0123456789":
+    if len(color) > 0 and color[0] in "0123456789":
         rgb = tuple(map(int, color.split(':')))
         label = color
     else:
@@ -194,8 +193,7 @@
                 return
         
         p = self.task.get_param(self.eventId, element = 'wxId', raiseError = False)
-        if not p or \
-                not p.has_key('wxId-bind'):
+        if not p or 'wxId-bind' not in p:
             return
         
         # get widget prompt
@@ -225,7 +223,7 @@
             name = win.GetName()
             
             if name == 'LayerSelect':
-                if cparams.has_key(map) and not cparams[map]['layers']:
+                if map in cparams and not cparams[map]['layers']:
                     win.InsertLayers(vector = map)
                     cparams[map]['layers'] = win.GetItems()
             
@@ -252,7 +250,7 @@
                     layer = 1
                 
                 if map:
-                    if cparams.has_key(map):
+                    if map in cparams:
                         if not cparams[map]['dbInfo']:
                             cparams[map]['dbInfo'] = gselect.VectorDBInfo(map)
                         self.data[win.InsertColumns] = { 'vector' : map, 'layer' : layer,
@@ -335,10 +333,11 @@
             self.request = callable(*args, **kwds)
 
             self.resultQ.put((requestId, self.request.run()))
-                        
-            event = wxUpdateDialog(data = self.request.data)
-            wx.PostEvent(self.parent, event)
-
+           
+            if self.request:
+                event = wxUpdateDialog(data = self.request.data)
+                wx.PostEvent(self.parent, event)
+        
 class grassTask:
     """!This class holds the structures needed for both filling by the
     parser and use by the interface constructor.
@@ -593,8 +592,15 @@
                 required = True
             else:
                 required = False
+
+            if not _ignoreBlackList and \
+                    self.task.name in _blackList and \
+                    p.get('name') in _blackList[self.task.name]['params']:
+                hidden = True
+            else:
+                hidden = False
             
-            self.task.params.append({
+            self.task.params.append( {
                 "name"           : p.get('name'),
                 "type"           : p.get('type'),
                 "required"       : required,
@@ -610,17 +616,29 @@
                 "values"         : values,
                 "values_desc"    : values_desc,
                 "value"          : '',
-                "key_desc"       : key_desc })
+                "key_desc"       : key_desc,
+                "hidden"         : hidden
+                })
             
     def __processFlags(self):
         """!Process flags description"""
+        global _ignoreBlackList
         for p in self.root.findall('flag'):
-            self.task.flags.append({
+            if not _ignoreBlackList and \
+                    self.task.name in _blackList and \
+                    p.get('name') in _blackList[self.task.name]['flags']:
+                hidden = True
+            else:
+                hidden = False
+            
+            self.task.flags.append( {
                     "name"              : p.get('name'),
                     "label"             : self._getNodeText(p, 'label'),
                     "description"       : self._getNodeText(p, 'description'),
                     "guisection"        : self._getNodeText(p, 'guisection'),
-                    "value"             : False })
+                    "value"             : False,
+                    "hidden"            : hidden
+                    } )
             
     def _getNodeText(self, node, tag, default = ''):
         """!Get node text"""
@@ -698,8 +716,8 @@
         
         # GRASS logo
         self.logo = wx.StaticBitmap(parent = self.panel,
-                                    bitmap = wx.Bitmap(name = os.path.join(imagepath,
-                                                                       'grass_form.png'),
+                                    bitmap = wx.Bitmap(name = os.path.join(globalvar.ETCIMGDIR,
+                                                                           'grass_form.png'),
                                                      type = wx.BITMAP_TYPE_PNG))
         topsizer.Add(item = self.logo, proportion = 0, border = 3,
                      flag = wx.ALL | wx.ALIGN_CENTER_VERTICAL)
@@ -904,7 +922,7 @@
                         display.GetRender().GetListOfLayers(l_type = 'raster') +
                         display.GetRender().GetListOfLayers(l_type = 'vector'))
         
-        task = GUI().ParseCommand(cmd, show = None)
+        task = GUI(show = None).ParseCommand(cmd)
         for p in task.get_options()['params']:
             if p.get('prompt', '') not in ('raster', 'vector'):
                 continue
@@ -1035,7 +1053,7 @@
         # Determine tab layout
         sections = []
         is_section = {}
-        not_hidden = [ p for p in self.task.params + self.task.flags if not p.get('hidden','no') ==  'yes' ]
+        not_hidden = [ p for p in self.task.params + self.task.flags if not p.get('hidden', False) ==  True ]
 
         self.label_id = [] # wrap titles on resize
 
@@ -1048,7 +1066,7 @@
             if task.get('guisection','') ==  '':
                 # Undefined guisections end up into Options
                 task['guisection'] = _('Optional')
-            if not is_section.has_key(task['guisection']):
+            if task['guisection'] not in is_section:
                 # We do it like this to keep the original order, except for Main which goes first
                 is_section[task['guisection']] = 1
                 sections.append(task['guisection'])
@@ -1108,7 +1126,7 @@
         # flags
         #
         text_style = wx.FONTWEIGHT_NORMAL
-        visible_flags = [ f for f in self.task.flags if not f.get('hidden', 'no') ==  'yes' ]
+        visible_flags = [ f for f in self.task.flags if not f.get('hidden', False) ==  True ]
         for f in visible_flags:
             which_sizer = tabsizer[ f['guisection'] ]
             which_panel = tab[ f['guisection'] ]
@@ -1141,7 +1159,7 @@
                                      label = _("Parameterized in model"))
                 parChk.SetName('ModelParam')
                 parChk.SetValue(f.get('parameterized', False))
-                if f.has_key('wxId'):
+                if 'wxId' in f:
                     f['wxId'].append(parChk.GetId())
                 else:
                     f['wxId'] = [ parChk.GetId() ]
@@ -1155,14 +1173,14 @@
                 if f['name'] ==  vq:
                     chk.SetValue(True)
                     f['value'] = True
-            elif f['name'] ==  'overwrite' and not f.has_key('value'):
+            elif f['name'] ==  'overwrite' and 'value' not in f:
                 chk.SetValue(UserSettings.Get(group = 'cmd', key = 'overwrite', subkey = 'enabled'))
                 f['value'] = UserSettings.Get(group = 'cmd', key = 'overwrite', subkey = 'enabled')
                 
         #
         # parameters
         #
-        visible_params = [ p for p in self.task.params if not p.get('hidden', 'no') ==  'yes' ]
+        visible_params = [ p for p in self.task.params if not p.get('hidden', False) ==  True ]
         
         try:
             first_param = visible_params[0]
@@ -1249,8 +1267,7 @@
                         chkbox = wx.CheckBox(parent = which_panel,
                                              label = text_beautify(label))
                         p[ 'wxId' ].append(chkbox.GetId())
-                        
-                        if isEnabled.has_key(val):
+                        if val in isEnabled:
                             chkbox.SetValue(True)
                         hSizer.Add(item = chkbox, proportion = 0,
                                     flag = wx.ADJUST_MINSIZE | wx.ALL, border = 1)
@@ -1282,7 +1299,7 @@
                             txt2.SetName("TextCtrl")
                             style = wx.EXPAND | wx.BOTTOM | wx.LEFT
                         
-                        value = self._GetValue(p)
+                        value = self._getValue(p)
                         # parameter previously set
                         if value:
                             if txt2.GetName() ==  "SpinCtrl":
@@ -1301,7 +1318,7 @@
                         cb = wx.ComboBox(parent = which_panel, id = wx.ID_ANY, value = p.get('default',''),
                                          size = globalvar.DIALOG_COMBOBOX_SIZE,
                                          choices = valuelist, style = wx.CB_DROPDOWN)
-                        value = self._GetValue(p)
+                        value = self._getValue(p)
                         if value:
                             cb.SetValue(value) # parameter previously set
                         which_sizer.Add( item=cb, proportion=0,
@@ -1322,7 +1339,7 @@
                         len(p.get('key_desc', [])) > 1:
                     txt3 = wx.TextCtrl(parent = which_panel, value = p.get('default',''))
                     
-                    value = self._GetValue(p)
+                    value = self._getValue(p)
                     if value:
                         # parameter previously set
                         txt3.SetValue(str(value))
@@ -1338,7 +1355,7 @@
                                            min = minValue, max = maxValue)
                         style = wx.BOTTOM | wx.LEFT | wx.RIGHT
                         
-                        value = self._GetValue(p)
+                        value = self._getValue(p)
                         if value:
                             txt3.SetValue(int(value)) # parameter previously set
                         
@@ -1348,7 +1365,7 @@
                                            validator = FloatValidator())
                         style = wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT
                         
-                        value = self._GetValue(p)
+                        value = self._getValue(p)
                         if value:
                             txt3.SetValue(str(value)) # parameter previously set
                     
@@ -1393,20 +1410,20 @@
                                                        isRaster = isRaster)
                         p['wxId'] = [ selection.GetId(), ]
                         selection.Bind(wx.EVT_COMBOBOX, self.OnSetValue)
-                        formatSelector = False
                         selection.Bind(wx.EVT_TEXT, self.OnUpdateSelection)
                     else:
                         selection = gselect.Select(parent = which_panel, id = wx.ID_ANY,
                                                    size = globalvar.DIALOG_GSELECT_SIZE,
                                                    type = p.get('element', ''),
                                                    multiple = multiple, mapsets = mapsets)
-                        formatSelector = True
+                        
                         # A select.Select is a combobox with two children: a textctl and a popupwindow;
                         # we target the textctl here
-                        p['wxId'] = [selection.GetChildren()[0].GetId(), ]
-                        selection.GetChildren()[0].Bind(wx.EVT_TEXT, self.OnSetValue)
+                        textWin = selection.GetTextCtrl()
+                        p['wxId'] = [ textWin.GetId(), ]
+                        textWin.Bind(wx.EVT_TEXT, self.OnSetValue)
                     
-                    value = self._GetValue(p)
+                    value = self._getValue(p)
                     if value:
                         selection.SetValue(value) # parameter previously set
 
@@ -1415,7 +1432,6 @@
                     
                     if p.get('prompt', '') in ('vector', 'group'):
                         selection.Bind(wx.EVT_TEXT, self.OnUpdateSelection)
-                
                 # subgroup
                 elif p.get('prompt', '') ==  'subgroup':
                     selection = gselect.SubGroupSelect(parent = which_panel)
@@ -1515,7 +1531,7 @@
                             win.Bind(wx.EVT_TEXT, self.OnUpdateSelection)
                             p['wxId'] = [ win.GetChildren()[1].GetId() ]
                             
-                    if not p.has_key('wxId'):
+                    if 'wxId' not in p:
                         try:
                             p['wxId'] = [ win.GetId(), ]
                         except AttributeError:
@@ -1567,7 +1583,7 @@
                                                       buttonText = _('Browse'),
                                                       startDirectory = os.getcwd(), fileMode = 0,
                                                       changeCallback = self.OnSetValue)
-                    value = self._GetValue(p)
+                    value = self._getValue(p)
                     if value:
                         fbb.SetValue(value) # parameter previously set
                     which_sizer.Add(item = fbb, proportion = 0,
@@ -1602,7 +1618,7 @@
                                      label = _("Parameterized in model"))
                 parChk.SetName('ModelParam')
                 parChk.SetValue(p.get('parameterized', False))
-                if p.has_key('wxId'):
+                if 'wxId' in p:
                     p['wxId'].append(parChk.GetId())
                 else:
                     p['wxId'] = [ parChk.GetId() ]
@@ -1625,8 +1641,9 @@
                     title_txt.SetToolTipString(tooltip)
 
             if p ==  first_param:
-                if p.has_key('wxId') and len(p['wxId']) > 0:
-                    self.FindWindowById(p['wxId'][0]).SetFocus()
+                if 'wxId' in p and len(p['wxId']) > 0:
+                    win = self.FindWindowById(p['wxId'][0])
+                    win.SetFocus()
         
         #
         # set widget relations for OnUpdateSelection
@@ -1734,7 +1751,7 @@
         
         self.Bind(EVT_DIALOG_UPDATE, self.OnUpdateDialog)
 
-    def _GetValue(self, p):
+    def _getValue(self, p):
         """!Get value or default value of given parameter
 
         @param p parameter directory
@@ -1857,7 +1874,7 @@
         # Keep the original order, so that some defaults may be recovered
         currentValueList = [] 
         for v in theParam['values']:
-            if currentValues.has_key(v):
+            if v in currentValues:
                 currentValueList.append(v)
 
         # Pack it back
@@ -1878,7 +1895,7 @@
 
         found = False
         for porf in self.task.params + self.task.flags:
-            if not porf.has_key('wxId'):
+            if 'wxId' not in porf:
                 continue
             if myId in porf['wxId']:
                 found = True
@@ -1967,7 +1984,7 @@
                                      stderr = grass.PIPE).communicate()
     except OSError, e:
         raise gcmd.GException, _("Unable to fetch interface description for command '%s'. "
-                                 "Details: %s") % (cmd, e.value)
+                                 "Details: %s") % (cmd, e)
     if cmderr and cmderr[:7] != 'WARNING':
         raise gcmd.GException, _("Unable to fetch interface description for command '%s'. "
                                  "Details: %s") % (cmd, cmderr)
@@ -1995,17 +2012,25 @@
         return True
 
 class GUI:
-    """
-    Parses GRASS commands when module is imported and used
-    from Layer Manager.
-    """
-    def __init__(self, parent = -1):
+    def __init__(self, parent = None, show = True, modal = False,
+                 centreOnParent = False, checkError = False):
+        """!Parses GRASS commands when module is imported and used from
+        Layer Manager.
+        """
         self.parent = parent
+        self.show   = show
+        self.modal  = modal
+        self.centreOnParent = centreOnParent
+        self.checkError     = checkError
+        
         self.grass_task = None
         self.cmd = list()
-
+        
+        global _ignoreBlackList
+        _ignoreBlackList = False if self.parent else True
+        
     def GetCmd(self):
-        """Get validated command"""
+        """!Get validated command"""
         return self.cmd
     
     def ParseInterface(self, cmd, parser = processTask):
@@ -2021,8 +2046,7 @@
         
         return processTask(tree).GetTask()
     
-    def ParseCommand(self, cmd, gmpath = None, completed = None, parentframe = None,
-                     show = True, modal = False, centreOnParent = False, checkError = False):
+    def ParseCommand(self, cmd, gmpath = None, completed = None):
         """!Parse command
         
         Note: cmd is given as list
@@ -2042,8 +2066,6 @@
             layer = completed[1]
             if completed[2]:
                 dcmd_params.update(completed[2])
-
-        self.parent = parentframe
         
         # parse the interface decription
         self.grass_task = self.ParseInterface(cmd)
@@ -2100,7 +2122,7 @@
             # update original command list
             cmd = cmd_validated
         
-        if show is not None:
+        if self.show is not None:
             self.mf = mainFrame(parent = self.parent, ID = wx.ID_ANY,
                                 task_description = self.grass_task,
                                 get_dcmd = get_dcmd, layer = layer)
@@ -2112,19 +2134,21 @@
             get_dcmd(dcmd = None, layer = layer, params = None,
                      propwin = self.mf)
         
-        if show is not None:
+        if self.show is not None:
             self.mf.notebookpanel.OnUpdateSelection(None)
-            if show is True:
-                if self.parent:
+            if self.show is True:
+                if self.parent and self.centreOnParent:
                     self.mf.CentreOnParent()
-                self.mf.Show(show)
-                self.mf.MakeModal(modal)
+                else:
+                    self.mf.CenterOnScreen()
+                self.mf.Show(self.show)
+                self.mf.MakeModal(self.modal)
             else:
                 self.mf.OnApply(None)
         
         self.cmd = cmd
         
-        if checkError:
+        if self.checkError:
             return self.grass_task, err
         else:
             return self.grass_task
@@ -2203,7 +2227,7 @@
         sys.exit(_("usage: %s <grass command>") % sys.argv[0])
     if sys.argv[1] !=  'test':
         q = wx.LogNull()
-        cmd = shlex.split(sys.argv[1])
+        cmd = utils.split(sys.argv[1])
         task = grassTask(cmd[0])
         task.set_options(cmd[1:])
         app = GrassGUIApp(task)
@@ -2231,7 +2255,7 @@
             },{
             "name" : "hidden_text",
             "description" : "This text should not appear in the form",
-            "hidden" : "yes"
+            "hidden" : True
             },{
             "name" : "text_default",
             "description" : "Enter text to override the default",

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/nviz_mapdisp.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/nviz_mapdisp.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/nviz_mapdisp.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -301,7 +301,7 @@
                               data['persp']['value'],
                               data['twist']['value'])
         
-        if event and event.zExag and data['z-exag'].has_key('value'):
+        if event and event.zExag and 'value' in data['z-exag']:
             self._display.SetZExag(data['z-exag']['value'])
         
         if event:
@@ -375,11 +375,11 @@
             return 0
         
         if layer.type ==  'raster':
-            if not data['surface'].has_key('object'):
+            if 'object' not in data['surface']:
                 return 0
         elif layer.type ==  'vector':
-            if not data['vlines'].has_key('object') and \
-                    not data['points'].has_key('object'):
+            if 'object' not in data['vlines'] and \
+                    'object' not in data['points']:
                 return 0
         
         return 1
@@ -430,7 +430,7 @@
                 elif type ==  'vector':
                     # data = self.tree.GetPyData(item)[0]['nviz']
                     # vecType = []
-                    # if data and data.has_key('vector'):
+                    # if data and 'vector' in data:
                     #     for v in ('lines', 'points'):
                     #         if data['vector'][v]:
                     #             vecType.append(v)
@@ -471,7 +471,7 @@
                     elif ltype ==  'vector':
                         data = self.tree.GetPyData(layer)[0]['nviz']
                         vecType = []
-                        if data and data.has_key('vector'):
+                        if data and 'vector' in data:
                             for v in ('lines', 'points'):
                                 if data['vector'][v]:
                                     vecType.append(v)
@@ -766,7 +766,7 @@
             vecTypes = ('lines', )
         
         for vecType in vecTypes:
-            if not data[vecType].has_key('object'):
+            if 'object' not in data[vecType]:
                 continue
             
             id = data[vecType]['object']['id']
@@ -842,21 +842,21 @@
         """!Generic method to update data layer properties"""
         data = event.data
         
-        if data.has_key('surface'):
+        if 'surface' in data:
             id = data['surface']['object']['id']
             self.UpdateSurfaceProperties(id, data['surface'])
             # -> initialized
             data['surface']['object']['init'] = True
             
-        elif data.has_key('volume'):
+        elif 'volume' in data:
             id = data['volume']['object']['id']
             self.UpdateVolumeProperties(id, data['volume'])
             # -> initialized
             data['volume']['object']['init'] = True
             
-        elif data.has_key('vector'):
+        elif 'vector' in data:
             for type in ('lines', 'points'):
-                if data['vector'][type].has_key('object'):
+                if 'object' in data['vector'][type]:
                     id = data['vector'][type]['object']['id']
                     self.UpdateVectorProperties(id, data['vector'], type)
                     # -> initialized
@@ -867,8 +867,8 @@
         # surface attributes
         for attrb in ('topo', 'color', 'mask',
                      'transp', 'shine', 'emit'):
-            if not data['attribute'].has_key(attrb) or \
-                    not data['attribute'][attrb].has_key('update'):
+            if attrb not in data['attribute'] or \
+                    'update' not in data['attribute'][attrb]:
                 continue
             
             map = data['attribute'][attrb]['map']
@@ -905,7 +905,7 @@
             data['attribute'][attrb].pop('update')
         
         # draw res
-        if data['draw']['resolution'].has_key('update'):
+        if 'update' in data['draw']['resolution']:
             coarse = data['draw']['resolution']['coarse']
             fine   = data['draw']['resolution']['fine']
             
@@ -916,7 +916,7 @@
             data['draw']['resolution'].pop('update')
         
         # draw style
-        if data['draw']['mode'].has_key('update'):
+        if 'update' in data['draw']['mode']:
             if data['draw']['mode']['value'] < 0: # need to calculate
                 data['draw']['mode']['value'] = \
                     self.nvizDefault.GetDrawMode(mode = data['draw']['mode']['desc']['mode'],
@@ -931,7 +931,7 @@
             data['draw']['mode'].pop('update')
         
         # wire color
-        if data['draw']['wire-color'].has_key('update'):
+        if 'update' in data['draw']['wire-color']:
             color = data['draw']['wire-color']['value']
             if data['draw']['all']:
                 self._display.SetWireColor(-1, str(color))
@@ -940,7 +940,7 @@
             data['draw']['wire-color'].pop('update')
         
         # position
-        if data['position'].has_key('update'):
+        if 'update' in data['position']:
             x = data['position']['x']
             y = data['position']['y']
             z = data['position']['z']
@@ -949,11 +949,11 @@
         
     def UpdateVolumeProperties(self, id, data, isosurfId = None):
         """!Update volume (isosurface/slice) map object properties"""
-        if data['draw']['resolution'].has_key('update'):
+        if 'update' in data['draw']['resolution']:
             self._display.SetIsosurfaceRes(id, data['draw']['resolution']['value'])
             data['draw']['resolution'].pop('update')
         
-        if data['draw']['shading'].has_key('update'):
+        if 'update' in data['draw']['shading']:
             if data['draw']['shading']['value'] < 0: # need to calculate
                 data['draw']['shading']['value'] = \
                     self.nvizDefault.GetDrawMode(shade = data['draw']['shading'],
@@ -967,8 +967,8 @@
         for isosurf in data['isosurface']:
             for attrb in ('color', 'mask',
                           'transp', 'shine', 'emit'):
-                if not isosurf.has_key(attrb) or \
-                    not isosurf[attrb].has_key('update'):
+                if attrb not in isosurf or \
+                        'update' not in isosurf[attrb]:
                     continue
                 map = isosurf[attrb]['map']
                 value = isosurf[attrb]['value']
@@ -1017,14 +1017,14 @@
     def UpdateVectorLinesProperties(self, id, data):
         """!Update vector line map object properties"""
         # mode
-        if data['color'].has_key('update') or \
-                data['width'].has_key('update') or \
-                data['mode'].has_key('update'):
+        if 'update' in data['color'] or \
+                'update' in data['width'] or \
+                'update' in data['mode']:
             width = data['width']['value']
             color = data['color']['value']
             if data['mode']['type'] ==  'flat':
                 flat = True
-                if data.has_key('surface'):
+                if 'surface' in data:
                     data.pop('surface')
             else:
                 flat = False
@@ -1032,21 +1032,21 @@
             self._display.SetVectorLineMode(id, color,
                                             width, flat)
             
-            if data['color'].has_key('update'):
+            if 'update' in data['color']:
                 data['color'].pop('update')
-            if data['width'].has_key('update'):
+            if 'update' in data['width']:
                 data['width'].pop('update')
-            if data['mode'].has_key('update'):
+            if 'update' in data['mode']:
                 data['mode'].pop('update')
         
         # height
-        if data['height'].has_key('update'):
+        if 'update' in data['height']:
             self._display.SetVectorLineHeight(id,
                                               data['height']['value'])
             data['height'].pop('update')
         
         # surface
-        if data['mode'].has_key('update'):
+        if 'update' in data['mode']:
             sid = self.GetLayerId(type = 'raster', name = data['mode']['surface'])
             if sid > -1:
                 self._display.SetVectorLineSurface(id, sid)
@@ -1055,10 +1055,10 @@
         
     def UpdateVectorPointsProperties(self, id, data):
         """!Update vector point map object properties"""
-        if data['size'].has_key('update') or \
-                data['width'].has_key('update') or \
-                data['marker'].has_key('update') or \
-                data['color'].has_key('update'):
+        if 'update' in data['size'] or \
+                'update' in data['width'] or \
+                'update' in data['marker'] or \
+                'update' in data['color']:
             ret = self._display.SetVectorPointMode(id, data['color']['value'],
                                                    data['width']['value'], float(data['size']['value']),
                                                    data['marker']['value'] + 1)
@@ -1073,17 +1073,17 @@
                 raise gcmd.GException(_("Setting data layer properties failed.\n\n%s") % error)
             
             for prop in ('size', 'width', 'marker', 'color'):
-                if data[prop].has_key('update'):
+                if 'update' in data[prop]:
                     data[prop].pop('update')
         
         # height
-        if data['height'].has_key('update'):
+        if 'update' in data['height']:
             self._display.SetVectorPointHeight(id,
                                                data['height']['value'])
             data['height'].pop('update')
         
         # surface
-        if data['mode'].has_key('update'):
+        if 'update' in data['mode']:
             sid = self.GetLayerId(type = 'raster', name = data['mode']['surface'])
             if sid > -1:
                 self._display.SetVectorPointSurface(id, sid)

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/nviz_tools.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/nviz_tools.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/nviz_tools.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -2532,7 +2532,7 @@
             self.SetMapObjUseMap(nvizType = 'surface',
                                  attrb = attr, map = True) # -> map
         
-        if data['attribute'].has_key('color'):
+        if 'color' in data['attribute']:
             value = data['attribute']['color']['value']
             if data['attribute']['color']['map']:
                 self.FindWindowById(self.win['surface']['color']['map']).SetValue(value)
@@ -2648,7 +2648,7 @@
         # lines
         #
         showLines = self.FindWindowById(self.win['vector']['lines']['show'])
-        if data['lines'].has_key('object'):
+        if 'object' in data['lines']:
             showLines.SetValue(True)
         else:
             showLines.SetValue(False)
@@ -2693,7 +2693,7 @@
         #
         showPoints = self.FindWindowById(self.win['vector']['points']['show'])
         
-        if data['points'].has_key('object'):
+        if 'object' in data['points']:
             showPoints.SetValue(True)
         else:
             showPoints.SetValue(False)
@@ -2772,7 +2772,7 @@
                 continue
             
             # skip empty attributes
-            if not data.has_key(attrb):
+            if attrb not in data:
                 continue
             
             value = data[attrb]['value']

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/ogc_services.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/ogc_services.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/ogc_services.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -194,7 +194,7 @@
             elif key == 'title':
                 layers[lastLayer][key] = value
             elif key == 'style':
-                if not layers[lastLayer].has_key('style'):
+                if 'style' not in layers[lastLayer]:
                     layers[lastLayer]['style'] = {}
                 layers[lastLayer]['style'][value] = ''
                 lastStyle = value
@@ -260,7 +260,7 @@
             title = data[layer]['title']
             lchild = self.AppendItem(self.root, layer)
             self.SetItemText(lchild, title, 1)
-            if data[layer].has_key('style'):
+            if 'style' in data[layer]:
                 styles = data[layer]['style'].keys()
                 if not styles:
                     continue

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/preferences.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/preferences.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/preferences.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -339,14 +339,6 @@
                 'delRecord' : {
                     'enabled' : True
                     },
-                # add centroid to left/right area
-                'addCentroid' : {
-                    'enabled' : False
-                    },
-                # do not attach category to boundary
-                'catBoundary' : {
-                    'enabled' : False
-                    },
                 # query tool
                 'query' : {
                     'selection' : 0,
@@ -910,15 +902,15 @@
         @param subkey subkey (value or list)
         @param value value
         """
-        if not dict.has_key(group):
+        if group not in dict:
             dict[group] = {}
         
-        if not dict[group].has_key(key):
+        if key not in dict[group]:
             dict[group][key] = {}
         
         if type(subkey) == types.ListType:
             # TODO: len(subkey) > 2
-            if not dict[group][key].has_key(subkey[0]):
+            if subkey[0] not in dict[group][key]:
                 dict[group][key][subkey[0]] = {}
             try:
                 dict[group][key][subkey[0]][subkey[1]] = value
@@ -1930,7 +1922,7 @@
         except ValueError:
             code = -1
         win = self.FindWindowById(self.winId['projection:statusbar:proj4'])
-        if self.epsgCodeDict.has_key(code):
+        if code in self.epsgCodeDict:
             win.SetValue(self.epsgCodeDict[code][1])
         else:
             list.SetSelection(0)

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/profile.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/profile.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/profile.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -53,7 +53,7 @@
 class ProfileFrame(wx.Frame):
     """!Mainframe for displaying profile of raster map. Uses wx.lib.plot.
     """
-    def __init__(self, parent=None, id=wx.ID_ANY, title=_("Profile Analysis"),
+    def __init__(self, parent=None, id=wx.ID_ANY, title=_("GRASS Profile Analysis Tool"),
                  rasterList=[],
                  pos=wx.DefaultPosition, size=wx.DefaultSize,
                  style=wx.DEFAULT_FRAME_STYLE):

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/prompt.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/prompt.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/prompt.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -21,9 +21,9 @@
 
 import os
 import sys
-import shlex
 import copy
 import difflib
+import codecs
 
 import wx
 import wx.stc
@@ -56,7 +56,7 @@
         """
         self.statusbar = statusbar
         
-        if kwargs.has_key('style'):
+        if 'style' in kwargs:
             kwargs['style'] = wx.TE_PROCESS_ENTER | kwargs['style']
         else:
             kwargs['style'] = wx.TE_PROCESS_ENTER
@@ -213,7 +213,7 @@
              col = self._colSearch
          itemtext = self.dropdownlistbox.GetItem(sel, col).GetText()
          
-         cmd = shlex.split(str(self.GetValue()))
+         cmd = utils.split(str(self.GetValue()))
          if len(cmd) > 0 and cmd[0] in self._choicesCmd:
              # -> append text (skip last item)
              if self._choiceType == 'param':
@@ -338,7 +338,7 @@
             return
         
         try:
-            cmd = shlex.split(str(text))
+            cmd = utils.split(str(text))
         except ValueError, e:
             self.statusbar.SetStatusText(str(e))
             cmd = text.split(' ')
@@ -505,10 +505,11 @@
         hist = list()
         env = grass.gisenv()
         try:
-            fileHistory = open(os.path.join(env['GISDBASE'],
-                                            env['LOCATION_NAME'],
-                                            env['MAPSET'],
-                                            '.bash_history'), 'r')
+            fileHistory = codecs.open(os.path.join(env['GISDBASE'],
+                                                   env['LOCATION_NAME'],
+                                                   env['MAPSET'],
+                                                   '.bash_history'),
+                                      encoding = 'utf-8', mode = 'r')
         except IOError:
             return hist
         
@@ -522,7 +523,7 @@
 
     def GetCommandDesc(self, cmd):
         """!Get description for given command"""
-        if self.moduleDesc.has_key(cmd):
+        if cmd in self.moduleDesc:
             return self.moduleDesc[cmd]['desc']
         
         return ''
@@ -560,7 +561,7 @@
             except ValueError:
                 continue # TODO
             
-            if not result.has_key(group):
+            if group not in result:
                 result[group] = list()
             result[group].append(name)
             
@@ -569,7 +570,7 @@
             for i in range(len(name.split('.'))-1):
                 group = '.'.join([group,name.split('.',1)[0]])
                 name = name.split('.',1)[1]
-                if not result.has_key(group):
+                if group not in result:
                     result[group] = list()
                 result[group].append(name)
       
@@ -1059,6 +1060,7 @@
                 cmd = utils.split(str(line))
             except UnicodeError:
                 cmd = utils.split(utils.EncodeString((line)))
+            cmd = map(utils.DecodeString, cmd)
             
             #  send the command list to the processor 
             if cmd[0] in ('r.mapcalc', 'r3.mapcalc') and len(cmd) == 1:

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/render.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/render.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/render.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -1,7 +1,7 @@
 """!
 @package render
 
-Rendering map layers and overlays into map composition image
+Rendering map layers and overlays into map composition image.
 
 Classes:
  - Layer
@@ -9,13 +9,13 @@
  - Overlay
  - Map
 
-(C) 2006-2010 by the GRASS Development Team
+(C) 2006-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.
 
 @author Michael Barton
- at author Jachym Cepicky,
+ at author Jachym Cepicky
 @author Martin Landa <landa.martin gmail.com>
 """
 
@@ -59,8 +59,8 @@
     For map layer use MapLayer class.
     For overlays use Overlay class.
     """
-    def __init__(self, type, cmd, name=None,
-                 active=True, hidden=False, opacity=1.0):
+    def __init__(self, type, cmd, name = None,
+                 active = True, hidden = False, opacity = 1.0):
         """!
         @todo pass cmd as tuple instead of list
         
@@ -90,7 +90,7 @@
         
         Debug.msg (3, "Layer.__init__(): type=%s, cmd='%s', name=%s, " \
                        "active=%d, opacity=%d, hidden=%d" % \
-                       (self.type, self.GetCmd(string=True), self.name, self.active,
+                       (self.type, self.GetCmd(string = True), self.name, self.active,
                         self.opacity, self.hidden))
         
         # generated file for each layer
@@ -103,7 +103,7 @@
         
     def __del__(self):
         Debug.msg (3, "Layer.__del__(): layer=%s, cmd='%s'" %
-                   (self.name, self.GetCmd(string=True)))
+                   (self.name, self.GetCmd(string = True)))
 
     def Render(self):
         """!Render layer to image
@@ -121,9 +121,7 @@
         Debug.msg (3, "Layer.Render(): type=%s, name=%s" % \
                        (self.type, self.name))
         
-        #
         # prepare command for each layer
-        #
         layertypes = ('raster', 'rgb', 'his', 'shaded', 'rastarrow', 'rastnum',
                       'vector','thememap','themechart',
                       'grid', 'geodesic', 'rhumb', 'labels',
@@ -134,16 +132,24 @@
             raise gcmd.GException(_("<%(name)s>: layer type <%(type)s> is not supported") % \
                                       {'type' : self.type, 'name' : self.name})
         
-        #
         # start monitor
-        #
         if UserSettings.Get(group='display', key='driver', subkey='type') == 'cairo':
-            os.environ["GRASS_CAIROFILE"] = self.mapfile
-            if 'cairo' not in gcmd.RunCommand('d.mon',
-                                              flags='p',
-                                              read = True):
-                gcmd.RunCommand('d.mon',
-                                start = 'cairo')
+#            os.environ["GRASS_CAIROFILE"] = self.mapfile
+#            if 'cairo' not in gcmd.RunCommand('d.mon',
+#                                              flags='p',
+#                                              read = True):
+#                gcmd.RunCommand('d.mon',
+#                                start = 'cairo')
+            if not self.mapfile:
+                self.gtemp = tempfile.mkstemp()[1]
+                self.maskfile = self.gtemp + ".pgm"
+                if self.type == 'overlay':
+                    self.mapfile  = self.gtemp + ".png"
+                else:
+                    self.mapfile  = self.gtemp + ".ppm"
+
+            if self.mapfile:
+                os.environ["GRASS_CAIROFILE"] = self.mapfile
         else:
             if not self.mapfile:
                 self.gtemp = tempfile.mkstemp()[1]
@@ -156,16 +162,15 @@
             if self.mapfile:
                 os.environ["GRASS_PNGFILE"] = self.mapfile
         
-        #
         # execute command
-        #
         try:
             if self.type == 'command':
                 read = False
                 for c in self.cmd:
-                    ret = gcmd.RunCommand(c[0],
-                                          quiet = True,
-                                          **c[1])
+                    ret, msg = gcmd.RunCommand(c[0],
+                                               getErrorMsg = True,
+                                               quiet = True,
+                                               **c[1])
                     if ret != 0:
                         break
                     if not read:
@@ -173,12 +178,17 @@
                 
                 os.environ["GRASS_PNG_READ"] = "FALSE"
             else:
-                ret = gcmd.RunCommand(self.cmd[0],
-                                      quiet = True,
-                                      **self.cmd[1])
-                
+                ret, msg = gcmd.RunCommand(self.cmd[0],
+                                           getErrorMsg = True,
+                                           quiet = True,
+                                           **self.cmd[1])
+            
+            # if len(msg):
+            # sys.stderr.write(_("Running") + " '" + utils.GetCmdString(self.cmd) + "'")
+            # sys.stderr.write(msg)
+            
             if ret != 0:
-                #clean up after probley
+                # clean up after problem
                 try:
                     os.remove(self.mapfile)
                     os.remove(self.maskfile)
@@ -189,8 +199,7 @@
                 self.maskfile = None
         
         except gcmd.GException, e:
-            sys.stderr.write(e.value)
-            
+            # sys.stderr.write(e.value)
             # clean up after problems
             try:
                 os.remove(self.mapfile)
@@ -201,21 +210,19 @@
             self.mapfile = None
             self.maskfile = None
         
-        #
         # stop monitor
-        #
         if UserSettings.Get(group='display', key='driver', subkey='type') == 'cairo':
-            gcmd.RunCommand('d.mon',
-                            stop = 'cairo')
+#            gcmd.RunCommand('d.mon',
+#                            stop = 'cairo')
             del os.environ["GRASS_CAIROFILE"]
-        elif os.environ.has_key("GRASS_PNGFILE"):
+        elif "GRASS_PNGFILE" in os.environ:
             del os.environ["GRASS_PNGFILE"]
         
         self.force_render = False
         
         return self.mapfile
     
-    def GetCmd(self, string=False):
+    def GetCmd(self, string = False):
         """!Get GRASS command as list of string.
         
         @param string get command as string if True otherwise as list
@@ -244,7 +251,7 @@
             return 'cell'
         return self.type
     
-    def GetOpacity(self, float=False):
+    def GetOpacity(self, float = False):
         """
         Get layer opacity level
         
@@ -295,11 +302,11 @@
         """!Set layer name"""
         self.name = name
         
-    def SetActive(self, enable=True):
+    def SetActive(self, enable = True):
         """!Active or deactive layer"""
         self.active = bool(enable)
 
-    def SetHidden(self, enable=False):
+    def SetHidden(self, enable = False):
         """!Hide or show map layer in Layer Manager"""
         self.hidden = bool(enable)
 
@@ -320,14 +327,14 @@
                 self.cmd.append(utils.CmdToTuple(c))
         else:
             self.cmd  = utils.CmdToTuple(cmd)
-        Debug.msg(3, "Layer.SetCmd(): cmd='%s'" % self.GetCmd(string=True))
+        Debug.msg(3, "Layer.SetCmd(): cmd='%s'" % self.GetCmd(string = True))
         
         # for re-rendering
         self.force_render = True
         
 class MapLayer(Layer):
-    def __init__(self, type, cmd, name=None,
-                 active=True, hidden=False, opacity=1.0): 
+    def __init__(self, type, cmd, name = None,
+                 active = True, hidden = False, opacity = 1.0): 
         """!Represents map layer in the map canvas
         
         @param type layer type ('raster', 'vector', 'command', etc.)
@@ -357,7 +364,7 @@
         
 class Overlay(Layer):
     def __init__(self, id, type, cmd,
-                 active=True, hidden=True, opacity=1.0):
+                 active = True, hidden = True, opacity = 1.0):
         """!Represents overlay displayed in map canvas
         
         @param id overlay id (for PseudoDC)
@@ -396,7 +403,7 @@
         self.gisrc = gisrc
         
         # generated file for g.pnmcomp output for rendering the map
-        self.mapfile = tempfile.mkstemp(suffix='.ppm')[1]
+        self.mapfile = tempfile.mkstemp(suffix = '.ppm')[1]
         
         # setting some initial env. variables
         self._initGisEnv() # g.gisenv
@@ -440,6 +447,9 @@
         """!Return region projection and map units information
         """
         projinfo = dict()
+        if not grass.find_program('g.proj', ['--help']):
+            sys.exit(_("GRASS module '%s' not found. Unable to start map "
+                       "display window.") % 'g.proj')
         
         ret = self._runCommand(gcmd.RunCommand, prog = 'g.proj',
                                read = True, flags = 'p')
@@ -637,14 +647,16 @@
         if vect:
             cmd['vect'] = ','.join(vect)
         
-        ret = gcmd.RunCommand('g.region',
-                              read = True,
-                              **cmd)
-        if not ret:
+        ret, reg, msg = gcmd.RunCommand('g.region',
+                                        read = True,
+                                        getErrorMsg = True,
+                                        **cmd)
+        
+        if ret != 0:
             if rast:
-                message = _("Unable to zoom to raster map <%s>.") % rast[0]
+                message = _("Unable to zoom to raster map <%s>.\n\nDetails: %s") % (rast[0], msg)
             elif vect:
-                message = _("Unable to zoom to vector map <%s>.") % vect[0]
+                message = _("Unable to zoom to vector map <%s>.\n\nDetails: %s") % (vect[0], msg)
             else:
                 message = _("Unable to get current geographic extent. "
                             "Force quiting wxGUI. Please run manually g.region to "
@@ -652,8 +664,8 @@
             gcmd.GError(message)
             return self.region
         
-        for reg in ret.splitlines():
-            key, val = reg.split("=", 1)
+        for r in reg.splitlines():
+            key, val = r.split("=", 1)
             try:
                 region[key] = float(val)
             except ValueError:
@@ -678,7 +690,7 @@
         """!Get current display region settings"""
         return self.region
 
-    def SetRegion(self, windres=False):
+    def SetRegion(self, windres = False):
         """!Render string for GRASS_REGION env. variable, so that the
         images will be rendered from desired zoom level.
         
@@ -745,8 +757,8 @@
         except:
             return None
         
-    def GetListOfLayers(self, l_type=None, l_mapset=None, l_name=None,
-                        l_active=None, l_hidden=None):
+    def GetListOfLayers(self, l_type = None, l_mapset = None, l_name = None,
+                        l_active = None, l_hidden = None):
         """!Returns list of layers of selected properties or list of
         all layers.
 
@@ -832,7 +844,7 @@
             if mapWindow:
                 # update progress bar
                 ### wx.SafeYield(mapWindow)
-                event = wxUpdateProgressBar(value=ilayer)
+                event = wxUpdateProgressBar(value = ilayer)
                 wx.PostEvent(mapWindow, event)
             
             # add image to compositing list
@@ -844,7 +856,7 @@
             Debug.msg (3, "Map.Render() type=%s, layer=%s " % (layer.type, layer.name))
             ilayer += 1
         
-    def Render(self, force=False, mapWindow=None, windres=False):
+    def Render(self, force = False, mapWindow = None, windres = False):
         """!Creates final image composite
         
         This function can conditionaly use high-level tools, which
@@ -857,7 +869,7 @@
         @return name of file with rendered image or None
         """
         maps = []
-        masks =[]
+        masks = []
         opacities = []
         
         # use external gisrc if defined
@@ -871,8 +883,9 @@
         os.environ["GRASS_HEIGHT"] = str(self.height)
         if UserSettings.Get(group='display', key='driver', subkey='type') == 'cairo':
             os.environ["GRASS_AUTO_WRITE"] = "TRUE"
-            if os.environ.has_key("GRASS_RENDER_IMMEDIATE"):
+            if "GRASS_RENDER_IMMEDIATE" in os.environ:
                 del os.environ["GRASS_RENDER_IMMEDIATE"]
+            os.environ["GRASS_RENDER_IMMEDIATE"] = "TRUE"
         else:
             os.environ["GRASS_PNG_AUTO_WRITE"] = "TRUE"
             os.environ["GRASS_PNG_READ"] = "FALSE"
@@ -881,7 +894,7 @@
             os.environ["GRASS_RENDER_IMMEDIATE"] = "TRUE"
         
         self._renderLayers(force, mapWindow, maps, masks, opacities)
-            
+        
         # ugly hack for MSYS
         if not subprocess.mswindows:
             mapstr = ",".join(maps)
@@ -899,8 +912,8 @@
             mapoutstr = self.mapfile.replace('\\', '/')
         
         # compose command
-        bgcolor = ':'.join(map(str, UserSettings.Get(group='display', key='bgcolor',
-                                                     subkey='color')))
+        bgcolor = ':'.join(map(str, UserSettings.Get(group = 'display', key = 'bgcolor',
+                                                     subkey = 'color')))
         
         complist = ["g.pnmcomp",
                     "in=%s" % ",".join(maps),
@@ -943,9 +956,9 @@
         
         return self.mapfile
 
-    def AddLayer(self, type, command, name=None,
-                 l_active=True, l_hidden=False, l_opacity=1.0, l_render=False,
-                 pos=-1):
+    def AddLayer(self, type, command, name = None,
+                 l_active = True, l_hidden = False, l_opacity = 1.0, l_render = False,
+                 pos = -1):
         """!Adds generic map layer to list of layers
         
         @param type layer type ('raster', 'vector', etc.)
@@ -963,8 +976,8 @@
         # l_opacity must be <0;1>
         if l_opacity < 0: l_opacity = 0
         elif l_opacity > 1: l_opacity = 1
-        layer = MapLayer(type=type, name=name, cmd=command,
-                         active=l_active, hidden=l_hidden, opacity=l_opacity)
+        layer = MapLayer(type = type, name = name, cmd = command,
+                         active = l_active, hidden = l_hidden, opacity = l_opacity)
         
         # add maplayer to the list of layers
         if pos > -1:
@@ -979,7 +992,7 @@
         
         return layer
 
-    def DeleteLayer(self, layer, overlay=False):
+    def DeleteLayer(self, layer, overlay = False):
         """!Removes layer from list of layers
         
         @param layer layer instance in layer tree
@@ -1024,7 +1037,7 @@
         Debug.msg (4, "Map.ReoderLayers(): layers=%s" % \
                    (layerNameList))
         
-    def ChangeLayer(self, layer, render=False, **kargs):
+    def ChangeLayer(self, layer, render = False, **kargs):
         """!Change map layer properties
 
         @param layer map layer instance
@@ -1038,22 +1051,22 @@
         """
         Debug.msg (3, "Map.ChangeLayer(): layer=%s" % layer.name)
         
-        if kargs.has_key('type'):
+        if 'type' in kargs:
             layer.SetType(kargs['type']) # check type
         
-        if kargs.has_key('command'):
+        if 'command' in kargs:
             layer.SetCmd(kargs['command'])
         
-        if kargs.has_key('name'):
+        if 'name' in kargs:
             layer.SetName(kargs['name'])
         
-        if kargs.has_key('active'):
+        if 'active' in kargs:
             layer.SetActive(kargs['active'])
         
-        if kargs.has_key('hidden'):
+        if 'hidden' in kargs:
             layer.SetHidden(kargs['hidden'])
         
-        if kargs.has_key('opacity'):
+        if 'opacity' in kargs:
             layer.SetOpacity(kargs['opacity'])
         
         if render and not layer.Render():
@@ -1097,7 +1110,7 @@
                    (layer.name, name))
         layer.name =  name
 
-    def RemoveLayer(self, name=None, id=None):
+    def RemoveLayer(self, name = None, id = None):
         """!Removes layer from layer list
         
         Layer is defined by name at mapset or id.
@@ -1124,7 +1137,7 @@
         
         return None
 
-    def GetLayerIndex(self, layer, overlay=False):
+    def GetLayerIndex(self, layer, overlay = False):
         """!Get index of layer in layer list.
         
         @param layer layer instace in layer tree
@@ -1144,7 +1157,7 @@
         return -1
 
     def AddOverlay(self, id, type, command,
-                   l_active=True, l_hidden=True, l_opacity=1.0, l_render=False):
+                   l_active = True, l_hidden = True, l_opacity = 1.0, l_render = False):
         """!Adds overlay (grid, barscale, legend, etc.) to list of
         overlays
         
@@ -1159,8 +1172,8 @@
         @retutn None on failure
         """
         Debug.msg (2, "Map.AddOverlay(): cmd=%s, render=%d" % (command, l_render))
-        overlay = Overlay(id=id, type=type, cmd=command,
-                          active=l_active, hidden=l_hidden, opacity=l_opacity)
+        overlay = Overlay(id = id, type = type, cmd = command,
+                          active = l_active, hidden = l_hidden, opacity = l_opacity)
         
         # add maplayer to the list of layers
         self.overlays.append(overlay)
@@ -1171,7 +1184,7 @@
         
         return self.overlays[-1]
 
-    def ChangeOverlay(self, id, render=False, **kargs):
+    def ChangeOverlay(self, id, render = False, **kargs):
         """!Change overlay properities
         
         Add new overlay if overlay with 'id' doesn't exist.
@@ -1185,23 +1198,23 @@
         
         @return new layer on success
         """
-        overlay = self.GetOverlay(id, list=False)
+        overlay = self.GetOverlay(id, list = False)
         if  overlay is None:
             overlay = Overlay(id, type = None, cmd = None)
         
-        if kargs.has_key('type'):
+        if 'type' in kargs:
             overlay.SetName(kargs['type']) # type -> overlay
         
-        if kargs.has_key('command'):
+        if 'command' in kargs:
             overlay.SetCmd(kargs['command'])
         
-        if kargs.has_key('active'):
+        if 'active' in kargs:
             overlay.SetActive(kargs['active'])
         
-        if kargs.has_key('hidden'):
+        if 'hidden' in kargs:
             overlay.SetHidden(kargs['hidden'])
         
-        if kargs.has_key('opacity'):
+        if 'opacity' in kargs:
             overlay.SetOpacity(kargs['opacity'])
         
         if render and command != [] and not overlay.Render():
@@ -1210,7 +1223,7 @@
         
         return overlay
 
-    def GetOverlay(self, id, list=False):
+    def GetOverlay(self, id, list = False):
         """!Return overlay(s) with 'id'
         
         @param id overlay id
@@ -1241,7 +1254,7 @@
         
         @return removed overlay on success or None
         """
-        return self.DeleteLayer(overlay, overlay=True)
+        return self.DeleteLayer(overlay, overlay = True)
 
     def Clean(self):
         """!Clean layer stack - go trough all layers and remove them
@@ -1289,27 +1302,25 @@
     Usage: display=Render()
     """
     import gettext
-    gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode=True)
+    gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode = True)
     
     print "Initializing..."
-    grass.run_command("g.region", flags="d")
+    grass.run_command("g.region", flags = "d")
     
     map = Map()
     map.width = 640
     map.height = 480
     
-    map.AddLayer(item=None,
-                 type="raster",
-                 name="elevation.dem",
+    map.AddLayer(type = "raster",
+                 name = "elevation.dem",
                  command = ["d.rast", "elevation.dem at PERMANENT", "catlist=1000-1500", "-i"],
-                 l_opacity=.7)
+                 l_opacity = .7)
     
-    map.AddLayer(item=None,
-                 type="vector",
-                 name="streams",
+    map.AddLayer(type = "vector",
+                 name = "streams",
                  command = ["d.vect", "streams at PERMANENT", "color=red", "width=3", "type=line"])
     
-    image = map.Render(force=True)
+    image = map.Render(force = True)
     
     if image:
         os.system("display %s" % image)

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/toolbars.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/toolbars.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/toolbars.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -6,8 +6,8 @@
 Classes:
  - AbstractToolbar
  - MapToolbar
- - GRToolbar
- - GCPToolbar
+ - GCPMapToolbar
+ - GCPDisplayToolbar
  - VDigitToolbar
  - ProfileToolbar
  - NvizToolbar
@@ -15,7 +15,7 @@
  - HistogramToolbar
  - LayerManagerToolbar
 
-(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.
 
@@ -35,23 +35,21 @@
 import globalvar
 import gcmd
 import gdialogs
-import vdigit
-from vdigit import VDigitSettingsDialog, haveVDigit
+from vdigit import VDigitSettingsDialog, haveVDigit, VDigit
 from debug import Debug
 from preferences import globalSettings as UserSettings
 from nviz import haveNviz
 from nviz_preferences import NvizPreferencesDialog
 
-gmpath = os.path.join(globalvar.ETCWXDIR, "icons")
-sys.path.append(gmpath)
-from icon import Icons as Icons
+sys.path.append(os.path.join(globalvar.ETCWXDIR, "icons"))
+from icon import Icons
 
 class AbstractToolbar(wx.ToolBar):
     """!Abstract toolbar class"""
     def __init__(self, parent):
         self.parent = parent
         wx.ToolBar.__init__(self, parent = self.parent, id = wx.ID_ANY)
-    
+        
         self.action = dict()
         
         self.Bind(wx.EVT_TOOL, self.OnTool)
@@ -66,7 +64,7 @@
         
         self._data = toolData
         
-    def ToolbarData(self):
+    def _toolbarData(self):
         """!Toolbar data (virtual)"""
         return None
     
@@ -78,9 +76,10 @@
         """
         bmpDisabled = wx.NullBitmap
         
-        if label:
+        if label: 
             Debug.msg(3, "CreateTool(): tool=%d, label=%s bitmap=%s" % \
-                  (tool, label, bitmap))
+                          (tool, label, bitmap))
+            
             toolWin = self.AddLabelTool(tool, label, bitmap,
                                         bmpDisabled, kind,
                                         shortHelp, longHelp)
@@ -105,14 +104,16 @@
                 self.SetToolLongHelp(tool[0], "")
         
     def OnTool(self, event):
-        """!Tool selected"""
+        """!Tool selected
+        """
         if self.parent.GetName() == "GCPFrame":
             return
         
-        if self.parent.toolbars['vdigit']:
-            # update vdigit toolbar (unselect currently selected tool)
-            id = self.parent.toolbars['vdigit'].GetAction(type = 'id')
-            self.parent.toolbars['vdigit'].ToggleTool(id, False)
+        if hasattr(self.parent, 'toolbars'):
+            if self.parent.toolbars['vdigit']:
+                # update vdigit toolbar (unselect currently selected tool)
+                id = self.parent.toolbars['vdigit'].GetAction(type = 'id')
+                self.parent.toolbars['vdigit'].ToggleTool(id, False)
         
         if event:
             # deselect previously selected tool
@@ -162,6 +163,24 @@
         
         self.EnableTool(id, enable)
         
+    def _getToolbarData(self, data):
+        """!Define tool
+        """
+        retData = list()
+        for args in data:
+            retData.append(self._defineTool(*args))
+        
+        return retData
+
+    def _defineTool(self, key, name = None, icon = None, handler = None, item = wx.ITEM_NORMAL):
+        """!Define tool
+        """
+        if key:
+            return (key, name, icon.GetBitmap(),
+                    item, icon.GetLabel(), icon.GetDesc(),
+                    handler)
+        return ("", "", "", "", "", "", "") # separator
+    
 class MapToolbar(AbstractToolbar):
     """!Map Display toolbar
     """
@@ -174,12 +193,14 @@
         self.mapcontent = mapcontent # render.Map
         AbstractToolbar.__init__(self, parent = parent) # MapFrame
         
-        self.InitToolbar(self.ToolbarData())
+        self.InitToolbar(self._toolbarData())
         
         # optional tools
         choices = [ _('2D view'), ]
         self.toolId = { '2d' : 0 }
-        log = self.parent.GetLayerManager().GetLogWindow()
+        if self.parent.GetLayerManager():
+            log = self.parent.GetLayerManager().GetLogWindow()
+        
         if haveNviz:
             choices.append(_('3D view'))
             self.toolId['3d'] = 1
@@ -193,6 +214,7 @@
                            'In the meantime you can use "NVIZ" from the File menu.'), wrap = 60)
             
             self.toolId['3d'] = -1
+
         if haveVDigit:
             choices.append(_('Digitize'))
             if self.toolId['3d'] > -1:
@@ -235,7 +257,7 @@
         
         self.FixSize(width = 90)
         
-    def ToolbarData(self):
+    def _toolbarData(self):
         """!Toolbar data"""
         self.displaymap = wx.NewId()
         self.rendermap = wx.NewId()
@@ -253,59 +275,48 @@
         self.savefile = wx.NewId()
         self.printmap = wx.NewId()
         
-        # tool, label, bitmap, kind, shortHelp, longHelp, handler
-        return (
-            (self.displaymap, "displaymap", Icons["displaymap"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["displaymap"].GetLabel(), Icons["displaymap"].GetDesc(),
-             self.parent.OnDraw),
-            (self.rendermap, "rendermap", Icons["rendermap"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["rendermap"].GetLabel(), Icons["rendermap"].GetDesc(),
-             self.parent.OnRender),
-            (self.erase, "erase", Icons["erase"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["erase"].GetLabel(), Icons["erase"].GetDesc(),
-             self.parent.OnErase),
-            ("", "", "", "", "", "", ""),
-            (self.pointer, "pointer", Icons["pointer"].GetBitmap(),
-             wx.ITEM_CHECK, Icons["pointer"].GetLabel(), Icons["pointer"].GetDesc(),
-             self.parent.OnPointer),
-            (self.query, "query", Icons["query"].GetBitmap(),
-             wx.ITEM_CHECK, Icons["query"].GetLabel(), Icons["query"].GetDesc(),
-             self.parent.OnQuery),
-            (self.pan, "pan", Icons["pan"].GetBitmap(),
-             wx.ITEM_CHECK, Icons["pan"].GetLabel(), Icons["pan"].GetDesc(),
-             self.parent.OnPan),
-            (self.zoomin, "zoom_in", Icons["zoom_in"].GetBitmap(),
-             wx.ITEM_CHECK, Icons["zoom_in"].GetLabel(), Icons["zoom_in"].GetDesc(),
-             self.parent.OnZoomIn),
-            (self.zoomout, "zoom_out", Icons["zoom_out"].GetBitmap(),
-             wx.ITEM_CHECK, Icons["zoom_out"].GetLabel(), Icons["zoom_out"].GetDesc(),
-             self.parent.OnZoomOut),
-            (self.zoomextent, "zoom_extent", Icons["zoom_extent"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["zoom_extent"].GetLabel(), Icons["zoom_extent"].GetDesc(),
-             self.parent.OnZoomToMap),
-            (self.zoomback, "zoom_back", Icons["zoom_back"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["zoom_back"].GetLabel(), Icons["zoom_back"].GetDesc(),
-             self.parent.OnZoomBack),
-            (self.zoommenu, "zoommenu", Icons["zoommenu"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["zoommenu"].GetLabel(), Icons["zoommenu"].GetDesc(),
-             self.parent.OnZoomMenu),
-            ("", "", "", "", "", "", ""),
-            (self.analyze, "analyze", Icons["analyze"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["analyze"].GetLabel(), Icons["analyze"].GetDesc(),
-             self.parent.OnAnalyze),
-            ("", "", "", "", "", "", ""),
-            (self.dec, "overlay", Icons["overlay"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["overlay"].GetLabel(), Icons["overlay"].GetDesc(),
-             self.parent.OnDecoration),
-            ("", "", "", "", "", "", ""),
-            (self.savefile, "savefile", Icons["savefile"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["savefile"].GetLabel(), Icons["savefile"].GetDesc(),
-             self.parent.SaveToFile),
-            (self.printmap, "printmap", Icons["printmap"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["printmap"].GetLabel(), Icons["printmap"].GetDesc(),
-             self.parent.PrintMenu),
-            ("", "", "", "", "", "", "")
-            )
+        icons = Icons['displayWindow']
+        return self._getToolbarData(((self.displaymap, 'display', icons['display'],
+                                      self.parent.OnDraw),
+                                     (self.rendermap, 'render', icons['render'],
+                                      self.parent.OnRender),
+                                     (self.erase, 'erase', icons['erase'],
+                                      self.parent.OnErase),
+                                     (None, ),
+                                     (self.pointer, 'pointer', icons['pointer'],
+                                      self.parent.OnPointer,
+                                      wx.ITEM_CHECK),
+                                     (self.query, 'query', icons['query'],
+                                      self.parent.OnQuery,
+                                      wx.ITEM_CHECK),
+                                     (self.pan, 'pan', icons['pan'],
+                                      self.parent.OnPan,
+                                      wx.ITEM_CHECK),
+                                     (self.zoomin, 'zoomIn', icons['zoomIn'],
+                                      self.parent.OnZoomIn,
+                                      wx.ITEM_CHECK),
+                                     (self.zoomout, 'zoomOut', icons['zoomOut'],
+                                      self.parent.OnZoomOut,
+                                      wx.ITEM_CHECK),
+                                     (self.zoomextent, 'zoomExtent', icons['zoomExtent'],
+                                      self.parent.OnZoomToMap),
+                                     (self.zoomback, 'zoomBack', icons['zoomBack'],
+                                      self.parent.OnZoomBack),
+                                     (self.zoommenu, 'zoomMenu', icons['zoomMenu'],
+                                      self.parent.OnZoomMenu),
+                                     (None, ),
+                                     (self.analyze, 'analyze', icons['analyze'],
+                                      self.parent.OnAnalyze),
+                                     (None, ),
+                                     (self.dec, 'overlay', icons['overlay'],
+                                      self.parent.OnDecoration),
+                                     (None, ),
+                                     (self.savefile, 'saveFile', icons['saveFile'],
+                                      self.parent.SaveToFile),
+                                     (self.printmap, 'print', icons['print'],
+                                      self.parent.PrintMenu),
+                                     (None, ))
+                                    )
     
     def OnSelectTool(self, event):
         """!Select / enable tool available in tools list
@@ -354,12 +365,12 @@
     def __init__(self, parent):
         AbstractToolbar.__init__(self, parent)
         
-        self.InitToolbar(self.ToolbarData())
+        self.InitToolbar(self._toolbarData())
         
         # realize the toolbar
         self.Realize()
 
-    def ToolbarData(self):
+    def _toolbarData(self):
         self.gcpSave = wx.NewId()
         self.gcpReload = wx.NewId()
         self.gcpAdd = wx.NewId()
@@ -368,31 +379,24 @@
         self.rms = wx.NewId()
         self.georect = wx.NewId()
 
-        return (
-            (self.gcpSave, 'grGcpSave', Icons["grGcpSave"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["grGcpSave"].GetLabel(), Icons["grGcpSave"].GetDesc(),
-             self.parent.SaveGCPs),
-            (self.gcpReload, 'grGcpReload', Icons["grGcpReload"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["grGcpReload"].GetLabel(), Icons["grGcpReload"].GetDesc(), 
-             self.parent.ReloadGCPs),
-            ("", "", "", "", "", "", ""),
-            (self.gcpAdd, 'grGrGcpAdd', Icons["grGcpAdd"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["grGcpAdd"].GetLabel(), Icons["grGcpAdd"].GetDesc(),
-             self.parent.AddGCP),
-            (self.gcpDelete, 'grGrGcpDelete', Icons["grGcpDelete"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["grGcpDelete"].GetLabel(), Icons["grGcpDelete"].GetDesc(), 
-             self.parent.DeleteGCP),
-            (self.gcpClear, 'grGcpClear', Icons["grGcpClear"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["grGcpClear"].GetLabel(), Icons["grGcpClear"].GetDesc(), 
-             self.parent.ClearGCP),
-            ("", "", "", "", "", "", ""),
-            (self.rms, 'grGcpRms', Icons["grGcpRms"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["grGcpRms"].GetLabel(), Icons["grGcpRms"].GetDesc(),
-             self.parent.OnRMS),
-            (self.georect, 'grGeorect', Icons["grGeorect"].GetBitmap(), 
-             wx.ITEM_NORMAL, Icons["grGeorect"].GetLabel(), Icons["grGeorect"].GetDesc(),
-             self.parent.OnGeorect),
-            )
+        icons = Icons['georectify']
+        return self._getToolbarData(((self.gcpSave, 'gcpSave', icons["gcpSave"],
+                                      self.parent.SaveGCPs),
+                                     (self.gcpReload, 'gcpReload', icons["gcpReload"],
+                                      self.parent.ReloadGCPs),
+                                     (None, ),
+                                     (self.gcpAdd, 'gcpAdd', icons["gcpAdd"],
+                                      self.parent.AddGCP),
+                                     (self.gcpDelete, 'gcpDelete', icons["gcpDelete"],
+                                      self.parent.DeleteGCP),
+                                     (self.gcpClear, 'gcpClear', icons["gcpClear"],
+                                      self.parent.ClearGCP),
+                                     (None, ),
+                                     (self.rms, 'gcpRms', icons["gcpRms"],
+                                      self.parent.OnRMS),
+                                     (self.georect, 'georectify', icons["georectify"],
+                                      self.parent.OnGeorect))
+                                    )
     
 class GCPDisplayToolbar(AbstractToolbar):
     """
@@ -404,7 +408,7 @@
         """
         AbstractToolbar.__init__(self, parent)
         
-        self.InitToolbar(self.ToolbarData())
+        self.InitToolbar(self._toolbarData())
         
         # add tool to toggle active map window
         self.togglemapid = wx.NewId()
@@ -415,7 +419,7 @@
         self.InsertControl(10, self.togglemap)
 
         self.SetToolShortHelp(self.togglemapid, '%s %s %s' % (_('Set map canvas for '),
-                                                              Icons["zoom_back"].GetLabel(),
+                                                              Icons['displayWindow']["zoomBack"].GetLabel(),
                                                               _(' / Zoom to map')))
 
         # realize the toolbar
@@ -429,7 +433,7 @@
         
         self.EnableTool(self.zoomback, False)
         
-    def ToolbarData(self):
+    def _toolbarData(self):
         """!Toolbar data"""
         self.displaymap = wx.NewId()
         self.rendermap = wx.NewId()
@@ -445,198 +449,55 @@
         self.helpid = wx.NewId()
         self.quit = wx.NewId()
         
-        # tool, label, bitmap, kind, shortHelp, longHelp, handler
-        return (
-            (self.displaymap, "displaymap", Icons["displaymap"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["displaymap"].GetLabel(), Icons["displaymap"].GetDesc(),
-             self.parent.OnDraw),
-            (self.rendermap, "rendermap", Icons["rendermap"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["rendermap"].GetLabel(), Icons["rendermap"].GetDesc(),
-             self.parent.OnRender),
-            (self.erase, "erase", Icons["erase"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["erase"].GetLabel(), Icons["erase"].GetDesc(),
-             self.parent.OnErase),
-            ("", "", "", "", "", "", ""),
-            (self.gcpset, "grGcpSet", Icons["grGcpSet"].GetBitmap(),
-             wx.ITEM_RADIO, Icons["grGcpSet"].GetLabel(), Icons["grGcpSet"].GetDesc(),
-             self.parent.OnPointer),
-            (self.pan, "pan", Icons["pan"].GetBitmap(),
-             wx.ITEM_RADIO, Icons["pan"].GetLabel(), Icons["pan"].GetDesc(),
-             self.parent.OnPan),
-            (self.zoomin, "zoom_in", Icons["zoom_in"].GetBitmap(),
-             wx.ITEM_RADIO, Icons["zoom_in"].GetLabel(), Icons["zoom_in"].GetDesc(),
-             self.parent.OnZoomIn),
-            (self.zoomout, "zoom_out", Icons["zoom_out"].GetBitmap(),
-             wx.ITEM_RADIO, Icons["zoom_out"].GetLabel(), Icons["zoom_out"].GetDesc(),
-             self.parent.OnZoomOut),
-            (self.zoommenu, "zoommenu", Icons["zoommenu"].GetBitmap(),
-             wx.ITEM_NORMAL, _("Adjust display zoom"), Icons["zoommenu"].GetDesc(),
-             self.parent.OnZoomMenuGCP),
-            ("", "", "", "", "", "", ""),
-            (self.zoomback, "zoom_back", Icons["zoom_back"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["zoom_back"].GetLabel(), Icons["zoom_back"].GetDesc(),
-             self.parent.OnZoomBack),
-            (self.zoomtomap, "zoomtomap", Icons["zoom_extent"].GetBitmap(),
-             wx.ITEM_NORMAL, _("Zoom to map"), _("Zoom to displayed map"),
-             self.parent.OnZoomToMap),
-            ("", "", "", "", "", "", ""),
-            (self.settings, 'grSettings', Icons["grSettings"].GetBitmap(), 
-             wx.ITEM_NORMAL, Icons["grSettings"].GetLabel(), Icons["grSettings"].GetDesc(),
-             self.parent.OnSettings),
-            (self.helpid, 'grHelp', wx.ArtProvider.GetBitmap(id=wx.ART_HELP, client=wx.ART_TOOLBAR, size=globalvar.toolbarSize), 
-             wx.ITEM_NORMAL, _('Show Help'), _('Show Help for GCP Manager'),
-             self.parent.OnHelp),
-            ("", "", "", "", "", "", ""),
-            (self.quit, 'grGcpQuit', Icons["grGcpQuit"].GetBitmap(), 
-             wx.ITEM_NORMAL, Icons["grGcpQuit"].GetLabel(), Icons["grGcpQuit"].GetDesc(),
-             self.parent.OnQuit)
-            )
+        icons = Icons['displayWindow']
+        return self._getToolbarData(((self.displaymap, "display", icons["display"],
+                                      self.parent.OnDraw),
+                                     (self.rendermap, "render", icons["render"],
+                                      self.parent.OnRender),
+                                     (self.erase, "erase", icons["erase"],
+                                      self.parent.OnErase),
+                                     (None, ),
+                                     (self.gcpset, "gcpSet", Icons["georectify"]["gcpSet"],
+                                      self.parent.OnPointer),
+                                     (self.pan, "pan", icons["pan"],
+                                      self.parent.OnPan),
+                                     (self.zoomin, "zoomIn", icons["zoomIn"],
+                                      self.parent.OnZoomIn),
+                                     (self.zoomout, "zoomOut", icons["zoomOut"],
+                                      self.parent.OnZoomOut),
+                                     (self.zoommenu, "zoomMenu", icons["zoomMenu"],
+                                      self.parent.OnZoomMenuGCP),
+                                     (None, ),
+                                     (self.zoomback, "zoomBack", icons["zoomBack"],
+                                      self.parent.OnZoomBack),
+                                     (self.zoomtomap, "zoomtomap", icons["zoomExtent"],
+                                      self.parent.OnZoomToMap),
+                                     (None, ),
+                                     (self.settings, 'settings', Icons["georectify"]["settings"],
+                                      self.parent.OnSettings),
+                                     (self.helpid, 'help', Icons["misc"]["help"],
+                                      self.parent.OnHelp),
+                                     (None, ),
+                                     (self.quit, 'gcpQuit', Icons["georectify"]["quit"],
+                                      self.parent.OnQuit))
+                                    )
     
-class GRToolbar(AbstractToolbar):
-    """
-    Georectification toolbar
-    """
-    def __init__(self, parent, mapcontent):
-        """!
-        Georectification toolbar constructor
-
-        @param parent reference to MapFrame
-        @param mapcontent reference to render.Map (registred by MapFrame)
-        """
-        self.mapcontent = mapcontent
-        AbstractToolbar.__init__(self, parent)
-        
-        self.InitToolbar(self.ToolbarData())
-        
-        # realize the toolbar
-        self.Realize()
-        
-        self.action = { 'id' : self.gcpset }
-        self.defaultAction = { 'id' : self.gcpset,
-                               'bind' : self.parent.OnPointer }
-        
-        self.OnTool(None)
-        
-        self.EnableTool(self.zoomback, False)
-        
-    def ToolbarData(self):
-        """!Toolbar data"""
-        self.displaymap = wx.NewId()
-        self.rendermap = wx.NewId()
-        self.erase = wx.NewId()
-        self.gcpset = wx.NewId()
-        self.pan = wx.NewId()
-        self.zoomin = wx.NewId()
-        self.zoomout = wx.NewId()
-        self.zoomback = wx.NewId()
-        self.zoomtomap = wx.NewId()
-        
-        # tool, label, bitmap, kind, shortHelp, longHelp, handler
-        return (
-            (self.displaymap, "displaymap", Icons["displaymap"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["displaymap"].GetLabel(), Icons["displaymap"].GetDesc(),
-             self.parent.OnDraw),
-            (self.rendermap, "rendermap", Icons["rendermap"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["rendermap"].GetLabel(), Icons["rendermap"].GetDesc(),
-             self.parent.OnRender),
-            (self.erase, "erase", Icons["erase"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["erase"].GetLabel(), Icons["erase"].GetDesc(),
-             self.parent.OnErase),
-            ("", "", "", "", "", "", ""),
-            (self.gcpset, "grGcpSet", Icons["grGcpSet"].GetBitmap(),
-             wx.ITEM_RADIO, Icons["grGcpSet"].GetLabel(), Icons["grGcpSet"].GetDesc(),
-             self.parent.OnPointer),
-            (self.pan, "pan", Icons["pan"].GetBitmap(),
-             wx.ITEM_RADIO, Icons["pan"].GetLabel(), Icons["pan"].GetDesc(),
-             self.parent.OnPan),
-            (self.zoomin, "zoom_in", Icons["zoom_in"].GetBitmap(),
-             wx.ITEM_RADIO, Icons["zoom_in"].GetLabel(), Icons["zoom_in"].GetDesc(),
-             self.parent.OnZoomIn),
-            (self.zoomout, "zoom_out", Icons["zoom_out"].GetBitmap(),
-             wx.ITEM_RADIO, Icons["zoom_out"].GetLabel(), Icons["zoom_out"].GetDesc(),
-             self.parent.OnZoomOut),
-            (self.zoomback, "zoom_back", Icons["zoom_back"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["zoom_back"].GetLabel(), Icons["zoom_back"].GetDesc(),
-             self.parent.OnZoomBack),
-            (self.zoomtomap, "zoomtomap", Icons["zoommenu"].GetBitmap(),
-             wx.ITEM_NORMAL, _("Zoom to map"), _("Zoom to displayed map"),
-             self.OnZoomMap),
-            )
-    
     def OnZoomMap(self, event):
         """!Zoom to selected map"""
         self.parent.MapWindow.ZoomToMap(layers = self.mapcontent.GetListOfLayers())
         if event:
             event.Skip()
         
-class GCPToolbar(AbstractToolbar):
-    """!
-    Toolbar for managing ground control points during georectification
-
-    @param parent reference to GCP widget
-    """
-    def __init__(self, parent):
-        AbstractToolbar.__init__(self, parent)
-        
-        self.InitToolbar(self.ToolbarData())
-        
-        # realize the toolbar
-        self.Realize()
-
-    def ToolbarData(self):
-        self.gcpSave = wx.NewId()
-        self.gcpAdd = wx.NewId()
-        self.gcpDelete = wx.NewId()
-        self.gcpClear = wx.NewId()
-        self.gcpReload = wx.NewId()
-        self.rms = wx.NewId()
-        self.georect = wx.NewId()
-        self.settings = wx.NewId()
-        self.quit = wx.NewId()
-
-        return (
-            (self.gcpSave, 'grGcpSave', Icons["grGcpSave"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["grGcpSave"].GetLabel(), Icons["grGcpSave"].GetDesc(),
-             self.parent.SaveGCPs),
-            (self.gcpAdd, 'grGrGcpAdd', Icons["grGcpAdd"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["grGcpAdd"].GetLabel(), Icons["grGcpAdd"].GetDesc(),
-             self.parent.AddGCP),
-            (self.gcpDelete, 'grGrGcpDelete', Icons["grGcpDelete"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["grGcpDelete"].GetLabel(), Icons["grGcpDelete"].GetDesc(), 
-             self.parent.DeleteGCP),
-            (self.gcpClear, 'grGcpClear', Icons["grGcpClear"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["grGcpClear"].GetLabel(), Icons["grGcpClear"].GetDesc(), 
-             self.parent.ClearGCP),
-            (self.gcpReload, 'grGcpReload', Icons["grGcpReload"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["grGcpReload"].GetLabel(), Icons["grGcpReload"].GetDesc(), 
-             self.parent.ReloadGCPs),
-
-            ("", "", "", "", "", "", ""),
-            (self.rms, 'grGcpRms', Icons["grGcpRms"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["grGcpRms"].GetLabel(), Icons["grGcpRms"].GetDesc(),
-             self.parent.OnRMS),
-            (self.georect, 'grGeorect', Icons["grGeorect"].GetBitmap(), 
-             wx.ITEM_NORMAL, Icons["grGeorect"].GetLabel(), Icons["grGeorect"].GetDesc(),
-             self.parent.OnGeorect),
-            ("", "", "", "", "", "", ""),
-            (self.settings, 'grSettings', Icons["grSettings"].GetBitmap(), 
-             wx.ITEM_NORMAL, Icons["grSettings"].GetLabel(), Icons["grSettings"].GetDesc(),
-             self.parent.OnSettings),
-            (self.quit, 'grGcpQuit', Icons["grGcpQuit"].GetBitmap(), 
-             wx.ITEM_NORMAL, Icons["grGcpQuit"].GetLabel(), Icons["grGcpQuit"].GetDesc(),
-             self.parent.OnQuit)
-            )
-    
 class VDigitToolbar(AbstractToolbar):
+    """!Toolbar for digitization
     """
-    Toolbar for digitization
-    """
     def __init__(self, parent, mapcontent, layerTree = None, log = None):
         self.mapcontent    = mapcontent # Map class instance
         self.layerTree     = layerTree  # reference to layer tree associated to map display
         self.log           = log        # log area
         AbstractToolbar.__init__(self, parent)
-        
+        self.digit         = self.parent.MapWindow.digit
+
         # currently selected map layer for editing (reference to MapLayer instance)
         self.mapLayer = None
         # list of vector layers from Layer Manager (only in the current mapset)
@@ -648,7 +509,7 @@
         self.settingsDialog   = None
         
         # create toolbars (two rows optionally)
-        self.InitToolbar(self.ToolbarData())
+        self.InitToolbar(self._toolbarData())
         self.Bind(wx.EVT_TOOL, self.OnTool)
         
         # default action (digitize new point, line, etc.)
@@ -673,9 +534,8 @@
         
         self.FixSize(width = 105)
         
-    def ToolbarData(self):
-        """!
-        Toolbar data
+    def _toolbarData(self):
+        """!Toolbar data
         """
         data = []
         
@@ -683,6 +543,7 @@
         self.addLine = wx.NewId()
         self.addBoundary = wx.NewId()
         self.addCentroid = wx.NewId()
+        self.addArea = wx.NewId()
         self.moveVertex = wx.NewId()
         self.addVertex = wx.NewId()
         self.removeVertex = wx.NewId()
@@ -698,68 +559,63 @@
         self.settings = wx.NewId()
         self.exit = wx.NewId()
         
-        data = [("", "", "", "", "", "", ""),
-                (self.addPoint, "digAddPoint", Icons["digAddPoint"].GetBitmap(),
-                 wx.ITEM_CHECK, Icons["digAddPoint"].GetLabel(), Icons["digAddPoint"].GetDesc(),
-                 self.OnAddPoint),
-                (self.addLine, "digAddLine", Icons["digAddLine"].GetBitmap(),
-                 wx.ITEM_CHECK, Icons["digAddLine"].GetLabel(), Icons["digAddLine"].GetDesc(),
-                 self.OnAddLine),
-                (self.addBoundary, "digAddBoundary", Icons["digAddBoundary"].GetBitmap(),
-                 wx.ITEM_CHECK, Icons["digAddBoundary"].GetLabel(), Icons["digAddBoundary"].GetDesc(),
-                 self.OnAddBoundary),
-                (self.addCentroid, "digAddCentroid", Icons["digAddCentroid"].GetBitmap(),
-                 wx.ITEM_CHECK, Icons["digAddCentroid"].GetLabel(), Icons["digAddCentroid"].GetDesc(),
-                 self.OnAddCentroid),
-                (self.moveVertex, "digMoveVertex", Icons["digMoveVertex"].GetBitmap(),
-                 wx.ITEM_CHECK, Icons["digMoveVertex"].GetLabel(), Icons["digMoveVertex"].GetDesc(),
-                 self.OnMoveVertex),
-                (self.addVertex, "digAddVertex", Icons["digAddVertex"].GetBitmap(),
-                 wx.ITEM_CHECK, Icons["digAddVertex"].GetLabel(), Icons["digAddVertex"].GetDesc(),
-                 self.OnAddVertex),
-                (self.removeVertex, "digRemoveVertex", Icons["digRemoveVertex"].GetBitmap(),
-                 wx.ITEM_CHECK, Icons["digRemoveVertex"].GetLabel(), Icons["digRemoveVertex"].GetDesc(),
-                 self.OnRemoveVertex),
-                (self.splitLine, "digSplitLine", Icons["digSplitLine"].GetBitmap(),
-                 wx.ITEM_CHECK, Icons["digSplitLine"].GetLabel(), Icons["digSplitLine"].GetDesc(),
-                 self.OnSplitLine),
-                (self.editLine, "digEditLine", Icons["digEditLine"].GetBitmap(),
-                 wx.ITEM_CHECK, Icons["digEditLine"].GetLabel(), Icons["digEditLine"].GetDesc(),
-                 self.OnEditLine),
-                (self.moveLine, "digMoveLine", Icons["digMoveLine"].GetBitmap(),
-                 wx.ITEM_CHECK, Icons["digMoveLine"].GetLabel(), Icons["digMoveLine"].GetDesc(),
-                 self.OnMoveLine),
-                (self.deleteLine, "digDeleteLine", Icons["digDeleteLine"].GetBitmap(),
-                 wx.ITEM_CHECK, Icons["digDeleteLine"].GetLabel(), Icons["digDeleteLine"].GetDesc(),
-                 self.OnDeleteLine),
-                (self.displayCats, "digDispCats", Icons["digDispCats"].GetBitmap(),
-                 wx.ITEM_CHECK, Icons["digDispCats"].GetLabel(), Icons["digDispCats"].GetDesc(),
-                 self.OnDisplayCats),
-                (self.copyCats, "digCopyCats", Icons["digCopyCats"].GetBitmap(),
-                 wx.ITEM_CHECK, Icons["digCopyCats"].GetLabel(), Icons["digCopyCats"].GetDesc(),
-                 self.OnCopyCA),
-                (self.displayAttr, "digDispAttr", Icons["digDispAttr"].GetBitmap(),
-                 wx.ITEM_CHECK, Icons["digDispAttr"].GetLabel(), Icons["digDispAttr"].GetDesc(),
-                 self.OnDisplayAttr),
-                (self.additionalTools, "digAdditionalTools", Icons["digAdditionalTools"].GetBitmap(),
-                 wx.ITEM_CHECK, Icons["digAdditionalTools"].GetLabel(),
-                 Icons["digAdditionalTools"].GetDesc(),
-                 self.OnAdditionalToolMenu),
-                ("", "", "", "", "", "", ""),
-                (self.undo, "digUndo", Icons["digUndo"].GetBitmap(),
-                 wx.ITEM_NORMAL, Icons["digUndo"].GetLabel(), Icons["digUndo"].GetDesc(),
-                 self.OnUndo),
-                # data.append((self.undo, "digRedo", Icons["digRedo"].GetBitmap(),
-                #             wx.ITEM_NORMAL, Icons["digRedo"].GetLabel(), Icons["digRedo"].GetDesc(),
-                #             self.OnRedo))
-                (self.settings, "digSettings", Icons["digSettings"].GetBitmap(),
-                 wx.ITEM_NORMAL, Icons["digSettings"].GetLabel(), Icons["digSettings"].GetDesc(),
-                 self.OnSettings),
-                (self.exit, "digExit", Icons["quit"].GetBitmap(),
-                 wx.ITEM_NORMAL, Icons["digExit"].GetLabel(), Icons["digExit"].GetDesc(),
-                 self.OnExit)]
-        
-        return data
+        icons = Icons['vdigit']
+        return self._getToolbarData(((None, ),
+                                     (self.addPoint, "addPoint", icons["addPoint"],
+                                      self.OnAddPoint),
+                                     (self.addLine, "addLine", icons["addLine"],
+                                      self.OnAddLine,
+                                      wx.ITEM_CHECK),
+                                     (self.addBoundary, "addBoundary", icons["addBoundary"],
+                                      self.OnAddBoundary,
+                                      wx.ITEM_CHECK),
+                                     (self.addCentroid, "addCentroid", icons["addCentroid"],
+                                      self.OnAddCentroid,
+                                      wx.ITEM_CHECK),
+                                     (self.addArea, "addArea", icons["addArea"],
+                                      self.OnAddArea,
+                                      wx.ITEM_CHECK),
+                                     (self.moveVertex, "moveVertex", icons["moveVertex"],
+                                      self.OnMoveVertex,
+                                      wx.ITEM_CHECK),
+                                     (self.addVertex, "addVertex", icons["addVertex"],
+                                      self.OnAddVertex,
+                                      wx.ITEM_CHECK),
+                                     (self.removeVertex, "removeVertex", icons["removeVertex"],
+                                      self.OnRemoveVertex,
+                                      wx.ITEM_CHECK),
+                                     (self.splitLine, "splitLine", icons["splitLine"],
+                                      self.OnSplitLine,
+                                      wx.ITEM_CHECK),
+                                     (self.editLine, "editLine", icons["editLine"],
+                                      self.OnEditLine,
+                                      wx.ITEM_CHECK),
+                                     (self.moveLine, "moveLine", icons["moveLine"],
+                                      self.OnMoveLine,
+                                      wx.ITEM_CHECK),
+                                     (self.deleteLine, "deleteLine", icons["deleteLine"],
+                                      self.OnDeleteLine,
+                                      wx.ITEM_CHECK),
+                                     (self.displayCats, "displayCats", icons["displayCats"],
+                                      self.OnDisplayCats,
+                                      wx.ITEM_CHECK),
+                                     (self.copyCats, "copyCats", icons["copyCats"],
+                                      self.OnCopyCA,
+                                      wx.ITEM_CHECK),
+                                     (self.displayAttr, "displayAttr", icons["displayAttr"],
+                                      self.OnDisplayAttr,
+                                      wx.ITEM_CHECK),
+                                     (self.additionalTools, "additionalTools", icons["additionalTools"],
+                                      self.OnAdditionalToolMenu,
+                                      wx.ITEM_CHECK),                                      
+                                     (None, ),
+                                     (self.undo, "undo", icons["undo"],
+                                      self.OnUndo),
+                                     (self.settings, "settings", icons["settings"],
+                                      self.OnSettings),
+                                     (self.exit, "quit", icons["quit"],
+                                      self.OnExit))
+                                    )
     
     def OnTool(self, event):
         """!Tool selected -> disable selected tool in map toolbar"""
@@ -790,8 +646,8 @@
         # clear tmp canvas
         if self.action['id'] != id:
             self.parent.MapWindow.ClearLines(pdc = self.parent.MapWindow.pdcTmp)
-            if self.parent.digit and \
-                    len(self.parent.digit.driver.GetSelected()) > 0:
+            if self.parent.MapWindow.digit and \
+                    len(self.parent.MapWindow.digit.GetDisplay().GetSelected()) > 0:
                 # cancel action
                 self.parent.MapWindow.OnMiddleDown(None)
         
@@ -834,6 +690,14 @@
                         'id'   : self.addCentroid }
         self.parent.MapWindow.mouse['box'] = 'point'
 
+    def OnAddArea(self, event):
+        """!Add area to the vector map layer"""
+        Debug.msg (2, "VDigitToolbar.OnAddCentroid()")
+        self.action = { 'desc' : "addLine",
+                        'type' : "area",
+                        'id'   : self.addArea }
+        self.parent.MapWindow.mouse['box'] = 'line'
+
     def OnExit (self, event=None):
         """!Quit digitization tool"""
         # stop editing of the currently selected map layer
@@ -971,7 +835,7 @@
         
     def OnUndo(self, event):
         """!Undo previous changes"""
-        self.parent.digit.Undo()
+        self.digit.Undo()
         
         event.Skip()
 
@@ -989,13 +853,11 @@
         
     def OnSettings(self, event):
         """!Show settings dialog"""
-        if self.parent.digit is None:
-            reload(vdigit)
-            from vdigit import VDigit as VDigit
+        if self.digit is None:
             try:
-                self.parent.digit = VDigit(mapwindow=self.parent.MapWindow)
+                self.digit = self.parent.MapWindow.digit = VDigit(mapwindow = self.parent.MapWindow)
             except SystemExit:
-                self.parent.digit = None
+                self.digit = self.parent.MapWindow.digit = None
         
         if not self.settingsDialog:
             self.settingsDialog = VDigitSettingsDialog(parent = self.parent, title = _("Digitization settings"),
@@ -1181,10 +1043,9 @@
 
     def OnZBulk(self, event):
         """!Z bulk-labeling selected lines/boundaries"""
-        if not self.parent.digit.driver.Is3D():
-            wx.MessageBox(parent = self.parent,
-                          message = _("Vector map is not 3D. Operation canceled."),
-                          caption = _("Error"), style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
+        if not self.digit.IsVector3D():
+            gcmd.GError(parent = self.parent,
+                        message = _("Vector map is not 3D. Operation canceled."))
             return
         
         if self.action['desc'] == 'zbulkLine': # select previous action
@@ -1272,11 +1133,14 @@
     def StartEditing (self, mapLayer):
         """!Start editing selected vector map layer.
         
-        @param mapLayer reference to MapLayer instance
+        @param mapLayer MapLayer to be edited
         """
         # deactive layer
         self.mapcontent.ChangeLayerActive(mapLayer, False)
         
+        # clean map canvas
+        self.parent.MapWindow.EraseMap()
+        
         # unset background map if needed
         if mapLayer:
             if UserSettings.Get(group = 'vdigit', key = 'bgmap',
@@ -1285,35 +1149,26 @@
                                  subkey = 'value', value = '', internal = True)
             
             self.parent.statusbar.SetStatusText(_("Please wait, "
-                                                  "opening vector map <%s> for editing...") % \
-                                                    mapLayer.GetName(),
+                                                  "opening vector map <%s> for editing...") % mapLayer.GetName(),
                                                 0)
         
-        # reload vdigit module
-        reload(vdigit)
-        from vdigit import VDigit as VDigit
-        # use vdigit's PseudoDC
-        self.parent.MapWindow.DefinePseudoDC(vdigit = True)
-        self.parent.digit = VDigit(mapwindow = self.parent.MapWindow)
+        self.parent.MapWindow.pdcVector = wx.PseudoDC()
+        self.digit = self.parent.MapWindow.digit = VDigit(mapwindow = self.parent.MapWindow)
         
         self.mapLayer = mapLayer
         
         # open vector map
-        try:
-            if not self.parent.MapWindow.CheckPseudoDC():
-                raise gcmd.GException(_("Unable to initialize display driver of vector "
-                                        "digitizer. See 'Command output' for details."))
-            self.parent.digit.SetMapName(mapLayer.GetName())
-        except gcmd.GException, e:
+        if self.digit.OpenMap(mapLayer.GetName()) is None:
             self.mapLayer = None
             self.StopEditing()
-            gcmd.GError(parent = self.parent,
-                        message = str(e))
             return False
         
         # update toolbar
         self.combo.SetValue(mapLayer.GetName())
         self.parent.toolbars['map'].combo.SetValue (_('Digitize'))
+        lmgr = self.parent.GetLayerManager()
+        if lmgr:
+            lmgr.toolbar.Enable('vdigit', enable = False)
         
         Debug.msg (4, "VDigitToolbar.StartEditing(): layer=%s" % mapLayer.GetName())
         
@@ -1321,17 +1176,13 @@
         if self.parent.MapWindow.mouse['use'] == 'pointer':
             self.parent.MapWindow.SetCursor(self.parent.cursors["cross"])
         
-        # create pseudoDC for drawing the map
-        self.parent.MapWindow.pdcVector = vdigit.PseudoDC()
-        self.parent.digit.driver.SetDevice(self.parent.MapWindow.pdcVector)
-        
         if not self.parent.MapWindow.resize:
             self.parent.MapWindow.UpdateMap(render = True)
         
         opacity = mapLayer.GetOpacity(float = True)
         if opacity < 1.0:
             alpha = int(opacity * 255)
-            self.parent.digit.driver.UpdateSettings(alpha)
+            self.digit.UpdateSettings(alpha)
         
         return True
 
@@ -1341,16 +1192,13 @@
         @return True on success
         @return False on failure
         """
-        # use wx's PseudoDC
-        self.parent.MapWindow.DefinePseudoDC(vdigit = False)
-        
         self.combo.SetValue (_('Select vector map'))
         
         # save changes
         if self.mapLayer:
             Debug.msg (4, "VDigitToolbar.StopEditing(): layer=%s" % self.mapLayer.GetName())
             if UserSettings.Get(group = 'vdigit', key = 'saveOnExit', subkey = 'enabled') is False:
-                if self.parent.digit.GetUndoLevel() > -1:
+                if self.digit.GetUndoLevel() > -1:
                     dlg = wx.MessageDialog(parent = self.parent,
                                            message = _("Do you want to save changes "
                                                      "in vector map <%s>?") % self.mapLayer.GetName(),
@@ -1358,16 +1206,22 @@
                                            style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
                     if dlg.ShowModal() == wx.ID_NO:
                         # revert changes
-                        self.parent.digit.Undo(0)
+                        self.digit.Undo(0)
                     dlg.Destroy()
             
             self.parent.statusbar.SetStatusText(_("Please wait, "
                                                   "closing and rebuilding topology of "
                                                   "vector map <%s>...") % self.mapLayer.GetName(),
                                                 0)
-        
-            self.parent.digit.SetMapName(None) # -> close map
-        
+            lmgr = self.parent.GetLayerManager()
+            if lmgr:
+                lmgr.toolbar.Enable('vdigit', enable = True)
+                lmgr.notebook.SetSelection(1)
+            self.digit.CloseMap()
+            if lmgr:
+                lmgr.GetLogWindow().GetProgressBar().SetValue(0)
+                lmgr.GetLogWindow().WriteCmdLog(_("Editing of vector map <%s> successfully finished") % \
+                                                    self.mapLayer.GetName())
             # re-active layer 
             item = self.parent.tree.FindItemByData('maplayer', self.mapLayer)
             if item and self.parent.tree.IsItemChecked(item):
@@ -1375,10 +1229,7 @@
         
         # change cursor
         self.parent.MapWindow.SetCursor(self.parent.cursors["default"])
-        
-        # disable pseudodc for vector map layer
         self.parent.MapWindow.pdcVector = None
-        self.parent.digit.driver.SetDevice(None)
         
         # close dialogs
         for dialog in ('attributes', 'category'):
@@ -1386,8 +1237,8 @@
                 self.parent.dialogs[dialog].Close()
                 self.parent.dialogs[dialog] = None
         
-        self.parent.digit.__del__() # FIXME: destructor is not called here (del)
-        self.parent.digit = None
+        self.digit.__del__() # FIXME: destructor is not called here (del)
+        self.digit = self.parent.MapWindow.digit = None
         
         self.mapLayer = None
         
@@ -1447,12 +1298,12 @@
     def __init__(self, parent):
         AbstractToolbar.__init__(self, parent)
         
-        self.InitToolbar(self.ToolbarData())
+        self.InitToolbar(self._toolbarData())
         
         # realize the toolbar
         self.Realize()
         
-    def ToolbarData(self):
+    def _toolbarData(self):
         """!Toolbar data"""
         self.transect = wx.NewId()
         self.addraster = wx.NewId()
@@ -1467,48 +1318,35 @@
         self.printer = wx.NewId()
         self.quit = wx.NewId()
                 
-        # tool, label, bitmap, kind, shortHelp, longHelp, handler
-        return   (
-            (self.addraster, 'raster', Icons["addrast"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["addrast"].GetLabel(), Icons["addrast"].GetDesc(),
-             self.parent.OnSelectRaster),
-            (self.transect, 'transect', Icons["transect"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["transect"].GetLabel(), Icons["transect"].GetDesc(),
-             self.parent.OnDrawTransect),
-            ("", "", "", "", "", "", ""),
-            (self.draw, 'profiledraw', Icons["profiledraw"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["profiledraw"].GetLabel(), Icons["profiledraw"].GetDesc(),
-             self.parent.OnCreateProfile),
-            (self.erase, 'erase', Icons["erase"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["erase"].GetLabel(), Icons["erase"].GetDesc(),
-             self.parent.OnErase),
-            (self.drag, 'drag', Icons['pan'].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["pan"].GetLabel(), Icons["pan"].GetDesc(),
-             self.parent.OnDrag),
-            (self.zoom, 'zoom', Icons['zoom_in'].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["zoom_in"].GetLabel(), Icons["zoom_in"].GetDesc(),
-             self.parent.OnZoom),
-            (self.unzoom, 'unzoom', Icons['zoom_back'].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["zoom_back"].GetLabel(), Icons["zoom_back"].GetDesc(),
-             self.parent.OnRedraw),
-            ("", "", "", "", "", "", ""),
-            (self.datasave, 'save data', Icons["datasave"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["datasave"].GetLabel(), Icons["datasave"].GetDesc(),
-             self.parent.SaveProfileToFile),
-            (self.save, 'save image', Icons["savefile"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["savefile"].GetLabel(), Icons["savefile"].GetDesc(),
-             self.parent.SaveToFile),
-            (self.printer, 'print', Icons["printmap"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["printmap"].GetLabel(), Icons["printmap"].GetDesc(),
-             self.parent.PrintMenu),
-            ("", "", "", "", "", "", ""),
-            (self.options, 'options', Icons["profileopt"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["profileopt"].GetLabel(), Icons["profileopt"].GetDesc(),
-             self.parent.ProfileOptionsMenu),
-            (self.quit, 'quit', Icons["quit"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["quit"].GetLabel(), Icons["quit"].GetDesc(),
-             self.parent.OnQuit),
-            )
+        icons = Icons['profile']
+        return self._getToolbarData(((self.addraster, 'raster', Icons['layerManager']["addRast"],
+                                      self.parent.OnSelectRaster),
+                                     (self.transect, 'transect', icons["transect"],
+                                      self.parent.OnDrawTransect),
+                                     (None, ),
+                                     (self.draw, 'draw', icons["draw"],
+                                      self.parent.OnCreateProfile),
+                                     (self.erase, 'erase', Icons['displayWindow']["erase"],
+                                      self.parent.OnErase),
+                                     (self.drag, 'drag', Icons['displayWindow']['pan'],
+                                      self.parent.OnDrag),
+                                     (self.zoom, 'zoom', Icons['displayWindow']['zoomIn'],
+                                      self.parent.OnZoom),
+                                     (self.unzoom, 'unzoom', Icons['displayWindow']['zoomBack'],
+                                      self.parent.OnRedraw),
+                                     (None, ),
+                                     (self.datasave, 'save', icons["save"],
+                                      self.parent.SaveProfileToFile),
+                                     (self.save, 'image', Icons['displayWindow']["saveFile"],
+                                      self.parent.SaveToFile),
+                                     (self.printer, 'print', Icons['displayWindow']["print"],
+                                      self.parent.PrintMenu),
+                                     (None, ),
+                                     (self.options, 'options', icons["options"],
+                                      self.parent.ProfileOptionsMenu),
+                                     (self.quit, 'quit', icons["quit"],
+                                      self.parent.OnQuit),
+                                     ))
     
 class NvizToolbar(AbstractToolbar):
     """!Nviz toolbar
@@ -1522,12 +1360,12 @@
         # only one dialog can be open
         self.settingsDialog   = None
         
-        self.InitToolbar(self.ToolbarData())
+        self.InitToolbar(self._toolbarData())
         
         # realize the toolbar
         self.Realize()
         
-    def ToolbarData(self):
+    def _toolbarData(self):
         """!Toolbar data"""
         self.view = wx.NewId()
         self.surface = wx.NewId()
@@ -1539,40 +1377,30 @@
         self.help = wx.NewId()
         self.quit = wx.NewId()
         
-        # tool, label, bitmap, kind, shortHelp, longHelp, handler
-        return   (
-            (self.view, "view", Icons["nvizView"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["nvizView"].GetLabel(), Icons["nvizView"].GetDesc(),
-             self.OnShowPage),
-            ("", "", "", "", "", "", ""),
-            (self.surface, "surface", Icons["nvizSurface"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["nvizSurface"].GetLabel(), Icons["nvizSurface"].GetDesc(),
-             self.OnShowPage),
-            (self.vector, "vector", Icons["nvizVector"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["nvizVector"].GetLabel(), Icons["nvizVector"].GetDesc(),
-             self.OnShowPage),
-            (self.volume, "volume", Icons["nvizVolume"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["nvizVolume"].GetLabel(), Icons["nvizVolume"].GetDesc(),
-             self.OnShowPage),
-            ("", "", "", "", "", "", ""),
-            (self.light, "light", Icons["nvizLight"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["nvizLight"].GetLabel(), Icons["nvizLight"].GetDesc(),
-             self.OnShowPage),
-            (self.fringe, "fringe", Icons["nvizFringe"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["nvizFringe"].GetLabel(), Icons["nvizFringe"].GetDesc(),
-             self.OnShowPage),
-            ("", "", "", "", "", "", ""),
-            (self.settings, "settings", Icons["nvizSettings"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["nvizSettings"].GetLabel(), Icons["nvizSettings"].GetDesc(),
-             self.OnSettings),
-            (self.help, "help", Icons["nvizHelp"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["nvizHelp"].GetLabel(), Icons["nvizHelp"].GetDesc(),
-             self.OnHelp),
-            ("", "", "", "", "", "", ""),
-            (self.quit, 'quit', Icons["nvizQuit"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["nvizQuit"].GetLabel(), Icons["nvizQuit"].GetDesc(),
-             self.OnExit),
-            )
+        icons = Icons['nviz']
+        return self._getToolbarData(((self.view, "view", icons["view"],
+                                      self.OnShowPage),
+                                     (None, ),
+                                     (self.surface, "surface", icons["surface"],
+                                      self.OnShowPage),
+                                     (self.vector, "vector", icons["vector"],
+                                      self.OnShowPage),
+                                     (self.volume, "volume", icons["volume"],
+                                      self.OnShowPage),
+                                     (None, ),
+                                     (self.light, "light", icons["light"],
+                                      self.OnShowPage),
+                                     (self.fringe, "fringe", icons["fringe"],
+                                      self.OnShowPage),
+                                     (None, ),
+                                     (self.settings, "settings", icons["settings"],
+                                      self.OnSettings),
+                                     (self.help, "help", Icons['misc']["help"],
+                                      self.OnHelp),
+                                     (None, ),
+                                     (self.quit, 'quit', icons["quit"],
+                                      self.OnExit))
+                                    )
     
     def OnShowPage(self, event):
         """!Go to the selected page"""
@@ -1622,6 +1450,9 @@
         self.parent.MapWindow.mouse['box'] = "point"
         self.parent.MapWindow.polycoords = []
         
+        # return to map layer page (gets rid of ugly exit bug)
+        self.lmgr.notebook.SetSelection(0)
+
         # disable the toolbar
         self.parent.RemoveToolbar("nviz")
         
@@ -1631,12 +1462,12 @@
     def __init__(self, parent):
         AbstractToolbar.__init__(self, parent)
         
-        self.InitToolbar(self.ToolbarData())
+        self.InitToolbar(self._toolbarData())
         
         # realize the toolbar
         self.Realize()
         
-    def ToolbarData(self):
+    def _toolbarData(self):
         """!Toolbar data"""
         self.new = wx.NewId()
         self.open = wx.NewId()
@@ -1654,58 +1485,42 @@
         self.redraw = wx.NewId()
         self.help = wx.NewId()
         
-        # tool, label, bitmap, kind, shortHelp, longHelp, handler
-        return (
-            (self.new, 'new', Icons['modelNew'].GetBitmap(),
-             wx.ITEM_NORMAL, Icons['modelNew'].GetLabel(), Icons['modelNew'].GetDesc(),
-             self.parent.OnModelNew),
-            (self.open, 'open', Icons['modelOpen'].GetBitmap(),
-             wx.ITEM_NORMAL, Icons['modelOpen'].GetLabel(), Icons['modelOpen'].GetDesc(),
-             self.parent.OnModelOpen),
-            (self.save, 'save', Icons['modelSave'].GetBitmap(),
-             wx.ITEM_NORMAL, Icons['modelSave'].GetLabel(), Icons['modelSave'].GetDesc(),
-             self.parent.OnModelSave),
-            (self.image, 'image', Icons['modelToImage'].GetBitmap(),
-             wx.ITEM_NORMAL, Icons['modelToImage'].GetLabel(), Icons['modelToImage'].GetDesc(),
-             self.parent.OnExportImage),
-            (self.python, 'python', Icons['modelToPython'].GetBitmap(),
-             wx.ITEM_NORMAL, Icons['modelToPython'].GetLabel(), Icons['modelToPython'].GetDesc(),
-             self.parent.OnExportPython),
-            ('', '', '', '', '', '', ''),
-            (self.action, 'action', Icons['modelActionAdd'].GetBitmap(),
-             wx.ITEM_NORMAL, Icons['modelActionAdd'].GetLabel(), Icons['modelActionAdd'].GetDesc(),
-             self.parent.OnAddAction),
-            (self.data, 'data', Icons['modelDataAdd'].GetBitmap(),
-             wx.ITEM_NORMAL, Icons['modelDataAdd'].GetLabel(), Icons['modelDataAdd'].GetDesc(),
-             self.parent.OnAddData),
-            (self.relation, 'relation', Icons['modelRelation'].GetBitmap(),
-             wx.ITEM_NORMAL, Icons['modelRelation'].GetLabel(), Icons['modelRelation'].GetDesc(),
-             self.parent.OnDefineRelation),
-            ('', '', '', '', '', '', ''),
-            (self.redraw, 'redraw', Icons['modelRedraw'].GetBitmap(),
-             wx.ITEM_NORMAL, Icons['modelRedraw'].GetLabel(), Icons['modelRedraw'].GetDesc(),
-             self.parent.OnCanvasRefresh),
-            (self.validate, 'validate', Icons['modelValidate'].GetBitmap(),
-             wx.ITEM_NORMAL, Icons['modelValidate'].GetLabel(), Icons['modelValidate'].GetDesc(),
-             self.parent.OnValidateModel),
-            (self.run, 'run', Icons['modelRun'].GetBitmap(),
-             wx.ITEM_NORMAL, Icons['modelRun'].GetLabel(), Icons['modelRun'].GetDesc(),
-             self.parent.OnRunModel),
-            ('', '', '', '', '', '', ''),
-            (self.variables, "variables", Icons["modelVariables"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["modelVariables"].GetLabel(), Icons["modelVariables"].GetDesc(),
-             self.parent.OnVariables),
-            (self.settings, "settings", Icons["modelSettings"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["modelSettings"].GetLabel(), Icons["modelSettings"].GetDesc(),
-             self.parent.OnPreferences),
-            (self.help, "help", Icons["modelHelp"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["modelHelp"].GetLabel(), Icons["modelHelp"].GetDesc(),
-             self.parent.OnHelp),
-            ('', '', '', '', '', '', ''),
-            (self.quit, 'quit', Icons['quit'].GetBitmap(),
-             wx.ITEM_NORMAL, Icons['quit'].GetLabel(), Icons['quit'].GetDesc(),
-             self.parent.OnCloseWindow),
-            )
+        icons = Icons['modeler']
+        return self._getToolbarData(((self.new, 'new', icons['new'],
+                                      self.parent.OnModelNew),
+                                     (self.open, 'open', icons['open'],
+                                      self.parent.OnModelOpen),
+                                     (self.save, 'save', icons['save'],
+                                      self.parent.OnModelSave),
+                                     (self.image, 'image', icons['toImage'],
+                                      self.parent.OnExportImage),
+                                     (self.python, 'python', icons['toPython'],
+                                      self.parent.OnExportPython),
+                                     (None, ),
+                                     (self.action, 'action', icons['actionAdd'],
+                                      self.parent.OnAddAction),
+                                     (self.data, 'data', icons['dataAdd'],
+                                      self.parent.OnAddData),
+                                     (self.relation, 'relation', icons['relation'],
+                                      self.parent.OnDefineRelation),
+                                     (None, ),
+                                     (self.redraw, 'redraw', icons['redraw'],
+                                      self.parent.OnCanvasRefresh),
+                                     (self.validate, 'validate', icons['validate'],
+                                      self.parent.OnValidateModel),
+                                     (self.run, 'run', icons['run'],
+                                      self.parent.OnRunModel),
+                                     (None, ),
+                                     (self.variables, "variables", icons['variables'],
+                                      self.parent.OnVariables),
+                                     (self.settings, "settings", icons['settings'],
+                                      self.parent.OnPreferences),
+                                     (self.help, "help", Icons['misc']['help'],
+                                      self.parent.OnHelp),
+                                     (None, ),
+                                     (self.quit, 'quit', icons['quit'],
+                                      self.parent.OnCloseWindow))
+                                    )
     
 class HistogramToolbar(AbstractToolbar):
     """!Histogram toolbar (see histogram.py)
@@ -1713,12 +1528,12 @@
     def __init__(self, parent):
         AbstractToolbar.__init__(self, parent)
         
-        self.InitToolbar(self.ToolbarData())
+        self.InitToolbar(self._toolbarData())
         
         # realize the toolbar
         self.Realize()
         
-    def ToolbarData(self):
+    def _toolbarData(self):
         """!Toolbar data"""
         self.histogram = wx.NewId()
         self.rendermap = wx.NewId()
@@ -1728,32 +1543,24 @@
         self.hprint = wx.NewId()
         self.quit = wx.NewId()
         
-        # tool, label, bitmap, kind, shortHelp, longHelp, handler
-        return (
-            (self.histogram, 'histogram', Icons["histogram"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["histogram"].GetLabel(), Icons["histogram"].GetDesc(),
-             self.parent.OnOptions),
-            (self.rendermap, 'rendermap', Icons["displaymap"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["displaymap"].GetLabel(), Icons["displaymap"].GetDesc(),
-             self.parent.OnRender),
-            (self.erase, 'erase', Icons["erase"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["erase"].GetLabel(), Icons["erase"].GetDesc(),
-             self.parent.OnErase),
-            (self.font, 'font', Icons["font"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["font"].GetLabel(), Icons["font"].GetDesc(),
-             self.parent.SetHistFont),
-            ('', '', '', '', '', '', ''),
-            (self.save, 'save', Icons["savefile"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["savefile"].GetLabel(), Icons["savefile"].GetDesc(),
-             self.parent.SaveToFile),
-            (self.hprint, 'print', Icons["printmap"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["printmap"].GetLabel(), Icons["printmap"].GetDesc(),
-             self.parent.PrintMenu),
-            ('', '', '', '', '', '', ''),
-            (self.quit, 'quit', Icons["quit"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["quit"].GetLabel(), Icons["quit"].GetDesc(),
-             self.parent.OnQuit)
-            )
+        icons = Icons['displayWindow']
+        return self._getToolbarData(((self.histogram, 'histogram', icons["histogram"],
+                                      self.parent.OnOptions),
+                                     (self.rendermap, 'render', icons["display"],
+                                      self.parent.OnRender),
+                                     (self.erase, 'erase', icons["erase"],
+                                      self.parent.OnErase),
+                                     (self.font, 'font', Icons['misc']["font"],
+                                      self.parent.SetHistFont),
+                                     (None, ),
+                                     (self.save, 'save', icons["saveFile"],
+                                      self.parent.SaveToFile),
+                                     (self.hprint, 'print', icons["print"],
+                                      self.parent.PrintMenu),
+                                     (None, ),
+                                     (self.quit, 'quit', Icons['misc']["quit"],
+                                      self.parent.OnQuit))
+                                    )
 
 class LayerManagerToolbar(AbstractToolbar):
     """!Layer Manager toolbar (see wxgui.py)
@@ -1761,13 +1568,14 @@
     def __init__(self, parent):
         AbstractToolbar.__init__(self, parent)
         
-        self.InitToolbar(self.ToolbarData())
+        self.InitToolbar(self._toolbarData())
         
         # realize the toolbar
         self.Realize()
 
-    def ToolbarData(self):
-        """!Toolbar data"""
+    def _toolbarData(self):
+        """!Toolbar data
+        """
         self.newdisplay = wx.NewId()
         self.workspaceLoad = wx.NewId()
         self.workspaceOpen = wx.NewId()
@@ -1780,56 +1588,28 @@
         self.addovl = wx.NewId()
         self.delcmd = wx.NewId()
         self.attribute = wx.NewId()
+        self.vdigit = wx.NewId()
         self.preferences = wx.NewId()
         self.modeler = wx.NewId() 
         
-        # tool, label, bitmap, kind, shortHelp, longHelp, handler
-        return (
-            (self.newdisplay, 'newdisplay', Icons["newdisplay"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["newdisplay"].GetLabel(), Icons["newdisplay"].GetDesc(),
-             self.parent.OnNewDisplay),
-            ('', '', '', '', '', '', ''),
-            (self.workspaceLoad, 'workspaceLoad', Icons["workspaceLoad"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["workspaceLoad"].GetLabel(), Icons["workspaceLoad"].GetDesc(),
-             self.parent.OnWorkspace),
-            (self.workspaceOpen, 'workspaceOpen', Icons["workspaceOpen"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["workspaceOpen"].GetLabel(), Icons["workspaceOpen"].GetDesc(),
-             self.parent.OnWorkspaceOpen),
-            (self.workspaceSave, 'workspaceSave', Icons["workspaceSave"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["workspaceSave"].GetLabel(), Icons["workspaceSave"].GetDesc(),
-             self.parent.OnWorkspaceSave),
-            ('', '', '', '', '', '', ''),
-            (self.addrast, 'addrast', Icons["addrast"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["addrast"].GetLabel(), Icons["addrast"].GetDesc(),
-             self.parent.OnAddRaster),
-            (self.rastmisc, 'rastmisc', Icons["rastmisc"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["rastmisc"].GetLabel(), Icons["rastmisc"].GetDesc(),
-             self.parent.OnAddRasterMisc),
-            (self.addvect, 'addvect', Icons["addvect"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["addvect"].GetLabel(), Icons["addvect"].GetDesc(),
-             self.parent.OnAddVector),
-            (self.vectmisc, 'vectmisc', Icons["vectmisc"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["vectmisc"].GetLabel(), Icons["vectmisc"].GetDesc(),
-             self.parent.OnAddVectorMisc),
-            (self.addgrp, 'addgrp',  Icons["addgrp"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["addgrp"].GetLabel(), Icons["addgrp"].GetDesc(),
-             self.parent.OnAddGroup),
-            (self.addovl, 'addovl',  Icons["addovl"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["addovl"].GetLabel(), Icons["addovl"].GetDesc(),
-             self.parent.OnAddOverlay),
-            (self.delcmd, 'delcmd',  Icons["delcmd"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["delcmd"].GetLabel(), Icons["delcmd"].GetDesc(),
-             self.parent.OnDeleteLayer),
-            ('', '', '', '', '', '', ''),
-            (self.attribute, 'attrtable', Icons["attrtable"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["attrtable"].GetLabel(), Icons["attrtable"].GetDesc(),
-             self.parent.OnShowAttributeTable),
-            ('', '', '', '', '', '', ''),
-            (self.modeler, 'modeler', Icons["modeler"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["modeler"].GetLabel(), Icons["modeler"].GetDesc(),
-             self.parent.OnGModeler),
-            (self.preferences, 'preferences', Icons["settings"].GetBitmap(),
-             wx.ITEM_NORMAL, Icons["settings"].GetLabel(), Icons["settings"].GetDesc(),
-             self.parent.OnPreferences)
-            )
-    
+        icons = Icons['layerManager']
+        return self._getToolbarData(((self.newdisplay, 'newdisplay', icons["newdisplay"], self.parent.OnNewMenu),
+                                     (None, ),
+                                     (self.workspaceLoad, 'workspaceLoad', icons["workspaceLoad"], self.parent.OnLoadMenu),
+                                     (self.workspaceOpen, 'workspaceOpen', icons["workspaceOpen"], self.parent.OnWorkspaceOpen),
+                                     (self.workspaceSave, 'workspaceSave', icons["workspaceSave"], self.parent.OnWorkspaceSave),
+                                     (None, ),
+                                     (self.addrast, 'addRast', icons["addRast"], self.parent.OnAddRaster),
+                                     (self.rastmisc, 'rastMisc', icons["rastMisc"], self.parent.OnAddRasterMisc),
+                                     (self.addvect, 'addVect', icons["addVect"], self.parent.OnAddVector),
+                                     (self.vectmisc, 'vectMisc', icons["vectMisc"], self.parent.OnAddVectorMisc),
+                                     (self.addgrp, 'addGroup',  icons["addGroup"], self.parent.OnAddGroup),
+                                     (self.addovl, 'addOverlay',  icons["addOverlay"], self.parent.OnAddOverlay),
+                                     (self.delcmd, 'delCmd',  icons["delCmd"], self.parent.OnDeleteLayer),
+                                     (None, ),
+                                     (self.vdigit, 'vdigit', icons["vdigit"], self.parent.OnVDigit),
+                                     (self.attribute, 'attrTable', icons["attrTable"], self.parent.OnShowAttributeTable),
+                                     (None, ),
+                                     (self.modeler, 'modeler', icons["modeler"], self.parent.OnGModeler),
+                                     (self.preferences, 'preferences', icons["settings"], self.parent.OnPreferences))
+                                    )

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/utils.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/utils.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/utils.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -452,11 +452,11 @@
     
     scmd = cmd[0]
     
-    if cmd[1].has_key('flags'):
+    if 'flags' in cmd[1]:
         for flag in cmd[1]['flags']:
             scmd += ' -' + flag
     for flag in ('verbose', 'quiet', 'overwrite'):
-        if cmd[1].has_key(flag) and cmd[1][flag] is True:
+        if flag in cmd[1] and cmd[1][flag] is True:
             scmd += ' --' + flag
     
     for k, v in cmd[1].iteritems():
@@ -481,7 +481,7 @@
             if flag in ('verbose', 'quiet', 'overwrite'):
                 dcmd[str(flag)] = True
         else: # -> flags
-            if not dcmd.has_key('flags'):
+            if 'flags' not in dcmd:
                 dcmd['flags'] = ''
             dcmd['flags'] += item.replace('-', '')
                 
@@ -619,16 +619,16 @@
         
         if not ret:
             return listOfMapsets
-            
+        
         for line in ret.rstrip().splitlines():
             listOfMapsets += line.split(' ')
     else:
         for mapset in glob.glob(os.path.join(dbase, location, "*")):
             if os.path.isdir(mapset) and \
                     os.path.isfile(os.path.join(dbase, location, mapset, "WIND")):
-                listOfMapsets.append(EncodeString(os.path.basename(mapset)))
+                listOfMapsets.append(os.path.basename(mapset))
     
-    ListSortLower(listOfMapsets)    
+    ListSortLower(listOfMapsets)
     return listOfMapsets
 
 def GetColorTables():
@@ -641,11 +641,30 @@
     
     return ret.splitlines()
 
+def DecodeString(string):
+    """!Return decoded string
+    
+    String is decoded as unicode, on failure
+    are used system locales.
+
+    @param string string to be decoded
+    
+    @return decoded string
+    """
+    try:
+        return string.decode('utf-8')
+    except LookupError:
+        enc = locale.getdefaultlocale()[1]
+        if enc:
+            return string.decode(enc)
+    
+    return string
+
 def EncodeString(string):
-    """!Return encoded string
-
+    """!Return encoded string using system locales
+    
     @param string string to be encoded
-
+    
     @return encoded string
     """
     enc = locale.getdefaultlocale()[1]

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/vdigit.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/vdigit.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/vdigit.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -1,21 +1,18 @@
 """!
 @package vdigit
 
- at brief wxGUI vector digitizer user interface
+ at brief Dialogs for wxGUI vector digitizer
 
 Classes:
- - AbstractDigit 
  - VDigit
- - AbstractDisplayDriver
- - CDisplayDriver
  - VDigitSettingsDialog
  - VDigitCategoryDialog
  - CategoryListCtrl
  - VDigitZBulkDialog
  - VDigitDuplicatesDialog
- - VDigitVBuildDialog
+ - CheckListFeature
 
-(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.
 
@@ -43,1103 +40,40 @@
 from units import Units
 from preferences import globalSettings as UserSettings
 try:
-    digitPath = os.path.join(globalvar.ETCWXDIR, "vdigit")
-    sys.path.append(digitPath)
-    import grass6_wxvdigit as wxvdigit
-    GV_LINES = wxvdigit.GV_LINES
-    PseudoDC = wxvdigit.PseudoDC
+    from wxvdigit  import IVDigit, GV_LINES
     haveVDigit = True
     errorMsg = ''
 except ImportError, err:
     haveVDigit = False
-    GV_LINES = None
-    PseudoDC = wx.PseudoDC
     errorMsg = err
-    
-class AbstractDigit:
-    """!Abstract digitization class
-    """
-    def __init__(self, mapwindow):
-        """!Initialization
+    GV_LINES = -1
+    class IVDigit:
+        def __init__(self):
+            pass
 
-        @param mapwindow reference to mapwindow (MapFrame) instance
-        @param settings  initial settings of digitization tool
-        """
-        self.map       = None
-        self.mapWindow = mapwindow
-        
-        Debug.msg (3, "AbstractDigit.__init__(): map=%s" % \
-                   self.map)
-
-        #self.SetCategory()
-
-        self.driver = CDisplayDriver(self, mapwindow)
-
-    def __del__(self):
-        pass
-    
-    def SetCategoryNextToUse(self):
-        """!Find maximum category number in the map layer
-        and update Digit.settings['category']
-
-        @return 'True' on success, 'False' on failure
-        """
-        # vector map layer without categories, reset to '1'
-        UserSettings.Set(group='vdigit', key='category', subkey='value', value=1)
-
-        if self.map:
-            cat = self.digit.GetCategory(UserSettings.Get(group='vdigit', key='layer', subkey='value'))
-            cat += 1
-            UserSettings.Set(group='vdigit', key='category', subkey='value',
-                             value=cat)
-        
-    def SetCategory(self):
-        """!Return category number to use (according Settings)"""
-        if UserSettings.Get(group='vdigit', key="categoryMode", subkey='selection') == 0:
-            self.SetCategoryNextToUse()
-
-        return UserSettings.Get(group='vdigit', key="category", subkey='value')
-
-    def SetMapName(self, map):
-        """!Set map name
-
-        @param map map name to be set up or None (will close currently edited map)
-        """
-        Debug.msg (3, "AbstractDigit.SetMapName map=%s" % map)
-        self.map = map
-
-        try:
-            ret = self.driver.Reset(self.map)
-        except StandardError, e:
-            raise gcmd.GException(_("Unable to initialize display driver of vector "
-                              "digitizer. See 'Command output' for details.\n\n"
-                              "Details: ") + e)
-        
-        if map and ret == -1:
-            raise gcmd.GException(_('Unable to open vector map <%s> for editing.\n\n'
-                                    'Data are probably corrupted, '
-                                    'try to run v.build to rebuild '
-                                    'the topology (Vector->Develop vector map->'
-                                    'Create/rebuild topology).') % map)
-        if not map and ret != 0:
-            raise gcmd.GException(_('Unable to open vector map <%s> for editing.\n\n'
-                                    'Data are probably corrupted, '
-                                    'try to run v.build to rebuild '
-                                    'the topology (Vector->Develop vector map->'
-                                    'Create/rebuild topology).') % map)
-        
-        if self.digit:
-            self.digit.InitCats()
-        
-    def SelectLinesByQueryThresh(self):
-        """!Generic method used for SelectLinesByQuery()
-        -- to get threshold value"""
-        thresh = 0.0
-        if UserSettings.Get(group='vdigit', key='query', subkey='selection') == 0:
-            thresh = UserSettings.Get(group='vdigit', key='queryLength', subkey='thresh')
-            if UserSettings.Get(group='vdigit', key="queryLength", subkey='than-selection') == 0:
-                thresh = -1 * thresh
-        else:
-            thresh = UserSettings.Get(group='vdigit', key='queryDangle', subkey='thresh')
-            if UserSettings.Get(group='vdigit', key="queryDangle", subkey='than-selection') == 0:
-                thresh = -1 * thresh
-
-        return thresh
-
-    def GetSelectType(self):
-        """!Get type(s) to be selected
-
-        Used by SelectLinesByBox() and SelectLinesByPoint()"""
-
-        type = 0
-        for feature in (('point', wxvdigit.GV_POINT),
-                        ('line', wxvdigit.GV_LINE),
-                        ('centroid', wxvdigit.GV_CENTROID),
-                        ('boundary', wxvdigit.GV_BOUNDARY)):
-            if UserSettings.Get(group='vdigit', key='selectType',
-                                subkey=[feature[0], 'enabled']) is True:
-                type |= feature[1]
-
-        return type
-
-    def SelectLinesFromBackgroundMap(self, pos1, pos2):
-        """!Select features from background map
-
-        @param pos1,pos2 bounding box
-        """
-        bgmap = str(UserSettings.Get(group='vdigit', key='bgmap', subkey='value',
-                                     internal=True))
-        
-        if bgmap == '':
-            Debug.msg(4, "VEdit.SelectLinesFromBackgroundMap(): []")
-            return []
-
-        x1, y1 = pos1
-        x2, y2 = pos2
-        ret = gcmd.RunCommand('v.edit',
-                              parent = self,
-                              quiet = True,
-                              read = True,
-                              map = bgmap,
-                              tool = 'select',
-                              bbox = '%f,%f,%f,%f' % (x1, y1, x2, y2))
-
-        if not ret:
-            x, y = pos1
-            ret = gcmd.RunCommand('v.edit',
-                                  parent = self,
-                                  quiet = True,
-                                  read = True,
-                                  map = bgmap,
-                                  tool = 'select',
-                                  coords = '%f,%f' % (x, y),
-                                  thresh = self.driver.GetThreshold(type='selectThresh'))
-        
-        if not ret:
-            return []
-        
-        output = ret.splitlines()[0] # first line
-        ids = output.split(',') 
-        ids = map(int, ids) # str -> int
-        
-        Debug.msg(4, "VEdit.SelectLinesFromBackgroundMap(): %s" % \
-                      ",".join(["%d" % v for v in ids]))
-        
-        return ids
-
-class VDigit(AbstractDigit):
-    """!Prototype of digitization class based on v.digit
-    reimplementation (wxWidgets C/C++)
-    """
+class VDigit(IVDigit):
     def __init__(self, mapwindow):
-        """!VDigit constructor
+        """!Base class of vector digitizer
         
-        @param mapwindow reference to mapwindow (MapFrame) instance
+        @param mapwindow reference to mapwindow (mapdisp_window.BufferedWindow) instance
         """
-        AbstractDigit.__init__(self, mapwindow)
+        IVDigit.__init__(self, mapwindow)
         
-        if not mapwindow.parent.IsStandalone():
-            self.log = mapwindow.parent.GetLayerManager().goutput.cmd_stderr
-        else:
-            self.log = sys.stderr
-        
-        self.toolbar = mapwindow.parent.toolbars['vdigit']
-        
-        try:
-            self.digit = wxvdigit.Digit(self.driver.GetDevice(),
-                                        mapwindow)
-        except (ImportError, NameError, TypeError), e:
-            # print traceback
-            traceback.print_exc(file = self.log)
-            self.digit = None
-        self.UpdateSettings()
-        
-    def __del__(self):
-        del self.digit
-        
-    def AddPoint (self, map, point, x, y, z=None):
-        """!Add new point/centroid
-
-        @param map   map name (unused, for compatability with VEdit)
-        @param point feature type (if true point otherwise centroid)
-        @param x,y,z coordinates
+class VDigitSettingsDialog(wx.Dialog):
+    def __init__(self, parent, title, style = wx.DEFAULT_DIALOG_STYLE):
+        """!Standard settings dialog for digitization purposes
         """
-        if UserSettings.Get(group='vdigit', key="categoryMode", subkey='selection') == 2:
-            layer = -1 # -> no category
-            cat   = -1
-        else:
-            layer = UserSettings.Get(group='vdigit', key="layer", subkey='value')
-            cat   = self.SetCategory()
-            
-        if point:
-            type = wxvdigit.GV_POINT 
-        else:
-            type = wxvdigit.GV_CENTROID 
-
-        snap, thresh = self.__getSnapThreshold()
-
-        bgmap = str(UserSettings.Get(group='vdigit', key="bgmap",
-                                     subkey='value', internal=True))
-        if z:
-            ret = self.digit.AddLine(type, [x, y, z], layer, cat,
-                                     bgmap, snap, thresh)
-        else:
-            ret = self.digit.AddLine(type, [x, y], layer, cat,
-                                     bgmap, snap, thresh)
-        self.toolbar.EnableUndo()
-
-        return ret
+        wx.Dialog.__init__(self, parent = parent, id = wx.ID_ANY, title = title, style = style)
         
-    def AddLine (self, map, line, coords):
-        """!Add line/boundary
-
-        @param map    map name (unused, for compatability with VEdit)
-        @param line   feature type (if True line, otherwise boundary)
-        @param coords list of coordinates
-        """
-        if len(coords) < 2:
-            return
-        
-        if UserSettings.Get(group='vdigit', key="categoryMode", subkey='selection') == 2:
-            layer = -1 # -> no category
-            cat   = -1
-        else:
-            layer = UserSettings.Get(group='vdigit', key="layer", subkey='value')
-            cat   = self.SetCategory()
-        
-        if line:
-            type = wxvdigit.GV_LINE
-        else:
-            type = wxvdigit.GV_BOUNDARY
-        
-        listCoords = []
-        for c in coords:
-            for x in c:
-                listCoords.append(x)
-        
-        snap, thresh = self.__getSnapThreshold()
-        
-        bgmap = str(UserSettings.Get(group='vdigit', key="bgmap",
-                                     subkey='value', internal=True))
-        
-        ret = self.digit.AddLine(type, listCoords, layer, cat,
-                                 bgmap, snap, thresh)
-
-        self.toolbar.EnableUndo()
-        
-        return ret
-    
-    def DeleteSelectedLines(self):
-        """!Delete selected features
-
-        @return number of deleted lines
-        """
-        nlines = self.digit.DeleteLines(UserSettings.Get(group='vdigit', key='delRecord', subkey='enabled'))
-        
-        if nlines > 0:
-            self.toolbar.EnableUndo()
-            
-        return nlines
-
-    def MoveSelectedLines(self, move):
-        """!Move selected features
-
-        @param move direction (x, y)
-        """
-        snap, thresh = self.__getSnapThreshold()
-        
-        bgmap = str(UserSettings.Get(group='vdigit', key="bgmap",
-                                     subkey='value', internal=True))
-        
-        try:
-            nlines = self.digit.MoveLines(move[0], move[1], 0.0, # TODO 3D
-                                          bgmap, snap, thresh)
-        except SystemExit:
-            pass
-        
-        if nlines > 0:
-            self.toolbar.EnableUndo()
-        
-        return nlines
-
-    def MoveSelectedVertex(self, coords, move):
-        """!Move selected vertex of the line
-
-        @param coords click coordinates
-        @param move   X,Y direction
-
-        @return id of new feature
-        @return 0 vertex not moved (not found, line is not selected)
-        """
-        snap, thresh = self.__getSnapThreshold()
-
-        bgmap = str(UserSettings.Get(group='vdigit', key="bgmap",
-                                     subkey='value', internal=True))
-        
-        moved = self.digit.MoveVertex(coords[0], coords[1], 0.0, # TODO 3D
-                                      move[0], move[1], 0.0,
-                                      bgmap, snap,
-                                      self.driver.GetThreshold(type='selectThresh'), thresh)
-
-        if moved:
-            self.toolbar.EnableUndo()
-
-        return moved
-
-    def AddVertex(self, coords):
-        """!Add new vertex to the selected line/boundary on position 'coords'
-
-        @param coords coordinates to add vertex
-
-        @return id of new feature
-        @return 0 nothing changed
-        @return -1 on failure
-        """
-        added = self.digit.ModifyLineVertex(1, coords[0], coords[1], 0.0, # TODO 3D
-                                            self.driver.GetThreshold(type='selectThresh'))
-
-        if added > 0:
-            self.toolbar.EnableUndo()
-
-        return added
-
-    def RemoveVertex(self, coords):
-        """!Remove vertex from the selected line/boundary on position 'coords'
-
-        @param coords coordinates to remove vertex
-
-        @return id of new feature
-        @return 0 nothing changed
-        @return -1 on failure
-        """
-        deleted = self.digit.ModifyLineVertex(0, coords[0], coords[1], 0.0, # TODO 3D
-                                              self.driver.GetThreshold(type='selectThresh'))
-
-        if deleted > 0:
-            self.toolbar.EnableUndo()
-
-        return deleted
-
-
-    def SplitLine(self, coords):
-        """!Split selected line/boundary on position 'coords'
-
-        @param coords coordinates to split line
-
-        @return 1 line modified
-        @return 0 nothing changed
-        @return -1 error
-        """
-        ret = self.digit.SplitLine(coords[0], coords[1], 0.0, # TODO 3D
-                                   self.driver.GetThreshold('selectThresh'))
-
-        if ret > 0:
-            self.toolbar.EnableUndo()
-
-        return ret
-
-    def EditLine(self, line, coords):
-        """!Edit existing line/boundary
-
-        @param line id of line to be modified
-        @param coords list of coordinates of modified line
-
-        @return feature id of new line
-        @return -1 on error
-        """
-        try:
-            lineid = line[0]
-        except:
-            lineid = -1
-
-        if len(coords) < 2:
-            self.DeleteSelectedLines()
-            return 0
-            
-        listCoords = []
-        for c in coords:
-            for x in c:
-                listCoords.append(x)
-
-        snap, thresh = self.__getSnapThreshold()
-        
-        bgmap = str(UserSettings.Get(group='vdigit', key="bgmap",
-                                     subkey='value', internal=True))
-        
-        try:
-            ret = self.digit.RewriteLine(lineid, listCoords,
-                                         bgmap, snap, thresh)
-        except SystemExit:
-            pass
-
-        if ret > 0:
-            self.toolbar.EnableUndo()
-
-        return ret
-
-    def FlipLine(self):
-        """!Flip selected lines/boundaries
-
-        @return number of modified lines
-        @return -1 on error
-        """
-        ret = self.digit.FlipLines()
-
-        if ret > 0:
-            self.toolbar.EnableUndo()
-
-        return ret
-
-    def MergeLine(self):
-        """!Merge selected lines/boundaries
-
-        @return number of modified lines
-        @return -1 on error
-        """
-        ret = self.digit.MergeLines()
-
-        if ret > 0:
-            self.toolbar.EnableUndo()
-
-        return ret
-
-    def BreakLine(self):
-        """!Break selected lines/boundaries
-
-        @return number of modified lines
-        @return -1 on error
-        """
-        ret = self.digit.BreakLines()
-
-        if ret > 0:
-            self.toolbar.EnableUndo()
-
-        return ret
-
-    def SnapLine(self):
-        """!Snap selected lines/boundaries
-
-        @return on success
-        @return -1 on error
-        """
-        snap, thresh = self.__getSnapThreshold()
-        ret = self.digit.SnapLines(thresh)
-        
-        if ret == 0:
-            self.toolbar.EnableUndo()
-
-        return ret
-
-    def ConnectLine(self):
-        """!Connect selected lines/boundaries
-
-        @return 1 lines connected
-        @return 0 lines not connected
-        @return -1 on error
-        """
-        snap, thresh = self.__getSnapThreshold()
-        ret = self.digit.ConnectLines(thresh)
-
-        if ret > 0:
-            self.toolbar.EnableUndo()
-
-        return ret
-        
-    def CopyLine(self, ids=[]):
-        """!Copy features from (background) vector map
-
-        @param ids list of line ids to be copied
-
-        @return number of copied features
-        @return -1 on error
-        """
-        bgmap = str(UserSettings.Get(group='vdigit', key='bgmap',
-                                     subkey='value', internal=True))
-        
-        if len(bgmap) > 0:
-            ret = self.digit.CopyLines(ids, bgmap)
-        else:
-            ret = self.digit.CopyLines(ids, None)
-
-        if ret > 0:
-            self.toolbar.EnableUndo()
-
-        return ret
-
-    def CopyCats(self, fromId, toId, copyAttrb=False):
-        """!Copy given categories to objects with id listed in ids
-
-        @param cats ids of 'from' feature
-        @param ids  ids of 'to' feature(s)
-
-        @return number of modified features
-        @return -1 on error
-        """
-        if len(fromId) == 0 or len(toId) == 0:
-            return 0
-        
-        ret = self.digit.CopyCats(fromId, toId, copyAttrb)
-
-        if ret > 0:
-            self.toolbar.EnableUndo()
-
-        return ret
-
-    def SelectLinesByQuery(self, pos1, pos2):
-        """!Select features by query
-
-        @param pos1, pos2 bounding box definition
-        """
-        thresh = self.SelectLinesByQueryThresh()
-        
-        w, n = pos1
-        e, s = pos2
-
-        query = wxvdigit.QUERY_UNKNOWN
-        if UserSettings.Get(group='vdigit', key='query', subkey='selection') == 0:
-            query = wxvdigit.QUERY_LENGTH
-        else:
-            query = wxvdigit.QUERY_DANGLE
-
-        type = wxvdigit.GV_POINTS | wxvdigit.GV_LINES # TODO: 3D
-        
-        ids = self.digit.SelectLinesByQuery(w, n, 0.0, e, s, 1000.0,
-                                            UserSettings.Get(group='vdigit', key='query', subkey='box'),
-                                            query, type, thresh)
-
-        Debug.msg(4, "VDigit.SelectLinesByQuery(): %s" % \
-                      ",".join(["%d" % v for v in ids]))
-        
-        return ids
-
-    def GetLineCats(self, line=-1):
-        """!Get layer/category pairs from given (selected) line
-        
-        @param line feature id (-1 for first selected line)
-        """
-        return dict(self.digit.GetLineCats(line))
-
-    def GetLineLength(self, line):
-        """!Get line length
-
-        @param line feature id
-
-        @return line length
-        @return -1 on error
-        """
-        return self.digit.GetLineLength(line)
-
-    def GetAreaSize(self, centroid):
-        """!Get area size
-
-        @param centroid centroid id
-
-        @return area size
-        @return -1 on error
-        """
-        return self.digit.GetAreaSize(centroid)
-        
-    def GetAreaPerimeter(self, centroid):
-        """!Get area perimeter
-
-        @param centroid centroid id
-
-        @return area size
-        @return -1 on error
-        """
-        return self.digit.GetAreaPerimeter(centroid)
-
-    def SetLineCats(self, line, layer, cats, add=True):
-        """!Set categories for given line and layer
-
-        @param line feature id
-        @param layer layer number (-1 for first selected line)
-        @param cats list of categories
-        @param add if True to add, otherwise do delete categories
-
-        @return new feature id (feature need to be rewritten)
-        @return -1 on error
-        """
-        ret = self.digit.SetLineCats(line, layer, cats, add)
-
-        if ret > 0:
-            self.toolbar.EnableUndo()
-
-        return ret
-
-    def GetLayers(self):
-        """!Get list of layers"""
-        return self.digit.GetLayers()
-
-    def TypeConvForSelectedLines(self):
-        """!Feature type conversion for selected objects.
-
-        Supported conversions:
-         - point <-> centroid
-         - line <-> boundary
-
-        @return number of modified features
-        @return -1 on error
-        """
-        ret = self.digit.TypeConvLines()
-
-        if ret > 0:
-            self.toolbar.EnableUndo()
-
-        return ret
-
-    def Undo(self, level=-1):
-        """!Undo action
-
-        @param level levels to undo (0 to revert all)
-
-        @return id of current changeset
-        """
-        try:
-            ret = self.digit.Undo(level)
-        except SystemExit:
-            ret = -2
-
-        if ret == -2:
-            raise gcmd.GException(_("Undo failed, data corrupted."))
-
-        self.mapWindow.UpdateMap(render=False)
-        
-        if ret < 0: # disable undo tool
-            self.toolbar.EnableUndo(False)
-
-    def GetUndoLevel(self):
-        """!Get undo level (number of active changesets)
-        
-        Note: Changesets starts wiht 0
-        """
-        if not self.digit:
-            return -1
-        
-        return self.digit.GetUndoLevel()
-
-    def UpdateSettings(self):
-        """!Update digit settigs"""
-        if not self.digit:
-            return
-        
-        self.digit.UpdateSettings(UserSettings.Get(group='vdigit', key='breakLines',
-                                                   subkey='enabled'),
-                                  UserSettings.Get(group='vdigit', key='addCentroid',
-                                                   subkey='enabled'),
-                                  UserSettings.Get(group='vdigit', key='catBoundary',
-                                                   subkey='enabled'))
-        
-    def ZBulkLines(self, pos1, pos2, start, step):
-        """!Z-bulk labeling
-
-        @param pos1 reference line (start point)
-        @param pos1 reference line (end point)
-        @param start starting value
-        @param step step value
-
-        @return number of modified lines
-        @return -1 on error
-        """
-        ret = self.digit.ZBulkLabeling(pos1[0], pos1[1], pos2[0], pos2[1],
-                                       start, step)
-        
-        if ret > 0:
-            self.toolbar.EnableUndo()
-        
-        return ret
-    
-    def __getSnapThreshold(self):
-        """!Get snap mode and threshold value
-
-        @return (snap, thresh)
-        """
-        thresh = self.driver.GetThreshold()
-
-        if thresh > 0.0:
-            if UserSettings.Get(group='vdigit', key='snapToVertex', subkey='enabled') is True:
-                snap = wxvdigit.SNAPVERTEX
-            else:
-                snap = wxvdigit.SNAP
-        else:
-            snap = wxvdigit.NO_SNAP
-
-        return (snap, thresh)
-
-class AbstractDisplayDriver:
-    """!Abstract classs for display driver"""
-    def __init__(self, parent, mapwindow):
-        """!Initialization
-
-        @param parent
-        @param mapwindow reference to mapwindow (MFrame)
-        """
-        self.parent      = parent
-        self.mapwindow   = mapwindow
-        
-        self.ids         = {}   # dict[g6id] = [pdcId]
-        self.selected    = []   # list of selected objects (grassId!)
-
-    def GetThreshold(self, type='snapping', value=None, units=None):
-        """!Return threshold in map units
-
-        @param value threshold to be set up
-        @param units units (map, screen)
-        """
-        if value is None:
-            value = UserSettings.Get(group='vdigit', key=type, subkey='value')
-
-        if units is None:
-            units = UserSettings.Get(group='vdigit', key=type, subkey='units')
-
-        reg = self.mapwindow.Map.region
-        if value < 0:
-            value = (reg['nsres'] + reg['ewres']) / 2.
-        
-        if units == "screen pixels":
-            # pixel -> cell
-            if reg['nsres'] > reg['ewres']:
-                res = reg['nsres']
-            else:
-                res = reg['ewres']
-
-            threshold = value * res
-        else:
-            threshold = value
-
-        Debug.msg(4, "AbstractDisplayDriver.GetThreshold(): type=%s, thresh=%f" % (type, threshold))
-        
-        return threshold
-
-class CDisplayDriver(AbstractDisplayDriver):
-    """
-    Display driver using grass6_wxdriver module
-    """
-    def __init__(self, parent, mapwindow):
-        """!Initialization
-
-        @param parent
-        @param mapwindow reference to mapwindow (MFrame)
-        """
-        AbstractDisplayDriver.__init__(self, parent, mapwindow)
-
-        self.mapWindow = mapwindow
-
-        if not self.mapwindow.parent.IsStandalone():
-            logerr = self.mapwindow.parent.GetLayerManager().goutput.cmd_stderr
-        else:
-            logerr = None
-
-        # initialize wx display driver
-        try:
-            self.__display = wxvdigit.DisplayDriver(mapwindow.pdcVector,
-                                                    mapwindow.pdcTmp,
-                                                    logerr)
-        except:
-            self.__display = None
-            
-        self.UpdateSettings()
-
-    def GetDevice(self):
-        """!Get device"""
-        return self.__display
-    
-    def SetDevice(self, pdc):
-        """!Set device for driver
-
-        @param pdc wx.PseudoDC instance
-        """
-        if self.__display:
-            self.__display.SetDevice(pdc)
-            
-    def Reset(self, map):
-        """!Reset map
-
-        Open or close the vector map by driver.
-
-        @param map map name or None to close the map
-
-        @return 0 on success (close map)
-        @return topo level on success (open map)
-        @return non-zero (close map)
-        @return -1 on error (open map)
-        """
-        if map:
-            name, mapset = map.split('@')
-            try:
-                ret = self.__display.OpenMap(str(name), str(mapset), True)
-            except SystemExit:
-                ret = -1
-        else:
-            ret = self.__display.CloseMap()
-
-        return ret
-    
-    def ReloadMap(self):
-        """!Reload map (close and re-open).
-
-        Needed for v.edit, TODO: get rid of that..."""
-        
-        Debug.msg(4, "CDisplayDriver.ReloadMap():")
-        self.__display.ReloadMap()
-
-    def DrawMap(self):
-        """!Draw vector map layer content
-
-        @return wx.Image instance
-        """
-        if not self.__display:
-            return 0
-        
-        nlines = self.__display.DrawMap(True) # force
-        Debug.msg(3, "CDisplayDriver.DrawMap(): nlines=%d" % nlines)
-
-        return nlines
-
-    def SelectLinesByBox(self, begin, end, type=0, drawSeg=False):
-        """!Select vector features by given bounding box.
-
-        If type is given, only vector features of given type are selected.
-
-        @param begin,end bounding box definition
-        @param type      select only objects of given type
-        """
-        x1, y1 = begin
-        x2, y2 = end
-
-        inBox = UserSettings.Get(group='vdigit', key='selectInside', subkey='enabled')
-        
-        nselected = self.__display.SelectLinesByBox(x1, y1, -1.0 * wxvdigit.PORT_DOUBLE_MAX,
-                                                    x2, y2, wxvdigit.PORT_DOUBLE_MAX,
-                                                    type, inBox, drawSeg)
-        
-        Debug.msg(4, "CDisplayDriver.SelectLinesByBox(): selected=%d" % \
-                      nselected)
-        
-        return nselected
-
-    def SelectLineByPoint(self, point, type=0):
-        """!Select vector feature by coordinates of click point (in given threshold).
-
-        If type is given, only vector features of given type are selected.
-
-        @param point click coordinates (bounding box given by threshold)
-        @param type  select only objects of given type
-        """
-        pointOnLine = self.__display.SelectLineByPoint(point[0], point[1], 0.0,
-                                                       self.GetThreshold(type='selectThresh'),
-                                                       type, 0); # without_z
-
-        if len(pointOnLine) > 0:
-            Debug.msg(4, "CDisplayDriver.SelectLineByPoint(): pointOnLine=%f,%f" % \
-                          (pointOnLine[0], pointOnLine[1]))
-            return pointOnLine
-        else:
-            Debug.msg(4, "CDisplayDriver.SelectLineByPoint(): no line found")
-            return None
-        
-    def GetSelected(self, grassId=True):
-        """!Return ids of selected vector features
-        
-        @param grassId if grassId is True returns GRASS ids, otherwise
-        internal ids of objects drawn in PseudoDC"""
-        if not self.__display:
-            return list()
-        
-        if grassId:
-            selected = self.__display.GetSelected(True)
-        else:
-            selected = self.__display.GetSelected(False)
-            
-        Debug.msg(4, "CDisplayDriver.GetSelected(): grassId=%d, ids=%s" % \
-                      (grassId, (",".join(["%d" % v for v in selected]))))
-            
-        return selected
-
-    def GetSelectedCoord(self):
-        """!Return ids of selected vector features and their coordinates"""
-        return dict(self.__display.GetSelectedCoord())
-        
-    def GetRegionSelected(self):
-        """!Get minimal region extent of selected features (ids/cats)"""
-        return self.__display.GetRegionSelected()
-    
-    def GetDuplicates(self):
-        """!Return ids of (selected) duplicated vector features
-        """
-        # -> id : (list of ids)
-        dupl = dict(self.__display.GetDuplicates())
-
-        # -> id : ((id, cat), ...)
-        dupl_full = {}
-        for key in dupl.keys():
-            dupl_full[key] = []
-            for id in dupl[key]:
-                catStr = ''
-                
-                cats = self.parent.GetLineCats(line=id)
-                
-                for layer in cats.keys():
-                    if len(cats[layer]) > 0:
-                        catStr = "%d: (" % layer
-                        for cat in cats[layer]:
-                            catStr += "%d," % cat
-                        catStr = catStr.rstrip(',')
-                        catStr += ')'
-                
-                dupl_full[key].append([id, catStr])
-
-        return dupl_full
-
-    def GetSelectedVertex(self, coords):
-        """!Get PseudoDC id(s) of vertex (of selected line)
-        on position 'coords'
-
-        @param coords click position
-        """
-        x, y = coords
-
-        id = self.__display.GetSelectedVertex(x, y, self.GetThreshold(type='selectThresh'))
-
-        Debug.msg(4, "CDisplayDriver.GetSelectedVertex(): id=%s" % \
-                      (",".join(["%d" % v for v in id])))
-
-        return id 
-
-    def SetSelected(self, id, field=-1):
-        """!Set selected vector features
-
-        @param id list of feature ids/categories to be selected
-        @param field field(layer) number, -1 for ids instead of cats
-        """
-        Debug.msg(4, "CDisplayDriver.SetSelected(): id=%s" % \
-                      id)
-
-        self.__display.SetSelected(id, field)
-
-    def UnSelect(self, id):
-        """!Unselect vector features
-
-        @param id list of feature id(s)
-        """
-
-        Debug.msg(4, "CDisplayDriver.UnSelect(): id=%s" % \
-                      ",".join(["%d" % v for v in id]))
-        
-        self.__display.UnSelect(id)
-
-    def UpdateRegion(self):
-        """!Set geographical region
-        
-        Needed for 'cell2pixel' conversion"""
-        if not self.__display:
-            return
-        
-        map = self.mapwindow.Map
-        reg = map.region
-        
-        self.__display.SetRegion(reg['n'],
-                                 reg['s'],
-                                 reg['e'],
-                                 reg['w'],
-                                 reg['nsres'],
-                                 reg['ewres'],
-                                 reg['center_easting'],
-                                 reg['center_northing'],
-                                 map.width, map.height)
-
-    def GetMapBoundingBox(self):
-        """!Return bounding box of given vector map layer
-
-        @return (w,s,b,e,n,t)
-        """
-
-        return self.__display.GetMapBoundingBox()
-
-    def Is3D(self):
-        """!Check if open vector map is 3D
-
-        @return True if 3D
-        @return False if not 3D"""
-        return self.__display.Is3D()
-    
-    def DrawSelected(self, draw=True):
-        """!Show/hide selected features"""
-        self.__display.DrawSelected(draw)
-        
-    def UpdateSettings(self, alpha=255):
-        """!Update display driver settings"""
-        # TODO map units
-
-        if not self.__display:
-            return
-        
-        color = {}
-        for symbol in ("highlight",
-                       "highlightDupl",
-                       "point",
-                       "line",
-                       "boundaryNo",
-                       "boundaryOne",
-                       "boundaryTwo",
-                       "centroidIn",
-                       "centroidOut",
-                       "centroidDup",
-                       "nodeOne",
-                       "nodeTwo",
-                       "vertex",
-                       "area",
-                       "direction"):
-            color[symbol] = wx.Color(UserSettings.Get(group='vdigit', key='symbol',
-                                                      subkey=[symbol, 'color'])[0],
-                                     UserSettings.Get(group='vdigit', key='symbol',
-                                                      subkey=[symbol, 'color'])[1],
-                                     UserSettings.Get(group='vdigit', key='symbol',
-                                                      subkey=[symbol, 'color'])[2]).GetRGB()
-
-        self.__display.UpdateSettings (color['highlight'],
-                                       UserSettings.Get(group='vdigit', key='checkForDupl',
-                                                        subkey='enabled'),
-                                       color['highlightDupl'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['point', 'enabled']),
-                                       color['point'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['line', 'enabled']),
-                                       color['line'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['boundaryNo', 'enabled']),
-                                       color['boundaryNo'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['boundaryOne', 'enabled']),
-                                       color['boundaryOne'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['boundaryTwo', 'enabled']),
-                                       color['boundaryTwo'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['centroidIn', 'enabled']),
-                                       color['centroidIn'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['centroidOut', 'enabled']),
-                                       color['centroidOut'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['centroidDup', 'enabled']),
-                                       color['centroidDup'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['nodeOne', 'enabled']),
-                                       color['nodeOne'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['nodeTwo', 'enabled']),
-                                       color['nodeTwo'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['vertex', 'enabled']),
-                                       color['vertex'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['area', 'enabled']),
-                                       color['area'],
-                                       UserSettings.Get(group='vdigit', key='symbol',
-                                                        subkey=['direction', 'enabled']),
-                                       color['direction'],
-                                       UserSettings.Get(group='vdigit', key='lineWidth',
-                                                        subkey='value'),
-                                       alpha)
-
-class VDigitSettingsDialog(wx.Dialog):
-    """
-    Standard settings dialog for digitization purposes
-    """
-    def __init__(self, parent, title, style=wx.DEFAULT_DIALOG_STYLE):
-        wx.Dialog.__init__(self, parent=parent, id=wx.ID_ANY, title=title, style=style)
-
         self.parent = parent # mapdisplay.BufferedWindow class instance
 
         # notebook
-        notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
-        self.__CreateSymbologyPage(notebook)
-        parent.digit.SetCategory() # update category number (next to use)
-        self.__CreateGeneralPage(notebook)
-        self.__CreateAttributesPage(notebook)
-        self.__CreateQueryPage(notebook)
+        notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
+        self._createSymbologyPage(notebook)
+        self.parent.digit.SetCategory()
+        self._createGeneralPage(notebook)
+        self._createAttributesPage(notebook)
+        self._createQueryPage(notebook)
 
         # buttons
         btnApply = wx.Button(self, wx.ID_APPLY)
@@ -1164,268 +98,265 @@
         btnSizer.Realize()
         
         mainSizer = wx.BoxSizer(wx.VERTICAL)
-        mainSizer.Add(item=notebook, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
-        mainSizer.Add(item=btnSizer, proportion=0,
-                      flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
+        mainSizer.Add(item = notebook, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 5)
+        mainSizer.Add(item = btnSizer, proportion = 0,
+                      flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
         
         self.Bind(wx.EVT_CLOSE, self.OnCancel)
         
         self.SetSizer(mainSizer)
         mainSizer.Fit(self)
 
-    def __CreateSymbologyPage(self, notebook):
-        """!Create notebook page concerning with symbology settings"""
+    def _createSymbologyPage(self, notebook):
+        """!Create notebook page concerning symbology settings"""
+        panel = wx.Panel(parent = notebook, id = wx.ID_ANY)
+        notebook.AddPage(page = panel, text = _("Symbology"))
 
-        panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
-        notebook.AddPage(page=panel, text=_("Symbology"))
-
         sizer = wx.BoxSizer(wx.VERTICAL)
         
-        flexSizer = wx.FlexGridSizer (cols=3, hgap=5, vgap=5)
+        flexSizer = wx.FlexGridSizer (cols = 3, hgap = 5, vgap = 5)
         flexSizer.AddGrowableCol(0)
 
         self.symbology = {}
-        for label, key in self.__SymbologyData():
+        for label, key in self._symbologyData():
             textLabel = wx.StaticText(panel, wx.ID_ANY, label)
-            color = csel.ColourSelect(panel, id=wx.ID_ANY,
-                                      colour=UserSettings.Get(group='vdigit', key='symbol',
-                                                              subkey=[key, 'color']), size=globalvar.DIALOG_COLOR_SIZE)
-            isEnabled = UserSettings.Get(group='vdigit', key='symbol',
-                                         subkey=[key, 'enabled'])
+            color = csel.ColourSelect(panel, id = wx.ID_ANY,
+                                      colour = UserSettings.Get(group = 'vdigit', key = 'symbol',
+                                                              subkey = [key, 'color']), size = globalvar.DIALOG_COLOR_SIZE)
+            isEnabled = UserSettings.Get(group = 'vdigit', key = 'symbol',
+                                         subkey = [key, 'enabled'])
             if isEnabled is not None:
-                enabled = wx.CheckBox(panel, id=wx.ID_ANY, label="")
+                enabled = wx.CheckBox(panel, id = wx.ID_ANY, label = "")
                 enabled.SetValue(isEnabled)
                 self.symbology[key] = (enabled, color)
             else:
                 enabled = (1, 1)
                 self.symbology[key] = (None, color)
             
-            flexSizer.Add(textLabel, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-            flexSizer.Add(enabled, proportion=0, flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
-            flexSizer.Add(color, proportion=0, flag=wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
+            flexSizer.Add(textLabel, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+            flexSizer.Add(enabled, proportion = 0, flag = wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
+            flexSizer.Add(color, proportion = 0, flag = wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
             color.SetName("GetColour")
         
-        sizer.Add(item=flexSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=10)
+        sizer.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 10)
         
         panel.SetSizer(sizer)
         
         return panel
 
-    def __CreateGeneralPage(self, notebook):
-        """!Create notebook page concerning with symbology settings"""
+    def _createGeneralPage(self, notebook):
+        """!Create notebook page concerning general settings"""
+        panel = wx.Panel(parent = notebook, id = wx.ID_ANY)
+        notebook.AddPage(page = panel, text = _("General"))
 
-        panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
-        notebook.AddPage(page=panel, text=_("General"))
-
         border = wx.BoxSizer(wx.VERTICAL)
         
         #
         # display section
         #
-        box   = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Display"))
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Display"))
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        flexSizer = wx.FlexGridSizer (cols=3, hgap=5, vgap=5)
+        flexSizer = wx.FlexGridSizer (cols = 3, hgap = 5, vgap = 5)
         flexSizer.AddGrowableCol(0)
         # line width
-        text = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Line width"))
-        self.lineWidthValue = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(75, -1),
-                                          initial=UserSettings.Get(group='vdigit', key="lineWidth", subkey='value'),
-                                          min=1, max=1e6)
-        units = wx.StaticText(parent=panel, id=wx.ID_ANY, size=(115, -1),
-                              label=UserSettings.Get(group='vdigit', key="lineWidth", subkey='units'),
-                              style=wx.ALIGN_LEFT)
-        flexSizer.Add(text, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(self.lineWidthValue, proportion=0, flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
-        flexSizer.Add(units, proportion=0, flag=wx.ALIGN_RIGHT | wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL | wx.LEFT,
-                      border=10)
+        text = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Line width"))
+        self.lineWidthValue = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = (75, -1),
+                                          initial = UserSettings.Get(group = 'vdigit', key = "lineWidth", subkey = 'value'),
+                                          min = 1, max = 1e6)
+        units = wx.StaticText(parent = panel, id = wx.ID_ANY, size = (115, -1),
+                              label = UserSettings.Get(group = 'vdigit', key = "lineWidth", subkey = 'units'),
+                              style = wx.ALIGN_LEFT)
+        flexSizer.Add(text, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(self.lineWidthValue, proportion = 0, flag = wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
+        flexSizer.Add(units, proportion = 0, flag = wx.ALIGN_RIGHT | wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL | wx.LEFT,
+                      border = 10)
 
-        sizer.Add(item=flexSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=1)
-        border.Add(item=sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
+        sizer.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
 
         #
         # snapping section
         #
-        box   = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Snapping"))
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Snapping"))
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        flexSizer = wx.FlexGridSizer (cols=3, hgap=5, vgap=5)
+        flexSizer = wx.FlexGridSizer(cols = 3, hgap = 5, vgap = 5)
         flexSizer.AddGrowableCol(0)
 
         # snapping
-        text = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Snapping threshold"))
-        self.snappingValue = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(75, -1),
-                                         initial=UserSettings.Get(group='vdigit', key="snapping", subkey='value'),
-                                         min=-1, max=1e6)
+        text = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Snapping threshold"))
+        self.snappingValue = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = (75, -1),
+                                         initial = UserSettings.Get(group = 'vdigit', key = "snapping", subkey = 'value'),
+                                         min = -1, max = 1e6)
         self.snappingValue.Bind(wx.EVT_SPINCTRL, self.OnChangeSnappingValue)
         self.snappingValue.Bind(wx.EVT_TEXT, self.OnChangeSnappingValue)
-        self.snappingUnit = wx.Choice(parent=panel, id=wx.ID_ANY, size=(125, -1),
-                                      choices=["screen pixels", "map units"])
-        self.snappingUnit.SetStringSelection(UserSettings.Get(group='vdigit', key="snapping", subkey='units'))
+        self.snappingUnit = wx.Choice(parent = panel, id = wx.ID_ANY, size = (125, -1),
+                                      choices = ["screen pixels", "map units"])
+        self.snappingUnit.SetStringSelection(UserSettings.Get(group = 'vdigit', key = "snapping", subkey = 'units'))
         self.snappingUnit.Bind(wx.EVT_CHOICE, self.OnChangeSnappingUnits)
-        flexSizer.Add(text, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(self.snappingValue, proportion=0, flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
-        flexSizer.Add(self.snappingUnit, proportion=0, flag=wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
+        flexSizer.Add(text, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(self.snappingValue, proportion = 0, flag = wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
+        flexSizer.Add(self.snappingUnit, proportion = 0, flag = wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
 
         vertexSizer = wx.BoxSizer(wx.VERTICAL)
-        self.snapVertex = wx.CheckBox(parent=panel, id=wx.ID_ANY,
-                                      label=_("Snap also to vertex"))
-        self.snapVertex.SetValue(UserSettings.Get(group='vdigit', key="snapToVertex", subkey='enabled'))
-        vertexSizer.Add(item=self.snapVertex, proportion=0, flag=wx.EXPAND)
+        self.snapVertex = wx.CheckBox(parent = panel, id = wx.ID_ANY,
+                                      label = _("Snap also to vertex"))
+        self.snapVertex.SetValue(UserSettings.Get(group = 'vdigit', key = "snapToVertex", subkey = 'enabled'))
+        vertexSizer.Add(item = self.snapVertex, proportion = 0, flag = wx.EXPAND)
         self.mapUnits = self.parent.MapWindow.Map.GetProjInfo()['units']
-        self.snappingInfo = wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                          label=_("Snapping threshold is %(value).1f %(units)s") % \
-                                              {'value' : self.parent.digit.driver.GetThreshold(),
+        self.snappingInfo = wx.StaticText(parent = panel, id = wx.ID_ANY,
+                                          label = _("Snapping threshold is %(value).1f %(units)s") % \
+                                              {'value' : self.parent.digit.GetDisplay().GetThreshold(),
                                                'units' : self.mapUnits})
-        vertexSizer.Add(item=self.snappingInfo, proportion=0,
-                        flag=wx.ALL | wx.EXPAND, border=1)
+        vertexSizer.Add(item = self.snappingInfo, proportion = 0,
+                        flag = wx.ALL | wx.EXPAND, border = 1)
 
-        sizer.Add(item=flexSizer, proportion=1, flag=wx.EXPAND)
-        sizer.Add(item=vertexSizer, proportion=1, flag=wx.EXPAND)
-        border.Add(item=sizer, proportion=0, flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
+        sizer.Add(item = flexSizer, proportion = 1, flag = wx.EXPAND)
+        sizer.Add(item = vertexSizer, proportion = 1, flag = wx.EXPAND)
+        border.Add(item = sizer, proportion = 0, flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 5)
 
         #
         # select box
         #
-        box   = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Select vector features"))
+        box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Select vector features"))
         # feature type
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
         inSizer = wx.BoxSizer(wx.HORIZONTAL)
         self.selectFeature = {}
         for feature in ('point', 'line',
                         'centroid', 'boundary'):
-            chkbox = wx.CheckBox(parent=panel, label=feature)
+            chkbox = wx.CheckBox(parent = panel, label = feature)
             self.selectFeature[feature] = chkbox.GetId()
-            chkbox.SetValue(UserSettings.Get(group='vdigit', key='selectType',
-                                             subkey=[feature, 'enabled']))
-            inSizer.Add(item=chkbox, proportion=0,
-                        flag=wx.EXPAND | wx.ALL, border=5)
-        sizer.Add(item=inSizer, proportion=0, flag=wx.EXPAND)
+            chkbox.SetValue(UserSettings.Get(group = 'vdigit', key = 'selectType',
+                                             subkey = [feature, 'enabled']))
+            inSizer.Add(item = chkbox, proportion = 0,
+                        flag = wx.EXPAND | wx.ALL, border = 5)
+        sizer.Add(item = inSizer, proportion = 0, flag = wx.EXPAND)
         # threshold
-        flexSizer = wx.FlexGridSizer (cols=3, hgap=5, vgap=5)
+        flexSizer = wx.FlexGridSizer (cols = 3, hgap = 5, vgap = 5)
         flexSizer.AddGrowableCol(0)
-        text = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Select threshold"))
-        self.selectThreshValue = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(75, -1),
-                                             initial=UserSettings.Get(group='vdigit', key="selectThresh", subkey='value'),
-                                             min=1, max=1e6)
-        units = wx.StaticText(parent=panel, id=wx.ID_ANY, size=(115, -1),
-                              label=UserSettings.Get(group='vdigit', key="lineWidth", subkey='units'),
-                              style=wx.ALIGN_LEFT)
-        flexSizer.Add(text, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(self.selectThreshValue, proportion=0, flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
-        flexSizer.Add(units, proportion=0, flag=wx.ALIGN_RIGHT | wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL | wx.LEFT,
-                      border=10)
+        text = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Select threshold"))
+        self.selectThreshValue = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = (75, -1),
+                                             initial = UserSettings.Get(group = 'vdigit', key = "selectThresh", subkey = 'value'),
+                                             min = 1, max = 1e6)
+        units = wx.StaticText(parent = panel, id = wx.ID_ANY, size = (115, -1),
+                              label = UserSettings.Get(group = 'vdigit', key = "lineWidth", subkey = 'units'),
+                              style = wx.ALIGN_LEFT)
+        flexSizer.Add(text, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(self.selectThreshValue, proportion = 0, flag = wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
+        flexSizer.Add(units, proportion = 0, flag = wx.ALIGN_RIGHT | wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL | wx.LEFT,
+                      border = 10)
 
-        self.selectIn = wx.CheckBox(parent=panel, id=wx.ID_ANY,
-                                    label=_("Select only features inside of selection bounding box"))
-        self.selectIn.SetValue(UserSettings.Get(group='vdigit', key="selectInside", subkey='enabled'))
+        self.selectIn = wx.CheckBox(parent = panel, id = wx.ID_ANY,
+                                    label = _("Select only features inside of selection bounding box"))
+        self.selectIn.SetValue(UserSettings.Get(group = 'vdigit', key = "selectInside", subkey = 'enabled'))
         self.selectIn.SetToolTipString(_("By default are selected all features overlapping selection bounding box "))
         
-        self.checkForDupl = wx.CheckBox(parent=panel, id=wx.ID_ANY,
-                                        label=_("Check for duplicates"))
-        self.checkForDupl.SetValue(UserSettings.Get(group='vdigit', key="checkForDupl", subkey='enabled'))
+        self.checkForDupl = wx.CheckBox(parent = panel, id = wx.ID_ANY,
+                                        label = _("Check for duplicates"))
+        self.checkForDupl.SetValue(UserSettings.Get(group = 'vdigit', key = "checkForDupl", subkey = 'enabled'))
 
 
-        sizer.Add(item=flexSizer, proportion=0, flag=wx.EXPAND)
-        sizer.Add(item=self.selectIn, proportion=0, flag=wx.EXPAND | wx.ALL, border=1)
-        sizer.Add(item=self.checkForDupl, proportion=0, flag=wx.EXPAND | wx.ALL, border=1)        
-        border.Add(item=sizer, proportion=0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border=5)
+        sizer.Add(item = flexSizer, proportion = 0, flag = wx.EXPAND)
+        sizer.Add(item = self.selectIn, proportion = 0, flag = wx.EXPAND | wx.ALL, border = 1)
+        sizer.Add(item = self.checkForDupl, proportion = 0, flag = wx.EXPAND | wx.ALL, border = 1)        
+        border.Add(item = sizer, proportion = 0, flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
 
         #
         # digitize lines box
         #
-        box   = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Digitize line features"))
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Digitize line features"))
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
 
-        self.intersect = wx.CheckBox(parent=panel, label=_("Break lines at intersection"))
-        self.intersect.SetValue(UserSettings.Get(group='vdigit', key='breakLines', subkey='enabled'))
+        self.intersect = wx.CheckBox(parent = panel, label = _("Break lines at intersection"))
+        self.intersect.SetValue(UserSettings.Get(group = 'vdigit', key = 'breakLines', subkey = 'enabled'))
         
-        sizer.Add(item=self.intersect, proportion=0, flag=wx.ALL | wx.EXPAND, border=1)
+        sizer.Add(item = self.intersect, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 1)
 
-        border.Add(item=sizer, proportion=0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border=5)
+        border.Add(item = sizer, proportion = 0, flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
 
         #
         # save-on-exit box
         #
-        box   = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Save changes"))
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Save changes"))
         # save changes on exit?
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        self.save = wx.CheckBox(parent=panel, label=_("Save changes on exit"))
-        self.save.SetValue(UserSettings.Get(group='vdigit', key='saveOnExit', subkey='enabled'))
-        sizer.Add(item=self.save, proportion=0, flag=wx.ALL | wx.EXPAND, border=1)
-        border.Add(item=sizer, proportion=0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border=5)
+        self.save = wx.CheckBox(parent = panel, label = _("Save changes on exit"))
+        self.save.SetValue(UserSettings.Get(group = 'vdigit', key = 'saveOnExit', subkey = 'enabled'))
+        sizer.Add(item = self.save, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 1)
+        border.Add(item = sizer, proportion = 0, flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
 
         panel.SetSizer(border)
         
         return panel
 
-    def __CreateQueryPage(self, notebook):
+    def _createQueryPage(self, notebook):
         """!Create notebook page for query tool"""
+        panel = wx.Panel(parent = notebook, id = wx.ID_ANY)
+        notebook.AddPage(page = panel, text = _("Query tool"))
 
-        panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
-        notebook.AddPage(page=panel, text=_("Query tool"))
-
         border = wx.BoxSizer(wx.VERTICAL)
 
         #
         # query tool box
         #
-        box   = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Choose query tool"))
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Choose query tool"))
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
 
         LocUnits = self.parent.MapWindow.Map.GetProjInfo()['units']
 
-        self.queryBox = wx.CheckBox(parent=panel, id=wx.ID_ANY, label=_("Select by box"))
-        self.queryBox.SetValue(UserSettings.Get(group='vdigit', key="query", subkey='box'))
+        self.queryBox = wx.CheckBox(parent = panel, id = wx.ID_ANY, label = _("Select by box"))
+        self.queryBox.SetValue(UserSettings.Get(group = 'vdigit', key = "query", subkey = 'box'))
 
-        sizer.Add(item=self.queryBox, proportion=0, flag=wx.ALL | wx.EXPAND, border=1)
+        sizer.Add(item = self.queryBox, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 1)
         sizer.Add((0, 5))
 
         #
         # length
         #
-        self.queryLength = wx.RadioButton(parent=panel, id=wx.ID_ANY, label=_("length"))
+        self.queryLength = wx.RadioButton(parent = panel, id = wx.ID_ANY, label = _("length"))
         self.queryLength.Bind(wx.EVT_RADIOBUTTON, self.OnChangeQuery)
-        sizer.Add(item=self.queryLength, proportion=0, flag=wx.ALL | wx.EXPAND, border=1)
-        flexSizer = wx.FlexGridSizer (cols=4, hgap=5, vgap=5)
+        sizer.Add(item = self.queryLength, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 1)
+        flexSizer = wx.FlexGridSizer (cols = 4, hgap = 5, vgap = 5)
         flexSizer.AddGrowableCol(0)
-        txt = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Select lines"))
-        self.queryLengthSL = wx.Choice (parent=panel, id=wx.ID_ANY, 
-                                        choices = [_("shorter than"), _("longer than")])
-        self.queryLengthSL.SetSelection(UserSettings.Get(group='vdigit', key="queryLength", subkey='than-selection'))
-        self.queryLengthValue = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(100, -1),
-                                            initial=1,
-                                            min=0, max=1e6)
-        self.queryLengthValue.SetValue(UserSettings.Get(group='vdigit', key="queryLength", subkey='thresh'))
-        units = wx.StaticText(parent=panel, id=wx.ID_ANY, label="%s" % LocUnits)
-        flexSizer.Add(txt, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(self.queryLengthSL, proportion=0, flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
-        flexSizer.Add(self.queryLengthValue, proportion=0, flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
-        flexSizer.Add(units, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        sizer.Add(item=flexSizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=1)
+        txt = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Select lines"))
+        self.queryLengthSL = wx.Choice (parent = panel, id = wx.ID_ANY, 
+                                        choices  =  [_("shorter than"), _("longer than")])
+        self.queryLengthSL.SetSelection(UserSettings.Get(group = 'vdigit', key = "queryLength", subkey = 'than-selection'))
+        self.queryLengthValue = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = (100, -1),
+                                            initial = 1,
+                                            min = 0, max = 1e6)
+        self.queryLengthValue.SetValue(UserSettings.Get(group = 'vdigit', key = "queryLength", subkey = 'thresh'))
+        units = wx.StaticText(parent = panel, id = wx.ID_ANY, label = "%s" % LocUnits)
+        flexSizer.Add(txt, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(self.queryLengthSL, proportion = 0, flag = wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
+        flexSizer.Add(self.queryLengthValue, proportion = 0, flag = wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
+        flexSizer.Add(units, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        sizer.Add(item = flexSizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 1)
 
         #
         # dangle
         #
-        self.queryDangle = wx.RadioButton(parent=panel, id=wx.ID_ANY, label=_("dangle"))
+        self.queryDangle = wx.RadioButton(parent = panel, id = wx.ID_ANY, label = _("dangle"))
         self.queryDangle.Bind(wx.EVT_RADIOBUTTON, self.OnChangeQuery)
-        sizer.Add(item=self.queryDangle, proportion=0, flag=wx.ALL | wx.EXPAND, border=1)
-        flexSizer = wx.FlexGridSizer (cols=4, hgap=5, vgap=5)
+        sizer.Add(item = self.queryDangle, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 1)
+        flexSizer = wx.FlexGridSizer (cols = 4, hgap = 5, vgap = 5)
         flexSizer.AddGrowableCol(0)
-        txt = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Select dangles"))
-        self.queryDangleSL = wx.Choice (parent=panel, id=wx.ID_ANY, 
+        txt = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Select dangles"))
+        self.queryDangleSL = wx.Choice (parent = panel, id = wx.ID_ANY, 
                                         choices = [_("shorter than"), _("longer than")])
-        self.queryDangleSL.SetSelection(UserSettings.Get(group='vdigit', key="queryDangle", subkey='than-selection'))
-        self.queryDangleValue = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(100, -1),
-                                       initial=1,
-                                       min=0, max=1e6)
-        self.queryDangleValue.SetValue(UserSettings.Get(group='vdigit', key="queryDangle", subkey='thresh'))
-        units = wx.StaticText(parent=panel, id=wx.ID_ANY, label="%s" % LocUnits)
-        flexSizer.Add(txt, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(self.queryDangleSL, proportion=0, flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
-        flexSizer.Add(self.queryDangleValue, proportion=0, flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
-        flexSizer.Add(units, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        sizer.Add(item=flexSizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=1)
+        self.queryDangleSL.SetSelection(UserSettings.Get(group = 'vdigit', key = "queryDangle", subkey = 'than-selection'))
+        self.queryDangleValue = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = (100, -1),
+                                       initial = 1,
+                                       min = 0, max = 1e6)
+        self.queryDangleValue.SetValue(UserSettings.Get(group = 'vdigit', key = "queryDangle", subkey = 'thresh'))
+        units = wx.StaticText(parent = panel, id = wx.ID_ANY, label = "%s" % LocUnits)
+        flexSizer.Add(txt, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(self.queryDangleSL, proportion = 0, flag = wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
+        flexSizer.Add(self.queryDangleValue, proportion = 0, flag = wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
+        flexSizer.Add(units, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        sizer.Add(item = flexSizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 1)
 
-        if UserSettings.Get(group='vdigit', key="query", subkey='selection') == 0:
+        if UserSettings.Get(group = 'vdigit', key = "query", subkey = 'selection') == 0:
             self.queryLength.SetValue(True)
         else:
             self.queryDangle.SetValue(True)
@@ -1433,99 +364,78 @@
         # enable & disable items
         self.OnChangeQuery(None)
 
-        border.Add(item=sizer, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
+        border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
 
         panel.SetSizer(border)
         
         return panel
 
-    def __CreateAttributesPage(self, notebook):
-        """!Create notebook page for query tool"""
+    def _createAttributesPage(self, notebook):
+        """!Create notebook page for attributes"""
+        panel = wx.Panel(parent = notebook, id = wx.ID_ANY)
+        notebook.AddPage(page = panel, text = _("Attributes"))
 
-        panel = wx.Panel(parent=notebook, id=wx.ID_ANY)
-        notebook.AddPage(page=panel, text=_("Attributes"))
-
         border = wx.BoxSizer(wx.VERTICAL)
 
         #
         # add new record
         #
-        box   = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Digitize new feature"))
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Digitize new feature"))
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
 
         # checkbox
-        self.addRecord = wx.CheckBox(parent=panel, id=wx.ID_ANY,
-                                     label=_("Add new record into table"))
-        self.addRecord.SetValue(UserSettings.Get(group='vdigit', key="addRecord", subkey='enabled'))
-        sizer.Add(item=self.addRecord, proportion=0, flag=wx.ALL | wx.EXPAND, border=1)
+        self.addRecord = wx.CheckBox(parent = panel, id = wx.ID_ANY,
+                                     label = _("Add new record into table"))
+        self.addRecord.SetValue(UserSettings.Get(group = 'vdigit', key = "addRecord", subkey = 'enabled'))
+        sizer.Add(item = self.addRecord, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 1)
         # settings
-        flexSizer = wx.FlexGridSizer(cols=2, hgap=3, vgap=3)
+        flexSizer = wx.FlexGridSizer(cols = 2, hgap = 3, vgap = 3)
         flexSizer.AddGrowableCol(0)
         settings = ((_("Layer"), 1), (_("Category"), 1), (_("Mode"), _("Next to use")))
         # layer
-        text = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Layer"))
-        self.layer = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(125, -1),
+        text = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Layer"))
+        self.layer = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = (125, -1),
                                  min = 1, max = 1e3)
-        self.layer.SetValue(int(UserSettings.Get(group='vdigit', key="layer", subkey='value')))
-        flexSizer.Add(item=text, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(item=self.layer, proportion=0,
-                      flag=wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
+        self.layer.SetValue(int(UserSettings.Get(group = 'vdigit', key = "layer", subkey = 'value')))
+        flexSizer.Add(item = text, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(item = self.layer, proportion = 0,
+                      flag = wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
         # category number
-        text = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Category number"))
-        self.category = wx.SpinCtrl(parent=panel, id=wx.ID_ANY, size=(125, -1),
-                                    initial=UserSettings.Get(group='vdigit', key="category", subkey='value'),
-                                    min=-1e9, max=1e9) 
-        if UserSettings.Get(group='vdigit', key="categoryMode", subkey='selection') != 1:
+        text = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Category number"))
+        self.category = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = (125, -1),
+                                    initial = UserSettings.Get(group = 'vdigit', key = "category", subkey = 'value'),
+                                    min = -1e9, max = 1e9) 
+        if UserSettings.Get(group = 'vdigit', key = "categoryMode", subkey = 'selection') != 1:
             self.category.Enable(False)
-        flexSizer.Add(item=text, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(item=self.category, proportion=0,
-                      flag=wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(item = text, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(item = self.category, proportion = 0,
+                      flag = wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
         # category mode
-        text = wx.StaticText(parent=panel, id=wx.ID_ANY, label=_("Category mode"))
-        self.categoryMode = wx.Choice(parent=panel, id=wx.ID_ANY, size=(125, -1),
-                                      choices=[_("Next to use"), _("Manual entry"), _("No category")])
-        self.categoryMode.SetSelection(UserSettings.Get(group='vdigit', key="categoryMode", subkey='selection'))
-        flexSizer.Add(item=text, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(item=self.categoryMode, proportion=0,
-                      flag=wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
+        text = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Category mode"))
+        self.categoryMode = wx.Choice(parent = panel, id = wx.ID_ANY, size = (125, -1),
+                                      choices = [_("Next to use"), _("Manual entry"), _("No category")])
+        self.categoryMode.SetSelection(UserSettings.Get(group = 'vdigit', key = "categoryMode", subkey = 'selection'))
+        flexSizer.Add(item = text, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(item = self.categoryMode, proportion = 0,
+                      flag = wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
 
-        sizer.Add(item=flexSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=1)
-        border.Add(item=sizer, proportion=0,
-                   flag=wx.ALL | wx.EXPAND, border=5)
+        sizer.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
+        border.Add(item = sizer, proportion = 0,
+                   flag = wx.ALL | wx.EXPAND, border = 5)
 
         #
-        # digitize new area
-        #
-        box   = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Digitize new area"))
-        sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        
-        # add centroid
-        self.addCentroid = wx.CheckBox(parent=panel, id=wx.ID_ANY,
-                                       label=_("Add centroid to left/right area"))
-        self.addCentroid.SetValue(UserSettings.Get(group='vdigit', key="addCentroid", subkey='enabled'))
-        sizer.Add(item=self.addCentroid, proportion=0, flag=wx.ALL | wx.EXPAND, border=1)
-        
-        # attach category to boundary
-        self.catBoundary = wx.CheckBox(parent=panel, id=wx.ID_ANY,
-                                       label=_("Do not attach category to boundaries"))
-        self.catBoundary.SetValue(UserSettings.Get(group='vdigit', key="catBoundary", subkey='enabled'))
-        sizer.Add(item=self.catBoundary, proportion=0, flag=wx.ALL | wx.EXPAND, border=1)
-        border.Add(item=sizer, proportion=0,
-                   flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
-        
-        #
         # delete existing record
         #
-        box   = wx.StaticBox (parent=panel, id=wx.ID_ANY, label=" %s " % _("Delete existing feature(s)"))
+        box   = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Delete existing feature(s)"))
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
         
         # checkbox
-        self.deleteRecord = wx.CheckBox(parent=panel, id=wx.ID_ANY,
-                                        label=_("Delete record from table"))
-        self.deleteRecord.SetValue(UserSettings.Get(group='vdigit', key="delRecord", subkey='enabled'))
-        sizer.Add(item=self.deleteRecord, proportion=0, flag=wx.ALL | wx.EXPAND, border=1)
-        border.Add(item=sizer, proportion=0,
-                   flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
+        self.deleteRecord = wx.CheckBox(parent = panel, id = wx.ID_ANY,
+                                        label = _("Delete record from table"))
+        self.deleteRecord.SetValue(UserSettings.Get(group = 'vdigit', key = "delRecord", subkey = 'enabled'))
+        sizer.Add(item = self.deleteRecord, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 1)
+        border.Add(item = sizer, proportion = 0,
+                   flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 5)
 
         #
         # geometry attributes (currently only length and area are supported)
@@ -1533,7 +443,7 @@
         box   = wx.StaticBox (parent = panel, id = wx.ID_ANY,
                               label = " %s " % _("Geometry attributes"))
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        gridSizer = wx.GridBagSizer(hgap=3, vgap=3)
+        gridSizer = wx.GridBagSizer(hgap = 3, vgap = 3)
         gridSizer.AddGrowableCol(0)
         self.geomAttrb = { 'length' : { 'label' : _('length') },
                            'area' : { 'label' : _('area') },
@@ -1544,7 +454,7 @@
             vectorName = digitToolbar.GetLayer().GetName()
         except AttributeError:
             vectorName = None # no vector selected for editing
-        layer = UserSettings.Get(group='vdigit', key="layer", subkey='value')
+        layer = UserSettings.Get(group = 'vdigit', key = "layer", subkey = 'value')
         mapLayer = self.parent.toolbars['vdigit'].GetLayer()
         tree = self.parent.tree
         item = tree.FindItemByData('maplayer', mapLayer)
@@ -1556,7 +466,7 @@
             ### self.deleteRecord.SetValue(UserSettings.Get(group='vdigit', key="delRecord", subkey='enabled'))
             check.Bind(wx.EVT_CHECKBOX, self.OnGeomAttrb)
             # column (only numeric)
-            column = gselect.ColumnSelect(parent = panel, size=(200, -1))
+            column = gselect.ColumnSelect(parent = panel, size = (200, -1))
             column.InsertColumns(vector = vectorName,
                                  layer = layer, excludeKey = True,
                                  type = ['integer', 'double precision'])
@@ -1566,13 +476,13 @@
             else:
                 choices = Units.GetUnitsList('length')
             win_units = wx.Choice(parent = panel, id = wx.ID_ANY,
-                                  choices = choices, size=(120, -1))
+                                  choices = choices, size = (120, -1))
             
             # default values
             check.SetValue(False)
             if item and tree.GetPyData(item)[0]['vdigit'] and \
-                    tree.GetPyData(item)[0]['vdigit'].has_key('geomAttr') and \
-                    tree.GetPyData(item)[0]['vdigit']['geomAttr'].has_key(attrb):
+                    'geomAttr' in tree.GetPyData(item)[0]['vdigit'] and \
+                    attrb in tree.GetPyData(item)[0]['vdigit']['geomAttr']:
                 check.SetValue(True)
                 column.SetStringSelection(tree.GetPyData(item)[0]['vdigit']['geomAttr'][attrb]['column'])
                 if attrb == 'area':
@@ -1604,16 +514,16 @@
             row += 1
         
         note = '\n'.join(textwrap.wrap(_("Note: These settings are stored "
-                                         " in the workspace not in the vector digitizer "
+                                         "in the workspace not in the vector digitizer "
                                          "preferences."), 55))
         gridSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY,
                                            label = note),
-                      pos = (3, 0), span=(1, 3))
+                      pos = (3, 0), span = (1, 3))
                       
-        sizer.Add(item=gridSizer, proportion=1,
-                  flag=wx.ALL | wx.EXPAND, border=1)
-        border.Add(item=sizer, proportion=0,
-                   flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
+        sizer.Add(item = gridSizer, proportion = 1,
+                  flag = wx.ALL | wx.EXPAND, border = 1)
+        border.Add(item = sizer, proportion = 0,
+                   flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 5)
 
         # bindings
         self.Bind(wx.EVT_CHECKBOX, self.OnChangeAddRecord, self.addRecord)
@@ -1624,9 +534,8 @@
         
         return panel
 
-    def __SymbologyData(self):
-        """
-        Data for __CreateSymbologyPage()
+    def _symbologyData(self):
+        """!Data for _createSymbologyPage()
 
         label | checkbox | color
         """
@@ -1650,7 +559,8 @@
             (_("Direction"), "direction"),)
 
     def OnGeomAttrb(self, event):
-        """!Register geometry attributes (enable/disable)"""
+        """!Register geometry attributes (enable/disable)
+        """
         checked = event.IsChecked()
         id = event.GetId()
         key = None
@@ -1666,48 +576,51 @@
             column.Enable(False)
         
     def OnChangeCategoryMode(self, event):
-        """!Change category mode"""
-
+        """!Change category mode
+        """
         mode = event.GetSelection()
-        UserSettings.Set(group='vdigit', key="categoryMode", subkey='selection', value=mode)
+        UserSettings.Set(group = 'vdigit', key = "categoryMode", subkey = 'selection', value = mode)
         if mode == 1: # manual entry
             self.category.Enable(True)
         elif self.category.IsEnabled(): # disable
             self.category.Enable(False)
-
+        
         if mode == 2 and self.addRecord.IsChecked(): # no category
             self.addRecord.SetValue(False)
-
+        
         self.parent.digit.SetCategory()
-        self.category.SetValue(UserSettings.Get(group='vdigit', key='category', subkey='value'))
+        self.category.SetValue(UserSettings.Get(group = 'vdigit', key = 'category', subkey = 'value'))
 
     def OnChangeLayer(self, event):
-        """!Layer changed"""
+        """!Layer changed
+        """
         layer = event.GetInt()
         if layer > 0:
-            UserSettings.Set(group='vdigit', key='layer', subkey='value', value=layer)
+            UserSettings.Set(group = 'vdigit', key = 'layer', subkey = 'value', value = layer)
             self.parent.digit.SetCategory()
-            self.category.SetValue(UserSettings.Get(group='vdigit', key='category', subkey='value'))
+            self.category.SetValue(UserSettings.Get(group = 'vdigit', key = 'category', subkey = 'value'))
             
         event.Skip()
 
     def OnChangeAddRecord(self, event):
-        """!Checkbox 'Add new record' status changed"""
+        """!Checkbox 'Add new record' status changed
+        """
         self.category.SetValue(self.parent.digit.SetCategory())
             
     def OnChangeSnappingValue(self, event):
-        """!Change snapping value - update static text"""
+        """!Change snapping value - update static text
+        """
         value = self.snappingValue.GetValue()
         
         if value < 0:
             region = self.parent.MapWindow.Map.GetRegion()
             res = (region['nsres'] + region['ewres']) / 2.
-            threshold = self.parent.digit.driver.GetThreshold(value=res)
+            threshold = self.parent.digit.GetDisplay().GetThreshold(value = res)
         else:
             if self.snappingUnit.GetStringSelection() == "map units":
                 threshold = value
             else:
-                threshold = self.parent.digit.driver.GetThreshold(value=value)
+                threshold = self.parent.digit.GetDisplay().GetThreshold(value = value)
             
         if value == 0:
             self.snappingInfo.SetLabel(_("Snapping disabled"))
@@ -1724,10 +637,11 @@
         event.Skip()
 
     def OnChangeSnappingUnits(self, event):
-        """!Snapping units change -> update static text"""
+        """!Snapping units change -> update static text
+        """
         value = self.snappingValue.GetValue()
         units = self.snappingUnit.GetStringSelection()
-        threshold = self.parent.digit.driver.GetThreshold(value=value, units=units)
+        threshold = self.parent.digit.GetDisplay().GetThreshold(value = value, units = units)
 
         if units == "map units":
             self.snappingInfo.SetLabel(_("Snapping threshold is %(value).1f %(units)s") % 
@@ -1741,7 +655,8 @@
         event.Skip()
 
     def OnChangeQuery(self, event):
-        """!Change query"""
+        """!Change query
+        """
         if self.queryLength.GetValue():
             # length
             self.queryLengthSL.Enable(True)
@@ -1756,13 +671,14 @@
             self.queryDangleValue.Enable(True)
 
     def OnSave(self, event):
-        """!Button 'Save' clicked"""
+        """!Button 'Save' pressed
+        """
         self.UpdateSettings()
         self.parent.toolbars['vdigit'].settingsDialog = None
 
         fileSettings = {}
-        UserSettings.ReadSettingsFile(settings=fileSettings)
-        fileSettings['vdigit'] = UserSettings.Get(group='vdigit')
+        UserSettings.ReadSettingsFile(settings = fileSettings)
+        fileSettings['vdigit'] = UserSettings.Get(group = 'vdigit')
         
         file = UserSettings.SaveToFile(fileSettings)
         self.parent.GetLayerManager().goutput.WriteLog(_('Vector digitizer settings saved to file <%s>.') % file)
@@ -1772,11 +688,13 @@
         event.Skip()
         
     def OnApply(self, event):
-        """!Button 'Apply' clicked"""
+        """!Button 'Apply' pressed
+        """
         self.UpdateSettings()
 
     def OnCancel(self, event):
-        """!Button 'Cancel' clicked"""
+        """!Button 'Cancel' pressed
+        """
         self.parent.toolbars['vdigit'].settingsDialog = None
         self.Destroy()
 
@@ -1784,52 +702,47 @@
             event.Skip()
         
     def UpdateSettings(self):
-        """!Update UserSettings"""
-
+        """!Update digitizer settings
+        """
+        self.parent.GetLayerManager().WorkspaceChanged() # geometry attributes
         # symbology
         for key, (enabled, color) in self.symbology.iteritems():
             if enabled:
-                UserSettings.Set(group='vdigit', key='symbol',
-                                 subkey=[key, 'enabled'],
-                                 value=enabled.IsChecked())
-                UserSettings.Set(group='vdigit', key='symbol',
-                                 subkey=[key, 'color'],
-                                 value=tuple(color.GetColour()))
+                UserSettings.Set(group = 'vdigit', key = 'symbol',
+                                 subkey = [key, 'enabled'],
+                                 value = enabled.IsChecked())
+                UserSettings.Set(group = 'vdigit', key = 'symbol',
+                                 subkey = [key, 'color'],
+                                 value = tuple(color.GetColour()))
             else:
-                UserSettings.Set(group='vdigit', key='symbol',
-                                 subkey=[key, 'color'],
-                                 value=tuple(color.GetColour()))
+                UserSettings.Set(group = 'vdigit', key = 'symbol',
+                                 subkey = [key, 'color'],
+                                 value = tuple(color.GetColour()))
         # display
-        UserSettings.Set(group='vdigit', key="lineWidth", subkey='value',
-                         value=int(self.lineWidthValue.GetValue()))
+        UserSettings.Set(group = 'vdigit', key = "lineWidth", subkey = 'value',
+                         value = int(self.lineWidthValue.GetValue()))
 
         # snapping
-        UserSettings.Set(group='vdigit', key="snapping", subkey='value',
-                         value=int(self.snappingValue.GetValue()))
-        UserSettings.Set(group='vdigit', key="snapping", subkey='units',
-                         value=self.snappingUnit.GetStringSelection())
-        UserSettings.Set(group='vdigit', key="snapToVertex", subkey='enabled',
-                         value=self.snapVertex.IsChecked())
+        UserSettings.Set(group = 'vdigit', key = "snapping", subkey = 'value',
+                         value = int(self.snappingValue.GetValue()))
+        UserSettings.Set(group = 'vdigit', key = "snapping", subkey = 'units',
+                         value = self.snappingUnit.GetStringSelection())
+        UserSettings.Set(group = 'vdigit', key = "snapToVertex", subkey = 'enabled',
+                         value = self.snapVertex.IsChecked())
         
         # digitize new feature
-        UserSettings.Set(group='vdigit', key="addRecord", subkey='enabled',
-                         value=self.addRecord.IsChecked())
-        UserSettings.Set(group='vdigit', key="layer", subkey='value',
-                         value=int(self.layer.GetValue()))
-        UserSettings.Set(group='vdigit', key="category", subkey='value',
-                         value=int(self.category.GetValue()))
-        UserSettings.Set(group='vdigit', key="categoryMode", subkey='selection',
-                         value=self.categoryMode.GetSelection())
+        UserSettings.Set(group = 'vdigit', key = "addRecord", subkey = 'enabled',
+                         value = self.addRecord.IsChecked())
+        UserSettings.Set(group = 'vdigit', key = "layer", subkey = 'value',
+                         value = int(self.layer.GetValue()))
+        UserSettings.Set(group = 'vdigit', key = "category", subkey = 'value',
+                         value = int(self.category.GetValue()))
+        UserSettings.Set(group = 'vdigit', key = "categoryMode", subkey = 'selection',
+                         value = self.categoryMode.GetSelection())
 
-        # digitize new area
-        UserSettings.Set(group='vdigit', key="addCentroid", subkey='enabled',
-                         value=self.addCentroid.IsChecked())
-        UserSettings.Set(group='vdigit', key="catBoundary", subkey='enabled',
-                         value=self.catBoundary.IsChecked())
-        
         # delete existing feature
-        UserSettings.Set(group='vdigit', key="delRecord", subkey='enabled',
-                         value=self.deleteRecord.IsChecked())
+        UserSettings.Set(group = 'vdigit', key = "delRecord", subkey = 'enabled',
+                         value = self.deleteRecord.IsChecked())
 
         # geometry attributes (workspace)
         mapLayer = self.parent.toolbars['vdigit'].GetLayer()
@@ -1852,55 +765,48 @@
                                                                        'units' : unitsKey }
             else:
                 if item and tree.GetPyData(item)[0]['vdigit'] and \
-                        tree.GetPyData(item)[0]['vdigit']['geomAttr'].has_key(key):
+                        key in tree.GetPyData(item)[0]['vdigit']['geomAttr']:
                     del tree.GetPyData(item)[0]['vdigit']['geomAttr'][key]
         
-        # snapping threshold
-        self.parent.digit.threshold = self.parent.digit.driver.GetThreshold()
-
         # query tool
         if self.queryLength.GetValue():
-            UserSettings.Set(group='vdigit', key="query", subkey='selection',
-                             value=0)
+            UserSettings.Set(group = 'vdigit', key = "query", subkey = 'selection',
+                             value = 0)
         else:
-            UserSettings.Set(group='vdigit', key="query", subkey='type',
-                             value=1)
-        UserSettings.Set(group='vdigit', key="query", subkey='box',
-                         value=self.queryBox.IsChecked())
-        UserSettings.Set(group='vdigit', key="queryLength", subkey='than-selection',
-                         value=self.queryLengthSL.GetSelection())
-        UserSettings.Set(group='vdigit', key="queryLength", subkey='thresh',
-                         value=int(self.queryLengthValue.GetValue()))
-        UserSettings.Set(group='vdigit', key="queryDangle", subkey='than-selection',
-                         value=self.queryDangleSL.GetSelection())
-        UserSettings.Set(group='vdigit', key="queryDangle", subkey='thresh',
-                         value=int(self.queryDangleValue.GetValue()))
+            UserSettings.Set(group = 'vdigit', key = "query", subkey = 'type',
+                             value = 1)
+        UserSettings.Set(group = 'vdigit', key = "query", subkey = 'box',
+                         value = self.queryBox.IsChecked())
+        UserSettings.Set(group = 'vdigit', key = "queryLength", subkey = 'than-selection',
+                         value = self.queryLengthSL.GetSelection())
+        UserSettings.Set(group = 'vdigit', key = "queryLength", subkey = 'thresh',
+                         value = int(self.queryLengthValue.GetValue()))
+        UserSettings.Set(group = 'vdigit', key = "queryDangle", subkey = 'than-selection',
+                         value = self.queryDangleSL.GetSelection())
+        UserSettings.Set(group = 'vdigit', key = "queryDangle", subkey = 'thresh',
+                         value = int(self.queryDangleValue.GetValue()))
 
         # select features
         for feature in ('point', 'line',
                         'centroid', 'boundary'):
-            UserSettings.Set(group='vdigit', key='selectType',
-                             subkey=[feature, 'enabled'],
-                             value=self.FindWindowById(self.selectFeature[feature]).IsChecked())
-        UserSettings.Set(group='vdigit', key="selectThresh", subkey='value',
-                         value=int(self.selectThreshValue.GetValue()))
-        UserSettings.Set(group='vdigit', key="checkForDupl", subkey='enabled',
-                         value=self.checkForDupl.IsChecked())
-        UserSettings.Set(group='vdigit', key="selectInside", subkey='enabled',
-                         value=self.selectIn.IsChecked())
+            UserSettings.Set(group = 'vdigit', key = 'selectType',
+                             subkey = [feature, 'enabled'],
+                             value = self.FindWindowById(self.selectFeature[feature]).IsChecked())
+        UserSettings.Set(group = 'vdigit', key = "selectThresh", subkey = 'value',
+                         value = int(self.selectThreshValue.GetValue()))
+        UserSettings.Set(group = 'vdigit', key = "checkForDupl", subkey = 'enabled',
+                         value = self.checkForDupl.IsChecked())
+        UserSettings.Set(group = 'vdigit', key = "selectInside", subkey = 'enabled',
+                         value = self.selectIn.IsChecked())
 
         # on-exit
-        UserSettings.Set(group='vdigit', key="saveOnExit", subkey='enabled',
-                         value=self.save.IsChecked())
+        UserSettings.Set(group = 'vdigit', key = "saveOnExit", subkey = 'enabled',
+                         value = self.save.IsChecked())
 
         # break lines
-        UserSettings.Set(group='vdigit', key="breakLines", subkey='enabled',
-                         value=self.intersect.IsChecked())
+        UserSettings.Set(group = 'vdigit', key = "breakLines", subkey = 'enabled',
+                         value = self.intersect.IsChecked())
         
-        # update driver settings
-        self.parent.digit.driver.UpdateSettings()
-
-        # update digit settings
         self.parent.digit.UpdateSettings()
         
         # redraw map if auto-rendering is enabled
@@ -1908,21 +814,19 @@
             self.parent.OnRender(None)
 
 class VDigitCategoryDialog(wx.Dialog, listmix.ColumnSorterMixin):
-    """
-    Dialog used to display/modify categories of vector objects
-    
-    @param parent
-    @param title dialog title
-    @param query {coordinates, qdist} - used by v.edit/v.what
-    @param cats  directory of lines (layer/categories) - used by vdigit
-    @param pos
-    @param style
-    """
     def __init__(self, parent, title,
-                 map, query=None, cats=None,
-                 pos=wx.DefaultPosition,
-                 style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
-
+                 map, query = None, cats = None,
+                 pos = wx.DefaultPosition,
+                 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
+        """!Dialog used to display/modify categories of vector objects
+        
+        @param parent
+        @param title dialog title
+        @param query {coordinates, qdist} - used by v.edit/v.what
+        @param cats  directory of lines (layer/categories) - used by vdigit
+        @param pos
+        @param style
+        """
         # parent
         self.parent = parent # mapdisplay.BufferedWindow class instance
 
@@ -1934,7 +838,7 @@
         
         # do not display dialog if no line is found (-> self.cats)
         if cats is None:
-            if self.__GetCategories(query[0], query[1]) == 0 or not self.line:
+            if self._getCategories(query[0], query[1]) == 0 or not self.line:
                 Debug.msg(3, "VDigitCategoryDialog(): nothing found!")
         else:
             self.cats = cats
@@ -1949,15 +853,15 @@
         # make copy of cats (used for 'reload')
         self.cats_orig = copy.deepcopy(self.cats)
         
-        wx.Dialog.__init__(self, parent=self.parent, id=wx.ID_ANY, title=title,
-                          style=style, pos=pos)
+        wx.Dialog.__init__(self, parent = self.parent, id = wx.ID_ANY, title = title,
+                          style = style, pos = pos)
         
         # list of categories
-        box = wx.StaticBox(parent=self, id=wx.ID_ANY,
-                           label=" %s " % _("List of categories - right-click to delete"))
+        box = wx.StaticBox(parent = self, id = wx.ID_ANY,
+                           label = " %s " % _("List of categories - right-click to delete"))
         listSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        self.list = CategoryListCtrl(parent=self, id=wx.ID_ANY,
-                                     style=wx.LC_REPORT |
+        self.list = CategoryListCtrl(parent = self, id = wx.ID_ANY,
+                                     style = wx.LC_REPORT |
                                      wx.BORDER_NONE |
                                      wx.LC_SORT_ASCENDING |
                                      wx.LC_HRULES |
@@ -1966,10 +870,10 @@
         self.fid = self.cats.keys()[0]
         self.itemDataMap = self.list.Populate(self.cats[self.fid])
         listmix.ColumnSorterMixin.__init__(self, 2)
-        self.fidMulti = wx.Choice(parent=self, id=wx.ID_ANY,
-                                  size=(150, -1))
+        self.fidMulti = wx.Choice(parent = self, id = wx.ID_ANY,
+                                  size = (150, -1))
         self.fidMulti.Bind(wx.EVT_CHOICE, self.OnFeature)
-        self.fidText = wx.StaticText(parent=self, id=wx.ID_ANY)
+        self.fidText = wx.StaticText(parent = self, id = wx.ID_ANY)
         if len(self.cats.keys()) == 1:
             self.fidMulti.Show(False)
             self.fidText.SetLabel(str(self.fid))
@@ -1981,44 +885,44 @@
             self.fidMulti.SetItems(choices)
             self.fidMulti.SetSelection(0)
         
-        listSizer.Add(item=self.list, proportion=1, flag=wx.EXPAND)
+        listSizer.Add(item = self.list, proportion = 1, flag = wx.EXPAND)
 
         # add new category
-        box = wx.StaticBox(parent=self, id=wx.ID_ANY,
-                           label=" %s " % _("Add new category"))
+        box = wx.StaticBox(parent = self, id = wx.ID_ANY,
+                           label = " %s " % _("Add new category"))
         addSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        flexSizer = wx.FlexGridSizer (cols=5, hgap=5, vgap=5)
+        flexSizer = wx.FlexGridSizer (cols = 5, hgap = 5, vgap = 5)
         flexSizer.AddGrowableCol(3)
 
-        layerNewTxt = wx.StaticText(parent=self, id=wx.ID_ANY,
-                                 label="%s:" % _("Layer"))
-        self.layerNew = wx.Choice(parent=self, id=wx.ID_ANY, size=(75, -1),
-                                  choices=layers)
+        layerNewTxt = wx.StaticText(parent = self, id = wx.ID_ANY,
+                                 label = "%s:" % _("Layer"))
+        self.layerNew = wx.Choice(parent = self, id = wx.ID_ANY, size = (75, -1),
+                                  choices = layers)
         if len(layers) > 0:
             self.layerNew.SetSelection(0)
         
-        catNewTxt = wx.StaticText(parent=self, id=wx.ID_ANY,
-                               label="%s:" % _("Category"))
+        catNewTxt = wx.StaticText(parent = self, id = wx.ID_ANY,
+                               label = "%s:" % _("Category"))
 
         try:
             newCat = max(self.cats[self.fid][1]) + 1
         except KeyError:
             newCat = 1
-        self.catNew = wx.SpinCtrl(parent=self, id=wx.ID_ANY, size=(75, -1),
-                                  initial=newCat, min=0, max=1e9)
+        self.catNew = wx.SpinCtrl(parent = self, id = wx.ID_ANY, size = (75, -1),
+                                  initial = newCat, min = 0, max = 1e9)
         btnAddCat = wx.Button(self, wx.ID_ADD)
-        flexSizer.Add(item=layerNewTxt, proportion=0,
-                      flag=wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(item=self.layerNew, proportion=0,
-                      flag=wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(item=catNewTxt, proportion=0,
-                      flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT,
-                      border=10)
-        flexSizer.Add(item=self.catNew, proportion=0,
-                      flag=wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(item=btnAddCat, proportion=0,
-                      flag=wx.EXPAND | wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
-        addSizer.Add(item=flexSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=5)
+        flexSizer.Add(item = layerNewTxt, proportion = 0,
+                      flag = wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(item = self.layerNew, proportion = 0,
+                      flag = wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(item = catNewTxt, proportion = 0,
+                      flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT,
+                      border = 10)
+        flexSizer.Add(item = self.catNew, proportion = 0,
+                      flag = wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(item = btnAddCat, proportion = 0,
+                      flag = wx.EXPAND | wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
+        addSizer.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 5)
 
         # buttons
         btnApply = wx.Button(self, wx.ID_APPLY)
@@ -2039,24 +943,24 @@
         btnSizer.Realize()
         
         mainSizer = wx.BoxSizer(wx.VERTICAL)
-        mainSizer.Add(item=listSizer, proportion=1,
-                      flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
-        mainSizer.Add(item=addSizer, proportion=0,
-                      flag=wx.EXPAND | wx.ALIGN_CENTER |
-                      wx.LEFT | wx.RIGHT | wx.BOTTOM, border=5)
+        mainSizer.Add(item = listSizer, proportion = 1,
+                      flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
+        mainSizer.Add(item = addSizer, proportion = 0,
+                      flag = wx.EXPAND | wx.ALIGN_CENTER |
+                      wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
         fidSizer = wx.BoxSizer(wx.HORIZONTAL)
-        fidSizer.Add(item=wx.StaticText(parent=self, id=wx.ID_ANY,
-                                        label=_("Feature id:")),
-                     proportion=0, border=5,
-                     flag=wx.ALIGN_CENTER_VERTICAL)
-        fidSizer.Add(item=self.fidMulti, proportion=0,
-                     flag=wx.EXPAND | wx.ALL,  border=5)
-        fidSizer.Add(item=self.fidText, proportion=0,
-                     flag=wx.EXPAND | wx.ALL,  border=5)
-        mainSizer.Add(item=fidSizer, proportion=0,
-                      flag=wx.EXPAND | wx.ALL, border=5)
-        mainSizer.Add(item=btnSizer, proportion=0,
-                      flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
+        fidSizer.Add(item = wx.StaticText(parent = self, id = wx.ID_ANY,
+                                        label = _("Feature id:")),
+                     proportion = 0, border = 5,
+                     flag = wx.ALIGN_CENTER_VERTICAL)
+        fidSizer.Add(item = self.fidMulti, proportion = 0,
+                     flag = wx.EXPAND | wx.ALL,  border = 5)
+        fidSizer.Add(item = self.fidText, proportion = 0,
+                     flag = wx.EXPAND | wx.ALL,  border = 5)
+        mainSizer.Add(item = fidSizer, proportion = 0,
+                      flag = wx.EXPAND | wx.ALL, border = 5)
+        mainSizer.Add(item = btnSizer, proportion = 0,
+                      flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
         
         self.SetSizer(mainSizer)
         mainSizer.Fit(self)
@@ -2066,16 +970,12 @@
         self.SetMinSize(self.GetBestSize())
 
         # bindings
-        # buttons
-        #btnReload.Bind(wx.EVT_BUTTON, self.OnReload)
         btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
         btnOk.Bind(wx.EVT_BUTTON, self.OnOK)
         btnAddCat.Bind(wx.EVT_BUTTON, self.OnAddCat)
         btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
                                      
         # list
-        # self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected, self.list)
-        # self.list.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
         self.list.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.OnRightUp) #wxMSW
         self.list.Bind(wx.EVT_RIGHT_UP, self.OnRightUp) #wxGTK
         self.Bind(wx.EVT_LIST_BEGIN_LABEL_EDIT, self.OnBeginEdit, self.list)
@@ -2083,19 +983,23 @@
         self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick, self.list)
 
     def GetListCtrl(self):
-        """!Used by ColumnSorterMixin"""
+        """!Used by ColumnSorterMixin
+        """
         return self.list
 
     def OnColClick(self, event):
-        """!Click on column header (order by)"""
+        """!Click on column header (order by)
+        """
         event.Skip()
         
     def OnBeginEdit(self, event):
-        """!Editing of item started"""
+        """!Editing of item started
+        """
         event.Allow()
 
     def OnEndEdit(self, event):
-        """!Finish editing of item"""
+        """!Finish editing of item
+        """
         itemIndex = event.GetIndex()
         layerOld = int (self.list.GetItem(itemIndex, 0).GetText())
         catOld = int (self.list.GetItem(itemIndex, 1).GetText())
@@ -2127,7 +1031,8 @@
             return False
 
     def OnRightDown(self, event):
-        """!Mouse right button down"""
+        """!Mouse right button down
+        """
         x = event.GetX()
         y = event.GetY()
         item, flags = self.list.HitTest((x, y))
@@ -2139,14 +1044,15 @@
         event.Skip()
 
     def OnRightUp(self, event):
-        """!Mouse right button up"""
+        """!Mouse right button up
+        """
         if not hasattr(self, "popupID1"):
             self.popupID1 = wx.NewId()
             self.popupID2 = wx.NewId()
             self.popupID3 = wx.NewId()
-            self.Bind(wx.EVT_MENU, self.OnItemDelete,    id=self.popupID1)
-            self.Bind(wx.EVT_MENU, self.OnItemDeleteAll, id=self.popupID2)
-            self.Bind(wx.EVT_MENU, self.OnReload, id=self.popupID3)
+            self.Bind(wx.EVT_MENU, self.OnItemDelete,    id = self.popupID1)
+            self.Bind(wx.EVT_MENU, self.OnItemDeleteAll, id = self.popupID2)
+            self.Bind(wx.EVT_MENU, self.OnReload, id = self.popupID3)
 
         # generate popup-menu
         menu = wx.Menu()
@@ -2162,11 +1068,13 @@
         menu.Destroy()
 
     def OnItemSelected(self, event):
-        """!Item selected"""
+        """!Item selected
+        """
         event.Skip()
 
     def OnItemDelete(self, event):
-        """!Delete selected item(s) from the list (layer/category pair)"""
+        """!Delete selected item(s) from the list (layer/category pair)
+        """
         item = self.list.GetFirstSelected()
         while item != -1:
             layer = int (self.list.GetItem(item, 0).GetText())
@@ -2179,18 +1087,20 @@
         event.Skip()
         
     def OnItemDeleteAll(self, event):
-        """!Delete all items from the list"""
+        """!Delete all items from the list
+        """
         self.list.DeleteAllItems()
         self.cats[self.fid] = {}
 
         event.Skip()
 
     def OnFeature(self, event):
-        """!Feature id changed (on duplicates)"""
+        """!Feature id changed (on duplicates)
+        """
         self.fid = int(event.GetString())
         
         self.itemDataMap = self.list.Populate(self.cats[self.fid],
-                                              update=True)
+                                              update = True)
 
         try:
             newCat = max(self.cats[self.fid][1]) + 1
@@ -2201,12 +1111,12 @@
         
         event.Skip()
         
-    def __GetCategories(self, coords, qdist):
+    def _getCategories(self, coords, qdist):
         """!Get layer/category pairs for all available
         layers
 
-        Return True line found or False if not found"""
-        
+        Return True line found or False if not found
+        """
         ret = gcmd.RunCommand('v.what',
                               parent = self,
                               quiet = True,
@@ -2232,35 +1142,42 @@
         return True
 
     def OnReload(self, event):
-        """!Reload button pressed"""
+        """!Reload button pressed
+        """
         # restore original list
         self.cats = copy.deepcopy(self.cats_orig)
 
         # polulate list
         self.itemDataMap = self.list.Populate(self.cats[self.fid],
-                                              update=True)
+                                              update = True)
 
         event.Skip()
 
     def OnCancel(self, event):
-        """!Cancel button pressed"""
+        """!Cancel button pressed
+        """
         self.parent.parent.dialogs['category'] = None
         if self.parent.parent.digit:
-            self.parent.parent.digit.driver.SetSelected([])
-            self.parent.UpdateMap(render=False)
+            self.parent.parent.digit.GetDisplay().SetSelected([])
+            self.parent.UpdateMap(render = False)
         else:
             self.parent.parent.OnRender(None)
             
         self.Close()
 
     def OnApply(self, event):
-        """!Apply button pressed"""
+        """!Apply button pressed
+        """
         for fid in self.cats.keys():
             newfid = self.ApplyChanges(fid)
             if fid == self.fid:
                 self.fid = newfid
             
     def ApplyChanges(self, fid):
+        """!Apply changes 
+
+        @param fid feature id
+        """
         cats = self.cats[fid]
         cats_orig = self.cats_orig[fid]
 
@@ -2299,20 +1216,22 @@
                     
                     fid = newfid
                     if self.fid < 0:
-                        wx.MessageBox(parent=self, message=_("Unable to update vector map."),
-                                      caption=_("Error"), style=wx.OK | wx.ICON_ERROR)
+                        wx.MessageBox(parent = self, message = _("Unable to update vector map."),
+                                      caption = _("Error"), style = wx.OK | wx.ICON_ERROR)
         
         self.cats_orig[fid] = copy.deepcopy(cats)
         
         return newfid
 
     def OnOK(self, event):
-        """!OK button pressed"""
+        """!OK button pressed
+        """
         self.OnApply(event)
         self.OnCancel(event)
 
     def OnAddCat(self, event):
-        """!Button 'Add' new category pressed"""
+        """!Button 'Add' new category pressed
+        """
         try:
             layer = int(self.layerNew.GetStringSelection())
             cat   = int(self.catNew.GetValue())
@@ -2336,7 +1255,7 @@
 
         # reload list
         self.itemDataMap = self.list.Populate(self.cats[self.fid],
-                                              update=True)
+                                              update = True)
 
         # update category number for add
         self.catNew.SetValue(cat + 1)
@@ -2346,13 +1265,14 @@
         return True
 
     def GetLine(self):
-        """!Get id of selected line of 'None' if no line is selected"""
+        """!Get id of selected line of 'None' if no line is selected
+        """
         return self.cats.keys()
 
-    def UpdateDialog(self, query=None, cats=None):
+    def UpdateDialog(self, query = None, cats = None):
         """!Update dialog
         
-        @param query {coordinates, distance} - v.edit/v.what
+        @param query {coordinates, distance} - v.what
         @param cats  directory layer/cats    - vdigit
         Return True if updated otherwise False
         """
@@ -2360,7 +1280,7 @@
         self.cats = {}
         # do not display dialog if no line is found (-> self.cats)
         if cats is None:
-            ret = self.__GetCategories(query[0], query[1])
+            ret = self._getCategories(query[0], query[1])
         else:
             self.cats = cats
             for line in cats.keys():
@@ -2377,7 +1297,7 @@
         # polulate list
         self.fid = self.cats.keys()[0]
         self.itemDataMap = self.list.Populate(self.cats[self.fid],
-                                              update=True)
+                                              update = True)
 
         try:
             newCat = max(self.cats[self.fid][1]) + 1
@@ -2405,11 +1325,9 @@
 class CategoryListCtrl(wx.ListCtrl,
                        listmix.ListCtrlAutoWidthMixin,
                        listmix.TextEditMixin):
-    """!List of layers/categories"""
-
-    def __init__(self, parent, id, pos=wx.DefaultPosition,
-                 size=wx.DefaultSize, style=0):
-        
+    def __init__(self, parent, id, pos = wx.DefaultPosition,
+                 size = wx.DefaultSize, style = 0):
+        """!List of layers/categories"""
         self.parent = parent
         
         wx.ListCtrl.__init__(self, parent, id, pos, size, style)
@@ -2417,9 +1335,9 @@
         listmix.ListCtrlAutoWidthMixin.__init__(self)
         listmix.TextEditMixin.__init__(self)
 
-    def Populate(self, cats, update=False):
-        """!Populate the list"""
-
+    def Populate(self, cats, update = False):
+        """!Populate the list
+        """
         itemData = {} # requested by sorter
 
         if not update:
@@ -2448,11 +1366,10 @@
         return itemData
 
 class VDigitZBulkDialog(wx.Dialog):
-    """
-    Dialog used for Z bulk-labeling tool
-    """
-    def __init__(self, parent, title, nselected, style=wx.DEFAULT_DIALOG_STYLE):
-        wx.Dialog.__init__(self, parent=parent, id=wx.ID_ANY, title=title, style=style)
+    def __init__(self, parent, title, nselected, style = wx.DEFAULT_DIALOG_STYLE):
+        """!Dialog used for Z bulk-labeling tool
+        """
+        wx.Dialog.__init__(self, parent = parent, id = wx.ID_ANY, title = title, style = style)
 
         self.parent = parent # mapdisplay.BufferedWindow class instance
 
@@ -2460,35 +1377,35 @@
 
         border = wx.BoxSizer(wx.VERTICAL)
         
-        txt = wx.StaticText(parent=self,
-                            label=_("%d lines selected for z bulk-labeling") % nselected);
-        border.Add(item=txt, proportion=0, flag=wx.ALL | wx.EXPAND, border=5)
+        txt = wx.StaticText(parent = self,
+                            label = _("%d lines selected for z bulk-labeling") % nselected);
+        border.Add(item = txt, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
 
-        box   = wx.StaticBox (parent=self, id=wx.ID_ANY, label=" %s " % _("Set value"))
+        box   = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " %s " % _("Set value"))
         sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
-        flexSizer = wx.FlexGridSizer (cols=2, hgap=5, vgap=5)
+        flexSizer = wx.FlexGridSizer (cols = 2, hgap = 5, vgap = 5)
         flexSizer.AddGrowableCol(0)
 
         # starting value
-        txt = wx.StaticText(parent=self,
-                            label=_("Starting value"));
-        self.value = wx.SpinCtrl(parent=self, id=wx.ID_ANY, size=(150, -1),
-                                 initial=0,
-                                 min=-1e6, max=1e6)
-        flexSizer.Add(txt, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(self.value, proportion=0, flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
+        txt = wx.StaticText(parent = self,
+                            label = _("Starting value"));
+        self.value = wx.SpinCtrl(parent = self, id = wx.ID_ANY, size = (150, -1),
+                                 initial = 0,
+                                 min = -1e6, max = 1e6)
+        flexSizer.Add(txt, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(self.value, proportion = 0, flag = wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
 
         # step
-        txt = wx.StaticText(parent=self,
-                            label=_("Step"))
-        self.step  = wx.SpinCtrl(parent=self, id=wx.ID_ANY, size=(150, -1),
-                                 initial=0,
-                                 min=0, max=1e6)
-        flexSizer.Add(txt, proportion=0, flag=wx.ALIGN_CENTER_VERTICAL)
-        flexSizer.Add(self.step, proportion=0, flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
+        txt = wx.StaticText(parent = self,
+                            label = _("Step"))
+        self.step  = wx.SpinCtrl(parent = self, id = wx.ID_ANY, size = (150, -1),
+                                 initial = 0,
+                                 min = 0, max = 1e6)
+        flexSizer.Add(txt, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
+        flexSizer.Add(self.step, proportion = 0, flag = wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
 
-        sizer.Add(item=flexSizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=1)
-        border.Add(item=sizer, proportion=1, flag=wx.ALL | wx.EXPAND, border=0)
+        sizer.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
+        border.Add(item = sizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 0)
 
         # buttons
         btnCancel = wx.Button(self, wx.ID_CANCEL)
@@ -2502,23 +1419,21 @@
         btnSizer.Realize()
         
         mainSizer = wx.BoxSizer(wx.VERTICAL)
-        mainSizer.Add(item=border, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
-        mainSizer.Add(item=btnSizer, proportion=0,
-                      flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
+        mainSizer.Add(item = border, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 5)
+        mainSizer.Add(item = btnSizer, proportion = 0,
+                      flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
 
         self.SetSizer(mainSizer)
         mainSizer.Fit(self)
 
 class VDigitDuplicatesDialog(wx.Dialog):
-    """
-    Show duplicated feature ids
-    """
-    def __init__(self, parent, data, title=_("List of duplicates"),
-                 style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
-                 pos=wx.DefaultPosition):
-
-        wx.Dialog.__init__(self, parent=parent, id=wx.ID_ANY, title=title, style=style,
-                           pos=pos)
+    def __init__(self, parent, data, title = _("List of duplicates"),
+                 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
+                 pos = wx.DefaultPosition):
+        """!Show duplicated feature ids
+        """
+        wx.Dialog.__init__(self, parent = parent, id = wx.ID_ANY, title = title, style = style,
+                           pos = pos)
         
         self.parent = parent # BufferedWindow
         self.data = data
@@ -2527,21 +1442,21 @@
         # panel  = wx.Panel(parent=self, id=wx.ID_ANY)
 
         # notebook
-        self.notebook = wx.Notebook(parent=self, id=wx.ID_ANY, style=wx.BK_DEFAULT)
+        self.notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
 
         id = 1
         for key in self.data.keys():
-            panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
-            self.notebook.AddPage(page=panel, text=" %d " % (id))
+            panel = wx.Panel(parent = self.notebook, id = wx.ID_ANY)
+            self.notebook.AddPage(page = panel, text = " %d " % (id))
             
             # notebook body
             border = wx.BoxSizer(wx.VERTICAL)
 
-            win = CheckListFeature(parent=panel, data=list(self.data[key]))
+            win = CheckListFeature(parent = panel, data = list(self.data[key]))
             self.winList.append(win.GetId())
 
-            border.Add(item=win, proportion=1,
-                       flag=wx.ALL | wx.EXPAND, border=5)
+            border.Add(item = win, proportion = 1,
+                       flag = wx.ALL | wx.EXPAND, border = 5)
 
             panel.SetSizer(border)
 
@@ -2559,9 +1474,9 @@
         btnSizer.Realize()
         
         mainSizer = wx.BoxSizer(wx.VERTICAL)
-        mainSizer.Add(item=self.notebook, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
-        mainSizer.Add(item=btnSizer, proportion=0,
-                      flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
+        mainSizer.Add(item = self.notebook, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 5)
+        mainSizer.Add(item = btnSizer, proportion = 0,
+                      flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
 
         self.SetSizer(mainSizer)
         mainSizer.Fit(self)
@@ -2586,14 +1501,15 @@
         return ids
 
 class CheckListFeature(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.CheckListCtrlMixin):
-    """!List of mapset/owner/group"""
     def __init__(self, parent, data,
-                 pos=wx.DefaultPosition, log=None):
+                 pos = wx.DefaultPosition, log = None):
+        """!List of mapset/owner/group
+        """
         self.parent = parent
         self.data = data
 
         wx.ListCtrl.__init__(self, parent, wx.ID_ANY,
-                             style=wx.LC_REPORT)
+                             style = wx.LC_REPORT)
 
         listmix.CheckListCtrlMixin.__init__(self)
 
@@ -2605,7 +1521,8 @@
         self.LoadData(self.data)
 
     def LoadData(self, data):
-        """!Load data into list"""
+        """!Load data into list
+        """
         self.InsertColumn(0, _('Feature id'))
         self.InsertColumn(1, _('Layer (Categories)'))
 
@@ -2617,9 +1534,10 @@
         for item in range(self.GetItemCount()):
             self.CheckItem(item, True)
 
-        self.SetColumnWidth(col=0, width=wx.LIST_AUTOSIZE_USEHEADER)
-        self.SetColumnWidth(col=1, width=wx.LIST_AUTOSIZE_USEHEADER)
+        self.SetColumnWidth(col = 0, width = wx.LIST_AUTOSIZE_USEHEADER)
+        self.SetColumnWidth(col = 1, width = wx.LIST_AUTOSIZE_USEHEADER)
                 
     def OnCheckItem(self, index, flag):
-        """!Mapset checked/unchecked"""
+        """!Mapset checked/unchecked
+        """
         pass

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/workspace.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/workspace.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/workspace.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -250,7 +250,7 @@
         # init nviz layer properties
         vdigit = dict()
         for node in node_vdigit.findall('geometryAttribute'):
-            if not vdigit.has_key('geomAttr'):
+            if 'geomAttr' not in vdigit:
                 vdigit['geomAttr'] = dict()
             type = node.get('type')
             vdigit['geomAttr'][type] = dict()
@@ -277,7 +277,7 @@
             for sec in ('lines', 'points'):
                 nviz['vector'][sec] = {}
         
-        if nviz.has_key('surface'):
+        if 'surface' in nviz:
             node_surface = node_nviz.find('surface')
             # attributes
             for attrb in node_surface.findall('attribute'):
@@ -315,7 +315,7 @@
                 # resolution
                 for node_res in node_draw.findall('resolution'):
                     resType = str(node_res.get('type', ''))
-                    if not nviz['surface']['draw'].has_key('resolution'):
+                    if 'resolution' not in nviz['surface']['draw']:
                         nviz['surface']['draw']['resolution'] = {}
                     value = int(self.__getNodeText(node_res, 'value'))
                     nviz['surface']['draw']['resolution'][resType] = value
@@ -338,7 +338,7 @@
                     value = int(self.__getNodeText(node, 'value'))
                     dc[coor] = value
             
-        elif nviz.has_key('vector'):
+        elif 'vector' in nviz:
             # vpoints
             node_vpoints = node_nviz.find('vpoints')
             if node_vpoints is not None:
@@ -444,9 +444,9 @@
         data['draw']['all'] = False # apply only for current surface
         for control, value in UserSettings.Get(group='nviz', key='surface', subkey='draw').iteritems():
             if control[:3] == 'res':
-                if not data['draw'].has_key('resolution'):
+                if 'resolution' not in data['draw']:
                     data['draw']['resolution'] = {}
-                if not data['draw']['resolution'].has_key('update'):
+                if 'update' not in data['draw']['resolution']:
                     data['draw']['resolution']['update'] = None
                 data['draw']['resolution'][control[4:]] = value
                 continue
@@ -454,7 +454,7 @@
             if control == 'wire-color':
                 value = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
             elif control in ('mode', 'style', 'shading'):
-                if not data['draw'].has_key('mode'):
+                if 'mode' not in data['draw']:
                     data['draw']['mode'] = {}
                 continue
 
@@ -502,7 +502,7 @@
             else:
                 data['draw'][control] = { 'value' : value }
 
-            if not data['draw'][control].has_key('update'):
+            if 'update' not in data['draw'][control]:
                 data['draw'][control]['update'] = None
         
         #
@@ -558,7 +558,7 @@
         data['height'] = { 'value' : UserSettings.Get(group='nviz', key='vector',
                                                       subkey=['lines', 'height']) }
 
-        if data.has_key('object'):
+        if 'object' in data:
             for attrb in ('color', 'width', 'mode', 'height'):
                 data[attrb]['update'] = None
         
@@ -590,7 +590,7 @@
         data['height'] = { 'value' : UserSettings.Get(group='nviz', key='vector',
                                                       subkey=['points', 'height']) }
 
-        if data.has_key('object'):
+        if 'object' in data:
             for attrb in ('size', 'width', 'marker',
                           'color', 'surface', 'height'):
                 data[attrb]['update'] = None
@@ -809,7 +809,7 @@
                 vdigit = mapTree.GetPyData(item)[0]['vdigit']
                 if vdigit:
                     self.file.write('%s<vdigit>\n' % (' ' * self.indent))
-                    if vdigit.has_key('geomAttr'):
+                    if 'geomAttr' in vdigit:
                         self.indent += 4
                         for type, val in vdigit['geomAttr'].iteritems():
                             units = ''
@@ -838,7 +838,7 @@
 
         @param data Nviz layer properties
         """
-        if not data.has_key('object'): # skip disabled
+        if 'object' not in data: # skip disabled
             return
 
         self.indent += 4
@@ -864,12 +864,12 @@
             # draw mode
             if attrb == 'draw':
                 self.file.write('%s<%s' %(' ' * self.indent, attrb))
-                if data[attrb].has_key('mode'):
+                if 'mode' in data[attrb]:
                     for tag, value in data[attrb]['mode']['desc'].iteritems():
                         self.file.write(' %s="%s"' % (tag, value))
                 self.file.write('>\n') # <draw ...>
 
-                if data[attrb].has_key('resolution'):
+                if 'resolution' in data[attrb]:
                     self.indent += 4
                     for type in ('coarse', 'fine'):
                         self.file.write('%s<resolution type="%s">\n' % (' ' * self.indent, type))
@@ -879,7 +879,7 @@
                         self.indent -= 4
                         self.file.write('%s</resolution>\n' % (' ' * self.indent))
 
-                if data[attrb].has_key('wire-color'):
+                if 'wire-color' in data[attrb]:
                     self.file.write('%s<wire_color>\n' % (' ' * self.indent))
                     self.indent += 4
                     self.file.write('%s<value>%s</value>\n' % (' ' * self.indent,
@@ -917,7 +917,7 @@
             if len(data[attrb]) < 1: # skip empty attributes
                 continue
 
-            if not data[attrb].has_key('object'): # skip disabled
+            if 'object' not in data[attrb]: # skip disabled
                 continue
             if attrb == 'lines':
                 self.file.write('%s<v%s>\n' % (' ' * self.indent, attrb))

Modified: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/wxnviz.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/wxnviz.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/wxnviz.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -22,7 +22,7 @@
 from threading import Thread
 
 from ctypes import *
-from grass.lib.grass import *
+from grass.lib.gis   import *
 from grass.lib.g3d   import *
 from grass.lib.ogsf  import *
 from grass.lib.nviz  import *

Added: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/wxvdigit.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/wxvdigit.py	                        (rev 0)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/wxvdigit.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -0,0 +1,1578 @@
+"""!
+ at package wxvdigit.py
+
+ at brief wxGUI vector digitizer (base class)
+
+Code based on wxVdigit C++ component from GRASS 6.4.0
+(gui/wxpython/vdigit). Converted to Python in 2010/12-2011/01.
+
+List of classes:
+ - VDigitError
+ - IVDigit
+
+(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.
+
+ at author Martin Landa <landa.martin gmail.com>
+"""
+
+from gcmd        import GError
+from debug       import Debug
+from preferences import globalSettings as UserSettings
+
+from wxvdriver   import DisplayDriver
+
+from grass.lib.gis    import *
+from grass.lib.vector import *
+from grass.lib.vedit  import *
+from grass.lib.dbmi   import *
+
+class VDigitError:
+    def __init__(self, parent):
+        """!Class for managing error messages of vector digitizer
+
+        @param parent parent window for dialogs
+        """
+        self.parent  = parent
+        self.caption = _('Digitization Error')
+    
+    def NoMap(self, name = None):
+        """!No map for editing"""
+        if name:
+            message = _('Unable to open vector map <%s>.') % name
+        else:
+            message =  _('No vector map open for editing.')
+        GError(message + ' ' + _('Operation cancelled.'),
+               parent  = self.parent,
+               caption = self.caption)
+
+    def WriteLine(self):
+        """!Writing line failed
+        """
+        GError(message = _('Writing new feature failed. '
+                           'Operation cancelled.'),
+               parent  = self.parent,
+               caption = self.caption)
+
+    def ReadLine(self, line):
+        """!Reading line failed
+        """
+        GError(message = _('Reading feature id %d failed. '
+                           'Operation cancelled.') % line,
+               parent  = self.parent,
+               caption = self.caption)
+
+    def DbLink(self, dblink):
+        """!No dblink available
+        """
+        GError(message = _('Database link %d not available. '
+                           'Operation cancelled.') % dblink,
+               parent  = self.parent,
+               caption = self.caption)
+
+    def Driver(self, driver):
+        """!Staring driver failed
+        """
+        GError(message = _('Unable to start database driver <%s>. '
+                           'Operation cancelled.') % driver,
+               parent  = self.parent,
+               caption = self.caption)
+
+    def Database(self, driver, database):
+        """!Opening database failed
+        """
+        GError(message = _('Unable to open database <%s> by driver <%s>. '
+                           'Operation cancelled.') % (database, driver),
+               parent  = self.parent,
+               caption = self.caption)
+
+    def DbExecute(self, sql):
+        """!Sql query failed
+        """
+        GError(message = _("Unable to execute SQL query '%s'. "
+                           "Operation cancelled.") % sql,
+               parent  = self.parent,
+               caption = self.caption)
+
+    def DeadLine(self, line):
+        """!Dead line
+        """
+        GError(message = _("Feature id %d is marked as dead. "
+                           "Operation cancelled.") % line,
+               parent  = self.parent,
+               caption = self.caption)
+
+    def FeatureType(self, ftype):
+        """!Unknown feature type
+        """
+        GError(message = _("Unsupported feature type %d. "
+                           "Operation cancelled.") % ftype,
+               parent  = self.parent,
+               caption = self.caption)
+        
+class IVDigit:
+    def __init__(self, mapwindow):
+        """!Base class for vector digitizer (ctypes interface)
+        
+        @parem mapwindow reference for map window (BufferedWindow)
+        """
+        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()
+            log = goutput.GetLog(err = True)
+            progress = goutput.GetProgressBar()
+        else:
+            log = sys.stderr
+            progress = None
+        
+        self.toolbar = mapwindow.parent.toolbars['vdigit']
+        
+        self._error   = VDigitError(parent = self.mapWindow)
+        
+        self._display = DisplayDriver(device    = mapwindow.pdcVector,
+                                      deviceTmp = mapwindow.pdcTmp,
+                                      mapObj    = mapwindow.Map,
+                                      window    = mapwindow,
+                                      glog      = log,
+                                      gprogress = progress)
+        
+        # GRASS lib
+        self.poPoints = Vect_new_line_struct()
+        self.poCats   = Vect_new_cats_struct()
+        
+        # self.SetCategory()
+        
+        # layer / max category
+        self.cats = dict()
+        
+        self._settings = dict()
+        self.UpdateSettings() # -> self._settings
+        
+        # undo/redo
+        self.changesets = dict()
+        self.changesetCurrent = -1 # first changeset to apply
+        self.changesetEnd     = -1 # last changeset to be applied
+        
+        if self.poMapInfo:
+            self.InitCats()
+        
+    def __del__(self):
+        Vect_destroy_line_struct(self.poPoints)
+        self.poPoints = None
+        Vect_destroy_cats_struct(self.poCats)
+        self.poCats = None
+        
+        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
+        
+        @param bgmap name of vector map to be opened
+
+        @return pointer to map_info
+        @return None on error
+        """
+        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   = str(name.value)
+            mapset = str(mapset.value)
+        
+        if (name == Vect_get_name(self.poMapInfo) and \
+                mapset == Vect_get_mapset(self.poMapInfo)):
+            self.poBgMapInfo = self.popoBgMapInfo = None
+            self._error.NoMap(bgmap)
+            return
+        
+        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
+
+         - snap to vertex
+         - snap to nodes
+         - no snapping
+        
+        @return snap mode
+        """
+        threshold = self._display.GetThreshold()
+        if threshold > 0.0:
+            if UserSettings.Get(group = 'vdigit', key = 'snapToVertex', subkey = 'enabled'):
+                return SNAPVERTEX
+            else:
+                return SNAP
+        else:
+            return NO_SNAP
+    
+    def _breakLineAtIntersection(self, line, pointsLine, changeset):
+        """!Break given line at intersection
+
+        \param line line id
+        \param pointsLine line geometry
+        \param changeset id
+  
+        \return number of modified lines
+        """
+        if not self._checkMap():
+            return -1
+        
+        if not Vect_line_alive(self.poMapInfo, line):
+            return 0
+        
+        if not pointsLine:
+            if Vect_read_line(self.poMapInfo, self.poPoints, None, line) < 0:
+                self._error.ReadLine(line)
+                return -1
+            points = self.poPoints
+        else:
+            points = pointsLine
+        
+        listLine  = Vect_new_list()
+        listRef   = Vect_new_list()
+        listBreak = Vect_new_list()
+    
+        pointsCheck = Vect_new_line_struct()
+    
+        lineBox = bound_box()
+        # find all relevant lines
+        Vect_get_line_box(self.poMapInfo, line, byref(lineBox))
+        Vect_select_lines_by_box(self.poMapInfo, byref(lineBox),
+                                 GV_LINES, listLine)
+    
+        # check for intersection
+        Vect_list_append(listBreak, line)
+        Vect_list_append(listRef, line)
+        for i in range(listLine.contents.n_values):
+            lineBreak = listLine.contents.value[i]
+            if lineBreak == line:
+		continue
+            
+            ltype = Vect_read_line(self.poMapInfo, pointsCheck, None, lineBreak)
+            if not (ltype & GV_LINES):
+                continue
+            
+            if Vect_line_check_intersection(self.poPoints, pointsCheck,
+                                            WITHOUT_Z):
+                Vect_list_append(listBreak, lineBreak)
+        
+        nlines = Vect_get_num_lines(self.poMapInfo)
+        
+        for i in range(listBreak.contents.n_values):
+            self._addActionToChangeset(changeset, listBreak.contents.value[i], add = False)
+        
+        ret = Vect_break_lines_list(self.poMapInfo, listBreak, listRef,
+                                    GV_LINES, None)
+        
+        for i in range(listBreak.contents.n_values):
+            if Vect_line_alive(self.poMapInfo, listBreak.contents.value[i]):
+                self._removeActionFromChangeset(changeset, listBreak.contents.value[i],
+                                                add = False)
+        
+        for line in range(nlines + 1, Vect_get_num_lines(self.poMapInfo) + 1):
+            self._addActionToChangeset(changeset, line, add = True)
+        
+        Vect_destroy_line_struct(pointsCheck)
+
+        Vect_destroy_list(listLine)
+        Vect_destroy_list(listBreak)
+        Vect_destroy_list(listRef)
+        
+        return ret
+    
+    def _addActionsBefore(self):
+        """!Register action before operation
+  
+        @return changeset id
+        """
+        changeset = len(self.changesets)
+        for line in self._display.selected['ids']:
+            if Vect_line_alive(self.poMapInfo, line):
+                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
+
+        @param changeset changeset id
+        @param nline number of lines
+        """
+        for line in self._display.selected['ids']:
+            if Vect_line_alive(self.poMapInfo, line):
+                self._removeActionFromChangeset(changeset, line, add = False)
+        
+        for line in range(nlines + 1, Vect_get_num_lines(self.poMapInfo)):
+            if Vect_line_alive(self.poMapInfo, line):
+                self._addActionToChangeset(changeset, line, add = True)
+        
+    def _addActionToChangeset(self, changeset, line, add):
+        """!Add action to changeset
+        
+        @param changeset id of changeset
+        @param line feature id
+        @param add True to add, otherwise delete
+        """
+        if not self._checkMap():
+            return 
+        
+        if not Vect_line_alive(self.poMapInfo, line):
+            return
+        
+        offset = Vect_get_line_offset(self.poMapInfo, line)
+        
+        if changeset not in self.changesets:
+            self.changesets[changeset] = list()
+            self.changesetCurrent = changeset
+        
+        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 _removeActionFromChangeset(self, changeset, line, add):
+        """!Remove action from changeset
+        
+        @param changeset changeset id
+        @param line line id
+        @param add True for add, False for delete
+        
+        @return number of actions in changeset
+        @return -1 on error
+        """
+        if changeset not in self.changesets.keys():
+            return -1
+        
+        alist = self.changesets[changeset] 
+        for action in alist:
+            if action['add'] == add and action['line'] == line:
+                alist.remove(action)
+        
+        return len(alist)
+
+    def AddFeature(self, ftype, points):
+        """!Add new feature
+        
+        @param ftype feature type (point, line, centroid, boundary)
+        @param points tuple of points ((x, y), (x, y), ...)
+        
+        @return tuple (number of added features, feature ids)
+        """
+        if UserSettings.Get(group = 'vdigit', key = "categoryMode", subkey = 'selection') == 2:
+            layer = -1 # -> no category
+            cat   = -1
+        else:
+            layer = UserSettings.Get(group = 'vdigit', key = "layer", subkey = 'value')
+            cat   = self.SetCategory()
+        
+        if ftype == 'point':
+            vtype = GV_POINT
+        elif ftype == 'line':
+            vtype = GV_LINE
+        elif ftype == 'centroid':
+            vtype = GV_CENTROID
+        elif ftype == 'boundary':
+            vtype = GV_BOUNDARY
+        elif ftype == 'area':
+            vtype = GV_AREA
+        else:
+            GError(parent = self.mapWindow,
+                   message = _("Unknown feature type '%s'") % ftype)
+            return (-1, None)
+        
+        if vtype & GV_LINES and len(points) < 2:
+            GError(parent = self.mapWindow,
+                   message = _("Not enough points for line"))
+            return (-1, None)
+        
+        self.toolbar.EnableUndo()
+        
+        return self._addFeature(vtype, points, layer, cat,
+                                self._getSnapMode(), self._display.GetThreshold())
+    
+    def DeleteSelectedLines(self):
+        """!Delete selected features
+
+        @return number of deleted features
+        """
+        deleteRec = UserSettings.Get(group = 'vdigit', key = 'delRecord', subkey = 'enabled')
+        if not self._checkMap():
+            return -1
+        
+        n_dblinks = Vect_get_num_dblinks(self.poMapInfo)
+        Cats_del = None
+        
+        # collect categories for delete if requested
+        if deleteRec:
+            poCats    = Vect_new_cats_struct()
+            poCatsDel = Vect_new_cats_struct()
+            for i in self._display.selected['ids']:
+                if Vect_read_line(self.poMapInfo, None, poCats, i) < 0:
+                    Vect_destroy_cats_struct(poCatsDel)
+                    self._error.ReadLine(i)
+                    return -1
+                
+                cats = poCats.contents
+                for j in range(cats.n_cats):
+                    Vect_cat_set(poCatsDel, cats.field[j], cats.cat[j])
+            
+            Vect_destroy_cats_struct(poCats)
+        
+        # register changeset
+        changeset = self._addActionsBefore()
+        
+        poList = self._display.GetSelectedIList()
+        nlines = Vedit_delete_lines(self.poMapInfo, poList)
+        Vect_destroy_list(poList)
+        self._display.selected['ids'] = list()
+        
+        if nlines > 0 and deleteRec:
+            handle  = dbHandle()
+            poHandle = pointer(handle)
+            stmt    = dbString()
+            poStmt   = pointer(stmt)
+            
+            for dblink in range(n_dblinks):
+                poFi = Vect_get_dblink(self.poMapInfo, dblink)
+                if poFi is None:
+                    self._error.DbLink(dblink)
+                    return -1
+                
+                Fi = poFi.contents
+                poDriver = db_start_driver(Fi.driver)
+                if poDriver is None:
+                    self._error.Driver(Fi.driver)
+                    return -1
+                
+                db_init_handle(poHandle)
+                db_set_handle(poHandle, Fi.database, None)
+                if db_open_database(poDriver, poHandle) != DB_OK:
+                    self._error.Database(Fi.driver, Fi.database)
+                    return -1
+                
+                db_init_string(poStmt)
+                db_set_string(poStmt, "DELETE FROM %s WHERE" % Fi.table)
+                n_cats = 0;
+                catsDel = poCatsDel.contents
+                for c in range(catsDel.n_cats):
+                    if catsDel.field[c] == Fi.number:
+                        if n_cats > 0:
+                            db_append_string(poStmt, " or")
+                    
+		    db_append_string(poStmt, " %s = %d" % (Fi.key, catsDel.cat[c]))
+		    n_cats += 1
+                
+                Vect_cat_del(poCatsDel, Fi.number)
+                
+                if n_cats and \
+                        db_execute_immediate(poDriver, poStmt) != DB_OK:
+                    self._error.DbExecute(db_get_string(poStmt))
+                    return -1
+                
+                db_close_database(poDriver)
+                db_shutdown_driver(poDriver)
+        
+        if poCatsDel:
+            Vect_destroy_cats_struct(poCatsDel)
+        
+        if nlines > 0:
+            self.toolbar.EnableUndo()
+        
+        return nlines
+
+    def MoveSelectedLines(self, move):
+        """!Move selected features
+
+        @param move direction (x, y)
+        """
+        if not self._checkMap():
+            return -1
+        
+        thresh = self._display.GetThreshold()
+        snap   = self._getSnapMode()
+        
+        nlines = Vect_get_num_lines(self.poMapInfo)
+        
+        # register changeset
+        changeset = self._addActionsBefore()
+        
+        poList = self._display.GetSelectedIList()
+        nlines = Vedit_move_lines(self.poMapInfo, self.popoBgMapInfo, int(self.poBgMapInfo is not None),
+                                  poList,
+                                  move[0], move[1], 0,
+                                  snap, thresh)
+        Vect_destroy_list(poList)
+        
+        if nlines > 0:
+            self._addActionsAfter(changeset, nlines)
+        else:
+            del self.changesets[changeset]
+        
+        if nlines > 0 and self._settings['breakLines']:
+            for i in range(1, nlines):
+                self._breakLineAtIntersection(nlines + i, None, changeset)
+        
+        if nlines > 0:
+            self.toolbar.EnableUndo()
+        
+        return nlines
+
+    def MoveSelectedVertex(self, point, move):
+        """!Move selected vertex of the line
+
+        @param point location point
+        @param move  x,y direction
+        
+        @return id of new feature
+        @return 0 vertex not moved (not found, line is not selected)
+        @return -1 on error
+        """
+        if not self._checkMap():
+            return -1
+        
+        if len(self._display.selected['ids']) != 1:
+            return -1
+        
+        Vect_reset_line(self.poPoints)
+        Vect_append_point(self.poPoints, point[0], point[1], 0.0)
+        
+        nlines = Vect_get_num_lines(self.poMapInfo)
+        
+        changeset = self._addActionsBefore()
+        
+        # move only first found vertex in bbox 
+        poList = self._display.GetSelectedIList()
+        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(),
+                                  move[0], move[1], 0.0,
+                                  1, self._getSnapMode())
+        Vect_destroy_list(poList)
+        
+        if moved > 0:
+            self._addActionsAfter(changeset, nlines)
+        else:
+            del self.changesets[changeset]
+        
+        if moved > 0 and self._settings['breakLines']:
+            self._breakLineAtIntersection(Vect_get_num_lines(self.poMapInfo),
+                                          None, changeset)
+        
+        if moved > 0:
+            self.toolbar.EnableUndo()
+        
+        return moved
+
+    def AddVertex(self, coords):
+        """!Add new vertex to the selected line/boundary on position 'coords'
+
+        @param coords coordinates to add vertex
+
+        @return id of new feature
+        @return 0 nothing changed
+        @return -1 on failure
+        """
+        added = self._ModifyLineVertex(coords, add = True)
+        
+        if added > 0:
+            self.toolbar.EnableUndo()
+
+        return added
+
+    def RemoveVertex(self, coords):
+        """!Remove vertex from the selected line/boundary on position 'coords'
+
+        @param coords coordinates to remove vertex
+
+        @return id of new feature
+        @return 0 nothing changed
+        @return -1 on failure
+        """
+        deleted = self._ModifyLineVertex(coords, add = False)
+        
+        if deleted > 0:
+            self.toolbar.EnableUndo()
+
+        return deleted
+
+
+    def SplitLine(self, point):
+        """!Split/break selected line/boundary on given position
+
+        @param point point where to split line
+        
+        @return 1 line modified
+        @return 0 nothing changed
+        @return -1 error
+        """
+        thresh = self._display.GetThreshold('selectThresh')
+        if not self._checkMap():
+            return -1
+        
+        poList  = self._display.GetSelectedIList()
+        Vect_reset_line(self.poPoints)
+        Vect_append_point(self.poPoints, point[0], point[1], 0.0)
+        
+        nlines = Vect_get_num_lines(self.poMapInfo)
+        
+        changeset = self._addActionsBefore()
+        
+        ret = Vedit_split_lines(self.poMapInfo, poList,
+                                self.poPoints, thresh, None)
+        Vect_destroy_list(poList)
+        
+        if ret > 0:
+            self._addActionsAfter(changeset, nlines)
+            self.toolbar.EnableUndo()
+        else:
+            del self.changesets[changeset]
+        
+        return ret
+
+    def EditLine(self, line, coords):
+        """!Edit existing line/boundary
+
+        @param line id of line to be modified
+        @param coords list of coordinates of modified line
+
+        @return feature id of new line
+        @return -1 on error
+        """
+        if self._checkMap():
+            return -1
+        
+        try:
+            lineid = line[0]
+        except:
+            lineid = -1
+        
+        if len(coords) < 2:
+            self.DeleteSelectedLines()
+            return 0
+        
+        ret = self.digit.RewriteLine(lineid, listCoords,
+                                     bgmap, self._getSnapMode(),
+                                     self._display.GetThreshold())
+        
+        if ret > 0:
+            self.toolbar.EnableUndo()
+        
+        return ret
+
+    def FlipLine(self):
+        """!Flip selected lines/boundaries
+
+        @return number of modified lines
+        @return -1 on error
+        """
+        if not self._checkMap():
+            return -1
+        
+        nlines = Vect_get_num_lines(self.poMapInfo)
+        
+        # register changeset
+        changeset = self._addActionsBefore()
+        
+        poList = self._display.GetSelectedIList()
+        ret = Vedit_flip_lines(self.poMapInfo, poList)
+        Vect_destroy_list(poList)
+        
+        if ret > 0:
+            self._addActionsAfter(changeset, nlines)
+            self.toolbar.EnableUndo()
+        else:
+            del self.changesets[changeset]
+        
+        return ret
+
+    def MergeLine(self):
+        """!Merge selected lines/boundaries
+
+        @return number of modified lines
+        @return -1 on error
+        """
+        if not self._checkMap():
+            return -1
+        
+        nlines = Vect_get_num_lines(self.poMapInfo)
+        
+        changeset = self._addActionsBefore()
+        
+        poList = self._display.GetSelectedIList()
+        ret = Vedit_merge_lines(self.poMapInfo, poList)
+        Vect_destroy_list(poList)
+        
+        if ret > 0:
+            self._addActionsAfter(changeset, nlines)
+            self.toolbar.EnableUndo()
+        else:
+            del self.changesets[changeset]
+                
+        return ret
+
+    def BreakLine(self):
+        """!Break selected lines/boundaries
+
+        @return number of modified lines
+        @return -1 on error
+        """
+        if not self._checkMap():
+            return -1
+        
+        nlines = Vect_get_num_lines(self.poMapInfo)
+        
+        changeset = self._addActionsBefore()
+        
+        poList = self._display.GetSelectedIList()
+        ret = Vect_break_lines_list(self.poMapInfo, poList, None,
+                                    GV_LINES, None)
+        Vect_destroy_list(poList)
+        
+        if ret > 0:
+            self._addActionsAfter(changeset, nlines)
+            self.toolbar.EnableUndo()
+        else:
+            del self.changesets[changeset]
+                
+        return ret
+
+    def SnapLine(self):
+        """!Snap selected lines/boundaries
+
+        @return on success
+        @return -1 on error
+        """
+        if not self._checkMap():
+            return -1
+        
+        nlines = Vect_get_num_lines(self.poMapInfo)
+        
+        changeset = self._addActionsBefore()
+        
+        poList = self._display.GetSelectedIList()
+        Vect_snap_lines_list(self.poMapInfo, poList,
+                             self._display.GetThreshold(), None)
+        Vect_destroy_list(poList)
+        
+        if nlines < Vect_get_num_lines(self.poMapInfo):
+            self._addActionsAfter(changeset, nlines)
+            self.toolbar.EnableUndo()
+        else:
+            del self.changesets[changeset]
+        
+    def ConnectLine(self):
+        """!Connect selected lines/boundaries
+
+        @return 1 lines connected
+        @return 0 lines not connected
+        @return -1 on error
+        """
+        if not self._checkMap():
+            return -1
+        
+        nlines = Vect_get_num_lines(self.poMapInfo)
+        
+        # register changeset
+        changeset = self._addActionsBefore()
+        
+        poList = self._display.GetSelectedIList()
+        ret = Vedit_connect_lines(self.poMapInfo, poList,
+                                  self._display.GetThreshold())
+        Vect_destroy_list(poList)
+        
+        if ret > 0:
+            self._addActionsAfter(changeset, nlines)
+            self.toolbar.EnableUndo()
+        else:
+            del self.changesets[changeset]
+        
+        return ret
+        
+    def CopyLine(self, ids = []):
+        """!Copy features from (background) vector map
+
+        @param ids list of line ids to be copied
+
+        @return number of copied features
+        @return -1 on error
+        """
+        if not self._checkMap():
+            return -1
+        
+        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):
+        """!Copy given categories to objects with id listed in ids
+
+        @param cats ids of 'from' feature
+        @param ids  ids of 'to' feature(s)
+
+        @return number of modified features
+        @return -1 on error
+        """
+        if len(fromId) == 0 or len(toId) == 0:
+            return 0
+        
+        ret = self.digit.CopyCats(fromId, toId, copyAttrb)
+
+        if ret > 0:
+            self.toolbar.EnableUndo()
+
+        return ret
+
+    def _selectLinesByQueryThresh(self):
+        """!Generic method used for SelectLinesByQuery() -- to get
+        threshold value"""
+        thresh = 0.0
+        if UserSettings.Get(group = 'vdigit', key = 'query', subkey = 'selection') == 0:
+            thresh = UserSettings.Get(group = 'vdigit', key = 'queryLength', subkey = 'thresh')
+            if UserSettings.Get(group = 'vdigit', key = "queryLength", subkey = 'than-selection') == 0:
+                thresh = -1 * thresh
+        else:
+            thresh = UserSettings.Get(group = 'vdigit', key = 'queryDangle', subkey = 'thresh')
+            if UserSettings.Get(group = 'vdigit', key = "queryDangle", subkey = 'than-selection') == 0:
+                thresh = -1 * thresh
+        
+        return thresh
+
+    def SelectLinesByQuery(self, bbox):
+        """!Select features by query
+        
+        @todo layer / 3D
+        
+        @param bbox bounding box definition
+        """
+        if not self._checkMap():
+            return -1
+        
+        thresh = self._selectLinesByQueryThresh()
+        
+        query = QUERY_UNKNOWN
+        if UserSettings.Get(group = 'vdigit', key = 'query', subkey = 'selection') == 0:
+            query = QUERY_LENGTH
+        else:
+            query = QUERY_DANGLE
+        
+        ftype = GV_POINTS | GV_LINES # TODO: 3D
+        layer = 1 # TODO
+        
+        ids = list()
+        poList = Vect_new_list()
+        coList = poList.contents
+        if UserSettings.Get(group = 'vdigit', key = 'query', subkey = 'box'):
+            Vect_reset_line(self.poPoints)
+            x1, y1 = bbox[0]
+            x2, y2 = bbox[1]
+            z1 = z2 = 0.0
+            
+            Vect_append_point(self.poPoints, x1, y1, z1)
+            Vect_append_point(self.poPoints, x2, y1, z2)
+            Vect_append_point(self.poPoints, x2, y2, z1)
+            Vect_append_point(self.poPoints, x1, y2, z2)
+            Vect_append_point(self.poPoints, x1, y1, z1)
+	
+            Vect_select_lines_by_polygon(self.poMapInfo, self.poPoints, 0, None,
+                                         ftype, poList)
+            
+            if coList.n_values == 0:
+                return ids
+        
+        Vedit_select_by_query(self.poMapInfo,
+                              ftype, layer, thresh, query,
+                              poList)
+        
+        for i in range(coList.n_values):
+            ids.append(int(coList.value[i]))
+            
+        Debug.msg(3, "IVDigit.SelectLinesByQuery(): lines=%d", coList.n_values)    
+        Vect_destroy_list(poList)
+        
+        return ids
+
+    def IsVector3D(self):
+        """!Check if open vector map is 3D
+        """
+        if not self._checkMap():
+            return False
+        
+        return Vect_is_3d(self.poMapInfo)
+    
+    def GetLineCats(self, line=-1):
+        """!Get layer/category pairs from given (selected) line
+        
+        @param line feature id (-1 for first selected line)
+        """
+        return dict(self.digit.GetLineCats(line))
+
+    def GetLineLength(self, line):
+        """!Get line length
+
+        @param line feature id
+
+        @return line length
+        @return -1 on error
+        """
+        if not self._checkMap():
+            return -1
+        
+        if not Vect_line_alive(self.poMapInfo, line):
+            return -1
+    
+        ltype = Vect_read_line(self.poMapInfo, self.poPoints, None, line)
+        if ltype < 0:
+            self._error.ReadLine(line)
+            return ret
+        
+        length = -1
+        if ltype & GV_LINES: # lines & boundaries
+            length = Vect_line_length(self.poPoints)
+        
+        return length
+
+    def GetAreaSize(self, centroid):
+        """!Get area size
+
+        @param centroid centroid id
+
+        @return area size
+        @return -1 on error
+        """
+        if not self._checkMap():
+            return -1
+        
+        ltype = Vect_read_line(self.poMapInfo, None, None, centroid)
+        if ltype < 0:
+            self._error.ReadLine(line)
+            return ret
+        
+        if ltype != GV_CENTROID:
+            return -1
+        
+        area = Vect_get_centroid_area(self.poMapInfo, centroid)
+        size = -1
+        if area > 0:
+            if not Vect_area_alive(self.poMapInfo, area):
+                return size
+            
+            size = Vect_get_area_area(self.poMapInfo, area)
+        
+        return size
+        
+    def GetAreaPerimeter(self, centroid):
+        """!Get area perimeter
+        
+        @param centroid centroid id
+        
+        @return area size
+        @return -1 on error
+        """
+        if not self._checkMap():
+            return -1
+        
+        ltype = Vect_read_line(self.poMapInfo, None, None, centroid)
+        if ltype < 0:
+            self._error.ReadLine(line)
+            return ret
+        
+        if ltype != GV_CENTROID:
+            return -1
+        
+        area = Vect_get_centroid_area(self.poMapInfo, centroid)
+        perimeter = -1
+        if area > 0:
+            if not Vect_area_alive(self.poMapInfo, area):
+                return -1
+            
+            Vect_get_area_points(self.poMapInfo, area, self.poPoints)
+            perimeter = Vect_area_perimeter(self.poPoints)
+        
+        return perimeter
+    
+    def SetLineCats(self, line, layer, cats, add=True):
+        """!Set categories for given line and layer
+
+        @param line feature id
+        @param layer layer number (-1 for first selected line)
+        @param cats list of categories
+        @param add if True to add, otherwise do delete categories
+
+        @return new feature id (feature need to be rewritten)
+        @return -1 on error
+        """
+        ret = self.digit.SetLineCats(line, layer, cats, add)
+
+        if ret > 0:
+            self.toolbar.EnableUndo()
+
+        return ret
+
+    def GetLayers(self):
+        """!Get list of layers"""
+        return self.digit.GetLayers()
+
+    def TypeConvForSelectedLines(self):
+        """!Feature type conversion for selected objects.
+
+        Supported conversions:
+         - point <-> centroid
+         - line <-> boundary
+
+        @return number of modified features
+        @return -1 on error
+        """
+        if not self._checkMap():
+            return -1
+        
+        nlines = Vect_get_num_lines(self.poMapInfo)
+        
+        # register changeset
+        changeset = self._addActionsBefore()
+        
+        poList = self._display.GetSelectedIList()
+        ret = Vedit_chtype_lines(self.poMapInfo, poList)
+        Vect_destroy_list(poList)
+        
+        if ret > 0:
+            self._addActionsAfter(changeset, nlines)
+            self.toolbar.EnableUndo()
+        else:
+            del self.changesets[changeset]
+        
+        return ret
+
+    def Undo(self, level = -1):
+        """!Undo action
+
+        @param level levels to undo (0 to revert all)
+
+        @return id of current changeset
+        """
+        changesetLast = len(self.changesets.keys()) - 1
+
+        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
+
+        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)
+        
+        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):
+        """!Z-bulk labeling
+
+        @param pos1 reference line (start point)
+        @param pos1 reference line (end point)
+        @param start starting value
+        @param step step value
+
+        @return number of modified lines
+        @return -1 on error
+        """
+        if not self._checkMap():
+            return -1
+        
+        nlines = Vect_get_num_lines(self.poMapInfo)
+        
+        # register changeset
+        changeset = self._addActionsBefore()
+        
+        poList = self._display.GetSelectedIList()
+        ret = Vedit_bulk_labeling(self.poMapInfo, poList,
+                                  pos1[0], pos1[1], pos2[0], pos2[1],
+                                  start, step)
+        Vect_destroy_list(poList)
+        
+        if ret > 0:
+            self._addActionsAfter(changeset, nlines)
+            self.toolbar.EnableUndo()
+        else:
+            del self.changesets[changeset]
+        
+        return ret
+    
+    def GetDisplay(self):
+        """!Get display driver instance"""
+        return self._display
+    
+    def OpenMap(self, name):
+        """!Open vector map for editing
+        
+        @param map name of vector map to be set up
+        """
+        Debug.msg (3, "AbstractDigit.SetMapName map=%s" % name)
+        
+        name, mapset = name.split('@')
+        
+        self.poMapInfo = self._display.OpenMap(str(name), str(mapset), True)
+        
+        if self.poMapInfo:
+            self.InitCats()
+        
+        return self.poMapInfo
+    
+    def CloseMap(self):
+        """!Close currently open vector map
+        """
+        if not self._checkMap():
+            return
+        
+        self._display.CloseMap()
+
+    def InitCats(self):
+        """!Initialize categories information
+        
+        @return 0 on success
+        @return -1 on error
+        """
+        self.cats.clear()
+        if not self._checkMap():
+            return -1
+        
+        ndblinks = Vect_get_num_dblinks(self.poMapInfo)
+        for i in range(ndblinks):
+            fi = Vect_get_dblink(self.poMapInfo, i).contents
+            if fi:
+                self.cats[fi.number] = None
+        
+        # find max category
+        nfields = Vect_cidx_get_num_fields(self.poMapInfo)
+        Debug.msg(2, "wxDigit.InitCats(): nfields=%d", nfields)
+        
+        for i in range(nfields):
+            field = Vect_cidx_get_field_number(self.poMapInfo, i)
+            ncats = Vect_cidx_get_num_cats_by_index(self.poMapInfo, i)
+            if field <= 0:
+                continue
+            for j in range(ncats):
+                cat = c_int()
+                type = c_int()
+                id = c_int()
+                Vect_cidx_get_cat_by_index(self.poMapInfo, i, j,
+                                           byref(cat), byref(type), byref(id))
+                if field in self.cats:
+                    if cat > self.cats[field]:
+                        self.cats[field] = cat.value
+                else:
+                    self.cats[field] = cat.value
+            Debug.msg(3, "wxDigit.InitCats(): layer=%d, cat=%d", field, self.cats[field])
+            
+        # set default values
+        for field, cat in self.cats.iteritems():
+            if cat == None:
+                self.cats[field] = 0 # first category 1
+	    Debug.msg(3, "wxDigit.InitCats(): layer=%d, cat=%d", field, self.cats[field])
+        
+    def _checkMap(self):
+        """!Check if map is open
+        """
+        if not self.poMapInfo:
+            self._error.NoMap()
+            return False
+        
+        return True
+
+    def _addFeature(self, ftype, coords, layer, cat, snap, threshold):
+        """!Add new feature(s) to the vector map
+
+        @param ftype 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 snap snap to node/vertex
+        @param threshold threshold for snapping
+        
+        @return tuple (number of added features, list of fids)
+        @return number of features -1 on error
+        """
+        fids = list()
+        if not self._checkMap():
+            return (-1, None)
+        
+        is3D = bool(Vect_is_3d(self.poMapInfo))
+        
+        Debug.msg(2, "IVDigit._addFeature(): npoints=%d, layer=%d, cat=%d, snap=%d",
+                  len(coords), layer, cat, snap)
+        
+        if not (ftype & (GV_POINTS | GV_LINES | GV_AREA)): # TODO: 3D
+            self._error.FeatureType(ftype)
+            return (-1, None)
+        
+        # set category
+        Vect_reset_cats(self.poCats)
+        if layer > 0 and ftype != GV_AREA:
+            Vect_cat_set(self.poCats, layer, cat)
+            self.cats[layer] = max(cat, self.cats.get(layer, 1))
+        
+        # append points
+        Vect_reset_line(self.poPoints)
+        for c in coords:
+            Vect_append_point(self.poPoints, c[0], c[1], 0.0)
+        
+        if ftype & (GV_BOUNDARY | GV_AREA):
+            # close boundary
+            points = self.poPoints.contents
+            last = points.n_points - 1
+            if Vect_points_distance(points.x[0], points.x[0], points.z[0],
+                                    points.x[last], points.x[last], points.z[last],
+                                    is3D) <= threshold:
+                points.x[last] = points.x[0]
+                points.y[last] = points.y[0]
+                points.z[last] = points.z[0]
+        
+        if snap != NO_SNAP:
+            # apply snapping (node or vertex)
+            modeSnap = not (snap == SNAP)
+            Vedit_snap_line(self.poMapInfo, self.popoBgMapInfo, int(self.poBgMapInfo is not None),
+                            -1, self.poPoints, threshold, modeSnap)
+        
+        if ftype == GV_AREA:
+            ltype = GV_BOUNDARY
+        else:
+            ltype = ftype
+        newline = Vect_write_line(self.poMapInfo, ltype, self.poPoints, self.poCats)
+        if newline < 0:
+            self._error.WriteLine()
+            return (-1, None)
+        else:
+            fids.append(newline)
+        
+        left = right = -1
+        if ftype & GV_AREA:
+            # add centroids for left/right area
+            bpoints = Vect_new_line_struct()
+            cleft = c_int()
+            cright = c_int()
+            
+            Vect_get_line_areas(self.poMapInfo, newline,
+                                byref(cleft), byref(cright))
+            left = cleft.value
+            right = cright.value
+            
+            # check if area exists and has no centroid inside
+            if layer > 0 and (left > 0 or right > 0):
+                Vect_cat_set(self.poCats, layer, cat)
+                self.cats[layer] = max(cat, self.cats.get(layer, 0))
+            
+            x = c_double()
+            y = c_double()
+            if left > 0 and \
+                    Vect_get_area_centroid(self.poMapInfo, left) == 0:
+                # if Vect_get_area_points(self.poMapInfo, left, bpoints) > 0 and
+                # Vect_find_poly_centroid(bpoints, byref(x), byref(y)) == 0:
+                if Vect_get_point_in_area(self.poMapInfo, left, byref(x), byref(y)) == 0:
+                    Vect_reset_line(bpoints)
+                    Vect_append_point(bpoints, x.value, y.value, 0.0)
+                    newline = Vect_write_line(self.poMapInfo, GV_CENTROID,
+                                              bpoints, self.poCats)
+                    if newline < 0:
+                        self._error.WriteLine()
+                        return (len(fids), fids)
+                    else:
+                        fids.append(newline)
+                    
+            if right > 0 and \
+                    Vect_get_area_centroid(self.poMapInfo, right) == 0:
+                # if Vect_get_area_points(byref(self.poMapInfo), right, bpoints) > 0 and 
+                # Vect_find_poly_centroid(bpoints, byref(x), byref(y)) == 0:
+                if Vect_get_point_in_area(self.poMapInfo, left, byref(x), byref(y)) == 0:
+                    Vect_reset_line(bpoints)
+                    Vect_append_point(bpoints, x.value, y.value, 0.0)
+                    newline =  Vect_write_line(byref(self.poMapInfo), GV_CENTROID,
+                                               bpoints, self.poCats)
+                    if newline < 0:
+                        self._error.WriteLine()
+                        return (len(fids, fids))
+                    else:
+                        fids.append(newline)
+                    
+            Vect_destroy_line_struct(bpoints)
+        
+        # register changeset
+        changeset = len(self.changesets)
+        self._addActionToChangeset(changeset, newline, add = True)
+        
+        # break at intersection
+        if self._settings['breakLines']:
+            self._breakLineAtIntersection(newline, self.poPoints, changeset)
+        
+        return (len(fids), fids)
+    
+    def _ModifyLineVertex(self, coords, add = True):
+        """!Add or remove vertex
+        
+        Shape of line/boundary is not changed when adding new vertex.
+        
+        @param coords coordinates of point
+        @param add True to add, False to remove
+        
+        @return id id of the new feature
+        @return 0 nothing changed
+        @return -1 error
+        """
+        if not self._checkMap():
+            return -1
+        
+        selected = self._display.selected
+        if len(selected['ids']) != 1:
+            return 0
+        
+        poList  = self._display.GetSelectedIList()
+        Vect_reset_line(self.poPoints)
+        Vect_append_point(self.poPoints, coords[0], coords[1], 0.0)
+        
+        nlines = Vect_get_num_lines(self.poMapInfo)
+        thresh = self._display.GetThreshold(type = 'selectThresh')
+        
+        changeset = self._addActionsBefore()
+        
+        if add:
+            ret = Vedit_add_vertex(self.poMapInfo, poList,
+                                   self.poPoints, thresh)
+        else:
+            ret = Vedit_remove_vertex(self.poMapInfo, poList,
+                                      self.poPoints, thresh)
+        Vect_destroy_list(poList)
+        
+        if ret > 0:
+            self._addActionsAfter(changeset, nlines)
+        else:
+            del self.changesets[changeset]
+        
+        if not add and ret > 0 and self._settings['breakLines']:
+            self._breakLineAtIntersection(Vect_get_num_lines(self.poMapInfo),
+                                          None, changeset)
+                
+        return nlines + 1 # feature is write at the end of the file
+    
+    def GetLineCats(self, line):
+        """!Get list of layer/category(ies) for selected feature.
+
+        @param line feature id (-1 for first selected feature)
+
+        @return list of layer/cats
+        """
+        ret = dict()
+        if not self._checkMap():
+            return ret
+        
+        if line == -1 and len(self._display.selected['ids']) < 1:
+            return ret
+        
+        if line == -1:
+            line = self._display.selected['ids'][0]
+            
+        if not Vect_line_alive(self.poMapInfo, line):
+            self._error.DeadLine(line)
+            return ret
+        
+        if Vect_read_line(self.poMapInfo, None, self.poCats, line) < 0:
+            self._error.ReadLine(line)
+            return ret
+        
+        cats = self.poCats.contents
+        for i in range(cats.n_cats):
+            field = cats.field[i]
+            if field not in ret:
+                ret[field] = list()
+            ret[field].append(cats.cat[i])
+        
+        return ret
+
+    def GetLayers(self):
+        """!Get list of layers
+        
+        Requires self.InitCats() to be called.
+
+        @return list of layers
+        """
+        return self.cats.keys()
+    
+    def UpdateSettings(self):
+        """!Update digit (and display) settings
+        """
+        self._display.UpdateSettings()
+        
+        self._settings['breakLines']  = bool(UserSettings.Get(group = 'vdigit', key = "breakLines",
+                                                              subkey = 'enabled'))
+        
+    def SetCategory(self):
+        """!Update self.cats based on settings"""
+        sel = UserSettings.Get(group = 'vdigit', key = 'categoryMode', subkey = 'selection')
+        cat = None
+        if sel == 0: # next to usep
+            cat = self._setCategoryNextToUse()
+        elif sel == 1:
+            cat = UserSettings.Get(group = 'vdigit', key = 'category', subkey = 'value')
+        
+        if cat:
+            layer = UserSettings.Get(group = 'vdigit', key = 'layer', subkey = 'value')
+            self.cats[layer] = cat
+        
+        return cat
+    
+    def _setCategoryNextToUse(self):
+        """!Find maximum category number for the given layer and
+        update the settings
+
+        @return category to be used
+        """
+        # get max category number for given layer and update the settings
+        layer = UserSettings.Get(group = 'vdigit', key = 'layer', subkey = 'value')
+        cat = self.cats.get(layer, 0) + 1
+        UserSettings.Set(group = 'vdigit', key = 'category', subkey = 'value',
+                         value = cat)
+        Debug.msg(1, "IVDigit._setCategoryNextToUse(): cat=%d", cat)
+        
+        return 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
+    


Property changes on: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/wxvdigit.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Added: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/wxvdriver.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/wxvdriver.py	                        (rev 0)
+++ grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/wxvdriver.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -0,0 +1,1002 @@
+"""!
+ at package wxvdriver.py
+
+ at brief wxGUI vector digitizer (display driver)
+
+Code based on wxVdigit C++ component from GRASS 6.4.0
+(gui/wxpython/vdigit). Converted to Python in 2010/12-2011/01.
+
+List of classes:
+ - DisplayDriver
+
+(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.
+
+ at author Martin Landa <landa.martin gmail.com>
+"""
+
+import math
+
+import wx
+
+from debug import Debug
+from preferences import globalSettings as UserSettings
+
+from grass.lib.gis    import *
+from grass.lib.vector import *
+from grass.lib.vedit  import *
+
+log      = None
+progress = None
+
+def print_error(msg, type):
+    """!Redirect stderr"""
+    global log
+    if log:
+        log.write(msg)
+    else:
+        print msg
+    
+    return 0
+
+def print_progress(value):
+    """!Redirect progress info"""
+    global progress
+    if progress:
+        progress.SetValue(value)
+    else:
+        print value
+    
+    return 0
+
+errtype = CFUNCTYPE(UNCHECKED(c_int), String, c_int)
+errfunc = errtype(print_error)
+pertype = CFUNCTYPE(UNCHECKED(c_int), c_int)
+perfunc = pertype(print_progress)
+
+class DisplayDriver:
+    def __init__(self, device, deviceTmp, mapObj, window, glog, gprogress):
+        """!Display driver used by vector digitizer
+        
+        @param device    wx.PseudoDC device where to draw vector objects
+        @param deviceTmp wx.PseudoDC device where to draw temporary vector objects
+        @param mapOng    Map Object (render.Map)
+        @param windiow   parent window for dialogs
+        @param glog      logging device (None to discard messages)
+        @param gprogress progress bar device (None to discard message)
+        """
+        global errfunc, perfunc, log, progress
+        log = glog
+        progress = gprogress
+        
+        G_gisinit('')             # initialize GRASS libs
+        G_set_error_routine(errfunc) 
+        G_set_percent_routine(perfunc)
+        
+        self.mapInfo   = None     # open vector map (Map_Info structure)
+        self.poMapInfo = None     # pointer to self.mapInfo
+        self.is3D      = False    # is open vector map 3D
+        
+        self.dc      = device     # PseudoDC devices
+        self.dcTmp   = deviceTmp
+        self.mapObj  = mapObj
+        self.region  = mapObj.GetCurrentRegion()
+        self.window  = window
+        self.log     = log        # log device
+
+        self.firstNode = True     # track PseudoDC Id of selected features
+        self.lastNodeId = -1
+        
+        # GRASS lib
+        self.poPoints = Vect_new_line_struct()
+        self.poCats   = Vect_new_cats_struct()
+        
+        # selected objects
+        self.selected = {
+            'field'   : -1,      # field number
+            'cats'    : list(),  # list of cats
+            'ids'     : list(),  # list of ids
+            'idsDupl' : list(),  # list of duplicated features
+            }
+        
+        # digitizer settings
+        self.settings = {
+            'highlight'     : None,
+            'highlightDupl' : { 'enabled' : False,
+                                'color'   : None },
+            'point'         : { 'enabled' : False,
+                                'color'   : None },
+            'line'          : { 'enabled' : False,
+                                'color'   : None },
+            'boundaryNo'    : { 'enabled' : False,
+                                'color'   : None },
+            'boundaryOne'   : { 'enabled' : False,
+                                'color'   : None },
+            'boundaryTwo'   : { 'enabled' : False,
+                                'color'   : None },
+            'centroidIn'    : { 'enabled' : False,
+                                'color'   : None },
+            'centroidOut'   : { 'enabled' : False,
+                                'color'   : None },
+            'centroidDup'   : { 'enabled' : False,
+                                'color'   : None },
+            'nodeOne'       : { 'enabled' : False,
+                                'color'   : None },
+            'nodeTwo'       : { 'enabled' : False,
+                                'color'   : None },
+            'vertex'        : { 'enabled' : False,
+                                'color'   : None },
+            'area'          : { 'enabled' : False,
+                                'color'   : None },
+            'direction'     : { 'enabled' : False,
+                                'color'   : None },
+            'lineWidth'     : -1,    # screen units 
+            }
+        
+        # topology
+        self._resetTopology()
+        
+        self._drawSelected = False
+        self._drawSegments = False
+        
+        self.UpdateSettings()
+        
+    def __del__(self):
+        """!Close currently open vector map"""
+        G_unset_error_routine()
+        G_unset_percent_routine()
+        
+        if self.poMapInfo:
+            self.CloseMap()
+        
+        Vect_destroy_line_struct(self.poPoints)
+        Vect_destroy_cats_struct(self.poCats)
+
+    def _resetTopology(self):
+        """!Reset topology dict
+        """
+        self.topology = {
+            'highlight'   : 0,
+            'point'       : 0,
+            'line'        : 0,
+            'boundaryNo'  : 0,
+            'boundaryOne' : 0,
+            'boundaryTwo' : 0,
+            'centroidIn'  : 0,
+            'centroidOut' : 0,
+            'centroidDup' : 0,
+            'nodeOne'     : 0,
+            'nodeTwo'     : 0,
+            'vertex'      : 0,
+            }
+        
+    def _cell2Pixel(self, east, north, elev):
+        """!Conversion from geographic coordinates (east, north)
+        to screen (x, y)
+  
+        @todo 3D stuff...
+
+        @param east, north, elev geographical coordinates
+
+        @return x, y screen coordinates (integer)
+        """
+        map_res = max(self.region['ewres'], self.region['nsres'])
+        w = self.region['center_easting']  - (self.mapObj.width  / 2) * map_res
+        n = self.region['center_northing'] + (self.mapObj.height / 2) * map_res
+        
+        return int((east - w) / map_res), int((n - north) / map_res)
+    
+    def _drawCross(self, pdc, point, size = 5):
+        """!Draw cross symbol of given size to device content
+   
+        Used for points, nodes, vertices
+
+        @param[in,out] PseudoDC where to draw
+        @param point coordinates of center
+        @param size size of the cross symbol
+   
+        @return 0 on success
+        @return -1 on failure
+        """
+        if not pdc or not point:
+            return -1
+        
+        pdc.DrawLine(point.x - size, point.y, point.x + size, point.y)
+        pdc.DrawLine(point.x, point.y - size, point.x, point.y + size)
+        
+        return 0
+    
+    def _drawObject(self, robj):
+        """!Draw given object to the device
+        
+        The object is defined as robject() from vedit.h.
+        
+        @param robj object to be rendered
+        
+        @return  1 on success
+        @return -1 on failure (vector feature marked as dead, etc.)
+        """
+        if not self.dc or not self.dcTmp:
+            return -1
+        
+        Debug.msg(3, "_drawObject(): type=%d npoints=%d", robj.type, robj.npoints)
+        brush = None
+        if self._isSelected(robj.fid):
+            pdc = self.dcTmp
+            if self.settings['highlightDupl']['enabled'] and self._isDuplicated(robj.fid):
+                pen = wx.Pen(self.settings['highlightDupl']['color'], self.settings['lineWidth'], wx.SOLID)
+            else:            
+                pen = wx.Pen(self.settings['highlight'], self.settings['lineWidth'], wx.SOLID)
+            
+            dcId = 1
+            self.topology['highlight'] += 1
+            if not self._drawSelected:
+                return
+        else:
+            pdc = self.dc
+            pen, brush = self._definePen(robj.type)
+            dcId = 0
+        
+        pdc.SetPen(pen)        
+        if brush:
+            pdc.SetBrush(brush)
+        
+        if robj.type & (TYPE_POINT | TYPE_CENTROIDIN | TYPE_CENTROIDOUT | TYPE_CENTROIDDUP |
+                        TYPE_NODEONE | TYPE_NODETWO | TYPE_VERTEX): # -> point
+            if dcId > 0:
+                if robj.type == TYPE_VERTEX:
+                    dcId = 3 # first vertex
+                elif robj.type & (TYPE_NODEONE | TYPE_NODETWO):
+                    if self.firstNode:
+                        dcId = 1
+                        self.firstNode = False
+                    else:
+                        dcId = self.lastNodeId
+            
+            for i in range(robj.npoints):
+                p = robj.point[i]
+                if dcId > 0:
+                    pdc.SetId(dcId)
+                    dcId += 2
+                self._drawCross(pdc, p)
+        else:
+            if dcId > 0 and self._drawSegments:
+                self.fisrtNode = True
+                self.lastNodeId = robj.npoints * 2 - 1
+                dcId = 2 # first segment
+                i = 0
+                while i < robj.npoints - 1:
+                    point_beg = wx.Point(robj.point[i].x, robj.point[i].y)
+                    point_end = wx.Point(robj.point[i+1].x, robj.point[i+1].y)
+                    pdc.SetId(dcId) # set unique id & set bbox for each segment
+                    pdc.SetPen(pen)
+                    pdc.SetIdBounds(dcId - 1, wx.Rect(point_beg.x, point_beg.y, 0, 0))
+                    pdc.SetIdBounds(dcId, wx.RectPP(point_beg, point_end))
+                    pdc.DrawLine(point_beg.x, point_beg.y,
+                                 point_end.x, point_end.y)
+                    i    += 1
+                    dcId += 2
+                pdc.SetIdBounds(dcId - 1, wx.Rect(robj.point[robj.npoints - 1].x,
+                                                  robj.point[robj.npoints - 1].y,
+                                                  0, 0))
+            else:
+                points = list()
+                for i in range(robj.npoints):
+                    p = robj.point[i]
+                    points.append(wx.Point(p.x, p.y))
+                    
+                if robj.type == TYPE_AREA:
+                    pdc.DrawPolygon(points)
+                else:
+                    pdc.DrawLines(points)
+        
+    def _definePen(self, rtype):
+        """!Define pen/brush based on rendered object)
+        
+        Updates also self.topology dict
+
+        @return pen, brush
+        """
+        if rtype == TYPE_POINT:
+            key = 'point'
+        elif rtype == TYPE_LINE:
+            key = 'line'
+        elif rtype == TYPE_BOUNDARYNO:
+            key = 'boundaryNo'
+        elif rtype == TYPE_BOUNDARYTWO:
+            key = 'boundaryTwo'
+        elif rtype == TYPE_BOUNDARYONE:
+            key = 'boundaryOne'
+        elif rtype == TYPE_CENTROIDIN:
+            key = 'centroidIn'
+        elif rtype == TYPE_CENTROIDOUT:
+            key = 'centroidOut'
+        elif rtype == TYPE_CENTROIDDUP:
+            key = 'centroidDup'
+        elif rtype == TYPE_NODEONE:
+            key = 'nodeOne'
+        elif rtype == TYPE_NODETWO:
+            key = 'nodeTwo'
+        elif rtype == TYPE_VERTEX:
+            key = 'vertex'
+        elif rtype == TYPE_AREA:
+            key = 'area' 
+        elif rtype == TYPE_ISLE:
+            key = 'isle'
+        elif rtype == TYPE_DIRECTION:
+            key = 'direction'
+        
+        if key not in ('direction', 'area', 'isle'):
+            self.topology[key] += 1
+        
+        if key in ('area', 'isle'):
+            pen = wx.TRANSPARENT_PEN
+            if key == 'area':
+                brush = wx.Brush(self.settings[key]['color'], wx.SOLID)
+            else:
+                brush = wx.TRANSPARENT_BRUSH
+        else:
+            pen = wx.Pen(self.settings[key]['color'], self.settings['lineWidth'], wx.SOLID)
+            brush = None
+        
+        return pen, brush
+        
+    def _getDrawFlag(self):
+        """!Get draw flag from the settings
+        
+        See vedit.h for list of draw flags.
+        
+        @return draw flag (int)
+        """
+        ret = 0
+        if self.settings['point']['enabled']:
+            ret |= DRAW_POINT
+        if self.settings['line']['enabled']:
+            ret |= DRAW_LINE
+        if self.settings['boundaryNo']['enabled']:
+            ret |= DRAW_BOUNDARYNO
+        if self.settings['boundaryTwo']['enabled']:
+            ret |= DRAW_BOUNDARYTWO
+        if self.settings['boundaryOne']['enabled']:
+            ret |= DRAW_BOUNDARYONE
+        if self.settings['centroidIn']['enabled']:
+            ret |= DRAW_CENTROIDIN
+        if self.settings['centroidOut']['enabled']:
+            ret |= DRAW_CENTROIDOUT
+        if self.settings['centroidDup']['enabled']:
+            ret |= DRAW_CENTROIDDUP
+        if self.settings['nodeOne']['enabled']:
+            ret |= DRAW_NODEONE
+        if self.settings['nodeTwo']['enabled']:
+            ret |= DRAW_NODETWO
+        if self.settings['vertex']['enabled']:
+            ret |= DRAW_VERTEX
+        if self.settings['area']['enabled']:
+            ret |= DRAW_AREA
+        if self.settings['direction']['enabled']:
+            ret |= DRAW_DIRECTION
+        
+        return ret
+        
+    def _isSelected(self, line, force = False):
+        """!Check if vector object selected?
+   
+        @param line feature id
+
+        @return True if vector object is selected
+        @return False if vector object is not selected
+        """
+        if len(self.selected['cats']) < 1 or force:
+            # select by id
+            if line in self.selected['ids']:
+                return True
+        else: 
+            # select by cat
+            cats = self.poCats.contents
+            for i in range(cats.n_cats):
+                if cats.field[i] == self.selected['field'] and \
+                        cats.cat[i] in self.selected['cats']:
+                    # remember id
+                    # -> after drawing all features selected.cats is reseted */
+                    self.selected['ids'].append(line)
+                    return True
+        
+        return False
+
+    def _isDuplicated(self, line):
+        """!Check for already marked duplicates
+        
+        @param line feature id
+
+        @return True line already marked as duplicated
+        @return False not duplicated
+        """
+        return line in self.selected['idsDupl']
+    
+    def _getRegionBox(self):
+        """!Get bound_box() from current region
+
+        @return bound_box
+        """
+        box = bound_box()
+        
+        box.N = self.region['n']
+        box.S = self.region['s']
+        box.E = self.region['e']
+        box.W = self.region['w']
+        box.T = PORT_DOUBLE_MAX
+        box.B = -PORT_DOUBLE_MAX
+        
+        return box
+
+    def DrawMap(self, force = False):
+        """!Draw content of the vector map to the device
+        
+        @param force force drawing
+        @return number of drawn features
+        @return -1 on error
+        """
+        Debug.msg(1, "DisplayDriver.DrawMap(): force=%d", force)
+        
+        if not self.poMapInfo or not self.dc or not self.dcTmp:
+            return -1
+        
+        rlist = Vedit_render_map(self.poMapInfo, byref(self._getRegionBox()), self._getDrawFlag(),
+                                 self.region['center_easting'], self.region['center_northing'],
+                                 self.mapObj.width, self.mapObj.height,
+                                 max(self.region['nsres'], self.region['ewres'])).contents
+        
+        self._resetTopology()
+        
+        self.dc.BeginDrawing()
+        self.dcTmp.BeginDrawing()
+        
+        # draw objects
+        for i in range(rlist.nitems):
+            robj = rlist.item[i].contents
+            self._drawObject(robj)
+        
+        self.dc.EndDrawing()
+        self.dcTmp.EndDrawing()
+        
+        # reset list of selected features by cat 
+        # list of ids - see IsSelected()
+        self.selected['field'] = -1
+        self.selected['cats'] = list()
+        
+    def _getSelectType(self):
+        """!Get type(s) to be selected
+
+        Used by SelectLinesByBox() and SelectLineByPoint()
+        """
+        ftype = 0
+        for feature in (('point',    GV_POINT),
+                        ('line',     GV_LINE),
+                        ('centroid', GV_CENTROID),
+                        ('boundary', GV_BOUNDARY)):
+            if UserSettings.Get(group = 'vdigit', key = 'selectType',
+                                subkey = [feature[0], 'enabled']):
+                ftype |= feature[1]
+        
+        return ftype
+
+    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
+        be excluded from this list.
+        
+        @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 None on error
+        """
+        thisMapInfo = poMapInfo is None
+        if not poMapInfo:
+            poMapInfo = self.poMapInfo
+        
+        if not poMapInfo:
+            return None
+        
+        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()
+        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(poMapInfo, poBbox,
+                                     0, None, # isles
+                                     self._getSelectType(), poList)
+        
+        flist = poList.contents
+        nlines = flist.n_values
+        Debug.msg(1, "DisplayDriver.SelectLinesByBox() num = %d", nlines)
+        for i in range(nlines):
+            line = flist.value[i]
+            if UserSettings.Get(group = 'vdigit', key = 'selectInside',
+                                subkey = 'enabled'):
+                inside = True
+                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],
+                                              poBbox):
+                        inside = False
+                        break
+                    
+                if not inside:
+                    continue # skip lines just overlapping bbox
+            
+            if not self._isSelected(line):
+                selected.append(line)
+            else:
+                selected.remove(line)
+        
+        Vect_destroy_line_struct(poBbox)
+        Vect_destroy_list(poList)
+        
+        return nlines
+
+    def SelectLineByPoint(self, point, poMapInfo = None):
+        """!Select vector feature by given point in given
+        threshold
+   
+        Only one vector object can be selected. Bounding boxes of
+        all segments are stores.
+        
+        @param point points coordinates (x, y)
+        @param poMapInfo use external Map_info, None for self.poMapInfo
+
+        @return dict {'line' : feature id, 'point' : point on line}
+        """
+        thisMapInfo = poMapInfo is None
+        if not poMapInfo:
+            poMapInfo = self.poMapInfo
+        
+        if not poMapInfo:
+            return { 'line' : -1, 'point': 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()
+        
+        lineNearest = Vect_find_line_list(poMapInfo, point[0], point[1], 0,
+                                           self._getSelectType(), self.GetThreshold(), self.is3D,
+                                           None, poFound)
+        Debug.msg(1, "DisplayDriver.SelectLineByPoint() found = %d", lineNearest)
+        
+        if lineNearest > 0:
+            if not self._isSelected(lineNearest):
+                selected.append(lineNearest)
+            else:
+                selected.remove(lineNearest)
+        
+        px = c_double()
+        py = c_double()
+        pz = c_double()
+        if not self._validLine(lineNearest):
+            return { 'line' : -1, 'point': None }
+	ftype = Vect_read_line(poMapInfo, self.poPoints, self.poCats, lineNearest)
+	Vect_line_distance (self.poPoints, point[0], point[1], 0.0, self.is3D,
+			    byref(px), byref(py), byref(pz),
+			    None, None, None)
+        
+	# check for duplicates 
+	if self.settings['highlightDupl']['enabled']:
+            found = poFound.contents
+	    for i in range(found.n_values):
+		line = found.value[i]
+		if line != lineNearest:
+                    selected.append(line)
+	    
+            self.GetDuplicates()
+	    
+	    for i in range(found.n_values):
+		line = found.value[i]
+		if line != lineNearest and not self._isDuplicated(line):
+                    selected.remove(line)
+        
+        Vect_destroy_list(poFound)
+        
+        if thisMapInfo:
+            # drawing segments can be very expensive
+            # only one features selected
+            self._drawSegments = True
+        
+        return { 'line'  : lineNearest,
+                 'point' : (px.value, py.value, pz.value) }
+    
+    def _listToIList(self, plist):
+        """!Generate from list struct_ilist
+        """
+        ilist = Vect_new_list()
+        for val in plist:
+            Vect_list_append(ilist, val)
+        
+        return ilist
+        
+    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):
+        """!Get ids of selected objects
+        
+        @param grassId True for feature id, False for PseudoDC id
+        
+        @return list of ids of selected vector objects
+        """
+        if grassId:
+            return self.selected['ids']
+        
+        dc_ids = list()
+        
+        if not self._drawSegments:
+            dc_ids.append(1)
+        elif len(self.selected['ids']) > 0:
+            # only first selected feature
+            Vect_read_line(self.poMapInfo, self.poPoints, None,
+                           self.selected['ids'][0])
+            points = self.poPoints.contents
+            # node - segment - vertex - segment - node
+            for i in range(1, 2 * points.n_points):
+                dc_ids.append(i)
+        
+        return dc_ids
+        
+    def SetSelected(self, ids, layer = -1):
+        """!Set selected vector objects
+
+        @param list of ids (None to unselect features)
+        @param layer layer number for features selected based on category number
+        """
+        if ids:
+            self._drawSelected = True
+        else:
+            self._drawSelected = False
+        
+        if layer > 0:
+            selected.field = layer
+            self.selected['cats'] = ids
+        else:
+            field = -1
+            self.selected['ids'] = ids
+        
+    def GetSelectedVertex(self, pos):
+        """!Get PseudoDC vertex id of selected line
+
+        Set bounding box for vertices of line.
+        
+        @param pos position
+        
+        @return id of center, left and right vertex
+        @return 0 no line found
+        @return -1 on error
+        """
+        returnId = list()
+        # only one object can be selected
+        if len(self.selected['ids']) != 1 or not self._drawSegments:
+            return returnId
+        
+        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
+        Gid = -1
+        # find the closest vertex (x, y)
+        DCid = 1
+        points = self.poPoints.contents
+        for idx in range(points.n_points):
+            dist = Vect_points_distance(pos[0], pos[1], 0.0,
+                                        points.x[idx], points.y[idx], points.z[idx], 0)
+            
+            if idx == 0:
+                minDist = dist
+                Gid     = idx
+            else:
+                if minDist > dist:
+                    minDist = dist
+                    Gid = idx
+            
+            vx, vy = self._cell2Pixel(points.x[idx], points.y[idx], points.z[idx])
+            rect = wx.Rect(vx, vy, 0, 0)
+            self.dc.SetIdBounds(DCid, rect)
+            DCid += 2
+        
+        if minDist > self.GetThreshold():
+            return returnId
+        
+        # translate id
+        DCid = Gid * 2 + 1
+        
+        # add selected vertex
+        returnId.append(DCid)
+        # left vertex
+        if DCid == startId:
+            returnId.append(-1)
+        else:
+            returnId.append(DCid - 2)
+        # right vertex
+        if DCid == (points.n_points - 1) * 2 + startId:
+            returnId.append(-1)
+        else:
+            returnId.append(DCid + 2)
+        
+        return returnId
+
+    def DrawSelected(self, flag):
+        """!Draw selected features
+        
+        @param flag True to draw selected features
+        """
+        self._drawSelected = bool(flag)
+        
+    def CloseMap(self):
+        """!Close vector map
+        
+        @return 0 on success
+        @return non-zero on error
+        """
+        ret = 0
+        if self.poMapInfo:
+            # rebuild topology
+            Vect_build_partial(self.poMapInfo, GV_BUILD_NONE)
+            Vect_build(self.poMapInfo)
+
+            # close map and store topo/cidx
+            ret = Vect_close(self.poMapInfo)
+            del self.mapInfo
+            self.poMapInfo = self.mapInfo = None
+        
+        return ret
+    
+    def OpenMap(self, name, mapset, update = True):
+        """!Open vector map by the driver
+        
+        @param name name of vector map to be open
+        @param mapset name of mapset where the vector map lives
+   
+        @return map_info
+        @return None on error
+        """
+        Debug.msg("DisplayDriver.OpenMap(): name=%s mapset=%s updated=%d",
+                  name, mapset, update)
+        if not self.mapInfo:
+            self.mapInfo = Map_info()
+            self.poMapInfo = pointer(self.mapInfo)
+        
+        # open existing map
+        if update:
+            ret = Vect_open_update(self.poMapInfo, name, mapset)
+        else:
+            ret = Vect_open_old(self.poMapInfo, name, mapset)
+        self.is3D = Vect_is_3d(self.poMapInfo)
+        
+        if ret == -1: # error
+            del self.mapInfo
+            self.poMapInfo = self.mapInfo = None
+        elif ret < 2:
+            dlg = wx.MessageDialog(parent = self.window,
+                                   message = _("Topology for vector map <%s> is not available. "
+                                               "Topology is required by digitizer. Do you want to "
+                                               "rebuild topology (takes some time) and open the vector map "
+                                               "for editing?") % name,
+                                   caption=_("Topology missing"),
+                                   style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION | wx.CENTRE)
+            ret = dlg.ShowModal()
+            if ret != wx.ID_YES:
+                del self.mapInfo
+                self.poMapInfo = self.mapInfo = None
+            else:
+                Vect_build(self.poMapInfo)
+        
+        return self.poMapInfo
+    
+    def GetMapBoundingBox(self):
+        """!Get bounding box of (opened) vector map layer
+
+        @return (w,s,b,e,n,t)
+        """
+        if not self.poMapInfo:
+            return None
+        
+        bbox = bound_box()
+        Vect_get_map_box(self.poMapInfo, byref(bbox))
+
+        return bbox.W, bbox.S, bbox.B, \
+            bbox.E, bbox.N, bbox.T
+    
+    def UpdateSettings(self, alpha = 255):
+        """!Update display driver settings
+
+        @todo map units
+        
+        @alpha color value for aplha channel
+        """
+        color = dict()
+        for key in self.settings.keys():
+            if key == 'lineWidth':
+                self.settings[key] = int(UserSettings.Get(group = 'vdigit', key = 'lineWidth',
+                                                          subkey = 'value'))
+                continue
+            
+            color = wx.Color(UserSettings.Get(group = 'vdigit', key = 'symbol',
+                                              subkey = [key, 'color'])[0],
+                             UserSettings.Get(group = 'vdigit', key = 'symbol',
+                                              subkey = [key, 'color'])[1],
+                             UserSettings.Get(group = 'vdigit', key = 'symbol',
+                                              subkey = [key, 'color'])[2])
+            
+            if key == 'highlight':
+                self.settings[key] = color
+                continue
+            
+            if key == 'highlightDupl':
+                self.settings[key]['enabled'] = bool(UserSettings.Get(group = 'vdigit', key = 'checkForDupl',
+                                                                      subkey = 'enabled'))
+            else:
+                self.settings[key]['enabled'] = bool(UserSettings.Get(group = 'vdigit', key = 'symbol',
+                                                                      subkey = [key, 'enabled']))
+            
+            self.settings[key]['color'] = color
+        
+    def UpdateRegion(self):
+        """!Update geographical region used by display driver
+        """
+        self.region = self.mapObj.GetCurrentRegion()
+        
+    def GetThreshold(self, type = 'snapping', value = None, units = None):
+        """!Return threshold value in map units
+        
+        @param type snapping mode (node, vertex)
+        @param value threshold to be set up
+        @param units units (map, screen)
+
+        @return threshold value
+        """
+        if value is None:
+            value = UserSettings.Get(group = 'vdigit', key = type, subkey = 'value')
+        
+        if units is None:
+            units = UserSettings.Get(group = 'vdigit', key = type, subkey = 'units')
+        
+        if value < 0:
+            value = (self.region['nsres'] + self.region['ewres']) / 2.0
+        
+        if units == "screen pixels":
+            # pixel -> cell
+            res = max(self.region['nsres'], self.region['ewres'])
+            return value * res
+        
+        return value
+    
+    def GetDuplicates(self):
+        """!Return ids of (selected) duplicated vector features
+        """
+        if not self.poMapInfo:
+            return
+        
+        ids = dict()
+        APoints = Vect_new_line_struct()
+        BPoints = Vect_new_line_struct()
+        
+        self.selected['idsDupl'] = list()
+        
+        for i in range(len(self.selected['ids'])):
+            line1 = self.selected['ids'][i]
+            if self._isDuplicated(line1):
+                continue
+            
+            Vect_read_line(self.poMapInfo, APoints, None, line1)
+            
+            for line2 in self.selected['ids']:
+                if line1 == line2 or self._isDuplicated(line2):
+                    continue
+                
+                Vect_read_line(self.poMapInfo, BPoints, None, line2)
+	    
+                if Vect_line_check_duplicate(APoints, BPoints, WITHOUT_Z):
+                    if i not in ids:
+                        ids[i] = list()
+                        ids[i].append((line1, self._getCatString(line1)))
+                        self.selected['idsDupl'].append(line1)
+                    
+                    ids[i].append((line2, self._getCatString(line2)))
+                    self.selected['idsDupl'].append(line2)
+        
+        Vect_destroy_line_struct(APoints)
+        Vect_destroy_line_struct(BPoints)
+
+        return ids
+    
+    def _getCatString(self, line):
+        Vect_read_line(self.poMapInfo, None, self.poCats, line)
+        
+        cats = self.poCats.contents
+        catsDict = dict()
+        for i in range(cats.n_cats):
+            layer = cats.field[i]
+            if layer not in catsDict:
+                catsDict[layer] = list()
+            catsDict[layer].append(cats.cat[i])
+        
+        catsStr = ''
+        for l, c in catsDict.iteritems():
+            catsStr = '%d: (%s)' % (l, ','.join(map(str, c)))
+        
+        return catsStr
+
+    def UnSelect(self, lines):
+        """!Unselect vector features
+
+        @param lines list of feature id(s)
+        """
+        checkForDupl = False
+
+        for line in lines:
+            if self._isSelected(line):
+                self.selected['ids'].remove(line)
+            if self.settings['highlightDupl']['enabled'] and self._isDuplicated(line):
+                checkForDupl = True
+
+        if checkForDupl:
+            self.GetDuplicates()
+        
+        return len(self.selected['ids'])
+    
+


Property changes on: grass/branches/releasebranch_6_4/gui/wxpython/gui_modules/wxvdriver.py
___________________________________________________________________
Added: svn:mime-type
   + text/x-python
Added: svn:eol-style
   + native

Modified: grass/branches/releasebranch_6_4/gui/wxpython/icons/grass2_icons.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/icons/grass2_icons.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/icons/grass2_icons.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -9,120 +9,12 @@
 
 import globalvar
 
-iconpath = os.path.join(globalvar.ETCDIR, "gui", "icons", "grass2")
+iconPath = os.path.join(globalvar.ETCDIR, "gui", "icons", "grass2")
 
-IconsGrass2 = {
-    # map display
-    "displaymap" : 'show.png',
-    "rendermap"  : 'layer-redraw.png',
-    "erase"      : 'erase.png',
-    "pointer"    : 'pointer.png',
-    "query"      : 'info.png',
-    "savefile"   : 'map-export.png',
-    "printmap"   : 'print.png',
-    "pan"        : 'pan.png', 
-    # zoom (mapdisplay)
-    "zoom_in"     : 'zoom-in.png',
-    "zoom_out"    : 'zoom-out.png',
-    "zoom_back"   : 'zoom-last.png',
-    "zoommenu"    : 'zoom-more.png',
-    "zoom_extent" : 'zoom-extent.png',
-    # analyze raster (mapdisplay)
-    "analyze"    : 'layer-raster-analyze.png',
-    "measure"    : 'measure-length.png',
-    "profile"    : 'layer-raster-profile.png',
-    "histogram"  : 'layer-raster-histogram.png',
-    "font"       : 'font.png',
-    # overlay (mapdisplay)
-    "overlay"    : 'overlay-add.png',
-    "addtext"    : 'text-add.png',
-    "addbarscale": 'scalebar-add.png',
-    "addlegend"  : 'legend-add.png',
-    "quit"       : 'quit.png',
-    # digit
-    ## add feature
-    "digAddPoint": 'point-create.png',
-    "digAddLine" : 'line-create.png',
-    "digAddBoundary": 'polygon-create.png',
-    "digAddCentroid": 'centroid-create.png',
-    ## vertex
-    "digAddVertex" : 'vertex-create.png',
-    "digMoveVertex" : 'vertex-move.png',
-    "digRemoveVertex" : 'vertex-delete.png',
-    "digSplitLine" : 'line-split.png',
-    ## edit feature
-    "digEditLine" : 'line-edit.png',
-    "digMoveLine" : 'line-move.png',
-    "digDeleteLine" : 'line-delete.png',
-    ## cats
-    "digDispCats" : 'cats-display.png',
-    "digCopyCats" : 'cats-copy.png',
-    ## attributes
-    "digDispAttr" : 'attributes-display.png',
-    ## general
-    "digUndo" : 'undo.png',
-    "digAdditionalTools" : 'tools.png',
-    # layer manager
-    "newdisplay" : 'monitor-create.png',
-    "fileNew"    : 'create.png',
-    "fileLoad"   : 'layer-open.png',
-    "fileOpen"   : 'open.png',
-    "fileSave"   : 'save.png',
-    "fileImport" : 'layer-import.png',
-    "addrast"    : 'layer-raster-add.png',
-    "rastmisc"   : 'layer-raster-more.png',
-    "addrast3d"  : 'layer-raster3d-add.png',
-    "addshaded"  : 'layer-shaded-relief-add.png',
-    "addrarrow"  : 'layer-aspect-arrow-add.png',
-    "addrnum"    : 'layer-cell-cats-add.png',
-    "addvect"    : 'layer-vector-add.png',
-    "vectmisc"   : 'layer-vector-more.png',
-    "addcmd"     : 'layer-command-add.png',
-    "addgrp"     : 'layer-group-add.png',
-    "addovl"     : 'layer-more.png',
-    "addgrid"    : 'layer-grid-add.png',
-    "addgeodesic": 'shortest-distance.png',
-    "addrhumb"   : 'shortest-distance.png',
-    "addlabels"  : 'layer-label-add.png',
-    "delcmd"     : 'layer-remove.png',
-    "attrtable"  : 'table.png',
-    "addrgb"     : 'layer-rgb-add.png',
-    "addhis"     : 'layer-his-add.png',
-    "addthematic": 'layer-vector-thematic-add.png',
-    "addchart"   : 'layer-vector-chart-add.png',
-    "layeropts"  : 'options.png',
-    "modeler"    : 'modeler-main.png',
-    # profile analysis
-    "transect"     : 'layer-raster-profile.png',
-    "profiledraw"  : 'show.png',
-    # georectify
-    "grGcpSet"     : 'gcp-create.png',
-    'grGcpClear'   : 'gcp-remove.png',
-    'grGeorect'    : 'georectify.png',
-    'grGcpRms'     : 'gcp-rms.png',
-    "grGcpSave"    : 'gcp-save.png',
-    "grGcpAdd"     : 'gcp-add.png',
-    "grGcpDelete"  : 'gcp-delete.png',
-    "grGcpReload"  : 'reload.png',
-    # modeler
-    "modelActionAdd" : 'module-add.png',
-    "modelDataAdd"   : 'data-add.png',
-    "modelRelation"  : 'relation-create.png',
-    "modelRun"       : 'execute.png',
-    "modelValidate"  : 'check.png',
-    "imageSave"      : 'image-export.png',
-    "pythonSave"     : 'python-export.png',
-    "modelProperties" : 'options.png',
-    "modelVariables" : 'modeler-variables.png',
-    # 3d view
-    "nvizView"       : '3d-view.png',
-    "nvizSurface"    : '3d-raster.png',
-    "nvizVector"     : '3d-vector.png',
-    "nvizVolume"     : '3d-volume.png',
-    "nvizLight"      : '3d-light.png',
-    "nvizFringe"     : '3d-fringe.png',
-    # various
-    "settings"       : 'settings.png',
-    "redraw"         : 'redraw.png',
-    "help"           : 'help.png',
-    }
+iconSet = dict()
+
+for icon in os.listdir(iconPath):
+    name, ext = os.path.splitext(icon)
+    if ext != '.png':
+        continue
+    iconSet[name] = icon

Modified: grass/branches/releasebranch_6_4/gui/wxpython/icons/grass_icons.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/icons/grass_icons.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/icons/grass_icons.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -8,121 +8,84 @@
 
 import globalvar
 
-iconpath = os.path.join(globalvar.ETCDIR, "gui", "icons", "grass")
-iconpath_vdigit  = os.path.join(globalvar.ETCDIR, "gui", "icons", "grass", "vdigit")
+iconPath = os.path.join(globalvar.ETCDIR, "gui", "icons", "grass")
+iconPathVDigit  = os.path.join(globalvar.ETCDIR, "gui", "icons", "grass", "edit")
 
-IconsGrass = {
-    # map display
-    "displaymap" : 'gui-display.gif',
-    "rendermap"  : 'gui-redraw.gif',
+iconSet = {
+    "show" : 'gui-display.gif',
+    "layer-redraw"  : 'gui-redraw.gif',
     "erase"      : 'gui-erase.gif',
     "pointer"    : 'gui-pointer.gif',
-    "zoom_in"    : 'gui-zoom_in.gif',
-    "zoom_out"   : 'gui-zoom_out.gif',
+    "zoom-in"    : 'gui-zoom_in.gif',
+    "zoom-out"   : 'gui-zoom_out.gif',
     "pan"        : 'gui-pan.gif',
-    "query"      : 'gui-query.gif',
-    "zoom_back"  : 'gui-zoom_back.gif',
-    "zoommenu"   : 'gui-mapzoom.gif',
-    "zoom_extent" : wx.ART_ERROR, # FIXME
-    "savefile"   : 'file-save.gif',
-    "printmap"   : 'file-print.gif',
-    "overlay"    : 'gui-overlay.gif',
-    # digit
-    ## add feature
-    "digAddPoint": 'new.point.gif',
-    "digAddLine" : 'new.line.gif',
-    "digAddBoundary": 'new.boundary.gif',
-    "digAddCentroid": 'new.centroid.gif',
-    ## vertex
-    "digAddVertex" : 'add.vertex.gif',
-    "digMoveVertex" : 'move.vertex.gif',
-    "digRemoveVertex" : 'rm.vertex.gif',
-    "digSplitLine" : 'split.line.gif',
-    ## edit feature
-    "digEditLine" : 'edit.line.gif',
-    "digMoveLine" : 'move.line.gif',
-    "digDeleteLine" : 'delete.line.gif',
-    ## cats
-    "digCopyCats" : 'copy.cats.gif',
-    "digDispCats" : 'display.cats.gif',
-    ## attributes
-    "digDispAttr" : 'display.attributes.gif',
-    ## general
-    "digUndo" : wx.ART_ERROR, # FIXME
-    "digAdditionalTools" : wx.ART_ERROR, # FIXME
-    # layer manager
-    "newdisplay" : 'gui-startmon.gif',
-    "fileNew"    : 'file-new.gif',
-    "fileLoad"   : 'file-new.gif', 
-    "fileOpen"   : 'file-open.gif',
-    "fileSave"   : 'file-save.gif',
-    "fileImport" : 'file-new.gif',
-    "addrast"    : 'element-cell.gif',
-    "rastmisc"   : 'module-d.shadedmap.gif',
-    "addrast3d"  : 'element-grid3.gif',
-    "addvect"    : 'element-vector.gif',
-    "vectmisc"   : 'module-d.vect.thematic.gif',
-    "addcmd"     : 'gui-cmd.gif',
-    "addgrp"     : 'gui-group.gif',
-    "addovl"     : 'module-d.grid.gif',
-    "delcmd"     : 'edit-cut.gif',
-    "attrtable"  : 'db-values.gif',
-    "addrgb"     : 'module-d.rgb.gif',
-    "addhis"     : 'channel-his.gif',
-    "addshaded"  : 'module-d.shadedmap.gif',
-    "addrarrow"  : 'module-d.rast.arrow.gif',
-    "addrnum"    : 'module-d.rast.num.gif',
-    "addthematic": 'module-d.vect.thematic.gif',
-    "addchart"   : 'module-d.vect.chart.gif',
-    "addgrid"    : 'module-d.grid.gif',
-    "addgeodesic": 'module-d.geodesic.gif',
-    "addrhumb"   : 'module-d.rhumbline.gif',
-    "addlabels"  : 'module-d.labels.gif',
-    "addtext"    : 'module-d.text.gif',
-    "addbarscale": 'module-d.barscale.gif',
-    "addlegend"  : 'module-d.legend.gif',
+    "info"      : 'gui-query.gif',
+    "zoom-last"  : 'gui-zoom_back.gif',
+    "zoom-more"   : 'gui-mapzoom.gif',
+    "map-export"   : 'file-save.gif',
+    "print"   : 'file-print.gif',
+    "overlay-add"    : 'gui-overlay.gif',
+    "point-create": 'new.point.gif',
+    "line-create" : 'new.line.gif',
+    "boundary-create": 'new.boundary.gif',
+    "centroid-create": 'new.centroid.gif',
+    "vertex-create" : 'add.vertex.gif',
+    "vertex-move" : 'move.vertex.gif',
+    "vertex-delete" : 'rm.vertex.gif',
+    "line-split" : 'split.line.gif',
+    "line-edit" : 'edit.line.gif',
+    "line-move" : 'move.line.gif',
+    "line-delete" : 'delete.line.gif',
+    "cats-copy" : 'copy.cats.gif',
+    "cats-display" : 'display.cats.gif',
+    "attributes-display" : 'display.attributes.gif',
+    "monitor-create" : 'gui-startmon.gif',
+    "create"    : 'file-new.gif',
+    "layer-open"   : 'file-new.gif', 
+    "open"   : 'file-open.gif',
+    "save"   : 'file-save.gif',
+    "layer-import" : 'file-new.gif',
+    "layer-raster-add"    : 'element-cell.gif',
+    "layer-raster-more"   : 'module-d.shadedmap.gif',
+    "layer-raster3d-add"  : 'element-grid3.gif',
+    "layer-vector-add"    : 'element-vector.gif',
+    "layer-vector-more"   : 'module-d.vect.thematic.gif',
+    "layer-command-add"     : 'gui-cmd.gif',
+    "layer-group-add"     : 'gui-group.gif',
+    "layer-more"     : 'module-d.grid.gif',
+    "layer-remove"     : 'edit-cut.gif',
+    "table"  : 'db-values.gif',
+    "layer-rgb-add"     : 'module-d.rgb.gif',
+    "layer-his-add"     : 'channel-his.gif',
+    "layer-shaded-relief-add"  : 'module-d.shadedmap.gif',
+    "layer-aspect-arrow-add"  : 'module-d.rast.arrow.gif',
+    "layer-cell-cats-add"    : 'module-d.rast.num.gif',
+    "layer-vector-thematic-add": 'module-d.vect.thematic.gif',
+    "layer-vector-chart-add"   : 'module-d.vect.chart.gif',
+    "layer-grid-add"    : 'module-d.grid.gif',
+    "options": 'module-d.geodesic.gif',
+    "options"   : 'module-d.rhumbline.gif',
+    "layer-label-add"  : 'module-d.labels.gif',
+    "text-add"    : 'module-d.text.gif',
+    "scalebar-add": 'module-d.barscale.gif',
+    "legend-add"  : 'module-d.legend.gif',
     "quit"       : 'gui-exit.gif',
-    "modeler"    : wx.ART_ERROR,
-    # analyze raster
-    "analyze"    : 'gui-rastanalyze.gif',
-    "measure"    : 'gui-measure.gif',
+    "layer-raster-analyze"    : 'gui-rastanalyze.gif',
+    "measure-length"    : 'gui-measure.gif',
     "font"       : 'gui-font.gif',
-    "histogram"  : 'module-d.histogram.gif',
+    "layer-raster-histogram"  : 'module-d.histogram.gif',
     "color"      : 'edit-color.gif',
-    "layeropts"  : 'gui-layeroptions.gif',
-    # profile 
-    "profile"    : 'gui-profile.gif',
-    "transect"   : 'gui-profiledefine.gif',
-    "profiledraw" : 'gui-display.gif',
+    "options"  : 'gui-layeroptions.gif',
+    "layer-raster-profile"    : 'gui-profile.gif',
+    "layer-raster-profile"   : 'gui-profiledefine.gif',
+    "show" : 'gui-display.gif',
     "profileopt" : 'gui-profileopt.gif',
-    # georectify
-    'grGcpClear'   : 'gui-gcperase.gif',
-    'grGcpSet'     : 'gui-gcpset.gif',
-    'grGeorect'    : 'gui-georect.gif',
-    'grGcpRms'     : 'gui-rms.gif',
-    "grGcpSave"    : 'file-save.gif', 
-    "grGcpAdd"     : wx.ART_NEW, # FIXME
-    "grGcpDelete"  : wx.ART_DELETE, # FIXME
-    "grGcpReload"  : 'gui-redraw.gif',
-    # modeler
-    "modelActionAdd" : wx.ART_ERROR,
-    "modelDataAdd"   : wx.ART_ERROR,
-    "modelRelation"  : wx.ART_ERROR,
-    "modelRun"       : wx.ART_ERROR,
-    "modelValidate"  : wx.ART_ERROR,
-    "imageSave"      : wx.ART_ERROR,
-    "pythonSave"     : wx.ART_ERROR,
-    "modelProperties" : wx.ART_ERROR,
-    "modelVariables" : wx.ART_ERROR,
-    # 3d view
-    "nvizView"       : wx.ART_ERROR,
-    "nvizSurface"    : wx.ART_ERROR,
-    "nvizVector"     : wx.ART_ERROR,
-    "nvizVolume"     : wx.ART_ERROR,
-    "nvizLight"      : wx.ART_ERROR,
-    "nvizFringe"     : wx.ART_ERROR,
-    # various
+    'gcp-remove'   : 'gui-gcperase.gif',
+    'gcp-create'     : 'gui-gcpset.gif',
+    'georectify'    : 'gui-georect.gif',
+    'gcp-rms'     : 'gui-rms.gif',
+    "gcp-save"    : 'file-save.gif', 
+    "reload"  : 'gui-redraw.gif',
     "settings"       : 'edit-color.gif',
     "redraw"         : 'gui-display.gif',
-    "help"           : wx.ART_ERROR,
     }

Modified: grass/branches/releasebranch_6_4/gui/wxpython/icons/icon.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/icons/icon.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/icons/icon.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -10,7 +10,7 @@
 Classes:
  - MetaIcon
 
-(C) 2007-2008, 2010 by the GRASS Development Team
+(C) 2007-2008, 2010-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.
@@ -20,6 +20,7 @@
 
 import os
 import sys
+import types
 
 sys.path.append(os.path.join(os.getenv("GISBASE"), "etc", "wxpython", "gui_modules"))
 
@@ -30,55 +31,63 @@
 
 from preferences import globalSettings as UserSettings
 
-import grass_icons # default icon set
-iconpath_default = grass_icons.iconpath
-iconpath_vdigit = grass_icons.iconpath_vdigit
-Icons_default = grass_icons.IconsGrass
+import grass2_icons # default icon set
+iconPathDefault = grass2_icons.iconPath
+iconSetDefault  = grass2_icons.iconSet
 
 iconTheme = UserSettings.Get(group='advanced', key='iconTheme', subkey='type')
 if iconTheme == 'silk':
     import silk_icons
-    iconpath = silk_icons.iconpath
-    Icons = silk_icons.IconsSilk
-elif iconTheme == 'grass2':
-    import grass2_icons
-    iconpath = grass2_icons.iconpath
-    Icons = grass2_icons.IconsGrass2
+    iconPath = silk_icons.iconPath
+    iconSet  = silk_icons.iconSet
+elif iconTheme == 'grass':
+    import grass_icons
+    iconPath = grass_icons.iconPath
+    iconPathVDigit = grass_icons.iconPathVDigit
+    iconSet  = grass_icons.iconSet
 else:
-    iconpath = iconpath_default
-    Icons = grass_icons.IconsGrass
+    iconPath = iconPathDefault
+    iconSet  = iconSetDefault
 
 # merge icons dictionaries, join paths
 try:
-    if iconpath and not os.path.exists(iconpath):
+    if iconPath and not os.path.exists(iconPath):
         raise OSError
     
     if iconTheme != 'grass':
         # use default icons if no icon is available
-        for key, img in Icons_default.iteritems():
-            if not Icons.has_key(key) or \
-                    Icons[key] is None: # add key
-                Icons[key] = img
+        for key, img in iconSet.iteritems():
+            if key not in iconSet or \
+                    iconSet[key] is None: # add key
+                iconSet[key] = img
             
-            if Icons[key] == img:
-                if key[0:3] == 'dig':
-                    iconpath_tmp = iconpath_vdigit
-                else:
-                    iconpath_tmp = iconpath_default
-            else:
-                iconpath_tmp = iconpath
-            
-            Icons[key] = os.path.join(iconpath_tmp, Icons[key])
+            iconSet[key] = os.path.join(iconPath, iconSet[key])
     else:
-        for key, img in Icons.iteritems():
-            if img and type (Icons[key]) == type(''):
-                if key[0:3] == 'dig':
-                    Icons[key] = os.path.join(iconpath_vdigit, img)
+        for key, img in iconSet.iteritems():
+            if img and type(iconSet[key]) == types.StringType:
+                if key in ("point-create",
+                           "line-create",
+                           "boundary-create",
+                           "centroid-create",
+                           "polygon-create",
+                           "vertex-create",
+                           "vertex-move",
+                           "vertex-delete",
+                           "line-split",
+                           "line-edit",
+                           "line-move",
+                           "line-delete",
+                           "cats-copy",
+                           "cats-display",
+                           "attributes-display",
+                           "undo",
+                           "tools"):
+                    iconSet[key] = os.path.join(iconPathVDigit, img)
                 else:
-                    Icons[key] = os.path.join(iconpath_default, img)
-except:
-    print >> sys.stderr, _("Unable to load icon theme...")
-    sys.exit(1)
+                    iconSet[key] = os.path.join(iconPath, img)
+                print img, iconSet[key]
+except StandardError, e:
+    sys.exit(_("Unable to load icon theme. Reason: %s") % e)
 
 class MetaIcon:
     """!Handle icon metadata (image path, tooltip, ...)
@@ -134,279 +143,297 @@
 # create list of icon instances
 #
 Icons = {
-    # map display
-    "displaymap" : MetaIcon (img=Icons["displaymap"],
-                             label=_("Display map"),
-                             desc = _("Re-render modified map layers")),
-    "rendermap"  : MetaIcon (img=Icons["rendermap"],
-                             label=_("Re-render map"),
-                             desc=_("Force re-rendering all map layers")),
-    "erase"      : MetaIcon (img=Icons["erase"],
-                             label=_("Erase display")),
-    "pointer"    : MetaIcon (img=Icons["pointer"],
-                             label=_("Pointer")),
-    "zoom_in"    : MetaIcon (img=Icons["zoom_in"],
-                             label=_("Zoom in"),
-                             desc=_("Drag or click mouse to zoom")),
-    "zoom_out"   : MetaIcon (img=Icons["zoom_out"],
-                             label=_("Zoom out"),
-                             desc=_("Drag or click mouse to unzoom")),
-    "pan"        : MetaIcon (img=Icons["pan"],
-                             label=_("Pan"),
-                             desc=_("Drag with mouse to pan")),
-    "query" : MetaIcon (img=Icons["query"],
-                        label=_("Query raster/vector map(s)"),
-                        desc=_("Query selected raster/vector map(s)")),
-    "zoom_back"  : MetaIcon (img=Icons["zoom_back"],
-                             label=_("Return to previous zoom")),
-    "zoommenu"   : MetaIcon (img=Icons["zoommenu"],
-                             label=_("Zoom options"),
-                             desc=_("Display zoom management")),
-    "zoom_extent" : MetaIcon (img=Icons["zoom_extent"],
-                             label=_("Zoom to selected map layer(s)")),
-    "overlay"    : MetaIcon (img=Icons["overlay"],
-                             label=_("Add map elements"),
-                             desc=_("Overlay elements like scale and legend onto map")),
-    "addbarscale": MetaIcon (img=Icons["addbarscale"],
-                             label=_("Add scalebar and north arrow")),
-    "addlegend"  : MetaIcon (img=Icons["addlegend"],
-                             label=_("Add legend")),
-    "savefile"   : MetaIcon (img=Icons["savefile"],
-                             label=_("Save display to graphic file")),
-    "printmap"   : MetaIcon (img=Icons["printmap"],
-                             label=_("Print display")),
-    # layer manager
-    "newdisplay" : MetaIcon (img=Icons["newdisplay"],
-                             label=_("Start new display")),
-    "workspaceNew" : MetaIcon (img=Icons["fileNew"],
-                               label=_("Create new workspace file (Ctrl+N)")),
-    "workspaceLoad" : MetaIcon (img=Icons["fileLoad"],
-                                label=_("Load map layers into workspace (Ctrl+L)")),
-    "workspaceOpen" : MetaIcon (img=Icons["fileOpen"],
-                                label=_("Open existing workspace file (Ctrl+O)")),
-    "workspaceSave" : MetaIcon (img=Icons["fileSave"],
-                                label=_("Save current workspace to file (Ctrl+S)")),
-    "rastImport" : MetaIcon (img=Icons["fileImport"],
-                             label=_("Import raster data")),
-    "vectImport" : MetaIcon (img=Icons["fileImport"],
-                             label=_("Import vector data")),
-    "addrast"    : MetaIcon (img=Icons["addrast"],
-                             label=_("Add raster map layer (Ctrl+R)")),
-    "rastmisc" : MetaIcon (img=Icons["rastmisc"],
-                             label=_("Add various raster map layers (RGB, HIS, shaded relief...)")),
-    "addvect"    : MetaIcon (img=Icons["addvect"],
-                             label=_("Add vector map layer (Ctrl+V)")),
-    "vectmisc" : MetaIcon (img=Icons["vectmisc"],
-                             label=_("Add various vector map layers (thematic, chart...)")),
-    "addcmd"     : MetaIcon (img=Icons["addcmd"],
-                             label=_("Add command layer")),
-    "addgrp"     : MetaIcon (img=Icons["addgrp"],
-                             label=_("Add group")),
-    "addovl"     : MetaIcon (img=Icons["addovl"],
-                             label=_("Add grid or vector labels overlay")),
-    "delcmd"     : MetaIcon (img=Icons["delcmd"],
-                             label=_("Delete selected map layer")),
-    "quit"       : MetaIcon (img=Icons["quit"],
-                             label=_("Quit")),
-    "attrtable"  : MetaIcon (img=Icons["attrtable"],
-                             label=_("Show attribute table")),
-    "addrgb"     : MetaIcon (img=Icons["addrgb"],
-                             label=_("Add RGB map layer")),
-    "addhis"     : MetaIcon (img=Icons["addhis"],
-                             label=_("Add HIS map layer")),
-    "addshaded"  : MetaIcon (img=Icons["addshaded"],
-                             label=_("Add shaded relief map layer")),
-    "addrarrow"  : MetaIcon (img=Icons["addrarrow"],
-                             label=_("Add raster flow arrows")),
-    "addrnum"    : MetaIcon (img=Icons["addrnum"],
-                             label=_("Add raster cell numbers")),
-    "addthematic": MetaIcon (img=Icons["addthematic"],
-                             label=_("Add thematic layer")),
-    "addchart"   : MetaIcon (img=Icons["addchart"],
-                             label=_("Add thematic chart layer")),
-    "addgrid"    : MetaIcon (img=Icons["addgrid"],
-                             label=_("Add grid layer")),
-    "addgeodesic": MetaIcon (img=Icons["addgeodesic"],
-                             label=_("Add geodesic line layer")),
-    "addrhumb"   : MetaIcon (img=Icons["addrhumb"],
-                             label=_("Add rhumbline layer")),
-    "addlabels"  : MetaIcon (img=Icons["addlabels"],
-                             label=_("Add labels")),
-    "addtext"    : MetaIcon (img=Icons["addtext"],
-                             label=_("Add text layer")),
-    "addrast3d"  : MetaIcon (img=Icons["addrast3d"],
-                             label=_("Add 3D raster map layer"),
-                             desc = _("Note that 3D raster data are rendered only in 3D view mode")),
-    "settings"   : MetaIcon (img=Icons["settings"],
-                             label=_("Show GUI settings")),
-    # digit
-    "digAddPoint": MetaIcon (img=Icons["digAddPoint"],
-                             label=_("Digitize new point"),
-                             desc=_("Left: new point")),
-    "digAddLine" : MetaIcon (img=Icons["digAddLine"],
-                             label=_("Digitize new line"),
-                             desc=_("Left: new point; Middle: undo last point; Right: close line")),
-    "digAddBoundary": MetaIcon (img=Icons["digAddBoundary"],
-                                label=_("Digitize new boundary"),
-                                desc=_("Left: new point; Middle: undo last point; Right: close line")),
-    "digAddCentroid": MetaIcon (img=Icons["digAddCentroid"],
-                                label=_("Digitize new centroid"),
-                             desc=_("Left: new point")),
-    "digAddVertex": MetaIcon (img=Icons["digAddVertex"],
-                              label=_("Add new vertex"),
-                              desc=_("Left: Select; Middle: Unselect; Right: Confirm")),
-    "digCopyCats": MetaIcon (img=Icons["digCopyCats"],
-                             label=_("Copy categories"),
-                             desc=_("Left: Select; Middle: Unselect; Right: Confirm")),
-    "digDeleteLine": MetaIcon (img=Icons["digDeleteLine"],
-                               label=_("Delete feature(s)"),
-                               desc=_("Left: Select; Middle: Unselect; Right: Confirm")),
-    "digDispAttr": MetaIcon (img=Icons["digDispAttr"],
-                             label=_("Display/update attributes"),
-                             desc=_("Left: Select")),
-    "digDispCats": MetaIcon (img=Icons["digDispCats"],
-                             label=_("Display/update categories"),
-                             desc=_("Left: Select")),
-    "digEditLine": MetaIcon (img=Icons["digEditLine"],
-                             label=_("Edit line/boundary"),
-                             desc=_("Left: new point; Middle: undo last point; Right: close line")),
-    "digMoveLine": MetaIcon (img=Icons["digMoveLine"],
-                             label=_("Move feature(s)"),
-                             desc=_("Left: Select; Middle: Unselect; Right: Confirm")),
-    "digMoveVertex": MetaIcon (img=Icons["digMoveVertex"],
-                               label=_("Move vertex"),
-                               desc=_("Left: Select; Middle: Unselect; Right: Confirm")),
-    "digRemoveVertex": MetaIcon (img=Icons["digRemoveVertex"],
-                                 label=_("Remove vertex"),
-                                 desc=_("Left: Select; Middle: Unselect; Right: Confirm")),
-    "digSettings": MetaIcon (img=Icons["settings"],
-                             label=_("Settings"),
-                             desc=_("Settings dialog for digitization tool")),
-    "digSplitLine": MetaIcon (img=Icons["digSplitLine"],
-                              label=_("Split line/boundary"),
-                              desc=_("Left: Select; Middle: Unselect; Right: Confirm")),
-    "digExit"    : MetaIcon (img=Icons["quit"],
-                             label=_("Quit digitizing tool")),
-    "digAdditionalTools" : MetaIcon (img=Icons["digAdditionalTools"],
-                                     label=_("Additional tools " \
-                                                 "(copy, flip, connect, etc.)"),
-                                     desc=_("Left: Select; Middle: Unselect; Right: Confirm")),
-    "digUndo" : MetaIcon (img=Icons["digUndo"],
-                          label=_("Undo"),
-                          desc=_("Undo previous changes")),
-    # analyze raster
-    "analyze"    : MetaIcon (img=Icons["analyze"],
-                             label=_("Analyze map")),
-    "measure"    : MetaIcon (img=Icons["measure"],
-                             label=_("Measure distance")),
-    "transect"   : MetaIcon (img=Icons["transect"],
-                             label=_("Draw transect in map display window to profile")),
-    "profile"    : MetaIcon (img=Icons["profile"],
-                             label=_("Profile surface map")),
-    "profiledraw": MetaIcon (img=Icons["profiledraw"],
-                             label=_("Draw/re-draw profile")),
-    "profileopt" : MetaIcon (img=Icons["settings"],
-                             label=_("Profile options")),
-    "datasave"   : MetaIcon (img=Icons["fileSave"],
-                             label=_("Save profile data to csv file")),
-    "histogram"  : MetaIcon (img=Icons["histogram"],
-                             label=_("Create histogram of image or raster file")),
-    "font"       : MetaIcon (img=Icons["font"],
-                             label=_("Select font")),
-    "color"      : MetaIcon (img=Icons["color"],
-                             label=_("Select color")),
-    "layeropts"  : MetaIcon (img=Icons["layeropts"],
-                             label=_("Set options")),
-    "analyze"    : MetaIcon (img=Icons["analyze"],
-                             label=_("Analyze")),
-    # georectify
-    'grGcpSet'     : MetaIcon (img=Icons["grGcpSet"],
-                             label=_("Set GCP"),
-                             desc=_("Define GCP (Ground Control Points)")),
-    'grGeorect'    : MetaIcon (img=Icons["grGeorect"],
-                             label=_("Georectify")),
-    'grGcpRms'        : MetaIcon (img=Icons["grGcpRms"],
-                                  label=_("Recalculate RMS error")),
-    'grGcpSave' : MetaIcon (img=Icons["grGcpSave"],
-                            label=_("Save GCPs to POINTS file")),
-    'grGcpAdd' : MetaIcon (img=Icons["grGcpAdd"],
-                           label=_("Add new GCP")),
-    'grGcpDelete' : MetaIcon (img=Icons["grGcpDelete"],
-                              label=_("Delete selected GCP")),
-    'grGcpClear' : MetaIcon (img=Icons["grGcpClear"],
-                             label=_("Clear selected GCP")),
-    'grGcpReload' : MetaIcon (img=Icons["grGcpReload"],
-                              label=_("Reload GCPs from POINTS file")),
-    'grGcpQuit' : MetaIcon (img=Icons["quit"],
-                            label=_("Quit georectification module")),
-    "grSettings": MetaIcon (img=Icons["settings"],
-                            label=_("Settings"),
-                            desc=_("Settings dialog for georectification tool")),
-    # nviz
-    "nvizView": MetaIcon (img=Icons["nvizView"],
-                          label=_("Switch to view control page"),
-                          desc=_("Change view settings")),
-    "nvizSurface": MetaIcon (img=Icons["nvizSurface"],
-                             label=_("Switch to surface (raster) control page"),
-                             desc=_("Change surface (loaded raster maps) settings")),
-    "nvizVector": MetaIcon (img=Icons["nvizVector"],
-                            label=_("Switch to vector (2D/3D) control page"),
-                            desc=_("Change 2D/3D vector settings")),
-    "nvizVolume": MetaIcon (img=Icons["nvizVolume"],
-                            label=_("Switch to volume (3D raster) control page"),
-                            desc=_("Change volume (loaded 3D raster maps) settings")),
-    "nvizLight": MetaIcon (img=Icons["nvizLight"],
-                           label=_("Switch to lighting control page"),
-                           desc=_("Change lighting settings")),
-    "nvizFringe": MetaIcon (img=Icons["nvizFringe"],
-                            label=_("Switch to fringe control page"),
-                            desc=_("Switch on/off fringes")),
-    "nvizSettings": MetaIcon (img=Icons["settings"],
-                              label=_("3D view mode tools"),
-                              desc=_("Show/hide 3D view mode settings dialog")),
-    "nvizHelp"   : MetaIcon (img=Icons["help"],
-                             label=_("Show help"),
-                             desc = _("Display 3D view mode manual page")),
-    "nvizQuit": MetaIcon (img=Icons["quit"],
-                          label=_("Quit 3D view mode"),
-                          desc=_("Switch back to 2D view mode")),
-    # modeler
-    "modeler" : MetaIcon (img=Icons["modeler"],
-                          label=_("Start Graphical Modeler")),
-    "modelNew" : MetaIcon (img=Icons["fileNew"],
-                           label=_("Create new model (Ctrl+N)")),
-    "modelOpen" : MetaIcon (img=Icons["fileOpen"],
-                                label=_("Load model from file (Ctrl+O)")),
-    "modelSave" : MetaIcon (img=Icons["fileSave"],
-                                label=_("Save current model to file (Ctrl+S)")),
-    "modelToImage" : MetaIcon (img=Icons["imageSave"],
-                                label=_("Export model to image")),
-    "modelToPython" : MetaIcon (img=Icons["pythonSave"],
-                                label=_("Export model to Python script")),
-    "modelActionAdd" : MetaIcon (img=Icons["modelActionAdd"],
-                                 label=_("Add action (GRASS module) to model")),
-    "modelDataAdd" : MetaIcon (img=Icons["modelDataAdd"],
-                                 label=_("Add data item to model")),
-    "modelRelation" : MetaIcon (img=Icons["modelRelation"],
-                                label=_("Define relation between data and action items")),
-    "modelRun" : MetaIcon (img=Icons["modelRun"],
-                           label=_("Run model")),
-    "modelValidate" : MetaIcon (img=Icons["modelValidate"],
-                                label=_("Validate model")),
-    "modelSettings" : MetaIcon (img=Icons["settings"],
-                                label=_("Show modeler settings")),
-    "modelProperties" : MetaIcon (img=Icons["modelProperties"],
-                                  label=_("Show model properties")),
-    "modelVariables" : MetaIcon (img=Icons["modelVariables"],
-                                 label=_("Manage model variables")),
-    "modelRedraw" : MetaIcon (img=Icons["redraw"],
-                              label=_("Redraw model canvas")),
-    "modelHelp"   : MetaIcon (img=Icons["help"],
-                             label=_("Show help"),
-                             desc = _("Display Graphical Modeler manual page")),
+    'displayWindow' : {
+        'display'    : MetaIcon(img = iconSet.get('show', wx.ART_ERROR),
+                                label = _('Display map'),
+                                desc  =  _('Re-render modified map layers only')),
+        'render'     : MetaIcon(img = iconSet.get('layer-redraw', wx.ART_ERROR),
+                                label = _('Render map'),
+                                desc = _('Force re-rendering all map layers')),
+        'erase'      : MetaIcon(img = iconSet.get('erase', wx.ART_ERROR),
+                                label = _('Erase display'),
+                                desc = _('Erase display canvas with given background color')),
+        'pointer'    : MetaIcon(img = iconSet.get('pointer', wx.ART_ERROR),
+                                label = _('Pointer')),
+        'zoomIn'     : MetaIcon(img = iconSet.get('zoom-in', wx.ART_ERROR),
+                                label = _('Zoom in'),
+                                desc = _('Drag or click mouse to zoom')),
+        'zoomOut'    : MetaIcon(img = iconSet.get('zoom-out', wx.ART_ERROR),
+                                label = _('Zoom out'),
+                                desc = _('Drag or click mouse to unzoom')),
+        'pan'        : MetaIcon(img = iconSet.get('pan', wx.ART_ERROR),
+                                label = _('Pan'),
+                                desc = _('Drag with mouse to pan')),
+        'query'      : MetaIcon(img = iconSet.get('info', wx.ART_ERROR),
+                                label = _('Query raster/vector map(s)'),
+                                desc = _('Query selected raster/vector map(s)')),
+        'zoomBack'   : MetaIcon(img = iconSet.get('zoom-last', wx.ART_ERROR),
+                                label = _('Return to previous zoom')),
+        'zoomMenu'   : MetaIcon(img = iconSet.get('zoom-more', wx.ART_ERROR),
+                                label = _('Various zoom options'),
+                                desc = _('Zoom to computational, default, saved region, ...')),
+        'zoomExtent' : MetaIcon(img = iconSet.get('zoom-extent', wx.ART_ERROR),
+                                label = _('Zoom to selected map layer(s)')),
+        'overlay'    : MetaIcon(img = iconSet.get('overlay-add', wx.ART_ERROR),
+                                label = _('Add map elements'),
+                                desc = _('Overlay elements like scale and legend onto map')),
+        'addBarscale': MetaIcon(img = iconSet.get('scalebar-add', wx.ART_ERROR),
+                                label = _('Add scalebar and north arrow')),
+        'addLegend'  : MetaIcon(img = iconSet.get('legend-add', wx.ART_ERROR),
+                                label = _('Add legend')),
+        'saveFile'   : MetaIcon(img = iconSet.get('map-export', wx.ART_ERROR),
+                                label = _('Save display to graphic file')),
+        'print'      : MetaIcon(img = iconSet.get('print', wx.ART_ERROR),
+                                label = _('Print display')),
+        'analyze'    : MetaIcon(img = iconSet.get('layer-raster-analyze', wx.ART_ERROR),
+                                label = _('Analyze map'),
+                                desc = _('Measuring, profiling, histogramming, ...')),
+        'measure'    : MetaIcon(img = iconSet.get('measure-length', wx.ART_ERROR),
+                                label = _('Measure distance')),
+        'profile'    : MetaIcon(img = iconSet.get('layer-raster-profile', wx.ART_ERROR),
+                                label = _('Profile surface map')),
+        'addText'    : MetaIcon(img = iconSet.get('text-add', wx.ART_ERROR),
+                                label = _('Add text layer')),
+        'histogram'  : MetaIcon(img = iconSet.get('layer-raster-histogram', wx.ART_ERROR),
+                                label = _('Create histogram of image or raster file')),
+        },
+    'layerManager' : {
+        'newdisplay'   : MetaIcon(img = iconSet.get('monitor-create', wx.ART_ERROR),
+                                  label = _('Start new map display')),
+        'workspaceNew'  : MetaIcon(img = iconSet.get('create', wx.ART_ERROR),
+                                   label = _('Create new workspace (Ctrl+N)')),
+        'workspaceLoad' : MetaIcon(img = iconSet.get('layer-open', wx.ART_ERROR),
+                                   label = _('Load map layers into workspace (Ctrl+L)')),
+        'workspaceOpen' : MetaIcon(img = iconSet.get('open', wx.ART_ERROR),
+                                   label = _('Open existing workspace file (Ctrl+O)')),
+        'workspaceSave' : MetaIcon(img = iconSet.get('save', wx.ART_ERROR),
+                                   label = _('Save current workspace to file (Ctrl+S)')),
+        'rastImport' : MetaIcon(img = iconSet.get('layer-import', wx.ART_ERROR),
+                                label = _('Import raster data')),
+        'rastLink'   : MetaIcon(img = iconSet.get('layer-import', wx.ART_ERROR),
+                                label = _('Link external raster data')),
+        'vectImport' : MetaIcon(img = iconSet.get('layer-import', wx.ART_ERROR),
+                                label = _('Import vector data')),
+        'vectLink'   : MetaIcon(img = iconSet.get('layer-import', wx.ART_ERROR),
+                                label = _('Link external vector data')),
+        'addRast'    : MetaIcon(img = iconSet.get('layer-raster-add', wx.ART_ERROR),
+                                label = _('Add raster map layer (Ctrl+R)')),
+        'rastMisc'   : MetaIcon(img = iconSet.get('layer-raster-more', wx.ART_ERROR),
+                                label = _('Add various raster map layers (RGB, HIS, shaded relief...)')),
+        'addVect'    : MetaIcon(img = iconSet.get('layer-vector-add', wx.ART_ERROR),
+                                label = _('Add vector map layer (Ctrl+V)')),
+        'vectMisc'   : MetaIcon(img = iconSet.get('layer-vector-more', wx.ART_ERROR),
+                                label = _('Add various vector map layers (thematic, chart...)')),
+        'addCmd'     : MetaIcon(img = iconSet.get('layer-command-add', wx.ART_ERROR),
+                                label = _('Add command layer')),
+        'addGroup'   : MetaIcon(img = iconSet.get('layer-group-add', wx.ART_ERROR),
+                                label = _('Add group')),
+        'addOverlay' : MetaIcon(img = iconSet.get('layer-more', wx.ART_ERROR),
+                                label = _('Add grid or vector labels overlay')),
+        'delCmd'     : MetaIcon(img = iconSet.get('layer-remove', wx.ART_ERROR),
+                                label = _('Delete selected map layer')),
+        'quit'       : MetaIcon(img = iconSet.get('quit', wx.ART_ERROR),
+                                label = _('Quit')),
+        'attrTable'  : MetaIcon(img = iconSet.get('table', wx.ART_ERROR),
+                                label = _('Show attribute table')),
+        'vdigit'     : MetaIcon(img = iconSet.get('edit', wx.ART_ERROR),
+                                label = _('Edit vector maps')),
+        'addRgb'     : MetaIcon(img = iconSet.get('layer-rgb-add', wx.ART_ERROR),
+                                label = _('Add RGB map layer')),
+        'addHis'     : MetaIcon(img = iconSet.get('layer-his-add', wx.ART_ERROR),
+                                label = _('Add HIS map layer')),
+        'addShaded'  : MetaIcon(img = iconSet.get('layer-shaded-relief-add', wx.ART_ERROR),
+                                label = _('Add shaded relief map layer')),
+        'addRArrow'  : MetaIcon(img = iconSet.get('layer-aspect-arrow-add', wx.ART_ERROR),
+                                label = _('Add raster flow arrows')),
+        'addRNum'    : MetaIcon(img = iconSet.get('layer-cell-cats-add', wx.ART_ERROR),
+                                label = _('Add raster cell numbers')),
+        'addThematic': MetaIcon(img = iconSet.get('layer-vector-thematic-add', wx.ART_ERROR),
+                                label = _('Add thematic area (choropleth) map layer')),
+        'addChart'   : MetaIcon(img = iconSet.get('layer-vector-chart-add', wx.ART_ERROR),
+                                label = _('Add thematic chart layer')),
+        'addGrid'    : MetaIcon(img = iconSet.get('layer-grid-add', wx.ART_ERROR),
+                                label = _('Add grid layer')),
+        'addGeodesic': MetaIcon(img = iconSet.get('shortest-distance', wx.ART_ERROR),
+                                label = _('Add geodesic line layer')),
+        'addRhumb'   : MetaIcon(img = iconSet.get('shortest-distance', wx.ART_ERROR),
+                                label = _('Add rhumbline layer')),
+        'addLabels'  : MetaIcon(img = iconSet.get('layer-label-add', wx.ART_ERROR),
+                                label = _('Add labels')),
+        'addRast3d'  : MetaIcon(img = iconSet.get('layer-raster3d-add', wx.ART_ERROR),
+                                label = _('Add 3D raster map layer'),
+                                desc  =  _('Note that 3D raster data are rendered only in 3D view mode')),
+        'settings'   : MetaIcon(img = iconSet.get('settings', wx.ART_ERROR),
+                                label = _('Show GUI settings')),
+        'modeler'    : MetaIcon(img = iconSet.get('modeler-main', wx.ART_ERROR),
+                                label = _('Start Graphical Modeler')),
+        "layerOptions"  : MetaIcon(img = iconSet.get('options', wx.ART_ERROR),
+                                   label = _('Set options')),
+        },
+    'vdigit' : {
+        'addPoint'        : MetaIcon(img = iconSet.get('point-create', wx.ART_ERROR),
+                                     label = _('Digitize new point'),
+                                     desc = _('Left: new point')),
+        'addLine'         : MetaIcon(img = iconSet.get('line-create', wx.ART_ERROR),
+                                     label = _('Digitize new line'),
+                                     desc = _('Left: new point; Ctrl+Left: undo last point; Right: close line')),
+        'addBoundary'     : MetaIcon(img = iconSet.get('boundary-create', wx.ART_ERROR),
+                                     label = _('Digitize new boundary'),
+                                     desc = _('Left: new point; Ctrl+Left: undo last point; Right: close line')),
+        'addCentroid'     : MetaIcon(img = iconSet.get('centroid-create', wx.ART_ERROR),
+                                     label = _('Digitize new centroid'),
+                                     desc = _('Left: new point')),
+        'addArea'         : MetaIcon(img = iconSet.get('polygon-create', wx.ART_ERROR),
+                                     label = _('Digitize new area (composition of bondaries without category and one centroid with category)'),
+                                     desc = _('Left: new point')),
+        'addVertex'       : MetaIcon(img = iconSet.get('vertex-create', wx.ART_ERROR),
+                                     label = _('Add new vertex'),
+                                     desc = _('Left: Select; Ctrl+Left: Unselect; Right: Confirm')),
+        'copyCats'        : MetaIcon(img = iconSet.get('cats-copy', wx.ART_ERROR),
+                                     label = _('Copy categories'),
+                                     desc = _('Left: Select; Ctrl+Left: Unselect; Right: Confirm')),
+        'deleteLine'      : MetaIcon(img = iconSet.get('line-delete', wx.ART_ERROR),
+                                     label = _('Delete feature(s)'),
+                                     desc = _('Left: Select; Ctrl+Left: Unselect; Right: Confirm')),
+        'displayAttr'     : MetaIcon(img = iconSet.get('attributes-display', wx.ART_ERROR),
+                                     label = _('Display/update attributes'),
+                                     desc = _('Left: Select')),
+        'displayCats'     : MetaIcon(img = iconSet.get('cats-display', wx.ART_ERROR),
+                                     label = _('Display/update categories'),
+                                     desc = _('Left: Select')),
+        'editLine'        : MetaIcon(img = iconSet.get('line-edit', wx.ART_ERROR),
+                                     label = _('Edit line/boundary'),
+                                     desc = _('Left: new point; Ctrl+Left: undo last point; Right: close line')),
+        'moveLine'        : MetaIcon(img = iconSet.get('line-move', wx.ART_ERROR),
+                                     label = _('Move feature(s)'),
+                                     desc = _('Left: Select; Ctrl+Left: Unselect; Right: Confirm')),
+        'moveVertex'      : MetaIcon(img = iconSet.get('vertex-move', wx.ART_ERROR),
+                                     label = _('Move vertex'),
+                                     desc = _('Left: Select; Ctrl+Left: Unselect; Right: Confirm')),
+        'removeVertex'    : MetaIcon(img = iconSet.get('vertex-delete', wx.ART_ERROR),
+                                     label = _('Remove vertex'),
+                                     desc = _('Left: Select; Ctrl+Left: Unselect; Right: Confirm')),
+        'settings'        : MetaIcon(img = iconSet.get('settings', wx.ART_ERROR),
+                                     label = _('Digitization settings')),
+        'splitLine'       : MetaIcon(img = iconSet.get('line-split', wx.ART_ERROR),
+                                     label = _('Split line/boundary'),
+                                     desc = _('Left: Select; Ctrl+Left: Unselect; Right: Confirm')),
+        'quit'            : MetaIcon(img = iconSet.get('quit', wx.ART_ERROR),
+                                     label = _('Quit digitizer'),
+                                     desc = _('Quit digitizer and save changes')),
+        'additionalTools' : MetaIcon(img = iconSet.get('tools', wx.ART_ERROR),
+                                     label = _('Additional tools ' \
+                                                   '(copy, flip, connect, etc.)'),
+                                     desc = _('Left: Select; Ctrl+Left: Unselect; Right: Confirm')),
+        'undo'             : MetaIcon(img = iconSet.get('undo', wx.ART_ERROR),
+                                      label = _('Undo'),
+                                      desc = _('Undo previous changes')),
+        },
+    'profile' : {
+        'draw'         : MetaIcon(img = iconSet.get('show', wx.ART_ERROR),
+                                  label = _('Draw/re-draw profile')),
+        'transect'     : MetaIcon(img = iconSet.get('layer-raster-profile', wx.ART_ERROR),
+                                  label = _('Draw transect in map display window to profile')),
+        'options'      : MetaIcon(img = iconSet.get('settings', wx.ART_ERROR),
+                                  label = _('Profile options')),
+        'save'         : MetaIcon(img = iconSet.get('save', wx.ART_ERROR),
+                                  label = _('Save profile data to CSV file')),
+        'quit'         : MetaIcon(img = iconSet.get('quit', wx.ART_ERROR),
+                                  label = _('Quit Profile Analysis Tool'))
+        },
+    'georectify' : {
+        'gcpSet'    : MetaIcon(img = iconSet.get('gcp-create', wx.ART_ERROR),
+                               label = _('Set GCP'),
+                               desc = _('Define GCP (Ground Control Points)')),
+        'georectify': MetaIcon(img = iconSet.get('georectify', wx.ART_ERROR),
+                               label = _('Georectify')),
+        'gcpRms'    : MetaIcon(img = iconSet.get('gcp-rms', wx.ART_ERROR),
+                               label = _('Recalculate RMS error')),
+        'gcpSave'   : MetaIcon(img = iconSet.get('gcp-save', wx.ART_ERROR),
+                               label = _('Save GCPs to POINTS file')),
+        'gcpAdd'    : MetaIcon(img = iconSet.get('gcp-add', wx.ART_ERROR),
+                               label = _('Add new GCP')),
+        'gcpDelete' : MetaIcon(img = iconSet.get('gcp-delete', wx.ART_ERROR),
+                               label = _('Delete selected GCP')),
+        'gcpClear'  : MetaIcon(img = iconSet.get('gcp-remove', wx.ART_ERROR),
+                                label = _('Clear selected GCP')),
+        'gcpReload' : MetaIcon(img = iconSet.get('reload', wx.ART_ERROR),
+                               label = _('Reload GCPs from POINTS file')),
+        'quit'      : MetaIcon(img = iconSet.get('quit', wx.ART_ERROR),
+                               label = _('Quit georectification')),
+        'settings'  : MetaIcon(img = iconSet.get('settings', wx.ART_ERROR),
+                               label = _('Settings'),
+                               desc = _('Settings dialog for georectification tool')),
+        },
+    'nviz' : {
+        'view'    : MetaIcon(img = iconSet.get('3d-view', wx.ART_ERROR),
+                             label = _('Switch to view control page'),
+                             desc = _('Change view settings')),
+        'surface' : MetaIcon(img = iconSet.get('3d-raster', wx.ART_ERROR),
+                             label = _('Switch to surface (raster) control page'),
+                             desc = _('Change surface (loaded raster maps) settings')),
+        'vector'  : MetaIcon(img = iconSet.get('3d-vector', wx.ART_ERROR),
+                             label = _('Switch to vector (2D/3D) control page'),
+                             desc = _('Change 2D/3D vector settings')),
+        'volume'  : MetaIcon(img = iconSet.get('3d-volume', wx.ART_ERROR),
+                             label = _('Switch to volume (3D raster) control page'),
+                             desc = _('Change volume (loaded 3D raster maps) settings')),
+        'light'   : MetaIcon(img = iconSet.get('3d-light', wx.ART_ERROR),
+                             label = _('Switch to lighting control page'),
+                             desc = _('Change lighting settings')),
+        'fringe'  : MetaIcon(img = iconSet.get('3d-fringe', wx.ART_ERROR),
+                             label = _('Switch to fringe control page'),
+                             desc = _('Switch on/off fringes')),
+        'settings': MetaIcon(img = iconSet.get('settings', wx.ART_ERROR),
+                             label = _('3D view mode tools'),
+                             desc = _('Show/hide 3D view mode settings dialog')),
+        'quit'    : MetaIcon(img = iconSet.get('quit', wx.ART_ERROR),
+                             label = _('Quit 3D view mode'),
+                             desc = _('Switch back to 2D view mode')),
+        },
+    'modeler' : {
+        'new'        : MetaIcon(img = iconSet.get('create', wx.ART_ERROR),
+                                label = _('Create new model (Ctrl+N)')),
+        'open'       : MetaIcon(img = iconSet.get('open', wx.ART_ERROR),
+                                label = _('Load model from file (Ctrl+O)')),
+        'save'       : MetaIcon(img = iconSet.get('save', wx.ART_ERROR),
+                                label = _('Save current model to file (Ctrl+S)')),
+        'toImage'    : MetaIcon(img = iconSet.get('image-export', wx.ART_ERROR),
+                                label = _('Export model to image')),
+        'toPython'   : MetaIcon(img = iconSet.get('python-export', wx.ART_ERROR),
+                                label = _('Export model to Python script')),
+        'actionAdd'  : MetaIcon(img = iconSet.get('module-add', wx.ART_ERROR),
+                                label = _('Add action (GRASS module) to model')),
+        'dataAdd'    : MetaIcon(img = iconSet.get('data-add', wx.ART_ERROR),
+                                label = _('Add data item to model')),
+        'relation'   : MetaIcon(img = iconSet.get('relation-create', wx.ART_ERROR),
+                                label = _('Define relation between data and action items')),
+        'run'        : MetaIcon(img = iconSet.get('execute', wx.ART_ERROR),
+                                label = _('Run model')),
+        'validate'   : MetaIcon(img = iconSet.get('check', wx.ART_ERROR),
+                                label = _('Validate model')),
+        'settings'   : MetaIcon(img = iconSet.get('settings', wx.ART_ERROR),
+                                label = _('Show modeler settings')),
+        'properties' : MetaIcon(img = iconSet.get('options', wx.ART_ERROR),
+                                label = _('Show model properties')),
+        'variables'  : MetaIcon(img = iconSet.get('modeler-variables', wx.ART_ERROR),
+                                label = _('Manage model variables')),
+        'redraw'     : MetaIcon(img = iconSet.get('redraw', wx.ART_ERROR),
+                                label = _('Redraw model canvas')),
+        'quit'    : MetaIcon(img = iconSet.get('quit', wx.ART_ERROR),
+                             label = _('Quit Graphical Modeler')),
+        },
+    'misc' : {
+        'font' : MetaIcon(img = iconSet.get('font', wx.ART_ERROR),
+                          label = _('Select font')),
+        'help' : MetaIcon(img = iconSet.get('help', wx.ART_ERROR),
+                          label = _('Show help page')),
+        'quit' : MetaIcon(img = iconSet.get('quit', wx.ART_ERROR),
+                          label = _('Quit')),
+        }
     }
 
 # testing ...
-if __name__ == "__main__":
-    for k, v in Icons.iteritems():
+if __name__ == '__main__':
+    for k, v in iconSet.iteritems():
         print v.GetImageName()

Modified: grass/branches/releasebranch_6_4/gui/wxpython/icons/silk_icons.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/icons/silk_icons.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/icons/silk_icons.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -12,119 +12,85 @@
 
 import globalvar
 
-iconpath = os.path.join(globalvar.ETCDIR, "gui", "icons", "silk")
+iconPath = os.path.join(globalvar.ETCDIR, "gui", "icons", "silk")
 
-IconsSilk = {
-    # map display
-    "displaymap" : 'map_go.png',
-    "rendermap"  : 'arrow_refresh.png',
+iconSet = {
+    "show" : 'map_go.png',
+    "layer-redraw"  : 'arrow_refresh.png',
     "erase"      : 'cross.png',
     "pointer"    : 'cursor.png',
-    "query"      : 'information.png',
-    "savefile"   : 'picture_save.png',
-    "printmap"   : 'printer.png',
+    "info"      : 'information.png',
+    "map-export"   : 'picture_save.png',
+    "print"   : 'printer.png',
     "pan"        : 'arrow_out.png', 
-    # zoom (mapdisplay)
-    "zoom_in"    : 'zoom_in.png',
-    "zoom_out"   : 'zoom_out.png',
-    "zoom_back"  : 'zoom_back.png',
-    "zoommenu"   : 'zoom.png',
-    "zoom_extent" : 'zoom_extent.png',
-    # analyze raster (mapdisplay)
-    "analyze"    : 'application_lightning.png',
-    "measure"    : 'sum.png',
-    "profile"    : 'wand.png',
-    "histogram"  : 'chart_bar.png',
+    "zoom-in"    : 'zoom_in.png',
+    "zoom-out"   : 'zoom_out.png',
+    "zoom-last"  : 'zoom_back.png',
+    "zoom-more"   : 'zoom.png',
+    "zoom-extent" : 'zoom_extent.png',
+    "layer-raster-analyze"    : 'application_lightning.png',
+    "measure-length"    : 'sum.png',
+    "layer-raster-profile"    : 'wand.png',
+    "layer-raster-histogram"  : 'chart_bar.png',
     "font"       : 'font.png',
-    # overlay (mapdisplay)
-    "overlay"    : 'overlays.png',
-    "addtext"    : 'textfield_add.png',
-    "addbarscale": 'page_white_picture.png',
-    "addlegend"  : 'page_green.png',
+    "overlay-add"    : 'overlays.png',
+    "text-add"    : 'textfield_add.png',
+    "scalebar-add": 'page_white_picture.png',
+    "legend-add"  : 'page_green.png',
     "quit"       : 'door_in.png',
-    # digit
-    ## add feature
-    "digAddPoint": 'bullet_add.png',
-    "digAddLine" : 'vector_add.png',
-    "digAddBoundary": 'shape_handles.png',
-    "digAddCentroid": 'shape_square_add.png',
-    ## vertex
-    "digAddVertex" : 'chart_line_add.png',
-    "digMoveVertex" : 'chart_line.png',
-    "digRemoveVertex" : 'chart_line_delete.png',
-    "digSplitLine" : 'chart_line_link.png',
-    ## edit feature
-    "digEditLine" : 'chart_line_edit.png',
-    "digMoveLine" : 'bullet_go.png',
-    "digDeleteLine" : 'vector_delete.png',
-    ## cats
-    "digDispCats" : 'chart_organisation.png',
-    "digCopyCats" : 'chart_organisation_add.png',
-    ## attributes
-    "digDispAttr" : 'table.png',
-    ## general
-    "digUndo" : 'arrow_undo.png',
-    "digAdditionalTools" : 'plugin.png',
-    # layer manager
-    "newdisplay" : 'application_add.png',
-    "fileNew"    : 'page_white.png',
-    "fileLoad"   : 'page_white_get.png',
-    "fileOpen"   : 'folder.png',
-    "fileSave"   : 'page_save.png',
-    "fileImport" : 'page_white_get.png',
-    "addrast"    : 'image_add.png',
-    "rastmisc"   : 'picture_empty.png',
-    "addrast3d"  : 'bricks.png',
-    "addshaded"  : 'picture_empty.png',
-    "addrarrow"  : 'arrow_inout.png',
-    "addrnum"    : 'color_swatch.png',
-    "addvect"    : 'map_add.png',
-    "vectmisc"   : 'thematic.png',
-    "addcmd"     : 'cog_add.png',
-    "addgrp"     : 'folder_add.png',
-    "addovl"     : 'images.png',
-    "addgrid"    : 'application_view_icons.png',
-    "addlabels"  : 'tag_blue_add.png',
-    "delcmd"     : 'bin_closed.png',
-    "attrtable"  : 'application_view_columns.png',
-    "addrgb"     : 'rgb.png',
-    "addhis"     : 'his.png',
-    "addthematic": 'thematic.png',
-    "addchart"   : 'chart_bar.png',
-    "layeropts"  : 'map_edit.png',
-    "modeler"    : wx.ART_ERROR,
-    # profile analysis
-    "transect"   : 'image_edit.png',
-    "profiledraw"  : 'arrow_refresh.png',
-    "profileopt"   : 'color_swatch.png',
-    # georectify
-    "grGcpSet"     : 'bullet_add.png',
-    'grGcpClear'   : 'cross.png',
-    'grGeorect'    : 'application_lightning.png',
-    'grGcpRms'     : 'error.png',
-    "grGcpSave"    : 'picture_save.png',
-    "grGcpAdd"     : 'bullet_add.png', 
-    "grGcpDelete"  : 'bullet_delete.png',
-    "grGcpReload"  : 'arrow_refresh.png',
-    # modeler
-    "modelActionAdd" : wx.ART_ERROR,
-    "modelDataAdd"   : wx.ART_ERROR,
-    "modelRelation"  : wx.ART_ERROR,
-    "modelRun"       : wx.ART_ERROR,
-    "modelValidate"  : wx.ART_ERROR,
-    "imageSave"      : wx.ART_ERROR,
-    "pythonSave"     : wx.ART_ERROR,
-    "modelProperties" : wx.ART_ERROR,
-    "modelVariables" : wx.ART_ERROR,
-    # 3d view
-    "nvizView"       : wx.ART_ERROR,
-    "nvizSurface"    : wx.ART_ERROR,
-    "nvizVector"     : wx.ART_ERROR,
-    "nvizVolume"     : wx.ART_ERROR,
-    "nvizLight"      : wx.ART_ERROR,
-    "nvizFringe"     : wx.ART_ERROR,
-    # various
+    "point-create": 'bullet_add.png',
+    "line-create" : 'vector_add.png',
+    "boundary-create": 'shape_handles.png',
+    "centroid-create": 'shape_square_add.png',
+    "vertex-create" : 'chart_line_add.png',
+    "vertex-move" : 'chart_line.png',
+    "vertex-delete" : 'chart_line_delete.png',
+    "line-split" : 'chart_line_link.png',
+    "line-edit" : 'chart_line_edit.png',
+    "line-move" : 'bullet_go.png',
+    "line-delete" : 'vector_delete.png',
+    "cats-display" : 'chart_organisation.png',
+    "cats-copy" : 'chart_organisation_add.png',
+    "attributes-display" : 'table.png',
+    "undo" : 'arrow_undo.png',
+    "tools" : 'plugin.png',
+    "monitor-create" : 'application_add.png',
+    "create"    : 'page_white.png',
+    "layer-open"   : 'page_white_get.png',
+    "open"   : 'folder.png',
+    "save"   : 'page_save.png',
+    "layer-import" : 'page_white_get.png',
+    "layer-raster-add"    : 'image_add.png',
+    "layer-raster-more"   : 'picture_empty.png',
+    "layer-raster3d-add"  : 'bricks.png',
+    "layer-shaded-relief-add"  : 'picture_empty.png',
+    "layer-aspect-arrow-add"  : 'arrow_inout.png',
+    "layer-cell-cats-add"    : 'color_swatch.png',
+    "layer-vector-add"    : 'map_add.png',
+    "layer-vector-more"   : 'thematic.png',
+    "layer-command-add"     : 'cog_add.png',
+    "layer-group-add"     : 'folder_add.png',
+    "layer-more"     : 'images.png',
+    "layer-grid-add"    : 'application_view_icons.png',
+    "layer-label-add"  : 'tag_blue_add.png',
+    "layer-remove"     : 'bin_closed.png',
+    "table"  : 'application_view_columns.png',
+    "layer-rgb-add"     : 'rgb.png',
+    "layer-his-add"     : 'his.png',
+    "layer-vector-thematic-add": 'thematic.png',
+    "layer-vector-chart-add"   : 'chart_bar.png',
+    "options"  : 'map_edit.png',
+    "layer-raster-profile"   : 'image_edit.png',
+    "layer-raster-show"  : 'arrow_refresh.png',
+    "layer-raster-profileopt"   : 'color_swatch.png',
+    "gcp-create"     : 'bullet_add.png',
+    'gcp-remove'   : 'cross.png',
+    'georectify'    : 'application_lightning.png',
+    'gcp-rms'     : 'error.png',
+    "gcp-save"    : 'picture_save.png',
+    "gcp-add"     : 'bullet_add.png', 
+    "gcp-delete"  : 'bullet_delete.png',
+    "reload"  : 'arrow_refresh.png',
     "settings"       : 'color_swatch.png',
     "redraw"         : 'arrow_refresh.png',
-    "help"           : wx.ART_ERROR,
     }

Modified: grass/branches/releasebranch_6_4/gui/wxpython/scripts/Makefile
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/scripts/Makefile	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/scripts/Makefile	2011-04-13 09:30:47 UTC (rev 45931)
@@ -5,7 +5,7 @@
 
 SCRIPTDIR = $(ETC)/wxpython/scripts
 
-ifdef MINGW
+ifeq ($(MSYSTEM),MINGW32)
 PYFILES := $(patsubst %.py, $(SCRIPTDIR)/%.py, $(filter %.py, $(PY_SOURCES)))
 else
 PYFILES := $(patsubst %.py, $(SCRIPTDIR)/%, $(filter %.py, $(PY_SOURCES)))

Modified: grass/branches/releasebranch_6_4/gui/wxpython/support/update_menudata.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/support/update_menudata.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/support/update_menudata.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -77,14 +77,14 @@
         for child in node.getchildren():
             item[child.tag] = child.text
         
-        if not item.has_key('command'):
+        if 'command' not in item:
             continue
         
         if item['command'] in ignore:
             continue
         
         module = item['command'].split(' ')[0]
-        if not modules.has_key(module):
+        if module not in modules:
             grass.warning("'%s' not found in modules" % item['command'])
             continue
         
@@ -95,7 +95,7 @@
         if node.find('handler').text == 'OnMenuCmd':
             node.find('help').text = desc
         
-        if not modules[module].has_key('keywords'):
+        if 'keywords' not in modules[module]:
             grass.warning('%s: keywords missing' % module)
         else:
             if node.find('keywords') is None:

Modified: grass/branches/releasebranch_6_4/gui/wxpython/wxgui.py
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/wxgui.py	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/wxgui.py	2011-04-13 09:30:47 UTC (rev 45931)
@@ -9,7 +9,7 @@
  - GMFrame
  - GMApp
 
-(C) 2006-2010 by the GRASS Development Team
+(C) 2006-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.
@@ -57,6 +57,11 @@
     import wx.lib.customtreectrl as CT
     import wx.lib.flatnotebook   as FN
 
+try:
+    import wx.lib.agw.advancedsplash as SC
+except ImportError:
+    SC = None
+
 sys.path.append(os.path.join(globalvar.ETCDIR, "python"))
 from grass.script import core as grass
 
@@ -84,6 +89,7 @@
 from   gui_modules.debug import Debug
 from   gui_modules.ghelp import MenuTreeWindow
 from   gui_modules.ghelp import AboutWindow
+from   gui_modules.ghelp import InstallExtensionWindow
 from   gui_modules.toolbars import LayerManagerToolbar
 from   icons.icon import Icons
 
@@ -113,8 +119,8 @@
 
         # initialize variables
         self.disp_idx      = 0            # index value for map displays and layer trees
-        self.curr_page     = ''           # currently selected page for layer tree notebook
-        self.curr_pagenum  = ''           # currently selected page number for layer tree notebook
+        self.curr_page     = None         # currently selected page for layer tree notebook
+        self.curr_pagenum  = None         # currently selected page number for layer tree notebook
         self.workspaceFile = workspace    # workspace file
         self.workspaceChanged = False     # track changes in workspace
         self.georectifying = None         # reference to GCP class or None
@@ -259,6 +265,22 @@
         
         win.Show()
         
+    def OnPsMap(self, event):
+        """!Launch Hardcopy Map Output Utility
+        """
+        try:
+            import psmap
+        except:
+            gcmd.GError(parent = self.parent,
+                        message = _("Hardcopy Map Output Utility is not available. You can install it by "
+                                    "'g.extension -s svnurl=https://svn.osgeo.org/grass/grass-addons extension=psmap'"))
+            return
+        
+        win = psmap.PsMapFrame(parent = self)
+        win.CentreOnScreen()
+        
+        win.Show()
+        
     def OnDone(self, returncode):
         """Command execution finised"""
         if hasattr(self, "model"):
@@ -417,18 +439,57 @@
         
         return cmdlist
 
-    def RunMenuCmd(self, event, cmd = ''):
+    def RunMenuCmd(self, event = None, cmd = []):
         """!Run command selected from menu"""
         if event:
             cmd = self.GetMenuCmd(event)
         self.goutput.RunCmd(cmd, switchPage = False)
 
-    def OnMenuCmd(self, event, cmd = ''):
+    def OnMenuCmd(self, event = None, cmd = []):
         """!Parse command selected from menu"""
         if event:
             cmd = self.GetMenuCmd(event)
-        menuform.GUI().ParseCommand(cmd, parentframe = self)
-
+        menuform.GUI(parent = self).ParseCommand(cmd)
+        
+    def OnVDigit(self, event):
+        """!Start vector digitizer
+        """
+        if not self.curr_page:
+            self.MsgNoLayerSelected()
+            return
+        
+        tree = self.GetLayerTree()
+        layer = tree.layer_selected
+        # no map layer selected
+        if not layer:
+            self.MsgNoLayerSelected()
+            return
+        
+        # available only for vector map layers
+        try:
+            mapLayer = tree.GetPyData(layer)[0]['maplayer']
+        except:
+            mapLayer = None
+        
+        if not mapLayer or mapLayer.GetType() != 'vector':
+            gcmd.GMessage(parent = self,
+                          message = _("Selected map layer is not vector."))
+            return
+        
+        if mapLayer.GetMapset() != grass.gisenv()['MAPSET']:
+            gcmd.GMessage(parent = self,
+                          message = _("Editing is allowed only for vector maps from the "
+                                      "current mapset."))
+            return
+        
+        if not tree.GetPyData(layer)[0]:
+            return
+        dcmd = tree.GetPyData(layer)[0]['cmd']
+        if not dcmd:
+            return
+        
+        tree.OnStartEditing(None)
+        
     def OnRunScript(self, event):
         """!Run script"""
         # open dialog and choose script file
@@ -514,21 +575,18 @@
         win.CentreOnScreen()
         win.Show(True)  
         
-    def OnWorkspace(self, event):
-        """!Workspace menu (new, load, import)"""
+    def _popupMenu(self, data):
+        """!Create popup menu
+        """
         point = wx.GetMousePosition()
         menu = wx.Menu()
-
-        for key, handler in (('workspaceNew',  self.OnWorkspaceNew),
-                             ('workspaceLoad', self.OnWorkspaceLoad),
-                             (None, None),
-                             ('rastImport',    self.OnImportGdalLayers),
-                             ('vectImport',    self.OnImportOgrLayers)):
+        
+        for key, handler in data:
             if key is None:
                 menu.AppendSeparator()
                 continue
-            item = wx.MenuItem(menu, wx.ID_ANY, Icons[key].GetLabel())
-            item.SetBitmap(Icons[key].GetBitmap(self.iconsize))
+            item = wx.MenuItem(menu, wx.ID_ANY, Icons['layerManager'][key].GetLabel())
+            item.SetBitmap(Icons['layerManager'][key].GetBitmap(self.iconsize))
             menu.AppendItem(item)
             self.Bind(wx.EVT_MENU, handler, item)
         
@@ -536,6 +594,23 @@
         self.PopupMenu(menu)
         menu.Destroy()
 
+    def OnNewMenu(self, event):
+        """!New display/workspace menu
+        """
+        self._popupMenu((('newdisplay', self.OnNewDisplay),
+                         ('workspaceNew',  self.OnWorkspaceNew)))
+
+    def OnLoadMenu(self, event):
+        """!Load maps menu (new, load, import, link)
+        """
+        self._popupMenu((('workspaceLoad', self.OnWorkspaceLoad),
+                         (None, None),
+                         ('rastImport',    self.OnImportGdalLayers),
+                         ('rastLink',      self.OnLinkGdalLayers),
+                         (None, None),
+                         ('vectImport',    self.OnImportOgrLayers),
+                         ('vectLink',      self.OnLinkOgrLayers)))
+        
     def OnWorkspaceNew(self, event = None):
         """!Create new workspace file
 
@@ -869,6 +944,22 @@
         """
         Debug.msg(4, "GMFrame.OnWorkspaceClose(): file=%s" % self.workspaceFile)
         
+        self.OnDisplayCloseAll()
+        self.workspaceFile = None
+        self.workspaceChanged = False
+        self.SetTitle(self.baseTitle)
+        self.disp_idx = 0
+        self.curr_page = None
+        
+    def OnDisplayClose(self, event = None):
+        """!Close current map display window
+        """
+        if self.curr_page and self.curr_page.maptree.mapdisplay:
+            self.curr_page.maptree.mapdisplay.OnCloseWindow(event)
+        
+    def OnDisplayCloseAll(self, event = None):
+        """!Close all open map display windows
+        """
         displays = list()
         for page in range(0, self.gm_cb.GetPageCount()):
             displays.append(self.gm_cb.GetPage(page).maptree.mapdisplay)
@@ -876,12 +967,6 @@
         for display in displays:
             display.OnCloseWindow(event)
         
-        self.workspaceFile = None
-        self.workspaceChanged = False
-        self.SetTitle(self.baseTitle)
-        self.disp_idx = 0
-        self.curr_page = None
-        
     def RulesCmd(self, event):
         """!Launches dialog for commands that need rules input and
         processes rules
@@ -954,6 +1039,12 @@
         # reset display mode
         os.environ['GRASS_RENDER_IMMEDIATE'] = 'TRUE'
         
+    def OnInstallExtension(self, event):
+        """!Install extension from GRASS Addons SVN repository"""
+        win = InstallExtensionWindow(self, size = (650, 550))
+        win.CentreOnScreen()
+        win.Show()
+
     def OnPreferences(self, event):
         """!General GUI preferences/settings"""
         if not self.dialogs['preferences']:
@@ -1077,7 +1168,8 @@
             self.MsgNoLayerSelected()
             return
         
-        layer = self.curr_page.maptree.layer_selected
+        tree = self.GetLayerTree()
+        layer = tree.layer_selected
         # no map layer selected
         if not layer:
             self.MsgNoLayerSelected()
@@ -1085,21 +1177,18 @@
         
         # available only for vector map layers
         try:
-            maptype = self.curr_page.maptree.GetPyData(layer)[0]['maplayer'].type
+            maptype = tree.GetPyData(layer)[0]['maplayer'].type
         except:
             maptype = None
         
         if not maptype or maptype != 'vector':
-            wx.MessageBox(parent = self,
-                          message = _("Attribute management is available only "
-                                    "for vector maps."),
-                          caption = _("Message"),
-                          style = wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
+            gcmd.GMessage(parent = self,
+                          message = _("Selected map layer is not vector."))
             return
         
-        if not self.curr_page.maptree.GetPyData(layer)[0]:
+        if not tree.GetPyData(layer)[0]:
             return
-        dcmd = self.curr_page.maptree.GetPyData(layer)[0]['cmd']
+        dcmd = tree.GetPyData(layer)[0]['cmd']
         if not dcmd:
             return
         
@@ -1193,32 +1282,16 @@
         if not self.curr_page:
             self.NewDisplay(show = True)
         
-        point = wx.GetMousePosition()
-        rastmenu = wx.Menu()
+        self._popupMenu((('addRast3d', self.OnAddRaster3D),
+                         (None, None),
+                         ('addRgb',    self.OnAddRasterRGB),
+                         ('addHis',    self.OnAddRasterHIS),
+                         (None, None),
+                         ('addShaded', self.OnAddRasterShaded),
+                         (None, None),
+                         ('addRArrow', self.OnAddRasterArrow),
+                         ('addRNum',   self.OnAddRasterNum)))
         
-        for key, handler in (('addrast3d', self.OnAddRaster3D),
-                             (None, None),
-                             ('addrgb',    self.OnAddRasterRGB),
-                             ('addhis',    self.OnAddRasterHIS),
-                             (None, None),
-                             ('addshaded', self.OnAddRasterShaded),
-                             (None, None),
-                             ('addrarrow', self.OnAddRasterArrow),
-                             ('addrnum',   self.OnAddRasterNum)):
-            if key is None:
-                rastmenu.AppendSeparator()
-                continue
-            
-            item = wx.MenuItem(rastmenu, wx.ID_ANY, Icons[key].GetLabel())
-            item.SetBitmap(Icons[key].GetBitmap(self.iconsize))
-            rastmenu.AppendItem(item)
-            self.Bind(wx.EVT_MENU, handler, item)
-            
-        # Popup the menu. If an item is selected then its handler
-        # will be called before PopupMenu returns.
-        self.PopupMenu(rastmenu)
-        rastmenu.Destroy()
-        
         # show map display
         self.curr_page.maptree.mapdisplay.Show()
         
@@ -1237,25 +1310,9 @@
         if not self.curr_page:
             self.NewDisplay(show = True)
 
-        point = wx.GetMousePosition()
-        vectmenu = wx.Menu()
+        self._popupMenu((('addThematic', self.OnAddVectorTheme),
+                         ('addChart',    self.OnAddVectorChart)))
         
-        for key, handler in (('addthematic', self.OnAddVectorTheme),
-                             ('addchart',    self.OnAddVectorChart)):
-            if key is None:
-                rastmenu.AppendSeparator()
-                continue
-            
-            item = wx.MenuItem(vectmenu, wx.ID_ANY, Icons[key].GetLabel())
-            item.SetBitmap(Icons[key].GetBitmap(self.iconsize))
-            vectmenu.AppendItem(item)
-            self.Bind(wx.EVT_MENU, handler, item)
-        
-        # Popup the menu.  If an item is selected then its handler
-        # will be called before PopupMenu returns.
-        self.PopupMenu(vectmenu)
-        vectmenu.Destroy()
-
         # show map display
         self.curr_page.maptree.mapdisplay.Show()
 
@@ -1275,29 +1332,13 @@
         if not self.curr_page:
             self.NewDisplay(show = True)
 
-        point = wx.GetMousePosition()
-        ovlmenu = wx.Menu()
-
-        for key, handler in (('addgrid',     self.OnAddGrid),
-                             ('addlabels',   self.OnAddLabels),
-                             ('addgeodesic', self.OnAddGeodesic),
-                             ('addrhumb',    self.OnAddRhumb),
-                             (None, None),
-                             ('addcmd',      self.OnAddCommand)):
-            if key is None:
-                ovlmenu.AppendSeparator()
-                continue
-            
-            item = wx.MenuItem(ovlmenu, wx.ID_ANY, Icons[key].GetLabel())
-            item.SetBitmap(Icons[key].GetBitmap(self.iconsize))
-            ovlmenu.AppendItem(item)
-            self.Bind(wx.EVT_MENU, handler, item)
+        self._popupMenu((('addGrid',     self.OnAddGrid),
+                         ('addLabels',   self.OnAddLabels),
+                         ('addGeodesic', self.OnAddGeodesic),
+                         ('addRhumb',    self.OnAddRhumb),
+                         (None, None),
+                         ('addCmd',      self.OnAddCommand)))
         
-        # Popup the menu.  If an item is selected then its handler
-        # will be called before PopupMenu returns.
-        self.PopupMenu(ovlmenu)
-        ovlmenu.Destroy()
-
         # show map display
         self.curr_page.maptree.mapdisplay.Show()
         
@@ -1486,10 +1527,9 @@
         # don't ask any more...
         UserSettings.Set(group = 'manager', key = 'askOnQuit', subkey = 'enabled',
                          value = False)
-
-        for page in range(self.gm_cb.GetPageCount()):
-            self.gm_cb.GetPage(0).maptree.mapdisplay.OnCloseWindow(event)
-
+        
+        self.OnDisplayCloseAll()
+        
         self.gm_cb.DeleteAllPages()
         
         self._auimgr.UnInit()
@@ -1523,11 +1563,21 @@
         wx.InitAllImageHandlers()
 
         # create splash screen
-        introImagePath = os.path.join(globalvar.ETCWXDIR, "images", "grass_splash.png")
+        introImagePath = os.path.join(globalvar.ETCIMGDIR, "silesia_splash.png")
         introImage     = wx.Image(introImagePath, wx.BITMAP_TYPE_PNG)
         introBmp       = introImage.ConvertToBitmap()
-        wx.SplashScreen (bitmap = introBmp, splashStyle = wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_TIMEOUT,
-                         milliseconds = 2000, parent = None, id = wx.ID_ANY)
+        if SC:
+            splash = SC.AdvancedSplash(bitmap = introBmp, 
+                                       timeout = 2000, parent = None, id = wx.ID_ANY)
+            splash.SetText(_('Starting GRASS GUI...'))
+            splash.SetTextColour(wx.Colour(45, 52, 27))
+            splash.SetTextFont(wx.Font(pointSize = 15, family = wx.DEFAULT, style = wx.NORMAL,
+                                       weight = wx.BOLD))
+            splash.SetTextPosition((150, 430))
+        else:
+            wx.SplashScreen (bitmap = introBmp, splashStyle = wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_TIMEOUT,
+                             milliseconds = 2000, parent = None, id = wx.ID_ANY)
+        
         wx.Yield()
         
         w, h = wx.GetDisplaySize()

Modified: grass/branches/releasebranch_6_4/gui/wxpython/wxpythonlib.dox
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/wxpythonlib.dox	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/wxpythonlib.dox	2011-04-13 09:30:47 UTC (rev 45931)
@@ -266,10 +266,7 @@
 \subsection vdigit Vector digitizer
 
 - gui_modules/vdigit.py
- - gui_modules::vdigit::AbstractDigit
  - gui_modules::vdigit::VDigit
- - gui_modules::vdigit::AbstractDisplayDriver
- - gui_modules::vdigit::CDisplayDriver
  - gui_modules::vdigit::VDigitSettingsDialog
  - gui_modules::vdigit::VDigitCategoryDialog
  - gui_modules::vdigit::CategoryListCtrl
@@ -277,6 +274,13 @@
  - gui_modules::vdigit::VDigitDuplicatesDialog
  - gui_modules::vdigit::CheckListFeature
 
+- gui_modules/wxvdriver.py
+ - gui_modules::wxvdriver::DisplayDriver
+ 
+- gui_modules/wxvdigit.py
+ - gui_modules::wxvdigit::VDigitError
+ - gui_modules::wxvdigit::IVDigit
+
 \subsection wxnviz 3D view mode (wxNviz)
 
 - gui_modules/nviz_mapdisp.py

Modified: grass/branches/releasebranch_6_4/gui/wxpython/xml/menudata.xml
===================================================================
--- grass/branches/releasebranch_6_4/gui/wxpython/xml/menudata.xml	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/gui/wxpython/xml/menudata.xml	2011-04-13 09:30:47 UTC (rev 45931)
@@ -49,6 +49,40 @@
 	    </menuitem>
 	  </items>
 	</menu>
+	<menu>
+	  <label>Map display</label>
+	  <items>
+	    <menuitem>
+	      <label>New</label>
+	      <help>Open new map display window</help>
+	      <handler>OnNewDisplay</handler>
+	    </menuitem>
+	    <menuitem>
+	      <label>Close current</label>
+	      <help>Close current map display window</help>
+	      <handler>OnDisplayClose</handler>
+	      <shortcut>Ctrl+W</shortcut>
+	    </menuitem>
+	    <menuitem>
+	      <label>Close all</label>
+	      <help>Close all open map display windows</help>
+	      <handler>OnDisplayCloseAll</handler>
+	    </menuitem>
+	    <separator />
+	    <menuitem>
+	      <label>Add raster</label>
+	      <help>Add raster map layer to current display</help>
+	      <handler>OnAddRaster</handler>
+	      <shortcut>Ctrl+R</shortcut>
+	    </menuitem>
+	    <menuitem>
+	      <label>Add vector</label>
+	      <help>Add vector map layer to current display</help>
+	      <handler>OnAddVector</handler>
+	      <shortcut>Ctrl+V</shortcut>
+	    </menuitem>
+	  </items>
+	</menu>
 	<separator />
 	<menu>
 	  <label>Import raster data</label>
@@ -85,7 +119,7 @@
 	    <separator />
 	    <menuitem>
 	      <label>Binary file import</label>
-	      <help>Import a binary raster file into a GRASS raster map layer.</help>
+	      <help>Import a binary raster file into a GRASS raster map.</help>
 	      <keywords>raster,import</keywords>
 	      <handler>OnMenuCmd</handler>
 	      <command>r.in.bin</command>
@@ -233,7 +267,7 @@
 	    </menuitem>
 	    <menuitem>
 	      <label>Matlab array and MapGen import</label>
-	      <help>Import Mapgen or Matlab-ASCII vector maps into GRASS.</help>
+	      <help>Import Mapgen or Matlab vector maps into GRASS.</help>
 	      <keywords>vector,import</keywords>
 	      <handler>OnMenuCmd</handler>
 	      <command>v.in.mapgen</command>
@@ -322,16 +356,16 @@
 	    <separator />
 	    <menuitem>
 	      <label>Binary export</label>
-	      <help>Exports a GRASS raster to a binary array.</help>
-	      <keywords>raster</keywords>
+	      <help>Exports a GRASS raster map to a binary array.</help>
+	      <keywords>raster,export</keywords>
 	      <handler>OnMenuCmd</handler>
 	      <command>r.out.bin</command>
 	    </menuitem>
 	    <separator />
 	    <menuitem>
 	      <label>MPEG-1 export</label>
-	      <help>Raster File Series to MPEG Conversion Program.</help>
-	      <keywords>raster</keywords>
+	      <help>Raster File Series to MPEG Conversion.</help>
+	      <keywords>raster,animation</keywords>
 	      <handler>OnMenuCmd</handler>
 	      <command>r.out.mpeg</command>
 	    </menuitem>
@@ -555,7 +589,7 @@
 	  <items>
 	    <menuitem>
 	      <label>Raster to vector</label>
-	      <help>Converts a raster map into a vector map layer.</help>
+	      <help>Converts a raster map into a vector map.</help>
 	      <keywords>raster,conversion,vectorization</keywords>
 	      <handler>OnMenuCmd</handler>
 	      <command>r.to.vect</command>
@@ -655,8 +689,15 @@
 	</menuitem>
 	<separator />
 	<menuitem>
+	  <label>Hardcopy Map Output Utility</label>
+	  <help>Launch Hardcopy Map Output Utility</help>
+	  <keywords>postscript,map,printing</keywords>
+	  <handler>OnPsMap</handler>
+	  <command>ps.map</command>
+	</menuitem>
+	<menuitem>
 	  <label>Postscript plot</label>
-	  <help>Hardcopy PostScript map output utility.</help>
+	  <help>Produces hardcopy PostScript map output.</help>
 	  <keywords>postscript,map,printing</keywords>
 	  <handler>OnMenuCmd</handler>
 	  <command>ps.map</command>
@@ -737,14 +778,14 @@
 	    <menuitem>
 	      <label>Show settings</label>
 	      <help>Outputs and modifies the user's current GRASS variable settings.</help>
-	      <keywords>general</keywords>
+	      <keywords>general,settings</keywords>
               <handler>RunMenuCmd</handler>
 	      <command>g.gisenv -n</command>
 	    </menuitem>
 	    <menuitem>
 	      <label>Change settings</label>
 	      <help>Outputs and modifies the user's current GRASS variable settings.</help>
-	      <keywords>general</keywords>
+	      <keywords>general,settings</keywords>
               <handler>OnMenuCmd</handler>
 	      <command>g.gisenv</command>
 	    </menuitem>
@@ -759,7 +800,7 @@
 	    <menuitem>
 	      <label>Version</label>
 	      <help>Displays version and copyright information.</help>
-	      <keywords>general</keywords>
+	      <keywords>general,version</keywords>
               <handler>RunMenuCmd</handler>
 	      <command>g.version -c</command>
 	    </menuitem>
@@ -801,6 +842,11 @@
 	</menu>
 	<separator />
 	    <menuitem>
+	      <label>Install extension from add-ons</label>
+	      <help>Install new extension from GRASS AddOns SVN repository.</help>
+	      <handler>OnInstallExtension</handler>
+	    </menuitem>
+	    <menuitem>
 	      <label>Manage add-ons extensions</label>
 	      <help>Tool to maintain GRASS extensions in local GRASS installation.</help>
 	      <keywords>general,extensions</keywords>
@@ -1017,7 +1063,7 @@
 	</menuitem>
 	<menuitem>
 	  <label>Mask</label>
-	  <help>Create a MASK for limiting raster operation</help>
+	  <help>Creates a mask for limiting raster operation.</help>
 	  <keywords>raster,mask</keywords>
 	  <handler>OnMenuCmd</handler>
 	  <command>r.mask</command>
@@ -1212,23 +1258,23 @@
 	  <items>
 	    <menuitem>
 	      <label>Carve stream channels</label>
-	      <help>Takes vector stream data, transforms it to raster and subtracts depth from the output DEM.</help>
-	      <keywords>raster</keywords>
+	      <help>Generates stream channels.</help>
+	      <keywords>raster,hydrology</keywords>
 	      <handler>OnMenuCmd</handler>
 	      <command>r.carve</command>
 	    </menuitem>
 	    <menuitem>
 	      <label>Fill lake</label>
 	      <help>Fills lake from seed at given level.</help>
-	      <keywords>raster</keywords>
+	      <keywords>raster,hydrology</keywords>
 	      <handler>OnMenuCmd</handler>
 	      <command>r.lake</command>
 	    </menuitem>
 	    <separator />
 	    <menuitem>
 	      <label>Depressionless map and flowlines</label>
-	      <help>Filters and generates a depressionless elevation map and a flow direction map from a given elevation layer.</help>
-	      <keywords>raster</keywords>
+	      <help>Filters and generates a depressionless elevation map and a flow direction map from a given elevation raster map.</help>
+	      <keywords>raster,hydrology</keywords>
 	      <handler>OnMenuCmd</handler>
 	      <command>r.fill.dir</command>
 	    </menuitem>
@@ -1241,22 +1287,22 @@
 	    </menuitem>
 	    <menuitem>
 	      <label>Flow lines</label>
-	      <help>Construction of slope curves (flowlines), flowpath lengths, and flowline densities (upslope areas) from a raster digital elevation model (DEM)</help>
-	      <keywords>raster</keywords>
+	      <help>Constructs flow lines.</help>
+	      <keywords>raster,hydrology</keywords>
 	      <handler>OnMenuCmd</handler>
 	      <command>r.flow</command>
 	    </menuitem>
 	    <separator />
 	    <menuitem>
 	      <label>SIMWE Overland flow modeling</label>
-	      <help>Overland flow hydrologic simulation using path sampling method (SIMWE)</help>
+	      <help>Overland flow hydrologic simulation using path sampling method (SIMWE).</help>
 	      <keywords>raster,flow,hydrology</keywords>
 	      <handler>OnMenuCmd</handler>
 	      <command>r.sim.water</command>
 	    </menuitem>
 	    <menuitem>
 	      <label>SIMWE Sediment flux modeling</label>
-	      <help>Sediment transport and erosion/deposition simulation using path sampling method (SIMWE)</help>
+	      <help>Sediment transport and erosion/deposition simulation using path sampling method (SIMWE).</help>
 	      <keywords>raster,sediment flow,erosion,deposition</keywords>
 	      <handler>OnMenuCmd</handler>
 	      <command>r.sim.sediment</command>
@@ -1264,15 +1310,15 @@
 	    <separator />
 	    <menuitem>
 	      <label>Topographic index map</label>
-	      <help>Creates topographic index [ln(a/tan(beta))] map from elevation map.</help>
-	      <keywords>raster</keywords>
+	      <help>Creates topographic index map from elevation raster map.</help>
+	      <keywords>raster,hydrology</keywords>
 	      <handler>OnMenuCmd</handler>
 	      <command>r.topidx</command>
 	    </menuitem>
 	    <menuitem>
 	      <label>TOPMODEL simulation</label>
 	      <help>Simulates TOPMODEL which is a physically based hydrologic model.</help>
-	      <keywords>raster</keywords>
+	      <keywords>raster,hydrology</keywords>
 	      <handler>OnMenuCmd</handler>
 	      <command>r.topmodel</command>
 	    </menuitem>
@@ -1286,15 +1332,15 @@
 	    </menuitem>
 	    <menuitem>
 	      <label>Watershed analysis</label>
-	      <help>Watershed basin analysis program.</help>
-	      <keywords>raster</keywords>
+	      <help>Watershed basin analysis program</help>
+	      <keywords>raster,hydrology</keywords>
 	      <handler>OnMenuCmd</handler>
 	      <command>r.watershed</command>
 	    </menuitem>
 	    <menuitem>
 	      <label>Watershed basin creation</label>
-	      <help>Watershed basin creation program.</help>
-	      <keywords>raster</keywords>
+	      <help>Creates watershed basins.</help>
+	      <keywords>raster,hydrology</keywords>
 	      <handler>OnMenuCmd</handler>
 	      <command>r.water.outlet</command>
 	    </menuitem>
@@ -1495,8 +1541,8 @@
 	    </menuitem>
 	    <menuitem>
 	      <label>Reclassify</label>
-	      <help>Creates a new map layer whose category values are based upon a reclassification of the categories in an existing raster map layer.</help>
-	      <keywords>raster</keywords>
+	      <help>Reclassify raster map based on category values.</help>
+	      <keywords>raster,reclassification</keywords>
 	      <handler>OnMenuCmd</handler>
 	      <command>r.reclass</command>
 	    </menuitem>
@@ -1565,7 +1611,7 @@
 	    <separator />
 	    <menuitem>
 	      <label>Gaussian kernel density surface</label>
-	      <help>Generates a raster density map from vector points data using a moving 2D isotropic Gaussian kernel or optionally generates a vector density map on vector network with a 1D kernel.</help>
+	      <help>Generates a raster density map from vector point data using a moving kernel or optionally generates a vector density map on a vector network.</help>
 	      <keywords>vector,kernel density</keywords>
 	      <handler>OnMenuCmd</handler>
 	      <command>v.kernel</command>
@@ -1665,6 +1711,14 @@
 	    </menuitem>
 	    <separator />
 	    <menuitem>
+	      <label>Ordinary or block kriging</label>
+	      <help>Performs ordinary or block kriging.</help>
+	      <keywords>vector,interpolation,kriging</keywords>
+              <handler>RunMenuCmd</handler>
+	      <command>v.krige.py</command>
+	    </menuitem>
+	    <separator />
+	    <menuitem>
 	      <label>Fill NULL cells</label>
 	      <help>Fills no-data areas in raster maps using v.surf.rst splines interpolation</help>
 	      <keywords>raster,elevation,interpolation</keywords>
@@ -2099,6 +2153,27 @@
 	      <handler>OnMenuCmd</handler>
 	      <command>v.net.path</command>
 	    </menuitem>
+	    <menuitem>
+	      <label>Shortest path for sets of features</label>
+	      <help>Computes shortest distance via the network between the given sets of features.</help>
+	      <keywords>vector,network,shortest path</keywords>
+	      <handler>OnMenuCmd</handler>
+	      <command>v.net.distance</command>
+	    </menuitem>
+	    <menuitem>
+	      <label>Shortest path using timetables</label>
+	      <help>Finds shortest path using timetables.</help>
+	      <keywords>vector,network,shortest path</keywords>
+	      <handler>OnMenuCmd</handler>
+	      <command>v.net.timetable</command>
+	    </menuitem>
+	    <menuitem>
+	      <label>Shortest path for all pairs</label>
+	      <help>Computes the shortest path between all pairs of nodes in the network.</help>
+	      <keywords>vector,network,shortest path</keywords>
+	      <handler>OnMenuCmd</handler>
+	      <command>v.net.allpairs</command>
+	    </menuitem>
 	    <separator />
 	    <menuitem>
 	      <label>Visibility network</label>
@@ -2107,6 +2182,41 @@
 	      <handler>OnMenuCmd</handler>
 	      <command>v.net.visibility</command>
 	    </menuitem>
+	    <menuitem>
+	      <label>Bridges and articulation points</label>
+	      <help>Computes bridges and articulation points in the network.</help>
+	      <keywords>vector,network,articulation points</keywords>
+	      <handler>OnMenuCmd</handler>
+	      <command>v.net.bridge</command>
+	    </menuitem>
+	    <menuitem>
+	      <label>Maximum flow</label>
+	      <help>Computes the maximum flow between two sets of nodes in the network.</help>
+	      <keywords>vector,network,flow</keywords>
+	      <handler>OnMenuCmd</handler>
+	      <command>v.net.flow</command>
+	    </menuitem>
+	    <menuitem>
+	      <label>Vertex connectivity</label>
+	      <help>Computes vertex connectivity between two sets of nodes in the network.</help>
+	      <keywords>vector,network,connectivity</keywords>
+	      <handler>OnMenuCmd</handler>
+	      <command>v.net.connectivity</command>
+	    </menuitem>
+	    <menuitem>
+	      <label>Components</label>
+	      <help>Computes strongly and weakly connected components in the network.</help>
+	      <keywords>vector,network,components</keywords>
+	      <handler>OnMenuCmd</handler>
+	      <command>v.net.components</command>
+	    </menuitem>
+	    <menuitem>
+	      <label>Centrality</label>
+	      <help>Computes degree, centrality, betweeness, closeness and eigenvector centrality measures in the network.</help>
+	      <keywords>vector,network,centrality measures</keywords>
+	      <handler>OnMenuCmd</handler>
+	      <command>v.net.centrality</command>
+	    </menuitem>
 	    <separator />
 	    <menuitem>
 	      <label>Steiner tree</label>
@@ -2116,6 +2226,13 @@
 	      <command>v.net.steiner</command>
 	    </menuitem>
 	    <menuitem>
+	      <label>Minimum spanning tree</label>
+	      <help>Computes minimum spanning tree for the network.</help>
+	      <keywords>vector,network,spanning tree</keywords>
+	      <handler>OnMenuCmd</handler>
+	      <command>v.net.spanningtree</command>
+	    </menuitem>
+	    <menuitem>
 	      <label>Traveling salesman analysis</label>
 	      <help>Creates a cycle connecting given nodes (Traveling salesman problem).</help>
 	      <keywords>vector,networking</keywords>
@@ -2758,7 +2875,7 @@
 	  <items>
 	    <menuitem>
 	      <label>Query any table</label>
-	      <help>Selects data from table.</help>
+	      <help>Selects data from attribute table (performs SQL query statement(s)).</help>
 	      <keywords>database,attribute table,SQL</keywords>
 	      <handler>OnMenuCmd</handler>
 	      <command>db.select</command>

Modified: grass/branches/releasebranch_6_4/lib/init/gis_set.tcl
===================================================================
--- grass/branches/releasebranch_6_4/lib/init/gis_set.tcl	2011-04-12 21:05:46 UTC (rev 45930)
+++ grass/branches/releasebranch_6_4/lib/init/gis_set.tcl	2011-04-13 09:30:47 UTC (rev 45931)
@@ -201,7 +201,7 @@
     
     if { $screen_height > $small_window } {
 	set introimg  [label $titlefrm.img -image [image create photo -file \
-	    "$env(GISBASE)/etc/gui/images/gintro.gif"]]
+	    "$env(GISBASE)/etc/gui/images/startup_banner.gif"]]
 	pack $introimg -side top
     
 	set introtitle [text $titlefrm.msg -height 5 \



More information about the grass-commit mailing list