GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
lmgr/frame.py
Go to the documentation of this file.
1 """!
2 @package lmgr::frame
3 
4 @brief Layer Manager - main menu, layer management toolbar, notebook
5 control for display management and access to command console.
6 
7 Classes:
8  - frame::GMFrame
9 
10 (C) 2006-2014 by the GRASS Development Team
11 
12 This program is free software under the GNU General Public License
13 (>=v2). Read the file COPYING that comes with GRASS for details.
14 
15 @author Michael Barton (Arizona State University)
16 @author Jachym Cepicky (Mendel University of Agriculture)
17 @author Martin Landa <landa.martin gmail.com>
18 @author Vaclav Petras <wenzeslaus gmail.com> (menu customization)
19 """
20 
21 import sys
22 import os
23 import tempfile
24 import stat
25 import platform
26 try:
27  import xml.etree.ElementTree as etree
28 except ImportError:
29  import elementtree.ElementTree as etree # Python <= 2.4
30 
31 from core import globalvar
32 import wx
33 import wx.aui
34 try:
35  import wx.lib.agw.flatnotebook as FN
36 except ImportError:
37  import wx.lib.flatnotebook as FN
38 
39 sys.path.append(os.path.join(globalvar.ETCDIR, "python"))
40 from grass.script import core as grass
41 
42 from core.gcmd import Command, RunCommand, GError, GMessage
43 from core.settings import UserSettings
44 from core.utils import SetAddOnPath
45 from gui_core.preferences import MapsetAccess, PreferencesDialog, EVT_SETTINGS_CHANGED
46 from lmgr.layertree import LayerTree, LMIcons
47 from lmgr.menudata import ManagerData
48 from gui_core.widgets import GNotebook
49 from modules.mcalc_builder import MapCalcFrame
50 from dbmgr.manager import AttributeManager
51 from core.workspace import ProcessWorkspaceFile, ProcessGrcFile, WriteWorkspaceFile
52 from gui_core.goutput import GMConsole
53 from gui_core.dialogs import DxfImportDialog, GdalImportDialog, MapLayersDialog
54 from gui_core.dialogs import LocationDialog, MapsetDialog, CreateNewVector, GroupDialog
55 from modules.ogc_services import WMSDialog
56 from modules.colorrules import RasterColorTable, VectorColorTable
57 from gui_core.menu import Menu, MenuTreeWindow
58 from gmodeler.model import Model
59 from gmodeler.frame import ModelFrame
60 from psmap.frame import PsMapFrame
61 from core.debug import Debug
62 from gui_core.ghelp import AboutWindow
63 from modules.extensions import InstallExtensionWindow, UninstallExtensionWindow
64 from lmgr.toolbars import LMWorkspaceToolbar, LMDataToolbar, LMToolsToolbar
65 from lmgr.toolbars import LMMiscToolbar, LMVectorToolbar, LMNvizToolbar
66 from lmgr.pyshell import PyShellWindow
67 from gui_core.forms import GUI
68 from gcp.manager import GCPWizard
69 from nviz.main import haveNviz
70 
71 class GMFrame(wx.Frame):
72  """!Layer Manager frame with notebook widget for controlling GRASS
73  GIS. Includes command console page for typing GRASS (and other)
74  commands, tree widget page for managing map layers.
75  """
76  def __init__(self, parent, id = wx.ID_ANY, title = None,
77  workspace = None,
78  size = globalvar.GM_WINDOW_SIZE, style = wx.DEFAULT_FRAME_STYLE, **kwargs):
79  self.parent = parent
80  if title:
81  self.baseTitle = title
82  else:
83  self.baseTitle = _("GRASS GIS %s Layer Manager") % grass.version()['version']
84  self.iconsize = (16, 16)
85 
86  wx.Frame.__init__(self, parent = parent, id = id, size = size,
87  style = style, **kwargs)
88  self.SetTitle(self.baseTitle)
89  self.SetName("LayerManager")
90 
91  self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
92 
93  self._auimgr = wx.aui.AuiManager(self)
94 
95  # initialize variables
96  self.displayIndex = 0 # index value for map displays and layer trees
97  self.currentPage = None # currently selected page for layer tree notebook
98  self.currentPageNum = None # currently selected page number for layer tree notebook
99  self.workspaceFile = workspace # workspace file
100  self.workspaceChanged = False # track changes in workspace
101  self.georectifying = None # reference to GCP class or None
102  self.gcpmanagement = None # reference to GCP class or None
103 
104  # list of open dialogs
105  self.dialogs = dict()
106  self.dialogs['preferences'] = None
107  self.dialogs['atm'] = list()
108 
109  # creating widgets
110  self._createMenuBar()
111  self.statusbar = self.CreateStatusBar(number = 1)
112  self.notebook = self._createNoteBook()
113  self.toolbars = { 'workspace' : LMWorkspaceToolbar(parent = self),
114  'data' : LMDataToolbar(parent = self),
115  'tools' : LMToolsToolbar(parent = self),
116  'misc' : LMMiscToolbar(parent = self),
117  'vector' : LMVectorToolbar(parent = self),
118  'nviz' : LMNvizToolbar(parent = self)}
119 
120  self._toolbarsData = { 'workspace' : ("toolbarWorkspace", # name
121  _("Workspace Toolbar"), # caption
122  1), # row
123  'data' : ("toolbarData",
124  _("Data Toolbar"),
125  1),
126  'misc' : ("toolbarMisc",
127  _("Misc Toolbar"),
128  2),
129  'tools' : ("toolbarTools",
130  _("Tools Toolbar"),
131  2),
132  'vector' : ("toolbarVector",
133  _("Vector Toolbar"),
134  2),
135  'nviz' : ("toolbarNviz",
136  _("3D view Toolbar"),
137  2),
138  }
139  if sys.platform == 'win32':
140  self._toolbarsList = ('workspace', 'data',
141  'vector', 'tools', 'misc', 'nviz')
142  else:
143  self._toolbarsList = ('data', 'workspace',
144  'nviz', 'misc', 'tools', 'vector')
145  for toolbar in self._toolbarsList:
146  name, caption, row = self._toolbarsData[toolbar]
147  self._auimgr.AddPane(self.toolbars[toolbar],
148  wx.aui.AuiPaneInfo().
149  Name(name).Caption(caption).
150  ToolbarPane().Top().Row(row).
151  LeftDockable(False).RightDockable(False).
152  BottomDockable(False).TopDockable(True).
153  CloseButton(False).Layer(2).
154  BestSize((self.toolbars[toolbar].GetBestSize())))
155 
156  self._auimgr.GetPane('toolbarNviz').Hide()
157  # bindings
158  self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
159  self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
160 
161  # minimal frame size
162  self.SetMinSize((globalvar.GM_WINDOW_SIZE[0], 400))
163 
164  # AUI stuff
165  self._auimgr.AddPane(self.notebook, wx.aui.AuiPaneInfo().
166  Left().CentrePane().BestSize((-1,-1)).Dockable(False).
167  CloseButton(False).DestroyOnClose(True).Row(1).Layer(0))
168 
169  self._auimgr.Update()
170 
171  wx.CallAfter(self.notebook.SetSelectionByName, 'layers')
172 
173  # use default window layout ?
174  if UserSettings.Get(group = 'general', key = 'defWindowPos', subkey = 'enabled'):
175  dim = UserSettings.Get(group = 'general', key = 'defWindowPos', subkey = 'dim')
176  try:
177  x, y = map(int, dim.split(',')[0:2])
178  w, h = map(int, dim.split(',')[2:4])
179  self.SetPosition((x, y))
180  self.SetSize((w, h))
181  except:
182  pass
183  else:
184  self.Centre()
185 
186  self.Layout()
187  self.Show()
188 
189  # load workspace file if requested
190  if self.workspaceFile:
191  # load given workspace file
192  if self.LoadWorkspaceFile(self.workspaceFile):
193  self.SetTitle(self.baseTitle + " - " + os.path.basename(self.workspaceFile))
194  else:
195  self.workspaceFile = None
196  else:
197  # start default initial display
198  self.NewDisplay(show = False)
199 
200  # show map display widnow
201  # -> OnSize() -> UpdateMap()
202  for mapdisp in self.GetMapDisplay(onlyCurrent = False):
203  mapdisp.Show()
204 
205  # redirect stderr to log area
206  self.goutput.Redirect()
207 
208  # fix goutput's pane size (required for Mac OSX)`
209  self.goutput.SetSashPosition(int(self.GetSize()[1] * .8))
210 
211  self.workspaceChanged = False
212 
213  # start with layer manager on top
214  if self.currentPage:
215  self.GetMapDisplay().Raise()
216  wx.CallAfter(self.Raise)
217 
218  def _createMenuBar(self):
219  """!Creates menu bar"""
220  self.menubar = Menu(parent = self, data = ManagerData())
221  self.SetMenuBar(self.menubar)
222  self.menucmd = self.menubar.GetCmd()
223 
224  def _createTabMenu(self):
225  """!Creates context menu for display tabs.
226 
227  Used to rename display.
228  """
229  menu = wx.Menu()
230  item = wx.MenuItem(menu, id = wx.ID_ANY, text = _("Rename Map Display"))
231  menu.AppendItem(item)
232  self.Bind(wx.EVT_MENU, self.OnRenameDisplay, item)
233 
234  return menu
235 
236  def _setCopyingOfSelectedText(self):
237  copy = UserSettings.Get(group = 'manager', key = 'copySelectedTextToClipboard', subkey = 'enabled')
238  self.goutput.SetCopyingOfSelectedText(copy)
239 
240  def IsPaneShown(self, name):
241  """!Check if pane (toolbar, ...) of given name is currently shown"""
242  if self._auimgr.GetPane(name).IsOk():
243  return self._auimgr.GetPane(name).IsShown()
244  return False
245 
246  def _createNoteBook(self):
247  """!Creates notebook widgets"""
248  self.notebook = GNotebook(parent = self, style = globalvar.FNPageDStyle)
249  # create displays notebook widget and add it to main notebook page
250  cbStyle = globalvar.FNPageStyle
251  if globalvar.hasAgw:
252  self.notebookLayers = FN.FlatNotebook(self, id = wx.ID_ANY, agwStyle = cbStyle)
253  else:
254  self.notebookLayers = FN.FlatNotebook(self, id = wx.ID_ANY, style = cbStyle)
255  self.notebookLayers.SetTabAreaColour(globalvar.FNPageColor)
256  menu = self._createTabMenu()
257  self.notebookLayers.SetRightClickMenu(menu)
258  self.notebook.AddPage(page = self.notebookLayers, text = _("Map layers"), name = 'layers')
259 
260  # create 'command output' text area
261  self.goutput = GMConsole(self)
262  self.notebook.AddPage(page = self.goutput, text = _("Command console"), name = 'output')
264 
265  # create 'search module' notebook page
266  if not UserSettings.Get(group = 'manager', key = 'hideTabs', subkey = 'search'):
267  self.search = MenuTreeWindow(parent = self)
268  self.notebook.AddPage(page = self.search, text = _("Search module"), name = 'search')
269  else:
270  self.search = None
271 
272  # create 'python shell' notebook page
273  if not UserSettings.Get(group = 'manager', key = 'hideTabs', subkey = 'pyshell'):
274  self.pyshell = PyShellWindow(parent = self)
275  self.notebook.AddPage(page = self.pyshell, text = _("Python shell"), name = 'pyshell')
276  else:
277  self.pyshell = None
278 
279  # bindings
280  self.notebookLayers.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.OnCBPageChanged)
281  self.notebook.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
282  self.notebookLayers.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CLOSING, self.OnCBPageClosed)
283 
284  return self.notebook
285 
286  def AddNvizTools(self):
287  """!Add nviz notebook page"""
288  Debug.msg(5, "GMFrame.AddNvizTools()")
289  if not haveNviz:
290  return
291 
292  from nviz.main import NvizToolWindow
293 
294  # show toolbar
295  self._auimgr.GetPane('toolbarNviz').Show()
296  # reorder other toolbars
297  for pos, toolbar in enumerate(('toolbarVector', 'toolbarTools', 'toolbarMisc','toolbarNviz')):
298  self._auimgr.GetPane(toolbar).Row(2).Position(pos)
299  self._auimgr.Update()
300 
301  # create nviz tools tab
302  self.nviz = NvizToolWindow(parent = self,
303  display = self.GetMapDisplay())
304  idx = self.notebook.GetPageIndexByName('layers')
305  self.notebook.InsertPage(indx = idx + 1, page = self.nviz, text = _("3D view"), name = 'nviz')
306  self.notebook.SetSelectionByName('nviz')
307 
308 
309  def RemoveNvizTools(self):
310  """!Remove nviz notebook page"""
311  # if more mapwindow3D were possible, check here if nb page should be removed
312  self.notebook.SetSelectionByName('layers')
313  self.notebook.DeletePage(self.notebook.GetPageIndexByName('nviz'))
314 
315  # hide toolbar
316  self._auimgr.GetPane('toolbarNviz').Hide()
317  for pos, toolbar in enumerate(('toolbarVector', 'toolbarTools', 'toolbarMisc')):
318  self._auimgr.GetPane(toolbar).Row(2).Position(pos)
319  self._auimgr.Update()
320 
321  def WorkspaceChanged(self):
322  """!Update window title"""
323  if not self.workspaceChanged:
324  self.workspaceChanged = True
325 
326  if self.workspaceFile:
327  self.SetTitle(self.baseTitle + " - " + os.path.basename(self.workspaceFile) + '*')
328 
329  def OnLocationWizard(self, event):
330  """!Launch location wizard"""
331  from location_wizard.wizard import LocationWizard
332  from location_wizard.dialogs import RegionDef
333 
334  gWizard = LocationWizard(parent = self,
335  grassdatabase = grass.gisenv()['GISDBASE'])
336  location = gWizard.location
337 
338  if location != None:
339  dlg = wx.MessageDialog(parent = self,
340  message = _('Location <%s> created.\n\n'
341  'Do you want to switch to the '
342  'new location?') % location,
343  caption=_("Switch to new location?"),
344  style = wx.YES_NO | wx.NO_DEFAULT |
345  wx.ICON_QUESTION | wx.CENTRE)
346 
347  ret = dlg.ShowModal()
348  dlg.Destroy()
349  if ret == wx.ID_YES:
350  if RunCommand('g.mapset', parent = self,
351  location = location,
352  mapset = 'PERMANENT') != 0:
353  return
354 
355  GMessage(parent = self,
356  message = _("Current location is <%(loc)s>.\n"
357  "Current mapset is <%(mapset)s>.") % \
358  { 'loc' : location, 'mapset' : 'PERMANENT' })
359 
360  # code duplication with gis_set.py
361  dlg = wx.MessageDialog(parent = self,
362  message = _("Do you want to set the default "
363  "region extents and resolution now?"),
364  caption = _("Location <%s> created") % location,
365  style = wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
366  dlg.CenterOnScreen()
367  if dlg.ShowModal() == wx.ID_YES:
368  dlg.Destroy()
369  defineRegion = RegionDef(self, location = location)
370  defineRegion.CenterOnScreen()
371  defineRegion.ShowModal()
372  defineRegion.Destroy()
373  else:
374  dlg.Destroy()
375 
376  def OnSettingsChanged(self, event):
377  """!Here can be functions which have to be called after EVT_SETTINGS_CHANGED.
378  Now only set copying of selected text to clipboard (in goutput).
379  """
380  ### self._createMenuBar() # bug when menu is re-created on the fly
382 
383  def OnGCPManager(self, event):
384  """!Launch georectifier module
385  """
386  GCPWizard(self)
387 
388  def OnGModeler(self, event):
389  """!Launch Graphical Modeler"""
390  win = ModelFrame(parent = self)
391  win.CentreOnScreen()
392 
393  win.Show()
394 
395  def OnPsMap(self, event):
396  """!Launch Cartographic Composer
397  """
398  win = PsMapFrame(parent = self)
399  win.CentreOnScreen()
400 
401  win.Show()
402 
403  def OnDone(self, cmd, returncode):
404  """Command execution finished"""
405  if hasattr(self, "model"):
406  self.model.DeleteIntermediateData(log = self.goutput)
407  del self.model
408  self.SetStatusText('')
409 
410  def OnRunModel(self, event):
411  """!Run model"""
412  filename = ''
413  dlg = wx.FileDialog(parent = self, message =_("Choose model to run"),
414  defaultDir = os.getcwd(),
415  wildcard = _("GRASS Model File (*.gxm)|*.gxm"))
416  if dlg.ShowModal() == wx.ID_OK:
417  filename = dlg.GetPath()
418 
419  if not filename:
420  dlg.Destroy()
421  return
422 
423  self.model = Model()
424  self.model.LoadModel(filename)
425  self.model.Run(log = self.goutput, onDone = self.OnDone, parent = self)
426 
427  dlg.Destroy()
428 
429  def OnMapsets(self, event):
430  """!Launch mapset access dialog
431  """
432  dlg = MapsetAccess(parent = self, id = wx.ID_ANY)
433  dlg.CenterOnScreen()
434 
435  if dlg.ShowModal() == wx.ID_OK:
436  ms = dlg.GetMapsets()
437  RunCommand('g.mapsets',
438  parent = self,
439  mapset = '%s' % ','.join(ms))
440 
441  def OnCBPageChanged(self, event):
442  """!Page in notebook (display) changed"""
443  self.currentPage = self.notebookLayers.GetCurrentPage()
444  self.currentPageNum = self.notebookLayers.GetSelection()
445  try:
446  self.GetMapDisplay().SetFocus()
447  self.GetMapDisplay().Raise()
448  except:
449  pass
450 
451  event.Skip()
452 
453  def OnPageChanged(self, event):
454  """!Page in notebook changed"""
455  page = event.GetSelection()
456  if page == self.notebook.GetPageIndexByName('output'):
457  # remove '(...)'
458  self.notebook.SetPageText(page, _("Command console"))
459  wx.CallAfter(self.goutput.ResetFocus)
460  self.SetStatusText('', 0)
461 
462  event.Skip()
463 
464  def OnCBPageClosed(self, event):
465  """!Page of notebook closed
466  Also close associated map display
467  """
468  if UserSettings.Get(group = 'manager', key = 'askOnQuit', subkey = 'enabled'):
469  maptree = self.GetLayerTree()
470 
471  if self.workspaceFile:
472  message = _("Do you want to save changes in the workspace?")
473  else:
474  message = _("Do you want to store current settings "
475  "to workspace file?")
476 
477  # ask user to save current settings
478  if maptree.GetCount() > 0:
479  name = self.notebookLayers.GetPageText(self.currentPageNum)
480  dlg = wx.MessageDialog(self,
481  message = message,
482  caption = _("Close Map Display %s") % name,
483  style = wx.YES_NO | wx.YES_DEFAULT |
484  wx.CANCEL | wx.ICON_QUESTION | wx.CENTRE)
485  ret = dlg.ShowModal()
486  if ret == wx.ID_YES:
487  if not self.workspaceFile:
488  self.OnWorkspaceSaveAs()
489  else:
491  elif ret == wx.ID_CANCEL:
492  event.Veto()
493  dlg.Destroy()
494  return
495  dlg.Destroy()
496 
497  self.notebookLayers.GetPage(event.GetSelection()).maptree.Map.Clean()
498  self.notebookLayers.GetPage(event.GetSelection()).maptree.Close(True)
499 
500  self.currentPage = None
501 
502  event.Skip()
503 
504  def GetLayerNotebook(self):
505  """!Get Layers Notebook"""
506  return self.notebookLayers
507 
508  def GetLayerTree(self):
509  """!Get current layer tree
510 
511  @return LayerTree instance
512  @return None no layer tree selected
513  """
514  if self.currentPage:
515  return self.currentPage.maptree
516  return None
517 
518  def GetMapDisplay(self, onlyCurrent = True):
519  """!Get current map display
520 
521  @param onlyCurrent True to return only active mapdisplay
522  False for list of all mapdisplays
523 
524  @return MapFrame instance (or list)
525  @return None no mapdisplay selected
526  """
527  if onlyCurrent:
528  if self.currentPage:
529  return self.GetLayerTree().GetMapDisplay()
530  else:
531  return None
532  else: # -> return list of all mapdisplays
533  mlist = list()
534  for idx in range(0, self.notebookLayers.GetPageCount()):
535  mlist.append(self.notebookLayers.GetPage(idx).maptree.GetMapDisplay())
536 
537  return mlist
538 
539  return None
540 
541  def GetLogWindow(self):
542  """!Get widget for command output"""
543  return self.goutput
544 
545  def GetMenuCmd(self, event):
546  """!Get GRASS command from menu item
547 
548  Return command as a list"""
549  layer = None
550 
551  if event:
552  cmd = self.menucmd[event.GetId()]
553  else:
554  cmd = ''
555 
556  try:
557  cmdlist = cmd.split(' ')
558  except: # already list?
559  cmdlist = cmd
560 
561  # check list of dummy commands for GUI modules that do not have GRASS
562  # bin modules or scripts.
563  if cmd in ['vcolors', 'r.mapcalc', 'r3.mapcalc']:
564  return cmdlist
565 
566  try:
567  layer = self.GetLayerTree().layer_selected
568  name = self.GetLayerTree().GetPyData(layer)[0]['maplayer'].name
569  type = self.GetLayerTree().GetPyData(layer)[0]['type']
570  except:
571  layer = None
572 
573  if layer and len(cmdlist) == 1: # only if no paramaters given
574  if (type == 'raster' and cmdlist[0][0] == 'r' and cmdlist[0][1] != '3') or \
575  (type == 'vector' and cmdlist[0][0] == 'v'):
576  input = GUI().GetCommandInputMapParamKey(cmdlist[0])
577  if input:
578  cmdlist.append("%s=%s" % (input, name))
579 
580  return cmdlist
581 
582  def RunMenuCmd(self, event = None, cmd = []):
583  """!Run command selected from menu"""
584  if event:
585  cmd = self.GetMenuCmd(event)
586  self.goutput.RunCmd(cmd, switchPage = False)
587 
588  def OnMenuCmd(self, event = None, cmd = []):
589  """!Parse command selected from menu"""
590  if event:
591  cmd = self.GetMenuCmd(event)
592  GUI(parent = self).ParseCommand(cmd)
593 
594  def OnVDigit(self, event):
595  """!Start vector digitizer
596  """
597  if not self.currentPage:
598  self.MsgNoLayerSelected()
599  return
600 
601  tree = self.GetLayerTree()
602  layer = tree.layer_selected
603  # no map layer selected
604  if not layer:
605  self.MsgNoLayerSelected()
606  return
607 
608  # available only for vector map layers
609  try:
610  mapLayer = tree.GetPyData(layer)[0]['maplayer']
611  except:
612  mapLayer = None
613 
614  if not mapLayer or mapLayer.GetType() != 'vector':
615  GMessage(parent = self,
616  message = _("Selected map layer is not vector."))
617  return
618 
619  if mapLayer.GetMapset() != grass.gisenv()['MAPSET']:
620  GMessage(parent = self,
621  message = _("Editing is allowed only for vector maps from the "
622  "current mapset."))
623  return
624 
625  if not tree.GetPyData(layer)[0]:
626  return
627  dcmd = tree.GetPyData(layer)[0]['cmd']
628  if not dcmd:
629  return
630 
631  tree.OnStartEditing(None)
632 
633  def OnRunScript(self, event):
634  """!Run script"""
635  # open dialog and choose script file
636  dlg = wx.FileDialog(parent = self, message = _("Choose script file to run"),
637  defaultDir = os.getcwd(),
638  wildcard = _("Python script (*.py)|*.py|Bash script (*.sh)|*.sh"))
639 
640  filename = None
641  if dlg.ShowModal() == wx.ID_OK:
642  filename = dlg.GetPath()
643 
644  if not filename:
645  return False
646 
647  if not os.path.exists(filename):
648  GError(parent = self,
649  message = _("Script file '%s' doesn't exist. "
650  "Operation canceled.") % filename)
651  return
652 
653  # check permission
654  if not os.access(filename, os.X_OK):
655  dlg = wx.MessageDialog(self,
656  message = _("Script <%s> is not executable. "
657  "Do you want to set the permissions "
658  "that allows you to run this script "
659  "(note that you must be the owner of the file)?" % \
660  os.path.basename(filename)),
661  caption = _("Set permission?"),
662  style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
663  if dlg.ShowModal() != wx.ID_YES:
664  return
665  dlg.Destroy()
666  try:
667  mode = stat.S_IMODE(os.lstat(filename)[stat.ST_MODE])
668  os.chmod(filename, mode | stat.S_IXUSR)
669  except OSError:
670  GError(_("Unable to set permission. Operation canceled."), parent = self)
671  return
672 
673  # check GRASS_ADDON_PATH
674  addonPath = os.getenv('GRASS_ADDON_PATH', [])
675  if addonPath:
676  addonPath = addonPath.split(os.pathsep)
677  dirName = os.path.dirname(filename)
678  if dirName not in addonPath:
679  addonPath.append(dirName)
680  dlg = wx.MessageDialog(self,
681  message = _("Directory '%s' is not defined in GRASS_ADDON_PATH. "
682  "Do you want add this directory to GRASS_ADDON_PATH?") % \
683  dirName,
684  caption = _("Update Addons path?"),
685  style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
686  if dlg.ShowModal() == wx.ID_YES:
687  SetAddOnPath(os.pathsep.join(addonPath))
688 
689  self.goutput.WriteCmdLog(_("Launching script '%s'...") % filename)
690  self.goutput.RunCmd([filename], switchPage = True)
691 
692  def OnChangeLocation(self, event):
693  """Change current location"""
694  dlg = LocationDialog(parent = self)
695  if dlg.ShowModal() == wx.ID_OK:
696  location, mapset = dlg.GetValues()
697  dlg.Destroy()
698 
699  if not location or not mapset:
700  GError(parent = self,
701  message = _("No location/mapset provided. Operation canceled."))
702  return # this should not happen
703 
704  if RunCommand('g.mapset', parent = self,
705  location = location,
706  mapset = mapset) != 0:
707  return # error reported
708 
709  # close workspace
710  self.OnWorkspaceClose()
711  self.OnWorkspaceNew()
712  GMessage(parent = self,
713  message = _("Current location is <%(loc)s>.\n"
714  "Current mapset is <%(mapset)s>.") % \
715  { 'loc' : location, 'mapset' : mapset })
716 
717  def OnCreateMapset(self, event):
718  """!Create new mapset"""
719  dlg = wx.TextEntryDialog(parent = self,
720  message = _('Enter name for new mapset:'),
721  caption = _('Create new mapset'))
722 
723  if dlg.ShowModal() == wx.ID_OK:
724  mapset = dlg.GetValue()
725  if not mapset:
726  GError(parent = self,
727  message = _("No mapset provided. Operation canceled."))
728  return
729 
730  ret = RunCommand('g.mapset',
731  parent = self,
732  flags = 'c',
733  mapset = mapset)
734  if ret == 0:
735  GMessage(parent = self,
736  message = _("Current mapset is <%s>.") % mapset)
737 
738  def OnChangeMapset(self, event):
739  """Change current mapset"""
740  dlg = MapsetDialog(parent = self)
741 
742  if dlg.ShowModal() == wx.ID_OK:
743  mapset = dlg.GetMapset()
744  dlg.Destroy()
745 
746  if not mapset:
747  GError(parent = self,
748  message = _("No mapset provided. Operation canceled."))
749  return
750 
751  if RunCommand('g.mapset',
752  parent = self,
753  mapset = mapset) == 0:
754  GMessage(parent = self,
755  message = _("Current mapset is <%s>.") % mapset)
756 
757  def OnNewVector(self, event):
758  """!Create new vector map layer"""
759  dlg = CreateNewVector(self, log = self.goutput,
760  cmd = (('v.edit',
761  { 'tool' : 'create' },
762  'map')))
763 
764  if not dlg:
765  return
766 
767  name = dlg.GetName(full = True)
768  if name and dlg.IsChecked('add'):
769  # add layer to map layer tree
770  self.GetLayerTree().AddLayer(ltype = 'vector',
771  lname = name,
772  lcmd = ['d.vect', 'map=%s' % name])
773  dlg.Destroy()
774 
775  def OnSystemInfo(self, event):
776  """!Print system information"""
777  vInfo = grass.version()
778 
779  # GDAL/OGR
780  try:
781  from osgeo import gdal
782  gdalVersion = gdal.__version__
783  except:
784  try:
785  gdalVersion = grass.Popen(['gdalinfo', '--version'], stdout = grass.PIPE).communicate()[0].rstrip('\n')
786  except:
787  gdalVersion = _("unknown")
788  # PROJ4
789  try:
790  projVersion = RunCommand('proj', getErrorMsg = True)[1].splitlines()[0]
791  except:
792  projVersion = _("unknown")
793  # check also OSGeo4W on MS Windows
794  if sys.platform == 'win32' and \
795  not os.path.exists(os.path.join(os.getenv("GISBASE"), "WinGRASS-README.url")):
796  osgeo4w = ' (OSGeo4W)'
797  else:
798  osgeo4w = ''
799 
800  self.goutput.WriteCmdLog(_("System Info"))
801  self.goutput.WriteLog("%s: %s\n"
802  "%s: %s\n"
803  # "%s: %s (%s)\n"
804  "GDAL/OGR: %s\n"
805  "PROJ4: %s\n"
806  "Python: %s\n"
807  "wxPython: %s\n"
808  "%s: %s%s\n"% (_("GRASS version"), vInfo['version'],
809  _("GRASS SVN Revision"), vInfo['revision'],
810  # _("GIS Library Revision"), vInfo['libgis_revision'], vInfo['libgis_date'].split(' ', 1)[0],
811  gdalVersion, projVersion,
812  platform.python_version(),
813  wx.__version__,
814  _("Platform"), platform.platform(), osgeo4w),
815  switchPage = True)
816  self.goutput.WriteCmdLog(' ')
817 
818  def OnAboutGRASS(self, event):
819  """!Display 'About GRASS' dialog"""
820  win = AboutWindow(self)
821  win.CentreOnScreen()
822  win.Show(True)
823 
824  def _popupMenu(self, data):
825  """!Create popup menu
826  """
827  point = wx.GetMousePosition()
828  menu = wx.Menu()
829 
830  for key, handler in data:
831  if key is None:
832  menu.AppendSeparator()
833  continue
834  item = wx.MenuItem(menu, wx.ID_ANY, LMIcons[key].GetLabel())
835  item.SetBitmap(LMIcons[key].GetBitmap(self.iconsize))
836  menu.AppendItem(item)
837  self.Bind(wx.EVT_MENU, handler, item)
838 
839  # create menu
840  self.PopupMenu(menu)
841  menu.Destroy()
842 
843  def OnImportMenu(self, event):
844  """!Import maps menu (import, link)
845  """
846  self._popupMenu((('rastImport', self.OnImportGdalLayers),
847  ('vectImport', self.OnImportOgrLayers)))
848 
849  def OnWorkspaceNew(self, event = None):
850  """!Create new workspace file
851 
852  Erase current workspace settings first
853  """
854  Debug.msg(4, "GMFrame.OnWorkspaceNew():")
855 
856  # start new map display if no display is available
857  if not self.currentPage:
858  self.NewDisplay()
859 
860  maptree = self.GetLayerTree()
861 
862  # ask user to save current settings
863  if self.workspaceFile and self.workspaceChanged:
864  self.OnWorkspaceSave()
865  elif self.workspaceFile is None and maptree.GetCount() > 0:
866  dlg = wx.MessageDialog(self, message = _("Current workspace is not empty. "
867  "Do you want to store current settings "
868  "to workspace file?"),
869  caption = _("Create new workspace?"),
870  style = wx.YES_NO | wx.YES_DEFAULT | \
871  wx.CANCEL | wx.ICON_QUESTION)
872  ret = dlg.ShowModal()
873  if ret == wx.ID_YES:
874  self.OnWorkspaceSaveAs()
875  elif ret == wx.ID_CANCEL:
876  dlg.Destroy()
877  return
878 
879  dlg.Destroy()
880 
881  # delete all items
882  maptree.DeleteAllItems()
883 
884  # add new root element
885  maptree.root = maptree.AddRoot("Map Layers")
886  self.GetLayerTree().SetPyData(maptree.root, (None,None))
887 
888  # no workspace file loaded
889  self.workspaceFile = None
890  self.workspaceChanged = False
891  self.SetTitle(self.baseTitle)
892 
893  def OnWorkspaceOpen(self, event = None):
894  """!Open file with workspace definition"""
895  dlg = wx.FileDialog(parent = self, message = _("Choose workspace file"),
896  defaultDir = os.getcwd(), wildcard = _("GRASS Workspace File (*.gxw)|*.gxw"))
897 
898  filename = ''
899  if dlg.ShowModal() == wx.ID_OK:
900  filename = dlg.GetPath()
901 
902  if filename == '':
903  return
904 
905  Debug.msg(4, "GMFrame.OnWorkspaceOpen(): filename=%s" % filename)
906 
907  # delete current layer tree content
908  self.OnWorkspaceClose()
909 
910  self.LoadWorkspaceFile(filename)
911 
912  self.workspaceFile = filename
913  self.SetTitle(self.baseTitle + " - " + os.path.basename(self.workspaceFile))
914 
915  def LoadWorkspaceFile(self, filename):
916  """!Load layer tree definition stored in GRASS Workspace XML file (gxw)
917 
918  @todo Validate against DTD
919 
920  @return True on success
921  @return False on error
922  """
923  # dtd
924  dtdFilename = os.path.join(globalvar.ETCWXDIR, "xml", "grass-gxw.dtd")
925 
926  # parse workspace file
927  try:
928  gxwXml = ProcessWorkspaceFile(etree.parse(filename))
929  except Exception, e:
930  GError(parent = self,
931  message = _("Reading workspace file <%s> failed.\n"
932  "Invalid file, unable to parse XML document.") % filename)
933  return
934 
935  busy = wx.BusyInfo(message = _("Please wait, loading workspace..."),
936  parent = self)
937  wx.Yield()
938 
939  #
940  # load layer manager window properties
941  #
942  if not UserSettings.Get(group = 'general', key = 'workspace',
943  subkey = ['posManager', 'enabled']):
944  if gxwXml.layerManager['pos']:
945  self.SetPosition(gxwXml.layerManager['pos'])
946  if gxwXml.layerManager['size']:
947  self.SetSize(gxwXml.layerManager['size'])
948 
949  #
950  # start map displays first (list of layers can be empty)
951  #
952  displayId = 0
953  mapdisplay = list()
954  for display in gxwXml.displays:
955  mapdisp = self.NewDisplay(name = display['name'], show = False)
956  mapdisplay.append(mapdisp)
957  maptree = self.notebookLayers.GetPage(displayId).maptree
958 
959  # set windows properties
960  mapdisp.SetProperties(render = display['render'],
961  mode = display['mode'],
962  showCompExtent = display['showCompExtent'],
963  alignExtent = display['alignExtent'],
964  constrainRes = display['constrainRes'],
965  projection = display['projection']['enabled'])
966 
967  if display['projection']['enabled']:
968  if display['projection']['epsg']:
969  UserSettings.Set(group = 'display', key = 'projection', subkey = 'epsg',
970  value = display['projection']['epsg'])
971  if display['projection']['proj']:
972  UserSettings.Set(group = 'display', key = 'projection', subkey = 'proj4',
973  value = display['projection']['proj'])
974 
975  # set position and size of map display
976  if not UserSettings.Get(group = 'general', key = 'workspace', subkey = ['posDisplay', 'enabled']):
977  if display['pos']:
978  mapdisp.SetPosition(display['pos'])
979  if display['size']:
980  mapdisp.SetSize(display['size'])
981 
982  # set extent if defined
983  if display['extent']:
984  w, s, e, n = display['extent']
985  region = maptree.Map.region = maptree.Map.GetRegion(w = w, s = s, e = e, n = n)
986  mapdisp.GetWindow().ResetZoomHistory()
987  mapdisp.GetWindow().ZoomHistory(region['n'],
988  region['s'],
989  region['e'],
990  region['w'])
991 
992  displayId += 1
993 
994  maptree = None
995  selected = [] # list of selected layers
996  #
997  # load list of map layers
998  #
999  for layer in gxwXml.layers:
1000  display = layer['display']
1001  maptree = self.notebookLayers.GetPage(display).maptree
1002 
1003  newItem = maptree.AddLayer(ltype = layer['type'],
1004  lname = layer['name'],
1005  lchecked = layer['checked'],
1006  lopacity = layer['opacity'],
1007  lcmd = layer['cmd'],
1008  lgroup = layer['group'],
1009  lnviz = layer['nviz'],
1010  lvdigit = layer['vdigit'])
1011 
1012  if layer.has_key('selected'):
1013  if layer['selected']:
1014  selected.append((maptree, newItem))
1015  else:
1016  maptree.SelectItem(newItem, select = False)
1017 
1018  for maptree, layer in selected:
1019  if not maptree.IsSelected(layer):
1020  maptree.SelectItem(layer, select = True)
1021  maptree.layer_selected = layer
1022 
1023  busy.Destroy()
1024 
1025  for idx, mdisp in enumerate(mapdisplay):
1026  mdisp.MapWindow2D.UpdateMap()
1027  # nviz
1028  if gxwXml.displays[idx]['viewMode'] == '3d':
1029  mdisp.AddNviz()
1030  self.nviz.UpdateState(view = gxwXml.nviz_state['view'],
1031  iview = gxwXml.nviz_state['iview'],
1032  light = gxwXml.nviz_state['light'])
1033  mdisp.MapWindow3D.constants = gxwXml.nviz_state['constants']
1034  for idx, constant in enumerate(mdisp.MapWindow3D.constants):
1035  mdisp.MapWindow3D.AddConstant(constant, idx + 1)
1036  for page in ('view', 'light', 'fringe', 'constant', 'cplane'):
1037  self.nviz.UpdatePage(page)
1038  self.nviz.UpdateSettings()
1039  mdisp.toolbars['map'].combo.SetSelection(1)
1040 
1041  mdisp.Show() # show mapdisplay
1042 
1043  return True
1044 
1045  def OnWorkspaceLoadGrcFile(self, event):
1046  """!Load map layers from GRC file (Tcl/Tk GUI) into map layer tree"""
1047  dlg = wx.FileDialog(parent = self, message = _("Choose GRC file to load"),
1048  defaultDir = os.getcwd(), wildcard = _("Old GRASS Workspace File (*.grc)|*.grc"))
1049 
1050  filename = ''
1051  if dlg.ShowModal() == wx.ID_OK:
1052  filename = dlg.GetPath()
1053 
1054  if filename == '':
1055  return
1056 
1057  Debug.msg(4, "GMFrame.OnWorkspaceLoadGrcFile(): filename=%s" % filename)
1058 
1059  # start new map display if no display is available
1060  if not self.currentPage:
1061  self.NewDisplay()
1062 
1063  busy = wx.BusyInfo(message = _("Please wait, loading workspace..."),
1064  parent = self)
1065  wx.Yield()
1066 
1067  maptree = None
1068  for layer in ProcessGrcFile(filename).read(self):
1069  maptree = self.notebookLayers.GetPage(layer['display']).maptree
1070  newItem = maptree.AddLayer(ltype = layer['type'],
1071  lname = layer['name'],
1072  lchecked = layer['checked'],
1073  lopacity = layer['opacity'],
1074  lcmd = layer['cmd'],
1075  lgroup = layer['group'])
1076 
1077  busy.Destroy()
1078 
1079  if maptree:
1080  # reverse list of map layers
1081  maptree.Map.ReverseListOfLayers()
1082 
1083  def OnWorkspaceSaveAs(self, event = None):
1084  """!Save workspace definition to selected file"""
1085  dlg = wx.FileDialog(parent = self, message = _("Choose file to save current workspace"),
1086  defaultDir = os.getcwd(), wildcard = _("GRASS Workspace File (*.gxw)|*.gxw"), style = wx.FD_SAVE)
1087 
1088  filename = ''
1089  if dlg.ShowModal() == wx.ID_OK:
1090  filename = dlg.GetPath()
1091 
1092  if filename == '':
1093  return False
1094 
1095  # check for extension
1096  if filename[-4:] != ".gxw":
1097  filename += ".gxw"
1098 
1099  if os.path.exists(filename):
1100  dlg = wx.MessageDialog(self, message = _("Workspace file <%s> already exists. "
1101  "Do you want to overwrite this file?") % filename,
1102  caption = _("Save workspace"), style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
1103  if dlg.ShowModal() != wx.ID_YES:
1104  dlg.Destroy()
1105  return False
1106 
1107  Debug.msg(4, "GMFrame.OnWorkspaceSaveAs(): filename=%s" % filename)
1108 
1109  self.SaveToWorkspaceFile(filename)
1110  self.workspaceFile = filename
1111  self.SetTitle(self.baseTitle + " - " + os.path.basename(self.workspaceFile))
1112 
1113  def OnWorkspaceSave(self, event = None):
1114  """!Save file with workspace definition"""
1115  if self.workspaceFile:
1116  dlg = wx.MessageDialog(self, message = _("Workspace file <%s> already exists. "
1117  "Do you want to overwrite this file?") % \
1118  self.workspaceFile,
1119  caption = _("Save workspace"), style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
1120  if dlg.ShowModal() == wx.ID_NO:
1121  dlg.Destroy()
1122  else:
1123  Debug.msg(4, "GMFrame.OnWorkspaceSave(): filename=%s" % self.workspaceFile)
1125  self.SetTitle(self.baseTitle + " - " + os.path.basename(self.workspaceFile))
1126  self.workspaceChanged = False
1127  else:
1128  self.OnWorkspaceSaveAs()
1129 
1130  def SaveToWorkspaceFile(self, filename):
1131  """!Save layer tree layout to workspace file
1132 
1133  Return True on success, False on error
1134  """
1135  tmpfile = tempfile.TemporaryFile(mode = 'w+b')
1136  try:
1137  WriteWorkspaceFile(lmgr = self, file = tmpfile)
1138  except StandardError, e:
1139  GError(parent = self,
1140  message = _("Writing current settings to workspace file "
1141  "failed."))
1142  return False
1143 
1144  try:
1145  mfile = open(filename, "w")
1146  tmpfile.seek(0)
1147  for line in tmpfile.readlines():
1148  mfile.write(line)
1149  except IOError:
1150  GError(parent = self,
1151  message = _("Unable to open file <%s> for writing.") % filename)
1152  return False
1153 
1154  mfile.close()
1155 
1156  return True
1157 
1158  def OnWorkspaceClose(self, event = None):
1159  """!Close file with workspace definition
1160 
1161  If workspace has been modified ask user to save the changes.
1162  """
1163  Debug.msg(4, "GMFrame.OnWorkspaceClose(): file=%s" % self.workspaceFile)
1164 
1165  self.OnDisplayCloseAll()
1166  self.workspaceFile = None
1167  self.workspaceChanged = False
1168  self.SetTitle(self.baseTitle)
1169  self.displayIndex = 0
1170  self.currentPage = None
1171 
1172  def OnDisplayClose(self, event = None):
1173  """!Close current map display window
1174  """
1175  if self.currentPage and self.GetMapDisplay():
1176  self.GetMapDisplay().OnCloseWindow(event)
1177 
1178  def OnDisplayCloseAll(self, event = None):
1179  """!Close all open map display windows
1180  """
1181  displays = list()
1182  for page in range(0, self.notebookLayers.GetPageCount()):
1183  displays.append(self.notebookLayers.GetPage(page).maptree.GetMapDisplay())
1184 
1185  for display in displays:
1186  display.OnCloseWindow(event)
1187 
1188  def OnRenameDisplay(self, event):
1189  """!Change Map Display name"""
1190  name = self.notebookLayers.GetPageText(self.currentPageNum)
1191  dlg = wx.TextEntryDialog(self, message = _("Enter new name:"),
1192  caption = _("Rename Map Display"), defaultValue = name)
1193  if dlg.ShowModal() == wx.ID_OK:
1194  name = dlg.GetValue()
1195  self.notebookLayers.SetPageText(page = self.currentPageNum, text = name)
1196  mapdisplay = self.GetMapDisplay()
1197  mapdisplay.SetTitle(_("GRASS GIS %(version) Map Display: %(name)s - Location: %(loc)s") % \
1198  { 'version' : grass.version()['version'],
1199  'name' : name,
1200  'loc' : grass.gisenv()["LOCATION_NAME"] })
1201  dlg.Destroy()
1202 
1203  def OnRasterRules(self, event):
1204  """!Launches dialog for raster color rules
1205  """
1206  ctable = RasterColorTable(self, layerTree = self.GetLayerTree())
1207  ctable.Show()
1208  ctable.CentreOnScreen()
1209 
1210  def OnVectorRules(self, event):
1211  """!Launches dialog for vector color rules
1212  """
1213  ctable = VectorColorTable(self, layerTree = self.GetLayerTree(),
1214  attributeType = 'color')
1215  ctable.Show()
1216  ctable.CentreOnScreen()
1217 
1218  def OnXTermNoXMon(self, event):
1219  """!
1220  Run commands that need xterm
1221  """
1222  self.OnXTerm(event, need_xmon = False)
1223 
1224  def OnXTerm(self, event, need_xmon = True):
1225  """!
1226  Run commands that need interactive xmon
1227 
1228  @param need_xmon True to start X monitor
1229  """
1230  # unset display mode
1231  if os.getenv('GRASS_RENDER_IMMEDIATE'):
1232  del os.environ['GRASS_RENDER_IMMEDIATE']
1233 
1234  if need_xmon:
1235  # open next available xmon
1236  xmonlist = []
1237 
1238  # make list of xmons that are not running
1239  ret = RunCommand('d.mon',
1240  flags = 'L',
1241  read = True)
1242 
1243  for line in ret.split('\n'):
1244  line = line.strip()
1245  if line.startswith('x') and 'not running' in line:
1246  xmonlist.append(line[0:2])
1247 
1248  # find available xmon
1249  xmon = xmonlist[0]
1250 
1251  # bring up the xmon
1252  cmdlist = ['d.mon', xmon]
1253  p = Command(cmdlist, wait=False)
1254 
1255  # run the command
1256  command = self.GetMenuCmd(event)
1257  command = ' '.join(command)
1258 
1259  gisbase = os.environ['GISBASE']
1260 
1261  if sys.platform == "win32":
1262  runbat = os.path.join(gisbase,'etc','grass-run.bat')
1263  cmdlist = ["start", runbat, runbat, command]
1264  else:
1265  if sys.platform == "darwin":
1266  xtermwrapper = os.path.join(gisbase,'etc','grass-xterm-mac')
1267  else:
1268  xtermwrapper = os.path.join(gisbase,'etc','grass-xterm-wrapper')
1269 
1270  grassrun = os.path.join(gisbase,'etc','grass-run.sh')
1271  cmdlist = [xtermwrapper, '-e', grassrun, command]
1272 
1273  p = Command(cmdlist, wait=False)
1274 
1275  # reset display mode
1276  os.environ['GRASS_RENDER_IMMEDIATE'] = 'TRUE'
1277 
1278  def OnEditImageryGroups(self, event, cmd = None):
1279  """!Show dialog for creating and editing groups.
1280  """
1281  dlg = GroupDialog(self)
1282  dlg.CentreOnScreen()
1283  dlg.Show()
1284 
1285  def OnInstallExtension(self, event):
1286  """!Install extension from GRASS Addons SVN repository"""
1287  win = InstallExtensionWindow(self, size = (650, 550))
1288  win.CentreOnScreen()
1289  win.Show()
1290 
1291  def OnUninstallExtension(self, event):
1292  """!Uninstall extension"""
1293  win = UninstallExtensionWindow(self, size = (650, 300))
1294  win.CentreOnScreen()
1295  win.Show()
1296 
1297  def OnPreferences(self, event):
1298  """!General GUI preferences/settings
1299  """
1300  if not self.dialogs['preferences']:
1301  dlg = PreferencesDialog(parent = self)
1302  self.dialogs['preferences'] = dlg
1303  self.dialogs['preferences'].CenterOnScreen()
1304 
1305  dlg.Bind(EVT_SETTINGS_CHANGED, self.OnSettingsChanged)
1306 
1307  self.dialogs['preferences'].ShowModal()
1308 
1309  def OnHelp(self, event):
1310  """!Show help
1311  """
1312  self.goutput.RunCmd(['g.manual','-i'])
1313 
1314  def OnHistogram(self, event):
1315  """!Init histogram display canvas and tools
1316  """
1317  from modules.histogram import HistogramFrame
1318  win = HistogramFrame(self)
1319 
1320  win.CentreOnScreen()
1321  win.Show()
1322  win.Refresh()
1323  win.Update()
1324 
1325  def OnProfile(self, event):
1326  """!Launch profile tool
1327  """
1328  win = profile.ProfileFrame(parent = self)
1329 
1330  win.CentreOnParent()
1331  win.Show()
1332  win.Refresh()
1333  win.Update()
1334 
1335  def OnMapCalculator(self, event, cmd = ''):
1336  """!Init map calculator for interactive creation of mapcalc statements
1337  """
1338  if event:
1339  try:
1340  cmd = self.GetMenuCmd(event)
1341  except KeyError:
1342  cmd = ['r.mapcalc']
1343 
1344  win = MapCalcFrame(parent = self,
1345  cmd = cmd[0])
1346  win.CentreOnScreen()
1347  win.Show()
1348 
1349  def OnVectorCleaning(self, event, cmd = ''):
1350  """!Init interactive vector cleaning
1351  """
1352  from modules.vclean import VectorCleaningFrame
1353  win = VectorCleaningFrame(parent = self)
1354  win.CentreOnScreen()
1355  win.Show()
1356 
1357  def OnImportDxfFile(self, event, cmd = None):
1358  """!Convert multiple DXF layers to GRASS vector map layers"""
1359  dlg = DxfImportDialog(parent = self)
1360  dlg.CentreOnScreen()
1361  dlg.Show()
1362 
1363  def OnImportGdalLayers(self, event, cmd = None):
1364  """!Convert multiple GDAL layers to GRASS raster map layers"""
1365  dlg = GdalImportDialog(parent = self)
1366  dlg.CentreOnScreen()
1367  dlg.Show()
1368 
1369  def OnLinkGdalLayers(self, event, cmd = None):
1370  """!Link multiple GDAL layers to GRASS raster map layers"""
1371  dlg = GdalImportDialog(parent = self, link = True)
1372  dlg.CentreOnScreen()
1373  dlg.Show()
1374 
1375  def OnImportOgrLayers(self, event, cmd = None):
1376  """!Convert multiple OGR layers to GRASS vector map layers"""
1377  dlg = GdalImportDialog(parent = self, ogr = True)
1378  dlg.CentreOnScreen()
1379  dlg.Show()
1380 
1381  def OnLinkOgrLayers(self, event, cmd = None):
1382  """!Links multiple OGR layers to GRASS vector map layers"""
1383  dlg = GdalImportDialog(parent = self, ogr = True, link = True)
1384  dlg.CentreOnScreen()
1385  dlg.Show()
1386 
1387  def OnImportWMS(self, event, cmd = None):
1388  """!Import data from OGC WMS server"""
1389  dlg = WMSDialog(parent = self, service = 'wms')
1390  dlg.CenterOnScreen()
1391 
1392  if dlg.ShowModal() == wx.ID_OK: # -> import layers
1393  layers = dlg.GetLayers()
1394 
1395  if len(layers.keys()) > 0:
1396  for layer in layers.keys():
1397  cmd = ['r.in.wms',
1398  'mapserver=%s' % dlg.GetSettings()['server'],
1399  'layers=%s' % layer,
1400  'output=%s' % layer,
1401  'format=png',
1402  '--overwrite']
1403  styles = ','.join(layers[layer])
1404  if styles:
1405  cmd.append('styles=%s' % styles)
1406  self.goutput.RunCmd(cmd, switchPage = True)
1407 
1408  self.GetLayerTree().AddLayer(ltype = 'raster',
1409  lname = layer,
1410  lcmd = ['d.rast', 'map=%s' % layer],
1411  multiple = False)
1412  else:
1413  self.goutput.WriteWarning(_("Nothing to import. No WMS layer selected."))
1414 
1415 
1416  dlg.Destroy()
1417 
1418  def OnShowAttributeTable(self, event, selection = None):
1419  """!Show attribute table of the given vector map layer
1420  """
1421  if not self.currentPage:
1422  self.MsgNoLayerSelected()
1423  return
1424 
1425  tree = self.GetLayerTree()
1426  layer = tree.layer_selected
1427  # no map layer selected
1428  if not layer:
1429  self.MsgNoLayerSelected()
1430  return
1431 
1432  # available only for vector map layers
1433  try:
1434  maptype = tree.GetPyData(layer)[0]['maplayer'].type
1435  except:
1436  maptype = None
1437 
1438  if not maptype or maptype != 'vector':
1439  GMessage(parent = self,
1440  message = _("Selected map layer is not vector."))
1441  return
1442 
1443  if not tree.GetPyData(layer)[0]:
1444  return
1445  dcmd = tree.GetPyData(layer)[0]['cmd']
1446  if not dcmd:
1447  return
1448 
1449  busy = wx.BusyInfo(message = _("Please wait, loading attribute data..."),
1450  parent = self)
1451  wx.Yield()
1452 
1453  dbmanager = AttributeManager(parent = self, id = wx.ID_ANY,
1454  size = wx.Size(500, 300),
1455  item = layer, log = self.goutput,
1456  selection = selection)
1457 
1458  busy.Destroy()
1459 
1460  # register ATM dialog
1461  self.dialogs['atm'].append(dbmanager)
1462 
1463  # show ATM window
1464  dbmanager.Show()
1465 
1466  def OnNewDisplayWMS(self, event = None):
1467  """!Create new layer tree and map display instance"""
1468  self.NewDisplayWMS()
1469 
1470  def OnNewDisplay(self, event = None):
1471  """!Create new layer tree and map display instance"""
1472  self.NewDisplay()
1473 
1474  def NewDisplay(self, name = None, show = True):
1475  """!Create new layer tree, which will
1476  create an associated map display frame
1477 
1478  @param name name of new map display
1479  @param show show map display window if True
1480 
1481  @return reference to mapdisplay intance
1482  """
1483  Debug.msg(1, "GMFrame.NewDisplay(): idx=%d" % self.displayIndex)
1484 
1485  # make a new page in the bookcontrol for the layer tree (on page 0 of the notebook)
1486  self.pg_panel = wx.Panel(self.notebookLayers, id = wx.ID_ANY, style = wx.EXPAND)
1487  if name:
1488  dispName = name
1489  else:
1490  dispName = "Display " + str(self.displayIndex + 1)
1491  self.notebookLayers.AddPage(self.pg_panel, text = dispName, select = True)
1492  self.currentPage = self.notebookLayers.GetCurrentPage()
1493 
1494  # create layer tree (tree control for managing GIS layers) and put on new notebook page
1495  self.currentPage.maptree = LayerTree(self.currentPage, id = wx.ID_ANY, pos = wx.DefaultPosition,
1496  size = wx.DefaultSize, style = wx.TR_HAS_BUTTONS |
1497  wx.TR_LINES_AT_ROOT| wx.TR_HIDE_ROOT |
1498  wx.TR_DEFAULT_STYLE| wx.NO_BORDER | wx.FULL_REPAINT_ON_RESIZE,
1499  idx = self.displayIndex, lmgr = self, notebook = self.notebookLayers,
1500  auimgr = self._auimgr, showMapDisplay = show)
1501 
1502  # layout for controls
1503  cb_boxsizer = wx.BoxSizer(wx.VERTICAL)
1504  cb_boxsizer.Add(self.GetLayerTree(), proportion = 1, flag = wx.EXPAND, border = 1)
1505  self.currentPage.SetSizer(cb_boxsizer)
1506  cb_boxsizer.Fit(self.GetLayerTree())
1507  self.currentPage.Layout()
1508  self.GetLayerTree().Layout()
1509 
1510  # use default window layout
1511  if UserSettings.Get(group = 'general', key = 'defWindowPos', subkey = 'enabled'):
1512  dim = UserSettings.Get(group = 'general', key = 'defWindowPos', subkey = 'dim')
1513  idx = 4 + self.displayIndex * 4
1514  try:
1515  x, y = map(int, dim.split(',')[idx:idx + 2])
1516  w, h = map(int, dim.split(',')[idx + 2:idx + 4])
1517  self.GetMapDisplay().SetPosition((x, y))
1518  self.GetMapDisplay().SetSize((w, h))
1519  except:
1520  pass
1521 
1522  self.displayIndex += 1
1523 
1524  return self.GetMapDisplay()
1525 
1526  def OnAddMaps(self, event = None):
1527  """!Add selected map layers into layer tree"""
1528  dialog = MapLayersDialog(parent = self, title = _("Add selected map layers into layer tree"))
1529 
1530  if dialog.ShowModal() != wx.ID_OK:
1531  dialog.Destroy()
1532  return
1533 
1534  # start new map display if no display is available
1535  if not self.currentPage:
1536  self.NewDisplay()
1537 
1538  maptree = self.GetLayerTree()
1539 
1540  for layerName in dialog.GetMapLayers():
1541  ltype = dialog.GetLayerType(cmd = True)
1542  if ltype == 'rast':
1543  cmd = ['d.rast', 'map=%s' % layerName]
1544  wxType = 'raster'
1545  elif ltype == 'rast3d':
1546  cmd = ['d.rast3d', 'map=%s' % layerName]
1547  wxType = '3d-raster'
1548  elif ltype == 'vect':
1549  cmd = ['d.vect', 'map=%s' % layerName]
1550  wxType = 'vector'
1551  else:
1552  GError(parent = self,
1553  message = _("Unsupported map layer type <%s>.") % ltype)
1554  return
1555 
1556  newItem = maptree.AddLayer(ltype = wxType,
1557  lname = layerName,
1558  lchecked = False,
1559  lopacity = 1.0,
1560  lcmd = cmd,
1561  lgroup = None)
1562  dialog.Destroy()
1563 
1564  def OnAddRaster(self, event):
1565  """!Add raster map layer"""
1566  # start new map display if no display is available
1567  if not self.currentPage:
1568  self.NewDisplay(show = True)
1569 
1570  self.notebook.SetSelectionByName('layers')
1571  self.GetLayerTree().AddLayer('raster')
1572 
1573  def OnAddRasterMisc(self, event):
1574  """!Create misc raster popup-menu"""
1575  # start new map display if no display is available
1576  if not self.currentPage:
1577  self.NewDisplay(show = True)
1578 
1579  self._popupMenu((('addRast3d', self.OnAddRaster3D),
1580  (None, None),
1581  ('addRgb', self.OnAddRasterRGB),
1582  ('addHis', self.OnAddRasterHIS),
1583  (None, None),
1584  ('addShaded', self.OnAddRasterShaded),
1585  (None, None),
1586  ('addRArrow', self.OnAddRasterArrow),
1587  ('addRNum', self.OnAddRasterNum)))
1588 
1589  # show map display
1590  self.GetMapDisplay().Show()
1591 
1592  def OnAddVector(self, event):
1593  """!Add vector map to the current layer tree"""
1594  # start new map display if no display is available
1595  if not self.currentPage:
1596  self.NewDisplay(show = True)
1597 
1598  self.notebook.SetSelectionByName('layers')
1599  self.GetLayerTree().AddLayer('vector')
1600 
1601  def OnAddVectorMisc(self, event):
1602  """!Create misc vector popup-menu"""
1603  # start new map display if no display is available
1604  if not self.currentPage:
1605  self.NewDisplay(show = True)
1606 
1607  self._popupMenu((('addThematic', self.OnAddVectorTheme),
1608  ('addChart', self.OnAddVectorChart)))
1609 
1610  # show map display
1611  self.GetMapDisplay().Show()
1612 
1613  def OnAddVectorTheme(self, event):
1614  """!Add thematic vector map to the current layer tree"""
1615  self.notebook.SetSelectionByName('layers')
1616  self.GetLayerTree().AddLayer('thememap')
1617 
1618  def OnAddVectorChart(self, event):
1619  """!Add chart vector map to the current layer tree"""
1620  self.notebook.SetSelectionByName('layers')
1621  self.GetLayerTree().AddLayer('themechart')
1622 
1623  def OnAddOverlay(self, event):
1624  """!Create decoration overlay menu"""
1625  # start new map display if no display is available
1626  if not self.currentPage:
1627  self.NewDisplay(show = True)
1628 
1629  self._popupMenu((('addGrid', self.OnAddGrid),
1630  ('addLabels', self.OnAddLabels),
1631  ('addGeodesic', self.OnAddGeodesic),
1632  ('addRhumb', self.OnAddRhumb),
1633  (None, None),
1634  ('addCmd', self.OnAddCommand)))
1635 
1636  # show map display
1637  self.GetMapDisplay().Show()
1638 
1639  def OnAddRaster3D(self, event):
1640  """!Add 3D raster map to the current layer tree"""
1641  self.notebook.SetSelectionByName('layers')
1642  self.GetLayerTree().AddLayer('3d-raster')
1643 
1644  def OnAddRasterRGB(self, event):
1645  """!Add RGB raster map to the current layer tree"""
1646  self.notebook.SetSelectionByName('layers')
1647  self.GetLayerTree().AddLayer('rgb')
1648 
1649  def OnAddRasterHIS(self, event):
1650  """!Add HIS raster map to the current layer tree"""
1651  self.notebook.SetSelectionByName('layers')
1652  self.GetLayerTree().AddLayer('his')
1653 
1654  def OnAddRasterShaded(self, event):
1655  """!Add shaded relief raster map to the current layer tree"""
1656  self.notebook.SetSelectionByName('layers')
1657  self.GetLayerTree().AddLayer('shaded')
1658 
1659  def OnAddRasterArrow(self, event):
1660  """!Add flow arrows raster map to the current layer tree"""
1661  self.notebook.SetSelectionByName('layers')
1662  tree = self.GetLayerTree()
1663  resolution = tree.GetMapDisplay().GetProperty('resolution')
1664  if not resolution:
1665  dlg = self.MsgDisplayResolution()
1666  if dlg.ShowModal() == wx.ID_YES:
1667  tree.GetMapDisplay().SetProperty('resolution', True)
1668  dlg.Destroy()
1669 
1670  self.GetLayerTree().AddLayer('rastarrow')
1671 
1672  def OnAddRasterNum(self, event):
1673  """!Add cell number raster map to the current layer tree"""
1674  self.notebook.SetSelectionByName('layers')
1675  tree = self.GetLayerTree()
1676  resolution = tree.GetMapDisplay().GetProperty('resolution')
1677  if not resolution:
1678  limitText = _("Note that cell values can only be displayed for "
1679  "regions of less than 10,000 cells.")
1680  dlg = self.MsgDisplayResolution(limitText)
1681  if dlg.ShowModal() == wx.ID_YES:
1682  tree.GetMapDisplay().SetProperty('resolution', True)
1683  dlg.Destroy()
1684 
1685  # region = tree.GetMap().GetCurrentRegion()
1686  # if region['cells'] > 10000:
1687  # GMessage(message = "Cell values can only be displayed for regions of < 10,000 cells.", parent = self)
1688  self.GetLayerTree().AddLayer('rastnum')
1689 
1690  def OnAddCommand(self, event):
1691  """!Add command line map layer to the current layer tree"""
1692  # start new map display if no display is available
1693  if not self.currentPage:
1694  self.NewDisplay(show = True)
1695 
1696  self.notebook.SetSelectionByName('layers')
1697  self.GetLayerTree().AddLayer('command')
1698 
1699  # show map display
1700  self.GetMapDisplay().Show()
1701 
1702  def OnAddGroup(self, event):
1703  """!Add layer group"""
1704  # start new map display if no display is available
1705  if not self.currentPage:
1706  self.NewDisplay(show = True)
1707 
1708  self.notebook.SetSelectionByName('layers')
1709  self.GetLayerTree().AddLayer('group')
1710 
1711  # show map display
1712  self.GetMapDisplay().Show()
1713 
1714  def OnAddGrid(self, event):
1715  """!Add grid map layer to the current layer tree"""
1716  self.notebook.SetSelectionByName('layers')
1717  self.GetLayerTree().AddLayer('grid')
1718 
1719  def OnAddGeodesic(self, event):
1720  """!Add geodesic line map layer to the current layer tree"""
1721  self.notebook.SetSelectionByName('layers')
1722  self.GetLayerTree().AddLayer('geodesic')
1723 
1724  def OnAddRhumb(self, event):
1725  """!Add rhumb map layer to the current layer tree"""
1726  self.notebook.SetSelectionByName('layers')
1727  self.GetLayerTree().AddLayer('rhumb')
1728 
1729  def OnAddLabels(self, event):
1730  """!Add vector labels map layer to the current layer tree"""
1731  # start new map display if no display is available
1732  if not self.currentPage:
1733  self.NewDisplay(show = True)
1734 
1735  self.notebook.SetSelectionByName('layers')
1736  self.GetLayerTree().AddLayer('labels')
1737 
1738  # show map display
1739  self.GetMapDisplay().Show()
1740 
1741  def OnDeleteLayer(self, event):
1742  """!Remove selected map layer from the current layer Tree
1743  """
1744  if not self.currentPage or not self.GetLayerTree().layer_selected:
1745  self.MsgNoLayerSelected()
1746  return
1747 
1748  if UserSettings.Get(group = 'manager', key = 'askOnRemoveLayer', subkey = 'enabled'):
1749  layerName = ''
1750  for item in self.GetLayerTree().GetSelections():
1751  name = str(self.GetLayerTree().GetItemText(item))
1752  idx = name.find('(opacity')
1753  if idx > -1:
1754  layerName += '<' + name[:idx].strip(' ') + '>,\n'
1755  else:
1756  layerName += '<' + name + '>,\n'
1757  layerName = layerName.rstrip(',\n')
1758 
1759  if len(layerName) > 2: # <>
1760  message = _("Do you want to remove map layer(s)\n%s\n"
1761  "from layer tree?") % layerName
1762  else:
1763  message = _("Do you want to remove selected map layer(s) "
1764  "from layer tree?")
1765 
1766  dlg = wx.MessageDialog (parent = self, message = message,
1767  caption = _("Remove map layer"),
1768  style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
1769 
1770  if dlg.ShowModal() != wx.ID_YES:
1771  dlg.Destroy()
1772  return
1773 
1774  dlg.Destroy()
1775 
1776  for layer in self.GetLayerTree().GetSelections():
1777  if self.GetLayerTree().GetPyData(layer)[0]['type'] == 'group':
1778  self.GetLayerTree().DeleteChildren(layer)
1779  self.GetLayerTree().Delete(layer)
1780 
1781  def OnKeyDown(self, event):
1782  """!Key pressed"""
1783  kc = event.GetKeyCode()
1784 
1785  if event.ControlDown():
1786  if kc == wx.WXK_TAB:
1787  # switch layer list / command output
1788  if self.notebook.GetSelection() == self.notebook.GetPageIndexByName('layers'):
1789  self.notebook.SetSelectionByName('output')
1790  else:
1791  self.notebook.SetSelectionByName('layers')
1792 
1793  try:
1794  ckc = chr(kc)
1795  except ValueError:
1796  event.Skip()
1797  return
1798 
1799  if event.CtrlDown():
1800  if kc == 'R':
1801  self.OnAddRaster(None)
1802  elif kc == 'V':
1803  self.OnAddVector(None)
1804 
1805  event.Skip()
1806 
1807  def OnCloseWindow(self, event):
1808  """!Cleanup when wxGUI is quitted"""
1809  # save command protocol if actived
1810  if self.goutput.btnCmdProtocol.GetValue():
1811  self.goutput.CmdProtocolSave()
1812 
1813  if not self.currentPage:
1814  self._auimgr.UnInit()
1815  self.Destroy()
1816  return
1817 
1818  # save changes in the workspace
1819  maptree = self.GetLayerTree()
1820  if self.workspaceChanged and \
1821  UserSettings.Get(group = 'manager', key = 'askOnQuit', subkey = 'enabled'):
1822  if self.workspaceFile:
1823  message = _("Do you want to save changes in the workspace?")
1824  else:
1825  message = _("Do you want to store current settings "
1826  "to workspace file?")
1827 
1828  # ask user to save current settings
1829  if maptree.GetCount() > 0:
1830  dlg = wx.MessageDialog(self,
1831  message = message,
1832  caption = _("Quit GRASS GUI"),
1833  style = wx.YES_NO | wx.YES_DEFAULT |
1834  wx.CANCEL | wx.ICON_QUESTION | wx.CENTRE)
1835  ret = dlg.ShowModal()
1836  if ret == wx.ID_YES:
1837  if not self.workspaceFile:
1838  self.OnWorkspaceSaveAs()
1839  else:
1841  elif ret == wx.ID_CANCEL:
1842  # when called from menu, it gets CommandEvent and not CloseEvent
1843  if hasattr(event, 'Veto'):
1844  event.Veto()
1845  dlg.Destroy()
1846  return
1847  dlg.Destroy()
1848 
1849  # don't ask any more...
1850  UserSettings.Set(group = 'manager', key = 'askOnQuit', subkey = 'enabled',
1851  value = False)
1852 
1853  self.OnDisplayCloseAll()
1854 
1855  self.notebookLayers.DeleteAllPages()
1856 
1857  self._auimgr.UnInit()
1858  self.Destroy()
1859 
1861  """!Show dialog message 'No layer selected'"""
1862  wx.MessageBox(parent = self,
1863  message = _("No map layer selected. Operation canceled."),
1864  caption = _("Message"),
1865  style = wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
1866 
1867  def MsgDisplayResolution(self, limitText = None):
1868  """!Returns dialog for d.rast.num, d.rast.arrow
1869  when display resolution is not constrained
1870 
1871  @param limitText adds a note about cell limit
1872  """
1873  message = _("Display resolution is currently not constrained to "
1874  "computational settings. "
1875  "It's suggested to constrain map to region geometry. "
1876  "Do you want to constrain "
1877  "the resolution?")
1878  if limitText:
1879  message += "\n\n%s" % _(limitText)
1880  dlg = wx.MessageDialog(parent = self,
1881  message = message,
1882  caption = _("Constrain map to region geometry?"),
1883  style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION | wx.CENTRE)
1884  return dlg
def MsgNoLayerSelected
Show dialog message &#39;No layer selected&#39;.
Definition: lmgr/frame.py:1860
def OnVectorCleaning
Init interactive vector cleaning.
Definition: lmgr/frame.py:1349
def IsPaneShown
Check if pane (toolbar, ...) of given name is currently shown.
Definition: lmgr/frame.py:240
def OnRunScript
Run script.
Definition: lmgr/frame.py:633
def OnNewDisplayWMS
Create new layer tree and map display instance.
Definition: lmgr/frame.py:1466
def OnProfile
Launch profile tool.
Definition: lmgr/frame.py:1325
wxGUI command interface
def OnXTermNoXMon
Run commands that need xterm.
Definition: lmgr/frame.py:1218
def OnCreateMapset
Create new mapset.
Definition: lmgr/frame.py:717
def OnAddRasterShaded
Add shaded relief raster map to the current layer tree.
Definition: lmgr/frame.py:1654
def _createNoteBook
Creates notebook widgets.
Definition: lmgr/frame.py:246
def OnAddRaster
Add raster map layer.
Definition: lmgr/frame.py:1564
def OnDisplayClose
Close current map display window.
Definition: lmgr/frame.py:1172
def OnVDigit
Start vector digitizer.
Definition: lmgr/frame.py:594
def _createTabMenu
Creates context menu for display tabs.
Definition: lmgr/frame.py:224
def _createMenuBar
Creates menu bar.
Definition: lmgr/frame.py:218
Location wizard - dialogs.
wxGUI Graphical Modeler (base classes &amp; read/write)
Location wizard - creates a new GRASS Location.
def OnImportMenu
Import maps menu (import, link)
Definition: lmgr/frame.py:843
def OnSettingsChanged
Here can be functions which have to be called after EVT_SETTINGS_CHANGED.
Definition: lmgr/frame.py:376
wxGUI debugging
def OnNewDisplay
Create new layer tree and map display instance.
Definition: lmgr/frame.py:1470
def OnHistogram
Init histogram display canvas and tools.
Definition: lmgr/frame.py:1314
Layer Manager frame with notebook widget for controlling GRASS GIS.
Definition: lmgr/frame.py:71
wxGUI Interactive Python Shell for Layer Manager
def OnDeleteLayer
Remove selected map layer from the current layer Tree.
Definition: lmgr/frame.py:1741
def OnImportWMS
Import data from OGC WMS server.
Definition: lmgr/frame.py:1387
GUI for ps.map.
Core GUI widgets.
def AddNvizTools
Add nviz notebook page.
Definition: lmgr/frame.py:286
def OnUninstallExtension
Uninstall extension.
Definition: lmgr/frame.py:1291
def OnPsMap
Launch Cartographic Composer.
Definition: lmgr/frame.py:395
def RemoveNvizTools
Remove nviz notebook page.
Definition: lmgr/frame.py:309
def OnImportGdalLayers
Convert multiple GDAL layers to GRASS raster map layers.
Definition: lmgr/frame.py:1363
Open/save workspace definition file.
def OnCBPageChanged
Page in notebook (display) changed.
Definition: lmgr/frame.py:441
GRASS Attribute Table Manager.
def OnAddRasterHIS
Add HIS raster map to the current layer tree.
Definition: lmgr/frame.py:1649
def OnVectorRules
Launches dialog for vector color rules.
Definition: lmgr/frame.py:1210
def OnLinkOgrLayers
Links multiple OGR layers to GRASS vector map layers.
Definition: lmgr/frame.py:1381
def GetMapDisplay
Get current map display.
Definition: lmgr/frame.py:518
def OnGModeler
Launch Graphical Modeler.
Definition: lmgr/frame.py:388
Nviz (3D view) module.
Various dialogs used in wxGUI.
def OnHelp
Show help.
Definition: lmgr/frame.py:1309
def _popupMenu
Create popup menu.
Definition: lmgr/frame.py:824
def OnAddRaster3D
Add 3D raster map to the current layer tree.
Definition: lmgr/frame.py:1639
Menu classes for wxGUI.
def OnAddVectorChart
Add chart vector map to the current layer tree.
Definition: lmgr/frame.py:1618
wxGUI Graphical Modeler for creating, editing, and managing models
def OnEditImageryGroups
Show dialog for creating and editing groups.
Definition: lmgr/frame.py:1278
def OnPreferences
General GUI preferences/settings.
Definition: lmgr/frame.py:1297
def SetAddOnPath
Set default AddOn path.
Definition: core/utils.py:893
def OnAddVectorMisc
Create misc vector popup-menu.
Definition: lmgr/frame.py:1601
NvizToolWindow
Definition: nviz/main.py:35
Georectification module for GRASS GIS.
Plotting histogram based on d.histogram.
def OnDisplayCloseAll
Close all open map display windows.
Definition: lmgr/frame.py:1178
def OnAddMaps
Add selected map layers into layer tree.
Definition: lmgr/frame.py:1526
def OnMenuCmd
Parse command selected from menu.
Definition: lmgr/frame.py:588
def OnAddLabels
Add vector labels map layer to the current layer tree.
Definition: lmgr/frame.py:1729
def OnAddVector
Add vector map to the current layer tree.
Definition: lmgr/frame.py:1592
def SaveToWorkspaceFile
Save layer tree layout to workspace file.
Definition: lmgr/frame.py:1130
def OnAddVectorTheme
Add thematic vector map to the current layer tree.
Definition: lmgr/frame.py:1613
def OnKeyDown
Key pressed.
Definition: lmgr/frame.py:1781
def GetMenuCmd
Get GRASS command from menu item.
Definition: lmgr/frame.py:545
def OnWorkspaceSaveAs
Save workspace definition to selected file.
Definition: lmgr/frame.py:1083
def OnWorkspaceNew
Create new workspace file.
Definition: lmgr/frame.py:849
def OnRasterRules
Launches dialog for raster color rules.
Definition: lmgr/frame.py:1203
def OnCloseWindow
Cleanup when wxGUI is quitted.
Definition: lmgr/frame.py:1807
def _setCopyingOfSelectedText
Definition: lmgr/frame.py:236
def OnAboutGRASS
Display &#39;About GRASS&#39; dialog.
Definition: lmgr/frame.py:818
def CreateNewVector
Create new vector map layer.
wxGUI Layer Manager - toolbars
def OnGCPManager
Launch georectifier module.
Definition: lmgr/frame.py:383
def OnInstallExtension
Install extension from GRASS Addons SVN repository.
Definition: lmgr/frame.py:1285
def OnAddOverlay
Create decoration overlay menu.
Definition: lmgr/frame.py:1623
def OnChangeMapset
Definition: lmgr/frame.py:738
def MsgDisplayResolution
Returns dialog for d.rast.num, d.rast.arrow when display resolution is not constrained.
Definition: lmgr/frame.py:1867
Help window.
Utility classes for map layer management.
def OnAddRasterArrow
Add flow arrows raster map to the current layer tree.
Definition: lmgr/frame.py:1659
def OnAddRasterNum
Add cell number raster map to the current layer tree.
Definition: lmgr/frame.py:1672
Mainframe for displaying profile of one or more raster maps.
Definition: profile.py:42
def OnSystemInfo
Print system information.
Definition: lmgr/frame.py:775
Misc utilities for wxGUI.
def OnMapsets
Launch mapset access dialog.
Definition: lmgr/frame.py:429
def OnAddGroup
Add layer group.
Definition: lmgr/frame.py:1702
def OnLinkGdalLayers
Link multiple GDAL layers to GRASS raster map layers.
Definition: lmgr/frame.py:1369
def LoadWorkspaceFile
Load layer tree definition stored in GRASS Workspace XML file (gxw)
Definition: lmgr/frame.py:915
User preferences dialog.
def OnMapCalculator
Init map calculator for interactive creation of mapcalc statements.
Definition: lmgr/frame.py:1335
def OnAddRhumb
Add rhumb map layer to the current layer tree.
Definition: lmgr/frame.py:1724
def OnAddGrid
Add grid map layer to the current layer tree.
Definition: lmgr/frame.py:1714
def OnAddRasterMisc
Create misc raster popup-menu.
Definition: lmgr/frame.py:1573
def OnXTerm
Run commands that need interactive xmon.
Definition: lmgr/frame.py:1224
def OnWorkspaceClose
Close file with workspace definition.
Definition: lmgr/frame.py:1158
def OnCBPageClosed
Page of notebook closed Also close associated map display.
Definition: lmgr/frame.py:464
GRASS Addons extensions management classes.
def OnImportDxfFile
Convert multiple DXF layers to GRASS vector map layers.
Definition: lmgr/frame.py:1357
def NewDisplay
Create new layer tree, which will create an associated map display frame.
Definition: lmgr/frame.py:1474
Default GUI settings.
def GetLogWindow
Get widget for command output.
Definition: lmgr/frame.py:541
def OnLocationWizard
Launch location wizard.
Definition: lmgr/frame.py:329
def OnChangeLocation
Definition: lmgr/frame.py:692
def GetLayerNotebook
Get Layers Notebook.
Definition: lmgr/frame.py:504
def OnAddCommand
Add command line map layer to the current layer tree.
Definition: lmgr/frame.py:1690
def OnShowAttributeTable
Show attribute table of the given vector map layer.
Definition: lmgr/frame.py:1418
tuple range
Definition: tools.py:1406
def OnNewVector
Create new vector map layer.
Definition: lmgr/frame.py:757
def RunMenuCmd
Run command selected from menu.
Definition: lmgr/frame.py:582
def WorkspaceChanged
Update window title.
Definition: lmgr/frame.py:321
def OnWorkspaceOpen
Open file with workspace definition.
Definition: lmgr/frame.py:893
def OnWorkspaceSave
Save file with workspace definition.
Definition: lmgr/frame.py:1113
Command output widgets.
def OnRunModel
Run model.
Definition: lmgr/frame.py:410
def OnRenameDisplay
Change Map Display name.
Definition: lmgr/frame.py:1188
def GetLayerTree
Get current layer tree.
Definition: lmgr/frame.py:508
def OnWorkspaceLoadGrcFile
Load map layers from GRC file (Tcl/Tk GUI) into map layer tree.
Definition: lmgr/frame.py:1045
def RunCommand
Run GRASS command.
Definition: gcmd.py:625
def OnImportOgrLayers
Convert multiple OGR layers to GRASS vector map layers.
Definition: lmgr/frame.py:1375
def OnAddRasterRGB
Add RGB raster map to the current layer tree.
Definition: lmgr/frame.py:1644
def OnPageChanged
Page in notebook changed.
Definition: lmgr/frame.py:453
def OnAddGeodesic
Add geodesic line map layer to the current layer tree.
Definition: lmgr/frame.py:1719