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