[GRASS-SVN] r56736 - grass/trunk/gui/wxpython/vnet

svn_grass at osgeo.org svn_grass at osgeo.org
Sun Jun 16 14:36:51 PDT 2013


Author: turek
Date: 2013-06-16 14:36:51 -0700 (Sun, 16 Jun 2013)
New Revision: 56736

Added:
   grass/trunk/gui/wxpython/vnet/vnet_core.py
   grass/trunk/gui/wxpython/vnet/vnet_data.py
   grass/trunk/gui/wxpython/vnet/vnet_utils.py
Modified:
   grass/trunk/gui/wxpython/vnet/__init__.py
   grass/trunk/gui/wxpython/vnet/dialogs.py
   grass/trunk/gui/wxpython/vnet/toolbars.py
   grass/trunk/gui/wxpython/vnet/widgets.py
Log:
wx.vnet: basic refactoring (work in progress), added code for turns support (curently hidden until turns backend will be in GRASS)

Modified: grass/trunk/gui/wxpython/vnet/__init__.py
===================================================================
--- grass/trunk/gui/wxpython/vnet/__init__.py	2013-06-16 18:05:10 UTC (rev 56735)
+++ grass/trunk/gui/wxpython/vnet/__init__.py	2013-06-16 21:36:51 UTC (rev 56736)
@@ -2,4 +2,7 @@
     'widgets',
     'dialogs',
     'toolbars',
+    'vnet_core',
+    'vnet_data',
+    'vnet_utils'
     ]

Modified: grass/trunk/gui/wxpython/vnet/dialogs.py
===================================================================
--- grass/trunk/gui/wxpython/vnet/dialogs.py	2013-06-16 18:05:10 UTC (rev 56735)
+++ grass/trunk/gui/wxpython/vnet/dialogs.py	2013-06-16 21:36:51 UTC (rev 56736)
@@ -1,35 +1,32 @@
 """!
 @package vnet.dialogs
 
- at brief Dialog for vector network analysis front-end
+ at brief Dialogs for vector network analysis front-end
 
 Classes:
  - dialogs::VNETDialog
  - dialogs::PtsList
  - dialogs::SettingsDialog
- - dialogs::AddLayerDialog
- - dialogs::VnetTmpVectMaps
- - dialogs::VectMap
- - dialogs::History
+ - dialogs::CreateTtbDialog
+ - dialogs::OutputVectorDialog
  - dialogs::VnetStatusbar
+ - dialogs::DefIntesectionTurnCostDialog
+ - dialogs::DefGlobalTurnsDialog
+ - dialogs::TurnAnglesList
 
-(C) 2012 by the GRASS Development Team
+(C) 2012-2013 by the GRASS Development Team
 
 This program is free software under the GNU General Public License
 (>=v2). Read the file COPYING that comes with GRASS for details.
 
 @author Stepan Turek <stepan.turek seznam.cz> (GSoC 2012, mentor: Martin Landa)
+ at author Lukas Bocan <silent_bob centrum.cz> (turn costs support)
+ at author Eliska Kyzlikova <eliska.kyzlikova gmail.com> (turn costs support)
 """
 
 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
@@ -38,6 +35,8 @@
 import wx.aui
 import wx.lib.flatnotebook  as FN
 import wx.lib.colourselect as csel
+import wx.lib.mixins.listctrl  as  listmix
+import wx.lib.scrolledpanel    as scrolled
 
 from core             import globalvar, utils
 from core.gcmd        import RunCommand, GMessage
@@ -45,14 +44,16 @@
 from core.settings    import UserSettings
 
 from dbmgr.base       import DbMgrBase 
+from dbmgr.vinfo      import VectorDBInfo
 
 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
+from vnet.vnet_core   import VNETManager
+from vnet.vnet_utils  import DegreesToRadians, RadiansToDegrees, GetNearestNodeCat, ParseMapStr
 
 #Main TODOs
 # - when layer tree of is changed, tmp result map is removed from render list 
@@ -70,60 +71,38 @@
         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 
+        self.parent  = parent 
+        self.mapDisp  = giface.GetMapDisplay()
+        self.mapWin = giface.GetMapWindow().GetMapWindow()
         self._giface = giface
 
         # 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
-
+        self.defIsecTurnsHndlrReg = 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()
+        self.vnet_mgr = VNETManager(self, giface)
 
+        self.vnet_mgr.analysisDone.connect(self.AnalysisDone)
+        self.vnet_mgr.ttbCreated.connect(self.TtbCreated)
+        self.vnet_mgr.snapping.connect(self.Snapping)
+        self.vnet_mgr.pointsChanged.connect(self.PointsChanged)
+
+        self.currAnModule, valid = self.vnet_mgr.GetParam("analysis")
+
         # toobars
         self.toolbars = {}
-        self.toolbars['mainToolbar'] = MainToolbar(parent = self)
-        self.toolbars['analysisToolbar'] = AnalysisToolbar(parent = self)
+        self.toolbars['mainToolbar'] = MainToolbar(parent = self, vnet_mgr = self.vnet_mgr)
+        self.toolbars['analysisToolbar'] = AnalysisToolbar(parent = self, vnet_mgr = self.vnet_mgr)
         #
         # 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 |
@@ -134,14 +113,13 @@
         self.stBar = VnetStatusbar(parent = self.mainPanel, style = 0)
         self.stBar.SetFieldsCount(number = 1)
     
-        
+        self.def_isec_turns = None
+
         # 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 
@@ -167,20 +145,9 @@
         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)
+        self.SetSize((370, 550))
+        self.SetMinSize((370, 420))
 
-        # 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))
@@ -189,23 +156,13 @@
         self.notebook.SetSelectionByName("parameters")
         self.toolbars['analysisToolbar'].SetMinSize((-1, self.toolbars['mainToolbar'].GetSize()[1]))
 
+        self.toolbars['mainToolbar'].UpdateUndoRedo(0, 0)
+
     def  __del__(self):
         """!Removes temp layers, unregisters handlers and graphics"""
-        update = self.tmpMaps.DeleteAllTmpMaps()
+        #TODO onclose
+        pass
 
-        self.mapWin.UnregisterGraphicsToDraw(self.pointsToDraw)
-
-        if self.handlerRegistered:
-            self.mapWin.UnregisterMouseEventHandler(wx.EVT_LEFT_DOWN, 
-                                                  self.OnMapClickHandler)
-        if update:
-            up_map_evt = gUpdateMap(render = True, renderVector = True)
-            wx.PostEvent(self.mapWin, up_map_evt)
-        else:
-            up_map_evt = gUpdateMap(render = True, renderVector = True)
-            wx.PostEvent(self.mapWin, up_map_evt)
-
-
     def _addPanes(self):
         """!Adds toolbar pane and pane with tabs"""
         self._mgr.AddPane(self.toolbars['mainToolbar'],
@@ -254,8 +211,10 @@
                               text=_('Points'), 
                               name = 'points')
 
-        self.list = PtsList(parent = pointsPanel, dialog = self, cols = self.cols)
-        self.toolbars['pointsList'] = PointListToolbar(parent = pointsPanel, list = self.list)
+        self.list = PtsList(parent = pointsPanel, vnet_mgr = self.vnet_mgr)
+        self.toolbars['pointsList'] = PointListToolbar(parent = pointsPanel, 
+                                                       dialog = self, 
+                                                       vnet_mgr = self.vnet_mgr)
 
         anSettingsPanel = wx.Panel(parent = pointsPanel)
 
@@ -265,7 +224,9 @@
         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"].Bind(wx.EVT_SPINCTRL, lambda event : self.MaxDist())
         self.anSettings["max_dist"].SetValue(100000) #TODO init val
+        self.MaxDist()
 
         #showCutPanel =  wx.Panel(parent = anSettingsPanel)
         #self.anSettings["show_cut"] = wx.CheckBox(parent = showCutPanel, id=wx.ID_ANY,
@@ -275,7 +236,9 @@
         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"].Bind(wx.EVT_TEXT, lambda event : self.IsoLines())
         self.anSettings["iso_lines"].SetValue("1000,2000,3000")
+        self.IsoLines()
 
         # Layout
         AnalysisSizer = wx.BoxSizer(wx.VERTICAL)
@@ -313,6 +276,14 @@
         anSettingsPanel.SetSizer(anSettingsSizer)
         pointsPanel.SetSizer(AnalysisSizer)
 
+    def MaxDist(self):
+        val = self.anSettings["max_dist"].GetValue()
+        self.vnet_mgr.SetParams({"max_dist" : val}, {})
+
+    def IsoLines(self):
+        val = self.anSettings["iso_lines"].GetValue()
+        self.vnet_mgr.SetParams({"iso_lines" : val}, {})
+
     def OnShowCut(self, event):
         """!Shows vector map with minimal cut (v.net.flow) - not yet implemented"""
         val = event.IsChecked()
@@ -335,8 +306,8 @@
                               text = _("Output"), 
                               name = 'output')
 
-        self.goutput = GConsole(guiparent = self)
-        self.gwindow = GConsoleWindow(parent = outputPanel, gconsole = self.goutput)
+        goutput = self.vnet_mgr.goutput #TODO make interface
+        self.gwindow = GConsoleWindow(parent = outputPanel, gconsole = goutput)
 
         #Layout
         outputSizer = wx.BoxSizer(wx.VERTICAL)
@@ -347,7 +318,7 @@
 
     def _createParametersPage(self):
         """!Tab for selection of data for analysis"""
-        dataPanel = wx.Panel(parent=self)
+        dataPanel = scrolled.ScrolledPanel(parent=self)
         self.notebook.AddPage(page = dataPanel,
                               text=_('Parameters'), 
                               name = 'parameters')
@@ -356,12 +327,18 @@
                         ['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],
+                        #['tlayer', "Layer with turntable:", LayerSelect],
+                        #['tuclayer', "Layer with unique categories for turntable:", LayerSelect],
+                        ['afcolumn', "", ColumnSelect],
+                        ['abcolumn', "", ColumnSelect],
+                        ['ncolumn',  "", ColumnSelect],
                       ]
 
+        #self.useTurns = wx.CheckBox(parent = dataPanel, id=wx.ID_ANY,
+        #                            label = _('Use turns'))
+        
         selPanels = {}
+
         for dataSel in dataSelects:
             selPanels[dataSel[0]] = wx.Panel(parent = dataPanel)
             if dataSel[0] == 'input':
@@ -378,6 +355,11 @@
                 self.addToTreeBtn.Disable()
                 self.addToTreeBtn.Bind(wx.EVT_BUTTON, self.OnToTreeBtn)
             elif dataSel[0] != 'input':
+                #if dataSel[0] == "tlayer":
+                #    self.createTtbBtn = wx.Button(parent = selPanels[dataSel[0]], 
+                #                                 label = _("Create turntable")) 
+                #    self.createTtbBtn.Bind(wx.EVT_BUTTON, self.OnCreateTtbBtn)
+
                 self.inputData[dataSel[0]] = dataSel[2](parent = selPanels[dataSel[0]],  
                                                         size = (-1, -1))
             label[dataSel[0]] =  wx.StaticText(parent =  selPanels[dataSel[0]], 
@@ -388,6 +370,13 @@
         self.inputData['alayer'].Bind(wx.EVT_TEXT, self.OnALayerSel)
         self.inputData['nlayer'].Bind(wx.EVT_TEXT, self.OnNLayerSel)
 
+        for params in ["afcolumn", "abcolumn", "ncolumn"]:#, "tlayer", "tuclayer"]:
+            self.inputData[params].Bind(wx.EVT_TEXT, lambda event : self._setInputData())
+
+        #self.useTurns.Bind(wx.EVT_CHECKBOX,
+        #                    lambda event: self.UseTurns())
+        #self.UseTurns()
+
         # Layout
         mainSizer = wx.BoxSizer(wx.VERTICAL)
         box = wx.StaticBox(dataPanel, -1, "Vector map and layers for analysis")
@@ -396,15 +385,21 @@
         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':
+        for sel in ['input', 'alayer', 'nlayer']:#, 'tlayer', 'tuclayer']:
+            if sel == 'input':
                 btn = self.addToTreeBtn
+            #elif sel == "tlayer":
+            #    btn = self.createTtbBtn
             else:
                 btn = None
+            #if sel == 'tlayer':
+            #    bsizer.Add(item = self.useTurns, proportion = 0,
+            #                flag = wx.TOP | wx.LEFT | wx.RIGHT, border = 5)                       
+
             selPanels[sel].SetSizer(self._doSelLayout(title = label[sel], 
                                                       sel = self.inputData[sel], 
                                                       btn = btn))
-            bsizer.Add(item = selPanels[sel], proportion = 1,
+            bsizer.Add(item = selPanels[sel], proportion = 0,
                        flag = wx.EXPAND)
 
         box = wx.StaticBox(dataPanel, -1, "Costs")    
@@ -418,8 +413,12 @@
             bsizer.Add(item = selPanels[sel], proportion = 0,
                        flag = wx.EXPAND)
 
+
         dataPanel.SetSizer(mainSizer)
+        dataPanel.SetupScrolling()
 
+        dataPanel.SetAutoLayout(1)
+
     def _doSelLayout(self, title, sel, btn = None): 
         # helper function for layout of self.inputData widgets initialized in _createParametersPage
         selSizer = wx.BoxSizer(orient = wx.VERTICAL)
@@ -494,7 +493,7 @@
         # 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"]
+        haveDbMgr = self.vnet_mgr.GetAnalysisProperties(analysis)["resultProps"]["dbMgr"]
 
         if haveDbMgr and self.notebook.GetPageIndexByName('resultDbMgr') == -1:
             self.notebook.AddPage(page = self.resultDbMgrData['browse'],
@@ -587,7 +586,7 @@
     def OnToTreeBtn(self, event):
         """!Add vector map into layer tree"""
         vectorMap = self.inputData['input'].GetValue()
-        vectMapName, mapSet = self._parseMapStr(vectorMap)
+        vectMapName, mapSet = ParseMapStr(vectorMap)
         vectorMap = vectMapName + '@' + mapSet
         existsMap = grass.find_file(name = vectMapName, 
                                     element = 'vector', 
@@ -614,20 +613,72 @@
             up_map_evt = gUpdateMap(render = True, renderVector = True)
             wx.PostEvent(self.mapWin, up_map_evt)
 
+    def UseTurns(self):
+        if self.useTurns.IsChecked():
+            self.inputData["tlayer"].GetParent().Show()
+            self.inputData["tuclayer"].GetParent().Show()
+
+            self.vnet_mgr.SetParams(params = {}, flags = {"t" : True})
+        else:
+            self.inputData["tlayer"].GetParent().Hide()
+            self.inputData["tuclayer"].GetParent().Hide()
+
+            self.vnet_mgr.SetParams(params = {}, flags = {"t" : False})
+
+        self.Layout()
+
+    def PointsChanged(self, method, kwargs):
+
+        if method == "EditMode" and not kwargs["activated"]:
+            ptListToolbar = self.toolbars['pointsList']
+            if ptListToolbar:
+                ptListToolbar.ToggleTool(id = ptListToolbar.GetToolId("insertPoint"),
+                                         toggle = False)
+
+        if method == "EditMode" and kwargs["activated"]:
+            ptListToolbar = self.toolbars['pointsList']
+            if ptListToolbar:
+                ptListToolbar.ToggleTool(id = ptListToolbar.GetToolId("insertPoint"),
+                                         toggle = True)
+
+        if method == "SetPointData" and ("e" in kwargs.keys() or "n" in kwargs.keys()):
+          self.notebook.SetSelectionByName("points")
+
+
+    def OnCreateTtbBtn(self, event):
+
+        params, err_params, flags = self.vnet_mgr.GetParams()
+        dlg = CreateTtbDialog(parent = self, init_data = params)
+
+        if dlg.ShowModal() == wx.ID_OK:
+            self.stBar.AddStatusItem(text = _('Creating turntable...'),
+                                     key = 'ttb',
+                                     priority =  self.stPriorities['important'])
+
+            params = dlg.GetData()
+            if not self.vnet_mgr.CreateTttb(params):
+                self.stBar.RemoveStatusItem('ttb')    
+        dlg.Destroy()              
+
+    def TtbCreated(self):
+
+        params, err_params, flags = self.vnet_mgr.GetParams()
+        self._updateParamsTab(params, flags)
+        
+        self.stBar.RemoveStatusItem('ttb')  
+
     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)
+        if self.vnet_mgr.IsSnappingActive(): #TODO should be in vnet_mgr
+            self.vnet_mgr.Snapping(activate = True)
 
         vectMapName, mapSet = self._parseMapStr(self.inputData['input'].GetValue())
         vectorMap = vectMapName + '@' + mapSet
 
-        self.inputData['alayer'].Clear()
-        self.inputData['nlayer'].Clear()
+        for sel in ['alayer', 'nlayer']:#, 'tlayer', 'tuclayer']:
+            self.inputData[sel].Clear()
+            self.inputData[sel].InsertLayers(vector = vectorMap)
 
-        self.inputData['alayer'].InsertLayers(vector = vectorMap)
-        self.inputData['nlayer'].InsertLayers(vector = vectorMap)
-
         items = self.inputData['alayer'].GetItems()
         itemsLen = len(items)
         if itemsLen < 1:
@@ -657,6 +708,15 @@
         self.OnALayerSel(event) 
         self.OnNLayerSel(event)
 
+        self._setInputData()
+
+    def _updateParamsTab(self, params, flags):
+        #TODO flag
+
+                #'tlayer', 'tuclayer', 
+        for k in ['input', 'alayer', 'nlayer', 'afcolumn', 'abcolumn', 'ncolumn']:
+            self.inputData[k].SetValue(params[k])
+
     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(), 
@@ -666,63 +726,26 @@
                                                  layer = self.inputData['alayer'].GetValue(), 
                                                  type = self.columnTypes)
 
+        self._setInputData()
 
     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)
+        if self.vnet_mgr.IsSnappingActive():
+            self.vnet_mgr.Snapping(activate = True)
 
         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 = {}
+        self._setInputData()
 
-        mapVal = self.inputData['input'].GetValue()
-        mapName, mapSet = self._parseMapStr(mapVal)
-        vectMaps = grass.list_grouped('vect')[mapSet]
+    def _setInputData(self):
+        params = {}
+        for k, v in self.inputData.iteritems():
+            params[k] = v.GetValue()
+        flags = {}
+        self.vnet_mgr.SetParams(params, flags)
 
-        # 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 != self.inputData[colInptF].GetValue():
-                    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("@")
@@ -734,137 +757,41 @@
         
         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"              
+    def OnDefIsecTurnCosts(self, event):
+        """!Registers/unregisters mouse handler into map window"""
+        if self.defIsecTurnsHndlrReg == False:
+            self.mapWin.RegisterMouseEventHandler(wx.EVT_LEFT_DOWN, 
+                                                  self.OnDefIsecTurnCost,
+                                                  wx.StockCursor(wx.CURSOR_CROSS))
+            self.defIsecTurnsHndlrReg = True
         else:
-            wxPen = "used1cat"       
+            self.mapWin.UnregisterMouseEventHandler(wx.EVT_LEFT_DOWN, 
+                                                    self.OnDefIsecTurnCost)
 
-        item.SetPropertyVal('label', str(itemIndex + 1))
-        item.SetPropertyVal('penName', wxPen)       
+            self.defIsecTurnsHndlrReg = False
 
-    def OnMapClickHandler(self, event):
+    def OnDefGlobalTurnCosts(self, event):
+
+        dialog = DefGlobalTurnsDialog(self, data = self.vnet_mgr.GetGlobalTurnsData())
+        dialog.Show()
+
+    def OnDefIsecTurnCost(self, event): #TODO move to vnet mgr?
         """!Take coordinates from map window"""
         if event == 'unregistered':
             ptListToolbar = self.toolbars['pointsList']
             if ptListToolbar:
-                ptListToolbar.ToggleTool( id = ptListToolbar.GetToolId("insertPoint"),
+                ptListToolbar.ToggleTool( id = ptListToolbar.GetToolId("isec_turn_edit"),
                                           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', 
@@ -872,143 +799,49 @@
         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
+        params, err_params, flags = self.vnet_mgr.GetParams()
 
-        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
+        if "input" in err_params:
+            GMessage(parent = self,
+                     message = _("Input vector map does not exists."))
 
-        nodeNum =  vectlib.Vect_find_node(openedMap,     
-                                          c_double(e), 
-                                          c_double(n), 
-                                          c_double(0), 
-                                          c_double(snapTreshDist),
-                                          vectlib.WITHOUT_Z)
+        if ["tlayer", "tuclayer"] in err_params:
+            GMessage(parent = self, message = "Please choose existing turntable layer and unique categories layer in Parameters tab.")
 
-        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
+        cat = GetNearestNodeCat(e, n, int(params['tuclayer']), snapTreshDist, params["input"])
 
-        coords[0] = e
-        coords[1] = n
-        return True
+        if not self.def_isec_turns:
+            self.def_isec_turns = DefIntesectionTurnCostDialog(self, self.parent)
+            self.def_isec_turns.SetSize((500, 400))
 
+        self.def_isec_turns.SetData(params["input"], params["tlayer"])
+        self.def_isec_turns.SetIntersection(cat)
+        self.def_isec_turns.Show()
+
     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())
+        ret = self.vnet_mgr.RunAnalysis()
 
-        # save data from 
-        self._saveAnInputToHist()
-
+        #TODO
         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())
+        if ret < 0:
+            self.stBar.RemoveStatusItem(key = 'analyze')
+            if ret == -2:
+                self.notebook.SetSelectionByName("parameters")
 
-        catPts = self._getPtByCat()
+    def AnalysisDone(self):
 
-        if self.currAnModule == "v.net.path":
-            self._vnetPathRunAn(cmdParams, catPts)
-        else:
-            self._runAn(cmdParams, catPts)
+        curr_step, steps_num = self.vnet_mgr.GetHistStep()
+        self.toolbars['mainToolbar'].UpdateUndoRedo(curr_step, steps_num)
 
-    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"]
+        self.tmp_result = self.vnet_mgr.GetResults() 
 
-        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)
-
-        up_map_evt = gUpdateMap(render = True, renderVector = True)
-        wx.PostEvent(self.mapWin, up_map_evt)
-
         mainToolbar = self.toolbars['mainToolbar']
         id = vars(mainToolbar)['showResult']
         mainToolbar.ToggleTool(id =id,
@@ -1016,236 +849,12 @@
 
         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)
-
         up_map_evt = gUpdateMap(render = True, renderVector = True)
         wx.PostEvent(self.mapWin, up_map_evt)
 
-        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']
@@ -1256,109 +865,30 @@
             mainToolbar.ToggleTool(id =id,
                                    toggle = False)
         elif toggleState:
-            self._checkResultMapChanged(self.tmp_result)
-            cmd = self.GetLayerStyle()
-            self.tmp_result.AddRenderLayer(cmd)
+            self.vnet_mgr.ShowResult(True)
         else:
-            cmd = self.GetLayerStyle()
-            self.tmp_result.DeleteRenderLayer()
+            self.vnet_mgr.ShowResult(False)
 
-        up_map_evt = gUpdateMap(render = True, renderVector = True)
-        wx.PostEvent(self.mapWin, up_map_evt)
-
-    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)
+        dlg = OutputVectorDialog(parent = self)
+        dlg.ShowModal()
+        self.vnet_mgr.SaveTmpLayer(dlg.vectSel.GetValue())
+        dlg.Destroy()
 
-        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:
-                up_map_evt = gUpdateMap(render = True, renderVector = True)
-                wx.PostEvent(self.mapWin, up_map_evt)
-
     def OnSettings(self, event):
         """!Displays vnet settings dialog"""
-        dlg = SettingsDialog(parent=self, id=wx.ID_ANY, title=_('Settings'))
+        dlg = SettingsDialog(parent=self, id=wx.ID_ANY, 
+                             title=_('Settings'), vnet_mgr = self.vnet_mgr)
         
-        if dlg.ShowModal() == wx.ID_OK:
-            pass
-        
+        dlg.ShowModal()
         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]
+        self.currAnModule = self.vnet_mgr.GetAnalyses()[iAn]
+        self.vnet_mgr.SetParams({"analysis" : self.currAnModule}, {})
 
         # update dialog for particular analysis
         if self.currAnModule == "v.net.iso":
@@ -1373,9 +903,17 @@
 
         # 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"]
+
+        an_props = self.vnet_mgr.GetAnalysisProperties()
+
+        used_cols = []
+        attrCols = an_props["cmdParams"]["cols"]
+
+
+        for col in attrCols.iterkeys():
+
+            if "inputField" in attrCols[col]:
+                colInptF = attrCols[col]["inputField"]
             else:
                 colInptF = col
 
@@ -1383,690 +921,214 @@
                 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()
+            inputPanel.Show()
+            inputPanel.FindWindowByName(colInptF).SetLabel(attrCols[col]["label"])
 
-        # 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)
+            if col != colInptF:
+               skip.append(colInptF)
+            used_cols.append(colInptF)
 
-            currParamsCats = self.vnetParams[self.currAnModule]["cmdParams"]["cats"]
-            self.list.AdaptPointsList(currParamsCats)
-        else:
-            if self.list.IsShown('type'):
-                self.list.HideColumn('type')
+        for col in ["abcolumn", "afcolumn", "ncolumn"]:
+            if col not in used_cols:
+                inputPanel = self.inputData[colInptF].GetParent()
+                inputPanel.Hide()
 
-        # 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)
+        self.Layout()
 
-    def OnSnapping(self, event):
+    def Snapping(self, evt):
         """!Start/stop snapping mode"""
-        ptListToolbar = self.toolbars['pointsList']
 
-        if not haveCtypes:
+        if evt == "deactivated":
+            self.stBar.RemoveStatusItem(key = 'snap')
+            ptListToolbar = self.toolbars['pointsList']
             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() 
-                
-                up_map_evt = gUpdateMap(render = False, renderVector = False)
-                wx.PostEvent(self.mapWin, up_map_evt)
-
-            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:
+        elif evt == "computing_points":
             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()
+        elif evt == "computing_points_done":
+            self.stBar.RemoveStatusItem(key = 'snap')
 
-            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()
-
-            up_map_evt = gUpdateMap(render = True, renderVector = True)
-            wx.PostEvent(self.mapWin, up_map_evt)
-
-    def _onToPointsDone(self, event):
+    def SnapPointsDone(self):
         """!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() 
 
-            up_map_evt = gUpdateMap(render = True, renderVector = True)
-            wx.PostEvent(self.mapWin, up_map_evt)
-
     def OnUndo(self, event):
         """!Step back in history"""
-        histStepData = self.history.GetPrev()
-        self.toolbars['mainToolbar'].UpdateUndoRedo()
 
-        if histStepData:
-            self._updateHistStepData(histStepData)
+        curr_step, steps_num = self.vnet_mgr.Undo()
+        self._updateDialog()
+        self.toolbars['mainToolbar'].UpdateUndoRedo(curr_step, steps_num)
 
     def OnRedo(self, event):
         """!Step forward in history"""
-        histStepData = self.history.GetNext()
-        self.toolbars['mainToolbar'].UpdateUndoRedo()
 
-        if histStepData:
-            self._updateHistStepData(histStepData)
+        curr_step, steps_num = self.vnet_mgr.Redo()
+        self._updateDialog()
+        self.toolbars['mainToolbar'].UpdateUndoRedo(curr_step, steps_num)
 
-    def _saveAnInputToHist(self):
-        """!Save all data needed for analysis into history buffer"""
-        pts = self.pointsToDraw.GetAllItems()
+    def _updateDialog(self):
+        params, err_params, flags = self.vnet_mgr.GetParams()
+        self._updateParamsTab(params, flags)
 
-        for iPt, pt in enumerate(pts):
-            ptName = "pt" + str(iPt)
+        anChoice = self.toolbars['analysisToolbar'].anChoice
+        anChoice.SetSelection(self.vnet_mgr.GetAnalyses().index(params["analysis"]))
+        self.currAnModule = params["analysis"] 
+        self.resultDbMgrData['analysis'] = params["analysis"]
 
-            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'))
+        # set analysis combobox
+        anChoice = self.toolbars['analysisToolbar'].anChoice
+        anChoice.SetSelection(self.vnet_mgr.GetAnalyses().index(params["analysis"]))
 
-            topology = self.list.GetCellValue(iPt, 'topology')
-            self.history.Add(key = "points", 
-                             subkey = [ptName, "topology"], 
-                             value = topology)
+        self._updateResultDbMgrPage()
+        self._updateDbMgrData()
 
+        self.OnAnalysisChanged(None)
 
-            self.history.Add(key = "points", 
-                             subkey = [ptName, "checked"], 
-                             value = self.list.IsChecked(iPt))
+class PtsList(PointsList):
+    def __init__(self, parent, vnet_mgr, id=wx.ID_ANY):
+        """! List with points for analysis"""
+        self.updateMap = True
+        self.vnet_mgr = vnet_mgr
+        self.pts_data = self.vnet_mgr.GetPointsManager()
 
-            for inpName, inp in self.inputData.iteritems():
+        pts_data_cols = self.pts_data.GetColumns(only_relevant = False)
 
-                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)
+        cols = []
+        for i_col, name in enumerate(pts_data_cols["name"]): 
+            if i_col == 0:
+                continue
+            cols.append([name, pts_data_cols["label"][i_col], 
+                              pts_data_cols["type"][i_col], pts_data_cols["def_vals"][i_col]])
 
-        for settName, sett in self.anSettings.iteritems():
-            self.history.Add(key = "an_settings", 
-                             subkey = settName, 
-                             value = sett.GetValue())
+        PointsList.__init__(self, parent = parent, cols = cols, id =  id)      
 
+        self.vnet_mgr.pointsChanged.connect(self.PointsChanged)
+        self.vnet_mgr.parametersChanged.connect(self.ParametersChanged)
 
-    def _saveHistStep(self):
-        """!Save new step into history"""
-        removedHistData = self.history.SaveHistStep()
-        self.toolbars['mainToolbar'].UpdateUndoRedo()
+        analysis, valid = self.vnet_mgr.GetParam("analysis")
 
-        if not removedHistData:
-            return
+        self.AnalysisChanged(analysis)
 
-        # 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)
+        for iPt in range(self.pts_data.GetPointsCount()):
+            self.AddItem()
+            pt_dt = self.pts_data.GetPointData(iPt)
+            self.SetData(iPt, pt_dt)
+        self.Select(self.pts_data.GetSelected())
 
-    def _updateHistStepData(self, histStepData):
-        """!Updates dialog according to chosen history step"""
+    def AnalysisChanged(self, analysis):
+        active_cols = self.pts_data.GetColumns()
+        if 'type' in active_cols["name"]:
+            if not self.IsShown('type'):
+                self.ShowColumn('type', 1)
 
-        # set analysis module
-        self.currAnModule = histStepData["vnet_modules"]["curr_module"]
+            type_idx = active_cols["name"].index("type")
+            type_labels = active_cols["type"][type_idx]
 
-        # optimization -map is not re-rendered when change in points list is done
-        self.list.SetUpdateMap(updateMap = False)
+            self.ChangeColEditable('type', type_labels)
+            colNum = self._getColumnNum('type')
 
-        # delete points list items
-        while self.list.GetSelected() != wx.NOT_FOUND:
-            self.list.DeleteItem()
+            for iItem, item in enumerate(self.itemDataMap): 
+                self.EditCellKey(iItem, 'type', self.selIdxs[iItem][colNum])
 
-        # 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')
+                if not item[1]:               
+                    self.CheckItem(iItem, False)
 
-        # 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"])
+            if self.IsShown('type'):
+                self.HideColumn('type')
 
-        # set analysis combobox
-        anChoice = self.toolbars['analysisToolbar'].anChoice
-        anChoice.SetSelection(self.vnetModulesOrder.index(self.currAnModule)) 
+    def ParametersChanged(self, method, kwargs):
+            if "analysis" in kwargs["changed_params"].keys():
+                self.AnalysisChanged(analysis = kwargs["changed_params"]["analysis"])
 
-        # 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)
+    def OnItemActivated(self, event):
+        changed, key = PointsList.OnItemActivated(self, event)
+        
+        if not changed:
+            return
 
-                cmd = self.GetLayerStyle()
-                self.tmp_result.AddRenderLayer(cmd)
+        dt_dict = {}
+        active_cols = self.pts_data.GetColumns()
+        for col in active_cols["name"]:
+            if col == "use":
+                continue
+            dt_dict[col] = self.GetCellValue(key, col)
 
-        # update Parameters tab
-        histInputData = histStepData["input_data"]
-        for inpName, inp in histInputData.iteritems():
-            self.inputData[inpName].SetValue(str(inp)) 
-            if inpName == "input":
-                inpMap = inp
+        self.pts_data.SetPointData(key, dt_dict)
 
-        prevInpModTime = str(histStepData["other"]["input_modified"])
-        currInpModTime = VectMap(self, inpMap).GetLastModified()
+    def PointsChanged(self, method, kwargs):
+        if method == "AddPoint":
+            self.AddItem()
 
-        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()
+        elif method == "DeletePoint":
+            self.DeleteItem()
 
-        # 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) 
+        elif method == "SetPointData":
+            self.SetData(kwargs["pt_id"], kwargs["data"])
 
-        self.resultDbMgrData['analysis'] = self.currAnModule
-        self._updateResultDbMgrPage()
-        self._updateDbMgrData()
+        elif method == "SetPoints":
+            while self.GetSelected() != wx.NOT_FOUND:
+                self.DeleteItem()
 
-        self.OnAnalysisChanged(None)
-        self.list.SetUpdateMap(updateMap = True)
+            for iPt, pt_dt in enumerate(kwargs["pts_data"]):
+                self.AddItem()
+                self.SetData(iPt, pt_dt)
 
-        up_map_evt = gUpdateMap(render = True, renderVector = True)
-        wx.PostEvent(self.mapWin, up_map_evt)
-    
-    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()
+        elif method == "SetSelected":
+            self.Select(self._findIndex(kwargs["pt_id"]))
 
-    def NewTmpVectMapToHist(self, prefMapName):
-        """!Add new vector map, which will be saved into history step"""
+    def SetData(self, key, data):
 
-        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)
+        idx = self._findIndex(key)
+        for k, v in data.iteritems():
+            if k == "use":
+                
+                if v and not self.IsChecked(idx):
+                    self.CheckItem(idx, True)
+                elif not v and self.IsChecked(idx):
+                    self.CheckItem(idx, False) 
             else:
-                self.pointsToDraw.AddPen(colKey, wx.Pen(colour = wx.Colour(col[0], col[1], col[2], 255), width = ptWidth))
+                found = 0
+                for col in self.colsData:
+                    if k == col[0]:
+                      found = 1
+                      break
 
-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
+                if found:
+                    self.EditCellKey(key, k, v)    
 
-        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)
+        self.selectedkey = self.GetItemData(self.selected)
 
-        if self.updateMap:
-            up_map_evt = gUpdateMap(render = False, renderVector = False)
-            wx.PostEvent(self.dialog.mapWin, up_map_evt)
+        if self.selectedkey == self.pts_data.GetSelected():
+          return
 
-    def AdaptPointsList(self, currParamsCats):
-        """Rename category values when module is changed. Expample: Start point -> Sink point"""
-        colValues = [""]
+        if self.selectedkey == wx.NOT_FOUND:
+            self.pts_data.SetSelected(None)
+        else:
+            self.pts_data.SetSelected(self.selectedkey)
 
-        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]
+        "flag is True if the item was checked, False if unchecked"
+        key =  self.GetItemData(index)
+        if self.pts_data.GetPointData(key)["use"]!= flag:
+            self.pts_data.SetPointData(key, {"use" : flag})
 
-        currModule = self.dialog.currAnModule #TODO public func
-        cats = self.dialog.vnetParams[currModule]["cmdParams"]["cats"]
-
-        if self.updateMap:
-            up_map_evt = gUpdateMap(render = False, renderVector = False)
-            wx.PostEvent(self.dialog.mapWin, up_map_evt)
-
-        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,
+    def __init__(self, parent, id, title, vnet_mgr, pos=wx.DefaultPosition, size=wx.DefaultSize,
                  style=wx.DEFAULT_DIALOG_STYLE):
         """!Settings dialog"""
         wx.Dialog.__init__(self, parent, id, title, pos, size, style)
 
+        self.vnet_mgr = vnet_mgr
+
         maxValue = 1e8
         self.parent = parent
         self.settings = {}
@@ -2260,20 +1322,7 @@
         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()):
-            up_map_evt = gUpdateMap(render = False, renderVector = False)
-            wx.PostEvent(self.parent.mapWin, up_map_evt)
-        elif self.parent.tmp_result.GetRenderLayer():
-            cmd = self.parent.GetLayerStyle()
-            self.parent.tmp_result.AddRenderLayer(cmd)
-            
-            up_map_evt = gUpdateMap(render = True, renderVector = True)
-            wx.PostEvent(self.parent.mapWin, up_map_evt)#TODO optimization
-        else:
-            up_map_evt = gUpdateMap(render = False, renderVector = False)
-            wx.PostEvent(self.parent.mapWin, up_map_evt)
+        self.vnet_mgr.SettingsUpdated()
 
     def OnApply(self, event):
         """!Button 'Apply' pressed"""
@@ -2284,7 +1333,147 @@
         """!Button 'Cancel' pressed"""
         self.Close()
 
-class AddLayerDialog(wx.Dialog):
+class CreateTtbDialog(wx.Dialog):
+
+    def __init__(self, parent, init_data, id=wx.ID_ANY,
+                 title = _("New vector map with turntable"), style=wx.DEFAULT_DIALOG_STYLE):
+        """!Create turntable dialog."""
+        wx.Dialog.__init__(self, parent, id, title = _(title), style = style)
+
+        label = {}
+        dataSelects = [
+                        ['input', "Choose vector map for analysis:", Select],
+                        ['output', "Name of vector map with turntable:", Select],
+                        ['alayer', "Arc layer which will be expanded by turntable:", LayerSelect],
+                        ['tlayer', "Layer with turntable:", LayerSelect],
+                        ['tuclayer', "Layer with unique categories for turntable:", LayerSelect],
+                      ]
+
+        self.inputData = {}
+
+        selPanels = {}
+
+        for dataSel in dataSelects:
+            selPanels[dataSel[0]] = wx.Panel(parent = self)
+            if dataSel[0] in  ['input', 'output']:
+                self.inputData[dataSel[0]] = dataSel[2](parent = selPanels[dataSel[0]],
+                                                        size = (-1, -1), 
+                                                        type = 'vector')
+            elif dataSel[0] != 'input':
+                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, lambda event : self.InputSel) 
+
+        # buttons
+        self.btnCancel = wx.Button(self, wx.ID_CANCEL)
+        self.btnOk = wx.Button(self, wx.ID_OK)
+        self.btnOk.SetDefault()
+
+        # Layout
+        mainSizer = wx.BoxSizer(wx.VERTICAL)
+        box = wx.StaticBox(self, -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) 
+
+        btn = None
+        for sel in ['input', 'output', 'alayer', 'tlayer', 'tuclayer']:                      
+
+            selPanels[sel].SetSizer(self._doSelLayout(title = label[sel], 
+                                                      sel = self.inputData[sel], 
+                                                      btn = btn))
+            bsizer.Add(item = selPanels[sel], proportion = 0,
+                       flag = wx.EXPAND)
+  
+        for k, v in init_data.iteritems():
+            if self.inputData.has_key(k):
+                self.inputData[k].SetValue(v)
+
+        inp_vect_map = self.inputData["input"].GetValue().split("@")[0]
+        self.inputData['output'].SetValue(inp_vect_map + "_ttb")
+
+        btnSizer = wx.StdDialogButtonSizer()
+        btnSizer.AddButton(self.btnCancel)
+        btnSizer.AddButton(self.btnOk)
+        btnSizer.Realize()
+
+        mainSizer.Add(item = btnSizer, proportion = 0,
+                      flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
+
+
+        self.SetSizer(mainSizer)
+        self.Fit()
+
+    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 InputSel(self):
+        """!When vector map is selected it populates other comboboxes in Parameters tab (layer selects, columns selects)"""
+        vectMapName, mapSet = self._parseMapStr(self.inputData['input'].GetValue())
+        vectorMap = vectMapName + '@' + mapSet
+
+        for sel in ['alayer', 'tlayer', 'tuclayer']:
+            self.inputData[sel].Clear()
+            self.inputData[sel].InsertLayers(vector = vectorMap)
+
+        items = self.inputData['alayer'].GetItems()
+        itemsLen = len(items)
+        if itemsLen < 1:
+            self.addToTreeBtn.Disable()
+            if hasattr(self, 'inpDbMgrData'):
+                self._updateInputDbMgrPage(show = False)
+            self.inputData['alayer'].SetValue("")
+            return
+        elif itemsLen == 1:
+            self.inputData['alayer'].SetSelection(0)
+        elif itemsLen >= 1:
+            if unicode("1") in items:
+                iItem = items.index(unicode("1")) 
+                self.inputData['alayer'].SetSelection(iItem)
+        self.addToTreeBtn.Enable()
+        if hasattr(self, 'inpDbMgrData'):
+            self._updateInputDbMgrPage(show = True)
+
+    def GetData(self):
+
+        params = {}
+        for param, sel in self.inputData.iteritems():
+            params[param] = sel.GetValue()
+
+        return params
+
+class OutputVectorDialog(wx.Dialog):
     def __init__(self, parent,id=wx.ID_ANY,
                  title =_("Save analysis result"), style=wx.DEFAULT_DIALOG_STYLE):
         """!Save analysis result"""
@@ -2336,469 +1525,6 @@
         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(ltype = "vector",     command = cmd,
-                                                           name = self.fullName, active = True,
-                                                           opacity = 1.0,        render = True,       
-                                                           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):
@@ -2857,3 +1583,207 @@
                 if self.maxPriority < item['priority']:
                     self.maxPriority =  item['priority']
             self._updateStatus()
+
+class DefIntesectionTurnCostDialog(wx.Dialog):
+
+    def __init__(self, parent, mapWin, style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, id = wx.ID_ANY, title = _("Edit intersection turns costs"), **kwargs):
+        wx.Dialog.__init__(self, parent, id, style=style, title = title, **kwargs)
+
+        self.dbMgr = DbMgrBase(mapdisplay = mapWin)
+        self.browsePage = self.dbMgr.CreateDbMgrPage(parent = self, pageName = 'browse')
+
+    def layout(self):
+        sizer = wx.BoxSizer(wx.VERTICAL)
+
+        sizer.Add(item = self.browsePage, proportion = 1,
+                  flag = wx.EXPAND)
+        
+        self.SetSizer(sizer)
+
+    def SetData(self, vectMapName, layer):
+        if vectMapName != self.dbMgr.GetVectorName():
+            self.dbMgr.ChangeVectorMap(vectorName = vectMapName)
+        else:
+            self.browsePage.DeleteAllPages() 
+        
+        self.browsePage.AddLayer(int(layer))
+        self.layer = int(layer)
+
+        # TODO HACK!!!
+        self.browsePage.FindWindowById(self.browsePage.layerPage[int(layer)]['sqlNtb']).GetParent().Hide()
+
+    def SetIntersection(self, isec):
+
+        self.browsePage.LoadData(self.layer, where = "isec = %d" % (isec))
+
+class DefGlobalTurnsDialog(wx.Dialog):
+    def __init__(self, parent, data, style= wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, 
+                 id= wx.ID_ANY, title= _("Define Global Turn Costs"), **kwargs): # v Gassu dopln preklad
+
+        wx.Dialog.__init__(self, parent, id, title, style = style, **kwargs)
+
+        self.data = data
+
+        self.angle_list = TurnAnglesList(parent= self, data= self.data) 
+
+        self.btnAdd = wx.Button(parent=self, id=wx.ID_ANY, label = "Add" )
+        self.btnRemove = wx.Button(parent=self, id=wx.ID_ANY, label = "Remove" )
+        self.btnClose = wx.Button(parent = self, id = wx.ID_CLOSE)
+        self.useUTurns = wx.CheckBox(parent = self, id = wx.ID_ANY, label = "Use U-turns")
+
+        self.btnAdd.Bind(wx.EVT_BUTTON, self.OnAddButtonClick)
+        self.btnRemove.Bind(wx.EVT_BUTTON, self.OnRemoveButtonClick)
+        self.btnClose.Bind(wx.EVT_BUTTON, self.OnCloseDialog)
+        self.useUTurns.Bind(wx.EVT_CHECKBOX, self.OnCheckedUTurns)
+                
+        self.btnClose.SetDefault()
+        self.useUTurns.SetValue(True)
+        self.OnCheckedUTurns(None)
+        self.layout()
+        self.SetInitialSize((500, 200))
+
+
+
+    def layout(self):
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        labelSizer = wx.BoxSizer(wx.HORIZONTAL)
+        addRemoveSizer = wx.BoxSizer(wx.VERTICAL)
+        closeSizer = wx.BoxSizer(wx.HORIZONTAL)  
+
+        addRemoveSizer.Add(item= self.btnAdd, proportion= 0, flag= wx.ALIGN_RIGHT, border = 10)
+        addRemoveSizer.Add(item= self.btnRemove, proportion= 0, flag= wx.ALIGN_RIGHT, border = 10)
+
+        labelSizer.Add(item= self.angle_list, proportion= 1, flag= wx.EXPAND, border = 10)
+        labelSizer.Add(item=addRemoveSizer, proportion = 0, flag = wx.ALIGN_RIGHT, border = 10)       
+
+        closeSizer.Add(item=self.useUTurns, proportion = 1, flag = wx.ALIGN_LEFT, border = 10 )
+        closeSizer.Add(item=self.btnClose, proportion = 0, flag = wx.ALIGN_RIGHT, border = 10)        
+
+        sizer.Add(item=labelSizer, proportion = 1, flag = wx.EXPAND)
+        sizer.Add(item=closeSizer, proportion = 0, flag = wx.EXPAND)
+
+        self.SetSizer(sizer)
+     
+
+    def OnAddButtonClick(self, event):
+        """!Add new direction over selected row"""
+        selected_indices = self.angle_list.GetSelectedIndices()
+ 
+        if not selected_indices:
+            from_value = self.turn_data.GetValue(self.turn_data.GetLinesCount()-1,2)
+            to_value = self.turn_data.GetValue(0,1)
+            default_row = ["new", from_value, to_value, 0.0]
+            self.angle_list.AppendRow(default_row)
+
+        # If no row is selected, new direction is added to the end of table
+        i_addition = 0
+        for i in selected_indices:
+            i += i_addition
+            from_value = self.turn_data.GetValue(i-1,2)
+            to_value = self.turn_data.GetValue(i,1)
+            default_row = ["new", from_value, to_value, 0.0]
+            self.angle_list.InsertRow(i,default_row)
+            i_addition += 1
+
+
+    def OnRemoveButtonClick(self, event):
+        """!Delete one or more selected directions"""
+        selected_indices = self.angle_list.GetSelectedIndices()
+  
+        i_reduction = 0
+        for i in selected_indices:
+            i -= i_reduction
+            self.angle_list.DeleteRow(i)
+            i_reduction += 1
+
+    def OnCloseDialog(self, event):
+        """!Close dialog"""
+        self.Close()
+
+    def OnCheckedUTurns(self, event):
+        """!Use U-turns in analyse"""
+        self.data.SetUTurns(self.useUTurns.GetValue())
+       
+    def SetData(self, data):
+        self.angle_list.SetData(data)
+        self.data = data
+
+
+
+class TurnAnglesList(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.TextEditMixin):
+    """!Virtual editable table with global turns"""
+    def __init__(self, parent, data, id= wx.ID_ANY, style= wx.LC_REPORT | wx.LC_VIRTUAL, **kwargs):
+        wx.ListCtrl.__init__(self, parent, id,style= style, **kwargs)
+        listmix.ListCtrlAutoWidthMixin.__init__(self)
+        listmix.TextEditMixin.__init__(self)
+        
+        self.Populate()
+        self.data = data
+        self.SetItemCount(self.data.GetLinesCount())
+        
+
+    def Populate(self):
+        """!Columns definition"""
+        self.InsertColumn(col= 0, heading= "Direction", format= wx.LIST_FORMAT_LEFT) # v Gassu dopln preklad 
+        self.InsertColumn(col= 1, heading= "From Angle", format= wx.LIST_FORMAT_RIGHT)
+        self.InsertColumn(col= 2, heading= "To Angle", format= wx.LIST_FORMAT_RIGHT)
+        self.InsertColumn(col= 3, heading= "Cost", format= wx.LIST_FORMAT_RIGHT)
+
+    def OnGetItemText(self, item, col):
+        val = self.data.GetValue(item, col)
+        if col in [1,2]:
+            val = RadiansToDegrees(val)            
+        return str(val)
+
+    def SetVirtualData(self, row, column, text):
+        """!Set data to table"""
+        if column in [1,2,3]:
+            try:
+                text = float(text)
+            except:
+                return
+        if column in [1,2]:
+            text = DegreesToRadians(text)
+            
+            # Tested allowed range of values
+            if text > math.pi:
+                text = 0.0
+            elif text < -math.pi:
+                text = 0.0
+
+        self.data.SetValue(text, row, column)
+
+        self.edited_row = row
+        self.RefreshItems(0,self.data.GetLinesCount()-1)
+
+
+    def AppendRow(self, values):
+        self.data.AppendRow(values)
+        self.SetItemCount(self.data.GetLinesCount())
+
+    def InsertRow(self, line, values):
+        self.data.InsertRow(line,values)
+        self.SetItemCount(self.data.GetLinesCount())
+
+    def DeleteRow(self, row):
+        self.data.PopRow(row)
+        self.SetItemCount(self.data.GetLinesCount())
+
+    def SetData(self, data):
+        self.data = data
+        self.SetItemCount(self.data.GetLinesCount())
+        self.RefreshItems(0, self.data.GetLinesCount()-1)
+
+
+    def GetSelectedIndices(self, state =  wx.LIST_STATE_SELECTED):
+        """!Get numbers of selected rows"""
+        indices = []
+        lastFound = -1
+        while True:
+            index = self.GetNextItem(lastFound, wx.LIST_NEXT_ALL, state)
+            if index == -1:
+                break
+            else:
+                lastFound = index
+                indices.append(index)
+        return indices
\ No newline at end of file

Modified: grass/trunk/gui/wxpython/vnet/toolbars.py
===================================================================
--- grass/trunk/gui/wxpython/vnet/toolbars.py	2013-06-16 18:05:10 UTC (rev 56735)
+++ grass/trunk/gui/wxpython/vnet/toolbars.py	2013-06-16 21:36:51 UTC (rev 56736)
@@ -13,6 +13,8 @@
 (>=v2). Read the file COPYING that comes with GRASS for details.
 
 @author Stepan Turek <stepan.turek seznam.cz> (GSoC 2012, mentor: Martin Landa)
+ at author Lukas Bocan <silent_bob centrum.cz> (turn costs support)
+ at author Eliska Kyzlikova <eliska.kyzlikova gmail.com> (turn costs support)
 """
 
 import wx
@@ -25,9 +27,13 @@
 
     @param parent reference to VNETDialog
     """
-    def __init__(self, parent, list):
+    def __init__(self, parent, dialog, vnet_mgr):
         BaseToolbar.__init__(self, parent)
-        self.list = list
+        self.vnet_mgr = vnet_mgr
+        self.vnet_pts_mgr = self.vnet_mgr.GetPointsManager()
+
+        self.dialog = dialog
+
         self.InitToolbar(self._toolbarData())
         
         # realize the toolbar
@@ -41,6 +47,10 @@
                                     label = _('Insert points from Map Display')),
             'snapping'  : MetaIcon(img = 'move',
                                     label = _('Activate snapping to nodes')),
+            'isec_turn_edit'  : MetaIcon(img = 'line-edit',
+                                    label = _('Activate mode for turns editing')),
+            'global_turn_edit'  : MetaIcon(img = 'vector-tools',
+                                          label = _('Activate mode for global turns editing')),
             'pointAdd'     : MetaIcon(img = 'point-create',
                                     label = _('Add new point')),
             'pointDelete'  : MetaIcon(img = 'gcp-delete',
@@ -48,35 +58,45 @@
             }
 
         return  self._getToolbarData((('insertPoint', icons['insertPoint'],
-                                      self.list.dialog.OnInsertPoint,#TODO self.list.dialog
+                                      self.OnEditPointMode,#TODO self.list.dialog
                                       wx.ITEM_CHECK),
                                       ('snapping', icons['snapping'],
-                                      self.list.dialog.OnSnapping,
+                                      lambda event : self.vnet_mgr.Snapping(event.IsChecked()),
                                       wx.ITEM_CHECK),
                                       (None, ),
                                      ('pointAdd', icons["pointAdd"],
-                                        self.list.AddItem),
+                                        lambda event : self.vnet_pts_mgr.AddPoint()),
                                      ('pointDelete', icons["pointDelete"],
-                                        self.list.DeleteItem)))
+                                       self.OnDeletePoint),
+                                      (None, )#,
+                                      #('isec_turn_edit', icons['isec_turn_edit'],
+                                      #self.dialog.OnDefIsecTurnCosts,
+                                      #wx.ITEM_CHECK),
+                                      #('global_turn_edit', icons['global_turn_edit'],
+                                      #self.dialog.OnDefGlobalTurnCosts)
+                                      ))
                                     
     def GetToolId(self, toolName): #TODO can be useful in base
-
         return vars(self)[toolName]
 
+    def OnEditPointMode(self, event):
+        self.vnet_pts_mgr.EditPointMode(not self.vnet_pts_mgr.IsEditPointModeActive())
+
+    def OnDeletePoint(self, event):
+        pt_id = self.vnet_pts_mgr.GetSelected()
+        self.vnet_pts_mgr.DeletePoint(pt_id)
+
+
 class MainToolbar(BaseToolbar):
     """!Main toolbar
     """
-    def __init__(self, parent):
+    def __init__(self, parent, vnet_mgr):
         BaseToolbar.__init__(self, parent)
         
         self.InitToolbar(self._toolbarData())
 
-        choices = []
+        self.vnet_mgr = vnet_mgr
 
-        for moduleName in self.parent.vnetModulesOrder:
-            choices.append(self.parent.vnetParams[moduleName]['label'])
-
-        self.UpdateUndoRedo()
         # realize the toolbar
         self.Realize()
 
@@ -121,18 +141,18 @@
                                     ))
 
 
-    def UpdateUndoRedo(self):
+    def UpdateUndoRedo(self, curr_step, steps_num):
 
         id = vars(self)['showResult']
         self.ToggleTool(id =id,
                         toggle = True)
 
-        if self.parent.history.GetCurrHistStep() >= self.parent.history.GetStepsNum():
+        if curr_step >= steps_num:
            self.Enable("undo", False)
         else:
            self.Enable("undo", True)
 
-        if self.parent.history.GetCurrHistStep() <= 0:
+        if curr_step <= 0:
            self.Enable("redo", False)
         else:
            self.Enable("redo", True)  
@@ -144,15 +164,16 @@
 class AnalysisToolbar(BaseToolbar):
     """!Main toolbar
     """
-    def __init__(self, parent):
+    def __init__(self, parent, vnet_mgr):
         BaseToolbar.__init__(self, parent)
         
+        self.vnet_mgr = vnet_mgr
         self.InitToolbar(self._toolbarData())
 
         choices = []
 
-        for moduleName in self.parent.vnetModulesOrder:
-            choices.append(self.parent.vnetParams[moduleName]['label'])
+        for moduleName in self.vnet_mgr.GetAnalyses():
+            choices.append(self.vnet_mgr.GetAnalysisProperties(moduleName)['label'])
 
         self.anChoice = wx.ComboBox(parent = self, id = wx.ID_ANY,
                                     choices = choices,

Added: grass/trunk/gui/wxpython/vnet/vnet_core.py
===================================================================
--- grass/trunk/gui/wxpython/vnet/vnet_core.py	                        (rev 0)
+++ grass/trunk/gui/wxpython/vnet/vnet_core.py	2013-06-16 21:36:51 UTC (rev 56736)
@@ -0,0 +1,1120 @@
+"""!
+ at package vnet.vnet_core
+
+ at brief Vector network analysis logic.
+
+Classes:
+ - vnet_core::VNETManager
+ - vnet_core::VNETAnalyses
+ - vnet_core::VNETHistory
+ - vnet_core::SnappingNodes
+
+(C) 2013 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)
+ at author Lukas Bocan <silent_bob centrum.cz> (turn costs support)
+ at author Eliska Kyzlikova <eliska.kyzlikova gmail.com> (turn costs support)
+"""
+
+import os
+from grass.script     import core as grass
+
+import wx
+
+from core             import utils
+from core.gcmd        import RunCommand, GMessage
+from core.events      import gUpdateMap
+from core.gconsole    import CmdThread, EVT_CMD_DONE, GConsole
+
+from gui_core.gselect import VectorDBInfo
+
+from vnet.vnet_data   import VNETData, VNETTmpVectMaps, VectMap, History
+from vnet.vnet_utils  import ParseMapStr, haveCtypes, GetNearestNodeCat
+
+from grass.pydispatch.signal import Signal
+ 
+class VNETManager:
+    def __init__(self, guiparent, giface):
+
+        self.data = {}
+
+        self.guiparent = guiparent
+        self.mapDisp  = giface.GetMapDisplay()
+        self.mapWin = giface.GetMapWindow().GetMapWindow()
+
+        self.goutput = GConsole(guiparent = guiparent) 
+
+        self.vnet_data = VNETData(guiparent = guiparent, mapWin = self.mapWin)
+
+        self.results = {"analysis" : None,
+                        "vect_map" : None} #TODO more results
+
+        # this class instance manages all temporary vector maps created during life of VNETDialog  
+        self.tmp_maps = VNETTmpVectMaps(parent = guiparent, mapWin = self.mapWin)
+
+        # initialization of History class used for saving and reading data from file
+        # it is used for browsing analysis results
+        self.history = VNETHistory(self.guiparent, self.vnet_data, self.tmp_maps)
+        self.analyses = VNETAnalyses(self.vnet_data, self.RunAnDone, self.goutput, self.tmp_maps)
+
+        # information, whether mouse event handler is registered in map window
+        self.handlerRegistered = False
+
+        self.snap_nodes = SnappingNodes(self.vnet_data, self.tmp_maps, self.mapWin)
+
+        self.ttbCreated = Signal('VNETManager.ttbCreated')
+        self.analysisDone = Signal('VNETManager.analysisDone')
+        self.pointsChanged = self.vnet_data.pointsChanged
+        self.parametersChanged = self.vnet_data.parametersChanged
+
+        self.snapping = self.snap_nodes.snapping
+        self.pointsChanged.connect(self.PointsChanged)
+
+
+    def  __del__(self):
+        """!Removes temp layers, unregisters handlers and graphics"""
+        update = self.tmp_maps.DeleteAllTmpMaps()
+
+        if update:
+            up_map_evt = gUpdateMap(render = True, renderVector = True)
+            wx.PostEvent(self.mapWin, up_map_evt)
+        else:
+            up_map_evt = gUpdateMap(render = True, renderVector = True)
+            wx.PostEvent(self.mapWin, up_map_evt)
+
+    def GetPointsManager(self):
+        return self.vnet_data.GetPointsData()
+
+    def GetGlobalTurnsData(self):
+        return self.vnet_data.GetGlobalTurnsData()
+
+    def RunAnalysis(self):
+        
+        analysis, valid = self.vnet_data.GetParam("analysis")
+
+        params, err_params, flags = self.vnet_data.GetParams()
+        relevant_params = self.vnet_data.GetRelevantParams(analysis)
+
+        if not relevant_params:
+            return -1
+
+        if not self.vnet_data.InputsErrorMsgs(_("Unable to perform analysis."), 
+                                              analysis, params, flags, err_params, relevant_params):
+            return -2
+
+        if self.results["vect_map"]:
+            self.results["vect_map"].DeleteRenderLayer()
+
+        # history - delete data in buffer for hist step  
+        self.history.DeleteNewHistStepData()
+
+        # create new map (included to history) for result of analysis
+        self.results["vect_map"] = self.history.NewTmpVectMapToHist('vnet_tmp_result')
+
+        if not self.results["vect_map"]:
+                return False         
+
+        # 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.results["vect_map"].GetVectMapName())
+
+        # save data from 
+        self.history._saveAnInputToHist(analysis, params, flags)
+
+        ret = self.analyses.RunAnalysis(self.results["vect_map"].GetVectMapName(), params, flags)
+        if not ret:
+            return -3
+        else:
+            return 1
+
+    def RunAnDone(self, cmd, returncode, results):
+
+        self.results["analysis"] = cmd[0]
+       
+        self.results["vect_map"].SaveVectMapState()
+
+        cmd, cmd_colors =  self.vnet_data.GetLayerStyle()
+        self.results["vect_map"].AddRenderLayer(cmd, cmd_colors)
+
+        self.history.SaveHistStep()
+
+        self.analysisDone.emit()
+
+    def ShowResult(self, show):
+        #TODO can be more results e. g. smallest cut
+
+        if show:
+            self._checkResultMapChanged(self.results["vect_map"])
+            cmd, cmd_colors = self.vnet_data.GetLayerStyle()
+            self.results["vect_map"].AddRenderLayer(cmd, cmd_colors)
+        else:
+            self.results["vect_map"].DeleteRenderLayer()
+
+        up_map_evt = gUpdateMap(render = True, renderVector = True)
+        wx.PostEvent(self.mapWin, up_map_evt)
+
+    def GetAnalysisProperties(self, analysis = None):
+        return self.vnet_data.GetAnalysisProperties(analysis = analysis)
+
+    def GetResults(self):
+        return self.results["vect_map"]
+
+    def Undo(self):
+        self._updateDataForHistStep(self.history.Undo())
+        #SetUpdateMap TODO
+        return self.history.GetHistStep()
+    def Redo(self):
+        self._updateDataForHistStep(self.history.Redo())
+        #SetUpdateMap
+        return self.history.GetHistStep()
+
+    def _updateDataForHistStep(self, data):
+        if not data:
+            return
+
+        analysis, resultMapName, params, flags = data
+
+        self.results["analysis"] = analysis
+        self.vnet_data.SetParams(params, flags)
+
+        self.results["vect_map"].DeleteRenderLayer()
+        self.results["vect_map"]  = self.tmp_maps.GetTmpVectMap(resultMapName)
+        self._checkResultMapChanged(self.results["vect_map"])
+
+        cmd, cmd_colors = self.vnet_data.GetLayerStyle()
+        self.results["vect_map"].AddRenderLayer(cmd, cmd_colors)
+
+        up_map_evt = gUpdateMap(render = True, renderVector = True)
+        wx.PostEvent(self.mapWin, up_map_evt)
+
+    def GetHistStep(self):
+        return self.history.GetHistStep()
+
+    def SetParams(self, params, flags):
+        self.vnet_data.SetParams(params, flags)
+
+    def GetParams(self):
+        params, inv_params, flags = self.vnet_data.GetParams()
+        return params, inv_params, flags
+
+    def GetParam(self, param):
+        return self.vnet_data.GetParam(param)
+
+    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 IsSnappingActive(self):
+        return self.vnet_data.GetSnapping()
+
+    def Snapping(self, activate):
+        self.snap_nodes.ComputeNodes(activate)
+
+    def GetAnalyses(self):
+        return self.vnet_data.GetAnalyses()
+
+    def SettingsUpdated(self):
+        self.vnet_data.GetPointsData().SetPointDrawSettings()
+        if not self.results["vect_map"]  or \
+           not self.tmp_maps.HasTmpVectMap(self.results["vect_map"].GetVectMapName()):
+            up_map_evt = gUpdateMap(render = False, renderVector = False)
+            wx.PostEvent(self.mapWin, up_map_evt)
+        elif self.results["vect_map"].GetRenderLayer():
+            cmd, cmd_colors = self.vnet_data.GetLayerStyle()
+            self.results["vect_map"].AddRenderLayer(cmd, cmd_colors)
+            
+            up_map_evt = gUpdateMap(render = True, renderVector = True)
+            wx.PostEvent(self.mapWin, up_map_evt)#TODO optimization
+        else:
+            up_map_evt = gUpdateMap(render = False, renderVector = False)
+            wx.PostEvent(self.mapWin, up_map_evt)
+
+    def PointsChanged(self, method, kwargs):
+
+        up_map_evt = gUpdateMap(render = False, renderVector = False)
+        wx.PostEvent(self.mapWin, up_map_evt)
+
+    def CreateTttb(self, params):
+
+        outputMap = params["output"]
+        mapName, mapSet = ParseMapStr(outputMap)
+        if mapSet !=  grass.gisenv()['MAPSET']:
+            GMessage(parent = self,
+                     message = _("Map can be created only in current mapset"))
+            return False
+        existsMap = grass.find_file(name = mapName, 
+                                    element = 'vector', 
+                                    mapset = grass.gisenv()['MAPSET'])
+        if existsMap["name"]:
+            dlg = wx.MessageDialog(parent = self.guiparent,
+                                   message = _("Vector map %s already exists. " +
+                                                "Do you want to overwrite it?") % 
+                                                (existsMap["fullname"]),
+                                   caption = _("Overwrite vector map"),
+                                   style = wx.YES_NO | wx.NO_DEFAULT |
+                                               wx.ICON_QUESTION | wx.CENTRE) 
+            ret = dlg.ShowModal()
+            dlg.Destroy()
+            if ret == wx.ID_NO:
+                return False
+
+            cmdTtb = [ 
+                        "v.net.turntable",
+                        "input=" + params["input"], 
+                        "output=" + params["output"],
+                        "alayer=" + params["alayer"],
+                        "tlayer=" + params["tlayer"],
+                        "tuclayer=" + params["tuclayer"],
+                        "--overwrite", 
+                       ]
+
+            self.goutput.RunCmd(command = cmdTtb, onDone = self._createTtbDone)
+
+        return True
+
+    def _createTtbDone(self, cmd, returncode):
+
+        if returncode != 0:
+            GMessage(parent = self.guiparent,
+                     message = _("Creation of turntable failed."))
+            return
+        else:
+            params = {}
+            for c in cmd:
+                spl_c = c.split("=")
+                if len(spl_c) != 2:
+                    continue
+
+                if spl_c[0] and spl_c != "input":
+                    params[spl_c[0]] = spl_c[1]
+                if spl_c[0] == "output":
+                    params["input"] = spl_c[1]
+
+            self.vnet_data.SetParams(params, {})
+
+        self.ttbCreated.emit(returncode = returncode)
+
+    def SaveTmpLayer(self, layer_name):
+        """!Permanently saves temporary map of analysis result"""
+        msg = _("Vector map with analysis result does not exist.")
+
+        if not hasattr(self.results["vect_map"], "GetVectMapName"):
+            GMessage(parent = self.guiparent,
+                     message = msg)
+            return
+
+        mapToAdd = self.results["vect_map"].GetVectMapName()
+        mapToAddEx = grass.find_file(name = mapToAdd, 
+                                        element = 'vector', 
+                                        mapset = grass.gisenv()['MAPSET'])
+
+        if not mapToAddEx["name"]: 
+            GMessage(parent = self.guiparent,
+                    message = msg)
+            return
+
+        addedMap = layer_name
+        mapName, mapSet = ParseMapStr(addedMap)
+        if mapSet !=  grass.gisenv()['MAPSET']:
+            GMessage(parent = self.guiparent,
+                     message = _("Map can be saved only to currently set mapset"))
+            return
+        existsMap = grass.find_file(name = mapName, 
+                                    element = 'vector', 
+                                    mapset = grass.gisenv()['MAPSET'])
+        if existsMap["name"]:
+            dlg = wx.MessageDialog(parent = self.guiparent,
+                                    message = _("Vector map %s already exists. " +
+                                            "Do you want to overwrite it?") % 
+                                            (existsMap["fullname"]),
+                                   caption = _("Overwrite vector map"),
+                                   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.results["vect_map"].GetVectMapName(), mapName])
+
+
+        if not self.mapWin.tree:
+            return
+
+        if  self.mapWin.tree.FindItemByData(key = 'name', value = mapName) is None: 
+
+            cmd, cmd_colors = self.vnet_data.GetLayerStyle()#TODO get rid of insert
+            cmd.insert(0, 'd.vect')
+            cmd.append('map=%s' % mapName)
+
+            self.mapWin.tree.AddLayer(ltype = "vector", 
+                                      lname = mapName,
+                                      lcmd = cmd,
+                                      lchecked = True)
+            if cmd_colors:
+                layerStyleVnetColors = utils.CmdToTuple(cmd_colors)
+
+                RunCommand(layerStyleVnetColors[0],
+                        **layerStyleVnetColors[1])
+        else:
+            up_map_evt = gUpdateMap(render = True, renderVector = True)
+            wx.PostEvent(self.mapWin, up_map_evt)
+
+class VNETAnalyses:
+    def __init__(self, data, onAnDone, goutput, tmp_maps):
+        self.data = data
+
+        self.pts_data = self.data.GetPointsData()
+        self.tmp_maps = tmp_maps
+
+        self.onAnDone = onAnDone
+        self.goutput = goutput
+
+    def RunAnalysis(self, output, params, flags):
+        """!Perform network analysis"""
+
+        analysis, valid = self.data.GetParam("analysis")
+
+        catPts = self._getPtByCat(analysis)
+
+        if analysis == "v.net.path":
+            self._vnetPathRunAn(analysis, output, params, flags, catPts)
+        elif flags["t"]:
+            self._runTurnsAn(analysis, output, params, flags, catPts)
+        else:
+            self._runAn(analysis, output, params, flags, catPts)
+
+    def _vnetPathRunAn(self, analysis, output, params, flags, catPts):
+        """!Called when analysis is run for v.net.path module"""
+        if self.pts_data.GetPointsCount() < 1:
+            return False
+        cats = self.data.GetAnalysisProperties()["cmdParams"]["cats"]
+
+        # Creates part of cmd fro analysis
+        cmdParams = [analysis]
+        cmdParams.extend(self._setInputParams(analysis, params, flags))
+        cmdParams.append("output=" + output)
+
+        cmdPts = []
+        for cat in cats:
+            if  len(catPts[cat[0]]) < 1:#TODO
+                GMessage(parent = self.guiparent,
+                         message=_("Please choose '%s' and '%s' point.") % (cats[0][1], cats[1][1]))
+                return False
+            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()
+
+        if flags["t"]:
+            cmdParams.append("-t")
+
+            self.tmpTurnAn = AddTmpMapAnalysisMsg("vnet_tunr_an_tmp", self.tmp_maps)
+            if not self.tmpTurnAn:
+                return False
+
+            mapName, mapSet = ParseMapStr(self.tmpTurnAn.GetVectMapName())
+            cmdCopy = [ 
+                        "g.copy",
+                        "vect=%s,%s" % (params["input"], mapName), 
+                        "--overwrite",                             
+                       ]
+            cmdParams.append("input=" + self.tmpTurnAn.GetVectMapName())
+
+            ret, msg, err = RunCommand('g.copy',
+                                        getErrorMsg = True,
+                                        vect = "%s,%s" % (params['input'], mapName),
+                                        read = True,
+                                        overwrite = True)
+
+            self._updateTtbByGlobalCosts(self.tmpTurnAn.GetVectMapName(), 
+                                         int(params["tlayer"]))
+            
+            #self._prepareCmd(cmdCopy)
+            #self.goutput.RunCmd(command = cmdCopy)
+        else:
+            cmdParams.append("input=" + params["input"])
+
+        cmdParams.append("file=" + self.coordsTmpFile)
+
+        cmdParams.append("dmax=" + str(params["max_dist"]))
+
+        cmdParams.append("--overwrite")
+        self._prepareCmd(cmd = cmdParams)
+        
+        if flags["t"]:
+            self.goutput.RunCmd(command = cmdParams, onDone = self._vnetPathRunTurnsAnDone)
+        else:
+            self.goutput.RunCmd(command = cmdParams, onDone = self._vnetPathRunAnDone)
+
+    def _vnetPathRunTurnsAnDone(self, cmd, returncode):
+        #TODO
+        #self.tmp_maps.DeleteTmpMap(self.tmpTurnAn)
+        self._vnetPathRunAnDone(cmd, returncode)
+
+    def _vnetPathRunAnDone(self, cmd, returncode):
+        """!Called when v.net.path analysis is done"""
+        grass.try_remove(self.coordsTmpFile)
+
+        self._onDone(cmd, returncode)
+
+    def _onDone(self, cmd, returncode):
+        for c in cmd:
+            if "output=" in c:
+                output = c.split("=")[1]
+                break  
+
+        self.onAnDone(cmd, returncode, output)
+
+    def _runTurnsAn(self, analysis, output, params, flags, catPts):
+
+        # Creates part of cmd fro analysis
+        cmdParams = [analysis]
+        cmdParams.extend(self._setInputParams(analysis, params, flags))
+        cmdParams.append("output=" + output)
+
+        cats = {}
+        for cat_name, pts_coor in catPts.iteritems():
+
+            for coor in pts_coor:
+                cat_num = str(GetNearestNodeCat(e = coor[0], 
+                                                n = coor[1], 
+                                                field = int(params["tuclayer"],
+                                                tresh = params["max_dist"]), 
+                                                vectMap = params["input"]))
+                if cat_num < 0:
+                    continue
+                if cats.has_key(cat_name):
+                    cats[cat_name].append(cat_num)
+                else:
+                    cats[cat_name] = [cat_num]
+
+        for cat_name, cat_nums in cats.iteritems():
+            cmdParams.append(cat_name + "=" + ",".join(cat_nums))
+
+        self.tmpTurnAn = AddTmpMapAnalysisMsg("vnet_tunr_an_tmp", self.tmp_maps)
+        if not self.tmpTurnAn:
+            return False
+
+        # create and run commands which goes to analysis thread
+
+        mapName, mapSet = ParseMapStr(self.tmpTurnAn.GetVectMapName())
+        cmdCopy = [ 
+                    "g.copy",
+                    "vect=%s,%s" % (params['input'], mapName), 
+                    "--overwrite",                             
+                   ]
+        cmdParams.append("input=" + self.tmpTurnAn.GetVectMapName())
+
+        ret, msg, err = RunCommand('g.copy',
+                                    getErrorMsg = True,
+                                    vect = "%s,%s" % (params['input'], mapName),
+                                    read = True,
+                                    overwrite = True)
+
+        self._updateTtbByGlobalCosts(self.tmpTurnAn.GetVectMapName(), 
+                                     int(params["tlayer"]))
+
+
+        self._setCmdForSpecificAn(cmdParams)
+
+        cmdParams.append("-t")
+
+        self._prepareCmd(cmdParams)
+        self.goutput.RunCmd(command = cmdParams, onDone = self._runTurnsAnDone)
+
+    def _updateTtbByGlobalCosts(self, vectMapName, tlayer):
+        #TODO get layer number do not use it directly
+        intervals = self.turnsData["global"].GetData()
+
+        cmdUpdGlob = [ 
+                      "v.db.update",
+                      "map=", self.inputData["input"].GetValue(), 
+                      "layer=%d" % tlayer,
+                      "column=cost",
+                    ]
+
+        dbInfo = VectorDBInfo(vectMapName)
+        table = dbInfo.GetTable(tlayer)
+        driver,  database = dbInfo.GetDbSettings(tlayer)
+
+
+        sqlFile = grass.tempfile()
+        sqlFile_f = open(sqlFile, 'w')
+
+        for ival in intervals:
+            from_angle = ival[0]
+            to_angle = ival[1]
+            cost = ival[2]
+
+            if to_angle < from_angle:
+                to_angle = math.pi * 2  + to_angle
+            #if angle < from_angle:
+            #    angle = math.pi * 2  + angle
+
+            where = " WHERE (((angle < {0}) AND ({2} + angle >= {0} AND {2} + angle < {1})) OR \
+                            ((angle >= {0}) AND (angle >= {0} AND angle < {1}))) AND cost==0.0 ".format(str(from_angle), str(to_angle), str(math.pi * 2))
+
+            stm = ("UPDATE %s SET cost=%f " % (table, cost)) + where + ";\n";
+            sqlFile_f.write(stm)
+
+        sqlFile_f.close()
+
+            #TODO imporve parser and run in thread
+
+   
+        ret, msg, err = RunCommand('db.execute',
+                               getErrorMsg = True,
+                               input = sqlFile,
+                               read = True,
+                               driver = driver,
+                               database = database)
+
+        grass.try_remove(sqlFile)
+
+    def _runTurnsAnDone(self, cmd, returncode):
+        """!Called when analysis is done"""
+        #self.tmp_maps.DeleteTmpMap(self.tmpTurnAn) #TODO remove earlier (OnDone lambda?)
+ 
+        self._onDone(cmd, returncode)
+
+
+    def _runAn(self, analysis, output, params, flags, catPts):
+        """!Called for all v.net.* analysis (except v.net.path)"""
+
+        # Creates part of cmd fro analysis
+        cmdParams = [analysis]
+        cmdParams.extend(self._setInputParams(analysis, params, flags))
+        cmdParams.append("output=" + output)
+
+        cats = self.data.GetAnalysisProperties()["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 False
+        else:
+            for cat in cats:
+                if  len(catPts[cat[0]]) < 2:
+                    GMessage(parent = self, 
+                             message = _("Please choose at least two points."))
+                    return False      
+
+        # TODO add also to thread for analysis?
+        vcatResult = RunCommand("v.category",
+                           input = params['input'],
+                           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 = params["nlayer"]
+
+        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 = AddTmpMapAnalysisMsg("vnet_tmp_in_pts", self.tmp_maps)
+        if not self.tmpInPts:
+            return False
+
+        self.tmpInPtsConnected = AddTmpMapAnalysisMsg("vnet_tmp_in_pts_connected", self.tmp_maps)
+        if not self.tmpInPtsConnected:
+            return False
+
+        cmdParams.append("input=" + self.tmpInPtsConnected.GetVectMapName())
+        cmdParams.append("--overwrite")  
+        
+        self._setCmdForSpecificAn(cmdParams)
+        
+        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=" + params['input'],
+                    "output=" + self.tmpInPtsConnected.GetVectMapName(),
+                    "alayer=" +  params["alayer"],
+                    "nlayer=" +  params["nlayer"], 
+                    "operation=connect",
+                    "thresh=" + str(params["max_dist"]),             
+                    "--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.tmp_maps.DeleteTmpMap(self.tmpInPts) #TODO remove earlier (OnDone lambda?)
+        self.tmp_maps.DeleteTmpMap(self.tmpInPtsConnected)
+        grass.try_remove(self.tmpPtsAsciiFile)
+
+        if cmd[0] == "v.net.flow":
+            self.tmp_maps.DeleteTmpMap(self.vnetFlowTmpCut)
+
+        self._onDone(cmd, returncode)
+
+    def _setInputParams(self, analysis, params, flags):
+        """!Return list of chosen values (vector map, layers). 
+
+        The list items are in form to be used in command for analysis e.g. 'alayer=1'.    
+        """
+
+        inParams = []
+        for col, v in self.data.GetAnalysisProperties()["cmdParams"]["cols"].iteritems():
+
+            if "inputField" in v:
+                colInptF = v["inputField"]
+            else:
+                colInptF = col
+
+            inParams.append(col + '=' + params[colInptF])
+
+        for layer in ['alayer', 'nlayer', 'tlayer', 'tuclayer']:
+            if not flags["t"] and layer in ['tlayer', 'tuclayer']:
+                continue
+            # TODO
+            if flags["t"] and layer == 'nlayer':
+                inParams.append(layer + "=" + params['tuclayer'])
+                continue
+
+            inParams.append(layer + "=" + params[layer])
+
+        return inParams
+
+    def _getPtByCat(self, analysis):
+        """!Return points separated by theirs categories"""
+        anProps = self.data.GetAnalysisProperties()
+        cats = anProps["cmdParams"]["cats"]
+
+        ptByCats = {}
+        for cat in anProps["cmdParams"]["cats"]:
+            ptByCats[cat[0]] = []
+ 
+        for i in range(self.pts_data.GetPointsCount()):
+            pt_data = self.pts_data.GetPointData(i)
+            if pt_data["use"]:
+                for i_cat, cat in enumerate(cats):
+                    #i_cat + 1 - we ave to increment it because pt_data["type"] includes "" in first place
+                    if (i_cat + 1) == pt_data["type"] or len(ptByCats) == 1: 
+                        coords = (pt_data['e'], pt_data['n'])
+                        ptByCats[cat[0]].append(coords)
+
+        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 _setCmdForSpecificAn(self, cmdParams):
+        # append parameters needed for particular analysis
+        if cmdParams[0] == "v.net.distance":
+            cmdParams.append("from_layer=1")
+            cmdParams.append("to_layer=1")
+        elif cmdParams[0] == "v.net.flow":
+            #self.vnetFlowTmpCut = self.NewTmpVectMapToHist('vnet_tmp_flow_cut') TODO
+            self.vnetFlowTmpCut = AddTmpMapAnalysisMsg('vnet_tmp_flow_cut', self.tmp_maps)
+            if not self.vnetFlowTmpCut:
+                return          
+            cmdParams.append("cut=" +  self.vnetFlowTmpCut.GetVectMapName())         
+        elif cmdParams[0] == "v.net.iso":
+            costs, valid = self.data.GetParam("iso_lines") #TODO valid
+            cmdParams.append("costs=" + costs)
+
+class VNETHistory():
+    def __init__(self, guiparent, data, tmp_maps):
+        self.history = History()
+        self.guiparent = guiparent
+
+        self.tmp_maps = tmp_maps
+
+        # variable, which appends  unique number to every name of map, which is saved into history
+        self.histTmpVectMapNum = 0
+        
+        self.data = data
+    
+    def Undo(self):
+        """!Step back in history"""
+        histStepData = self.history.GetPrev()
+
+        if histStepData:
+            return self._updateHistStepData(histStepData)
+
+        return None
+
+    def Redo(self):
+        """!Step forward in history"""
+        histStepData = self.history.GetNext()
+
+        if histStepData:
+            return self._updateHistStepData(histStepData)
+
+        return None
+
+    def GetHistStep(self):
+        return self.history.GetCurrHistStep(), self.history.GetStepsNum()
+
+    def SaveHistStep(self):
+        """!Save new step into history"""
+        removedHistData = self.history.SaveHistStep()
+
+        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.tmp_maps.GetTmpVectMap(vectMapName)
+                self.tmp_maps.DeleteTmpMap(tmpMap)
+
+    def DeleteNewHistStepData(self):
+        # history - delete data in buffer for hist step  
+        self.history.DeleteNewHistStepData()
+        # empty list for maps to be saved to history
+        self.tmpVectMapsToHist= []
+
+    def _updateHistStepData(self, histStepData):
+        """!Updates dialog according to chosen history step"""
+        # set analysis module
+        analysis = histStepData["vnet_modules"]["curr_module"]
+        self.data.SetParams({"analysis" : analysis}, {})
+
+        pts = []
+        # add points to list
+        for iPt in range(len(histStepData["points"])):
+            ptDataHist = histStepData["points"]["pt" + str(iPt)]
+            
+            e, n = ptDataHist["coords"]
+            pt_data = {"e" : e, "n" : n}
+
+            pt_data['type'] = int(ptDataHist["catIdx"])
+
+            pt_data['topology'] = ptDataHist["topology"]
+
+            pt_data['use'] = ptDataHist["checked"]
+
+            pts.append(pt_data)
+
+        self.data.GetPointsData().SetPoints(pts)
+
+        # update analysis result maps 
+        mapsNames = histStepData["tmp_data"]["maps"]
+        for m in mapsNames:
+            if "vnet_tmp_result" in m:
+                resultMapName = m
+                break
+
+        # update parameters
+        params = {}
+        histInputData = histStepData["an_params"]
+        for inpName, inp in histInputData.iteritems():
+            params[inpName] = str(inp) 
+            if inpName == "input":
+                inpMap = inp
+
+        prevInpModTime = str(histStepData["other"]["input_modified"])
+        currInpModTime = VectMap(None, inpMap).GetLastModified()
+
+        if currInpModTime.strip()!= prevInpModTime.strip():
+            dlg = wx.MessageDialog(parent = self.guiparent,
+                                   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()
+    
+        #TODO 
+        flags = {}
+        return analysis, resultMapName, params, flags 
+
+    def _saveAnInputToHist(self, analysis, params, flags):
+        """!Save all data needed for analysis into history buffer"""
+        pts_num = self.data.GetPointsData().GetPointsCount()
+
+        for pt_id in range(pts_num):
+            data = self.data.GetPointsData().GetPointData(pt_id)
+
+            ptName = "pt" + str(pt_id)
+
+            coords = [data["e"], data["n"]]
+            self.history.Add(key = "points", 
+                             subkey = [ptName, "coords"], 
+                             value = coords)
+
+            self.history.Add(key = "points", 
+                             subkey = [ptName, "catIdx"], 
+                             value = data['type'])
+
+            self.history.Add(key = "points", 
+                             subkey = [ptName, "topology"], 
+                             value = data['topology'])
+
+
+            self.history.Add(key = "points", 
+                             subkey = [ptName, "checked"], 
+                             value = data["use"])
+
+            for param, value in params.iteritems():
+
+                if param == "input":
+                    inpMap = VectMap(self, value)
+                    self.history.Add(key = "other", 
+                                     subkey = "input_modified", 
+                                     value = inpMap.GetLastModified())  
+                    param_val =  value
+                else:
+                    param_val =  value
+                 
+                self.history.Add(key = "an_params", 
+                                 subkey = param, 
+                                 value = param_val)
+            
+        self.history.Add(key = "vnet_modules", 
+                         subkey = "curr_module", 
+                         value =  analysis)
+
+
+    def NewTmpVectMapToHist(self, prefMapName):
+        """!Add new vector map, which will be saved into history step"""
+
+        mapName = prefMapName + str(self.histTmpVectMapNum)
+        self.histTmpVectMapNum += 1
+
+        tmpMap = AddTmpMapAnalysisMsg(mapName, self.tmp_maps)
+        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(mapName, tmp_maps): #TODO 
+        """!Wraped AddTmpVectMap"""
+        msg = _("Temporary map %s  already exists.\n"  + 
+                "Do you want to continue in analysis and overwrite it?") \
+                 % (mapName +'@' + grass.gisenv()['MAPSET'])
+        tmpMap = tmp_maps.AddTmpVectMap(mapName, msg)
+        return tmpMap
+
+
+class SnappingNodes(wx.EvtHandler):
+    def __init__(self, data, tmp_maps, mapWin):
+
+        self.data = data
+        self.tmp_maps = tmp_maps
+        self.mapWin = mapWin
+
+        wx.EvtHandler.__init__(self)
+        self.snapping= Signal('VNETManager.snapping')
+
+        # Stores all data related to snapping
+        self.snapData = {}
+
+    def ComputeNodes(self, activate):
+        """!Start/stop snapping mode"""
+
+        if not haveCtypes:
+            GMessage(parent = self,
+                     message = _("Unable to use ctypes. \n") + \
+                               _("Snapping mode can not be activated."))
+            return -1
+
+        if not activate:
+
+            if self.tmp_maps.HasTmpVectMap("vnet_snap_points"):
+                self.snapPts.DeleteRenderLayer() 
+                
+                up_map_evt = gUpdateMap(render = False, renderVector = False)
+                wx.PostEvent(self.mapWin, up_map_evt)
+
+            if self.snapData.has_key('cmdThread'):
+                self.snapData['cmdThread'].abort()
+
+            self.data.SetSnapping(False)
+            
+            self.snapping.emit(evt = "deactivated")
+
+            return  -1
+
+        self.data.SetSnapping(activate)
+
+        params, inv_params, flags = self.data.GetParams()
+        if not self.data.InputsErrorMsgs(msg = _("Snapping mode can not be activated."),
+                                     analysis = None,
+                                     params = params,
+                                     inv_params = inv_params,
+                                     flags = flags,
+                                     relevant_params = ["input", "nlayer"]):
+            return -1
+
+        if not self.tmp_maps.HasTmpVectMap("vnet_snap_points"):
+            endStr = _("Do you really want to activate snapping and overwrite it?")
+            self.snapPts = self.tmp_maps.AddTmpVectMap("vnet_snap_points", endStr)
+
+            if not self.snapPts:
+                return -1 
+
+        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.tmp_maps.DeleteTmpMap(self.snapPts)
+                    return -1
+
+        self.data.SetSnapping(True)
+
+        inpFullName = params["input"]
+        inpName, mapSet = inpFullName.split("@")
+        computeNodes = True
+
+        if not self.snapData.has_key("inputMap"):
+            pass
+        elif inpFullName != self.snapData["inputMap"].GetVectMapName():
+            self.snapData["inputMap"] = VectMap(None, inpFullName)
+        elif self.snapData["inputMap"].VectMapState() == 1:
+                computeNodes = False
+    
+        # new map needed
+        if computeNodes:
+            if not self.snapData.has_key('cmdThread'):
+                self.snapData['cmdThread'] = CmdThread(self)
+            else:
+                self.snapData['cmdThread'].abort()
+
+            cmd = ["v.to.points", "input=" + params['input'], 
+                                  "output=" + self.snapPts.GetVectMapName(),
+                                  "use=node", "--overwrite"]
+            # process GRASS command with argument
+            self.snapData["inputMap"] = VectMap(None, inpFullName)
+            self.snapData["inputMap"].SaveVectMapState()
+
+            self.Bind(EVT_CMD_DONE, self._onNodesDone)
+            self.snapData['cmdThread'].RunCmd(cmd)
+
+            self.snapping.emit(evt = "computing_points")
+
+            return 0
+        # map is already created and up to date for input data
+        else:
+            self.snapPts.AddRenderLayer()
+            
+            up_map_evt = gUpdateMap(render = True, renderVector = True)
+            wx.PostEvent(self.mapWin, up_map_evt)
+
+            self.snapping.emit(evt = "computing_points_done")
+
+            return 1
+
+    def _onNodesDone(self, event):
+        """!Update map window, when map with nodes to snap is created"""
+        if not event.aborted:
+            self.snapPts.SaveVectMapState()
+            self.snapPts.AddRenderLayer() 
+
+            up_map_evt = gUpdateMap(render = True, renderVector = True)
+            wx.PostEvent(self.mapWin, up_map_evt)
+
+            self.snapping.emit(evt = "computing_points_done")

Added: grass/trunk/gui/wxpython/vnet/vnet_data.py
===================================================================
--- grass/trunk/gui/wxpython/vnet/vnet_data.py	                        (rev 0)
+++ grass/trunk/gui/wxpython/vnet/vnet_data.py	2013-06-16 21:36:51 UTC (rev 56736)
@@ -0,0 +1,1449 @@
+"""!
+ at package vnet.vnet_data
+
+ at brief Vector network analysis classes for data managment.
+
+Classes:
+ - vnet_data::VNETData
+ - vnet_data::VNETPointsData
+ - vnet_data::VNETAnalysisParameters
+ - vnet_data::VNETAnalysesProperties
+ - vnet_data::VNETTmpVectMaps
+ - vnet_data::VectMap
+ - vnet_data::History
+ - vnet_data::VNETGlobalTurnsData
+
+(C) 2013 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)
+ at author Lukas Bocan <silent_bob centrum.cz> (turn costs support)
+ at author Eliska Kyzlikova <eliska.kyzlikova gmail.com> (turn costs support)
+"""
+import os
+import types
+from copy import deepcopy
+
+from grass.script     import core as grass
+
+import wx
+
+
+from core             import utils
+from core.gcmd        import RunCommand, GMessage
+from core.settings    import UserSettings
+
+from vnet.vnet_utils  import ParseMapStr, SnapToNode
+
+from gui_core.gselect        import VectorDBInfo
+from grass.pydispatch.signal import Signal
+
+from vnet.vnet_utils  import DegreesToRadians, RadiansToDegrees
+
+class VNETData:
+    def __init__(self, guiparent, mapWin):
+
+        # setting initialization
+        self._initSettings()
+
+        self.guiparent = guiparent
+
+        self.an_props = VNETAnalysesProperties()
+        self.an_params = VNETAnalysisParameters(self.an_props)
+
+        self.an_points = VNETPointsData(mapWin, self.an_props, self.an_params)
+
+        self.global_turns = VNETGlobalTurnsData()
+
+        self.pointsChanged = self.an_points.pointsChanged
+        self.parametersChanged = self.an_params.parametersChanged
+
+    def GetAnalyses(self):
+        return self.an_props.used_an
+
+    def GetPointsData(self):
+        return self.an_points
+
+    def GetGlobalTurnsData(self):
+        return self.global_turns
+
+    def GetRelevantParams(self, analysis = None):
+        if analysis:
+            return self.an_props.GetRelevantParams(analysis)
+        else:
+            analysis, valid = self.an_params.GetParam("analysis")
+            return self.an_props.GetRelevantParams(analysis)
+
+    def GetAnalysisProperties(self, analysis = None):
+        if analysis:
+            return self.an_props[analysis]
+        else:
+            analysis, valid = self.an_params.GetParam("analysis")
+            return self.an_props[analysis]
+
+    def GetParam(self, param):
+        return self.an_params.GetParam(param)
+
+    def GetParams(self):
+        return self.an_params.GetParams()
+
+    def SetParams(self, params, flags):
+        return self.an_params.SetParams(params, flags)
+    
+    def SetSnapping(self, activate):
+        self.an_points.SetSnapping(activate)
+
+    def GetSnapping(self):
+        return self.an_points.GetSnapping()
+    
+    def GetLayerStyle(self):
+        """!Returns cmd for d.vect, with set style for analysis result"""
+        analysis, valid = self.an_params.GetParam("analysis")
+
+        resProps = self.an_props[analysis]["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]))        
+
+        layerStyleVnetColors = []
+        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",
+                                    "color=" + colorStyle,
+                                    "column=" + resProps["attrColColor"],
+                                   ]
+            if invert:
+                layerStyleVnetColors.append("-n")
+
+        return layerStyleCmd, layerStyleVnetColors
+
+    def InputsErrorMsgs(self, msg, analysis, params, flags, inv_params, relevant_params):
+        """!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 
+            @return True - if checked inputs are OK
+            @return False - if some of checked inputs is not ok
+        """
+
+        if flags["t"] and  "tlayer" not in relevant_params:
+            GMessage(parent = self.guiparent, message = _("Module <%s> does not support turns costs." % analysis))
+            return False
+
+        errMapStr = ""
+        if 'input' in inv_params:
+            if params['input']:
+                errMapStr = _("Vector map '%s' does not exist.") %  (params['input'])
+            else:
+                errMapStr = _("Vector map was not chosen.")
+
+
+        if errMapStr:
+            GMessage(parent = self.guiparent,
+                     message = msg + "\n" + errMapStr)
+            return False
+
+        errLayerStr = ""
+        for layer, layerLabel in {'alayer' : _("arc layer"), 
+                                  'nlayer' : _("node layer"),
+                                  'tlayer' : _("turntable layer"),
+                                  'tuclayer' : _("unique categories layer")}.iteritems():
+
+            if layer in ["tlayer", "tuclayer"] and not flags["t"]:
+                continue
+            if layer in inv_params:
+                if params[layer]:
+                    errLayerStr += _("Chosen %s '%s' does not exist in vector map '%s'.\n") % \
+                                   (layerLabel, params[layer], params['input'])
+                else:
+                    errLayerStr += _("Choose existing %s.\n") % \
+                                   (layerLabel)
+        if errLayerStr:
+            GMessage(parent = self.guiparent,
+                     message = msg + "\n" + errLayerStr)
+            return False
+
+        errColStr = ""
+        for col in ["afcol", "abcol", "ncol"]:
+            if col and col in inv_params and col in relevant_params:
+                errColStr += _("Chosen column '%s' does not exist in attribute table of layer '%s' of vector map '%s'.\n") % \
+                             (params[col], params[layer], params['input'])
+
+        if errColStr:
+            GMessage(parent = self.guiparent,
+                     message = msg + "\n" + errColStr)
+            return False
+
+        return True
+
+    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)
+
+class VNETPointsData:
+    def __init__(self, mapWin, an_data, an_params):
+
+        self.mapWin = mapWin
+        self.an_data = an_data
+        self.an_params = an_params
+
+        self.handlerRegistered = False
+
+        self.pointsChanged = Signal('VNETPointsData.pointsChanged')
+        self.an_params.parametersChanged.connect(self.ParametersChanged)
+
+        self.snapping = False
+
+        self.data = []
+        self.cols = { "name" : ['use', 'type', 'topology', 'e', 'n'],
+                      "label" : [_('use'), _('type'), _('topology'), 'e', 'n'],
+                      "type" :  [None, [_(""), _("Start point"), _("End Point")], None, float, float],#TDO
+                      "def_vals" : [False, 0, "new point", 0, 0]  
+                    }
+
+
+        # registration graphics for drawing
+        self.pointsToDraw = self.mapWin.RegisterGraphicsToDraw(graphicsType = "point", 
+                                                               setStatusFunc = self.SetPointStatus)
+
+        self.SetPointDrawSettings()
+
+        self.AddPoint()
+        self.AddPoint()
+
+        self.SetPointData(0, {'use' : True, 'type' : 1})
+        self.SetPointData(1, {'use' : True, 'type' : 2})
+
+        self.selected = 0
+
+    def  __del__(self):
+
+        self.mapWin.UnregisterGraphicsToDraw(self.pointsToDraw)
+
+        if self.handlerRegistered:
+            self.mapWin.UnregisterMouseEventHandler(wx.EVT_LEFT_DOWN, 
+                                                  self.OnMapClickHandler)
+
+    def SetSnapping(self, activate):
+        self.snapping = activate
+
+    def GetSnapping(self):
+        return self.snapping
+
+    def AddPoint(self):
+
+        self.pointsToDraw.AddItem(coords = (self.cols["def_vals"][3], self.cols["def_vals"][4]))
+        self.data.append(self.cols["def_vals"][:])
+        
+        self.pointsChanged.emit(method = "AddPoint", kwargs = {})
+
+    def DeletePoint(self, pt_id):
+        self.pointsToDraw.DeleteItem(pt_id)
+        self.data.pop(pt_id)
+
+        self.pointsChanged.emit(method = "DeletePoint", kwargs = {"pt_id" : pt_id})
+
+    def SetPoints(self, pts_data):
+
+        for item in self.pointsToDraw.GetAllItems():
+            self.pointsToDraw.DeleteItem(item)
+
+        self.data = []
+        for pt_data in pts_data:
+            pt_data_list = self._ptDataToList(pt_data)
+            self.data.append(pt_data_list)
+            self.pointsToDraw.AddItem(coords = (pt_data_list[3], pt_data_list[4]))
+
+        self.pointsChanged.emit(method = "SetPoints", kwargs = {"pts_data" : pts_data})
+
+    def SetPointData(self, pt_id, data):
+        for col, v in data.iteritems():
+            if col == 'use':
+                continue
+
+            idx = self.cols["name"].index(col)
+            self.data[pt_id][idx] = v
+
+        if data.has_key('use'):
+            if self._usePoint(pt_id, data["use"]) == -1:
+                data["use"] =  False
+            idx = self.cols["name"].index("use")
+            self.data[pt_id][idx] = v
+
+        self.pointsChanged.emit(method = "SetPointData", kwargs = {"pt_id" : pt_id, "data" : data})
+
+    def GetPointData(self, pt_id):
+        return self._ptListDataToPtData(self.data[pt_id])
+
+    def GetPointsCount(self):
+        return len(self.data)
+
+    def SetPointStatus(self, item, itemIndex):
+        """!Before point is drawn, decides properties of drawing style"""
+        analysis, valid = self.an_params.GetParam("analysis")
+        cats = self.an_data[analysis]["cmdParams"]["cats"]
+
+        if itemIndex == self.selected:
+            wxPen = "selected"
+        elif not self.data[itemIndex][0]:
+                wxPen = "unused"
+                item.hide = False
+        elif len(cats) > 1:
+            idx = self.data[itemIndex][1] 
+            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 SetSelected(self, pt_id):
+        self.selected = pt_id
+        self.pointsChanged.emit(method = "SetSelected", kwargs = {"pt_id" : pt_id})
+
+    def GetSelected(self):
+        return self.selected
+
+    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))
+
+    def ParametersChanged(self, method, kwargs):
+        if "analysis" in kwargs["changed_params"].keys():
+            self._updateTypeCol()
+
+    def _updateTypeCol(self):
+        """Rename category values when module is changed. Expample: Start point -> Sink point"""
+        colValues = [""]
+        analysis, valid = self.an_params.GetParam("analysis")
+        anParamsCats = self.an_data[analysis]["cmdParams"]["cats"]
+
+        for ptCat in anParamsCats:
+            colValues.append(ptCat[1])
+
+        type_idx = self.cols["name"].index("type")
+        self.cols['type'][type_idx] = colValues
+
+    def _ptDataToList(self, pt_data):
+
+        pt_list_data = [None] * len(self.cols['name'])
+
+        for k, val in pt_data.iteritems():
+            pt_list_data[self.cols["name"].index(k)] = val
+
+        return pt_list_data 
+
+    def _ptListDataToPtData(self, pt_list_data):
+
+        pt_data = {}
+        for i, val in enumerate(pt_list_data):
+            pt_data[self.cols["name"][i]] = val
+
+        return pt_data
+
+    def _usePoint(self, pt_id, use):
+        """!Item is checked/unchecked"""
+        analysis, valid = self.an_params.GetParam("analysis")
+        cats = self.an_data[analysis]["cmdParams"]["cats"]
+
+        ##TODO move
+        #if self.updateMap:
+        #    up_map_evt = gUpdateMap(render = False, renderVector = False)
+        #    wx.PostEvent(self.dialog.mapWin, up_map_evt)
+
+        if len(cats) <= 1:
+            return 0
+
+        type_idx = self.cols["name"].index("type")
+        use_idx = self.cols["name"].index("use")
+        checkedVal = self.data[pt_id][1]
+
+        if checkedVal == 0:
+            self.data[pt_id][use_idx] = False
+            self.pointsChanged.emit(method = "SetPointData", kwargs = {"pt_id" : pt_id, "data" : {"use" : False}})
+            return -1
+
+        if analysis == "v.net.path" and use:
+            alreadyChecked = []
+
+            if pt_id:
+                checkedKey = pt_id
+                alreadyChecked.append(self.data[pt_id][type_idx])
+            else:
+                checkedKey = -1
+
+            for iKey, dt in enumerate(self.data):
+                pt_type = dt[type_idx]
+
+                if ((pt_type in alreadyChecked and checkedKey != iKey) \
+                   or pt_type == 0) and self.data[iKey][use_idx]:
+                    self.data[iKey][use_idx] = False
+                    self.pointsChanged.emit(method = "SetPointData", kwargs = {"pt_id" : iKey, "data": {"use" : False}})
+                elif self.data[iKey][use_idx]:
+                    alreadyChecked.append(pt_type)
+
+
+    def EditPointMode(self, activate):
+        """!Registers/unregisters mouse handler into map window"""
+
+        if activate == self.handlerRegistered:
+            return
+
+        if activate:
+            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
+
+        self.pointsChanged.emit(method = "EditMode", kwargs = {"activated" : activate})
+
+    def IsEditPointModeActive(self):
+        return self.handlerRegistered
+
+    def OnMapClickHandler(self, event):
+        """!Take coordinates from map window"""
+        #TODO update snapping after input change
+        if event == 'unregistered':
+            self.handlerRegistered = False
+            return
+
+        if not self.data:
+            self.AddPoint()
+
+        e, n = self.mapWin.GetLastEN()
+        
+        if self.snapping:
+
+            # 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
+
+            params, err_params, flags = self.an_params.GetParams()
+            vectMap = params["input"]
+
+            if "input" in err_params:
+                msg = _("new point")
+
+            coords = SnapToNode(e, n, snapTreshDist, vectMap)     
+            if coords:
+                e = coords[0]
+                n = coords[1]
+
+                msg = ("snapped to node")
+            else:
+                msg = _("new point")
+
+        else:
+            msg = _("new point")
+
+        if self.selected == len(self.data) - 1:
+            self.SetSelected(0)
+        else:
+            self.SetSelected(self.GetSelected() + 1)
+
+        self.SetPointData(self.selected, 
+                         {'topology' : msg,
+                          'e' : e,
+                          'n' : n})
+
+        self.pointsToDraw.GetItem(self.selected).SetCoords([e, n])
+            
+    def GetColumns(self, only_relevant  = True):
+        
+        cols_data = deepcopy(self.cols)
+
+        hidden_cols = []
+        hidden_cols.append(self.cols["name"].index("e"))
+        hidden_cols.append(self.cols["name"].index("n"))
+
+        analysis, valid = self.an_params.GetParam("analysis")
+        if only_relevant and len(self.an_data[analysis]["cmdParams"]["cats"]) <= 1:
+            hidden_cols.append(self.cols["name"].index("type"))
+
+        i_red = 0
+        hidden_cols.sort()
+        for idx in hidden_cols:
+            for dt in cols_data.itervalues():
+                dt.pop(idx - i_red)
+            i_red +=1
+
+        return cols_data
+
+class VNETAnalysisParameters:
+    def __init__(self, an_props):
+
+        self.an_props = an_props
+
+        self.params = {"analysis"   : self.an_props.used_an[0],
+                       "input"      : "",
+                       "alayer"     : "",
+                       "nlayer"     : "",
+                       "afcolumn"   : "",
+                       "abcolumn"   : "",
+                       "ncolumn"    : "",
+                       "tlayer"     : "",
+                       "tuclayer"   : "",
+                       "iso_lines"  : "", #TODO check validity
+                       "max_dist"   : 0} #TODO check validity
+
+        self.flags = {"t" : False}
+
+        self.parametersChanged = Signal('VNETAnalysisParameters.parametersChanged')
+
+    def SetParams(self, params, flags):
+        
+        changed_params = {} 
+        for p, v in params.iteritems():
+            if p == "analysis" and  v not in self.an_props.used_an:
+                continue
+
+            if p == "input":
+                mapName, mapSet = ParseMapStr(v)
+                v = mapName + "@" + mapSet
+
+            if self.params.has_key(p):
+                if isinstance(v, str):
+                    v = v.strip()
+            
+                self.params[p] = v
+                changed_params[p] = v
+
+        changed_flags = {}
+        for p, v in flags.iteritems():
+            if self.flags.has_key(p):
+                self.flags[p] = v
+                changed_flags[p] = v
+
+        self.parametersChanged.emit(method = "SetParams", 
+                                    kwargs = {"changed_params" : changed_params , "changed_flags" : changed_flags})
+
+        return changed_params, changed_flags
+
+    def GetParam(self, param):
+
+        invParams = []
+        if param in ["input", "alayer", "nlayer", "afcolumn", 
+                     "abcolumn", "ncolumn", "tlayer", "tuclayer"]:
+            invParams = self._getInvalidParams(self.params)
+
+        if invParams: 
+            return self.params[param], False
+
+        return self.params[param], True
+
+    def GetParams(self):
+        
+        invParams = self._getInvalidParams(self.params)
+        return self.params, invParams, self.flags 
+
+    def _getInvalidParams(self, params):
+        """!Check of analysis input data for invalid values (Parameters tab)"""
+        # dict of invalid values {key from self.itemData (comboboxes from Parameters tab) : invalid value}
+        invParams = []
+
+        # check vector map
+        if params["input"]:
+            mapName, mapSet = params["input"].split("@")
+            if grass.list_grouped('vect').has_key(mapSet):
+                vectMaps = grass.list_grouped('vect')[mapSet]
+
+        if not params["input"] or mapName not in vectMaps:
+            invParams = params.keys()[:]
+            return invParams
+
+        # check arc/node layer
+        layers = utils.GetVectorNumberOfLayers(params["input"])    
+        
+        for l in ['alayer', 'nlayer', 'tlayer', 'tuclayer']:
+            if not layers or params[l] not in layers:
+                invParams.append(l)
+
+        dbInfo = VectorDBInfo(params["input"])
+
+        try:
+            table = dbInfo.GetTable(int(params["alayer"]))
+            columnchoices = dbInfo.GetTableDesc(table)
+        except (KeyError, ValueError):
+            table = None
+
+        # check costs columns
+        for col in ["afcolumn", "abcolumn", "ncolumn"]:
+            if col == "ncolumn":
+                try:
+                    table = dbInfo.GetTable(int(params["nlayer"]))
+                    columnchoices = dbInfo.GetTableDesc(table)
+                except (KeyError, ValueError):
+                    table = None
+
+            if not table or  not params[col]  in columnchoices.keys():
+                invParams.append(col)
+                continue
+
+            if not columnchoices[col].value['type'] not in ['integer', 'double precision']:
+                invParams.append(col)
+                continue
+     
+        return invParams  
+
+class VNETAnalysesProperties:
+    def __init__(self):
+        """!Initializes parameters for different v.net.* modules """
+        # initialization of v.net.* analysis parameters (data which characterizes particular analysis)
+
+        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.vnetProperties = {
+                                   "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  #TODO delete this property, this information can be get from result
+                                                                     },
+                                                     "turns_support" : True
+                                                  },
+
+                                    "v.net.salesman" : {
+                                                        "label" : _("Traveling salesman %s") % "(v.net.salesman)",  
+                                                        "cmdParams" : {
+                                                                        "cats" : [["ccats", None]],
+                                                                        "cols" : [
+                                                                                  'afcolumn',
+                                                                                  'abcolumn'
+                                                                                 ],
+                                                                      },
+                                                        "resultProps" : {
+                                                                         "singleColor" : None,
+                                                                         "dbMgr" : False
+                                                                        },
+                                                     "turns_support" : True
+
+                                                       },
+                                    "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
+                                                                     },
+                                                     "turns_support" : False
+                                                   },
+                                    "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
+                                                                      },
+                                                     "turns_support" : True
+                                                   },
+                                    "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 
+                                                                     },
+                                                     "turns_support" : True
+                                                   },
+                                   "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
+                                                                      },
+                                                     "turns_support" : False
+                                                     },
+                                    "v.net.iso" :  {
+                                                     "label" : _("Cost isolines %s") % "(v.net.iso)",  
+                                                     "cmdParams" : {
+                                                                      "cats" : [["ccats", None]],                           
+                                                                      "cols" : [
+                                                                                 'afcolumn',
+                                                                                 'abcolumn',
+                                                                                 'ncolumn'
+                                                                               ]
+                                                                  },
+                                                     "resultProps" : {
+                                                                      "catColor" : None,
+                                                                      "dbMgr" : False
+                                                                     },
+                                                     "turns_support" : True
+                                                   }
+                                }
+
+        self.used_an = ["v.net.path", 
+                         "v.net.salesman",
+                         "v.net.flow",
+                         "v.net.alloc",
+                         "v.net.distance",
+                         "v.net.iso",
+                         #"v.net.steiner"
+                        ] 
+
+        for an in self.vnetProperties.keys():
+            if an not in self.used_an:
+                del self.vnetProperties[an]
+                continue
+
+            cols = self.vnetProperties[an]["cmdParams"]["cols"] 
+            self.vnetProperties[an]["cmdParams"]["cols"] = {}
+            for c in  cols:
+                self.vnetProperties[an]["cmdParams"]["cols"][c] = self.attrCols[c]
+
+    def has_key(self, key):
+        return self.vnetProperties.has_key(key)
+
+    def __getitem__(self, key):
+        return self.vnetProperties[key]
+
+    def GetRelevantParams(self, analysis):
+
+        if not self.vnetProperties.has_key(analysis):
+            return None
+
+        relevant_params = ["input", "alayer", "nlayer"]
+
+        if self.vnetProperties[analysis]["turns_support"]:
+            relevant_params += ["tlayer", "tuclayer"]
+
+        cols = self.vnetProperties[analysis]["cmdParams"]["cols"]
+
+        for col, v in cols.iteritems():
+            if "inputField" in col:
+                colInptF = v["inputField"]
+            else:
+                colInptF = col
+            relevant_params.append(colInptF)
+
+        return relevant_params
+
+class VNETTmpVectMaps:
+    """!Class which creates, stores and destroys all tmp maps created during analysis"""
+    def __init__(self, parent, mapWin):
+        self.tmpMaps = [] # temporary maps 
+        self.parent = parent
+        self.mapWin = 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.mapWin, 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, mapWin, fullName):
+        self.fullName = fullName
+        self.mapWin = mapWin
+        self.renderLayer = None
+        self.modifTime = None # time, for modification check
+
+    def __del__(self):
+
+        self.DeleteRenderLayer()
+   
+    def AddRenderLayer(self, cmd = None, colorsCmd = None):
+        """!Add map from map window layers to render """
+
+        if not self.mapWin:
+            return False
+
+        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()
+
+        if colorsCmd:
+            colorsCmd.append('map=%s' % self.fullName)
+            layerStyleVnetColors = utils.CmdToTuple(colorsCmd)
+
+            RunCommand(layerStyleVnetColors[0],
+                        **layerStyleVnetColors[1])
+
+
+        self.renderLayer = self.mapWin.Map.AddLayer(ltype = "vector",     command = cmd,
+                                                    name = self.fullName, active = True,
+                                                    opacity = 1.0,        render = True,       
+                                                    pos = -1)
+        return True
+
+    def DeleteRenderLayer(self):
+        """!Remove map from map window layers to render"""
+        if not self.mapWin:
+            return False
+
+        if self.renderLayer: 
+             self.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)
+
+    @todo Maybe it could be useful for other GRASS wxGUI tools.
+    """   
+    def __init__(self):
+
+        # 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 VNETGlobalTurnsData:
+    """!Turn Data"""
+    def __init__(self):
+        # Definition of four basic directions
+        self.turn_data = [
+                            ["Straight", DegreesToRadians(-30), DegreesToRadians(+30), 0.0],
+                            ["Right Turn", DegreesToRadians(+30), DegreesToRadians(+150), 0.0],
+                            ["Reverse",  DegreesToRadians(+150), DegreesToRadians(-150), 0.0],
+                            ["Left Turn",  DegreesToRadians(-150), DegreesToRadians(-30), 0.0]  
+                            ]   
+    def GetData(self):
+        data = []
+        for ival in self.turn_data:
+            data.append(ival[1:])
+
+        return data
+
+    def GetValue(self, line, col):
+        return self.turn_data[line][col]
+
+    def GetLinesCount(self):
+        return len(self.turn_data)
+
+    def SetValue(self, value, line, col):
+        self.DataValidator(line, col, value)
+        self.turn_data[line][col] = value
+
+    def SetUTurns(self, value):
+        """!Checked if checeBox is checed"""
+        useUTurns = value
+
+    def AppendRow(self, values):
+        self.turn_data.append(values)
+
+    def InsertRow(self,line,values):
+        self.turn_data.insert(line,values)
+
+    def PopRow(self, values):
+        self.RemoveDataValidator(values)
+        self.turn_data.pop(values)
+             
+    def DataValidator(self, row, col, value):
+        """!Angle recalculation due to value changing"""
+
+        if col not in [1,2]:
+            return
+
+        if col == 1:
+            new_from_angle = value
+            old_from_angle = self.turn_data[row][1]
+            new_to_angle  = self.turn_data[row][2]
+            if self.IsInInterval(old_from_angle, new_to_angle, new_from_angle):
+
+                prev_row = row - 1
+                if  prev_row == -1:
+                    prev_row = len(self.turn_data) - 1
+                self.turn_data[prev_row][2] = new_from_angle
+                return
+        
+        if col ==2:
+            new_to_angle = value
+            old_to_angle = self.turn_data[row][2]
+            new_from_angle = self.turn_data[row][1]
+            if self.IsInInterval(new_from_angle, old_to_angle, new_to_angle):
+
+                next_row = row + 1
+                if len(self.turn_data) == next_row:
+                    next_row = 0
+                self.turn_data[next_row][1] = new_to_angle 
+                return     
+                   
+
+        inside_new = []
+        overlap_new_from = []
+        overlap_new_to = []
+
+        for i in range(self.GetLinesCount()):
+            if i == row:
+                continue
+            from_angle = self.turn_data[i][1]
+            is_in_from = self.IsInInterval(new_from_angle, new_to_angle, from_angle)
+
+            to_angle = self.turn_data[i][2]
+            is_in_to = self.IsInInterval(new_from_angle, new_to_angle, to_angle)
+
+
+            if is_in_from and is_in_to:
+                inside_new.append(i)
+            if is_in_from:
+                overlap_new_to.append(i)
+            if is_in_to:
+                overlap_new_from.append(i)
+
+        for i_row in overlap_new_from:
+            self.turn_data[i_row][2] = new_from_angle
+
+        for i_row in overlap_new_to:
+            self.turn_data[i_row][1] = new_to_angle
+
+        for i_row in inside_new:
+            if col == 1:
+                angle = new_from_angle            
+            else:
+                angle = new_to_angle
+
+            self.turn_data[i_row][1] = angle
+            self.turn_data[i_row][2] = angle
+
+    def RemoveDataValidator(self, row):
+        """!Angle recalculation due to direction remove"""
+        if row == 0:
+            prev_row = self.GetLinesCount() - 1
+        else:
+            prev_row = row - 1
+
+        remove_to_angle = self.turn_data[row][2]        
+        self.turn_data[prev_row][2] = remove_to_angle
+
+
+    def IsInInterval(self, from_angle, to_angle, angle):
+        """!Test if a direction includes or not includes a value"""  
+        if to_angle < from_angle:
+            to_angle = math.pi * 2  + to_angle
+        if angle < from_angle:
+                angle = math.pi * 2  + angle
+            
+        if angle > from_angle and angle < to_angle:
+            return True
+        return False
\ No newline at end of file

Added: grass/trunk/gui/wxpython/vnet/vnet_utils.py
===================================================================
--- grass/trunk/gui/wxpython/vnet/vnet_utils.py	                        (rev 0)
+++ grass/trunk/gui/wxpython/vnet/vnet_utils.py	2013-06-16 21:36:51 UTC (rev 56736)
@@ -0,0 +1,153 @@
+"""!
+ at package vnet.vnet_utils
+
+ at brief Vector network analysis utilities.
+
+Classes:
+ - vnet_core::VNETTmpVectMaps
+ - vnet_core::VectMap
+ - vnet_core::History
+
+(C) 2013 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)
+ at author Lukas Bocan <silent_bob centrum.cz> (turn costs support)
+ at author Eliska Kyzlikova <eliska.kyzlikova gmail.com> (turn costs support)
+"""
+
+import  math
+from grass.script     import core as grass
+
+try:
+    import grass.lib.vector as vectlib
+    from ctypes import pointer, byref, c_char_p, c_int, c_double, POINTER
+    haveCtypes = True
+except ImportError:
+    haveCtypes = False
+
+def ParseMapStr(mapStr):
+    """!Create full map name (add current mapset if it is not present in name)"""
+    mapValSpl = mapStr.strip().split("@")
+    if len(mapValSpl) > 1:
+        mapSet = mapValSpl[1]
+    else:
+        mapSet = grass.gisenv()['MAPSET']
+    mapName = mapValSpl[0] 
+        
+    return mapName, mapSet
+
+def DegreesToRadians(degrees):
+    return degrees * math.pi / 180
+
+def RadiansToDegrees(radians):
+    return radians * 180 / math.pi   
+
+def SnapToNode(e, n, tresh, vectMap):
+    """!Find nearest node to click coordinates (within given threshold)"""
+    if not haveCtypes:
+        return None
+
+    vectMap, mapSet = ParseMapStr(vectMap)
+
+    openedMap = pointer(vectlib.Map_info())
+    ret = vectlib.Vect_open_old(openedMap, 
+                                     c_char_p(vectMap),
+                                     c_char_p(mapSet))
+    if ret == 1:
+        vectlib.Vect_close(openedMap)
+    if ret != 2: 
+        return None
+
+    nodeNum =  vectlib.Vect_find_node(openedMap,     
+                                      c_double(e), 
+                                      c_double(n), 
+                                      c_double(0), 
+                                      c_double(tresh),
+                                      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
+
+    return e, n
+
+def GetNearestNodeCat(e, n, layer, tresh, vectMap):
+
+    if  not haveCtypes:
+        return -2
+
+    vectMapName, mapSet = ParseMapStr(vectMap)
+
+    openedMap = pointer(vectlib.Map_info())
+    ret = vectlib.Vect_open_old(openedMap, 
+                                     c_char_p(vectMapName),
+                                     c_char_p(mapSet))
+    if ret == 1:
+        vectlib.Vect_close(openedMap)
+    if ret != 2: 
+        return -1
+
+    nodeNum = vectlib.Vect_find_node(openedMap,     
+                                     c_double(e), 
+                                     c_double(n), 
+                                     c_double(0), 
+                                     c_double(tresh),
+                                     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 -1
+
+    box = vectlib.bound_box();
+    List = POINTER(vectlib.boxlist);
+    List = vectlib.Vect_new_boxlist(c_int(0));
+
+    box.E = box.W = e;
+    box.N = box.S = n;
+    box.T = box.B = 0;
+    vectlib.Vect_select_lines_by_box(openedMap, byref(box), vectlib.GV_POINT, List);
+
+    found = 0;
+    dcost = 0;
+
+    Cats = POINTER(vectlib.line_cats)
+    Cats = vectlib.Vect_new_cats_struct()
+ 
+    cat = c_int(0)
+
+    for j in range(List.contents.n_values): 
+        line = List.contents.id[j]
+        type = vectlib.Vect_read_line(openedMap, None, Cats, line)
+        if type != vectlib.GV_POINT:
+            continue
+
+        if vectlib.Vect_cat_get(Cats, c_int(layer), byref(cat)): 
+            found = 1
+            break
+    if found:
+        return cat.value
+
+    return -1
\ No newline at end of file

Modified: grass/trunk/gui/wxpython/vnet/widgets.py
===================================================================
--- grass/trunk/gui/wxpython/vnet/widgets.py	2013-06-16 18:05:10 UTC (rev 56735)
+++ grass/trunk/gui/wxpython/vnet/widgets.py	2013-06-16 21:36:51 UTC (rev 56736)
@@ -146,7 +146,7 @@
                 info.SetText(col[1][iLabel]) 
                 self.InsertColumnInfo(col[0], info)
 
-    def AddItem(self, event):
+    def AddItem(self):
         """!Appends an item to list with default values"""
         iDefVal = self.dataTypes["itemDefaultValue"]
         iColEd = self.dataTypes["colEditable"]
@@ -192,7 +192,14 @@
     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"]      
+
+        if colNum < 0:
+            return None
+
+        iColEd = self.dataTypes["colEditable"]
+        if self.selIdxs[key][colNum] != -1:
+            return self.selIdxs[key][colNum]
+
         return self.itemDataMap[key][colNum]
 
     def GetCellSelIdx(self, key, colName):
@@ -256,7 +263,7 @@
         iColEd = self.dataTypes["colEditable"]
         self.colsData[colNum][iColEd] = colType
 
-    def DeleteItem(self, event = None):
+    def DeleteItem(self):
         """!Delete selected item in list"""
         if self.selected == wx.NOT_FOUND:
             return
@@ -373,7 +380,7 @@
 
                 self.selIdxs[key] = dlg.GetSelectionIndexes()
         dlg.Destroy()
-        return changed
+        return changed, key
         
     def CreateEditDialog(self, data, pointNo):
         """!Helper function



More information about the grass-commit mailing list