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 OnSettings(self, event): """!Show settings dialog""" if self.digit is None: try: self.digit = self.parent.MapWindow.digit = VDigit( mapwindow=self.parent.MapWindow) except SystemExit: self.digit = self.parent.MapWindow.digit = None if not self.settingsDialog: self.settingsDialog = VDigitSettingsDialog( parent=self.parent, title=_("Digitization settings"), style=wx.DEFAULT_DIALOG_STYLE) self.settingsDialog.Show()
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") self.quitDigitizer = Signal("VDigitToolbar.quitDigitizer") layerTree = self._giface.GetLayerTree() if layerTree: self.editingStarted.connect(layerTree.StartEditing) self.editingStopped.connect(layerTree.StopEditing) self.editingBgMap.connect(layerTree.SetBgMapForEditing) # bind events self.Bind(wx.EVT_SHOW, self.OnShow) # 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 = [] self.quitDigitizer.emit() 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""" if self.digit: self.digit.Undo() event.Skip() def OnRedo(self, event): """Undo previous changes""" if self.digit: 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 = 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/map display mapName = dlg.GetName() + "@" + grass.gisenv()["MAPSET"] self._giface.GetLayerList().AddLayer( ltype="vector", name=mapName, checked=True, 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 = 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 self.digit = None self.MapWindow.digit = None 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 layer.name not 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 def OnShow(self, event): """Show frame event""" if event.IsShown(): # list of available vector maps self.UpdateListOfLayers(updateTool=True)
class VDigitToolbar(BaseToolbar): """!Toolbar for digitization """ def __init__(self, parent, mapcontent, layerTree=None, log=None): self.mapcontent = mapcontent # Map class instance self.layerTree = layerTree # reference to layer tree associated to map display self.log = log # log area BaseToolbar.__init__(self, parent) self.digit = None # 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 = None # only one dialog can be open self.settingsDialog = None # create toolbars (two rows optionally) self.InitToolbar(self._toolbarData()) self.Bind(wx.EVT_TOOL, self.OnTool) # default action (digitize new point, line, etc.) self.action = {'desc': '', 'type': '', 'id': -1} # list of available vector maps self.UpdateListOfLayers(updateTool=True) # realize toolbar self.Realize() # workaround for Mac bug. May be fixed by 2.8.8, but not before then. self.combo.Hide() self.combo.Show() # disable undo/redo self.EnableTool(self.undo, False) ### hide undo - this tool is quite buggy in GRASS 6 self.RemoveTool(self.undo) # toogle to pointer by default self.OnTool(None) self.FixSize(width=105) def _toolbarData(self): """!Toolbar data """ data = [] 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 (composition of boundaries without category and one centroid with category)' ), desc=_('Left: new point')), 'addVertex': MetaIcon( img='vertex-create', label=_('Add new vertex'), desc=_('Left: Select; Ctrl+Left: Unselect; Right: Confirm')), 'deleteLine': MetaIcon( img='line-delete', label=_('Delete feature(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 line/boundary'), desc= _('Left: new point; Ctrl+Left: undo last point; Right: close line' )), 'moveLine': MetaIcon( img='line-move', label=_('Move feature(s)'), desc=_('Left: Select; Ctrl+Left: Unselect; Right: Confirm')), 'moveVertex': MetaIcon( img='vertex-move', label=_('Move vertex'), desc=_('Left: Select; Ctrl+Left: Unselect; Right: Confirm')), 'removeVertex': MetaIcon( img='vertex-delete', label=_('Remove 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')), } return self._getToolbarData( ((None, ), ("addPoint", icons["addPoint"], self.OnAddPoint, wx.ITEM_CHECK), ("addLine", icons["addLine"], self.OnAddLine, wx.ITEM_CHECK), ("addBoundary", icons["addBoundary"], self.OnAddBoundary, wx.ITEM_CHECK), ("addCentroid", icons["addCentroid"], self.OnAddCentroid, wx.ITEM_CHECK), ("addArea", icons["addArea"], self.OnAddArea, wx.ITEM_CHECK), ("moveVertex", icons["moveVertex"], self.OnMoveVertex, wx.ITEM_CHECK), ("addVertex", icons["addVertex"], self.OnAddVertex, wx.ITEM_CHECK), ("removeVertex", icons["removeVertex"], self.OnRemoveVertex, wx.ITEM_CHECK), ("editLine", icons["editLine"], self.OnEditLine, wx.ITEM_CHECK), ("moveLine", icons["moveLine"], self.OnMoveLine, wx.ITEM_CHECK), ("deleteLine", icons["deleteLine"], self.OnDeleteLine, wx.ITEM_CHECK), ("displayCats", icons["displayCats"], self.OnDisplayCats, wx.ITEM_CHECK), ("displayAttr", icons["displayAttr"], self.OnDisplayAttr, wx.ITEM_CHECK), ("additionalTools", icons["additionalTools"], self.OnAdditionalToolMenu, wx.ITEM_CHECK), (None, ), ("undo", icons["undo"], self.OnUndo), ("settings", icons["settings"], self.OnSettings), ("help", icons["help"], self.OnHelp), ("quit", icons["quit"], self.OnExit))) def OnTool(self, event): """!Tool selected -> disable selected tool in map toolbar""" aId = self.parent.toolbars['map'].GetAction(type='id') self.parent.toolbars['map'].ToggleTool(aId, False) # set cursor cursor = self.parent.cursors["cross"] self.parent.MapWindow.SetCursor(cursor) # pointer self.parent.OnPointer(None) if event: # deselect previously selected tool aId = self.action.get('id', -1) if aId != event.GetId() and \ self.action['id'] != -1: self.ToggleTool(self.action['id'], False) else: self.ToggleTool(self.action['id'], True) self.action['id'] = event.GetId() event.Skip() if self.action['id'] != -1: self.ToggleTool(self.action['id'], True) # clear tmp canvas if self.action['id'] != aId: self.parent.MapWindow.ClearLines(pdc=self.parent.MapWindow.pdcTmp) if self.digit and \ len(self.parent.MapWindow.digit.GetDisplay().GetSelected()) > 0: # cancel action self.parent.MapWindow.OnMiddleDown(None) # set focus self.parent.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.parent.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.parent.MapWindow.mouse['box'] = 'line' ### self.parent.MapWindow.polycoords = [] # reset temp line def OnAddBoundary(self, event): """!Add boundary to the vector map layer""" Debug.msg(2, "VDigitToolbar.OnAddBoundary()") if self.action['desc'] != 'addLine' or \ self.action['type'] != 'boundary': self.parent.MapWindow.polycoords = [] # reset temp line self.action = { 'desc': "addLine", 'type': "boundary", 'id': self.addBoundary } self.parent.MapWindow.mouse['box'] = 'line' def OnAddCentroid(self, event): """!Add centroid to the vector map layer""" Debug.msg(2, "VDigitToolbar.OnAddCentroid()") self.action = { 'desc': "addLine", 'type': "centroid", 'id': self.addCentroid } self.parent.MapWindow.mouse['box'] = 'point' def OnAddArea(self, event): """!Add area to the vector map layer""" Debug.msg(2, "VDigitToolbar.OnAddCentroid()") self.action = {'desc': "addLine", 'type': "area", 'id': self.addArea} self.parent.MapWindow.mouse['box'] = 'line' def OnExit(self, event=None): """!Quit digitization tool""" # stop editing of the currently selected map layer if self.mapLayer: self.StopEditing() # close dialogs if still open if self.settingsDialog: self.settingsDialog.OnCancel(None) # set default mouse settings self.parent.MapWindow.mouse['use'] = "pointer" self.parent.MapWindow.mouse['box'] = "point" self.parent.MapWindow.polycoords = [] # disable the toolbar self.parent.RemoveToolbar("vdigit") def OnMoveVertex(self, event): """!Move line vertex""" Debug.msg(2, "Digittoolbar.OnMoveVertex():") self.action = {'desc': "moveVertex", 'id': self.moveVertex} self.parent.MapWindow.mouse['box'] = 'point' def OnAddVertex(self, event): """!Add line vertex""" Debug.msg(2, "Digittoolbar.OnAddVertex():") self.action = {'desc': "addVertex", 'id': self.addVertex} self.parent.MapWindow.mouse['box'] = 'point' def OnRemoveVertex(self, event): """!Remove line vertex""" Debug.msg(2, "Digittoolbar.OnRemoveVertex():") self.action = {'desc': "removeVertex", 'id': self.removeVertex} self.parent.MapWindow.mouse['box'] = 'point' def OnEditLine(self, event): """!Edit line""" Debug.msg(2, "Digittoolbar.OnEditLine():") self.action = {'desc': "editLine", 'id': self.editLine} self.parent.MapWindow.mouse['box'] = 'line' def OnMoveLine(self, event): """!Move line""" Debug.msg(2, "Digittoolbar.OnMoveLine():") self.action = {'desc': "moveLine", 'id': self.moveLine} self.parent.MapWindow.mouse['box'] = 'box' def OnDeleteLine(self, event): """!Delete line""" Debug.msg(2, "Digittoolbar.OnDeleteLine():") self.action = {'desc': "deleteLine", 'id': self.deleteLine} self.parent.MapWindow.mouse['box'] = 'box' def OnDisplayCats(self, event): """!Display/update categories""" Debug.msg(2, "Digittoolbar.OnDisplayCats():") self.action = {'desc': "displayCats", 'id': self.displayCats} self.parent.MapWindow.mouse['box'] = 'point' def OnDisplayAttr(self, event): """!Display/update attributes""" Debug.msg(2, "Digittoolbar.OnDisplayAttr():") self.action = {'desc': "displayAttrs", 'id': self.displayAttr} self.parent.MapWindow.mouse['box'] = 'point' def OnUndo(self, event): """!Undo previous changes""" self.digit.Undo() event.Skip() def EnableUndo(self, enable=True): """!Enable 'Undo' in toolbar @param enable False for disable """ if not self.FindById(self.undo): return if enable: if self.GetToolEnabled(self.undo) is False: self.EnableTool(self.undo, True) else: if self.GetToolEnabled(self.undo) is True: self.EnableTool(self.undo, False) def OnSettings(self, event): """!Show settings dialog""" if self.digit is None: try: self.digit = self.parent.MapWindow.digit = VDigit( mapwindow=self.parent.MapWindow) except SystemExit: self.digit = self.parent.MapWindow.digit = None if not self.settingsDialog: self.settingsDialog = VDigitSettingsDialog( parent=self.parent, title=_("Digitization settings"), style=wx.DEFAULT_DIALOG_STYLE) self.settingsDialog.Show() def OnHelp(self, event): """!Show digitizer help page in web browser""" log = self.parent.GetLayerManager().GetLogWindow() log.RunCmd(['g.manual', 'entry=wxGUI.Vector_Digitizer']) 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.parent.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.parent.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 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.parent.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.parent.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.parent.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.parent.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.parent.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.parent.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.parent.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.parent.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.parent.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.parent.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.parent.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.parent.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, log=self.log, cmd=(('v.edit', { 'tool': 'create' }, 'map')), disableAdd=True) if dlg and dlg.GetName(): # add layer to map layer tree if self.layerTree: mapName = dlg.GetName() + '@' + grass.gisenv()['MAPSET'] self.layerTree.AddLayer( ltype='vector', lname=mapName, lcmd=['d.vect', 'map=%s' % mapName]) vectLayers = self.UpdateListOfLayers(updateTool=True) selection = vectLayers.index(mapName) # create table ? if dlg.IsChecked('table'): 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 """ # deactive layer self.mapcontent.ChangeLayerActive(mapLayer, False) # clean map canvas self.parent.MapWindow.EraseMap() # unset background map if needed if mapLayer: if UserSettings.Get(group='vdigit', key='bgmap', subkey='value', internal=True) == mapLayer.GetName(): UserSettings.Set(group='vdigit', key='bgmap', subkey='value', value='', internal=True) self.parent.SetStatusText( _("Please wait, " "opening vector map <%s> for editing...") % mapLayer.GetName(), 0) self.parent.MapWindow.pdcVector = wx.PseudoDC() self.digit = self.parent.MapWindow.digit = VDigit( mapwindow=self.parent.MapWindow) self.mapLayer = mapLayer # open vector map if self.digit.OpenMap(mapLayer.GetName()) is None: self.mapLayer = None self.StopEditing() return False # update toolbar self.combo.SetValue(mapLayer.GetName()) self.parent.toolbars['map'].combo.SetValue(_('Digitize')) lmgr = self.parent.GetLayerManager() if lmgr: lmgr.toolbars['tools'].Enable('vdigit', enable=False) Debug.msg( 4, "VDigitToolbar.StartEditing(): layer=%s" % mapLayer.GetName()) # change cursor if self.parent.MapWindow.mouse['use'] == 'pointer': self.parent.MapWindow.SetCursor(self.parent.cursors["cross"]) if not self.parent.MapWindow.resize: self.parent.MapWindow.UpdateMap(render=True) # respect opacity opacity = mapLayer.GetOpacity(float=True) if opacity < 1.0: alpha = int(opacity * 255) self.digit.GetDisplay().UpdateSettings(alpha=alpha) return True def StopEditing(self): """!Stop editing of selected vector map layer. @return True on success @return False on failure """ 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() lmgr = self.parent.GetLayerManager() if lmgr: lmgr.toolbars['tools'].Enable('vdigit', enable=True) lmgr.GetLogWindow().GetProgressBar().SetValue(0) lmgr.GetLogWindow().WriteCmdLog(_("Editing of vector map <%s> successfully finished") % \ self.mapLayer.GetName(), switchPage = False) # re-active layer item = self.parent.tree.FindItemByData('maplayer', self.mapLayer) if item and self.parent.tree.IsItemChecked(item): self.mapcontent.ChangeLayerActive(self.mapLayer, True) # change cursor self.parent.MapWindow.SetCursor(self.parent.cursors["default"]) self.parent.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.parent.MapWindow.digit self.mapLayer = None self.parent.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 """ 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.mapcontent.GetListOfLayers( l_type="vector", l_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: 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