[GRASS-SVN] r54515 - in grass/trunk/gui/wxpython: . docs lmgr mapdisp vnet xml

svn_grass at osgeo.org svn_grass at osgeo.org
Thu Jan 3 09:46:18 PST 2013


Author: martinl
Date: 2013-01-03 09:46:18 -0800 (Thu, 03 Jan 2013)
New Revision: 54515

Added:
   grass/trunk/gui/wxpython/docs/wxGUI.vnet.html
   grass/trunk/gui/wxpython/vnet/
   grass/trunk/gui/wxpython/vnet/dialogs.py
   grass/trunk/gui/wxpython/vnet/toolbars.py
   grass/trunk/gui/wxpython/vnet/widgets.py
Modified:
   grass/trunk/gui/wxpython/Makefile
   grass/trunk/gui/wxpython/lmgr/frame.py
   grass/trunk/gui/wxpython/mapdisp/frame.py
   grass/trunk/gui/wxpython/mapdisp/toolbars.py
   grass/trunk/gui/wxpython/xml/menudata.xml
Log:
wxGUI: wx.vnet moved from addons to trunk


Modified: grass/trunk/gui/wxpython/Makefile
===================================================================
--- grass/trunk/gui/wxpython/Makefile	2013-01-03 16:59:02 UTC (rev 54514)
+++ grass/trunk/gui/wxpython/Makefile	2013-01-03 17:46:18 UTC (rev 54515)
@@ -11,12 +11,12 @@
 
 SRCFILES := $(wildcard icons/*.* scripts/* xml/*) \
 	$(wildcard animation/* core/* dbmgr/* gcp/* gmodeler/* gui_core/* iclass/* lmgr/* location_wizard/* \
-	mapdisp/* modules/* nviz/* psmap/* mapswipe/* vdigit/* wxplot/* ogc_services/* rlisetup/*) \
+	mapdisp/* modules/* nviz/* psmap/* mapswipe/* vdigit/* wxplot/* ogc_services/* rlisetup/* vnet/*) \
 	gis_set.py gis_set_error.py wxgui.py README
 DSTFILES := $(patsubst %,$(ETCDIR)/%,$(SRCFILES)) $(patsubst %.py,$(ETCDIR)/%.pyc,$(filter %.py,$(SRCFILES)))
 
 PYDSTDIRS := $(patsubst %,$(ETCDIR)/%,animation core dbmgr gcp gmodeler gui_core iclass lmgr location_wizard \
-	mapdisp modules nviz psmap mapswipe vdigit wxplot ogc_services rlisetup)
+	mapdisp modules nviz psmap mapswipe vdigit wxplot ogc_services rlisetup vnet)
 DSTDIRS := $(patsubst %,$(ETCDIR)/%,icons scripts xml)
 
 default: $(DSTFILES)
@@ -41,4 +41,4 @@
 	$(MKDIR) $@
 
 #doxygen:
-DOXNAME=wxpython
+DOXNAME = wxpython

Added: grass/trunk/gui/wxpython/docs/wxGUI.vnet.html
===================================================================
--- grass/trunk/gui/wxpython/docs/wxGUI.vnet.html	                        (rev 0)
+++ grass/trunk/gui/wxpython/docs/wxGUI.vnet.html	2013-01-03 17:46:18 UTC (rev 54515)
@@ -0,0 +1,100 @@
+<!-- meta page description: wxGUI Vector Network Analysis Tool -->
+<!-- meta page index: wxGUI -->
+
+<h2>DESCRIPTION</h2>
+
+<em>Vector Network Analysis Tool</em> is graphical front-end
+for <tt>v.net*</tt> modules. It allows perform network analysis
+directly in <em><a href="wxGUI.html">wxGUI</a></em> without need to
+use command line. The tool is available from GRASS AddOns repository
+and needs to be installed to GRASS GIS by command:
+
+<div class="code"><pre>
+g.extension -s extension=wx.vnet
+</pre></div>
+
+The tool can be launched from Map Display toolbar submenu
+of <em>Analyze Map</em> button where is <em>Vector network analysis
+(experimental, GSoC 2012)</em> item.
+
+<p>
+<em>Vector Network Analysis Tool</em> currently allows to:
+
+<ul>
+  <li> perform these network analyses:
+  <ul>
+    <li> Shortest path
+    (<em><a href="v.net.path.html">v.net.path</a></em>)</li>
+    <li> Salesman
+    (<em><a href="v.net.salesman.html">v.net.salesman</a></em>)</li>
+    <li> Flow (<em><a href="v.net.flow.html">v.net.flow</a></em>)</li>
+    <li> Allocate subnets for nearest centers
+    (<em><a href="v.net.alloc.html">v.net.alloc</a></em>)</li>
+    <li> Steiner tree for the network and given terminals
+    (<em><a href="v.net.distance.html">v.net.distance</a></em>)</li>
+    <li> Splits net by cost isolines
+    (<em><a href="v.net.iso.html">v.net.iso</a></em>)</li>
+  </ul>
+  </li>
+  <li>show and set all data needed for the analysis (points, attribute
+  tables, compute costs)</li>
+  <li>show analysis results (maps and it's attribute tables)</li>
+  <li>snapping to nodes</li>
+  <li>browse previous analysis results</li>
+</ul>
+
+<h2>NOTES</h2>
+
+The tool is split into tabs. Every tab represents some functionality:
+
+<ul>
+  <li> <tt>Parameters</tt> tab - It is used for setting vector map and
+  it's layer on which analysis will be done. Also it is possible to
+  set columns with cost values from attribute table connected 
+  to particular layer.</li>
+  <li> <tt>Points</tt> tab - It manages points, which are used for
+  analysis.</li>
+  <li> <tt>Output</tt> tab - There is a output console, which shows
+  information about running analysis. </li>
+  <li> <tt>Input tables</tt> tab - When existing vector map and it's
+  existing layers are set in <tt>Parameters</tt> tab, this tab is
+  dynamically added. It shows attribute tables of node and arc layers,
+  which were chosen for analysis. It is also possible to compute cost
+  values in this tab. This can be done by right mouse button click on
+  column label. Then from pop-up menu choose <tt>Add column</tt>,
+  where new column for cost values can be created. After that by right
+  mouse button click on the added column label can be chosen
+  item <tt>Field calculator</tt>. This tool allows to compute cost
+  values.</li>
+  <li> <tt>Result tables</tt> tab - Result of vector network analysis
+  is always vector map. Some vector network analysis results can also
+  include attribute tables. If such a table is connected to result
+  map, this tab is showed and allows to browse these data.</li>
+</ul>
+
+<h2>KNOWN ISSUES</h2>
+
+When some change is done in layer tree of Map Display, temporary
+vector map representing result of analysis is not rendered 
+(use <tt>Show result</tt> button in toolbar to render it again).
+
+<h2>SEE ALSO</h2>
+
+<em>
+  <a href="wxGUI.html">wxGUI</a><br>
+  <a href="wxGUI.Components.html">wxGUI components</a>
+</em>
+
+<p>
+See also the
+user <a href="http://grass.osgeo.org/wiki/WxGUI_Vector_Network_Analysis_Tool">wiki</a>
+page.
+
+<h2>AUTHOR</h2>
+
+Stepan
+Turek, <a href="http://grass.osgeo.org/wiki/GRASS_GSoC_2012_WxGUI_front_end_for_vector_analysis_modules">Google
+Summer of Code 2012</a> (mentor: Martin Landa)
+
+<p>
+<i>$Date$</i>


Property changes on: grass/trunk/gui/wxpython/docs/wxGUI.vnet.html
___________________________________________________________________
Added: svn:mime-type
   + text/html
Added: svn:keywords
   + Author Date Id
Added: svn:eol-style
   + native

Modified: grass/trunk/gui/wxpython/lmgr/frame.py
===================================================================
--- grass/trunk/gui/wxpython/lmgr/frame.py	2013-01-03 16:59:02 UTC (rev 54514)
+++ grass/trunk/gui/wxpython/lmgr/frame.py	2013-01-03 17:46:18 UTC (rev 54515)
@@ -725,6 +725,13 @@
             cmd = self.GetMenuCmd(event)
         GUI(parent = self).ParseCommand(cmd)
         
+    def OnVNet(self, event):
+        """Vector network analysis tool"""
+        if self.GetMapDisplay():
+            self.GetMapDisplay().OnVNet(event)
+        else:
+            self.NewDisplay(show = True).OnVNet(event)
+        
     def OnVDigit(self, event):
         """!Start vector digitizer
         """

Modified: grass/trunk/gui/wxpython/mapdisp/frame.py
===================================================================
--- grass/trunk/gui/wxpython/mapdisp/frame.py	2013-01-03 16:59:02 UTC (rev 54514)
+++ grass/trunk/gui/wxpython/mapdisp/frame.py	2013-01-03 17:46:18 UTC (rev 54515)
@@ -1335,24 +1335,17 @@
         """!Returns toolbar with zooming tools"""
         return self.toolbars['map']
 
-    def OnVnet(self, event):
+    def OnVNet(self, event):
         """!Dialog for v.net* modules 
         """
         if self.dialogs['vnet']:
             return
-        else:
-            try:
-                from vnet.dialogs import VNETDialog
-            except ImportError:
-                GError(_("Extension <%s> not available, run '%s' to install it.") % \
-                           ('wx.vnet', 'g.extension -s extension=wx.vnet'),
-                       parent = self, showTraceback = False)
-                return
+        
+        from vnet.dialogs import VNETDialog
+        self.dialogs['vnet'] = VNETDialog(parent = self)
+        self.dialogs['vnet'].CenterOnScreen()
+        self.dialogs['vnet'].Show()
             
-            self.dialogs['vnet'] = VNETDialog(parent = self)
-            self.dialogs['vnet'].CenterOnScreen()
-            self.dialogs['vnet'].Show()
-            
     def SwitchTool(self, toolbar, event):
         """!Calls UpdateTools to manage connected toolbars"""
         self.UpdateTools(event)

Modified: grass/trunk/gui/wxpython/mapdisp/toolbars.py
===================================================================
--- grass/trunk/gui/wxpython/mapdisp/toolbars.py	2013-01-03 16:59:02 UTC (rev 54514)
+++ grass/trunk/gui/wxpython/mapdisp/toolbars.py	2013-01-03 17:46:18 UTC (rev 54515)
@@ -47,7 +47,7 @@
     'histogram'  : MetaIcon(img = 'layer-raster-histogram',
                             label = _('Create histogram of raster map')),
     'vnet'       : MetaIcon(img = 'line-split',
-                            label = _('Vector network analysis (experimental, GSoC 2012)')),
+                            label = _('Vector network analysis tool')),
     }
 
 NvizIcons = {
@@ -239,12 +239,12 @@
     def OnAnalyze(self, event):
         """!Analysis tools menu
         """
-        self._onMenu(((MapIcons["measure"],    self.parent.OnMeasure),
-                      (MapIcons["profile"],    self.parent.OnProfile),
-                      (MapIcons["scatter"],    self.parent.OnScatterplot),
-                      (MapIcons["histogram"],  self.parent.OnHistogramPyPlot),
+        self._onMenu(((MapIcons["measure"],     self.parent.OnMeasure),
+                      (MapIcons["profile"],     self.parent.OnProfile),
+                      (MapIcons["scatter"],     self.parent.OnScatterplot),
+                      (MapIcons["histogram"],   self.parent.OnHistogramPyPlot),
                       (BaseIcons["histogramD"], self.parent.OnHistogram),
-                      (MapIcons["vnet"],        self.parent.OnVnet)))
+                      (MapIcons["vnet"],        self.parent.OnVNet)))
         
     def OnDecoration(self, event):
         """!Decorations overlay menu

Added: grass/trunk/gui/wxpython/vnet/dialogs.py
===================================================================
--- grass/trunk/gui/wxpython/vnet/dialogs.py	                        (rev 0)
+++ grass/trunk/gui/wxpython/vnet/dialogs.py	2013-01-03 17:46:18 UTC (rev 54515)
@@ -0,0 +1,2827 @@
+"""!
+ at package vnet.dialogs
+
+ at brief Dialog for vector network analysis front-end
+
+Classes:
+ - dialogs::VNETDialog
+ - dialogs::PtsList
+ - dialogs::SettingsDialog
+ - dialogs::AddLayerDialog
+ - dialogs::VnetTmpVectMaps
+ - dialogs::VectMap
+ - dialogs::History
+ - dialogs::VnetStatusbar
+
+(C) 2012 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 Stepan Turek <stepan.turek seznam.cz> (GSoC 2012, mentor: Martin Landa)
+"""
+
+import os
+import sys
+import types
+try:
+    import grass.lib.vector as vectlib
+    from ctypes import pointer, byref, c_char_p, c_int, c_double
+    haveCtypes = True
+except ImportError:
+    haveCtypes = False
+
+from copy import copy
+from grass.script     import core as grass
+
+import wx
+import wx.aui
+import wx.lib.flatnotebook  as FN
+import wx.lib.colourselect as csel
+
+from core             import globalvar, utils
+from core.settings    import UserSettings
+from core.gcmd        import RunCommand, GMessage
+
+from dbmgr.base       import DbMgrBase 
+
+from gui_core.widgets import GNotebook
+from gui_core.goutput import GConsoleWindow
+from core.gconsole    import CmdThread, EVT_CMD_DONE, GConsole
+from gui_core.gselect import Select, LayerSelect, ColumnSelect
+
+from vnet.widgets     import PointsList
+from vnet.toolbars    import MainToolbar, PointListToolbar, AnalysisToolbar
+
+#Main TODOs
+# - when layer tree of is changed, tmp result map is removed from render list 
+# - optimization of map drawing 
+# - tmp maps - add number of process
+# - destructor problem - when GRASS GIS is closed with open VNETDialog,
+#   it's destructor is not called
+
+class VNETDialog(wx.Dialog):
+    def __init__(self, parent,
+                 id = wx.ID_ANY, title = _("GRASS GIS Vector Network Analysis Tool"),
+                 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
+        """!Dialog for vector network analysis"""
+
+        wx.Dialog.__init__(self, parent, id, style=style, title = title, **kwargs)
+        self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
+
+        self.parent  = parent  # mapdisp.frame MapFrame class
+        self.mapWin = parent.MapWindow 
+
+        # contains current analysis result (do not have to be last one, when history is browsed), 
+        # it is instance of VectMap class
+        self.tmp_result = None 
+
+        # initialization of History class used for saving and reading data from file
+        # it is used for browsing analysis results
+        self.history = History(self)
+
+        # variable, which appends  unique number to every name of map, which is saved into history
+        self.histTmpVectMapNum = 0
+
+        # list of maps, which will be saved into history
+        self.tmpVectMapsToHist = []
+
+        # this class instance manages all temporary vector maps created during life of VNETDialog  
+        self.tmpMaps = VnetTmpVectMaps(parent = self)
+
+        # setting initialization
+        self._initSettings()
+
+        # registration graphics for drawing
+        self.pointsToDraw = self.mapWin.RegisterGraphicsToDraw(graphicsType = "point", 
+                                                               setStatusFunc = self.SetPointStatus)
+        self.SetPointDrawSettings()
+
+        # information, whether mouse event handler is registered in map window
+        self.handlerRegistered = False
+
+        # get attribute table columns only with numbers (for cost columns in vnet analysis)
+        self.columnTypes = ['integer', 'double precision'] 
+        
+        # initialization of v.net.* analysis parameters (data which characterizes particular analysis)
+        self._initVnetParams()
+
+        # toobars
+        self.toolbars = {}
+        self.toolbars['mainToolbar'] = MainToolbar(parent = self)
+        self.toolbars['analysisToolbar'] = AnalysisToolbar(parent = self)
+        #
+        # Fancy gui
+        #
+        self._mgr = wx.aui.AuiManager(self)
+
+        # Columns in points list
+        # TODO init dynamically, not hard typed v.net.path
+        self.cols =   [
+                        ['type', _('type'), [_(""), _("Start point"), _("End point")], 0], 
+                        ['topology',  _('topology'), None, ""] 
+                      ]
+
+        self.mainPanel = wx.Panel(parent=self)
+        self.notebook = GNotebook(parent = self.mainPanel,
+                                  style = FN.FNB_FANCY_TABS | FN.FNB_BOTTOM |
+                                          FN.FNB_NO_X_BUTTON)
+
+        # statusbar
+        self.stPriorities = {'important' : 5, 'iformation' : 1}
+        self.stBar = VnetStatusbar(parent = self.mainPanel, style = 0)
+        self.stBar.SetFieldsCount(number = 1)
+    
+        
+        # Create tabs
+        
+        # Stores all data related to snapping
+        self.snapData = {}
+        self.snapData['snap_mode'] = False
+        # Stores widgets which sets some of analysis parameters (e. g. v.ne.iso -> iso lines)
+        self.anSettings = {} 
+        self._createPointsPage()
+
+        # stores widgets which are shown on parameters page 
+        # they set data, on which analysis will be done
+        self.inputData = {}
+        self._createParametersPage()
+
+        # Output console for analysis
+        self._createOutputPage()
+
+        # Stores data which are needed for attribute table browser of analysis input map layers
+        self.inpDbMgrData = {}
+        self._createInputDbMgrPage()
+
+        # Stores data which are need for attribute table browser of analysis result map layers
+        self.resultDbMgrData = {}
+        self._createResultDbMgrPage()
+
+        self.notebook.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
+        self.Bind(wx.EVT_CLOSE, self.OnCloseDialog)
+
+        self._addPanes()
+        self._doVnetDialogLayout()
+        self._mgr.Update()
+
+        # adds 2 points into list
+        for i in range(2):
+            self.list.AddItem()
+            self.list.EditCellIndex(i, 'type', i + 1) 
+            self.list.CheckItem(i, True)
+
+        # selects first point
+        self.list.selected = 0
+        self.list.Select(self.list.selected)
+
+        dlgSize = (420, 560)
+        self.SetMinSize(dlgSize)
+        self.SetInitialSize(dlgSize)
+
+        #fix goutput's pane size (required for Mac OSX)
+        if self.gwindow:         
+            self.gwindow.SetSashPosition(int(self.GetSize()[1] * .75))
+
+        self.OnAnalysisChanged(None)
+        self.notebook.SetSelectionByName("parameters")
+        self.toolbars['analysisToolbar'].SetMinSize((-1, self.toolbars['mainToolbar'].GetSize()[1]))
+
+    def  __del__(self):
+        """!Removes temp layers, unregisters handlers and graphics"""
+        update = self.tmpMaps.DeleteAllTmpMaps()
+
+        self.mapWin.UnregisterGraphicsToDraw(self.pointsToDraw)
+
+        if self.handlerRegistered:
+            self.mapWin.UnregisterMouseEventHandler(wx.EVT_LEFT_DOWN, 
+                                                  self.OnMapClickHandler)
+        if update:
+            self.mapWin.UpdateMap(render=True, renderVector=True)
+        else:
+            self.mapWin.UpdateMap(render=False, renderVector=False)
+
+
+    def _addPanes(self):
+        """!Adds toolbar pane and pane with tabs"""
+        self._mgr.AddPane(self.toolbars['mainToolbar'],
+                              wx.aui.AuiPaneInfo().
+                              Name("pointlisttools").Caption(_("Point list toolbar")).
+                              ToolbarPane().Top().Row(0).
+                              Dockable(False).
+                              CloseButton(False).Layer(0))
+ 
+        self._mgr.AddPane(self.toolbars['analysisToolbar'],
+                              wx.aui.AuiPaneInfo().
+                              Name("pointlisttools").Caption(_("Point list toolbar")).
+                              ToolbarPane().Top().Row(1).
+                              Dockable(False).
+                              CloseButton(False).Layer(0))
+
+        self._mgr.AddPane(self.mainPanel,
+                              wx.aui.AuiPaneInfo().
+                              Name("tabs").CaptionVisible(visible = False).
+                              Center().
+                              Dockable(False).
+                              CloseButton(False).Layer(0))
+    def _doVnetDialogLayout(self):
+
+        sizer = wx.BoxSizer(wx.VERTICAL)
+
+        sizer.Add(item = self.notebook, proportion = 1,
+                  flag = wx.EXPAND)
+
+        sizer.Add(item = self.stBar, proportion = 0)
+
+        self.mainPanel.SetSizer(sizer)
+
+        sizer.Fit(self)  
+        self.Layout()
+
+    def _createPointsPage(self):
+        """!Tab with points list and analysis settings"""
+        pointsPanel = wx.Panel(parent = self)
+        maxValue = 1e8
+
+        listBox = wx.StaticBox(parent = pointsPanel, id = wx.ID_ANY,
+                                label =" %s " % _("Points for analysis:"))
+
+        self.notebook.AddPage(page = pointsPanel, 
+                              text=_('Points'), 
+                              name = 'points')
+
+        self.list = PtsList(parent = pointsPanel, dialog = self, cols = self.cols)
+        self.toolbars['pointsList'] = PointListToolbar(parent = pointsPanel, list = self.list)
+
+        anSettingsPanel = wx.Panel(parent = pointsPanel)
+
+        anSettingsBox = wx.StaticBox(parent = anSettingsPanel, id = wx.ID_ANY,
+                                label =" %s " % _("Analysis settings:"))
+
+        maxDistPanel =  wx.Panel(parent = anSettingsPanel)
+        maxDistLabel = wx.StaticText(parent = maxDistPanel, id = wx.ID_ANY, label = _("Maximum distance of point to the network:"))
+        self.anSettings["max_dist"] = wx.SpinCtrl(parent = maxDistPanel, id = wx.ID_ANY, min = 0, max = maxValue)
+        self.anSettings["max_dist"].SetValue(100000) #TODO init val
+
+        #showCutPanel =  wx.Panel(parent = anSettingsPanel)
+        #self.anSettings["show_cut"] = wx.CheckBox(parent = showCutPanel, id=wx.ID_ANY,
+        #                                          label = _("Show minimal cut"))
+        #self.anSettings["show_cut"].Bind(wx.EVT_CHECKBOX, self.OnShowCut)
+
+        isoLinesPanel =  wx.Panel(parent = anSettingsPanel)
+        isoLineslabel = wx.StaticText(parent = isoLinesPanel, id = wx.ID_ANY, label = _("Iso lines:"))
+        self.anSettings["iso_lines"] = wx.TextCtrl(parent = isoLinesPanel, id = wx.ID_ANY) 
+        self.anSettings["iso_lines"].SetValue("1000,2000,3000")
+
+        # Layout
+        AnalysisSizer = wx.BoxSizer(wx.VERTICAL)
+
+        listSizer = wx.StaticBoxSizer(listBox, wx.VERTICAL)
+
+        listSizer.Add(item = self.toolbars['pointsList'], proportion = 0)
+        listSizer.Add(item = self.list, proportion = 1, flag = wx.EXPAND)
+
+        anSettingsSizer = wx.StaticBoxSizer(anSettingsBox, wx.VERTICAL)
+
+        maxDistSizer = wx.BoxSizer(wx.HORIZONTAL)
+        maxDistSizer.Add(item = maxDistLabel, flag = wx.ALIGN_CENTER_VERTICAL, proportion = 1)
+        maxDistSizer.Add(item = self.anSettings["max_dist"],
+                         flag = wx.EXPAND | wx.ALL, border = 5, proportion = 0)
+        maxDistPanel.SetSizer(maxDistSizer)
+        anSettingsSizer.Add(item = maxDistPanel, proportion = 1, flag = wx.EXPAND)
+
+        #showCutSizer = wx.BoxSizer(wx.HORIZONTAL)
+        #showCutPanel.SetSizer(showCutSizer)
+        #showCutSizer.Add(item = self.anSettings["show_cut"],
+        #                 flag = wx.EXPAND | wx.ALL, border = 5, proportion = 0)
+        #anSettingsSizer.Add(item = showCutPanel, proportion = 1, flag = wx.EXPAND)
+
+        isoLinesSizer = wx.BoxSizer(wx.HORIZONTAL)
+        isoLinesSizer.Add(item = isoLineslabel, flag = wx.ALIGN_CENTER_VERTICAL, proportion = 1)
+        isoLinesSizer.Add(item = self.anSettings["iso_lines"],
+                        flag = wx.EXPAND | wx.ALL, border = 5, proportion = 1)
+        isoLinesPanel.SetSizer(isoLinesSizer)
+        anSettingsSizer.Add(item = isoLinesPanel, proportion = 1, flag = wx.EXPAND)
+
+        AnalysisSizer.Add(item = listSizer, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 5)
+        AnalysisSizer.Add(item = anSettingsPanel, proportion = 0, flag = wx.EXPAND | wx.RIGHT | wx.LEFT | wx.BOTTOM, border = 5)
+
+        anSettingsPanel.SetSizer(anSettingsSizer)
+        pointsPanel.SetSizer(AnalysisSizer)
+
+    def OnShowCut(self, event):
+        """!Shows vector map with minimal cut (v.net.flow) - not yet implemented"""
+        val = event.IsChecked()
+        if val and self.tmp_result:
+            self.tmp_result.DeleteRenderLayer()
+            cmd = self.GetLayerStyle()
+            self.vnetFlowTmpCut.AddRenderLayer(cmd)
+        else:
+            self.vnetFlowTmpCut.DeleteRenderLayer()
+            cmd = self.GetLayerStyle()
+            self.tmp_result.AddRenderLayer(cmd)
+
+        self.mapWin.UpdateMap(render = True, renderVector = True)
+
+    def _createOutputPage(self):
+        """!Tab with output console"""
+        outputPanel = wx.Panel(parent = self)
+        self.notebook.AddPage(page = outputPanel, 
+                              text = _("Output"), 
+                              name = 'output')
+
+        self.goutput = GConsole(guiparent = self)
+        self.gwindow = GConsoleWindow(parent = outputPanel, gconsole = self.goutput)
+
+        #Layout
+        outputSizer = wx.BoxSizer(wx.VERTICAL)
+        outputSizer.Add(item = self.gwindow, proportion = 1, flag = wx.EXPAND)
+        self.gwindow.SetMinSize((-1,-1))
+
+        outputPanel.SetSizer(outputSizer)
+
+    def _createParametersPage(self):
+        """!Tab for selection of data for analysis"""
+        dataPanel = wx.Panel(parent=self)
+        self.notebook.AddPage(page = dataPanel,
+                              text=_('Parameters'), 
+                              name = 'parameters')
+        label = {}
+        dataSelects = [
+                        ['input', "Choose vector map for analysis:", Select],
+                        ['alayer', "Arc layer number or name:", LayerSelect],
+                        ['nlayer', "Node layer number or name:", LayerSelect],
+                        ['afcolumn', self.attrCols['afcolumn']['label'], ColumnSelect],
+                        ['abcolumn', self.attrCols['abcolumn']['label'], ColumnSelect],
+                        ['ncolumn', self.attrCols['ncolumn']['label'], ColumnSelect],
+                      ]
+
+        selPanels = {}
+        for dataSel in dataSelects:
+            selPanels[dataSel[0]] = wx.Panel(parent = dataPanel)
+            if dataSel[0] == 'input' and self.mapWin.tree:
+                self.inputData[dataSel[0]] = dataSel[2](parent = selPanels[dataSel[0]],  
+                                                        size = (-1, -1), 
+                                                        type = 'vector')
+
+                icon = wx.Image(os.path.join(globalvar.ETCICONDIR, "grass", "layer-vector-add.png"))
+                icon.Rescale(18, 18)
+                icon = wx.BitmapFromImage(icon) 
+                self.addToTreeBtn = wx.BitmapButton(parent = selPanels[dataSel[0]], 
+                                                    bitmap = icon, 
+                                                    size = globalvar.DIALOG_COLOR_SIZE) 
+                self.addToTreeBtn.SetToolTipString(_("Add vector map into layer tree"))
+                self.addToTreeBtn.Disable()
+                self.addToTreeBtn.Bind(wx.EVT_BUTTON, self.OnToTreeBtn)
+            else:
+                self.inputData[dataSel[0]] = dataSel[2](parent = selPanels[dataSel[0]],  
+                                                        size = (-1, -1))
+            label[dataSel[0]] =  wx.StaticText(parent =  selPanels[dataSel[0]], 
+                                               name = dataSel[0])
+            label[dataSel[0]].SetLabel(dataSel[1])
+
+        self.inputData['input'].Bind(wx.EVT_TEXT, self.OnVectSel) 
+        self.inputData['alayer'].Bind(wx.EVT_TEXT, self.OnALayerSel)
+        self.inputData['nlayer'].Bind(wx.EVT_TEXT, self.OnNLayerSel)
+
+        # Layout
+        mainSizer = wx.BoxSizer(wx.VERTICAL)
+        box = wx.StaticBox(dataPanel, -1, "Vector map and layers for analysis")
+        bsizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+
+        mainSizer.Add(item = bsizer, proportion = 0,
+                      flag = wx.EXPAND  | wx.TOP | wx.LEFT | wx.RIGHT, border = 5) 
+
+        for sel in ['input', 'alayer', 'nlayer']:
+            if sel== 'input' and self.mapWin.tree:
+                btn = self.addToTreeBtn
+            else:
+                btn = None
+            selPanels[sel].SetSizer(self._doSelLayout(title = label[sel], 
+                                                      sel = self.inputData[sel], 
+                                                      btn = btn))
+            bsizer.Add(item = selPanels[sel], proportion = 1,
+                       flag = wx.EXPAND)
+
+        box = wx.StaticBox(dataPanel, -1, "Costs")    
+        bsizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+
+        mainSizer.Add(item = bsizer, proportion = 0,
+                                 flag = wx.EXPAND  | wx.TOP | wx.LEFT | wx.RIGHT, border = 5)       
+
+        for sel in ['afcolumn', 'abcolumn', 'ncolumn']:
+            selPanels[sel].SetSizer(self._doSelLayout(title = label[sel], sel = self.inputData[sel]))
+            bsizer.Add(item = selPanels[sel], proportion = 0,
+                       flag = wx.EXPAND)
+
+        dataPanel.SetSizer(mainSizer)
+
+    def _doSelLayout(self, title, sel, btn = None): 
+        # helper function for layout of self.inputData widgets initialized in _createParametersPage
+        selSizer = wx.BoxSizer(orient = wx.VERTICAL)
+
+        selTitleSizer = wx.BoxSizer(wx.HORIZONTAL)
+        selTitleSizer.Add(item = title, proportion = 1,
+                          flag = wx.LEFT | wx.TOP | wx.EXPAND, border = 5)
+
+        selSizer.Add(item = selTitleSizer, proportion = 0,
+                                 flag = wx.EXPAND)
+
+        if btn:
+                selFiledSizer = wx.BoxSizer(orient = wx.HORIZONTAL)
+                selFiledSizer.Add(item = sel, proportion = 1,
+                             flag = wx.EXPAND | wx.ALL)
+
+                selFiledSizer.Add(item = btn, proportion = 0,
+                             flag = wx.EXPAND | wx.ALL)
+
+                selSizer.Add(item = selFiledSizer, proportion = 0,
+                             flag = wx.EXPAND | wx.ALL| wx.ALIGN_CENTER_VERTICAL,
+                             border = 5)
+        else:
+                selSizer.Add(item = sel, proportion = 1,
+                             flag = wx.EXPAND | wx.ALL| wx.ALIGN_CENTER_VERTICAL,
+                             border = 5)
+        return selSizer
+
+    def _createInputDbMgrPage(self):
+        """!Tab with attribute tables of analysis input layers"""
+        self.inpDbMgrData['dbMgr'] = DbMgrBase()
+ 
+        selMapName = None       
+        # if selected vector map is in layer tree then set it
+        if self.mapWin.tree and self.mapWin.tree.layer_selected:
+            selMapData = self.mapWin.tree.GetPyData(self.mapWin.tree.layer_selected)[0]
+            if selMapData['type'] == 'vector': # wrap somehow in LayerTree
+                selMapName = selMapData['maplayer'].name
+
+        self.inpDbMgrData['browse'] = self.inpDbMgrData['dbMgr'].CreateDbMgrPage(parent = self.notebook,
+                                                                                 pageName = 'browse')
+        self.inpDbMgrData['browse'].SetTabAreaColour(globalvar.FNPageColor)
+
+        self.inpDbMgrData['input'] = None
+        if selMapName:
+            self.inputData['input'].SetValue(selMapName)
+            self.OnVectSel(None)
+
+    def _updateInputDbMgrPage(self, show):
+        """!Show or hide input tables tab"""
+        if show and self.notebook.GetPageIndexByName('inputDbMgr') == -1:
+            self.notebook.AddPage(page = self.inpDbMgrData['browse'],
+                                  text=_('Input tables'), 
+                                  name = 'inputDbMgr')
+        elif not show:
+            self.notebook.RemovePage(page = 'inputDbMgr')
+
+    def _createResultDbMgrPage(self):
+        """!Tab with attribute tables of analysis result layers"""
+        self.resultDbMgrData['dbMgr'] = DbMgrBase() 
+        self.resultDbMgrData['browse'] = self.resultDbMgrData['dbMgr'].CreateDbMgrPage(parent = self.notebook,
+                                                                                       pageName = 'browse')
+        self.resultDbMgrData['browse'].SetTabAreaColour(globalvar.FNPageColor)
+
+        if  self.tmp_result:
+            self.resultDbMgrData['input'] = self.tmp_result.GetVectMapName()
+        else:
+            self.resultDbMgrData['input'] = None
+
+    def _updateResultDbMgrPage(self):
+        """!Show or Hide Result tables tab"""
+        # analysis, which created result
+        analysis = self.resultDbMgrData['analysis']
+        #TODO maybe no need to store this information, just check it has attribute table, if so show it
+        haveDbMgr = self.vnetParams[analysis]["resultProps"]["dbMgr"]
+
+        if haveDbMgr and self.notebook.GetPageIndexByName('resultDbMgr') == -1:
+            self.notebook.AddPage(page = self.resultDbMgrData['browse'],
+                                  text=_('Result tables'), 
+                                  name = 'resultDbMgr')
+        elif not haveDbMgr:
+            self.notebook.RemovePage(page = 'resultDbMgr')
+
+    def OnPageChanged(self, event):
+        """!Tab switched"""
+        if event.GetEventObject() == self.notebook:
+            dbMgrIndxs = []
+            dbMgrIndxs.append(self.notebook.GetPageIndexByName('inputDbMgr'))
+            dbMgrIndxs.append(self.notebook.GetPageIndexByName('resultDbMgr'))
+            if self.notebook.GetSelection() in dbMgrIndxs:
+                self.stBar.AddStatusItem(text = _('Loading tables...'), 
+                                         key = 'dbMgr',
+                                         priority = self.stPriorities['important'])
+                self._updateDbMgrData()
+                self.stBar.RemoveStatusItem(key = 'dbMgr')
+            # update columns (when some is added in input tables browser), TODO needs optimization  
+            elif  self.notebook.GetSelection() == self.notebook.GetPageIndexByName('parameters'):
+                self.OnALayerSel(None) 
+                self.OnNLayerSel(None)
+
+    def _updateDbMgrData(self):
+            """!Updates input/result tables page """
+            if self.notebook.GetSelection() == self.notebook.GetPageIndexByName('inputDbMgr'):
+                self._updateInputDbMgrData()
+            elif self.notebook.GetSelection() == self.notebook.GetPageIndexByName('resultDbMgr'):
+                self._updateResultDbMgrData()
+            else:
+                self.stBar.RemoveStatusItem('manager')   
+
+    def _updateInputDbMgrData(self):
+        """!Loads data according to selected layers in Parameters tab"""
+        inpSel = self.inputData['input'].GetValue().strip()
+        # changed vector map
+        if self.inpDbMgrData['input'] != inpSel:
+            wx.BeginBusyCursor()
+            self.inpDbMgrData['dbMgr'].ChangeVectorMap(vectorName = inpSel)
+            self.inpDbMgrData['input'] = inpSel
+            for layerName in ['alayer', 'nlayer']:
+                try:
+                    layer = int(self.inputData[layerName].GetValue())
+                except ValueError:
+                    continue
+                self.inpDbMgrData['browse'].AddLayer(layer)
+            wx.EndBusyCursor()
+        # same vector map
+        else:
+            needLayers = []
+            browseLayers = self.inpDbMgrData['browse'].GetAddedLayers()
+            for layerName in ['alayer', 'nlayer']:
+                try:                
+                    inpLayer = int(self.inputData[layerName].GetValue())
+                except ValueError:
+                    continue
+
+                if inpLayer in browseLayers:
+                    needLayers.append(inpLayer)
+                    continue
+                else:
+                    wx.BeginBusyCursor()
+                    self.inpDbMgrData['browse'].AddLayer(inpLayer)
+                    wx.EndBusyCursor()
+                    needLayers.append(inpLayer)
+
+            for layer in browseLayers:
+                if layer not in needLayers:
+                    self.inpDbMgrData['browse'].DeletePage(layer)
+
+    def _updateResultDbMgrData(self):
+        """!Loads data from analysis result map"""
+        if not self.tmp_result:
+            return
+        vectName = self.tmp_result.GetVectMapName()
+
+        if self.resultDbMgrData['input'] != vectName:
+            wx.BeginBusyCursor()
+            dbMgr = self.resultDbMgrData['dbMgr']
+            dbMgr.ChangeVectorMap(vectorName = vectName)
+
+            for layer in dbMgr.GetVectorLayers():
+                self.resultDbMgrData['browse'].AddLayer(layer)
+
+            self.resultDbMgrData['input'] = vectName
+            wx.EndBusyCursor()
+
+    def OnToTreeBtn(self, event):
+        """!Add vector map into layer tree"""
+        vectorMap = self.inputData['input'].GetValue()
+        vectMapName, mapSet = self._parseMapStr(vectorMap)
+        vectorMap = vectMapName + '@' + mapSet
+        existsMap = grass.find_file(name = vectMapName, 
+                                    element = 'vector', 
+                                    mapset = mapSet)
+        if not existsMap["name"]:
+            return
+
+        cmd = ['d.vect', 
+               'map=' + vectorMap]
+
+        if self.mapWin.tree.FindItemByData(key = 'name', value = vectorMap) is None: 
+            self.mapWin.tree.AddLayer(ltype = "vector", 
+                                      lcmd = cmd,
+                                      lname =vectorMap,
+                                      lchecked = True)           
+
+    def OnVectSel(self, event):
+        """!When vector map is selected it populates other comboboxes in Parameters tab (layer selects, columns selects)"""
+        if self.snapData['snap_mode']:
+            self.OnSnapping(event = None)
+
+        vectMapName, mapSet = self._parseMapStr(self.inputData['input'].GetValue())
+        vectorMap = vectMapName + '@' + mapSet
+
+        self.inputData['alayer'].Clear()
+        self.inputData['nlayer'].Clear()
+
+        self.inputData['alayer'].InsertLayers(vector = vectorMap)
+        self.inputData['nlayer'].InsertLayers(vector = vectorMap)
+
+        items = self.inputData['alayer'].GetItems()
+        itemsLen = len(items)
+        if itemsLen < 1:
+            if self.mapWin.tree:
+                self.addToTreeBtn.Disable()
+            if hasattr(self, 'inpDbMgrData'):
+                self._updateInputDbMgrPage(show = False)
+            self.inputData['alayer'].SetValue("")
+            self.inputData['nlayer'].SetValue("")
+            for sel in ['afcolumn', 'abcolumn', 'ncolumn']:
+                self.inputData[sel].Clear()
+                self.inputData[sel].SetValue("")
+            return
+        elif itemsLen == 1:
+            self.inputData['alayer'].SetSelection(0)
+            self.inputData['nlayer'].SetSelection(0)
+        elif itemsLen >= 1:
+            if unicode("1") in items:
+                iItem = items.index(unicode("1")) 
+                self.inputData['alayer'].SetSelection(iItem)
+            if unicode("2") in items:
+                iItem = items.index(unicode("2")) 
+                self.inputData['nlayer'].SetSelection(iItem)
+
+        if self.mapWin.tree:
+            self.addToTreeBtn.Enable()
+        if hasattr(self, 'inpDbMgrData'):
+            self._updateInputDbMgrPage(show = True)
+
+        self.OnALayerSel(event) 
+        self.OnNLayerSel(event)
+
+    def OnALayerSel(self, event):
+        """!When arc layer from vector map is selected, populates corespondent columns selects"""
+        self.inputData['afcolumn'].InsertColumns(vector = self.inputData['input'].GetValue(), 
+                                                 layer = self.inputData['alayer'].GetValue(), 
+                                                 type = self.columnTypes)
+        self.inputData['abcolumn'].InsertColumns(vector = self.inputData['input'].GetValue(), 
+                                                 layer = self.inputData['alayer'].GetValue(), 
+                                                 type = self.columnTypes)
+
+
+    def OnNLayerSel(self, event):
+        """!When node layer from vector map is selected, populates corespondent column select"""
+        if self.snapData['snap_mode']:
+            self.OnSnapping(event = None)
+
+        self.inputData['ncolumn'].InsertColumns(vector = self.inputData['input'].GetValue(), 
+                                                layer = self.inputData['nlayer'].GetValue(), 
+                                                type = self.columnTypes)
+ 
+    def _getInvalidInputs(self, inpToTest):
+        """!Check of analysis input data for invalid values (Parameters tab)"""
+        # dict of invalid values {key from self.itemData (comboboxes from Parameters tab) : invalid value}
+        errInput = {}
+
+        mapVal = self.inputData['input'].GetValue()
+        mapName, mapSet = self._parseMapStr(mapVal)
+        vectMaps = grass.list_grouped('vect')[mapSet]
+
+        # check of vector map
+        if not inpToTest or "input" in inpToTest:
+            if mapName not in vectMaps:
+                errInput['input'] = mapVal
+
+        # check of arc/node layer
+        for layerSelName in ['alayer', 'nlayer'] :
+            if not inpToTest or layerSelName in inpToTest:
+
+                layerItems = self.inputData[layerSelName].GetItems()
+                layerVal = self.inputData[layerSelName].GetValue().strip()
+                if layerVal not in layerItems:
+                    errInput[layerSelName] = layerVal
+
+        # check of costs columns
+        currModCols = self.vnetParams[self.currAnModule]["cmdParams"]["cols"]
+        for col, colData in self.attrCols.iteritems():
+            if not inpToTest or col in inpToTest:
+
+                if col not in currModCols:
+                    continue  
+
+                if "inputField" in self.attrCols[col]: 
+                    colInptF = self.attrCols[col]["inputField"]
+                else:
+                    colInptF = col
+
+                if not self.inputData[colInptF].IsShown():
+                    continue
+                colVal = self.inputData[colInptF].GetValue().strip()
+
+                if not colVal:
+                    continue
+                if colVal not in self.inputData[colInptF].GetItems():
+                    errInput[col] = colVal
+
+        return errInput
+
+    def _parseMapStr(self, vectMapStr):
+        """!Create full map name (add current mapset if it is not present in name)"""
+        mapValSpl = vectMapStr.strip().split("@")
+        if len(mapValSpl) > 1:
+            mapSet = mapValSpl[1]
+        else:
+            mapSet = grass.gisenv()['MAPSET']
+        mapName = mapValSpl[0] 
+        
+        return mapName, mapSet      
+
+    def InputsErrorMsgs(self, msg, inpToTest = None):
+        """!Checks input data in Parameters tab and shows messages if some value is not valid
+
+            @param msg (str) - message added to start of message string 
+            @param inpToTest (list) - list of keys from self.itemData map, which says which input data should be checked,
+                                      if is empty or None, all input data are checked
+            @return True - if checked inputs are OK
+            @return False - if some of checked inputs is not ok
+        """
+        errInput = self._getInvalidInputs(inpToTest)
+
+        errMapStr = ""
+        if errInput.has_key('input'):
+            self.notebook.SetSelectionByName("parameters")
+            if errInput['input']:
+                errMapStr = _("Vector map '%s' does not exist.") %  (errInput['input'])
+            else:
+                errMapStr = _("Vector map was not chosen.")
+
+
+        if errMapStr:
+            GMessage(parent = self,
+                     message = msg + "\n" + errMapStr)
+            return False
+
+        errLayerStr = ""
+        for layer, layerLabel in {'alayer' : _("arc layer"), 
+                                  'nlayer' : _("node layer")}.iteritems():
+
+            if  errInput.has_key(layer):
+                if errInput[layer]:
+                    errLayerStr += _("Chosen %s '%s' does not exist in vector map '%s'.\n") % \
+                                   (layerLabel, self.inputData[layer].GetValue(), self.inputData['input'].GetValue())
+                else:
+                    errLayerStr += _("Choose existing %s.\n") % \
+                                   (layerLabel)
+        if errLayerStr:
+            GMessage(parent = self,
+                     message = msg + "\n" + errLayerStr)
+            return False
+
+        errColStr = ""
+        for col, colData in self.attrCols.iteritems():
+            if col in errInput.iterkeys():
+                errColStr += _("Chosen column '%s' does not exist in attribute table of layer '%s' of vector map '%s'.\n") % \
+                             (errInput[col], self.inputData[layer].GetValue(), self.inputData['input'].GetValue())
+
+        if errColStr:
+            self.notebook.SetSelectionByName("parameters")                   
+            GMessage(parent = self,
+                     message = msg + "\n" + errColStr)
+            return False
+
+        return True
+
+    def OnCloseDialog(self, event):
+        """!Cancel dialog"""
+        self.parent.dialogs['vnet'] = None
+        self.Destroy()
+
+    def SetPointStatus(self, item, itemIndex):
+        """!Before point is drawn, decides properties of drawing style"""
+        key = self.list.GetItemData(itemIndex)
+        cats = self.vnetParams[self.currAnModule]["cmdParams"]["cats"]
+
+        if key == self.list.selected:
+            wxPen = "selected"
+        elif not self.list.IsChecked(key):
+                wxPen = "unused"
+                item.hide = False
+        elif len(cats) > 1:
+            idx = self.list.GetCellSelIdx(key, 'type') 
+            if idx == 2: #End/To/Sink point
+                wxPen = "used2cat"
+            else:
+                wxPen = "used1cat"              
+        else:
+            wxPen = "used1cat"       
+
+        item.SetPropertyVal('label', str(itemIndex + 1))
+        item.SetPropertyVal('penName', wxPen)       
+
+    def OnMapClickHandler(self, event):
+        """!Take coordinates from map window"""
+        if event == 'unregistered':
+            ptListToolbar = self.toolbars['pointsList']
+            if ptListToolbar:
+                ptListToolbar.ToggleTool( id = ptListToolbar.GetToolId("insertPoint"),
+                                          toggle = False)  
+            self.handlerRegistered = False
+            return
+
+        self.notebook.SetSelectionByName("points")
+        if not self.list.itemDataMap:
+            self.list.AddItem(None)
+
+        e, n = self.mapWin.GetLastEN()
+
+        index = self.list.selected
+        key = self.list.GetItemData(index)
+
+        if self.snapData['snap_mode']:
+            coords = [e, n]
+            if self._snapPoint(coords):
+                msg = ("snapped to node")
+            else:
+                msg = _("new point")
+
+            e = coords[0]
+            n = coords[1]
+
+        else:
+            msg = _("new point")
+
+        self.list.EditCellKey(key = self.list.selected , 
+                              colName = 'topology', 
+                              cellData = msg)
+
+        self.pointsToDraw.GetItem(key).SetCoords([e, n])
+
+        if self.list.selected == self.list.GetItemCount() - 1:
+            self.list.selected = 0
+        else:
+            self.list.selected += 1
+        self.list.Select(self.list.selected)
+
+    def _snapPoint(self, coords):
+        """!Find nearest node to click coordinates (within given threshold)"""
+        e = coords[0]
+        n = coords[1]
+
+        # compute threshold
+        snapTreshPix = int(UserSettings.Get(group ='vnet', 
+                                            key = 'other', 
+                                            subkey = 'snap_tresh'))
+        res = max(self.mapWin.Map.region['nsres'], self.mapWin.Map.region['ewres'])
+        snapTreshDist = snapTreshPix * res
+
+        vectorMap = self.inputData['input'].GetValue()
+        vectMapName, mapSet = self._parseMapStr(vectorMap)
+        inpMapExists = grass.find_file(name = vectMapName, 
+                                       element = 'vector', 
+                                       mapset = mapSet)
+        if not inpMapExists['name']:
+            return False
+
+        openedMap = pointer(vectlib.Map_info())
+        ret = vectlib.Vect_open_old2(openedMap, 
+                                     c_char_p(vectMapName),
+                                     c_char_p(mapSet),
+                                     c_char_p(self.inputData['alayer'].GetValue()))
+        if ret == 1:
+            vectlib.Vect_close(openedMap)
+        if ret != 2: 
+            return False
+
+        nodeNum =  vectlib.Vect_find_node(openedMap,     
+                                          c_double(e), 
+                                          c_double(n), 
+                                          c_double(0), 
+                                          c_double(snapTreshDist),
+                                          vectlib.WITHOUT_Z)
+
+        if nodeNum > 0:
+            e = c_double(0)
+            n = c_double(0)
+            vectlib.Vect_get_node_coor(openedMap, 
+                                       nodeNum, 
+                                       byref(e), 
+                                       byref(n), 
+                                       None); # z
+            e = e.value
+            n = n.value
+        else:
+            vectlib.Vect_close(openedMap)
+            return False
+
+        coords[0] = e
+        coords[1] = n
+        return True
+
+    def OnAnalyze(self, event):
+        """!Called when network analysis is started"""
+        # Check of parameters for analysis
+        if not self.InputsErrorMsgs(msg = _("Analysis can not be done.")):
+            return
+
+        if self.tmp_result:
+            self.tmp_result.DeleteRenderLayer()
+
+        # history - delete data in buffer for hist step  
+        self.history.DeleteNewHistStepData()
+        # empty list for maps to be saved to history
+        self.tmpVectMapsToHist= []
+        # create new map (included to history) for result of analysis
+        self.tmp_result = self.NewTmpVectMapToHist('vnet_tmp_result')
+
+        if not self.tmp_result:
+                return          
+
+        self.stBar.AddStatusItem(text = _('Analysing...'),
+                                 key = 'analyze',
+                                 priority =  self.stPriorities['important'])
+
+        # for case there is some map with same name 
+        # (when analysis does not produce any map, this map would have been shown as result) 
+        RunCommand('g.remove', 
+                    vect = self.tmp_result.GetVectMapName())
+
+        # save data from 
+        self._saveAnInputToHist()
+
+        self.resultDbMgrData['analysis'] = self.currAnModule
+
+        # Creates part of cmd fro analysis
+        cmdParams = [self.currAnModule]
+        cmdParams.extend(self._getInputParams())
+        cmdParams.append("output=" + self.tmp_result.GetVectMapName())
+
+        catPts = self._getPtByCat()
+
+        if self.currAnModule == "v.net.path":
+            self._vnetPathRunAn(cmdParams, catPts)
+        else:
+            self._runAn(cmdParams, catPts)
+
+    def _vnetPathRunAn(self, cmdParams, catPts):
+        """!Called when analysis is run for v.net.path module"""
+        if len(self.pointsToDraw.GetAllItems()) < 1:
+            return
+        cats = self.vnetParams[self.currAnModule]["cmdParams"]["cats"]
+
+        cmdPts = []
+        for cat in cats:
+            if  len(catPts[cat[0]]) < 1:
+                GMessage(parent = self,
+                         message=_("Please choose '%s' and '%s' point.") % (cats[0][1], cats[1][1]))
+                return
+            cmdPts.append(catPts[cat[0]][0])
+
+        resId = 1
+        inpPoints = str(resId) + " " + str(cmdPts[0][0]) + " " + str(cmdPts[0][1]) + \
+                                 " " + str(cmdPts[1][0]) + " " + str(cmdPts[1][1])
+
+        self.coordsTmpFile = grass.tempfile()
+        coordsTmpFileOpened = open(self.coordsTmpFile, 'w')
+        coordsTmpFileOpened.write(inpPoints)
+        coordsTmpFileOpened.close()
+
+        cmdParams.append("file=" + self.coordsTmpFile)
+
+        cmdParams.append("dmax=" + str(self.anSettings["max_dist"].GetValue()))
+        cmdParams.append("input=" + self.inputData['input'].GetValue())
+
+        cmdParams.append("--overwrite")
+        self._prepareCmd(cmd = cmdParams)
+
+        self.goutput.RunCmd(command = cmdParams, onDone = self._vnetPathRunAnDone)
+
+    def _vnetPathRunAnDone(self, cmd, returncode):
+        """!Called when v.net.path analysis is done"""
+        grass.try_remove(self.coordsTmpFile)
+
+        self._saveHistStep()
+        self.tmp_result.SaveVectMapState()
+
+        self._updateResultDbMgrPage()
+        self._updateDbMgrData()
+
+        cmd = self.GetLayerStyle()
+        self.tmp_result.AddRenderLayer(cmd)
+        self.mapWin.UpdateMap(render=True, renderVector=True)
+        mainToolbar = self.toolbars['mainToolbar']
+        id = vars(mainToolbar)['showResult']
+        mainToolbar.ToggleTool(id =id,
+                               toggle = True)
+
+        self.stBar.RemoveStatusItem(key = 'analyze')
+
+    def _runAn(self, cmdParams, catPts):
+        """!Called for all v.net.* analysis (except v.net.path)"""
+
+        cats = self.vnetParams[self.currAnModule]["cmdParams"]["cats"]
+
+        if len(cats) > 1:
+            for cat in cats:
+                if  len(catPts[cat[0]]) < 1:
+                    GMessage(parent = self, 
+                            message = _("Please choose '%s' and '%s' point.") \
+                                        % (cats[0][1], cats[1][1]))
+                    return
+        else:
+            for cat in cats:
+                if  len(catPts[cat[0]]) < 2:
+                    GMessage(parent = self, 
+                             message = _("Please choose at least two points."))
+                    return        
+
+        # TODO add also to thread for analysis?
+        vcatResult = RunCommand("v.category",
+                           input = self.inputData['input'].GetValue(),
+                           option = "report",
+                           flags = "g",
+                           read = True)     
+
+        vcatResult = vcatResult.splitlines()
+        for cat in vcatResult:#TODO
+            cat = cat.split()
+            if "all" in cat:
+                maxCat = int(cat[4])
+                break
+
+        layerNum = self.inputData["nlayer"].GetValue().strip()
+
+        pt_ascii, catsNums = self._getAsciiPts (catPts = catPts, 
+                                                maxCat = maxCat, 
+                                                layerNum = layerNum)
+
+        self.tmpPtsAsciiFile = grass.tempfile()#TODO better tmp files cleanup (make class for managing tmp files)
+        tmpPtsAsciiFileOpened = open(self.tmpPtsAsciiFile, 'w')
+        tmpPtsAsciiFileOpened.write(pt_ascii)
+        tmpPtsAsciiFileOpened.close()
+
+        self.tmpInPts = self._addTmpMapAnalysisMsg("vnet_tmp_in_pts")
+        if not self.tmpInPts:
+            return
+
+        self.tmpInPtsConnected = self._addTmpMapAnalysisMsg("vnet_tmp_in_pts_connected")
+        if not self.tmpInPtsConnected:
+            return
+
+        cmdParams.append("input=" + self.tmpInPtsConnected.GetVectMapName())
+        cmdParams.append("--overwrite")  
+
+        # append parameters needed for particular analysis
+        if self.currAnModule == "v.net.distance":
+            cmdParams.append("from_layer=1")
+            cmdParams.append("to_layer=1")
+        elif self.currAnModule == "v.net.flow":
+            self.vnetFlowTmpCut = self.NewTmpVectMapToHist('vnet_tmp_flow_cut')
+            if not self.vnetFlowTmpCut:
+                return          
+            cmdParams.append("cut=" +  self.vnetFlowTmpCut.GetVectMapName())         
+        elif self.currAnModule == "v.net.iso":
+            costs = self.anSettings["iso_lines"].GetValue()
+            cmdParams.append("costs=" + costs)          
+        for catName, catNum in catsNums.iteritems():
+            if catNum[0] == catNum[1]:
+                cmdParams.append(catName + "=" + str(catNum[0]))
+            else:
+                cmdParams.append(catName + "=" + str(catNum[0]) + "-" + str(catNum[1]))
+
+        # create and run commands which goes to analysis thread
+        cmdVEdit = [ 
+                    "v.edit",
+                    "map=" + self.tmpInPts.GetVectMapName(), 
+                    "input=" + self.tmpPtsAsciiFile,
+                    "tool=create",
+                    "--overwrite", 
+                    "-n"                              
+                   ]
+        self._prepareCmd(cmdVEdit)
+        self.goutput.RunCmd(command = cmdVEdit)
+
+        cmdVNet = [
+                    "v.net",
+                    "points=" + self.tmpInPts.GetVectMapName(), 
+                    "input=" + self.inputData['input'].GetValue(),
+                    "output=" + self.tmpInPtsConnected.GetVectMapName(),
+                    "alayer=" +  self.inputData["alayer"].GetValue().strip(),
+                    "nlayer=" +  self.inputData["nlayer"].GetValue().strip(), 
+                    "operation=connect",
+                    "thresh=" + str(self.anSettings["max_dist"].GetValue()),             
+                    "--overwrite"                         
+                  ] #TODO snapping to nodes optimization
+        self._prepareCmd(cmdVNet)
+        self.goutput.RunCmd(command = cmdVNet)
+
+        self._prepareCmd(cmdParams)
+        self.goutput.RunCmd(command = cmdParams, onDone = self._runAnDone)
+
+    def _runAnDone(self, cmd, returncode):
+        """!Called when analysis is done"""
+        self.tmpMaps.DeleteTmpMap(self.tmpInPts) #TODO remove earlier (OnDone lambda?)
+        self.tmpMaps.DeleteTmpMap(self.tmpInPtsConnected)
+        grass.try_remove(self.tmpPtsAsciiFile)
+
+        self._saveHistStep()
+        self.tmp_result.SaveVectMapState()
+        if self.currAnModule == "v.net.flow":
+            self.vnetFlowTmpCut.SaveVectMapState()
+        self._updateResultDbMgrPage()
+        self._updateDbMgrData()
+
+        cmd = self.GetLayerStyle()
+        self.tmp_result.AddRenderLayer(cmd)
+        self.mapWin.UpdateMap(render=True, renderVector=True)
+        mainToolbar = self.toolbars['mainToolbar']
+        id = vars(mainToolbar)['showResult']
+        mainToolbar.ToggleTool(id =id,
+                               toggle = True)
+
+        self.stBar.RemoveStatusItem(key = 'analyze')
+
+    def _getInputParams(self):
+        """!Return list of chosen values (vector map, layers) from Parameters tab. 
+
+        The list items are in form to be used in command for analysis e.g. 'alayer=1'.    
+        """
+
+        inParams = []
+        for col in self.vnetParams[self.currAnModule]["cmdParams"]["cols"]:
+
+            if "inputField" in self.attrCols[col]:
+                colInptF = self.attrCols[col]["inputField"]
+            else:
+                colInptF = col
+
+            inParams.append(col + '=' + self.inputData[colInptF].GetValue())
+
+        for layer in ['alayer', 'nlayer']:
+            inParams.append(layer + "=" + self.inputData[layer].GetValue().strip())
+
+        return inParams
+
+    def _getPtByCat(self):
+        """!Return points separated by theirs categories"""
+        cats = self.vnetParams[self.currAnModule]["cmdParams"]["cats"]
+
+        ptByCats = {}
+        for cat in self.vnetParams[self.currAnModule]["cmdParams"]["cats"]:
+            ptByCats[cat[0]] = []
+ 
+        for i in range(len(self.list.itemDataMap)):
+            key = self.list.GetItemData(i)
+            if self.list.IsChecked(key):
+                for cat in cats:
+                    if cat[1] == self.list.itemDataMap[key][1] or len(ptByCats) == 1: 
+                        ptByCats[cat[0]].append(self.pointsToDraw.GetItem(key).GetCoords())
+                        continue
+
+        return ptByCats
+
+    def _getAsciiPts (self, catPts, maxCat, layerNum):
+        """!Return points separated by categories in GRASS ASCII vector representation"""
+        catsNums = {}
+        pt_ascii = ""
+        catNum = maxCat
+
+        for catName, pts in catPts.iteritems():
+
+            catsNums[catName] = [catNum + 1]
+            for pt in pts:
+                catNum += 1
+                pt_ascii += "P 1 1\n"
+                pt_ascii += str(pt[0]) + " " + str(pt[1]) +  "\n"
+                pt_ascii += str(layerNum) + " " + str(catNum) + "\n"
+
+            catsNums[catName].append(catNum)
+
+        return pt_ascii, catsNums
+
+    def _prepareCmd(self, cmd):
+        """!Helper function for preparation of cmd list into form for RunCmd method"""
+        for c in cmd[:]:
+            if c.find("=") == -1:
+                continue
+            v = c.split("=")
+            if len(v) != 2:
+                cmd.remove(c)
+            elif not v[1].strip():
+                cmd.remove(c)
+
+    def GetLayerStyle(self):
+        """!Returns cmd for d.vect, with set style for analysis result"""
+        resProps = self.vnetParams[self.currAnModule]["resultProps"]
+
+        width = UserSettings.Get(group='vnet', key='res_style', subkey= "line_width")
+        layerStyleCmd = ["layer=1",'width=' + str(width)]
+
+        if "catColor" in resProps:
+            layerStyleCmd.append('flags=c')
+        elif "singleColor" in resProps:
+            col = UserSettings.Get(group='vnet', key='res_style', subkey= "line_color")
+            layerStyleCmd.append('color=' + str(col[0]) + ':' + str(col[1]) + ':' + str(col[2]))        
+
+        if "attrColColor" in resProps:
+            colorStyle = UserSettings.Get(group='vnet', key='res_style', subkey= "color_table")
+            invert = UserSettings.Get(group='vnet', key='res_style', subkey= "invert_colors")
+
+            layerStyleVnetColors = [
+                                    "v.colors",
+                                    "map=" + self.tmp_result.GetVectMapName(),
+                                    "color=" + colorStyle,
+                                    "column=" + resProps["attrColColor"],
+                                   ]
+            if invert:
+                layerStyleVnetColors.append("-n")
+
+            layerStyleVnetColors  = utils.CmdToTuple(layerStyleVnetColors)
+
+            RunCommand( layerStyleVnetColors[0],
+                        **layerStyleVnetColors[1])
+
+        return layerStyleCmd 
+
+    def OnShowResult(self, event):
+        """!Show/hide analysis result"""
+        mainToolbar = self.toolbars['mainToolbar']
+        id = vars(mainToolbar)['showResult']
+        toggleState = mainToolbar.GetToolState(id)
+
+        if not self.tmp_result:
+            mainToolbar.ToggleTool(id =id,
+                                   toggle = False)
+        elif toggleState:
+            self._checkResultMapChanged(self.tmp_result)
+            cmd = self.GetLayerStyle()
+            self.tmp_result.AddRenderLayer(cmd)
+        else:
+            cmd = self.GetLayerStyle()
+            self.tmp_result.DeleteRenderLayer()
+
+        self.mapWin.UpdateMap(render=True, renderVector=True)
+
+    def OnInsertPoint(self, event):
+        """!Registers/unregisters mouse handler into map window"""
+        if self.handlerRegistered == False:
+            self.mapWin.RegisterMouseEventHandler(wx.EVT_LEFT_DOWN, 
+                                                  self.OnMapClickHandler,
+                                                  wx.StockCursor(wx.CURSOR_CROSS))
+            self.handlerRegistered = True
+        else:
+            self.mapWin.UnregisterMouseEventHandler(wx.EVT_LEFT_DOWN, 
+                                                  self.OnMapClickHandler)
+            self.handlerRegistered = False
+
+    def OnSaveTmpLayer(self, event):
+        """!Permanently saves temporary map of analysis result"""
+        dlg = AddLayerDialog(parent = self)
+
+        msg = _("Vector map with analysis result does not exist.")
+        if dlg.ShowModal() == wx.ID_OK: 
+
+            if not hasattr(self.tmp_result, "GetVectMapName"):
+                GMessage(parent = self,
+                         message = msg)
+                return
+
+            mapToAdd = self.tmp_result.GetVectMapName()
+            mapToAddEx = grass.find_file(name = mapToAdd, 
+                                        element = 'vector', 
+                                        mapset = grass.gisenv()['MAPSET'])
+
+            if not mapToAddEx["name"]: 
+                GMessage(parent = self,
+                         message = msg)
+                dlg.Destroy()
+                return
+
+            addedMap = dlg.vectSel.GetValue()
+            mapName, mapSet = self._parseMapStr(addedMap)
+            if mapSet !=  grass.gisenv()['MAPSET']:
+                GMessage(parent = self,
+                         message = _("Map can be saved only to currently set mapset"))
+                return
+            existsMap = grass.find_file(name = mapName, 
+                                        element = 'vector', 
+                                        mapset = grass.gisenv()['MAPSET'])
+            dlg.Destroy()
+            if existsMap["name"]:
+                dlg = wx.MessageDialog(parent = self.parent.parent,
+                                       message = _("Vector map %s already exists. " +
+                                                "Do you want to overwrite it?") % 
+                                                (existsMap["fullname"]),
+                                       caption = _("Overwrite map layer"),
+                                       style = wx.YES_NO | wx.NO_DEFAULT |
+                                               wx.ICON_QUESTION | wx.CENTRE)            
+                ret = dlg.ShowModal()
+                if ret == wx.ID_NO:
+                    dlg.Destroy()
+                    return
+                dlg.Destroy()
+
+            RunCommand("g.copy",
+                       overwrite = True,
+                       vect = [self.tmp_result.GetVectMapName(), mapName])
+
+            cmd = self.GetLayerStyle()#TODO get rid of insert
+            cmd.insert(0, 'd.vect')
+            cmd.append('map=%s' % mapName)
+
+            if not self.mapWin.tree:
+                return
+
+            if  self.mapWin.tree.FindItemByData(key = 'name', value = mapName) is None: 
+                self.mapWin.tree.AddLayer(ltype = "vector", 
+                                          lname = mapName,
+                                          lcmd = cmd,
+                                          lchecked = True)
+            else:
+                self.mapWin.UpdateMap(render=True, renderVector=True) 
+
+    def OnSettings(self, event):
+        """!Displays vnet settings dialog"""
+        dlg = SettingsDialog(parent=self, id=wx.ID_ANY, title=_('Settings'))
+        
+        if dlg.ShowModal() == wx.ID_OK:
+            pass
+        
+        dlg.Destroy()
+
+    def OnAnalysisChanged(self, event):
+        """!Updates dialog when analysis is changed"""
+        # set chosen analysis
+        iAn = self.toolbars['analysisToolbar'].anChoice.GetSelection() 
+        self.currAnModule = self.vnetModulesOrder[iAn]
+
+        # update dialog for particular analysis
+        if self.currAnModule == "v.net.iso":
+            self.anSettings['iso_lines'].GetParent().Show()
+        else:
+            self.anSettings['iso_lines'].GetParent().Hide()
+
+        #if self.currAnModule == "v.net.flow": TODO not implemented
+        #    self.anSettings['show_cut'].GetParent().Show()
+        #else:
+        #    self.anSettings['show_cut'].GetParent().Hide()
+
+        # show only corresponding selects for chosen v.net module
+        skip = []
+        for col in self.attrCols.iterkeys():
+            if "inputField" in self.attrCols[col]:
+                colInptF = self.attrCols[col]["inputField"]
+            else:
+                colInptF = col
+
+            if col in skip:
+                continue
+
+            inputPanel = self.inputData[colInptF].GetParent()
+            if col in self.vnetParams[self.currAnModule]["cmdParams"]["cols"]:
+                inputPanel.Show()
+                inputPanel.FindWindowByName(colInptF).SetLabel(self.attrCols[col]["label"])
+                inputPanel.Layout()
+                if col != colInptF:
+                    skip.append(colInptF)
+            else:
+                self.inputData[colInptF].GetParent().Hide()
+        self.Layout()
+
+        # if module has only one category -> hide type column in points list otherwise show it
+        if len(self.vnetParams[self.currAnModule]["cmdParams"]["cats"]) > 1:
+            if not self.list.IsShown('type'):
+                self.list.ShowColumn('type', 1)
+
+            currParamsCats = self.vnetParams[self.currAnModule]["cmdParams"]["cats"]
+            self.list.AdaptPointsList(currParamsCats)
+        else:
+            if self.list.IsShown('type'):
+                self.list.HideColumn('type')
+
+        # for v.net.path just one 'Start point' and one 'End point' can be checked
+        if self.currAnModule == "v.net.path":
+            self.list.UpdateCheckedItems(index = None)
+
+    def OnSnapping(self, event):
+        """!Start/stop snapping mode"""
+        ptListToolbar = self.toolbars['pointsList']
+
+        if not haveCtypes:
+            ptListToolbar.ToggleTool(id = ptListToolbar.GetToolId("snapping"),
+                                     toggle = False)
+            GMessage(parent = self,
+                     message = _("Unable to use ctypes. \n") + \
+                               _("Snapping mode can not be activated."))
+            return
+
+        if not event or not event.IsChecked():
+            if not event: 
+                ptListToolbar.ToggleTool(id = ptListToolbar.GetToolId("snapping"),
+                                         toggle = False)
+            if self.tmpMaps.HasTmpVectMap("vnet_snap_points"):
+                self.snapPts.DeleteRenderLayer() 
+                self.mapWin.UpdateMap(render = False, renderVector = False)
+
+            if self.snapData.has_key('cmdThread'):
+                self.snapData['cmdThread'].abort()
+
+            self.snapData['snap_mode'] = False
+            return  
+
+        if not self.InputsErrorMsgs(msg = _("Snapping mode can not be activated."),
+                                    inpToTest = ["input", "nlayer"]):
+
+            ptListToolbar.ToggleTool(id = ptListToolbar.GetToolId("snapping"),
+                                     toggle = False)
+            return
+
+        if not self.tmpMaps.HasTmpVectMap("vnet_snap_points"):
+            endStr = _("Do you really want to activate snapping and overwrite it?")
+            self.snapPts = self.tmpMaps.AddTmpVectMap("vnet_snap_points", endStr)
+
+            if not self.snapPts:
+                ptListToolbar.ToggleTool(id = ptListToolbar.GetToolId("snapping"),
+                                         toggle = False)
+                return   
+        elif self.snapPts.VectMapState() == 0:
+                dlg = wx.MessageDialog(parent = self.parent,
+                                       message = _("Temporary map '%s' was changed outside " +
+                                                    "vector analysis tool.\n" 
+                                                    "Do you really want to activate " + 
+                                                    "snapping and overwrite it? ") % \
+                                                    self.snapPts.GetVectMapName(),
+                                        caption = _("Overwrite map"),
+                                        style = wx.YES_NO | wx.NO_DEFAULT |
+                                                wx.ICON_QUESTION | wx.CENTRE)
+
+                ret = dlg.ShowModal()
+                dlg.Destroy()
+                
+                if ret == wx.ID_NO:
+                    self.tmpMaps.DeleteTmpMap(self.snapPts)
+                    ptListToolbar.ToggleTool(id = ptListToolbar.GetToolId("snapping"),
+                                             toggle = False)
+                    return
+
+        self.snapData['snap_mode'] = True
+
+        inpName = self.inputData['input'].GetValue()
+        inpName, mapSet = self._parseMapStr(inpName)
+        inpFullName = inpName + '@' + mapSet
+        computeNodes = True
+
+        if not self.snapData.has_key("inputMap"):
+            pass
+        elif inpFullName != self.snapData["inputMap"].GetVectMapName():
+            self.snapData["inputMap"] = VectMap(self, inpFullName)
+        elif self.snapData["inputMapNlayer"] == self.inputData["nlayer"].GetValue():
+            if self.snapData["inputMap"].VectMapState() == 1:
+                computeNodes = False
+    
+        # new map need
+        if computeNodes:
+            self.stBar.AddStatusItem(text = _('Computing nodes...'),
+                                     key = 'snap',
+                                     priority = self.stPriorities['important'])
+            if not self.snapData.has_key('cmdThread'):
+                self.snapData['cmdThread'] = CmdThread(self)
+
+            cmd = ["v.to.points", "input=" + self.inputData['input'].GetValue(), 
+                                  "output=" + self.snapPts.GetVectMapName(),
+                                  "llayer=" + self.inputData["nlayer"].GetValue(),
+                                  "-n", "--overwrite"]
+            # process GRASS command with argument
+            self.snapData["inputMap"] = VectMap(self, inpFullName)
+            self.snapData["inputMap"].SaveVectMapState()
+
+            self.Bind(EVT_CMD_DONE, self._onToPointsDone)
+            self.snapData['cmdThread'].RunCmd(cmd)
+
+            self.snapData["inputMapNlayer"] = self.inputData["nlayer"].GetValue()
+        # map is already created and up to date for input data
+        else:
+            self.snapPts.AddRenderLayer()           
+            self.mapWin.UpdateMap(render = True, renderVector = True)
+        
+
+    def _onToPointsDone(self, event):
+        """!Update map window, when map with nodes to snap is created"""
+        self.stBar.RemoveStatusItem(key = 'snap')
+        if not event.aborted:
+            self.snapPts.SaveVectMapState()
+            self.snapPts.AddRenderLayer() 
+            self.mapWin.UpdateMap(render = True, renderVector = True)
+
+    def OnUndo(self, event):
+        """!Step back in history"""
+        histStepData = self.history.GetPrev()
+        self.toolbars['mainToolbar'].UpdateUndoRedo()
+
+        if histStepData:
+            self._updateHistStepData(histStepData)
+
+    def OnRedo(self, event):
+        """!Step forward in history"""
+        histStepData = self.history.GetNext()
+        self.toolbars['mainToolbar'].UpdateUndoRedo()
+
+        if histStepData:
+            self._updateHistStepData(histStepData)
+
+    def _saveAnInputToHist(self):
+        """!Save all data needed for analysis into history buffer"""
+        pts = self.pointsToDraw.GetAllItems()
+
+        for iPt, pt in enumerate(pts):
+            ptName = "pt" + str(iPt)
+
+            coords = pt.GetCoords()
+            self.history.Add(key = "points", 
+                             subkey = [ptName, "coords"], 
+                             value = coords)
+            # save type column
+            # if is shown
+            if  len(self.vnetParams[self.currAnModule]["cmdParams"]["cats"]) > 1:
+                cat = self.list.GetCellSelIdx(iPt, 'type')
+                self.history.Add(key = "points", 
+                                 subkey = [ptName, "catIdx"], 
+                                 value = cat)
+            # if is hidden
+            else:
+                self.history.Add(key = 'points_hidden_cols', 
+                                 subkey = 'type', 
+                                 value = self.list.GetHiddenColSelIdxs('type'))
+
+            topology = self.list.GetCellValue(iPt, 'topology')
+            self.history.Add(key = "points", 
+                             subkey = [ptName, "topology"], 
+                             value = topology)
+
+
+            self.history.Add(key = "points", 
+                             subkey = [ptName, "checked"], 
+                             value = self.list.IsChecked(iPt))
+
+            for inpName, inp in self.inputData.iteritems():
+
+                if inpName == "input":
+                    vectMapName, mapSet = self._parseMapStr(inp.GetValue())
+                    inpMapFullName = vectMapName + '@' + mapSet
+                    inpMap = VectMap(self, inpMapFullName)
+                    self.history.Add(key = "other", 
+                                     subkey = "input_modified", 
+                                     value = inpMap.GetLastModified())  
+                    inpVal =  inpMapFullName
+                else:
+                    inpVal =  inp.GetValue()
+                 
+                self.history.Add(key = "input_data", 
+                                 subkey = inpName, 
+                                 value = inpVal)
+            
+        self.history.Add(key = "vnet_modules", 
+                         subkey = "curr_module", 
+                         value = self.currAnModule)
+
+        for settName, sett in self.anSettings.iteritems():
+            self.history.Add(key = "an_settings", 
+                             subkey = settName, 
+                             value = sett.GetValue())
+
+
+    def _saveHistStep(self):
+        """!Save new step into history"""
+        removedHistData = self.history.SaveHistStep()
+        self.toolbars['mainToolbar'].UpdateUndoRedo()
+
+        if not removedHistData:
+            return
+
+        # delete temporary maps in history steps which were deleted 
+        for removedStep in removedHistData.itervalues():
+            mapsNames = removedStep["tmp_data"]["maps"]
+            for vectMapName in mapsNames:
+                tmpMap = self.tmpMaps.GetTmpVectMap(vectMapName)
+                self.tmpMaps.DeleteTmpMap(tmpMap)
+
+    def _updateHistStepData(self, histStepData):
+        """!Updates dialog according to chosen history step"""
+
+        # set analysis module
+        self.currAnModule = histStepData["vnet_modules"]["curr_module"]
+
+        # optimization -map is not re-rendered when change in points list is done
+        self.list.SetUpdateMap(updateMap = False)
+
+        # delete points list items
+        while self.list.GetSelected() != wx.NOT_FOUND:
+            self.list.DeleteItem()
+
+        # show/hide 'type' column according to particular analysis
+        if  len(self.vnetParams[self.currAnModule]["cmdParams"]["cats"]) > 1:
+            hasType = True
+            self.list.ShowColumn('type', 1)
+        else:
+            hasType = False
+            self.list.HideColumn('type')
+
+        # add points to list
+        for iPt in range(len(histStepData["points"])):
+            ptData = histStepData["points"]["pt" + str(iPt)]
+            coords = ptData["coords"]
+            self.list.AddItem()
+            item = self.pointsToDraw.GetItem(iPt)
+            item.SetCoords(coords)
+
+            if hasType:
+                self.list.EditCellKey(iPt, 'type', int(ptData["catIdx"]))
+
+            self.list.EditCellKey(iPt, 'topology', ptData["topology"])           
+
+            if ptData["checked"]:
+                self.list.CheckItem(iPt, True)
+
+        if hasType:
+            currParamsCats = self.vnetParams[self.currAnModule]["cmdParams"]["cats"]
+            self.list.AdaptPointsList(currParamsCats)
+        else:
+            self.list.SetHiddenSelIdxs('type', histStepData["points_hidden_cols"]["type"])
+
+        # set analysis combobox
+        anChoice = self.toolbars['analysisToolbar'].anChoice
+        anChoice.SetSelection(self.vnetModulesOrder.index(self.currAnModule)) 
+
+        # update analysis result maps 
+        mapsNames = histStepData["tmp_data"]["maps"]
+        for vectMapName in mapsNames:
+            if "vnet_tmp_result" in vectMapName:
+                self.tmp_result.DeleteRenderLayer()
+                self.tmp_result  = self.tmpMaps.GetTmpVectMap(vectMapName)
+                self._checkResultMapChanged(self.tmp_result)
+
+                cmd = self.GetLayerStyle()
+                self.tmp_result.AddRenderLayer(cmd)
+
+        # update Parameters tab
+        histInputData = histStepData["input_data"]
+        for inpName, inp in histInputData.iteritems():
+            self.inputData[inpName].SetValue(str(inp)) 
+            if inpName == "input":
+                inpMap = inp
+
+        prevInpModTime = str(histStepData["other"]["input_modified"])
+        currInpModTime = VectMap(self, inpMap).GetLastModified()
+
+        if currInpModTime.strip()!= prevInpModTime.strip():
+            dlg = wx.MessageDialog(parent = self,
+                                   message = _("Input map '%s' for analysis was changed outside " + 
+                                               "vector network analysis tool.\n" +
+                                               "Topology column may not " +
+                                               "correspond to changed situation.") %\
+                                                inpMap,
+                                   caption = _("Input changed outside"),
+                                   style =  wx.ICON_INFORMATION| wx.CENTRE)
+            dlg.ShowModal()
+            dlg.Destroy()
+
+        # update Points tab (analysis settings)
+        histAnSettData = histStepData["an_settings"]
+        for settName, sett in histAnSettData.iteritems():
+            if settName == 'iso_lines':
+                sett = str(sett)
+            self.anSettings[settName].SetValue(sett) 
+
+        self.resultDbMgrData['analysis'] = self.currAnModule
+        self._updateResultDbMgrPage()
+        self._updateDbMgrData()
+
+        self.OnAnalysisChanged(None)
+        self.list.SetUpdateMap(updateMap = True)
+        self.mapWin.UpdateMap(render=True, renderVector=True)
+
+    def _checkResultMapChanged(self, resultVectMap):
+        """!Check if map was modified outside"""
+        if resultVectMap.VectMapState() == 0:
+            dlg = wx.MessageDialog(parent = self,
+                                   message = _("Temporary map '%s' with result " + 
+                                               "was changed outside vector network analysis tool.\n" +
+                                               "Showed result may not correspond " +
+                                               "original analysis result.") %\
+                                               resultVectMap.GetVectMapName(),
+                                   caption = _("Result changed outside"),
+                                   style =  wx.ICON_INFORMATION| wx.CENTRE)
+            dlg.ShowModal()
+            dlg.Destroy()
+
+    def NewTmpVectMapToHist(self, prefMapName):
+        """!Add new vector map, which will be saved into history step"""
+
+        mapName = prefMapName + str(self.histTmpVectMapNum)
+        self.histTmpVectMapNum += 1
+
+        tmpMap = self._addTmpMapAnalysisMsg(mapName)
+        if not tmpMap:
+            return tmpMap
+           
+        self.tmpVectMapsToHist.append(tmpMap.GetVectMapName())
+        self.history.Add(key = "tmp_data", 
+                         subkey = "maps",
+                         value = self.tmpVectMapsToHist)
+
+        return tmpMap
+
+    def _addTmpMapAnalysisMsg(self, mapName):
+        """!Wraped AddTmpVectMap"""
+        msg = _("Temporary map %s  already exists.\n"  + 
+                "Do you want to continue in analysis and overwrite it?") \
+                 % (mapName +'@' + grass.gisenv()['MAPSET'])
+        tmpMap = self.tmpMaps.AddTmpVectMap(mapName, msg)
+        return tmpMap
+
+
+    def _initVnetParams(self):
+        """!Initializes parameters for different v.net.* modules """
+
+        self.attrCols = {
+                          'afcolumn' : {
+                                        "label" : _("Arc forward/both direction(s) cost column:"),
+                                        "name" : _("arc forward/both")
+                                       },
+                          'abcolumn' : {
+                                        "label" : _("Arc backward direction cost column:"),
+                                        "name" : _("arc backward")
+                                       },
+                          'acolumn' : {
+                                       "label" : _("Arcs' cost column (for both directions):"),
+                                       "name" : _("arc"),
+                                       "inputField" : 'afcolumn',
+                                      },
+                          'ncolumn' : {
+                                       "label" : _("Node cost column:"),
+                                        "name" : _("node")                                      
+                                      }
+                        }
+
+        self.vnetParams = {
+                                   "v.net.path" : {
+                                                     "label" : _("Shortest path %s") % "(v.net.path)",  
+                                                     "cmdParams" : {
+                                                                      "cats" :  [
+                                                                                    ["st_pt", _("Start point")], 
+                                                                                    ["end_pt", _("End point")] 
+                                                                                ],
+                                                                      "cols" :  [
+                                                                                 'afcolumn',
+                                                                                 'abcolumn',
+                                                                                 'ncolumn'
+                                                                                ],
+                                                                   },
+                                                     "resultProps" : {
+                                                                      "singleColor" : None,
+                                                                      "dbMgr" : True  
+                                                                     }
+                                                  },
+
+                                    "v.net.salesman" : {
+                                                        "label" : _("Traveling salesman %s") % "(v.net.salesman)",  
+                                                        "cmdParams" : {
+                                                                        "cats" : [["ccats", None]],
+                                                                        "cols" : [
+                                                                                  'afcolumn',
+                                                                                  'abcolumn'
+                                                                                 ],
+                                                                      },
+                                                        "resultProps" : {
+                                                                         "singleColor" : None,
+                                                                         "dbMgr" : False
+                                                                        }
+                                                       },
+                                    "v.net.flow" : {
+                                                     "label" : _("Maximum flow %s") % "(v.net.flow)",  
+                                                     "cmdParams" : {
+                                                                      "cats" : [
+                                                                                ["source_cats", _("Source point")], 
+                                                                                ["sink_cats", _("Sink point")]
+                                                                               ],                                                   
+                                                                      "cols" : [
+                                                                                'afcolumn',
+                                                                                'abcolumn',
+                                                                                'ncolumn'
+                                                                               ]
+                                                                  },
+                                                     "resultProps" : {
+                                                                      "attrColColor": "flow",
+                                                                      "dbMgr" : True
+                                                                     }
+                                                   },
+                                    "v.net.alloc" : {
+                                                     "label" : _("Subnets for nearest centers %s") % "(v.net.alloc)",  
+                                                     "cmdParams" : {
+                                                                      "cats" : [["ccats", None]],                           
+                                                                      "cols" : [
+                                                                                 'afcolumn',
+                                                                                 'abcolumn',
+                                                                                 'ncolumn'
+                                                                               ]
+                                                                  },
+                                                     "resultProps" :  {
+                                                                       "catColor" : None, 
+                                                                       "dbMgr" : False
+                                                                      }
+                                                   },
+                                    "v.net.steiner" : {
+                                                     "label" : _("Steiner tree for the network and given terminals %s") % "(v.net.steiner)",  
+                                                     "cmdParams" : {
+                                                                      "cats" : [["tcats", None]],                           
+                                                                      "cols" : [
+                                                                                 'acolumn',
+                                                                               ]
+                                                                  },
+                                                     "resultProps" : {
+                                                                      "singleColor" : None,
+                                                                      "dbMgr" : False 
+                                                                     }
+                                                   },
+                                   "v.net.distance" : {
+                                                       "label" : _("Shortest distance via the network %s") % "(v.net.distance)",  
+                                                       "cmdParams" : {
+                                                                        "cats" : [
+                                                                                  ["from_cats", "From point"],
+                                                                                  ["to_cats", "To point"]
+                                                                                 ],
+                                                                        "cols" : [
+                                                                                  'afcolumn',
+                                                                                  'abcolumn',
+                                                                                  'ncolumn'
+                                                                                 ],
+                                                                  },
+                                                      "resultProps" : {
+                                                                        "catColor" : None,
+                                                                        "dbMgr" : True
+                                                                      }
+                                                     },
+                                    "v.net.iso" :  {
+                                                     "label" : _("Cost isolines %s") % "(v.net.iso)",  
+                                                     "cmdParams" : {
+                                                                      "cats" : [["ccats", None]],                           
+                                                                      "cols" : [
+                                                                                 'afcolumn',
+                                                                                 'abcolumn',
+                                                                                 'ncolumn'
+                                                                               ]
+                                                                  },
+                                                     "resultProps" : {
+                                                                      "catColor" : None,
+                                                                      "dbMgr" : False
+                                                                     }
+                                                   }
+                                }
+        # order in combobox for choose of analysis
+        self.vnetModulesOrder = ["v.net.path", 
+                                 "v.net.salesman",
+                                 "v.net.flow",
+                                 "v.net.alloc",
+                                 "v.net.distance",
+                                 "v.net.iso",
+                                 #"v.net.steiner"
+                                 ] 
+        self.currAnModule = self.vnetModulesOrder[0]
+
+    def _initSettings(self):
+        """!Initialization of settings (if not already defined)"""
+        # initializes default settings
+        initSettings = [
+                        ['res_style', 'line_width', 5],
+                        ['res_style', 'line_color', (192,0,0)],
+                        ['res_style', 'color_table', 'byr'],
+                        ['res_style', 'invert_colors', False],
+                        ['point_symbol', 'point_size', 10],             
+                        ['point_symbol', 'point_width', 2],
+                        ['point_colors', "unused", (131,139,139)],
+                        ['point_colors', "used1cat", (192,0,0)],
+                        ['point_colors', "used2cat", (0,0,255)],
+                        ['point_colors', "selected", (9,249,17)],
+                        ['other', "snap_tresh", 10],
+                        ['other', "max_hist_steps", 5]
+                       ]
+
+        for init in initSettings: 
+            UserSettings.ReadSettingsFile()
+            UserSettings.Append(dict = UserSettings.userSettings, 
+                                    group ='vnet',
+                                    key = init[0],
+                                    subkey =init[1],
+                                    value = init[2],
+                                    overwrite = False)
+
+
+    def SetPointDrawSettings(self):
+        """!Set settings for drawing of points"""
+        ptSize = int(UserSettings.Get(group='vnet', key='point_symbol', subkey = 'point_size'))
+        self.pointsToDraw.SetPropertyVal("size", ptSize)
+
+        colors = UserSettings.Get(group='vnet', key='point_colors')
+        ptWidth = int(UserSettings.Get(group='vnet', key='point_symbol', subkey = 'point_width'))
+
+        textProp = self.pointsToDraw.GetPropertyVal("text")
+        textProp["font"].SetPointSize(ptSize + 2)
+    
+        for colKey, col in colors.iteritems():
+            pen = self.pointsToDraw.GetPen(colKey)
+            if pen:
+                pen.SetColour(wx.Colour(col[0], col[1], col[2], 255))
+                pen.SetWidth(ptWidth)
+            else:
+                self.pointsToDraw.AddPen(colKey, wx.Pen(colour = wx.Colour(col[0], col[1], col[2], 255), width = ptWidth))
+
+class PtsList(PointsList):
+    def __init__(self, parent, dialog, cols, id=wx.ID_ANY):
+        """! List with points for analysis"""
+        self.updateMap = True
+        self.dialog = dialog # VNETDialog class
+
+        PointsList.__init__(self, parent = parent, cols = cols, id =  id)      
+
+    def AddItem(self, event = None, updateMap = True):
+        """!Append point to list"""
+        self.dialog.pointsToDraw.AddItem(coords = [0,0])
+
+        PointsList.AddItem(self, event)
+
+        self.EditCellKey(key = self.selected , 
+                         colName = 'topology', 
+                         cellData = _("new point"))  
+ 
+    def DeleteItem(self, event = None):
+        """!Delete selected point in list"""
+        key = self.GetItemData(self.selected)
+        if self.selected != wx.NOT_FOUND:
+            item = self.dialog.pointsToDraw.GetItem(key)
+            self.dialog.pointsToDraw.DeleteItem(item)
+
+        PointsList.DeleteItem(self, event)
+
+    def OnItemSelected(self, event):
+        """!Item selected"""
+        PointsList.OnItemSelected(self, event)
+
+        if self.updateMap:
+            self.dialog.mapWin.UpdateMap(render=False, renderVector=False)
+
+    def AdaptPointsList(self, currParamsCats):
+        """Rename category values when module is changed. Expample: Start point -> Sink point"""
+        colValues = [""]
+
+        for ptCat in currParamsCats:
+            colValues.append(ptCat[1])
+        colNum = self._getColumnNum('type')
+        self.ChangeColEditable('type', colValues)
+
+        for iItem, item in enumerate(self.itemDataMap): 
+            self.EditCellKey(iItem, 'type', self.selIdxs[iItem][colNum])
+
+            if not item[1]:               
+                self.CheckItem(iItem, False)
+   
+    def OnCheckItem(self, index, flag):
+        """!Item is checked/unchecked"""
+        key = self.GetItemData(index)
+        checkedVal = self.itemDataMap[key][1]
+
+        currModule = self.dialog.currAnModule #TODO public func
+        cats = self.dialog.vnetParams[currModule]["cmdParams"]["cats"]
+
+        if self.updateMap:
+            self.dialog.mapWin.UpdateMap(render=False, renderVector=False)
+
+        if len(cats) <= 1:
+            return 
+
+        if checkedVal == "":
+            self.CheckItem(key, False)
+            return
+
+        if currModule == "v.net.path" and flag:
+            self.UpdateCheckedItems(index)
+
+    def UpdateCheckedItems(self, index):
+        """!For v.net.path - max. just one checked 'Start point' and 'End point'"""
+        alreadyChecked = []
+        colNum = self._getColumnNum('type')
+        if colNum == -1:
+            return 
+        if index:
+            checkedKey = self.GetItemData(index)
+            checkedVal = self.selIdxs[checkedKey][colNum]
+            alreadyChecked.append(checkedVal)
+        else:
+            checkedKey = -1
+
+        for iKey, idx in enumerate(self.selIdxs):
+            index = self._findIndex(iKey)
+            if (idx[colNum] in alreadyChecked and checkedKey != iKey) \
+               or idx[colNum] == 0:
+                self.CheckItem(index, False)
+            elif self.IsChecked(index):
+                alreadyChecked.append(idx[colNum])
+
+    def SetUpdateMap(self, updateMap):
+        """!Update/Not update map window when some change in list is made"""
+        self.updateMap = updateMap
+
+    def GetHiddenColSelIdxs(self, colName):
+        """!Get indexes of chosen values in hidden 'type' column"""
+        if self.hiddenCols.has_key(colName):
+            return self.hiddenCols[colName]['selIdxs']
+        return None
+
+    def SetHiddenSelIdxs(self, colName, selIdxs):
+        """!Set indexes of chosen values in hidden 'type' column and update text in it's cells"""
+        if self.hiddenCols.has_key(colName):
+            self.hiddenCols[colName]['selIdxs'] = map(int, selIdxs)
+            self.hiddenCols[colName]['itemDataMap'] = []
+            # update text in hidden column cells
+            for idx in self.hiddenCols[colName]['selIdxs']:
+                    self.hiddenCols[colName]['itemDataMap'].append(self.hiddenCols[colName]['colsData'][2][idx])
+            return True
+        return False
+
+class SettingsDialog(wx.Dialog):
+    def __init__(self, parent, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize,
+                 style=wx.DEFAULT_DIALOG_STYLE):
+        """!Settings dialog"""
+        wx.Dialog.__init__(self, parent, id, title, pos, size, style)
+
+        maxValue = 1e8
+        self.parent = parent
+        self.settings = {}
+
+        rules = RunCommand('v.colors', 
+                           read = True,
+                           flags = 'l')
+
+        settsLabels = {} 
+
+        settsLabels['color_table'] = wx.StaticText(parent = self, id = wx.ID_ANY, 
+                                                   label = _('Color table style %s:') % '(v.net.flow)')
+        self.settings['color_table'] = wx.ComboBox(parent = self, id = wx.ID_ANY,
+                                                   choices = rules.split(),
+                                                   style = wx.CB_READONLY, size = (180, -1))
+
+        setStyle = UserSettings.Get(group ='vnet', key = "res_style", subkey = "color_table")
+        i = self.settings['color_table'].FindString(setStyle)
+        if i != wx.NOT_FOUND: 
+            self.settings['color_table'].Select(i)
+
+        self.settings["invert_colors"] = wx.CheckBox(parent = self, id=wx.ID_ANY,
+                                                       label = _('Invert colors %s:') % '(v.net.flow)')
+        setInvert = UserSettings.Get(group ='vnet', key = "res_style", subkey = "invert_colors")
+        self.settings["invert_colors"].SetValue(setInvert)
+
+        self.colorsSetts = {
+                            "line_color" : ["res_style", _("Line color:")],
+                            "unused" : ["point_colors", _("Color for unused point:")], 
+                            "used1cat" : ["point_colors", _("Color for Start/From/Source/Used point:")],
+                            "used2cat" : ["point_colors", _("Color for End/To/Sink point:")],
+                            "selected" : ["point_colors", _("Color for selected point:")]
+                           }
+
+        for settKey, sett in self.colorsSetts.iteritems():
+            settsLabels[settKey] = wx.StaticText(parent = self, id = wx.ID_ANY, label = sett[1])
+            col = UserSettings.Get(group ='vnet', key = sett[0], subkey = settKey)        
+            self.settings[settKey] = csel.ColourSelect(parent = self, id = wx.ID_ANY,
+                                            colour = wx.Colour(col[0],
+                                                               col[1],
+                                                               col[2], 
+                                                               255))
+
+        self.sizeSetts = {
+                          "line_width" : ["res_style", _("Line width:")],
+                          "point_size" : ["point_symbol", _("Point size:")], 
+                          "point_width" : ["point_symbol", _("Point width:")],
+                          "snap_tresh" : ["other", _("Snapping treshold in pixels:")],
+                          "max_hist_steps" : ["other", _("Maximum number of results in history:")]
+                         }
+
+        for settKey, sett in self.sizeSetts.iteritems():
+            settsLabels[settKey] = wx.StaticText(parent = self, id = wx.ID_ANY, label = sett[1])
+            self.settings[settKey] = wx.SpinCtrl(parent = self, id = wx.ID_ANY, min = 1, max = 50)
+            size = int(UserSettings.Get(group = 'vnet', key = sett[0], subkey = settKey))
+            self.settings[settKey].SetValue(size)
+
+
+        # buttons
+        self.btnSave = wx.Button(self, wx.ID_SAVE)
+        self.btnApply = wx.Button(self, wx.ID_APPLY)
+        self.btnClose = wx.Button(self, wx.ID_CLOSE)
+        self.btnApply.SetDefault()
+
+        # bindings
+        self.btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
+        self.btnApply.SetToolTipString(_("Apply changes for the current session"))
+        self.btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
+        self.btnSave.SetToolTipString(_("Apply and save changes to user settings file (default for next sessions)"))
+        self.btnClose.Bind(wx.EVT_BUTTON, self.OnClose)
+        self.btnClose.SetToolTipString(_("Close dialog"))
+
+        #Layout
+
+        # Analysis result style layout
+        self.SetMinSize(self.GetBestSize())
+
+        sizer = wx.BoxSizer(wx.VERTICAL)
+
+        styleBox = wx.StaticBox(parent = self, id = wx.ID_ANY,
+                                label =" %s " % _("Analysis result style:"))
+        styleBoxSizer = wx.StaticBoxSizer(styleBox, wx.VERTICAL)
+
+        gridSizer = wx.GridBagSizer(vgap = 1, hgap = 1)
+        gridSizer.AddGrowableCol(1)
+
+        row = 0
+        gridSizer.Add(item =  settsLabels["line_color"], flag = wx.ALIGN_CENTER_VERTICAL, pos =(row, 0))
+        gridSizer.Add(item = self.settings["line_color"],
+                      flag = wx.ALIGN_RIGHT | wx.ALL, border = 5,
+                      pos =(row, 1))
+ 
+        row += 1
+        gridSizer.Add(item =  settsLabels["line_width"], flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
+        gridSizer.Add(item = self.settings["line_width"],
+                      flag = wx.ALIGN_RIGHT | wx.ALL, border = 5,
+                      pos = (row, 1))
+        row += 1
+        gridSizer.Add(item = settsLabels['color_table'], flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
+        gridSizer.Add(item = self.settings['color_table'],
+                      flag = wx.ALIGN_RIGHT | wx.ALL, border = 5,
+                      pos = (row, 1))
+
+        row += 1
+        gridSizer.Add(item = self.settings["invert_colors"], flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
+
+        styleBoxSizer.Add(item = gridSizer, flag = wx.EXPAND)
+
+        # Point style layout
+        ptsStyleBox = wx.StaticBox(parent = self, id = wx.ID_ANY,
+                                   label =" %s " % _("Point style:"))
+        ptsStyleBoxSizer = wx.StaticBoxSizer(ptsStyleBox, wx.VERTICAL)
+
+        gridSizer = wx.GridBagSizer(vgap = 1, hgap = 1)
+        gridSizer.AddGrowableCol(1)
+
+        row = 0
+        setts = dict(self.colorsSetts.items() + self.sizeSetts.items())
+
+        settsOrder = ["selected", "used1cat", "used2cat", "unused", "point_size", "point_width"]
+        for settKey in settsOrder:
+            sett = setts[settKey]
+            gridSizer.Add(item = settsLabels[settKey], flag = wx.ALIGN_CENTER_VERTICAL, pos =(row, 0))
+            gridSizer.Add(item = self.settings[settKey],
+                          flag = wx.ALIGN_RIGHT | wx.ALL, border = 5,
+                          pos =(row, 1))  
+            row += 1
+
+        ptsStyleBoxSizer.Add(item = gridSizer, flag = wx.EXPAND)
+
+        # Other settings layout
+        otherBox = wx.StaticBox(parent = self, id = wx.ID_ANY,
+                                label =" %s " % _("Other settings"))
+        otherBoxSizer = wx.StaticBoxSizer(otherBox, wx.VERTICAL)
+
+        gridSizer = wx.GridBagSizer(vgap = 1, hgap = 1)
+        gridSizer.AddGrowableCol(1)
+
+        row = 0 
+        for otherSettName in ["snap_tresh", "max_hist_steps"]:
+            gridSizer.Add(item = settsLabels[otherSettName], flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
+            gridSizer.Add(item = self.settings[otherSettName],
+                          flag = wx.ALIGN_RIGHT | wx.ALL, border = 5,
+                          pos = (row, 1))
+            row += 1
+
+        otherBoxSizer.Add(item = gridSizer, flag = wx.EXPAND)
+
+        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
+        btnSizer.Add(self.btnApply, flag = wx.LEFT | wx.RIGHT, border = 5)
+        btnSizer.Add(self.btnSave, flag=wx.LEFT | wx.RIGHT, border=5)
+        btnSizer.Add(self.btnClose, flag = wx.LEFT | wx.RIGHT, border = 5)
+
+        sizer.Add(item = styleBoxSizer, flag = wx.EXPAND | wx.ALL, border = 5)
+        sizer.Add(item = ptsStyleBoxSizer, flag = wx.EXPAND | wx.ALL, border = 5)
+        sizer.Add(item = otherBoxSizer, flag = wx.EXPAND | wx.ALL, border = 5)
+        sizer.Add(item = btnSizer, flag = wx.EXPAND | wx.ALL, border = 5, proportion = 0)    
+
+        self.SetSizer(sizer)
+        sizer.Fit(self)
+     
+    def OnSave(self, event):
+        """!Button 'Save' pressed"""
+        self.UpdateSettings()
+
+        fileSettings = {}
+        UserSettings.ReadSettingsFile(settings=fileSettings)
+        fileSettings['vnet'] = UserSettings.Get(group='vnet')
+        UserSettings.SaveToFile(fileSettings)
+
+        self.Close()
+
+    def UpdateSettings(self):
+        UserSettings.Set(group ='vnet', key = "res_style", subkey ='line_width',
+                         value = self.settings["line_width"].GetValue())
+
+        for settKey, sett in self.colorsSetts.iteritems():
+            col = tuple(self.settings[settKey].GetColour())
+            UserSettings.Set(group = 'vnet', 
+                             key = sett[0], 
+                             subkey = settKey,
+                             value = col)
+
+        for settKey, sett in self.sizeSetts.iteritems():
+            UserSettings.Set(group = 'vnet', key = sett[0], subkey = settKey, 
+                             value = self.settings[settKey].GetValue())
+
+        UserSettings.Set(group = 'vnet', key = 'res_style', subkey = 'color_table', 
+                        value = self.settings['color_table'].GetStringSelection())
+
+        UserSettings.Set(group = 'vnet', key = 'res_style', subkey = 'invert_colors', 
+                        value = self.settings['invert_colors'].IsChecked())
+
+        self.parent.SetPointDrawSettings()
+        if not self.parent.tmp_result  or \
+           not self.parent.tmpMaps.HasTmpVectMap(self.parent.tmp_result.GetVectMapName()):
+            self.parent.mapWin.UpdateMap(render=False, renderVector=False)
+        elif self.parent.tmp_result.GetRenderLayer():
+            cmd = self.parent.GetLayerStyle()
+            self.parent.tmp_result.AddRenderLayer(cmd)
+            self.parent.mapWin.UpdateMap(render=True, renderVector=True)#TODO optimization
+        else:
+            self.parent.mapWin.UpdateMap(render=False, renderVector=False)
+
+    def OnApply(self, event):
+        """!Button 'Apply' pressed"""
+        self.UpdateSettings()
+        #self.Close()
+
+    def OnClose(self, event):
+        """!Button 'Cancel' pressed"""
+        self.Close()
+
+class AddLayerDialog(wx.Dialog):
+    def __init__(self, parent,id=wx.ID_ANY,
+                 title =_("Save analysis result"), style=wx.DEFAULT_DIALOG_STYLE):
+        """!Save analysis result"""
+        wx.Dialog.__init__(self, parent, id, title = _(title), style = style)
+
+        self.panel = wx.Panel(parent = self)
+       
+        # text fields and it's captions
+        self.vectSel = Select(parent = self.panel, type = 'vector', 
+                              mapsets = [grass.gisenv()['MAPSET']],size = (-1, -1))
+        self.vectSellabel = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
+                                          label = _("Name:")) 
+
+        # buttons
+        self.btnCancel = wx.Button(self.panel, wx.ID_CANCEL)
+        self.btnOk = wx.Button(self.panel, wx.ID_OK)
+        self.btnOk.SetDefault()
+
+        self.SetInitialSize((400, -1))
+        self._layout()
+
+    def _layout(self):
+
+        sizer = wx.BoxSizer(wx.VERTICAL)
+
+        box = wx.StaticBox (parent = self.panel, id = wx.ID_ANY,
+                            label = "Vector map")
+
+        boxSizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
+
+        boxSizer.Add(item = self.vectSellabel, 
+                     flag = wx.ALIGN_CENTER_VERTICAL,
+                     proportion = 0)
+
+        boxSizer.Add(item = self.vectSel, proportion = 1,
+                     flag = wx.EXPAND | wx.ALL, border = 5)
+
+        sizer.Add(item = boxSizer, proportion = 1,
+                  flag = wx.EXPAND | wx.ALL, border = 5)
+
+        btnSizer = wx.StdDialogButtonSizer()
+        btnSizer.AddButton(self.btnCancel)
+        btnSizer.AddButton(self.btnOk)
+        btnSizer.Realize()
+
+        sizer.Add(item = btnSizer, proportion = 0,
+                  flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
+
+        self.panel.SetSizer(sizer)
+        sizer.Fit(self)
+
+class VnetTmpVectMaps:
+    """!Class which creates, stores and destroys all tmp maps created during analysis"""
+    def __init__(self, parent):
+        self.tmpMaps = [] # temporary maps 
+        self.parent = parent
+        self.mapWin = self.parent.mapWin
+
+    def AddTmpVectMap(self, mapName, msg):
+        """!New temporary map
+
+            @return instance of VectMap representing temporary map 
+        """
+        currMapSet = grass.gisenv()['MAPSET']
+        tmpMap = grass.find_file(name = mapName, 
+                                 element = 'vector', 
+                                 mapset = currMapSet)
+
+        fullName = tmpMap["fullname"]
+        # map already exists
+        if fullName:
+            #TODO move dialog out of class, AddTmpVectMap(self, mapName, overvrite = False)
+            dlg = wx.MessageDialog(parent = self.parent, 
+                                   message = msg,
+                                   caption = _("Overwrite map layer"),
+                                   style = wx.YES_NO | wx.NO_DEFAULT |
+                                   wx.ICON_QUESTION | wx.CENTRE)
+                
+            ret = dlg.ShowModal()
+            dlg.Destroy()
+                
+            if ret == wx.ID_NO:
+                return None
+        else:
+            fullName = mapName + "@" + currMapSet
+
+        newVectMap = VectMap(self, fullName)
+        self.tmpMaps.append(newVectMap)
+
+        return newVectMap
+
+    def HasTmpVectMap(self, vectMapName):
+        """ 
+            @param vectMapName name of vector map
+
+            @return True if it contains the map
+            @return False if not 
+        """
+
+        mapValSpl = vectMapName.strip().split("@")
+        if len(mapValSpl) > 1:
+            mapSet = mapValSpl[1]
+        else:
+            mapSet = grass.gisenv()['MAPSET']
+        mapName = mapValSpl[0] 
+        fullName = mapName + "@" + mapSet
+
+        for vectTmpMap in self.tmpMaps:
+            if vectTmpMap.GetVectMapName() == fullName:
+                return True
+        return False
+
+    def GetTmpVectMap(self, vectMapName):
+        """ Get instance of VectMap with name vectMapName"""
+        for vectMap in self.tmpMaps:
+            if vectMap.GetVectMapName() == vectMapName.strip():
+                return vectMap
+        return None
+
+    def RemoveFromTmpMaps(self, vectMap):
+        """!Temporary map is removed from the class instance however it is not deleted
+
+            @param vectMap instance of VectMap class to be removed 
+
+            @return True if was removed
+            @return False if does not contain the map
+        """
+        try:
+            self.tmpMaps.remove(vectMap)
+            return True
+        except ValueError:
+            return False
+
+    def DeleteTmpMap(self, vectMap):
+        """!Temporary map is removed from the class and it is deleted
+        
+            @param vectMap instance of VectMap class to be deleted 
+
+            @return True if was removed
+            @return False if does not contain the map
+        """
+        if vectMap:
+            vectMap.DeleteRenderLayer()
+            RunCommand('g.remove', 
+                        vect = vectMap.GetVectMapName())
+            self.RemoveFromTmpMaps(vectMap)
+            return True
+        return False
+
+    def DeleteAllTmpMaps(self):
+        """Delete all temporary maps in the class"""
+        update = False
+        for tmpMap in self.tmpMaps:
+            RunCommand('g.remove', 
+                        vect = tmpMap.GetVectMapName())
+            if tmpMap.DeleteRenderLayer():
+                update = True
+        return update
+
+class VectMap:
+    """!Represents map 
+        It can check if it was modified or render it
+    """
+    def __init__(self, parent, fullName):
+        self.fullName = fullName
+        self.parent = parent
+        self.renderLayer = None
+        self.modifTime = None # time, for modification check
+
+    def __del__(self):
+
+        self.DeleteRenderLayer()
+   
+    def AddRenderLayer(self, cmd = None):
+        """!Add map from map window layers to render """
+        existsMap = grass.find_file(name = self.fullName, 
+                                    element = 'vector', 
+                                    mapset = grass.gisenv()['MAPSET'])
+
+        if not existsMap["name"]:
+            self.DeleteRenderLayer()
+            return False
+
+        if not cmd:
+            cmd = []    
+        cmd.insert(0, 'd.vect')
+        cmd.append('map=%s' % self.fullName)
+
+        if self.renderLayer:       
+             self.DeleteRenderLayer()
+
+        self.renderLayer = self.parent.mapWin.Map.AddLayer(type = "vector",  command = cmd,
+                                                           l_active=True,    name = self.fullName, 
+                                                           l_hidden = True,  l_opacity = 1.0, 
+                                                           l_render = False,  pos = -1)
+        return True
+
+    def DeleteRenderLayer(self):
+        """!Remove map from map window layers to render"""
+        if self.renderLayer: 
+             self.parent.mapWin.Map.DeleteLayer(self.renderLayer)
+             self.renderLayer = None
+             return True
+        return False
+
+    def GetRenderLayer(self):
+        return self.renderLayer
+
+    def GetVectMapName(self):
+        return self.fullName
+
+    def SaveVectMapState(self):
+        """!Save modification time for vector map"""
+        self.modifTime = self.GetLastModified()
+
+    def VectMapState(self):
+        """!Checks if map was modified
+
+            @return -1 - if no modification time was saved
+            @return  0 - if map was modified
+            @return  1 - if map was not modified
+        """
+        if self.modifTime is None:
+            return -1       
+        if self.modifTime != self.GetLastModified():
+            return 0  
+        return 1
+
+    def GetLastModified(self):
+        """!Get modification time 
+
+            @return MAP DATE time string from vector map head file 
+        """
+
+        mapValSpl = self.fullName.split("@")
+        mapSet = mapValSpl[1]
+        mapName = mapValSpl[0] 
+
+        headPath =  os.path.join(grass.gisenv()['GISDBASE'],
+                                 grass.gisenv()['LOCATION_NAME'],
+                                 mapSet,
+                                 "vector",
+                                 mapName,
+                                 "head")
+        try:
+            head = open(headPath, 'r')
+            for line in head.readlines():
+                i = line.find('MAP DATE:', )
+                if i == 0:
+                    head.close()
+                    return line.split(':', 1)[1].strip()
+
+            head.close()
+            return ""
+        except IOError:
+            return ""
+
+class History:
+    """!Class which reads and saves history data (based on gui.core.settings Settings class file save/load)"""   
+    def __init__(self, parent):
+
+        # max number of steps in history (zero based)
+        self.maxHistSteps = 3 
+        # current history step 
+        self.currHistStep = 0
+        # number of steps saved in history
+        self.histStepsNum = 0
+
+        # dict contains data saved in history for current history step 
+        self.currHistStepData = {} 
+
+        # buffer for data to be saved into history 
+        self.newHistStepData = {} 
+
+        self.histFile = grass.tempfile()
+
+        # key/value separator
+        self.sep = ';'
+
+    def __del__(self):
+        grass.try_remove(self.histFile)
+
+    def GetNext(self):
+        """!Go one step forward in history"""
+        self.currHistStep -= 1
+        self.currHistStepData.clear()
+        self.currHistStepData = self._getHistStepData(self.currHistStep)
+
+        return self.currHistStepData
+
+    def GetPrev(self):
+        """!Go one step back in history"""
+        self.currHistStep += 1 
+        self.currHistStepData.clear()
+        self.currHistStepData = self._getHistStepData(self.currHistStep)
+
+        return self.currHistStepData
+
+    def GetStepsNum(self):
+        """!Get number of steps saved in history"""
+        return self.histStepsNum
+
+    def GetCurrHistStep(self):
+        """!Get current history step"""
+        return self.currHistStep
+
+    def Add(self, key, subkey, value):
+        """!Add new data into buffer"""
+        if key not in self.newHistStepData:
+            self.newHistStepData[key] = {}
+
+        if type(subkey) == types.ListType:
+            if subkey[0] not in self.newHistStepData[key]:
+                self.newHistStepData[key][subkey[0]] = {}
+            self.newHistStepData[key][subkey[0]][subkey[1]] = value
+        else:
+            self.newHistStepData[key][subkey] = value
+
+    def SaveHistStep(self):
+        """!Create new history step with data in buffer"""
+        self.maxHistSteps = UserSettings.Get(group ='vnet',
+                                             key = 'other',
+                                             subkey = 'max_hist_steps')
+        self.currHistStep = 0 
+
+        newHistFile = grass.tempfile()
+        newHist = open(newHistFile, "w")
+
+        self._saveNewHistStep(newHist)
+
+        oldHist = open(self.histFile)
+        removedHistData = self._savePreviousHist(newHist, oldHist)
+
+        oldHist.close()
+        newHist.close()
+        grass.try_remove(self.histFile)
+        self.histFile = newHistFile
+
+        self.newHistStepData.clear() 
+
+        return removedHistData
+
+    def _savePreviousHist(self, newHist, oldHist):          
+        """!Save previous history into new file"""
+        newHistStep = False
+        removedHistData = {}
+        newHistStepsNum = self.histStepsNum
+
+        for line in oldHist.readlines():
+            if not line.strip():
+                newHistStep = True
+                newHistStepsNum += 1
+                continue
+
+            if newHistStep:
+                newHistStep = False
+
+                line = line.split("=")
+                line[1] = str(newHistStepsNum)
+                line = "=".join(line)
+
+                if newHistStepsNum >= self.maxHistSteps:
+                    removedHistStep = removedHistData[line] = {}
+                    continue
+                else:
+                    newHist.write('%s%s%s' % (os.linesep, line, os.linesep))
+                    self.histStepsNum = newHistStepsNum
+            else:
+                if newHistStepsNum >= self.maxHistSteps:
+                    self._parseLine(line, removedHistStep)
+                else:
+                    newHist.write('%s' % line)                
+
+        return removedHistData
+            
+    def _saveNewHistStep(self, newHist):
+        """!Save buffer (new step) data into file"""
+        newHist.write('%s%s%s' % (os.linesep, "history step=0", os.linesep))  
+        for key in self.newHistStepData.keys():
+            subkeys =  self.newHistStepData[key].keys()
+            newHist.write('%s%s' % (key, self.sep))
+            for idx in range(len(subkeys)):
+                value =  self.newHistStepData[key][subkeys[idx]]
+                if type(value) == types.DictType:
+                    if idx > 0:
+                        newHist.write('%s%s%s' % (os.linesep, key, self.sep))
+                    newHist.write('%s%s' % (subkeys[idx], self.sep))
+                    kvalues =  self.newHistStepData[key][subkeys[idx]].keys()
+                    srange = range(len(kvalues))
+                    for sidx in srange:
+                        svalue = self._parseValue(self.newHistStepData[key][subkeys[idx]][kvalues[sidx]])
+                        newHist.write('%s%s%s' % (kvalues[sidx], self.sep, svalue))
+                        if sidx < len(kvalues) - 1:
+                            newHist.write('%s' % self.sep)
+                else:
+                    if idx > 0 and \
+                            type( self.newHistStepData[key][subkeys[idx - 1]]) == types.DictType:
+                        newHist.write('%s%s%s' % (os.linesep, key, self.sep))
+                    value = self._parseValue(self.newHistStepData[key][subkeys[idx]])
+                    newHist.write('%s%s%s' % (subkeys[idx], self.sep, value))
+                    if idx < len(subkeys) - 1 and \
+                            type(self.newHistStepData[key][subkeys[idx + 1]]) != types.DictType:
+                        newHist.write('%s' % self.sep)
+            newHist.write(os.linesep)
+        self.histStepsNum = 0
+
+    def _parseValue(self, value, read = False):
+        """!Parse value"""
+        if read: # -> read data (cast values)
+
+            if value:
+                if value[0] == '[' and value[-1] == ']':# TODO, possible wrong interpretation
+                    value = value[1:-1].split(',')
+                    value = map(self._castValue, value)
+                    return value
+
+            if value == 'True':
+                value = True
+            elif value == 'False':
+                value = False
+            elif value == 'None':
+                value = None
+            elif ':' in value: # -> color
+                try:
+                    value = tuple(map(int, value.split(':')))
+                except ValueError: # -> string
+                    pass
+            else:
+                try:
+                    value = int(value)
+                except ValueError:
+                    try:
+                        value = float(value)
+                    except ValueError:
+                        pass
+        else: # -> write data
+            if type(value) == type(()): # -> color
+                value = str(value[0]) + ':' +\
+                    str(value[1]) + ':' + \
+                    str(value[2])
+                
+        return value
+
+    def _castValue(self, value):
+        """!Cast value"""
+        try:
+            value = int(value)
+        except ValueError:
+            try:
+                value = float(value)
+            except ValueError:
+                value = value[1:-1]
+
+        return value
+
+    def _getHistStepData(self, histStep):          
+        """!Load data saved in history step"""        
+        hist = open(self.histFile)
+        histStepData = {}
+
+        newHistStep = False
+        isSearchedHistStep = False
+        for line in hist.readlines():
+
+            if  not line.strip() and isSearchedHistStep:
+                 break
+            elif not line.strip():
+                newHistStep = True
+                continue
+            elif isSearchedHistStep:
+                self._parseLine(line, histStepData)
+
+            if newHistStep:
+                line = line.split("=")
+                if int(line[1]) == histStep:
+                    isSearchedHistStep = True
+                newHistStep = False
+
+        hist.close()
+        return histStepData
+
+    def _parseLine(self, line, histStepData):
+        """!Parse line in file with history"""        
+        line = line.rstrip('%s' % os.linesep).split(self.sep)
+        key = line[0]
+        kv = line[1:]
+        idx = 0
+        subkeyMaster = None
+        if len(kv) % 2 != 0: # multiple (e.g. nviz)
+            subkeyMaster = kv[0]
+            del kv[0]
+        idx = 0
+        while idx < len(kv):
+            if subkeyMaster:
+                subkey = [subkeyMaster, kv[idx]]
+            else:
+                subkey = kv[idx]
+            value = kv[idx+1]
+            value = self._parseValue(value, read = True)
+            if key not in histStepData:
+                histStepData[key] = {}
+
+            if type(subkey) == types.ListType:
+                if subkey[0] not in histStepData[key]:
+                    histStepData[key][subkey[0]] = {}
+                histStepData[key][subkey[0]][subkey[1]] = value
+            else:
+                histStepData[key][subkey] = value
+            idx += 2
+
+    def DeleteNewHistStepData(self):
+        """!Delete buffer data for new history step"""        
+        self.newHistStepData.clear() 
+
+class VnetStatusbar(wx.StatusBar):
+    """!Extends wx.StatusBar class with functionality to show multiple messages with the highest priority"""        
+    def __init__(self, parent, style, id = wx.ID_ANY, **kwargs):
+
+        wx.StatusBar.__init__(self, parent, id, style, **kwargs)
+
+        self.maxPriority = 0
+        self.statusItems = []
+
+    def AddStatusItem(self, text, key, priority):
+        """!Add new item to show
+
+            @param text - string to show
+            @param key - item identifier, if already contains 
+                         item with same identifier, overwrites this item
+            @param priority - only items with highest priority are showed 
+        """        
+        statusTextItem = {
+                            'text' : text, 
+                            'key' : key,
+                            'priority' : priority
+                         }
+
+        for item in self.statusItems:
+            if item['key'] == statusTextItem['key']:
+                self.statusItems.remove(item)
+        self.statusItems.append(statusTextItem)
+        if self.maxPriority < statusTextItem['priority']:
+            self.maxPriority =  statusTextItem['priority']
+        self._updateStatus()
+
+    def _updateStatus(self):
+
+        currStatusText = ''
+        for item in reversed(self.statusItems):
+            if item['priority'] == self.maxPriority:
+                if currStatusText:
+                    currStatusText += '; '
+                currStatusText += item['text']
+        wx.StatusBar.SetStatusText(self, currStatusText)
+
+    def RemoveStatusItem(self, key):
+        """!Remove item 
+
+            @param key - item identifier
+        """
+        update = False
+        for iItem, item in enumerate(self.statusItems):
+            if item['key'] == key:
+                if item['priority'] == self.maxPriority:
+                    update = True
+                self.statusItems.pop(iItem)
+        if update:
+            for item in self.statusItems:
+                self.maxPriority = 0
+                if self.maxPriority < item['priority']:
+                    self.maxPriority =  item['priority']
+            self._updateStatus()


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

Added: grass/trunk/gui/wxpython/vnet/toolbars.py
===================================================================
--- grass/trunk/gui/wxpython/vnet/toolbars.py	                        (rev 0)
+++ grass/trunk/gui/wxpython/vnet/toolbars.py	2013-01-03 17:46:18 UTC (rev 54515)
@@ -0,0 +1,176 @@
+"""!
+ at package vnet.toolbars
+
+ at brief Vector network analysis dialog - toolbars
+
+Classes:
+ - toolbars::PointListToolbar
+ - toolbars::MainToolbar
+
+(C) 2012 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 Stepan Turek <stepan.turek seznam.cz> (GSoC 2012, mentor: Martin Landa)
+"""
+
+import wx
+
+from icon              import MetaIcon
+from gui_core.toolbars import BaseToolbar, BaseIcons
+from core.gcmd         import RunCommand
+class PointListToolbar(BaseToolbar):
+    """!Toolbar for managing list of points
+
+    @param parent reference to VNETDialog
+    """
+    def __init__(self, parent, list):
+        BaseToolbar.__init__(self, parent)
+        self.list = list
+        self.InitToolbar(self._toolbarData())
+        
+        # realize the toolbar
+        self.Realize()
+
+
+    def _toolbarData(self):
+
+        icons = {
+            'insertPoint'  : MetaIcon(img = 'pointer',
+                                    label = _('Insert points from Map Display')),
+            'snapping'  : MetaIcon(img = 'move',
+                                    label = _('Activate snapping to nodes')),
+            'pointAdd'     : MetaIcon(img = 'point-create',
+                                    label = _('Add new point')),
+            'pointDelete'  : MetaIcon(img = 'gcp-delete',
+                                    label = _('Delete selected point'))
+            }
+
+        return  self._getToolbarData((('insertPoint', icons['insertPoint'],
+                                      self.list.dialog.OnInsertPoint,#TODO self.list.dialog
+                                      wx.ITEM_CHECK),
+                                      ('snapping', icons['snapping'],
+                                      self.list.dialog.OnSnapping,
+                                      wx.ITEM_CHECK),
+                                      (None, ),
+                                     ('pointAdd', icons["pointAdd"],
+                                        self.list.AddItem),
+                                     ('pointDelete', icons["pointDelete"],
+                                        self.list.DeleteItem)))
+                                    
+    def GetToolId(self, toolName): #TODO can be useful in base
+
+        return vars(self)[toolName]
+
+class MainToolbar(BaseToolbar):
+    """!Main toolbar
+    """
+    def __init__(self, parent):
+        BaseToolbar.__init__(self, parent)
+        
+        self.InitToolbar(self._toolbarData())
+
+        choices = []
+
+        for moduleName in self.parent.vnetModulesOrder:
+            choices.append(self.parent.vnetParams[moduleName]['label'])
+
+        self.UpdateUndoRedo()
+        # realize the toolbar
+        self.Realize()
+
+    def _toolbarData(self):
+
+        icons = {
+                 'run' : MetaIcon(img = 'execute',
+                                  label = _('Execute analysis')),
+                 'undo' : MetaIcon(img = 'undo',
+                                  label = _('Go to previous analysis result')),
+                 'redo' : MetaIcon(img = 'redo',
+                                  label = _('Go to next analysis result')),
+                 'showResult'   : MetaIcon(img = 'layer-add',
+                                    label = _("Show analysis result")),
+                 'saveTempLayer' : MetaIcon(img = 'map-export',
+                                             label = _('Save temporary result')),
+                 'settings' : BaseIcons['settings'].SetLabel( _('Vector network analysis settings')),
+                 'help'       : MetaIcon(img = 'help',
+                                         label = _('Show manual'))
+                }
+
+        return self._getToolbarData((
+                                     ("run", icons['run'],
+                                      self.parent.OnAnalyze),
+                                     (None, ),     
+                                     ("undo", icons['undo'], 
+                                      self.parent.OnUndo), 
+                                     ("redo", icons['redo'], 
+                                      self.parent.OnRedo),
+                                     (None, ),
+                                     ("showResult", icons['showResult'], 
+                                      self.parent.OnShowResult, wx.ITEM_CHECK), 
+                                     ("saveTempLayer", icons['saveTempLayer'],
+                                      self.parent.OnSaveTmpLayer),
+                                     (None, ),
+                                     ('settings', icons["settings"],
+                                      self.parent.OnSettings),  
+                                     ('help', icons["help"],
+                                      self.OnHelp),                                     
+                                     ("quit", BaseIcons['quit'],
+                                      self.parent.OnCloseDialog)
+                                    ))
+
+
+    def UpdateUndoRedo(self):
+
+        id = vars(self)['showResult']
+        self.ToggleTool(id =id,
+                        toggle = True)
+
+        if self.parent.history.GetCurrHistStep() >= self.parent.history.GetStepsNum():
+           self.Enable("undo", False)
+        else:
+           self.Enable("undo", True)
+
+        if self.parent.history.GetCurrHistStep() <= 0:
+           self.Enable("redo", False)
+        else:
+           self.Enable("redo", True)  
+
+    def OnHelp(self, event) :
+            RunCommand('g.manual',
+                       entry = 'wxGUI.VNet')
+
+class AnalysisToolbar(BaseToolbar):
+    """!Main toolbar
+    """
+    def __init__(self, parent):
+        BaseToolbar.__init__(self, parent)
+        
+        self.InitToolbar(self._toolbarData())
+
+        choices = []
+
+        for moduleName in self.parent.vnetModulesOrder:
+            choices.append(self.parent.vnetParams[moduleName]['label'])
+
+        self.anChoice = wx.ComboBox(parent = self, id = wx.ID_ANY,
+                                    choices = choices,
+                                    style = wx.CB_READONLY, size = (350, 30))#FIXME
+        self.anChoice.SetToolTipString(_('Availiable analyses'))
+        self.anChoice.SetSelection(0)
+               
+        self.anChoiceId = self.AddControl(self.anChoice)
+        self.parent.Bind(wx.EVT_COMBOBOX, self.parent.OnAnalysisChanged, self.anChoiceId)
+                
+        # workaround for Mac bug. May be fixed by 2.8.8, but not before then.
+        self.anChoice.Hide()
+        self.anChoice.Show()
+        # realize the toolbar
+        self.Realize()
+
+    def _toolbarData(self):
+
+        icons = {}
+
+        return self._getToolbarData(())
\ No newline at end of file


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

Added: grass/trunk/gui/wxpython/vnet/widgets.py
===================================================================
--- grass/trunk/gui/wxpython/vnet/widgets.py	                        (rev 0)
+++ grass/trunk/gui/wxpython/vnet/widgets.py	2013-01-03 17:46:18 UTC (rev 54515)
@@ -0,0 +1,638 @@
+"""!
+ at package vnet.widgets
+
+ at brief Base class for list of points. 
+
+Classes:
+ - widgets::PointsList
+ - widgets::EditItem
+
+(C) 2012 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 Original author Michael Barton
+ at author Original version improved by Martin Landa <landa.martin gmail.com>
+ at author Rewritten by Markus Metz redesign georectfier -> GCP Manage
+ at author Stepan Turek <stepan.turek seznam.cz> (Created PointsList from GCPList) (GSoC 2012, mentor: Martin Landa)
+"""
+
+import os
+import wx
+from copy import copy, deepcopy
+
+import wx
+from wx.lib.mixins.listctrl import CheckListCtrlMixin, ColumnSorterMixin, ListCtrlAutoWidthMixin, TextEditMixin
+
+from core import globalvar
+
+
+class PointsList(wx.ListCtrl,
+                 CheckListCtrlMixin,
+                 ListCtrlAutoWidthMixin,
+                 ColumnSorterMixin):
+
+    def __init__(self, parent, cols, id=wx.ID_ANY,
+                 pos=wx.DefaultPosition, size=wx.DefaultSize,
+                 style=wx.LC_REPORT | wx.SUNKEN_BORDER | wx.LC_HRULES |
+                 wx.LC_SINGLE_SEL):
+        """!Creates list for points. 
+
+        PointsList class was created from GCPList class in GCP manager. It is possible 
+        to be shared by GCP and VNET front end.
+
+        Important parameters:
+        @param cols is list containing list items. which represents columns.
+                This columns will be added in order as they are in list. 
+                Class will add as first column "use" with number of point and checkbox.
+                Structure of list item must be this:
+               -1. item: column name 
+               -2. item: column label                
+               -3. item: If column is editable by user, it must contain convert function to convert
+                         inserted string to it's type for sorting. Use None for not editable 
+                         columns. Values for insertion can be in list. This allows insert
+                         just values in the list. 
+               -4. item: Default value for column cell. Value should be given in it's  type 
+                         in order to sorting would work properly. If 3. item is list, it must be index
+                         of some item in the list.
+  
+        Example of cols parameter:
+                 column name, column label, convert function, default val
+        @code
+         cols =   [
+                   ['E', _('source E'), float, 0.0],
+                   ['N', _('source N'), float, 0.0],
+                   ['E', _('target E'), float, 0.0],
+                   ['N', _('target N'), float, 0.0],
+                   ['F_Err', _('Forward error'), None, 0],
+                   ['B_Err', _(Backward error'), None, 0]
+                   ['type', _('type'), [_(""), _("Start point"), _("End point")], 0] # Select from 3 choices ("Start point", "End point"), 
+                                                                                     # Choice with index 0 ("") is default.
+                  ]
+        @endcode 
+        """
+
+        wx.ListCtrl.__init__(self, parent, id, pos, size, style)
+
+        # Mixin settings
+        CheckListCtrlMixin.__init__(self)
+        ListCtrlAutoWidthMixin.__init__(self)
+        # TextEditMixin.__init__(self)
+
+        # inserts first column with points numbers and checkboxes
+        cols.insert(0, ['use', _('use'), False, 0])
+
+        self.colsData = cols
+        self.dataTypes = {"colName" : 0,
+                          "colLabel" : 1,
+                          "colEditable" : 2,
+                          "itemDefaultValue" : 3} # just for better understanding
+
+        # information whether list items are checked or not
+        self.CheckList = [] 
+
+        self._createCols()
+        self.hiddenCols = {}
+
+        self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
+        self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated)
+        self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick)
+
+        self.selected = wx.NOT_FOUND
+        self.selectedkey = -1
+
+
+        # CheckListCtrlMixin must set an ImageList first
+        self.il = self.GetImageList(wx.IMAGE_LIST_SMALL)
+
+        # images for column sorting
+        SmallUpArrow = wx.BitmapFromImage(self.getSmallUpArrowImage())            
+        SmallDnArrow = wx.BitmapFromImage(self.getSmallDnArrowImage())            
+        self.sm_dn = self.il.Add(SmallDnArrow)
+        self.sm_up = self.il.Add(SmallUpArrow)
+
+        # initialize column sorter
+        self.itemDataMap = [] 
+        ncols = self.GetColumnCount()
+        ColumnSorterMixin.__init__(self, ncols)
+
+        # init to ascending sort on first click
+        self._colSortFlag = [1] * ncols
+
+        # same structure as itemDataMap, information about choice index selected
+        # if cell is in column without values to choose then is -1 
+        self.selIdxs = []
+
+        self.ResizeColumns()
+        self.SetColumnWidth(0, 50)
+
+    def _createCols(self):
+        """!Creates columns in list"""
+        if 0:
+            # normal, simple columns
+            for col in enumerate(self.colsData):
+                iLabel = self.dataTypes["colLabel"]
+                self.InsertColumn(col[0], col[1][iLabel])
+        else:
+            # the hard way: we want images on the column header
+            info = wx.ListItem()
+            info.SetMask(wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT)
+            info.SetImage(-1)
+            info.m_format = wx.LIST_FORMAT_LEFT
+
+            for col in enumerate(self.colsData):
+                iLabel = self.dataTypes["colLabel"]
+                info.SetText(col[1][iLabel]) 
+                self.InsertColumnInfo(col[0], info)
+
+    def AddItem(self, event):
+        """!Appends an item to list with default values"""
+        iDefVal = self.dataTypes["itemDefaultValue"]
+        iColEd = self.dataTypes["colEditable"]
+        itemData = []
+        itemIndexes = []
+        for col in self.colsData:
+            if type(col[iColEd]).__name__ == "list":
+                itemData.append(col[iColEd][col[iDefVal]])
+                itemIndexes.append(col[iDefVal])
+            else:
+                itemData.append(col[iDefVal])
+                itemIndexes.append(-1)# not a choise column 
+
+                
+        self.selIdxs.append(itemIndexes) 
+
+        for hCol in self.hiddenCols.itervalues():
+            defVal = hCol['colsData'][iDefVal]
+            if type(hCol['colsData'][iColEd]).__name__ == "list":
+                hCol['itemDataMap'].append(hCol['colsData'][iColEd][defVal])
+                hCol['selIdxs'].append(defVal)
+            else:
+                hCol['itemDataMap'].append(defVal)
+                hCol['selIdxs'].append(-1)
+
+        self.selectedkey = self.GetItemCount()
+
+        itemData[0] = self.selectedkey + 1
+        self.itemDataMap.append(copy(itemData))
+
+        self.Append(map(str, itemData))             
+
+        self.selected = self.GetItemCount() - 1
+        self.SetItemData(self.selected, self.selectedkey)
+
+        self.SetItemState(self.selected,
+                          wx.LIST_STATE_SELECTED,
+                          wx.LIST_STATE_SELECTED)
+        self.ResizeColumns()
+
+        return self.selected
+
+    def GetCellValue(self, key, colName):
+        """!Get value in cell of list using key (same regardless of sorting)"""
+        colNum = self._getColumnNum(colName)
+        iColEd = self.dataTypes["colEditable"]      
+        return self.itemDataMap[key][colNum]
+
+    def GetCellSelIdx(self, key, colName):
+        """!Get selected index in cell of list using key (same regardless of sorting)
+
+            @return number of chosen value, if column has values to choose
+            @return -1 if column does not has values to choose
+        """
+        colNum = self._getColumnNum(colName)
+        iColEd = self.dataTypes["colEditable"]
+        return self.selIdxs[key][colNum]
+
+    def EditCellIndex(self, index, colName, cellData):
+        """!Changes value in list using key (same regardless of sorting)"""
+        colNum = self._getColumnNum(colName) 
+        key = self.GetItemData(index)
+
+        iColEd = self.dataTypes["colEditable"]
+        if type(self.colsData[colNum][iColEd]).__name__ == "list":
+            cellVal = self.colsData[colNum][iColEd][cellData]
+            self.selIdxs[key][colNum] = cellData
+        else:
+            cellVal = cellData  
+            self.selIdxs[key][colNum] = -1
+
+        self.itemDataMap[key][colNum] = cellVal
+        self.SetStringItem(index, colNum, str(cellVal))
+
+    def EditCellKey(self, key, colName, cellData):
+        """!Changes value in list using index (changes during sorting)"""
+        colNum = self._getColumnNum(colName)   
+
+        iColEd = self.dataTypes["colEditable"]
+        if type(self.colsData[colNum][iColEd]).__name__ == "list":
+            cellVal = self.colsData[colNum][iColEd][cellData]
+            self.selIdxs[key][colNum] = cellData
+        else:
+            cellVal = cellData  
+            self.selIdxs[key][colNum] = -1
+
+        self.itemDataMap[key][colNum] = cellVal
+        index = self._findIndex(key)
+
+        self.SetStringItem(index, colNum, str(cellVal))
+
+    def _findIndex(self, key):
+        """!Find index for key"""
+        index = -1
+        while True:
+            index = self.GetNextItem(index,
+                                     wx.LIST_NEXT_BELOW)
+            if key == self.GetItemData(index):
+                return index
+            if index == -1:
+                break
+        return -1
+
+    def ChangeColEditable(self, colName, colType):
+        """!Change 3. item in constructor parameter cols (see the class constructor hint)"""     
+        colNum = self._getColumnNum(colName)
+        iColEd = self.dataTypes["colEditable"]
+        self.colsData[colNum][iColEd] = colType
+
+    def DeleteItem(self, event = None):
+        """!Delete selected item in list"""
+        if self.selected == wx.NOT_FOUND:
+            return
+
+        key = self.GetItemData(self.selected)
+        wx.ListCtrl.DeleteItem(self, self.selected)
+
+        del self.itemDataMap[key]
+        self.selIdxs.pop(key)
+
+        # update hidden columns
+        for hCol in self.hiddenCols.itervalues():    
+            hCol['itemDataMap'].pop(key) 
+            hCol['selIdxs'].pop(key)
+
+        # update key and point number
+        for newkey in range(key, len(self.itemDataMap)):
+            index = self.FindItemData(-1, newkey + 1)
+            self.itemDataMap[newkey][0] = newkey
+            self.SetStringItem(index, 0, str(newkey + 1))
+            self.SetItemData(index, newkey)
+
+        # update selected
+        if self.GetItemCount() > 0:
+            if self.selected < self.GetItemCount():
+                self.selectedkey = self.GetItemData(self.selected)
+            else:
+                self.selected = self.GetItemCount() - 1
+                self.selectedkey = self.GetItemData(self.selected)
+                
+            self.SetItemState(self.selected,
+                              wx.LIST_STATE_SELECTED,
+                              wx.LIST_STATE_SELECTED)
+        else:
+            self.selected = wx.NOT_FOUND
+            self.selectedkey = -1
+
+    def ClearItem(self, event):
+        """"!Set all values to default in selected item of points list and uncheck it."""
+        if self.selected == wx.NOT_FOUND:
+            return
+        index = self.selected
+
+        iDefVal = self.dataTypes["itemDefaultValue"]
+        iColEd = self.dataTypes["colEditable"]
+
+        i = 0
+        for col in self.colsData:
+            if i == 0:
+                i  += 1
+                continue
+            if type(col[iColEd]).__name__ == "list":
+                self.EditCell(index, i, col[iColEd][col[iDefVal]])
+            else:
+                self.EditCell(index, i, col[iDefVal])
+            i  += 1
+        self.CheckItem(index, False)
+
+    def ResizeColumns(self, minWidth = [90, 120]):
+        """!Resize columns"""
+        for i in range(self.GetColumnCount()):
+            self.SetColumnWidth(i, wx.LIST_AUTOSIZE)
+            # first column is checkbox, don't set to minWidth
+            if i > 0 and self.GetColumnWidth(i) < minWidth[i > 4]:
+                self.SetColumnWidth(i, minWidth[i > 4])
+
+        self.SendSizeEvent()
+
+    def GetSelected(self):
+        """!Get index of selected item."""
+        return self.selected
+
+    # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py
+    def GetSortImages(self):
+        return (self.sm_dn, self.sm_up)
+
+    # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py
+    def GetListCtrl(self):
+        return self
+
+    def OnItemActivated(self, event):
+        """!When item is double clicked, open editor to edit editable columns."""
+        data = []
+
+        index = event.GetIndex()
+        key = self.GetItemData(index)       
+        changed = False
+        iColEd = self.dataTypes["colEditable"]
+
+        for col in  enumerate(self.colsData):
+            if col[1][iColEd]:
+                data.append([col[0], #culumn number
+                             self.GetItem(index, col[0]).GetText(), #cell value 
+                             col[1][iColEd]]) #convert function for type check
+
+        if not data:
+            return
+        dlg = self.CreateEditDialog(data = data, pointNo = key)
+
+        if dlg.ShowModal() == wx.ID_OK:
+            editedData = dlg.GetValues() # string
+            
+            if len(editedData) == 0:
+                GError(parent = self,
+                       message=_("Invalid value inserted. Operation canceled."))
+            else:
+                i = 0
+                for editedCell in editedData:
+                    if editedCell[1] != data[i][1]:
+                        self.SetStringItem(index, editedCell[0], str(editedCell[1]))
+                        self.itemDataMap[key][editedCell[0]] = editedCell[1]
+                        changed = True
+                    i += 1 
+
+                self.selIdxs[key] = dlg.GetSelectionIndexes()
+        dlg.Destroy()
+        return changed
+        
+    def CreateEditDialog(self, data, pointNo):
+        """!Helper function
+        It is possible to define in child derived class
+        and adapt created dialog (e. g. it's title...) 
+        """
+
+        return  EditItem(parent=self, id=wx.ID_ANY, data = data, pointNo=pointNo)
+
+    def OnColClick(self, event):
+        """!ListCtrl forgets selected item..."""
+        self.selected = self.FindItemData(-1, self.selectedkey)
+        self.SetItemState(self.selected,
+                          wx.LIST_STATE_SELECTED,
+                          wx.LIST_STATE_SELECTED)
+        event.Skip()
+
+    def OnItemSelected(self, event):
+        """!Updates class attributes holding information about selected item"""
+        if self.selected != event.GetIndex():
+            self.selected = event.GetIndex()
+            self.selectedkey = self.GetItemData(self.selected)
+
+        event.Skip()
+
+    def getSmallUpArrowImage(self):
+        """!Get arrow up symbol for indication of sorting"""
+        stream = open(os.path.join(globalvar.ETCIMGDIR, 'small_up_arrow.png'), 'rb')
+        try:
+            img = wx.ImageFromStream(stream)
+        finally:
+            stream.close()
+        return img
+
+    def getSmallDnArrowImage(self):
+        """!Get arrow down symbol for indication of sorting"""
+        stream = open(os.path.join(globalvar.ETCIMGDIR, 'small_down_arrow.png'), 'rb')
+        try:
+            img = wx.ImageFromStream(stream)
+        finally:
+            stream.close()
+        return img
+
+    def _getColumnNum(self, colName):
+        """!Get position of column among showed columns 
+
+        @param colName - name of column
+
+        @return index of columns or -1 if col was not found
+        """
+
+        for iCol, col in enumerate(self.colsData):
+             if colName == col[0]:
+                 return iCol
+ 
+        return -1
+
+    def HideColumn(self, colName):
+        """!Hide column (hidden columns are not editable)
+
+        @param colName - name of column
+
+        @return True - if column was hidden
+        @return False - if position is not valid or column is not showed
+        """
+        colNum = self._getColumnNum(colName)
+        if colNum == -1:
+            return False
+
+        hiddenCol = self.GetColumn(colNum)
+        self.DeleteColumn(colNum) 
+
+        self.hiddenCols[colName] = {}
+        self.hiddenCols[colName]['wxCol'] = hiddenCol
+        hiddenMaps = []
+        hiddenSelIdxs = []
+        for item in self.itemDataMap:
+            hiddenMaps.append(item.pop(colNum))
+        for item in self.selIdxs:
+            hiddenSelIdxs.append(item.pop(colNum))
+
+        self.hiddenCols[colName]['itemDataMap'] = hiddenMaps
+        self.hiddenCols[colName]['selIdxs'] = hiddenSelIdxs
+        self.hiddenCols[colName]['colsData'] = self.colsData.pop(colNum)
+        self.ResizeColumns()
+
+        return True
+
+    def ShowColumn(self, colName, pos):
+        """!Show column
+
+        @param colName - name of column
+        @param pos - zero based index of position among showed columns (including added 'use' column)
+
+        @return True - if column was shown
+        @return False - if position is not valid or column is not hidden
+        """
+        if pos < 0 and pos >= self.self.GetColumnCount():
+            return False
+        if self.hiddenCols.has_key(colName):
+            col = self.hiddenCols[colName]
+
+            for item in enumerate(self.itemDataMap):
+                item[1].insert(pos, col['itemDataMap'][item[0]])
+            for item in enumerate(self.selIdxs):
+                item[1].insert(pos, col['selIdxs'][item[0]])
+
+            self.colsData.insert(pos, col['colsData'])
+
+            self.InsertColumnItem(pos, col['wxCol'])
+            self.ResizeColumns()
+            del self.hiddenCols[colName]  
+            return True
+
+        return False
+
+    def IsShown(self, colName):
+        """!Is column shown
+
+        @param colName - name of column
+
+        @return True - if is shown
+        @return False - if is not shown
+        """
+
+        if self._getColumnNum(colName) == -1:
+            return False
+        else:
+            return True
+
+class EditItem(wx.Dialog):
+    
+    def __init__(self, parent, data, pointNo, itemCap = "Point No." ,id=wx.ID_ANY,
+                 title =_("Edit point"), style=wx.DEFAULT_DIALOG_STYLE):
+        """!Dialog for editing item cells in list"""
+
+        wx.Dialog.__init__(self, parent, id, title=_(title), style=style)
+
+        self.parent = parent
+        panel = wx.Panel(parent=self)
+        sizer = wx.BoxSizer(wx.VERTICAL)
+
+        box = wx.StaticBox (parent=panel, id=wx.ID_ANY,
+                            label=" %s %s " % (_(itemCap), str(pointNo + 1)))
+        boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+
+        # source coordinates
+        gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
+       
+        self.fields = [] 
+        self.data = deepcopy(data)
+
+
+        col = 0
+        row = 0
+        iField = 0
+        for cell in self.data:
+
+            # Select
+            if type(cell[2]).__name__ == "list":
+                self.fields.append(wx.ComboBox(parent = panel, id = wx.ID_ANY,
+                                               choices = cell[2],
+                                               style = wx.CB_READONLY, 
+                                               size = (110, -1)))
+            # Text field
+            else:
+                if cell[2] == float:
+                    validator = FloatValidator()
+                elif cell[2] == int:
+                    validator = IntegerValidator()
+                else:
+                    validator = None
+
+                if validator:
+                    self.fields.append(wx.TextCtrl(parent=panel, id=wx.ID_ANY, 
+                                                   validator = validator, size=(150, -1)))
+                else:
+                    self.fields.append(wx.TextCtrl(parent=panel, id=wx.ID_ANY, 
+                                                   size=(150, -1)))
+                    self.fields[iField].SetValue(str(cell[1]))
+
+            label = wx.StaticText(parent = panel, id=wx.ID_ANY,
+                                  label = _(parent.GetColumn(cell[0]).GetText()) + ":") # name of column)
+
+            gridSizer.Add(item=label,
+                          flag=wx.ALIGN_CENTER_VERTICAL,
+                          pos=(row, col))
+
+            col += 1
+
+            gridSizer.Add(item=self.fields[iField],
+                          pos=(row, col))
+
+
+            if col%3 == 0:
+                col = 0
+                row += 1
+            else:
+                col += 1
+
+            iField += 1
+
+        boxSizer.Add(item=gridSizer, proportion=1,
+                  flag=wx.EXPAND | wx.ALL, border=5)
+
+        sizer.Add(item=boxSizer, proportion=1,
+                  flag=wx.EXPAND | wx.ALL, border=5)
+
+        #
+        # buttons
+        #
+        self.btnCancel = wx.Button(panel, wx.ID_CANCEL)
+        self.btnOk = wx.Button(panel, wx.ID_OK)
+        self.btnOk.SetDefault()
+
+        btnSizer = wx.StdDialogButtonSizer()
+        btnSizer.AddButton(self.btnCancel)
+        btnSizer.AddButton(self.btnOk)
+        btnSizer.Realize()
+
+        sizer.Add(item=btnSizer, proportion=0,
+                  flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
+
+        panel.SetSizer(sizer)
+        sizer.Fit(self)
+
+    def GetValues(self):
+        """!Return list of values (as strings).
+        """
+
+        iField = 0
+        for cell in self.data:
+            value = self.fields[iField].GetValue()
+            
+            if type(cell[2]).__name__ == "list":
+                    cell[1] = value
+            else:
+                try:
+                    cell[1] = cell[2](value)
+                except ValueError:
+                    return []
+            iField += 1
+
+        return self.data
+
+    def GetSelectionIndexes(self):
+        """!Return indexes of selected values (works just for choice columns).
+        """
+        iField = 0
+        itemIndexes = []
+        for cell in self.parent.colsData:            
+            if type(cell[2]).__name__ == "list":
+                itemIndexes.append(self.fields[iField].GetSelection())
+            else:
+                itemIndexes.append(-1) # not a choise column 
+            if cell[2]:   
+                iField += 1
+
+        return itemIndexes
+
+
+


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

Modified: grass/trunk/gui/wxpython/xml/menudata.xml
===================================================================
--- grass/trunk/gui/wxpython/xml/menudata.xml	2013-01-03 16:59:02 UTC (rev 54514)
+++ grass/trunk/gui/wxpython/xml/menudata.xml	2013-01-03 17:46:18 UTC (rev 54515)
@@ -2314,6 +2314,13 @@
         <menu>
           <label>Network analysis</label>
           <items>`
+           <menuitem>
+              <label>Vector network analysis tool</label>
+              <help>Tool for interactive vector network analysis.</help>
+              <keywords>gui,vector,network</keywords>
+              <handler>OnVNet</handler>
+            </menuitem>
+            <separator />
             <menuitem>
               <label>Network preparation</label>
               <help>Performs network maintenance.</help>



More information about the grass-commit mailing list