4 @brief Main Python app for GRASS wxPython GUI. Main menu, layer management
5 toolbar, notebook control for display management and access to
12 (C) 2006-2011 by the GRASS Development Team
13 This program is free software under the GNU General Public
14 License (>=v2). Read the file COPYING that comes with GRASS
17 @author Michael Barton (Arizona State University)
18 @author Jachym Cepicky (Mendel University of Agriculture)
19 @author Martin Landa <landa.martin gmail.com>
20 @author Vaclav Petras <wenzeslaus gmail.com> (menu customization)
34 import xml.etree.ElementTree
as etree
36 import elementtree.ElementTree
as etree
40 gettext.install(
'grasswxpy', os.path.join(os.getenv(
"GISBASE"),
'locale'), unicode =
True)
42 from gui_modules
import globalvar
49 import wx.lib.agw.customtreectrl
as CT
50 import wx.lib.agw.flatnotebook
as FN
52 import wx.lib.customtreectrl
as CT
53 import wx.lib.flatnotebook
as FN
56 import wx.lib.agw.advancedsplash
as SC
60 sys.path.append(os.path.join(globalvar.ETCDIR,
"python"))
63 from gui_modules
import utils
64 from gui_modules
import preferences
65 from gui_modules
import layertree
66 from gui_modules
import mapdisp
67 from gui_modules
import menudata
68 from gui_modules
import menuform
69 from gui_modules
import histogram
70 from gui_modules
import profile
71 from gui_modules
import mcalc_builder
as mapcalculator
72 from gui_modules
import gcmd
73 from gui_modules
import dbm
74 from gui_modules
import workspace
75 from gui_modules
import goutput
76 from gui_modules
import gdialogs
77 from gui_modules
import colorrules
78 from gui_modules
import ogc_services
79 from gui_modules
import prompt
80 from gui_modules
import menu
81 from gui_modules
import gmodeler
82 from gui_modules
import vclean
83 from gui_modules
import nviz_tools
85 from gui_modules.ghelp import MenuTreeWindow, AboutWindow, InstallExtensionWindow, UninstallExtensionWindow
86 from gui_modules.toolbars import LMWorkspaceToolbar, LMDataToolbar, LMToolsToolbar, LMMiscToolbar, LMVectorToolbar
90 UserSettings = preferences.globalSettings
93 """!Layer Manager frame with notebook widget for controlling GRASS
94 GIS. Includes command console page for typing GRASS (and other)
95 commands, tree widget page for managing map layers.
97 def __init__(self, parent, id = wx.ID_ANY, title = _(
"GRASS GIS Layer Manager"),
99 size = globalvar.GM_WINDOW_SIZE, style = wx.DEFAULT_FRAME_STYLE, **kwargs):
104 wx.Frame.__init__(self, parent = parent, id = id, size = size,
105 style = style, **kwargs)
108 self.SetName(
"LayerManager")
110 self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR,
'grass.ico'), wx.BITMAP_TYPE_ICO))
112 self.
_auimgr = wx.aui.AuiManager(self)
124 self.
dialogs[
'preferences'] =
None
138 _(
"Workspace Toolbar"),
140 'data' : (
"toolbarData",
143 'misc' : (
"toolbarMisc",
146 'tools' : (
"toolbarTools",
149 'vector' : (
"toolbarVector",
153 if sys.platform ==
'win32':
155 'vector',
'tools',
'misc')
158 'misc',
'tools',
'vector')
161 self._auimgr.AddPane(self.
toolbars[toolbar],
162 wx.aui.AuiPaneInfo().
163 Name(name).Caption(caption).
164 ToolbarPane().Top().Row(row).
165 LeftDockable(
False).RightDockable(
False).
166 BottomDockable(
False).TopDockable(
True).
167 CloseButton(
False).Layer(2).
168 BestSize((self.
toolbars[toolbar].GetBestSize())))
172 self.Bind(wx.EVT_KEY_DOWN, self.
OnKeyDown)
175 self.SetMinSize((500, 400))
178 self._auimgr.AddPane(self.
notebook, wx.aui.AuiPaneInfo().
179 Left().CentrePane().BestSize((-1,-1)).Dockable(
False).
180 CloseButton(
False).DestroyOnClose(
True).Row(1).Layer(0))
182 self._auimgr.Update()
184 wx.CallAfter(self.notebook.SetSelectionByName,
'layers')
187 if UserSettings.Get(group =
'general', key =
'defWindowPos', subkey =
'enabled'):
188 dim = UserSettings.Get(group =
'general', key =
'defWindowPos', subkey =
'dim')
190 x, y =
map(int, dim.split(
',')[0:2])
191 w, h =
map(int, dim.split(
',')[2:4])
192 self.SetPosition((x, y))
215 if self.
curr_page and not self.curr_page.maptree.mapdisplay.IsShown():
216 self.curr_page.maptree.mapdisplay.Show()
219 self.goutput.Redirect()
221 self.goutput.SetSashPosition(int(self.GetSize()[1] * .60))
227 self.curr_page.maptree.mapdisplay.Raise()
228 wx.CallAfter(self.Raise)
230 def _createMenuBar(self):
231 """!Creates menu bar"""
232 self.
menubar = menu.Menu(parent = self, data = menudata.ManagerData())
236 def _setCopyingOfSelectedText(self):
237 copy = UserSettings.Get(group =
'manager', key =
'copySelectedTextToClipboard', subkey =
'enabled')
238 self.goutput.SetCopyingOfSelectedText(copy)
240 def _createNoteBook(self):
241 """!Creates notebook widgets"""
242 self.
notebook = menuform.GNotebook(parent = self, style = globalvar.FNPageDStyle)
244 cbStyle = globalvar.FNPageStyle
246 self.
gm_cb = FN.FlatNotebook(self, id = wx.ID_ANY, agwStyle = cbStyle)
248 self.
gm_cb = FN.FlatNotebook(self, id = wx.ID_ANY, style = cbStyle)
249 self.gm_cb.SetTabAreaColour(globalvar.FNPageColor)
250 self.notebook.AddPage(page = self.
gm_cb, text = _(
"Map layers"), name =
'layers')
254 self.notebook.AddPage(page = self.
goutput, text = _(
"Command console"), name =
'output')
258 if not UserSettings.Get(group =
'manager', key =
'hideTabs', subkey =
'search'):
260 self.notebook.AddPage(page = self.
search, text = _(
"Search module"), name =
'search')
265 if not UserSettings.Get(group =
'manager', key =
'hideTabs', subkey =
'pyshell'):
267 self.notebook.AddPage(page = self.
pyshell, text = _(
"Python shell"), name =
'pyshell')
272 self.gm_cb.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.
OnCBPageChanged)
273 self.notebook.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.
OnPageChanged)
274 self.gm_cb.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CLOSING, self.
OnCBPageClosed)
279 """!Add nviz notebook page"""
280 self.
nviz = nviz_tools.NvizToolWindow(parent = self,
281 display = self.curr_page.maptree.GetMapDisplay())
282 self.notebook.AddPage(page = self.
nviz, text = _(
"3D view"), name =
'nviz')
283 self.notebook.SetSelectionByName(
'nviz')
286 """!Remove nviz notebook page"""
288 self.notebook.RemovePage(self.notebook.GetPageIndexByName(
'nviz'))
290 self.notebook.SetSelectionByName(
'layers')
293 """!Update window title"""
301 """!Here can be functions which have to be called after EVT_SETTINGS_CHANGED.
302 Now only set copying of selected text to clipboard (in goutput).
308 """!Launch georectifier module
310 from gui_modules
import gcpmanager
311 gcpmanager.GCPWizard(self)
314 """!Launch Graphical Modeler"""
315 win = gmodeler.ModelFrame(parent = self)
321 """!Launch Cartographic Composer
324 from gui_modules
import psmap
326 gcmd.GError(parent = self.
parent,
327 message = _(
"Hardcopy Map Output Utility is not available. You can install it by %s") % \
328 'g.extension.py -s svnurl=https://svn.osgeo.org/grass/grass-addons extension=wx.psmap')
331 win = psmap.PsMapFrame(parent = self)
337 """Command execution finised"""
338 if hasattr(self,
"model"):
339 self.model.DeleteIntermediateData(log = self.
goutput)
341 self.SetStatusText(
'')
346 dlg = wx.FileDialog(parent = self, message =_(
"Choose model to run"),
347 defaultDir = os.getcwd(),
348 wildcard = _(
"GRASS Model File (*.gxm)|*.gxm"))
349 if dlg.ShowModal() == wx.ID_OK:
350 filename = dlg.GetPath()
357 self.model.LoadModel(filename)
358 self.model.Run(log = self.
goutput, onDone = self.
OnDone, parent = self)
363 """!Launch mapset access dialog
365 dlg = preferences.MapsetAccess(parent = self, id = wx.ID_ANY)
368 if dlg.ShowModal() == wx.ID_OK:
369 ms = dlg.GetMapsets()
370 gcmd.RunCommand(
'g.mapsets',
372 mapset =
'%s' %
','.join(ms))
375 """!Page in notebook (display) changed"""
376 old_pgnum = event.GetOldSelection()
377 new_pgnum = event.GetSelection()
379 self.
curr_page = self.gm_cb.GetCurrentPage()
382 self.curr_page.maptree.mapdisplay.SetFocus()
383 self.curr_page.maptree.mapdisplay.Raise()
390 """!Page in notebook changed"""
391 page = event.GetSelection()
392 if page == self.notebook.GetPageIndexByName(
'output'):
394 self.notebook.SetPageText(page, _(
"Command console"))
395 wx.CallAfter(self.goutput.cmd_prompt.SetFocus)
396 self.SetStatusText(
'', 0)
401 """!Page of notebook closed
402 Also close associated map display
404 if UserSettings.Get(group =
'manager', key =
'askOnQuit', subkey =
'enabled'):
405 maptree = self.curr_page.maptree
408 message = _(
"Do you want to save changes in the workspace?")
410 message = _(
"Do you want to store current settings "
411 "to workspace file?")
414 if maptree.GetCount() > 0:
415 dlg = wx.MessageDialog(self,
417 caption = _(
"Close Map Display %d") % (self.
curr_pagenum + 1),
418 style = wx.YES_NO | wx.YES_DEFAULT |
419 wx.CANCEL | wx.ICON_QUESTION | wx.CENTRE)
420 ret = dlg.ShowModal()
426 elif ret == wx.ID_CANCEL:
432 self.gm_cb.GetPage(event.GetSelection()).maptree.Map.Clean()
433 self.gm_cb.GetPage(event.GetSelection()).maptree.Close(
True)
440 """!Get current layer tree"""
441 return self.curr_page.maptree
444 """!Get widget for command output"""
448 """!Get GRASS command from menu item
450 Return command as a list"""
454 cmd = self.
menucmd[event.GetId()]
457 cmdlist = cmd.split(
' ')
463 if cmd
in [
'vcolors',
'r.mapcalc',
'r3.mapcalc']:
467 layer = self.curr_page.maptree.layer_selected
468 name = self.curr_page.maptree.GetPyData(layer)[0][
'maplayer'].name
469 type = self.curr_page.maptree.GetPyData(layer)[0][
'type']
473 if layer
and len(cmdlist) == 1:
474 if (type ==
'raster' and cmdlist[0][0] ==
'r' and cmdlist[0][1] != '3') or \
475 (type == 'vector' and cmdlist[0][0] == 'v'):
476 input = menuform.GUI().GetCommandInputMapParamKey(cmdlist[0])
478 cmdlist.append(
"%s=%s" % (input, name))
483 """!Run command selected from menu"""
486 self.goutput.RunCmd(cmd, switchPage =
False)
489 """!Parse command selected from menu"""
492 menuform.GUI(parent = self).ParseCommand(cmd)
495 """!Start vector digitizer
502 layer = tree.layer_selected
510 mapLayer = tree.GetPyData(layer)[0][
'maplayer']
514 if not mapLayer
or mapLayer.GetType() !=
'vector':
515 gcmd.GMessage(parent = self,
516 message = _(
"Selected map layer is not vector."))
519 if mapLayer.GetMapset() != grass.gisenv()[
'MAPSET']:
520 gcmd.GMessage(parent = self,
521 message = _(
"Editing is allowed only for vector maps from the "
525 if not tree.GetPyData(layer)[0]:
527 dcmd = tree.GetPyData(layer)[0][
'cmd']
531 tree.OnStartEditing(
None)
536 dlg = wx.FileDialog(parent = self, message = _(
"Choose script file to run"),
537 defaultDir = os.getcwd(),
538 wildcard = _(
"Python script (*.py)|*.py|Bash script (*.sh)|*.sh"))
541 if dlg.ShowModal() == wx.ID_OK:
542 filename = dlg.GetPath()
547 if not os.path.exists(filename):
548 gcmd.GError(parent = self,
549 message = _(
"Script file '%s' doesn't exist. "
550 "Operation cancelled.") % filename)
553 self.goutput.WriteCmdLog(_(
"Launching script '%s'...") % filename)
554 self.goutput.RunCmd([filename], switchPage =
True)
557 """Change current location"""
558 dlg = gdialogs.LocationDialog(parent = self)
559 if dlg.ShowModal() == wx.ID_OK:
560 location, mapset = dlg.GetValues()
561 if location
and mapset:
562 ret = gcmd.RunCommand(
"g.gisenv",
563 set =
"LOCATION_NAME=%s" % location)
564 ret += gcmd.RunCommand(
"g.gisenv",
565 set =
"MAPSET=%s" % mapset)
567 wx.MessageBox(parent = self,
568 message = _(
"Unable to switch to location <%(loc)s> mapset <%(mapset)s>.") % \
569 {
'loc' : location,
'mapset' : mapset },
570 caption = _(
"Error"), style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
575 wx.MessageBox(parent = self,
576 message = _(
"Current location is <%(loc)s>.\n"
577 "Current mapset is <%(mapset)s>.") % \
578 {
'loc' : location,
'mapset' : mapset },
579 caption = _(
"Info"), style = wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
582 """Change current mapset"""
583 dlg = gdialogs.MapsetDialog(parent = self)
584 if dlg.ShowModal() == wx.ID_OK:
585 mapset = dlg.GetMapset()
587 if gcmd.RunCommand(
"g.gisenv",
588 set =
"MAPSET=%s" % mapset) != 0:
589 wx.MessageBox(parent = self,
590 message = _(
"Unable to switch to mapset <%s>.") % mapset,
591 caption = _(
"Error"), style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
593 wx.MessageBox(parent = self,
594 message = _(
"Current mapset is <%s>.") % mapset,
595 caption = _(
"Info"), style = wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
598 """!Create new vector map layer"""
599 dlg = gdialogs.CreateNewVector(self, log = self.
goutput,
601 {
'tool' :
'create' },
607 name = dlg.GetName(full =
True)
608 if name
and dlg.IsChecked(
'add'):
610 self.curr_page.maptree.AddLayer(ltype =
'vector',
612 lcmd = [
'd.vect',
'map=%s' % name])
615 if dlg.IsChecked(
'table'):
621 """!Display 'About GRASS' dialog"""
626 def _popupMenu(self, data):
627 """!Create popup menu
629 point = wx.GetMousePosition()
632 for key, handler
in data:
634 menu.AppendSeparator()
636 item = wx.MenuItem(menu, wx.ID_ANY, Icons[
'layerManager'][key].GetLabel())
637 item.SetBitmap(Icons[
'layerManager'][key].GetBitmap(self.
iconsize))
638 menu.AppendItem(item)
639 self.Bind(wx.EVT_MENU, handler, item)
646 """!Import maps menu (import, link)
652 """!Create new workspace file
654 Erase current workspace settings first
656 Debug.msg(4,
"GMFrame.OnWorkspaceNew():")
662 maptree = self.curr_page.maptree
668 dlg = wx.MessageDialog(self, message = _(
"Current workspace is not empty. "
669 "Do you want to store current settings "
670 "to workspace file?"),
671 caption = _(
"Create new workspace?"),
672 style = wx.YES_NO | wx.YES_DEFAULT | \
673 wx.CANCEL | wx.ICON_QUESTION)
674 ret = dlg.ShowModal()
677 elif ret == wx.ID_CANCEL:
684 maptree.DeleteAllItems()
687 maptree.root = maptree.AddRoot(
"Map Layers")
688 self.curr_page.maptree.SetPyData(maptree.root, (
None,
None))
696 """!Open file with workspace definition"""
697 dlg = wx.FileDialog(parent = self, message = _(
"Choose workspace file"),
698 defaultDir = os.getcwd(), wildcard = _(
"GRASS Workspace File (*.gxw)|*.gxw"))
701 if dlg.ShowModal() == wx.ID_OK:
702 filename = dlg.GetPath()
707 Debug.msg(4,
"GMFrame.OnWorkspaceOpen(): filename=%s" % filename)
718 """!Load layer tree definition stored in GRASS Workspace XML file (gxw)
720 @todo Validate against DTD
722 @return True on success
723 @return False on error
726 dtdFilename = os.path.join(globalvar.ETCWXDIR,
"xml",
"grass-gxw.dtd")
730 gxwXml = workspace.ProcessWorkspaceFile(etree.parse(filename))
732 gcmd.GError(parent = self,
733 message = _(
"Reading workspace file <%s> failed.\n"
734 "Invalid file, unable to parse XML document.") % filename)
737 busy = wx.BusyInfo(message = _(
"Please wait, loading workspace..."),
744 if UserSettings.Get(group =
'workspace', key =
'posManager', subkey =
'enabled')
is False:
745 if gxwXml.layerManager[
'pos']:
746 self.SetPosition(gxwXml.layerManager[
'pos'])
747 if gxwXml.layerManager[
'size']:
748 self.SetSize(gxwXml.layerManager[
'size'])
755 for display
in gxwXml.displays:
757 mapdisplay.append(mapdisp)
758 maptree = self.gm_cb.GetPage(displayId).maptree
761 mapdisp.SetProperties(render = display[
'render'],
762 mode = display[
'mode'],
763 showCompExtent = display[
'showCompExtent'],
764 constrainRes = display[
'constrainRes'],
765 projection = display[
'projection'][
'enabled'])
767 if display[
'projection'][
'enabled']:
768 if display[
'projection'][
'epsg']:
769 UserSettings.Set(group =
'display', key =
'projection', subkey =
'epsg',
770 value = display[
'projection'][
'epsg'])
771 if display[
'projection'][
'proj']:
772 UserSettings.Set(group =
'display', key =
'projection', subkey =
'proj4',
773 value = display[
'projection'][
'proj'])
776 if UserSettings.Get(group =
'workspace', key =
'posDisplay', subkey =
'enabled')
is False:
778 mapdisp.SetPosition(display[
'pos'])
780 mapdisp.SetSize(display[
'size'])
783 if display[
'extent']:
784 w, s, e, n = display[
'extent']
785 region = maptree.Map.region = maptree.Map.GetRegion(w = w, s = s, e = e, n = n)
786 mapdisp.GetWindow().ResetZoomHistory()
787 mapdisp.GetWindow().ZoomHistory(region[
'n'],
801 for layer
in gxwXml.layers:
802 display = layer[
'display']
803 maptree = self.gm_cb.GetPage(display).maptree
805 newItem = maptree.AddLayer(ltype = layer[
'type'],
806 lname = layer[
'name'],
807 lchecked = layer[
'checked'],
808 lopacity = layer[
'opacity'],
810 lgroup = layer[
'group'],
811 lnviz = layer[
'nviz'],
812 lvdigit = layer[
'vdigit'])
814 if layer.has_key(
'selected'):
815 if layer[
'selected']:
816 selected.append((maptree, newItem))
818 maptree.SelectItem(newItem, select =
False)
820 for maptree, layer
in selected:
821 if not maptree.IsSelected(layer):
822 maptree.SelectItem(layer, select =
True)
823 maptree.layer_selected = layer
827 for mdisp
in mapdisplay:
828 mdisp.MapWindow2D.UpdateMap()
833 """!Load map layers from GRC file (Tcl/Tk GUI) into map layer tree"""
834 dlg = wx.FileDialog(parent = self, message = _(
"Choose GRC file to load"),
835 defaultDir = os.getcwd(), wildcard = _(
"Old GRASS Workspace File (*.grc)|*.grc"))
838 if dlg.ShowModal() == wx.ID_OK:
839 filename = dlg.GetPath()
844 Debug.msg(4,
"GMFrame.OnWorkspaceLoadGrcFile(): filename=%s" % filename)
850 busy = wx.BusyInfo(message = _(
"Please wait, loading workspace..."),
855 for layer
in workspace.ProcessGrcFile(filename).read(self):
856 maptree = self.gm_cb.GetPage(layer[
'display']).maptree
857 newItem = maptree.AddLayer(ltype = layer[
'type'],
858 lname = layer[
'name'],
859 lchecked = layer[
'checked'],
860 lopacity = layer[
'opacity'],
862 lgroup = layer[
'group'])
868 maptree.Map.ReverseListOfLayers()
871 """!Save workspace definition to selected file"""
872 dlg = wx.FileDialog(parent = self, message = _(
"Choose file to save current workspace"),
873 defaultDir = os.getcwd(), wildcard = _(
"GRASS Workspace File (*.gxw)|*.gxw"), style = wx.FD_SAVE)
876 if dlg.ShowModal() == wx.ID_OK:
877 filename = dlg.GetPath()
883 if filename[-4:] !=
".gxw":
886 if os.path.exists(filename):
887 dlg = wx.MessageDialog(self, message = _(
"Workspace file <%s> already exists. "
888 "Do you want to overwrite this file?") % filename,
889 caption = _(
"Save workspace"), style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
890 if dlg.ShowModal() != wx.ID_YES:
894 Debug.msg(4,
"GMFrame.OnWorkspaceSaveAs(): filename=%s" % filename)
901 """!Save file with workspace definition"""
903 dlg = wx.MessageDialog(self, message = _(
"Workspace file <%s> already exists. "
904 "Do you want to overwrite this file?") % \
906 caption = _(
"Save workspace"), style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
907 if dlg.ShowModal() == wx.ID_NO:
910 Debug.msg(4,
"GMFrame.OnWorkspaceSave(): filename=%s" % self.
workspaceFile)
918 """!Save layer tree layout to workspace file
920 Return True on success, False on error
922 tmpfile = tempfile.TemporaryFile(mode =
'w+b')
924 workspace.WriteWorkspaceFile(lmgr = self, file = tmpfile)
925 except StandardError, e:
926 gcmd.GError(parent = self,
927 message = _(
"Writing current settings to workspace file "
932 mfile = open(filename,
"w")
934 for line
in tmpfile.readlines():
937 gcmd.GError(parent = self,
938 message = _(
"Unable to open file <%s> for writing.") % filename)
946 """!Close file with workspace definition
948 If workspace has been modified ask user to save the changes.
950 Debug.msg(4,
"GMFrame.OnWorkspaceClose(): file=%s" % self.
workspaceFile)
960 """!Close current map display window
962 if self.
curr_page and self.curr_page.maptree.mapdisplay:
963 self.curr_page.maptree.mapdisplay.OnCloseWindow(event)
966 """!Close all open map display windows
969 for page
in range(0, self.gm_cb.GetPageCount()):
970 displays.append(self.gm_cb.GetPage(page).maptree.mapdisplay)
972 for display
in displays:
973 display.OnCloseWindow(event)
976 """!Launches dialog for commands that need rules input and
981 if cmd[0] ==
'r.colors':
982 ctable = colorrules.ColorTable(self, raster =
True)
984 ctable = colorrules.ColorTable(self, raster =
False)
985 ctable.CentreOnScreen()
990 Run commands that need xterm
992 self.
OnXTerm(event, need_xmon =
False)
996 Run commands that need interactive xmon
998 @param need_xmon True to start X monitor
1001 del os.environ[
'GRASS_RENDER_IMMEDIATE']
1008 ret = gcmd.RunCommand(
'd.mon',
1012 for line
in ret.split(
'\n'):
1014 if line.startswith(
'x')
and 'not running' in line:
1015 xmonlist.append(line[0:2])
1021 cmdlist = [
'd.mon', xmon]
1022 p = gcmd.Command(cmdlist, wait=
False)
1026 command =
' '.join(command)
1028 gisbase = os.environ[
'GISBASE']
1030 if sys.platform ==
"win32":
1031 runbat = os.path.join(gisbase,
'etc',
'grass-run.bat')
1032 cmdlist = [
"start", runbat, runbat, command]
1034 if sys.platform ==
"darwin":
1035 xtermwrapper = os.path.join(gisbase,
'etc',
'grass-xterm-mac')
1037 xtermwrapper = os.path.join(gisbase,
'etc',
'grass-xterm-wrapper')
1039 grassrun = os.path.join(gisbase,
'etc',
'grass-run.sh')
1040 cmdlist = [xtermwrapper,
'-e', grassrun, command]
1042 p = gcmd.Command(cmdlist, wait=
False)
1045 os.environ[
'GRASS_RENDER_IMMEDIATE'] =
'TRUE'
1048 """!Install extension from GRASS Addons SVN repository"""
1050 win.CentreOnScreen()
1054 """!Uninstall extension"""
1056 win.CentreOnScreen()
1060 """!General GUI preferences/settings
1062 if not self.
dialogs[
'preferences']:
1063 dlg = preferences.PreferencesDialog(parent = self)
1064 self.
dialogs[
'preferences'] = dlg
1065 self.
dialogs[
'preferences'].CenterOnScreen()
1069 self.
dialogs[
'preferences'].ShowModal()
1074 self.goutput.RunCmd([
'g.manual',
'-i'])
1078 Init histogram display canvas and tools
1081 id = wx.ID_ANY, pos = wx.DefaultPosition, size = (400,300),
1082 style = wx.DEFAULT_FRAME_STYLE)
1085 self.histogram.Show()
1086 self.histogram.Refresh()
1087 self.histogram.Update()
1091 Init profile canvas and tools
1094 id = wx.ID_ANY, pos = wx.DefaultPosition, size = (400,300),
1095 style = wx.DEFAULT_FRAME_STYLE)
1097 self.profile.Refresh()
1098 self.profile.Update()
1101 """!Init map calculator for interactive creation of mapcalc statements
1109 win = mapcalculator.MapCalcFrame(parent = self,
1111 win.CentreOnScreen()
1115 """!Init interactive vector cleaning
1121 win = vclean.VectorCleaningFrame(parent = self, cmd = cmd[0])
1122 win.CentreOnScreen()
1126 """!Convert multiple DXF layers to GRASS vector map layers"""
1127 dlg = gdialogs.DxfImportDialog(parent = self)
1128 dlg.CentreOnScreen()
1132 """!Convert multiple GDAL layers to GRASS raster map layers"""
1133 dlg = gdialogs.GdalImportDialog(parent = self)
1134 dlg.CentreOnScreen()
1138 """!Link multiple GDAL layers to GRASS raster map layers"""
1139 dlg = gdialogs.GdalImportDialog(parent = self, link =
True)
1140 dlg.CentreOnScreen()
1144 """!Convert multiple OGR layers to GRASS vector map layers"""
1145 dlg = gdialogs.GdalImportDialog(parent = self, ogr =
True)
1146 dlg.CentreOnScreen()
1150 """!Links multiple OGR layers to GRASS vector map layers"""
1151 dlg = gdialogs.GdalImportDialog(parent = self, ogr =
True, link =
True)
1152 dlg.CentreOnScreen()
1156 """!Import data from OGC WMS server"""
1157 dlg = ogc_services.WMSDialog(parent = self, service =
'wms')
1158 dlg.CenterOnScreen()
1160 if dlg.ShowModal() == wx.ID_OK:
1161 layers = dlg.GetLayers()
1163 if len(layers.keys()) > 0:
1164 for layer
in layers.keys():
1166 'mapserver=%s' % dlg.GetSettings()[
'server'],
1167 'layers=%s' % layer,
1168 'output=%s' % layer,
1171 styles =
','.join(layers[layer])
1173 cmd.append(
'styles=%s' % styles)
1174 self.goutput.RunCmd(cmd, switchPage =
True)
1176 self.curr_page.maptree.AddLayer(ltype =
'raster',
1178 lcmd = [
'd.rast',
'map=%s' % layer],
1181 self.goutput.WriteWarning(_(
"Nothing to import. No WMS layer selected."))
1187 """!Show attribute table of the given vector map layer
1194 layer = tree.layer_selected
1202 maptype = tree.GetPyData(layer)[0][
'maplayer'].type
1206 if not maptype
or maptype !=
'vector':
1207 gcmd.GMessage(parent = self,
1208 message = _(
"Selected map layer is not vector."))
1211 if not tree.GetPyData(layer)[0]:
1213 dcmd = tree.GetPyData(layer)[0][
'cmd']
1217 busy = wx.BusyInfo(message = _(
"Please wait, loading attribute data..."),
1221 dbmanager = dbm.AttributeManager(parent = self, id = wx.ID_ANY,
1222 size = wx.Size(500, 300),
1223 item = layer, log = self.
goutput,
1224 selection = selection)
1229 self.
dialogs[
'atm'].append(dbmanager)
1235 """!Create new layer tree and map display instance"""
1239 """!Create new layer tree, which will
1240 create an associated map display frame
1242 @param show show map display window if True
1244 @return reference to mapdisplay intance
1246 Debug.msg(1,
"GMFrame.NewDisplay(): idx=%d" % self.
disp_idx)
1250 self.gm_cb.AddPage(self.
pg_panel, text =
"Display "+ str(self.
disp_idx + 1), select =
True)
1251 self.
curr_page = self.gm_cb.GetCurrentPage()
1254 self.curr_page.maptree = layertree.LayerTree(self.
curr_page, id = wx.ID_ANY, pos = wx.DefaultPosition,
1255 size = wx.DefaultSize, style = wx.TR_HAS_BUTTONS |
1256 wx.TR_LINES_AT_ROOT| wx.TR_HIDE_ROOT |
1257 wx.TR_DEFAULT_STYLE| wx.NO_BORDER | wx.FULL_REPAINT_ON_RESIZE,
1259 auimgr = self.
_auimgr, showMapDisplay = show)
1262 cb_boxsizer = wx.BoxSizer(wx.VERTICAL)
1263 cb_boxsizer.Add(self.curr_page.maptree, proportion = 1, flag = wx.EXPAND, border = 1)
1264 self.curr_page.SetSizer(cb_boxsizer)
1265 cb_boxsizer.Fit(self.curr_page.maptree)
1266 self.curr_page.Layout()
1267 self.curr_page.maptree.Layout()
1270 if UserSettings.Get(group =
'general', key =
'defWindowPos', subkey =
'enabled'):
1271 dim = UserSettings.Get(group =
'general', key =
'defWindowPos', subkey =
'dim')
1274 x, y =
map(int, dim.split(
',')[idx:idx + 2])
1275 w, h =
map(int, dim.split(
',')[idx + 2:idx + 4])
1276 self.curr_page.maptree.mapdisplay.SetPosition((x, y))
1277 self.curr_page.maptree.mapdisplay.SetSize((w, h))
1283 return self.curr_page.maptree.mapdisplay
1286 """!Add selected map layers into layer tree"""
1287 dialog = gdialogs.AddMapLayersDialog(parent = self, title = _(
"Add selected map layers into layer tree"))
1289 if dialog.ShowModal() == wx.ID_OK:
1294 maptree = self.curr_page.maptree
1295 busy = wx.BusyInfo(message = _(
"Please wait, loading workspace..."),
1299 for layerName
in dialog.GetMapLayers():
1300 if dialog.GetLayerType() ==
'raster':
1301 cmd = [
'd.rast',
'map=%s' % layerName]
1302 elif dialog.GetLayerType() ==
'vector':
1303 cmd = [
'd.vect',
'map=%s' % layerName]
1304 newItem = maptree.AddLayer(ltype = dialog.GetLayerType(),
1314 """!Add raster map layer"""
1319 self.notebook.SetSelectionByName(
'layers')
1320 self.curr_page.maptree.AddLayer(
'raster')
1323 """!Add 3D raster map layer"""
1328 self.AddRaster3D(event)
1331 """!Create misc raster popup-menu"""
1347 self.curr_page.maptree.mapdisplay.Show()
1350 """!Add vector map to the current layer tree"""
1355 self.notebook.SetSelectionByName(
'layers')
1356 self.curr_page.maptree.AddLayer(
'vector')
1359 """!Create misc vector popup-menu"""
1368 self.curr_page.maptree.mapdisplay.Show()
1371 """!Add thematic vector map to the current layer tree"""
1372 self.notebook.SetSelectionByName(
'layers')
1373 self.curr_page.maptree.AddLayer(
'thememap')
1376 """!Add chart vector map to the current layer tree"""
1377 self.notebook.SetSelectionByName(
'layers')
1378 self.curr_page.maptree.AddLayer(
'themechart')
1381 """!Create decoration overlay menu"""
1394 self.curr_page.maptree.mapdisplay.Show()
1397 """!Add 3D raster map to the current layer tree"""
1398 self.notebook.SetSelectionByName(
'layers')
1399 self.curr_page.maptree.AddLayer(
'3d-raster')
1402 """!Add RGB raster map to the current layer tree"""
1403 self.notebook.SetSelectionByName(
'layers')
1404 self.curr_page.maptree.AddLayer(
'rgb')
1407 """!Add HIS raster map to the current layer tree"""
1408 self.notebook.SetSelectionByName(
'layers')
1409 self.curr_page.maptree.AddLayer(
'his')
1412 """!Add shaded relief raster map to the current layer tree"""
1413 self.notebook.SetSelectionByName(
'layers')
1414 self.curr_page.maptree.AddLayer(
'shaded')
1417 """!Add flow arrows raster map to the current layer tree"""
1418 self.notebook.SetSelectionByName(
'layers')
1419 self.curr_page.maptree.AddLayer(
'rastarrow')
1422 """!Add cell number raster map to the current layer tree"""
1423 self.notebook.SetSelectionByName(
'layers')
1424 self.curr_page.maptree.AddLayer(
'rastnum')
1427 """!Add command line map layer to the current layer tree"""
1432 self.notebook.SetSelectionByName(
'layers')
1433 self.curr_page.maptree.AddLayer(
'command')
1436 self.curr_page.maptree.mapdisplay.Show()
1439 """!Add layer group"""
1444 self.notebook.SetSelectionByName(
'layers')
1445 self.curr_page.maptree.AddLayer(
'group')
1448 self.curr_page.maptree.mapdisplay.Show()
1451 """!Add grid map layer to the current layer tree"""
1452 self.notebook.SetSelectionByName(
'layers')
1453 self.curr_page.maptree.AddLayer(
'grid')
1456 """!Add geodesic line map layer to the current layer tree"""
1457 self.notebook.SetSelectionByName(
'layers')
1458 self.curr_page.maptree.AddLayer(
'geodesic')
1461 """!Add rhumb map layer to the current layer tree"""
1462 self.notebook.SetSelectionByName(
'layers')
1463 self.curr_page.maptree.AddLayer(
'rhumb')
1466 """!Add vector labels map layer to the current layer tree"""
1471 self.notebook.SetSelectionByName(
'layers')
1472 self.curr_page.maptree.AddLayer(
'labels')
1475 self.curr_page.maptree.mapdisplay.Show()
1478 """!Remove selected map layer from the current layer Tree
1480 if not self.
curr_page or not self.curr_page.maptree.layer_selected:
1484 if UserSettings.Get(group =
'manager', key =
'askOnRemoveLayer', subkey =
'enabled'):
1486 for item
in self.curr_page.maptree.GetSelections():
1487 name = str(self.curr_page.maptree.GetItemText(item))
1488 idx = name.find(
'(opacity')
1490 layerName +=
'<' + name[:idx].strip(
' ') +
'>,\n'
1492 layerName +=
'<' + name +
'>,\n'
1493 layerName = layerName.rstrip(
',\n')
1495 if len(layerName) > 2:
1496 message = _(
"Do you want to remove map layer(s)\n%s\n"
1497 "from layer tree?") % layerName
1499 message = _(
"Do you want to remove selected map layer(s) "
1502 dlg = wx.MessageDialog (parent = self, message = message,
1503 caption = _(
"Remove map layer"),
1504 style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
1506 if dlg.ShowModal() != wx.ID_YES:
1512 for layer
in self.curr_page.maptree.GetSelections():
1513 if self.curr_page.maptree.GetPyData(layer)[0][
'type'] ==
'group':
1514 self.curr_page.maptree.DeleteChildren(layer)
1515 self.curr_page.maptree.Delete(layer)
1519 kc = event.GetKeyCode()
1521 if event.ControlDown():
1522 if kc == wx.WXK_TAB:
1524 if self.notebook.GetSelection() == self.notebook.GetPageIndexByName(
'layers'):
1525 self.notebook.SetSelectionByName(
'output')
1527 self.notebook.SetSelectionByName(
'layers')
1535 if event.CtrlDown():
1544 """!Cleanup when wxGUI is quitted"""
1546 self._auimgr.UnInit()
1550 maptree = self.curr_page.maptree
1552 UserSettings.Get(group =
'manager', key =
'askOnQuit', subkey =
'enabled'):
1554 message = _(
"Do you want to save changes in the workspace?")
1556 message = _(
"Do you want to store current settings "
1557 "to workspace file?")
1560 if maptree.GetCount() > 0:
1561 dlg = wx.MessageDialog(self,
1563 caption = _(
"Quit GRASS GUI"),
1564 style = wx.YES_NO | wx.YES_DEFAULT |
1565 wx.CANCEL | wx.ICON_QUESTION | wx.CENTRE)
1566 ret = dlg.ShowModal()
1567 if ret == wx.ID_YES:
1572 elif ret == wx.ID_CANCEL:
1579 UserSettings.Set(group =
'manager', key =
'askOnQuit', subkey =
'enabled',
1584 self.gm_cb.DeleteAllPages()
1586 self._auimgr.UnInit()
1590 """!Show dialog message 'No layer selected'"""
1591 wx.MessageBox(parent = self,
1592 message = _(
"No map layer selected. Operation cancelled."),
1593 caption = _(
"Message"),
1594 style = wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
1600 @param workspace path to the workspace file
1605 wx.App.__init__(self,
False)
1607 self.
locale = wx.Locale(language = wx.LANGUAGE_DEFAULT)
1610 """!Initialize all available image handlers
1614 wx.InitAllImageHandlers()
1617 introImagePath = os.path.join(globalvar.ETCIMGDIR,
"silesia_splash.png")
1618 introImage = wx.Image(introImagePath, wx.BITMAP_TYPE_PNG)
1619 introBmp = introImage.ConvertToBitmap()
1621 splash = SC.AdvancedSplash(bitmap = introBmp,
1622 timeout = 2000, parent =
None, id = wx.ID_ANY)
1623 splash.SetText(_(
'Starting GRASS GUI...'))
1624 splash.SetTextColour(wx.Colour(45, 52, 27))
1625 splash.SetTextFont(wx.Font(pointSize = 15, family = wx.DEFAULT, style = wx.NORMAL,
1627 splash.SetTextPosition((150, 430))
1629 wx.SplashScreen (bitmap = introBmp, splashStyle = wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_TIMEOUT,
1630 milliseconds = 2000, parent =
None, id = wx.ID_ANY)
1635 w, h = wx.GetDisplaySize()
1656 mainframe =
GMFrame(parent =
None, id = wx.ID_ANY,
1660 self.SetTopWindow(mainframe)
1669 """!Print program help"""
1670 print >> sys.stderr,
"Usage:"
1671 print >> sys.stderr,
" python wxgui.py [options]"
1672 print >> sys.stderr,
"%sOptions:" % os.linesep
1673 print >> sys.stderr,
" -w\t--workspace file\tWorkspace file to load"
1677 """!Process command-line arguments"""
1678 workspaceFile =
None
1680 if o
in (
"-h",
"--help"):
1683 if o
in (
"-w",
"--workspace"):
1685 workspaceFile = str(a)
1687 workspaceFile = args.pop(0)
1689 return (workspaceFile,)
1699 opts, args = getopt.getopt(argv[1:],
"hw:",
1700 [
"help",
"workspace"])
1701 except getopt.error, msg:
1705 print >> sys.stderr, err.msg
1706 print >> sys.stderr,
"for help use --help"
1714 app =
GMApp(workspaceFile)
1720 if __name__ ==
"__main__":