12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067 |
- """
- @package vdigit.toolbars
- @brief wxGUI vector digitizer toolbars
- List of classes:
- - toolbars::VDigitToolbar
- (C) 2007-2014 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 Martin Landa <landa.martin gmail.com>
- @author Stepan Turek <stepan.turek seznam.cz> (handlers support)
- """
- import wx
- from grass import script as grass
- from grass.pydispatch.signal import Signal
- from gui_core.toolbars import BaseToolbar, BaseIcons
- from gui_core.dialogs import CreateNewVector, VectorDialog
- from vdigit.preferences import VDigitSettingsDialog
- from core.debug import Debug
- from core.settings import UserSettings
- from core.gcmd import GError, RunCommand
- from core.utils import _
- from icons.icon import MetaIcon
- from iclass.digit import IClassVDigit
- from core.giface import Notification
- class VDigitToolbar(BaseToolbar):
- """Toolbar for digitization
- """
- def __init__(self, parent, toolSwitcher, MapWindow, digitClass, giface,
- tools=[]):
- self.MapWindow = MapWindow
- self.Map = MapWindow.GetMap() # Map class instance
- self.tools = tools
- self.digitClass = digitClass
- BaseToolbar.__init__(self, parent, toolSwitcher)
- self.digit = None
- self._giface = giface
- self.fType = None # feature type for simple features editing
- self.editingStarted = Signal("VDigitToolbar.editingStarted")
- self.editingStopped = Signal("VDigitToolbar.editingStopped")
- self.editingBgMap = Signal("VDigitToolbar.editingBgMap")
- layerTree = self._giface.GetLayerTree()
- if layerTree:
- self.editingStarted.connect(layerTree.StartEditing)
- self.editingStopped.connect(layerTree.StopEditing)
- self.editingBgMap.connect(layerTree.SetBgMapForEditing)
-
- # currently selected map layer for editing (reference to MapLayer instance)
- self.mapLayer = None
- # list of vector layers from Layer Manager (only in the current mapset)
- self.layers = []
-
- self.comboid = self.combo = None
- self.undo = -1
- self.redo = -1
-
- # only one dialog can be open
- self.settingsDialog = None
- # create toolbars (two rows optionally)
- self.InitToolbar(self._toolbarData())
-
- self._default = -1
- # default action (digitize new point, line, etc.)
- self.action = { 'desc' : '',
- 'type' : '',
- 'id' : -1 }
- self._currentAreaActionType = None
-
- # list of available vector maps
- self.UpdateListOfLayers(updateTool = True)
-
- for tool in ('addPoint', 'addLine', 'addBoundary', 'addCentroid', 'addArea',
- 'addVertex', 'deleteLine', 'deleteArea', 'displayAttr', 'displayCats',
- 'editLine', 'moveLine', 'moveVertex', 'removeVertex', 'additionalTools'):
- if hasattr(self, tool):
- tool = getattr(self, tool)
- self.toolSwitcher.AddToolToGroup(group='mouseUse', toolbar=self, tool=tool)
- else:
- Debug.msg(1, '%s skipped' % tool)
-
- # custom button for digitization of area/boundary/centroid
- # TODO: could this be somehow generalized?
- nAreaTools = 0
- if self.tools and 'addBoundary' in self.tools: nAreaTools += 1
- if self.tools and 'addCentroid' in self.tools: nAreaTools += 1
- if self.tools and 'addArea' in self.tools: nAreaTools += 1
- if nAreaTools != 1:
- self.areaButton = self.CreateSelectionButton(_("Select area/boundary/centroid tool"))
- self.areaButtonId = self.InsertControl(5, self.areaButton)
- self.areaButton.Bind(wx.EVT_BUTTON, self.OnAddAreaMenu)
-
- # realize toolbar
- self.Realize()
- # workaround for Mac bug. May be fixed by 2.8.8, but not before then.
- if self.combo:
- self.combo.Hide()
- self.combo.Show()
-
- # disable undo/redo
- if self.undo > 0:
- self.EnableTool(self.undo, False)
- if self.redo > 0:
- self.EnableTool(self.redo, False)
- self.FixSize(width = 105)
- def _toolbarData(self):
- """Toolbar data
- """
- data = []
-
- self.icons = {
- 'addPoint' : MetaIcon(img = 'point-create',
- label = _('Digitize new point'),
- desc = _('Left: new point')),
- 'addLine' : MetaIcon(img = 'line-create',
- label = _('Digitize new line'),
- desc = _('Left: new point; Ctrl+Left: undo last point; Right: close line')),
- 'addBoundary' : MetaIcon(img = 'boundary-create',
- label = _('Digitize new boundary'),
- desc = _('Left: new point; Ctrl+Left: undo last point; Right: close line')),
- 'addCentroid' : MetaIcon(img = 'centroid-create',
- label = _('Digitize new centroid'),
- desc = _('Left: new point')),
- 'addArea' : MetaIcon(img = 'polygon-create',
- label = _('Digitize new area (boundary without category)'),
- desc = _('Left: new point')),
- 'addVertex' : MetaIcon(img = 'vertex-create',
- label = _('Add new vertex to line or boundary'),
- desc = _('Left: Select; Ctrl+Left: Unselect; Right: Confirm')),
- 'deleteLine' : MetaIcon(img = 'line-delete',
- label = _('Delete selected point(s), line(s), boundary(ies) or centroid(s)'),
- desc = _('Left: Select; Ctrl+Left: Unselect; Right: Confirm')),
- 'deleteArea' : MetaIcon(img = 'polygon-delete',
- label = _('Delete selected area(s)'),
- desc = _('Left: Select; Ctrl+Left: Unselect; Right: Confirm')),
- 'displayAttr' : MetaIcon(img = 'attributes-display',
- label = _('Display/update attributes'),
- desc = _('Left: Select')),
- 'displayCats' : MetaIcon(img = 'cats-display',
- label = _('Display/update categories'),
- desc = _('Left: Select')),
- 'editLine' : MetaIcon(img = 'line-edit',
- label = _('Edit selected line/boundary'),
- desc = _('Left: new point; Ctrl+Left: undo last point; Right: close line')),
- 'moveLine' : MetaIcon(img = 'line-move',
- label = _('Move selected point(s), line(s), boundary(ies) or centroid(s)'),
- desc = _('Left: Select; Ctrl+Left: Unselect; Right: Confirm')),
- 'moveVertex' : MetaIcon(img = 'vertex-move',
- label = _('Move selected vertex'),
- desc = _('Left: Select; Ctrl+Left: Unselect; Right: Confirm')),
- 'removeVertex' : MetaIcon(img = 'vertex-delete',
- label = _('Remove selected vertex'),
- desc = _('Left: Select; Ctrl+Left: Unselect; Right: Confirm')),
- 'settings' : BaseIcons['settings'].SetLabel(_('Digitization settings')),
- 'quit' : BaseIcons['quit'].SetLabel(label = _('Quit digitizer'),
- desc = _('Quit digitizer and save changes')),
- 'help' : BaseIcons['help'].SetLabel(label = _('Vector Digitizer manual'),
- desc = _('Show Vector Digitizer manual')),
- 'additionalTools' : MetaIcon(img = 'tools',
- label = _('Additional tools '
- '(copy, flip, connect, etc.)'),
- desc = _('Left: Select; Ctrl+Left: Unselect; Right: Confirm')),
- 'undo' : MetaIcon(img = 'undo',
- label = _('Undo'),
- desc = _('Undo previous changes')),
- 'redo' : MetaIcon(img = 'redo',
- label = _('Redo'),
- desc = _('Redo previous changes')),
- }
-
- if not self.tools or 'selector' in self.tools:
- data.append((None, ))
- if not self.tools or 'addPoint' in self.tools:
- data.append(("addPoint", self.icons["addPoint"],
- self.OnAddPoint,
- wx.ITEM_CHECK))
- if not self.tools or 'addLine' in self.tools:
- data.append(("addLine", self.icons["addLine"],
- self.OnAddLine,
- wx.ITEM_CHECK))
- if not self.tools or 'addArea' in self.tools:
- data.append(("addArea", self.icons["addArea"],
- self.OnAddAreaTool,
- wx.ITEM_CHECK))
- if not self.tools or 'deleteLine' in self.tools:
- data.append(("deleteLine", self.icons["deleteLine"],
- self.OnDeleteLine,
- wx.ITEM_CHECK))
- if not self.tools or 'deleteArea' in self.tools:
- data.append(("deleteArea", self.icons["deleteArea"],
- self.OnDeleteArea,
- wx.ITEM_CHECK))
- if not self.tools or 'moveVertex' in self.tools:
- data.append(("moveVertex", self.icons["moveVertex"],
- self.OnMoveVertex,
- wx.ITEM_CHECK))
- if not self.tools or 'addVertex' in self.tools:
- data.append(("addVertex", self.icons["addVertex"],
- self.OnAddVertex,
- wx.ITEM_CHECK))
- if not self.tools or 'removeVertex' in self.tools:
- data.append(("removeVertex", self.icons["removeVertex"],
- self.OnRemoveVertex,
- wx.ITEM_CHECK))
- if not self.tools or 'editLine' in self.tools:
- data.append(("editLine", self.icons["editLine"],
- self.OnEditLine,
- wx.ITEM_CHECK))
- if not self.tools or 'moveLine' in self.tools:
- data.append(("moveLine", self.icons["moveLine"],
- self.OnMoveLine,
- wx.ITEM_CHECK))
- if not self.tools or 'displayCats' in self.tools:
- data.append(("displayCats", self.icons["displayCats"],
- self.OnDisplayCats,
- wx.ITEM_CHECK))
- if not self.tools or 'displayAttr' in self.tools:
- data.append(("displayAttr", self.icons["displayAttr"],
- self.OnDisplayAttr,
- wx.ITEM_CHECK))
- if not self.tools or 'additionalSelf.Tools' in self.tools:
- data.append(("additionalTools", self.icons["additionalTools"],
- self.OnAdditionalToolMenu,
- wx.ITEM_CHECK))
- if not self.tools or 'undo' in self.tools or \
- 'redo' in self.tools:
- data.append((None, ))
- if not self.tools or 'undo' in self.tools:
- data.append(("undo", self.icons["undo"],
- self.OnUndo))
- if not self.tools or 'redo' in self.tools:
- data.append(("redo", self.icons["redo"],
- self.OnRedo))
- if not self.tools or 'settings' in self.tools or \
- 'help' in self.tools or \
- 'quit' in self.tools:
- data.append((None, ))
- if not self.tools or 'settings' in self.tools:
- data.append(("settings", self.icons["settings"],
- self.OnSettings))
- if not self.tools or 'help' in self.tools:
- data.append(("help", self.icons["help"],
- self.OnHelp))
- if not self.tools or 'quit' in self.tools:
- data.append(("quit", self.icons["quit"],
- self.OnExit))
-
- return self._getToolbarData(data)
- def OnTool(self, event):
- """Tool selected -> untoggles previusly selected tool in
- toolbar"""
- Debug.msg(3, "VDigitToolbar.OnTool(): id = %s" % event.GetId())
- # set cursor
- self.MapWindow.SetNamedCursor('cross')
- self.MapWindow.mouse['box'] = 'point'
- self.MapWindow.mouse['use'] = 'pointer'
-
- aId = self.action.get('id', -1)
- BaseToolbar.OnTool(self, event)
- # clear tmp canvas
- if self.action['id'] != aId or aId == -1:
- self.MapWindow.polycoords = []
- self.MapWindow.ClearLines(pdc = self.MapWindow.pdcTmp)
- if self.digit and \
- len(self.MapWindow.digit.GetDisplay().GetSelected()) > 0:
- # cancel action
- self.MapWindow.OnMiddleDown(None)
-
- # set no action
- if self.action['id'] == -1:
- self.action = { 'desc' : '',
- 'type' : '',
- 'id' : -1 }
-
- # set focus
- self.MapWindow.SetFocus()
-
- def OnAddPoint(self, event):
- """Add point to the vector map Laier"""
- Debug.msg (2, "VDigitToolbar.OnAddPoint()")
- self.action = { 'desc' : "addLine",
- 'type' : "point",
- 'id' : self.addPoint }
- self.MapWindow.mouse['box'] = 'point'
-
- def OnAddLine(self, event):
- """Add line to the vector map layer"""
- Debug.msg (2, "VDigitToolbar.OnAddLine()")
- self.action = { 'desc' : "addLine",
- 'type' : "line",
- 'id' : self.addLine }
- self.MapWindow.mouse['box'] = 'line'
- ### self.MapWindow.polycoords = [] # reset temp line
- def OnAddBoundary(self, event):
- """Add boundary to the vector map layer"""
- Debug.msg (2, "VDigitToolbar.OnAddBoundary()")
- self._toggleAreaIfNeeded()
- # reset temp line
- if self.action['desc'] != 'addLine' or \
- self.action['type'] != 'boundary':
- self.MapWindow.polycoords = []
- # update icon and tooltip
- self.SetToolNormalBitmap(self.addArea, self.icons['addBoundary'].GetBitmap())
- self.SetToolShortHelp(self.addArea, self.icons['addBoundary'].GetLabel())
- # set action
- self.action = { 'desc' : "addLine",
- 'type' : "boundary",
- 'id' : self.addArea }
- self.MapWindow.mouse['box'] = 'line'
- self._currentAreaActionType = 'boundary'
-
- def OnAddCentroid(self, event):
- """Add centroid to the vector map layer"""
- Debug.msg (2, "VDigitToolbar.OnAddCentroid()")
- self._toggleAreaIfNeeded()
- # update icon and tooltip
- self.SetToolNormalBitmap(self.addArea, self.icons['addCentroid'].GetBitmap())
- self.SetToolShortHelp(self.addArea, self.icons['addCentroid'].GetLabel())
-
- # set action
- self.action = { 'desc' : "addLine",
- 'type' : "centroid",
- 'id' : self.addArea }
- self.MapWindow.mouse['box'] = 'point'
- self._currentAreaActionType = 'centroid'
- def OnAddArea(self, event):
- """Add area to the vector map layer"""
- Debug.msg (2, "VDigitToolbar.OnAddArea()")
- self._toggleAreaIfNeeded()
- # update icon and tooltip
- self.SetToolNormalBitmap(self.addArea, self.icons['addArea'].GetBitmap())
- self.SetToolShortHelp(self.addArea, self.icons['addArea'].GetLabel())
-
- # set action
- self.action = { 'desc' : "addLine",
- 'type' : "area",
- 'id' : self.addArea }
- self.MapWindow.mouse['box'] = 'line'
- self._currentAreaActionType = 'area'
- def _toggleAreaIfNeeded(self):
- """In some cases, the area tool is not toggled, we have to do it manually."""
- if not self.GetToolState(self.addArea):
- self.ToggleTool(self.addArea, True)
- self.toolSwitcher.ToolChanged(self.addArea)
- def OnAddAreaTool(self, event):
- """Area tool activated."""
- Debug.msg (2, "VDigitToolbar.OnAddAreaTool()")
- # we need the previous id
- if not self._currentAreaActionType or self._currentAreaActionType == 'area': # default action
- self.OnAddArea(event)
- elif self._currentAreaActionType == 'boundary':
- self.OnAddBoundary(event)
- elif self._currentAreaActionType == 'centroid':
- self.OnAddCentroid(event)
- def OnAddAreaMenu(self, event):
- """Digitize area menu (add area/boundary/centroid)"""
- menuItems = []
- if not self.tools or 'addArea' in self.tools:
- menuItems.append((self.icons["addArea"], self.OnAddArea))
- if not self.fType and not self.tools or 'addBoundary' in self.tools:
- menuItems.append((self.icons["addBoundary"], self.OnAddBoundary))
- if not self.fType and not self.tools or 'addCentroid' in self.tools:
- menuItems.append((self.icons["addCentroid"], self.OnAddCentroid))
-
- self._onMenu(menuItems)
- def OnExit (self, event = None):
- """Quit digitization tool"""
- # stop editing of the currently selected map layer
- if self.mapLayer:
- self.StopEditing()
-
- # close dialogs if still open
- if self.settingsDialog:
- self.settingsDialog.OnCancel(None)
-
- # set default mouse settings
- self.parent.GetMapToolbar().SelectDefault()
- self.MapWindow.polycoords = []
- # TODO: replace this by binding wx event in parent (or use signals...)
- if not self.parent.IsStandalone():
- # disable the toolbar
- self.parent.RemoveToolbar("vdigit")
- else:
- self.parent.Close()
-
- def OnMoveVertex(self, event):
- """Move line vertex"""
- Debug.msg(2, "Digittoolbar.OnMoveVertex():")
- self.action = { 'desc' : "moveVertex",
- 'id' : self.moveVertex }
- self.MapWindow.mouse['box'] = 'point'
- def OnAddVertex(self, event):
- """Add line vertex"""
- Debug.msg(2, "Digittoolbar.OnAddVertex():")
- self.action = { 'desc' : "addVertex",
- 'id' : self.addVertex }
- self.MapWindow.mouse['box'] = 'point'
-
- def OnRemoveVertex(self, event):
- """Remove line vertex"""
- Debug.msg(2, "Digittoolbar.OnRemoveVertex():")
- self.action = { 'desc' : "removeVertex",
- 'id' : self.removeVertex }
- self.MapWindow.mouse['box'] = 'point'
- def OnEditLine(self, event):
- """Edit line"""
- Debug.msg(2, "Digittoolbar.OnEditLine():")
- self.action = { 'desc' : "editLine",
- 'id' : self.editLine }
- self.MapWindow.mouse['box'] = 'line'
- def OnMoveLine(self, event):
- """Move line"""
- Debug.msg(2, "Digittoolbar.OnMoveLine():")
- self.action = { 'desc' : "moveLine",
- 'id' : self.moveLine }
- self.MapWindow.mouse['box'] = 'box'
- def OnDeleteLine(self, event):
- """Delete line"""
- Debug.msg(2, "Digittoolbar.OnDeleteLine():")
- self.action = { 'desc' : "deleteLine",
- 'id' : self.deleteLine }
- self.MapWindow.mouse['box'] = 'box'
- def OnDeleteArea(self, event):
- """Delete Area"""
- Debug.msg(2, "Digittoolbar.OnDeleteArea():")
- self.action = { 'desc' : "deleteArea",
- 'id' : self.deleteArea }
- self.MapWindow.mouse['box'] = 'box'
- def OnDisplayCats(self, event):
- """Display/update categories"""
- Debug.msg(2, "Digittoolbar.OnDisplayCats():")
- self.action = { 'desc' : "displayCats",
- 'id' : self.displayCats }
- self.MapWindow.mouse['box'] = 'point'
- def OnDisplayAttr(self, event):
- """Display/update attributes"""
- Debug.msg(2, "Digittoolbar.OnDisplayAttr():")
- self.action = { 'desc' : "displayAttrs",
- 'id' : self.displayAttr }
- self.MapWindow.mouse['box'] = 'point'
-
- def OnUndo(self, event):
- """Undo previous changes"""
- self.digit.Undo()
-
- event.Skip()
- def OnRedo(self, event):
- """Undo previous changes"""
- self.digit.Undo(level = 1)
-
- event.Skip()
-
- def EnableUndo(self, enable = True):
- """Enable 'Undo' in toolbar
-
- :param enable: False for disable
- """
- self._enableTool(self.undo, enable)
- def EnableRedo(self, enable = True):
- """Enable 'Redo' in toolbar
-
- :param enable: False for disable
- """
- self._enableTool(self.redo, enable)
-
- def _enableTool(self, tool, enable):
- if not self.FindById(tool):
- return
-
- if enable:
- if self.GetToolEnabled(tool) is False:
- self.EnableTool(tool, True)
- else:
- if self.GetToolEnabled(tool) is True:
- self.EnableTool(tool, False)
- def GetAction(self, type = 'desc'):
- """Get current action info"""
- return self.action.get(type, '')
- def OnSettings(self, event):
- """Show settings dialog"""
- if self.digit is None:
- try:
- self.digit = self.MapWindow.digit = self.digitClass(mapwindow = self.MapWindow)
- except SystemExit:
- self.digit = self.MapWindow.digit = None
-
- if not self.settingsDialog:
- self.settingsDialog = VDigitSettingsDialog(parent = self.parent, giface = self._giface)
- self.settingsDialog.Show()
- def OnHelp(self, event):
- """Show digitizer help page in web browser"""
- self._giface.Help('wxGUI.vdigit')
-
- def OnAdditionalToolMenu(self, event):
- """Menu for additional tools"""
- point = wx.GetMousePosition()
- toolMenu = wx.Menu()
-
- for label, itype, handler, desc in (
- (_('Break selected lines/boundaries at intersection'),
- wx.ITEM_CHECK, self.OnBreak, "breakLine"),
- (_('Connect selected lines/boundaries'),
- wx.ITEM_CHECK, self.OnConnect, "connectLine"),
- (_('Copy categories'),
- wx.ITEM_CHECK, self.OnCopyCats, "copyCats"),
- (_('Copy features from (background) vector map'),
- wx.ITEM_CHECK, self.OnCopy, "copyLine"),
- (_('Copy attributes'),
- wx.ITEM_CHECK, self.OnCopyAttrb, "copyAttrs"),
- (_('Feature type conversion'),
- wx.ITEM_CHECK, self.OnTypeConversion, "typeConv"),
- (_('Flip selected lines/boundaries'),
- wx.ITEM_CHECK, self.OnFlip, "flipLine"),
- (_('Merge selected lines/boundaries'),
- wx.ITEM_CHECK, self.OnMerge, "mergeLine"),
- (_('Snap selected lines/boundaries (only to nodes)'),
- wx.ITEM_CHECK, self.OnSnap, "snapLine"),
- (_('Split line/boundary'),
- wx.ITEM_CHECK, self.OnSplitLine, "splitLine"),
- (_('Query features'),
- wx.ITEM_CHECK, self.OnQuery, "queryLine"),
- (_('Z bulk-labeling of 3D lines'),
- wx.ITEM_CHECK, self.OnZBulk, "zbulkLine")):
- # Add items to the menu
- item = wx.MenuItem(parentMenu = toolMenu, id = wx.ID_ANY,
- text = label,
- kind = itype)
- toolMenu.AppendItem(item)
- self.MapWindow.Bind(wx.EVT_MENU, handler, item)
- if self.action['desc'] == desc:
- item.Check(True)
-
- # Popup the menu. If an item is selected then its handler
- # will be called before PopupMenu returns.
- self.MapWindow.PopupMenu(toolMenu)
- toolMenu.Destroy()
-
- if self.action['desc'] == 'addPoint':
- self.ToggleTool(self.additionalTools, False)
-
- def OnCopy(self, event):
- """Copy selected features from (background) vector map"""
- if not self.digit:
- GError(_("No vector map open for editing."), self.parent)
- return
-
- # select background map
- dlg = VectorDialog(self.parent, title = _("Select background vector map"),
- layerTree = self._giface.GetLayerTree())
- if dlg.ShowModal() != wx.ID_OK:
- dlg.Destroy()
- return
-
- mapName = dlg.GetName(full=True)
- dlg.Destroy()
-
- # close open background map if any
- bgMap = UserSettings.Get(group = 'vdigit', key = 'bgmap', subkey = 'value',
- settings_type='internal')
- if bgMap:
- self.digit.CloseBackgroundMap()
- self.editingBgMap.emit(mapName = bgMap, unset=True)
- # open background map for reading
- UserSettings.Set(group = 'vdigit', key = 'bgmap', subkey = 'value',
- value=str(mapName), settings_type='internal')
- self.digit.OpenBackgroundMap(mapName)
- self.editingBgMap.emit(mapName = mapName)
- if self.action['desc'] == 'copyLine': # select previous action
- self.ToggleTool(self.addPoint, True)
- self.ToggleTool(self.additionalTools, False)
- self.OnAddPoint(event)
- return
-
- Debug.msg(2, "Digittoolbar.OnCopy():")
- self.action = { 'desc' : "copyLine",
- 'id' : self.additionalTools }
- self.MapWindow.mouse['box'] = 'box'
- def OnSplitLine(self, event):
- """Split line"""
- if self.action['desc'] == 'splitLine': # select previous action
- self.ToggleTool(self.addPoint, True)
- self.ToggleTool(self.additionalTools, False)
- self.OnAddPoint(event)
- return
-
- Debug.msg(2, "Digittoolbar.OnSplitLine():")
- self.action = { 'desc' : "splitLine",
- 'id' : self.additionalTools }
- self.MapWindow.mouse['box'] = 'point'
- def OnCopyCats(self, event):
- """Copy categories"""
- if self.action['desc'] == 'copyCats': # select previous action
- self.ToggleTool(self.addPoint, True)
- self.ToggleTool(self.copyCats, False)
- self.OnAddPoint(event)
- return
-
- Debug.msg(2, "Digittoolbar.OnCopyCats():")
- self.action = { 'desc' : "copyCats",
- 'id' : self.additionalTools }
- self.MapWindow.mouse['box'] = 'point'
- def OnCopyAttrb(self, event):
- """Copy attributes"""
- if self.action['desc'] == 'copyAttrs': # select previous action
- self.ToggleTool(self.addPoint, True)
- self.ToggleTool(self.copyCats, False)
- self.OnAddPoint(event)
- return
-
- Debug.msg(2, "Digittoolbar.OnCopyAttrb():")
- self.action = { 'desc' : "copyAttrs",
- 'id' : self.additionalTools }
- self.MapWindow.mouse['box'] = 'point'
-
- def OnFlip(self, event):
- """Flip selected lines/boundaries"""
- if self.action['desc'] == 'flipLine': # select previous action
- self.ToggleTool(self.addPoint, True)
- self.ToggleTool(self.additionalTools, False)
- self.OnAddPoint(event)
- return
-
- Debug.msg(2, "Digittoolbar.OnFlip():")
- self.action = { 'desc' : "flipLine",
- 'id' : self.additionalTools }
- self.MapWindow.mouse['box'] = 'box'
- def OnMerge(self, event):
- """Merge selected lines/boundaries"""
- if self.action['desc'] == 'mergeLine': # select previous action
- self.ToggleTool(self.addPoint, True)
- self.ToggleTool(self.additionalTools, False)
- self.OnAddPoint(event)
- return
-
- Debug.msg(2, "Digittoolbar.OnMerge():")
- self.action = { 'desc' : "mergeLine",
- 'id' : self.additionalTools }
- self.MapWindow.mouse['box'] = 'box'
- def OnBreak(self, event):
- """Break selected lines/boundaries"""
- if self.action['desc'] == 'breakLine': # select previous action
- self.ToggleTool(self.addPoint, True)
- self.ToggleTool(self.additionalTools, False)
- self.OnAddPoint(event)
- return
-
- Debug.msg(2, "Digittoolbar.OnBreak():")
- self.action = { 'desc' : "breakLine",
- 'id' : self.additionalTools }
- self.MapWindow.mouse['box'] = 'box'
- def OnSnap(self, event):
- """Snap selected features"""
- if self.action['desc'] == 'snapLine': # select previous action
- self.ToggleTool(self.addPoint, True)
- self.ToggleTool(self.additionalTools, False)
- self.OnAddPoint(event)
- return
-
- Debug.msg(2, "Digittoolbar.OnSnap():")
- self.action = { 'desc' : "snapLine",
- 'id' : self.additionalTools }
- self.MapWindow.mouse['box'] = 'box'
- def OnConnect(self, event):
- """Connect selected lines/boundaries"""
- if self.action['desc'] == 'connectLine': # select previous action
- self.ToggleTool(self.addPoint, True)
- self.ToggleTool(self.additionalTools, False)
- self.OnAddPoint(event)
- return
-
- Debug.msg(2, "Digittoolbar.OnConnect():")
- self.action = { 'desc' : "connectLine",
- 'id' : self.additionalTools }
- self.MapWindow.mouse['box'] = 'box'
- def OnQuery(self, event):
- """Query selected lines/boundaries"""
- if self.action['desc'] == 'queryLine': # select previous action
- self.ToggleTool(self.addPoint, True)
- self.ToggleTool(self.additionalTools, False)
- self.OnAddPoint(event)
- return
-
- Debug.msg(2, "Digittoolbar.OnQuery(): %s" % \
- UserSettings.Get(group = 'vdigit', key = 'query', subkey = 'selection'))
- self.action = { 'desc' : "queryLine",
- 'id' : self.additionalTools }
- self.MapWindow.mouse['box'] = 'box'
- def OnZBulk(self, event):
- """Z bulk-labeling selected lines/boundaries"""
- if not self.digit.IsVector3D():
- GError(parent = self.parent,
- message = _("Vector map is not 3D. Operation canceled."))
- return
-
- if self.action['desc'] == 'zbulkLine': # select previous action
- self.ToggleTool(self.addPoint, True)
- self.ToggleTool(self.additionalTools, False)
- self.OnAddPoint(event)
- return
-
- Debug.msg(2, "Digittoolbar.OnZBulk():")
- self.action = { 'desc' : "zbulkLine",
- 'id' : self.additionalTools }
- self.MapWindow.mouse['box'] = 'line'
- def OnTypeConversion(self, event):
- """Feature type conversion
- Supported conversions:
- - point <-> centroid
- - line <-> boundary
- """
- if self.action['desc'] == 'typeConv': # select previous action
- self.ToggleTool(self.addPoint, True)
- self.ToggleTool(self.additionalTools, False)
- self.OnAddPoint(event)
- return
-
- Debug.msg(2, "Digittoolbar.OnTypeConversion():")
- self.action = { 'desc' : "typeConv",
- 'id' : self.additionalTools }
- self.MapWindow.mouse['box'] = 'box'
- def OnSelectMap (self, event):
- """Select vector map layer for editing
- If there is a vector map layer already edited, this action is
- firstly terminated. The map layer is closed. After this the
- selected map layer activated for editing.
- """
- if event.GetSelection() == 0: # create new vector map layer
- if self.mapLayer:
- openVectorMap = self.mapLayer.GetName(fullyQualified = False)['name']
- else:
- openVectorMap = None
- dlg = CreateNewVector(self.parent,
- exceptMap=openVectorMap, giface=self._giface,
- cmd=(('v.edit',
- {'tool': 'create'},
- 'map')),
- disableAdd = True)
-
- if dlg and dlg.GetName():
- # add layer to map layer tree
- if self._giface.GetLayerTree():
- mapName = dlg.GetName() + '@' + grass.gisenv()['MAPSET']
- self._giface.GetLayerList().AddLayer(ltype='vector',
- name=mapName,
- cmd=['d.vect', 'map=%s' % mapName])
-
- vectLayers = self.UpdateListOfLayers(updateTool = True)
- selection = vectLayers.index(mapName)
-
- # create table ?
- if dlg.IsChecked('table'):
- # TODO: replace this by signal
- # also note that starting of tools such as atm, iclass,
- # plots etc. should be handled in some better way
- # than starting randomly from mapdisp and lmgr
- lmgr = self.parent.GetLayerManager()
- if lmgr:
- lmgr.OnShowAttributeTable(None, selection = 'table')
- dlg.Destroy()
- else:
- self.combo.SetValue(_('Select vector map'))
- if dlg:
- dlg.Destroy()
- return
- else:
- selection = event.GetSelection() - 1 # first option is 'New vector map'
-
- # skip currently selected map
- if self.layers[selection] == self.mapLayer:
- return
-
- if self.mapLayer:
- # deactive map layer for editing
- self.StopEditing()
-
- # select the given map layer for editing
- self.StartEditing(self.layers[selection])
-
- event.Skip()
-
- def StartEditing(self, mapLayer):
- """Start editing selected vector map layer.
- :param mapLayer: MapLayer to be edited
- """
- # check if topology is available (skip for hidden - temporary
- # maps, see iclass for details)
- if not mapLayer.IsHidden() and grass.vector_info(mapLayer.GetName())['level'] != 2:
- dlg = wx.MessageDialog(parent = self.MapWindow,
- message = _("Topology for vector map <%s> is not available. "
- "Topology is required by digitizer.\nDo you want to "
- "rebuild topology (takes some time) and open the vector map "
- "for editing?") % mapLayer.GetName(),
- caption=_("Digitizer error"),
- style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION | wx.CENTRE)
- if dlg.ShowModal() == wx.ID_YES:
- RunCommand('v.build', map=mapLayer.GetName())
- else:
- return
-
- # deactive layer
- self.Map.ChangeLayerActive(mapLayer, False)
-
- # clean map canvas
- self.MapWindow.EraseMap()
-
- # unset background map if needed
- if mapLayer:
- if UserSettings.Get(group = 'vdigit', key = 'bgmap',
- subkey = 'value', settings_type='internal') == mapLayer.GetName():
- UserSettings.Set(group = 'vdigit', key = 'bgmap',
- subkey='value', value='', settings_type='internal')
-
- self.parent.SetStatusText(_("Please wait, "
- "opening vector map <%s> for editing...") % mapLayer.GetName(),
- 0)
-
- self.MapWindow.pdcVector = wx.PseudoDC()
- self.digit = self.MapWindow.digit = self.digitClass(mapwindow = self.MapWindow)
-
- self.mapLayer = mapLayer
- # open vector map (assume that 'hidden' map layer is temporary vector map)
- if self.digit.OpenMap(mapLayer.GetName(), tmp = mapLayer.IsHidden()) is None:
- self.mapLayer = None
- self.StopEditing()
- return False
-
- # check feature type (only for OGR layers)
- self.fType = self.digit.GetFeatureType()
- self.EnableAll()
- self.EnableUndo(False)
- self.EnableRedo(False)
-
- if self.fType == 'point':
- for tool in (self.addLine, self.addArea, self.moveVertex, self.addVertex,
- self.removeVertex, self.editLine):
- self.EnableTool(tool, False)
- elif self.fType == 'linestring':
- for tool in (self.addPoint, self.addArea):
- self.EnableTool(tool, False)
- elif self.fType == 'polygon':
- for tool in (self.addPoint, self.addLine):
- self.EnableTool(tool, False)
- elif self.fType:
- GError(parent = self,
- message = _("Unsupported feature type '%(type)s'. Unable to edit "
- "OGR layer <%(layer)s>.") % { 'type' : self.fType,
- 'layer' : mapLayer.GetName() })
- self.digit.CloseMap()
- self.mapLayer = None
- self.StopEditing()
- return False
-
- # update toolbar
- if self.combo:
- self.combo.SetValue(mapLayer.GetName())
- if 'map' in self.parent.toolbars:
- self.parent.toolbars['map'].combo.SetValue (_('Vector digitizer'))
-
- # here was dead code to enable vdigit button in toolbar
- # with if to ignore iclass
- # some signal (DigitizerStarted) can be emitted here
-
- Debug.msg (4, "VDigitToolbar.StartEditing(): layer=%s" % mapLayer.GetName())
-
- # change cursor
- if self.MapWindow.mouse['use'] == 'pointer':
- self.MapWindow.SetNamedCursor('cross')
-
- if not self.MapWindow.resize:
- self.MapWindow.UpdateMap(render = True)
-
- # respect opacity
- opacity = mapLayer.GetOpacity()
-
- if opacity < 1.0:
- alpha = int(opacity * 255)
- self.digit.GetDisplay().UpdateSettings(alpha = alpha)
- # emit signal
- layerTree = self._giface.GetLayerTree()
- if layerTree:
- item = layerTree.FindItemByData('maplayer', self.mapLayer)
- else:
- item = None
- self.editingStarted.emit(vectMap = mapLayer.GetName(), digit = self.digit, layerItem = item)
- return True
- def StopEditing(self):
- """Stop editing of selected vector map layer.
- :return: True on success
- :return: False on failure
- """
- item = None
-
- if self.combo:
- self.combo.SetValue (_('Select vector map'))
-
- # save changes
- if self.mapLayer:
- Debug.msg (4, "VDigitToolbar.StopEditing(): layer=%s" % self.mapLayer.GetName())
- if UserSettings.Get(group = 'vdigit', key = 'saveOnExit', subkey = 'enabled') is False:
- if self.digit.GetUndoLevel() > -1:
- dlg = wx.MessageDialog(parent = self.parent,
- message = _("Do you want to save changes "
- "in vector map <%s>?") % self.mapLayer.GetName(),
- caption = _("Save changes?"),
- style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
- if dlg.ShowModal() == wx.ID_NO:
- # revert changes
- self.digit.Undo(0)
- dlg.Destroy()
-
- self.parent.SetStatusText(_("Please wait, "
- "closing and rebuilding topology of "
- "vector map <%s>...") % self.mapLayer.GetName(),
- 0)
- self.digit.CloseMap()
- # close open background map if any
- bgMap = UserSettings.Get(group = 'vdigit', key = 'bgmap', subkey = 'value',
- settings_type='internal')
- if bgMap:
- self.digit.CloseBackgroundMap()
- self.editingBgMap.emit(mapName = bgMap, unset=True)
-
- self._giface.GetProgress().SetValue(0)
- self._giface.WriteCmdLog(_("Editing of vector map <%s> successfully finished") % \
- self.mapLayer.GetName(),
- notification=Notification.HIGHLIGHT)
- # re-active layer
- layerTree = self._giface.GetLayerTree()
- if layerTree:
- item = layerTree.FindItemByData('maplayer', self.mapLayer)
- if item and layerTree.IsItemChecked(item):
- self.Map.ChangeLayerActive(self.mapLayer, True)
-
- # change cursor
- self.MapWindow.SetNamedCursor('default')
- self.MapWindow.pdcVector = None
-
- # close dialogs
- for dialog in ('attributes', 'category'):
- if self.parent.dialogs[dialog]:
- self.parent.dialogs[dialog].Close()
- self.parent.dialogs[dialog] = None
-
- del self.digit
- del self.MapWindow.digit
- self.editingStopped.emit(layerItem = item)
-
- self.mapLayer = None
-
- self.MapWindow.redrawAll = True
- return True
-
- def UpdateListOfLayers (self, updateTool = False):
- """Update list of available vector map layers.
- This list consists only editable layers (in the current mapset)
- :param updateTool: True to update also toolbar
- :type updateTool: bool
- """
- Debug.msg (4, "VDigitToolbar.UpdateListOfLayers(): updateTool=%d" % \
- updateTool)
-
- layerNameSelected = None
- # name of currently selected layer
- if self.mapLayer:
- layerNameSelected = self.mapLayer.GetName()
-
- # select vector map layer in the current mapset
- layerNameList = []
- self.layers = self.Map.GetListOfLayers(ltype = "vector",
- mapset = grass.gisenv()['MAPSET'])
-
- for layer in self.layers:
- if not layer.name in layerNameList: # do not duplicate layer
- layerNameList.append (layer.GetName())
-
- if updateTool: # update toolbar
- if not self.mapLayer:
- value = _('Select vector map')
- else:
- value = layerNameSelected
-
- if not self.comboid:
- if not self.tools or 'selector' in self.tools:
- self.combo = wx.ComboBox(self, id = wx.ID_ANY, value = value,
- choices = [_('New vector map'), ] + layerNameList, size = (80, -1),
- style = wx.CB_READONLY)
- self.comboid = self.InsertControl(0, self.combo)
- self.parent.Bind(wx.EVT_COMBOBOX, self.OnSelectMap, self.comboid)
- else:
- self.combo.SetItems([_('New vector map'), ] + layerNameList)
-
- self.Realize()
-
- return layerNameList
- def GetLayer(self):
- """Get selected layer for editing -- MapLayer instance"""
- return self.mapLayer
|