4 @brief Layer Manager - main menu, layer management toolbar, notebook
5 control for display management and access to command console.
10 (C) 2006-2012 by the GRASS Development Team
12 This program is free software under the GNU General Public License
13 (>=v2). Read the file COPYING that comes with GRASS for details.
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)
27 import xml.etree.ElementTree
as etree
29 import elementtree.ElementTree
as etree
31 from core
import globalvar
35 import wx.lib.agw.flatnotebook
as FN
37 import wx.lib.flatnotebook
as FN
39 sys.path.append(os.path.join(globalvar.ETCDIR,
"python"))
42 from core.gcmd import Command, RunCommand, GError, GMessage
47 from lmgr.menudata
import ManagerData
49 from modules.mcalc_builder
import MapCalcFrame
51 from core.workspace import ProcessWorkspaceFile, ProcessGrcFile, WriteWorkspaceFile
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
64 from lmgr.toolbars import LMWorkspaceToolbar, LMDataToolbar, LMToolsToolbar
65 from lmgr.toolbars import LMMiscToolbar, LMVectorToolbar, LMNvizToolbar
67 from gui_core.forms
import GUI
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.
76 def __init__(self, parent, id = wx.ID_ANY, title = _(
"GRASS GIS Layer Manager"),
78 size = globalvar.GM_WINDOW_SIZE, style = wx.DEFAULT_FRAME_STYLE, **kwargs):
83 wx.Frame.__init__(self, parent = parent, id = id, size = size,
84 style = style, **kwargs)
87 self.SetName(
"LayerManager")
89 self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR,
'grass.ico'), wx.BITMAP_TYPE_ICO))
91 self.
_auimgr = wx.aui.AuiManager(self)
104 self.
dialogs[
'preferences'] =
None
111 self.
toolbars = {
'workspace' : LMWorkspaceToolbar(parent = self),
112 'data' : LMDataToolbar(parent = self),
113 'tools' : LMToolsToolbar(parent = self),
114 'misc' : LMMiscToolbar(parent = self),
115 'vector' : LMVectorToolbar(parent = self),
116 'nviz' : LMNvizToolbar(parent = self)}
119 _(
"Workspace Toolbar"),
121 'data' : (
"toolbarData",
124 'misc' : (
"toolbarMisc",
127 'tools' : (
"toolbarTools",
130 'vector' : (
"toolbarVector",
133 'nviz' : (
"toolbarNviz",
134 _(
"3D view Toolbar"),
137 if sys.platform ==
'win32':
139 'vector',
'tools',
'misc',
'nviz')
142 'nviz',
'misc',
'tools',
'vector')
145 self._auimgr.AddPane(self.
toolbars[toolbar],
146 wx.aui.AuiPaneInfo().
147 Name(name).Caption(caption).
148 ToolbarPane().Top().Row(row).
149 LeftDockable(
False).RightDockable(
False).
150 BottomDockable(
False).TopDockable(
True).
151 CloseButton(
False).Layer(2).
152 BestSize((self.
toolbars[toolbar].GetBestSize())))
154 self._auimgr.GetPane(
'toolbarNviz').Hide()
157 self.Bind(wx.EVT_KEY_DOWN, self.
OnKeyDown)
160 self.SetMinSize((500, 400))
163 self._auimgr.AddPane(self.
notebook, wx.aui.AuiPaneInfo().
164 Left().CentrePane().BestSize((-1,-1)).Dockable(
False).
165 CloseButton(
False).DestroyOnClose(
True).Row(1).Layer(0))
167 self._auimgr.Update()
169 wx.CallAfter(self.notebook.SetSelectionByName,
'layers')
172 if UserSettings.Get(group =
'general', key =
'defWindowPos', subkey =
'enabled'):
173 dim = UserSettings.Get(group =
'general', key =
'defWindowPos', subkey =
'dim')
175 x, y = map(int, dim.split(
',')[0:2])
176 w, h = map(int, dim.split(
',')[2:4])
177 self.SetPosition((x, y))
200 if self.
curr_page and not self.curr_page.maptree.mapdisplay.IsShown():
201 self.curr_page.maptree.mapdisplay.Show()
204 self.goutput.Redirect()
207 self.goutput.SetSashPosition(int(self.GetSize()[1] * .8))
213 self.curr_page.maptree.mapdisplay.Raise()
214 wx.CallAfter(self.Raise)
216 def _createMenuBar(self):
217 """!Creates menu bar"""
218 self.
menubar = Menu(parent = self, data = ManagerData())
222 def _createTabMenu(self):
223 """!Creates context menu for display tabs.
225 Used to rename display.
228 item = wx.MenuItem(menu, id = wx.ID_ANY, text = _(
"Rename Map Display"))
229 menu.AppendItem(item)
234 def _setCopyingOfSelectedText(self):
235 copy = UserSettings.Get(group =
'manager', key =
'copySelectedTextToClipboard', subkey =
'enabled')
236 self.goutput.SetCopyingOfSelectedText(copy)
239 """!Check if pane (toolbar, ...) of given name is currently shown"""
240 if self._auimgr.GetPane(name).IsOk():
241 return self._auimgr.GetPane(name).IsShown()
244 def _createNoteBook(self):
245 """!Creates notebook widgets"""
246 self.
notebook = GNotebook(parent = self, style = globalvar.FNPageDStyle)
248 cbStyle = globalvar.FNPageStyle
250 self.
gm_cb = FN.FlatNotebook(self, id = wx.ID_ANY, agwStyle = cbStyle)
252 self.
gm_cb = FN.FlatNotebook(self, id = wx.ID_ANY, style = cbStyle)
253 self.gm_cb.SetTabAreaColour(globalvar.FNPageColor)
255 self.gm_cb.SetRightClickMenu(menu)
256 self.notebook.AddPage(page = self.
gm_cb, text = _(
"Map layers"), name =
'layers')
260 self.notebook.AddPage(page = self.
goutput, text = _(
"Command console"), name =
'output')
264 if not UserSettings.Get(group =
'manager', key =
'hideTabs', subkey =
'search'):
265 self.
search = MenuTreeWindow(parent = self)
266 self.notebook.AddPage(page = self.
search, text = _(
"Search module"), name =
'search')
271 if not UserSettings.Get(group =
'manager', key =
'hideTabs', subkey =
'pyshell'):
273 self.notebook.AddPage(page = self.
pyshell, text = _(
"Python shell"), name =
'pyshell')
278 self.gm_cb.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.
OnCBPageChanged)
279 self.notebook.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.
OnPageChanged)
280 self.gm_cb.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CLOSING, self.
OnCBPageClosed)
285 """!Add nviz notebook page"""
286 Debug.msg(5,
"GMFrame.AddNvizTools()")
293 self._auimgr.GetPane(
'toolbarNviz').Show()
295 for pos, toolbar
in enumerate((
'toolbarVector',
'toolbarTools',
'toolbarMisc',
'toolbarNviz')):
296 self._auimgr.GetPane(toolbar).Row(2).Position(pos)
297 self._auimgr.Update()
301 display = self.curr_page.maptree.GetMapDisplay())
302 idx = self.notebook.GetPageIndexByName(
'layers')
303 self.notebook.InsertPage(indx = idx + 1, page = self.
nviz, text = _(
"3D view"), name =
'nviz')
304 self.notebook.SetSelectionByName(
'nviz')
308 """!Remove nviz notebook page"""
310 self.notebook.SetSelectionByName(
'layers')
311 self.notebook.DeletePage(self.notebook.GetPageIndexByName(
'nviz'))
314 self._auimgr.GetPane(
'toolbarNviz').Hide()
315 for pos, toolbar
in enumerate((
'toolbarVector',
'toolbarTools',
'toolbarMisc')):
316 self._auimgr.GetPane(toolbar).Row(2).Position(pos)
317 self._auimgr.Update()
320 """!Update window title"""
328 """!Launch location wizard"""
332 gWizard = LocationWizard(parent = self,
333 grassdatabase = grass.gisenv()[
'GISDBASE'])
334 location = gWizard.location
337 dlg = wx.MessageDialog(parent = self,
338 message = _(
'Location <%s> created.\n\n'
339 'Do you want to switch to the '
340 'new location?') % location,
341 caption=_(
"Switch to new location?"),
342 style = wx.YES_NO | wx.NO_DEFAULT |
343 wx.ICON_QUESTION | wx.CENTRE)
345 ret = dlg.ShowModal()
350 mapset =
'PERMANENT') != 0:
353 GMessage(parent = self,
354 message = _(
"Current location is <%(loc)s>.\n"
355 "Current mapset is <%(mapset)s>.") % \
356 {
'loc' : location,
'mapset' :
'PERMANENT' })
359 dlg = wx.MessageDialog(parent = self,
360 message = _(
"Do you want to set the default "
361 "region extents and resolution now?"),
362 caption = _(
"Location <%s> created") % location,
363 style = wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
365 if dlg.ShowModal() == wx.ID_YES:
367 defineRegion = RegionDef(self, location = location)
368 defineRegion.CenterOnScreen()
369 defineRegion.ShowModal()
370 defineRegion.Destroy()
375 """!Here can be functions which have to be called after EVT_SETTINGS_CHANGED.
376 Now only set copying of selected text to clipboard (in goutput).
382 """!Launch georectifier module
387 """!Launch Graphical Modeler"""
394 """!Launch Cartographic Composer
402 """Command execution finised"""
403 if hasattr(self,
"model"):
404 self.model.DeleteIntermediateData(log = self.
goutput)
406 self.SetStatusText(
'')
411 dlg = wx.FileDialog(parent = self, message =_(
"Choose model to run"),
412 defaultDir = os.getcwd(),
413 wildcard = _(
"GRASS Model File (*.gxm)|*.gxm"))
414 if dlg.ShowModal() == wx.ID_OK:
415 filename = dlg.GetPath()
422 self.model.LoadModel(filename)
423 self.model.Run(log = self.
goutput, onDone = self.
OnDone, parent = self)
428 """!Launch mapset access dialog
430 dlg = MapsetAccess(parent = self, id = wx.ID_ANY)
433 if dlg.ShowModal() == wx.ID_OK:
434 ms = dlg.GetMapsets()
437 mapset =
'%s' %
','.join(ms))
440 """!Page in notebook (display) changed"""
441 self.
curr_page = self.gm_cb.GetCurrentPage()
444 self.curr_page.maptree.mapdisplay.SetFocus()
445 self.curr_page.maptree.mapdisplay.Raise()
452 """!Page in notebook changed"""
453 page = event.GetSelection()
454 if page == self.notebook.GetPageIndexByName(
'output'):
456 self.notebook.SetPageText(page, _(
"Command console"))
457 wx.CallAfter(self.goutput.ResetFocus)
458 self.SetStatusText(
'', 0)
463 """!Page of notebook closed
464 Also close associated map display
466 if UserSettings.Get(group =
'manager', key =
'askOnQuit', subkey =
'enabled'):
467 maptree = self.curr_page.maptree
470 message = _(
"Do you want to save changes in the workspace?")
472 message = _(
"Do you want to store current settings "
473 "to workspace file?")
476 if maptree.GetCount() > 0:
478 dlg = wx.MessageDialog(self,
480 caption = _(
"Close Map Display %s") % name,
481 style = wx.YES_NO | wx.YES_DEFAULT |
482 wx.CANCEL | wx.ICON_QUESTION | wx.CENTRE)
483 ret = dlg.ShowModal()
489 elif ret == wx.ID_CANCEL:
495 self.gm_cb.GetPage(event.GetSelection()).maptree.Map.Clean()
496 self.gm_cb.GetPage(event.GetSelection()).maptree.Close(
True)
503 """!Get current layer tree"""
505 return self.curr_page.maptree
509 """!Get widget for command output"""
513 """!Get GRASS command from menu item
515 Return command as a list"""
519 cmd = self.
menucmd[event.GetId()]
522 cmdlist = cmd.split(
' ')
528 if cmd
in [
'vcolors',
'r.mapcalc',
'r3.mapcalc']:
532 layer = self.curr_page.maptree.layer_selected
533 name = self.curr_page.maptree.GetPyData(layer)[0][
'maplayer'].name
534 type = self.curr_page.maptree.GetPyData(layer)[0][
'type']
538 if layer
and len(cmdlist) == 1:
539 if (type ==
'raster' and cmdlist[0][0] ==
'r' and cmdlist[0][1] != '3') or \
540 (type == 'vector' and cmdlist[0][0] == 'v'):
541 input = GUI().GetCommandInputMapParamKey(cmdlist[0])
543 cmdlist.append(
"%s=%s" % (input, name))
548 """!Run command selected from menu"""
551 self.goutput.RunCmd(cmd, switchPage =
False)
554 """!Parse command selected from menu"""
557 GUI(parent = self).ParseCommand(cmd)
560 """!Start vector digitizer
567 layer = tree.layer_selected
575 mapLayer = tree.GetPyData(layer)[0][
'maplayer']
579 if not mapLayer
or mapLayer.GetType() !=
'vector':
580 GMessage(parent = self,
581 message = _(
"Selected map layer is not vector."))
584 if mapLayer.GetMapset() != grass.gisenv()[
'MAPSET']:
585 GMessage(parent = self,
586 message = _(
"Editing is allowed only for vector maps from the "
590 if not tree.GetPyData(layer)[0]:
592 dcmd = tree.GetPyData(layer)[0][
'cmd']
596 tree.OnStartEditing(
None)
601 dlg = wx.FileDialog(parent = self, message = _(
"Choose script file to run"),
602 defaultDir = os.getcwd(),
603 wildcard = _(
"Python script (*.py)|*.py|Bash script (*.sh)|*.sh"))
606 if dlg.ShowModal() == wx.ID_OK:
607 filename = dlg.GetPath()
612 if not os.path.exists(filename):
613 GError(parent = self,
614 message = _(
"Script file '%s' doesn't exist. "
615 "Operation canceled.") % filename)
619 if not os.access(filename, os.X_OK):
620 dlg = wx.MessageDialog(self,
621 message = _(
"Script <%s> is not executable. "
622 "Do you want to set the permissions "
623 "that allows you to run this script "
624 "(note that you must be the owner of the file)?" % \
625 os.path.basename(filename)),
626 caption = _(
"Set permission?"),
627 style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
628 if dlg.ShowModal() != wx.ID_YES:
632 mode = stat.S_IMODE(os.lstat(filename)[stat.ST_MODE])
633 os.chmod(filename, mode | stat.S_IXUSR)
635 GError(_(
"Unable to set permission. Operation canceled."), parent = self)
639 addonPath = os.getenv(
'GRASS_ADDON_PATH', [])
641 addonPath = addonPath.split(os.pathsep)
642 dirName = os.path.dirname(filename)
643 if dirName
not in addonPath:
644 addonPath.append(dirName)
645 dlg = wx.MessageDialog(self,
646 message = _(
"Directory '%s' is not defined in GRASS_ADDON_PATH. "
647 "Do you want add this directory to GRASS_ADDON_PATH?") % \
649 caption = _(
"Update Addons path?"),
650 style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
651 if dlg.ShowModal() == wx.ID_YES:
654 self.goutput.WriteCmdLog(_(
"Launching script '%s'...") % filename)
655 self.goutput.RunCmd([filename], switchPage =
True)
658 """Change current location"""
659 dlg = LocationDialog(parent = self)
660 if dlg.ShowModal() == wx.ID_OK:
661 location, mapset = dlg.GetValues()
664 if not location
or not mapset:
665 GError(parent = self,
666 message = _(
"No location/mapset provided. Operation canceled."))
671 mapset = mapset) != 0:
677 GMessage(parent = self,
678 message = _(
"Current location is <%(loc)s>.\n"
679 "Current mapset is <%(mapset)s>.") % \
680 {
'loc' : location,
'mapset' : mapset })
683 """!Create new mapset"""
684 dlg = wx.TextEntryDialog(parent = self,
685 message = _(
'Enter name for new mapset:'),
686 caption = _(
'Create new mapset'))
688 if dlg.ShowModal() == wx.ID_OK:
689 mapset = dlg.GetValue()
691 GError(parent = self,
692 message = _(
"No mapset provided. Operation canceled."))
700 GMessage(parent = self,
701 message = _(
"Current mapset is <%s>.") % mapset)
704 """Change current mapset"""
705 dlg = MapsetDialog(parent = self)
707 if dlg.ShowModal() == wx.ID_OK:
708 mapset = dlg.GetMapset()
712 GError(parent = self,
713 message = _(
"No mapset provided. Operation canceled."))
718 mapset = mapset) == 0:
719 GMessage(parent = self,
720 message = _(
"Current mapset is <%s>.") % mapset)
723 """!Create new vector map layer"""
726 {
'tool' :
'create' },
732 name = dlg.GetName(full =
True)
733 if name
and dlg.IsChecked(
'add'):
735 self.curr_page.maptree.AddLayer(ltype =
'vector',
737 lcmd = [
'd.vect',
'map=%s' % name])
741 """!Print system information"""
742 vInfo = grass.version()
746 from osgeo
import gdal
747 gdalVersion = gdal.__version__
750 gdalVersion = grass.Popen([
'gdalinfo',
'--version'], stdout = grass.PIPE).communicate()[0].rstrip(
'\n')
752 gdalVersion = _(
"unknown")
755 projVersion =
RunCommand(
'proj', getErrorMsg =
True)[1].splitlines()[0]
757 projVersion = _(
"unknown")
759 if sys.platform ==
'win32' and \
760 not os.path.exists(os.path.join(os.getenv(
"GISBASE"),
"WinGRASS-README.url")):
761 osgeo4w =
' (OSGeo4W)'
765 self.goutput.WriteCmdLog(_(
"System Info"))
766 self.goutput.WriteLog(
"%s: %s\n"
773 "%s: %s%s\n"% (_(
"GRASS version"), vInfo[
'version'],
774 _(
"GRASS SVN Revision"), vInfo[
'revision'],
775 _(
"GIS Library Revision"), vInfo[
'libgis_revision'], vInfo[
'libgis_date'].
split(
' ', 1)[0],
776 gdalVersion, projVersion,
777 platform.python_version(),
779 _(
"Platform"), platform.platform(), osgeo4w),
781 self.goutput.WriteCmdLog(
' ')
784 """!Display 'About GRASS' dialog"""
785 win = AboutWindow(self)
789 def _popupMenu(self, data):
790 """!Create popup menu
792 point = wx.GetMousePosition()
795 for key, handler
in data:
797 menu.AppendSeparator()
799 item = wx.MenuItem(menu, wx.ID_ANY, LMIcons[key].GetLabel())
800 item.SetBitmap(LMIcons[key].GetBitmap(self.
iconsize))
801 menu.AppendItem(item)
802 self.Bind(wx.EVT_MENU, handler, item)
809 """!Import maps menu (import, link)
815 """!Create new workspace file
817 Erase current workspace settings first
819 Debug.msg(4,
"GMFrame.OnWorkspaceNew():")
825 maptree = self.curr_page.maptree
831 dlg = wx.MessageDialog(self, message = _(
"Current workspace is not empty. "
832 "Do you want to store current settings "
833 "to workspace file?"),
834 caption = _(
"Create new workspace?"),
835 style = wx.YES_NO | wx.YES_DEFAULT | \
836 wx.CANCEL | wx.ICON_QUESTION)
837 ret = dlg.ShowModal()
840 elif ret == wx.ID_CANCEL:
847 maptree.DeleteAllItems()
850 maptree.root = maptree.AddRoot(
"Map Layers")
851 self.curr_page.maptree.SetPyData(maptree.root, (
None,
None))
859 """!Open file with workspace definition"""
860 dlg = wx.FileDialog(parent = self, message = _(
"Choose workspace file"),
861 defaultDir = os.getcwd(), wildcard = _(
"GRASS Workspace File (*.gxw)|*.gxw"))
864 if dlg.ShowModal() == wx.ID_OK:
865 filename = dlg.GetPath()
870 Debug.msg(4,
"GMFrame.OnWorkspaceOpen(): filename=%s" % filename)
881 """!Load layer tree definition stored in GRASS Workspace XML file (gxw)
883 @todo Validate against DTD
885 @return True on success
886 @return False on error
889 dtdFilename = os.path.join(globalvar.ETCWXDIR,
"xml",
"grass-gxw.dtd")
893 gxwXml = ProcessWorkspaceFile(etree.parse(filename))
895 GError(parent = self,
896 message = _(
"Reading workspace file <%s> failed.\n"
897 "Invalid file, unable to parse XML document.") % filename)
900 busy = wx.BusyInfo(message = _(
"Please wait, loading workspace..."),
907 if not UserSettings.Get(group =
'general', key =
'workspace',
908 subkey = [
'posManager',
'enabled']):
909 if gxwXml.layerManager[
'pos']:
910 self.SetPosition(gxwXml.layerManager[
'pos'])
911 if gxwXml.layerManager[
'size']:
912 self.SetSize(gxwXml.layerManager[
'size'])
919 for display
in gxwXml.displays:
920 mapdisp = self.
NewDisplay(name = display[
'name'], show =
False)
921 mapdisplay.append(mapdisp)
922 maptree = self.gm_cb.GetPage(displayId).maptree
925 mapdisp.SetProperties(render = display[
'render'],
926 mode = display[
'mode'],
927 showCompExtent = display[
'showCompExtent'],
928 alignExtent = display[
'alignExtent'],
929 constrainRes = display[
'constrainRes'],
930 projection = display[
'projection'][
'enabled'])
932 if display[
'projection'][
'enabled']:
933 if display[
'projection'][
'epsg']:
934 UserSettings.Set(group =
'display', key =
'projection', subkey =
'epsg',
935 value = display[
'projection'][
'epsg'])
936 if display[
'projection'][
'proj']:
937 UserSettings.Set(group =
'display', key =
'projection', subkey =
'proj4',
938 value = display[
'projection'][
'proj'])
941 if not UserSettings.Get(group =
'general', key =
'workspace', subkey = [
'posDisplay',
'enabled']):
943 mapdisp.SetPosition(display[
'pos'])
945 mapdisp.SetSize(display[
'size'])
948 if display[
'extent']:
949 w, s, e, n = display[
'extent']
950 region = maptree.Map.region = maptree.Map.GetRegion(w = w, s = s, e = e, n = n)
951 mapdisp.GetWindow().ResetZoomHistory()
952 mapdisp.GetWindow().ZoomHistory(region[
'n'],
966 for layer
in gxwXml.layers:
967 display = layer[
'display']
968 maptree = self.gm_cb.GetPage(display).maptree
970 newItem = maptree.AddLayer(ltype = layer[
'type'],
971 lname = layer[
'name'],
972 lchecked = layer[
'checked'],
973 lopacity = layer[
'opacity'],
975 lgroup = layer[
'group'],
976 lnviz = layer[
'nviz'],
977 lvdigit = layer[
'vdigit'])
979 if layer.has_key(
'selected'):
980 if layer[
'selected']:
981 selected.append((maptree, newItem))
983 maptree.SelectItem(newItem, select =
False)
985 for maptree, layer
in selected:
986 if not maptree.IsSelected(layer):
987 maptree.SelectItem(layer, select =
True)
988 maptree.layer_selected = layer
992 for idx, mdisp
in enumerate(mapdisplay):
993 mdisp.MapWindow2D.UpdateMap()
995 if gxwXml.displays[idx][
'viewMode'] ==
'3d':
997 self.nviz.UpdateState(view = gxwXml.nviz_state[
'view'],
998 iview = gxwXml.nviz_state[
'iview'],
999 light = gxwXml.nviz_state[
'light'])
1000 mdisp.MapWindow3D.constants = gxwXml.nviz_state[
'constants']
1001 for idx, constant
in enumerate(mdisp.MapWindow3D.constants):
1002 mdisp.MapWindow3D.AddConstant(constant, idx + 1)
1003 for page
in (
'view',
'light',
'fringe',
'constant',
'cplane'):
1004 self.nviz.UpdatePage(page)
1005 self.nviz.UpdateSettings()
1006 mdisp.toolbars[
'map'].combo.SetSelection(1)
1013 """!Load map layers from GRC file (Tcl/Tk GUI) into map layer tree"""
1014 dlg = wx.FileDialog(parent = self, message = _(
"Choose GRC file to load"),
1015 defaultDir = os.getcwd(), wildcard = _(
"Old GRASS Workspace File (*.grc)|*.grc"))
1018 if dlg.ShowModal() == wx.ID_OK:
1019 filename = dlg.GetPath()
1024 Debug.msg(4,
"GMFrame.OnWorkspaceLoadGrcFile(): filename=%s" % filename)
1030 busy = wx.BusyInfo(message = _(
"Please wait, loading workspace..."),
1035 for layer
in ProcessGrcFile(filename).read(self):
1036 maptree = self.gm_cb.GetPage(layer[
'display']).maptree
1037 newItem = maptree.AddLayer(ltype = layer[
'type'],
1038 lname = layer[
'name'],
1039 lchecked = layer[
'checked'],
1040 lopacity = layer[
'opacity'],
1041 lcmd = layer[
'cmd'],
1042 lgroup = layer[
'group'])
1048 maptree.Map.ReverseListOfLayers()
1051 """!Save workspace definition to selected file"""
1052 dlg = wx.FileDialog(parent = self, message = _(
"Choose file to save current workspace"),
1053 defaultDir = os.getcwd(), wildcard = _(
"GRASS Workspace File (*.gxw)|*.gxw"), style = wx.FD_SAVE)
1056 if dlg.ShowModal() == wx.ID_OK:
1057 filename = dlg.GetPath()
1063 if filename[-4:] !=
".gxw":
1066 if os.path.exists(filename):
1067 dlg = wx.MessageDialog(self, message = _(
"Workspace file <%s> already exists. "
1068 "Do you want to overwrite this file?") % filename,
1069 caption = _(
"Save workspace"), style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
1070 if dlg.ShowModal() != wx.ID_YES:
1074 Debug.msg(4,
"GMFrame.OnWorkspaceSaveAs(): filename=%s" % filename)
1081 """!Save file with workspace definition"""
1083 dlg = wx.MessageDialog(self, message = _(
"Workspace file <%s> already exists. "
1084 "Do you want to overwrite this file?") % \
1086 caption = _(
"Save workspace"), style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
1087 if dlg.ShowModal() == wx.ID_NO:
1090 Debug.msg(4,
"GMFrame.OnWorkspaceSave(): filename=%s" % self.
workspaceFile)
1098 """!Save layer tree layout to workspace file
1100 Return True on success, False on error
1102 tmpfile = tempfile.TemporaryFile(mode =
'w+b')
1104 WriteWorkspaceFile(lmgr = self, file = tmpfile)
1105 except StandardError, e:
1106 GError(parent = self,
1107 message = _(
"Writing current settings to workspace file "
1112 mfile = open(filename,
"w")
1114 for line
in tmpfile.readlines():
1117 GError(parent = self,
1118 message = _(
"Unable to open file <%s> for writing.") % filename)
1126 """!Close file with workspace definition
1128 If workspace has been modified ask user to save the changes.
1130 Debug.msg(4,
"GMFrame.OnWorkspaceClose(): file=%s" % self.
workspaceFile)
1140 """!Close current map display window
1142 if self.
curr_page and self.curr_page.maptree.mapdisplay:
1143 self.curr_page.maptree.mapdisplay.OnCloseWindow(event)
1146 """!Close all open map display windows
1149 for page
in range(0, self.gm_cb.GetPageCount()):
1150 displays.append(self.gm_cb.GetPage(page).maptree.mapdisplay)
1152 for display
in displays:
1153 display.OnCloseWindow(event)
1156 """!Change Map Display name"""
1158 dlg = wx.TextEntryDialog(self, message = _(
"Enter new name:"),
1159 caption = _(
"Rename Map Display"), defaultValue = name)
1160 if dlg.ShowModal() == wx.ID_OK:
1161 name = dlg.GetValue()
1162 self.gm_cb.SetPageText(page = self.
curr_pagenum, text = name)
1163 mapdisplay = self.curr_page.maptree.mapdisplay
1164 mapdisplay.SetTitle(_(
"GRASS GIS Map Display: %(name)s - Location: %(loc)s") % \
1166 'loc' : grass.gisenv()[
"LOCATION_NAME"] })
1170 """!Launches dialog for commands that need rules input and
1175 if cmd[0] ==
'r.colors':
1176 ctable = RasterColorTable(self)
1178 ctable = VectorColorTable(self, attributeType =
'color')
1179 ctable.CentreOnScreen()
1184 Run commands that need xterm
1186 self.
OnXTerm(event, need_xmon =
False)
1190 Run commands that need interactive xmon
1192 @param need_xmon True to start X monitor
1195 if os.getenv(
'GRASS_RENDER_IMMEDIATE'):
1196 del os.environ[
'GRASS_RENDER_IMMEDIATE']
1207 for line
in ret.split(
'\n'):
1209 if line.startswith(
'x')
and 'not running' in line:
1210 xmonlist.append(line[0:2])
1216 cmdlist = [
'd.mon', xmon]
1217 p = Command(cmdlist, wait=
False)
1221 command =
' '.join(command)
1223 gisbase = os.environ[
'GISBASE']
1225 if sys.platform ==
"win32":
1226 runbat = os.path.join(gisbase,
'etc',
'grass-run.bat')
1227 cmdlist = [
"start", runbat, runbat, command]
1229 if sys.platform ==
"darwin":
1230 xtermwrapper = os.path.join(gisbase,
'etc',
'grass-xterm-mac')
1232 xtermwrapper = os.path.join(gisbase,
'etc',
'grass-xterm-wrapper')
1234 grassrun = os.path.join(gisbase,
'etc',
'grass-run.sh')
1235 cmdlist = [xtermwrapper,
'-e', grassrun, command]
1237 p = Command(cmdlist, wait=
False)
1240 os.environ[
'GRASS_RENDER_IMMEDIATE'] =
'TRUE'
1243 """!Show dialog for creating and editing groups.
1245 dlg = GroupDialog(self)
1246 dlg.CentreOnScreen()
1250 """!Install extension from GRASS Addons SVN repository"""
1251 win = InstallExtensionWindow(self, size = (650, 550))
1252 win.CentreOnScreen()
1256 """!Uninstall extension"""
1257 win = UninstallExtensionWindow(self, size = (650, 300))
1258 win.CentreOnScreen()
1262 """!General GUI preferences/settings
1264 if not self.
dialogs[
'preferences']:
1265 dlg = PreferencesDialog(parent = self)
1266 self.
dialogs[
'preferences'] = dlg
1267 self.
dialogs[
'preferences'].CenterOnScreen()
1271 self.
dialogs[
'preferences'].ShowModal()
1276 self.goutput.RunCmd([
'g.manual',
'-i'])
1279 """!Init histogram display canvas and tools
1282 win = HistogramFrame(self)
1284 win.CentreOnScreen()
1290 """!Launch profile tool
1294 win.CentreOnParent()
1300 """!Init map calculator for interactive creation of mapcalc statements
1308 win = MapCalcFrame(parent = self,
1310 win.CentreOnScreen()
1314 """!Init interactive vector cleaning
1316 from modules.vclean
import VectorCleaningFrame
1317 win = VectorCleaningFrame(parent = self)
1318 win.CentreOnScreen()
1322 """!Convert multiple DXF layers to GRASS vector map layers"""
1323 dlg = DxfImportDialog(parent = self)
1324 dlg.CentreOnScreen()
1328 """!Convert multiple GDAL layers to GRASS raster map layers"""
1329 dlg = GdalImportDialog(parent = self)
1330 dlg.CentreOnScreen()
1334 """!Link multiple GDAL layers to GRASS raster map layers"""
1335 dlg = GdalImportDialog(parent = self, link =
True)
1336 dlg.CentreOnScreen()
1340 """!Convert multiple OGR layers to GRASS vector map layers"""
1341 dlg = GdalImportDialog(parent = self, ogr =
True)
1342 dlg.CentreOnScreen()
1346 """!Links multiple OGR layers to GRASS vector map layers"""
1347 dlg = GdalImportDialog(parent = self, ogr =
True, link =
True)
1348 dlg.CentreOnScreen()
1352 """!Import data from OGC WMS server"""
1353 dlg = WMSDialog(parent = self, service =
'wms')
1354 dlg.CenterOnScreen()
1356 if dlg.ShowModal() == wx.ID_OK:
1357 layers = dlg.GetLayers()
1359 if len(layers.keys()) > 0:
1360 for layer
in layers.keys():
1362 'mapserver=%s' % dlg.GetSettings()[
'server'],
1363 'layers=%s' % layer,
1364 'output=%s' % layer,
1367 styles =
','.join(layers[layer])
1369 cmd.append(
'styles=%s' % styles)
1370 self.goutput.RunCmd(cmd, switchPage =
True)
1372 self.curr_page.maptree.AddLayer(ltype =
'raster',
1374 lcmd = [
'd.rast',
'map=%s' % layer],
1377 self.goutput.WriteWarning(_(
"Nothing to import. No WMS layer selected."))
1383 """!Show attribute table of the given vector map layer
1390 layer = tree.layer_selected
1398 maptype = tree.GetPyData(layer)[0][
'maplayer'].type
1402 if not maptype
or maptype !=
'vector':
1403 GMessage(parent = self,
1404 message = _(
"Selected map layer is not vector."))
1407 if not tree.GetPyData(layer)[0]:
1409 dcmd = tree.GetPyData(layer)[0][
'cmd']
1413 busy = wx.BusyInfo(message = _(
"Please wait, loading attribute data..."),
1417 dbmanager = AttributeManager(parent = self, id = wx.ID_ANY,
1418 size = wx.Size(500, 300),
1419 item = layer, log = self.
goutput,
1420 selection = selection)
1425 self.
dialogs[
'atm'].append(dbmanager)
1431 """!Create new layer tree and map display instance"""
1432 self.NewDisplayWMS()
1435 """!Create new layer tree and map display instance"""
1439 """!Create new layer tree, which will
1440 create an associated map display frame
1442 @param name name of new map display
1443 @param show show map display window if True
1445 @return reference to mapdisplay intance
1447 Debug.msg(1,
"GMFrame.NewDisplay(): idx=%d" % self.
disp_idx)
1454 dispName =
"Display " + str(self.
disp_idx + 1)
1455 self.gm_cb.AddPage(self.
pg_panel, text = dispName, select =
True)
1456 self.
curr_page = self.gm_cb.GetCurrentPage()
1459 self.curr_page.maptree = LayerTree(self.
curr_page, id = wx.ID_ANY, pos = wx.DefaultPosition,
1460 size = wx.DefaultSize, style = wx.TR_HAS_BUTTONS |
1461 wx.TR_LINES_AT_ROOT| wx.TR_HIDE_ROOT |
1462 wx.TR_DEFAULT_STYLE| wx.NO_BORDER | wx.FULL_REPAINT_ON_RESIZE,
1464 auimgr = self.
_auimgr, showMapDisplay = show)
1467 cb_boxsizer = wx.BoxSizer(wx.VERTICAL)
1468 cb_boxsizer.Add(self.curr_page.maptree, proportion = 1, flag = wx.EXPAND, border = 1)
1469 self.curr_page.SetSizer(cb_boxsizer)
1470 cb_boxsizer.Fit(self.curr_page.maptree)
1471 self.curr_page.Layout()
1472 self.curr_page.maptree.Layout()
1475 if UserSettings.Get(group =
'general', key =
'defWindowPos', subkey =
'enabled'):
1476 dim = UserSettings.Get(group =
'general', key =
'defWindowPos', subkey =
'dim')
1479 x, y = map(int, dim.split(
',')[idx:idx + 2])
1480 w, h = map(int, dim.split(
',')[idx + 2:idx + 4])
1481 self.curr_page.maptree.mapdisplay.SetPosition((x, y))
1482 self.curr_page.maptree.mapdisplay.SetSize((w, h))
1488 return self.curr_page.maptree.mapdisplay
1491 """!Add selected map layers into layer tree"""
1492 dialog = MapLayersDialog(parent = self, title = _(
"Add selected map layers into layer tree"))
1494 if dialog.ShowModal() != wx.ID_OK:
1502 maptree = self.curr_page.maptree
1504 for layerName
in dialog.GetMapLayers():
1505 ltype = dialog.GetLayerType(cmd =
True)
1507 cmd = [
'd.rast',
'map=%s' % layerName]
1509 elif ltype ==
'rast3d':
1510 cmd = [
'd.rast3d',
'map=%s' % layerName]
1511 wxType =
'3d-raster'
1512 elif ltype ==
'vect':
1513 cmd = [
'd.vect',
'map=%s' % layerName]
1516 GError(parent = self,
1517 message = _(
"Unsupported map layer type <%s>.") % ltype)
1520 newItem = maptree.AddLayer(ltype = wxType,
1529 """!Add raster map layer"""
1534 self.notebook.SetSelectionByName(
'layers')
1535 self.curr_page.maptree.AddLayer(
'raster')
1538 """!Create misc raster popup-menu"""
1554 self.curr_page.maptree.mapdisplay.Show()
1557 """!Add vector map to the current layer tree"""
1562 self.notebook.SetSelectionByName(
'layers')
1563 self.curr_page.maptree.AddLayer(
'vector')
1566 """!Create misc vector popup-menu"""
1575 self.curr_page.maptree.mapdisplay.Show()
1578 """!Add thematic vector map to the current layer tree"""
1579 self.notebook.SetSelectionByName(
'layers')
1580 self.curr_page.maptree.AddLayer(
'thememap')
1583 """!Add chart vector map to the current layer tree"""
1584 self.notebook.SetSelectionByName(
'layers')
1585 self.curr_page.maptree.AddLayer(
'themechart')
1588 """!Create decoration overlay menu"""
1601 self.curr_page.maptree.mapdisplay.Show()
1604 """!Add 3D raster map to the current layer tree"""
1605 self.notebook.SetSelectionByName(
'layers')
1606 self.curr_page.maptree.AddLayer(
'3d-raster')
1609 """!Add RGB raster map to the current layer tree"""
1610 self.notebook.SetSelectionByName(
'layers')
1611 self.curr_page.maptree.AddLayer(
'rgb')
1614 """!Add HIS raster map to the current layer tree"""
1615 self.notebook.SetSelectionByName(
'layers')
1616 self.curr_page.maptree.AddLayer(
'his')
1619 """!Add shaded relief raster map to the current layer tree"""
1620 self.notebook.SetSelectionByName(
'layers')
1621 self.curr_page.maptree.AddLayer(
'shaded')
1624 """!Add flow arrows raster map to the current layer tree"""
1625 self.notebook.SetSelectionByName(
'layers')
1626 tree = self.curr_page.maptree
1627 resolution = tree.GetMapDisplay().GetProperty(
'resolution')
1630 if dlg.ShowModal() == wx.ID_YES:
1631 tree.GetMapDisplay().SetProperty(
'resolution',
True)
1634 self.curr_page.maptree.AddLayer(
'rastarrow')
1637 """!Add cell number raster map to the current layer tree"""
1638 self.notebook.SetSelectionByName(
'layers')
1639 tree = self.curr_page.maptree
1640 resolution = tree.GetMapDisplay().GetProperty(
'resolution')
1642 limitText = _(
"Note that cell values can only be displayed for "
1643 "regions of less than 10,000 cells.")
1645 if dlg.ShowModal() == wx.ID_YES:
1646 tree.GetMapDisplay().SetProperty(
'resolution',
True)
1652 self.curr_page.maptree.AddLayer(
'rastnum')
1655 """!Add command line map layer to the current layer tree"""
1660 self.notebook.SetSelectionByName(
'layers')
1661 self.curr_page.maptree.AddLayer(
'command')
1664 self.curr_page.maptree.mapdisplay.Show()
1667 """!Add layer group"""
1672 self.notebook.SetSelectionByName(
'layers')
1673 self.curr_page.maptree.AddLayer(
'group')
1676 self.curr_page.maptree.mapdisplay.Show()
1679 """!Add grid map layer to the current layer tree"""
1680 self.notebook.SetSelectionByName(
'layers')
1681 self.curr_page.maptree.AddLayer(
'grid')
1684 """!Add geodesic line map layer to the current layer tree"""
1685 self.notebook.SetSelectionByName(
'layers')
1686 self.curr_page.maptree.AddLayer(
'geodesic')
1689 """!Add rhumb map layer to the current layer tree"""
1690 self.notebook.SetSelectionByName(
'layers')
1691 self.curr_page.maptree.AddLayer(
'rhumb')
1694 """!Add vector labels map layer to the current layer tree"""
1699 self.notebook.SetSelectionByName(
'layers')
1700 self.curr_page.maptree.AddLayer(
'labels')
1703 self.curr_page.maptree.mapdisplay.Show()
1706 """!Remove selected map layer from the current layer Tree
1708 if not self.
curr_page or not self.curr_page.maptree.layer_selected:
1712 if UserSettings.Get(group =
'manager', key =
'askOnRemoveLayer', subkey =
'enabled'):
1714 for item
in self.curr_page.maptree.GetSelections():
1715 name = str(self.curr_page.maptree.GetItemText(item))
1716 idx = name.find(
'(opacity')
1718 layerName +=
'<' + name[:idx].strip(
' ') +
'>,\n'
1720 layerName +=
'<' + name +
'>,\n'
1721 layerName = layerName.rstrip(
',\n')
1723 if len(layerName) > 2:
1724 message = _(
"Do you want to remove map layer(s)\n%s\n"
1725 "from layer tree?") % layerName
1727 message = _(
"Do you want to remove selected map layer(s) "
1730 dlg = wx.MessageDialog (parent = self, message = message,
1731 caption = _(
"Remove map layer"),
1732 style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
1734 if dlg.ShowModal() != wx.ID_YES:
1740 for layer
in self.curr_page.maptree.GetSelections():
1741 if self.curr_page.maptree.GetPyData(layer)[0][
'type'] ==
'group':
1742 self.curr_page.maptree.DeleteChildren(layer)
1743 self.curr_page.maptree.Delete(layer)
1747 kc = event.GetKeyCode()
1749 if event.ControlDown():
1750 if kc == wx.WXK_TAB:
1752 if self.notebook.GetSelection() == self.notebook.GetPageIndexByName(
'layers'):
1753 self.notebook.SetSelectionByName(
'output')
1755 self.notebook.SetSelectionByName(
'layers')
1763 if event.CtrlDown():
1772 """!Cleanup when wxGUI is quitted"""
1774 if self.goutput.btnCmdProtocol.GetValue():
1775 self.goutput.CmdProtocolSave()
1778 self._auimgr.UnInit()
1783 maptree = self.curr_page.maptree
1785 UserSettings.Get(group =
'manager', key =
'askOnQuit', subkey =
'enabled'):
1787 message = _(
"Do you want to save changes in the workspace?")
1789 message = _(
"Do you want to store current settings "
1790 "to workspace file?")
1793 if maptree.GetCount() > 0:
1794 dlg = wx.MessageDialog(self,
1796 caption = _(
"Quit GRASS GUI"),
1797 style = wx.YES_NO | wx.YES_DEFAULT |
1798 wx.CANCEL | wx.ICON_QUESTION | wx.CENTRE)
1799 ret = dlg.ShowModal()
1800 if ret == wx.ID_YES:
1805 elif ret == wx.ID_CANCEL:
1807 if hasattr(event,
'Veto'):
1814 UserSettings.Set(group =
'manager', key =
'askOnQuit', subkey =
'enabled',
1819 self.gm_cb.DeleteAllPages()
1821 self._auimgr.UnInit()
1825 """!Show dialog message 'No layer selected'"""
1826 wx.MessageBox(parent = self,
1827 message = _(
"No map layer selected. Operation canceled."),
1828 caption = _(
"Message"),
1829 style = wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
1832 """!Returns dialog for d.rast.num, d.rast.arrow
1833 when display resolution is not constrained
1835 @param limitText adds a note about cell limit
1837 message = _(
"Display resolution is currently not constrained to "
1838 "computational settings. "
1839 "It's suggested to constrain map to region geometry. "
1840 "Do you want to constrain "
1843 message +=
"\n\n%s" % _(limitText)
1844 dlg = wx.MessageDialog(parent = self,
1846 caption = _(
"Constrain map to region geometry?"),
1847 style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION | wx.CENTRE)