2 @package gui_core.forms
4 @brief Construct simple wxPython GUI from a GRASS command interface
15 This program is just a coarse approach to automatically build a GUI
16 from a xml-based GRASS user interface description.
18 You need to have Python 2.4, wxPython 2.8 and python-xml.
20 The XML stream is read from executing the command given in the
21 command line, thus you may call it for instance this way:
23 python <this file.py> r.basins.fill
25 Or you set an alias or wrap the call up in a nice shell script, GUI
26 environment ... please contribute your idea.
28 Updated to wxPython 2.8 syntax and contrib widgets. Methods added to
29 make it callable by gui. Method added to automatically re-run with
33 - verify option value types
35 Copyright(C) 2000-2012 by the GRASS Development Team
37 This program is free software under the GPL(>=v2) Read the file
38 COPYING coming with GRASS for details.
40 @author Jan-Oliver Wagner <jan@intevation.de>
41 @author Bernhard Reiter <bernhard@intevation.de>
42 @author Michael Barton, Arizona State University
43 @author Daniel Calvelo <dca.gis@gmail.com>
44 @author Martin Landa <landa.martin@gmail.com>
45 @author Luca Delucchi <lucadeluge@gmail.com>
55 from threading
import Thread
59 gisbase = os.getenv(
"GISBASE")
61 print >>sys.stderr,
"We don't seem to be properly installed, or we are being run outside GRASS. Expect glitches."
62 gisbase = os.path.join(os.path.dirname(sys.argv[0]), os.path.pardir)
65 wxbase = os.path.join(gisbase,
'etc',
'wxpython')
67 sys.path.append(wxbase)
69 from core
import globalvar
72 import wx.lib.agw.flatnotebook
as FN
74 import wx.lib.flatnotebook
as FN
75 import wx.lib.colourselect
as csel
76 import wx.lib.filebrowsebutton
as filebrowse
77 from wx.lib.newevent
import NewEvent
80 import xml.etree.ElementTree
as etree
82 import elementtree.ElementTree
as etree
89 from gui_core
import gselect
91 from core
import utils
95 wxUpdateDialog, EVT_DIALOG_UPDATE = NewEvent()
99 str2rgb = {
'aqua': (100, 128, 255),
102 'brown': (180, 77, 25),
103 'cyan': (0, 255, 255),
104 'gray': (128, 128, 128),
105 'green': (0, 255, 0),
106 'grey': (128, 128, 128),
107 'indigo': (0, 128, 255),
108 'magenta': (255, 0, 255),
109 'orange': (255, 128, 0),
110 'purple': (128, 0, 128),
112 'violet': (128, 0, 255),
113 'white': (255, 255, 255),
114 'yellow': (255, 255, 0)}
116 for (s,r)
in str2rgb.items():
119 """!Hide some options in the GUI"""
120 _blackList = {
'enabled' :
False,
121 'items' : {
'd.legend' : {
'flags' : [
'm'] } }
125 if len(color) > 0
and color[0]
in "0123456789":
126 rgb = tuple(map(int, color.split(
':')))
131 rgb = str2rgb[ color ]
135 label = _(
'Select Color')
140 Make really long texts shorter, clean up whitespace and
141 remove trailing punctuation.
151 """!Escapes ampersands with additional ampersand for GUI"""
152 return string.replace(text,
"&",
"&&")
155 """!Update dialog widgets in the thread"""
157 Thread.__init__(self)
171 for p
in self.task.params:
172 if p.get(
'gisprompt',
False) ==
False:
174 prompt = p.get(
'element',
'')
175 if prompt ==
'vector':
176 name = p.get(
'name',
'')
177 if name
in (
'map',
'input'):
182 p = self.task.get_param(self.
eventId, element =
'wxId', raiseError =
False)
183 if not p
or 'wxId-bind' not in p:
187 pType = p.get(
'prompt',
'')
192 pMap = self.task.get_param(
'map', raiseError =
False)
195 pMap = self.task.get_param(
'input', raiseError =
False)
198 map = pMap.get(
'value',
'')
204 cparams[map] = {
'dbInfo' :
None,
208 for uid
in p[
'wxId-bind']:
209 win = self.parent.FindWindowById(uid)
214 pBind = self.task.get_param(uid, element =
'wxId', raiseError =
False)
218 if name ==
'LayerSelect':
219 if map
in cparams
and not cparams[map][
'layers']:
220 win.InsertLayers(vector = map)
221 cparams[map][
'layers'] = win.GetItems()
223 elif name ==
'TableSelect':
224 pDriver = self.task.get_param(
'dbdriver', element=
'prompt', raiseError=
False)
227 driver = pDriver[
'value']
228 pDb = self.task.get_param(
'dbname', element=
'prompt', raiseError=
False)
232 self.
data[win.InsertTables] = {
'driver' : driver,
235 elif name ==
'ColumnSelect':
236 pLayer = self.task.get_param(
'layer', element=
'element', raiseError=
False)
238 if pLayer.get(
'value',
'') !=
'':
239 layer = pLayer.get(
'value',
'')
241 layer = pLayer.get(
'default',
'')
247 if not cparams[map][
'dbInfo']:
249 self.
data[win.InsertColumns] = {
'vector' : map,
'layer' : layer,
250 'dbInfo' : cparams[map][
'dbInfo'] }
253 pDriver = self.task.get_param(
'dbdriver', element=
'prompt', raiseError=
False)
255 driver = pDriver.get(
'value',
None)
256 pDb = self.task.get_param(
'dbname', element=
'prompt', raiseError=
False)
258 db = pDb.get(
'value',
None)
259 pTable = self.task.get_param(
'dbtable', element=
'element', raiseError=
False)
261 pTable.get(
'value',
'') !=
'':
263 self.
data[win.InsertTableColumns] = {
'table' : pTable.get(
'value'),
267 self.
data[win.InsertTableColumns] = {
'table' : pTable.get(
'value') }
269 elif name ==
'SubGroupSelect':
270 self.
data[win.Insert] = {
'group' : p.get(
'value',
'')}
272 elif name ==
'LocationSelect':
273 pDbase = self.task.get_param(
'dbase', element =
'element', raiseError =
False)
275 self.
data[win.UpdateItems] = {
'dbase' : pDbase.get(
'value',
'')}
277 elif name ==
'MapsetSelect':
278 pDbase = self.task.get_param(
'dbase', element =
'element', raiseError =
False)
279 pLocation = self.task.get_param(
'location', element =
'element', raiseError =
False)
280 if pDbase
and pLocation:
281 self.
data[win.UpdateItems] = {
'dbase' : pDbase.get(
'value',
''),
282 'location' : pLocation.get(
'value',
'')}
284 elif name ==
'ProjSelect':
285 pDbase = self.task.get_param(
'dbase', element =
'element', raiseError =
False)
286 pLocation = self.task.get_param(
'location', element =
'element', raiseError =
False)
287 pMapset = self.task.get_param(
'mapset', element =
'element', raiseError =
False)
288 if pDbase
and pLocation
and pMapset:
289 self.
data[win.UpdateItems] = {
'dbase' : pDbase.get(
'value',
''),
290 'location' : pLocation.get(
'value',
''),
291 'mapset' : pMapset.get(
'value',
'')}
297 """!Update dialog widgets in the thread"""
299 def __init__(self, parent, requestQ, resultQ, **kwds):
300 Thread.__init__(self, **kwds)
310 def Update(self, callable, *args, **kwds):
311 UpdateQThread.requestId += 1
314 self.requestQ.put((UpdateQThread.requestId, callable, args, kwds))
316 return UpdateQThread.requestId
320 requestId, callable, args, kwds = self.requestQ.get()
322 requestTime = time.time()
324 self.
request = callable(*args, **kwds)
326 self.resultQ.put((requestId, self.request.run()))
329 event = wxUpdateDialog(data = self.request.data)
330 wx.PostEvent(self.
parent, event)
333 """!This is the Frame containing the dialog for options input.
335 The dialog is organized in a notebook according to the guisections
336 defined by each GRASS command.
338 If run with a parent, it may Apply, Ok or Cancel; the latter two
339 close the dialog. The former two trigger a callback.
341 If run standalone, it will allow execution of the command.
343 The command is checked and sent to the clipboard when clicking
346 def __init__(self, parent, ID, task_description,
347 get_dcmd =
None, layer =
None):
352 if parent
and parent.GetName() ==
'Modeler':
358 if self.task.name.split(
'.')[-1]
in (
'py',
'sh'):
359 title = str(self.task.name.rsplit(
'.',1)[0])
361 title = self.task.name
363 if self.task.keywords != [
'']:
364 title +=
" [" +
', '.join(self.task.keywords) +
"]"
368 wx.Frame.__init__(self, parent = parent, id = ID, title = title,
369 pos = wx.DefaultPosition, style = wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL,
372 self.
locale = wx.Locale(language = wx.LANGUAGE_DEFAULT)
374 self.
panel = wx.Panel(parent = self, id = wx.ID_ANY)
377 self.CreateStatusBar()
380 self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR,
'grass_dialog.ico'), wx.BITMAP_TYPE_ICO))
382 guisizer = wx.BoxSizer(wx.VERTICAL)
391 topsizer = wx.BoxSizer(wx.HORIZONTAL)
395 bitmap = wx.Bitmap(name = os.path.join(globalvar.ETCIMGDIR,
397 type = wx.BITMAP_TYPE_PNG))
398 topsizer.Add(item = self.
logo, proportion = 0, border = 3,
399 flag = wx.ALL | wx.ALIGN_CENTER_VERTICAL)
403 module_desc = self.task.label +
' ' + self.task.description
405 module_desc = self.task.description
408 topsizer.Add(item = self.
description, proportion = 1, border = 5,
409 flag = wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)
411 guisizer.Add(item = topsizer, proportion = 0, flag = wx.EXPAND)
413 self.panel.SetSizerAndFit(guisizer)
421 guisizer.Add(item = self.
notebookpanel, proportion = 1, flag = wx.EXPAND)
424 status_text = _(
"Enter parameters for '") + self.task.name +
"'"
429 self.SetStatusText(status_text)
432 btnsizer = wx.BoxSizer(orient = wx.HORIZONTAL)
435 self.btn_cancel.SetToolTipString(_(
"Close this window without executing the command (Ctrl+Q)"))
436 btnsizer.Add(item = self.
btn_cancel, proportion = 0, flag = wx.ALL | wx.ALIGN_CENTER, border = 10)
437 self.btn_cancel.Bind(wx.EVT_BUTTON, self.
OnCancel)
440 btn_apply = wx.Button(parent = self.
panel, id = wx.ID_APPLY)
441 btn_ok = wx.Button(parent = self.
panel, id = wx.ID_OK)
444 btnsizer.Add(item = btn_apply, proportion = 0,
445 flag = wx.ALL | wx.ALIGN_CENTER,
447 btnsizer.Add(item = btn_ok, proportion = 0,
448 flag = wx.ALL | wx.ALIGN_CENTER,
451 btn_apply.Bind(wx.EVT_BUTTON, self.
OnApply)
452 btn_ok.Bind(wx.EVT_BUTTON, self.
OnOK)
455 self.
btn_run = wx.Button(parent = self.
panel, id = wx.ID_OK, label = _(
"&Run"))
456 self.btn_run.SetToolTipString(_(
"Run the command (Ctrl+R)"))
457 self.btn_run.SetDefault()
458 self.btn_run.SetForegroundColour(wx.Colour(35, 142, 35))
462 self.btn_clipboard.SetToolTipString(_(
"Copy the current command string to the clipboard (Ctrl+C)"))
464 btnsizer.Add(item = self.
btn_run, proportion = 0,
465 flag = wx.ALL | wx.ALIGN_CENTER,
469 flag = wx.ALL | wx.ALIGN_CENTER,
472 self.btn_run.Bind(wx.EVT_BUTTON, self.
OnRun)
473 self.btn_clipboard.Bind(wx.EVT_BUTTON, self.
OnCopy)
476 self.btn_help.SetToolTipString(_(
"Show manual page of the command (Ctrl+H)"))
477 self.btn_help.Bind(wx.EVT_BUTTON, self.
OnHelp)
478 if self.notebookpanel.notebook.GetPageIndexByName(
'manual') < 0:
482 btnsizer.Add(item = self.
btn_help, proportion = 0, flag = wx.ALL | wx.ALIGN_CENTER, border = 10)
484 guisizer.Add(item = btnsizer, proportion = 0, flag = wx.ALIGN_CENTER | wx.LEFT | wx.RIGHT,
489 for p
in self.task.params:
490 if p.get(
'age',
'old') ==
'new' and \
491 p.get(
'prompt',
'')
in (
'raster',
'vector',
'3d-raster'):
497 label = _(
'Add created map(s) into layer tree'), style = wx.NO_BORDER)
498 self.addbox.SetValue(UserSettings.Get(group =
'cmd', key =
'addNewLayer', subkey =
'enabled'))
499 guisizer.Add(item = self.
addbox, proportion = 0,
500 flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
504 for p
in self.task.params:
505 if p.get(
'age',
'old') ==
'new':
509 if self.
get_dcmd is None and hasNew:
512 label = _(
'Close dialog on finish'), style = wx.NO_BORDER)
513 self.closebox.SetValue(UserSettings.Get(group =
'cmd', key =
'closeDlg', subkey =
'enabled'))
514 self.closebox.SetToolTipString(_(
"Close dialog when command is successfully finished. "
515 "Change this settings in Preferences dialog ('Command' tab)."))
516 guisizer.Add(item = self.
closebox, proportion = 0,
517 flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
520 self.Bind(wx.EVT_CLOSE, self.
OnCancel)
521 self.Bind(wx.EVT_KEY_UP, self.
OnKeyUp)
525 self.panel.SetAutoLayout(
True)
526 self.panel.SetSizerAndFit(guisizer)
528 sizeFrame = self.GetBestSize()
529 self.SetMinSize(sizeFrame)
530 self.SetSize(wx.Size(sizeFrame[0], sizeFrame[1] + 0.33 *
max(self.notebookpanel.panelMinHeight,
531 self.notebookpanel.constrained_size[1])))
542 width, height = self.GetSizeTuple()
543 self.SetSize(wx.Size(
min(width, 650),
548 self.goutput.SetSashPosition(int(self.GetSize()[1] * .75))
551 """!Update status bar data"""
552 self.SetStatusText(
' '.join(self.notebookpanel.createCmd(ignoreErrors =
True)))
557 """!Key released (check hot-keys)"""
559 kc = chr(event.GetKeyCode())
564 if not event.ControlDown():
582 """!This function is launched from OnRun() when command is
585 @param returncode command's return code (0 for success)
587 if not self.
parent or returncode != 0:
589 if self.parent.GetName()
not in (
'LayerTree',
'LayerManager'):
592 if self.parent.GetName() ==
'LayerTree':
593 display = self.parent.GetMapDisplay()
596 tree = self.parent.GetLayerTree()
598 display = tree.GetMapDisplay()
600 if not display
or not display.IsAutoRendered():
603 mapLayers = map(
lambda x: x.GetName(),
604 display.GetMap().GetListOfLayers(l_type =
'raster') +
605 display.GetMap().GetListOfLayers(l_type =
'vector'))
607 task =
GUI(show =
None).ParseCommand(cmd)
608 for p
in task.get_options()[
'params']:
609 if p.get(
'prompt',
'')
not in (
'raster',
'vector'):
611 mapName = p.get(
'value',
'')
612 if '@' not in mapName:
613 mapName = mapName +
'@' + grass.gisenv()[
'MAPSET']
614 if mapName
in mapLayers:
615 display.GetWindow().UpdateMap(render =
True)
619 """!OK button pressed"""
621 if cmd
is not None and self.
get_dcmd is not None:
625 """!Apply the command"""
627 cmd = self.
createCmd(ignoreErrors =
True, ignoreRequired =
True)
631 if cmd
is not None and self.
get_dcmd is not None:
634 "flags" : self.task.flags},
642 """!Run the command"""
645 if not cmd
or len(cmd) < 1:
651 self.notebookpanel.notebook.SetSelectionByName(
'output')
655 self.goutput.RunCmd(cmd, onDone = self.
OnDone)
656 except AttributeError, e:
657 print >> sys.stderr,
"%s: Probably not running in wxgui.py session?" % (e)
658 print >> sys.stderr,
"parent window is: %s" % (str(self.
parent))
670 """!Abort running command"""
672 event = wxCmdAbort(aborted =
True)
673 wx.PostEvent(self.
goutput, event)
676 """!Copy the command"""
677 cmddata = wx.TextDataObject()
679 cmdstring =
' '.join(self.
createCmd(ignoreErrors =
True))
680 cmddata.SetText(cmdstring)
681 if wx.TheClipboard.Open():
683 wx.TheClipboard.SetData(cmddata)
684 wx.TheClipboard.Close()
685 self.SetStatusText(_(
"'%s' copied to clipboard") % \
689 """!Cancel button pressed"""
690 self.MakeModal(
False)
694 self.parent.GetName()
in (
'LayerTree',
698 if self.task.name
in [
'd.barscale',
'd.legend',
'd.histogram'] \
699 or len(self.parent.GetPyData(self.
layer)[0][
'cmd']) >= 1:
702 elif len(self.parent.GetPyData(self.
layer)[0][
'cmd']) < 1:
703 self.parent.Delete(self.
layer)
710 """!Show manual page (switch to the 'Manual' notebook page)"""
711 if self.notebookpanel.notebook.GetPageIndexByName(
'manual') > -1:
712 self.notebookpanel.notebook.SetSelectionByName(
'manual')
713 self.notebookpanel.OnPageChange(
None)
718 def createCmd(self, ignoreErrors = False, ignoreRequired = False):
719 """!Create command string (python list)"""
720 return self.notebookpanel.createCmd(ignoreErrors = ignoreErrors,
721 ignoreRequired = ignoreRequired)
724 """!A panel containing a notebook dividing in tabs the different
725 guisections of the GRASS cmd.
727 def __init__(self, parent, task, id = wx.ID_ANY, frame = None, *args, **kwargs):
734 wx.Panel.__init__(self, parent, id = id, *args, **kwargs)
739 not_hidden = [ p
for p
in self.task.params + self.task.flags
if not p.get(
'hidden',
False) ==
True ]
743 self.Bind(wx.EVT_SIZE, self.
OnSize)
745 for task
in not_hidden:
746 if task.get(
'required',
False):
748 task[
'guisection'] = _(
'Required')
749 if task.get(
'guisection',
'') ==
'':
751 task[
'guisection'] = _(
'Optional')
752 if task[
'guisection']
not in is_section:
754 is_section[task[
'guisection']] = 1
755 sections.append(task[
'guisection'])
757 is_section[ task[
'guisection'] ] += 1
761 for (newidx,content)
in [ (0,_(
'Required')), (len(sections)-1,_(
'Optional')) ]:
762 if content
in sections:
763 idx = sections.index(content)
764 sections[idx:idx+1] = []
765 sections[newidx:newidx] = [content]
767 panelsizer = wx.BoxSizer(orient = wx.VERTICAL)
770 self.
notebook = GNotebook(self, style = globalvar.FNPageStyle | FN.FNB_NO_X_BUTTON )
771 self.notebook.SetTabAreaColour(globalvar.FNPageColor)
772 self.notebook.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.
OnPageChange)
776 for section
in sections:
777 tab[section] = ScrolledPanel(parent = self.
notebook)
778 tab[section].SetScrollRate(10, 10)
779 tabsizer[section] = wx.BoxSizer(orient = wx.VERTICAL)
780 self.notebook.AddPage(page = tab[section], text = section)
784 if self.parent.GetName() ==
"MainFrame" and self.parent.get_dcmd
is None:
786 self.
goutput = GMConsole(parent = self, margin =
False)
787 self.
outpage = self.notebook.AddPage(page = self.
goutput, text = _(
"Command output"), name =
'output')
791 self.
manual_tab = HelpPanel(parent = self, grass_command = self.task.name)
792 if not self.manual_tab.GetFile():
793 self.manual_tab.Hide()
795 self.notebook.AddPage(page = self.
manual_tab, text = _(
"Manual"), name =
'manual')
797 self.notebook.SetSelection(0)
799 panelsizer.Add(item = self.
notebook, proportion = 1, flag = wx.EXPAND)
804 text_style = wx.FONTWEIGHT_NORMAL
805 visible_flags = [ f
for f
in self.task.flags
if not f.get(
'hidden',
False) ==
True ]
806 for f
in visible_flags:
807 which_sizer = tabsizer[ f[
'guisection'] ]
808 which_panel = tab[ f[
'guisection'] ]
810 if f.get(
'label',
'') !=
'':
816 title_sizer = wx.BoxSizer(wx.HORIZONTAL)
817 rtitle_txt = wx.StaticText(parent = which_panel,
818 label =
'(' + f[
'name'] +
')')
819 chk = wx.CheckBox(parent = which_panel, label = title, style = wx.NO_BORDER)
820 self.label_id.append(chk.GetId())
822 chk.SetToolTipString(tooltip)
823 chk.SetValue(f.get(
'value',
False))
824 title_sizer.Add(item = chk, proportion = 1,
826 title_sizer.Add(item = rtitle_txt, proportion = 0,
827 flag = wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL)
828 which_sizer.Add(item = title_sizer, proportion = 0,
829 flag = wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, border = 5)
830 f[
'wxId'] = [ chk.GetId(), ]
833 if self.parent.GetName() ==
'MainFrame' and self.parent.modeler:
834 parChk = wx.CheckBox(parent = which_panel, id = wx.ID_ANY,
835 label = _(
"Parameterized in model"))
836 parChk.SetName(
'ModelParam')
837 parChk.SetValue(f.get(
'parameterized',
False))
839 f[
'wxId'].append(parChk.GetId())
841 f[
'wxId'] = [ parChk.GetId() ]
843 which_sizer.Add(item = parChk, proportion = 0,
844 flag = wx.LEFT, border = 20)
846 if f[
'name']
in (
'verbose',
'quiet'):
848 vq = UserSettings.Get(group =
'cmd', key =
'verbosity', subkey =
'selection')
852 elif f[
'name'] ==
'overwrite' and 'value' not in f:
853 chk.SetValue(UserSettings.Get(group =
'cmd', key =
'overwrite', subkey =
'enabled'))
854 f[
'value'] = UserSettings.Get(group =
'cmd', key =
'overwrite', subkey =
'enabled')
859 visible_params = [ p
for p
in self.task.params
if not p.get(
'hidden',
False) ==
True ]
862 first_param = visible_params[0]
866 for p
in visible_params:
867 which_sizer = tabsizer[ p[
'guisection'] ]
868 which_panel = tab[ p[
'guisection'] ]
871 if p.get(
'label',
'') !=
'':
880 if not p.get(
'required',
False):
881 text_style = wx.FONTWEIGHT_NORMAL
883 text_style = wx.FONTWEIGHT_BOLD
886 if (len(p.get(
'values', [])) > 0)
and \
887 p.get(
'multiple',
False)
and \
888 p.get(
'gisprompt',
False) ==
False and \
889 p.get(
'type',
'') ==
'string':
890 title_txt = wx.StaticBox(parent = which_panel, id = wx.ID_ANY)
892 title_sizer = wx.BoxSizer(wx.HORIZONTAL)
893 title_txt = wx.StaticText(parent = which_panel)
895 ltype =
','.join(p[
'key_desc'])
898 rtitle_txt = wx.StaticText(parent = which_panel,
899 label =
'(' + p[
'name'] +
'=' + ltype +
')')
900 title_sizer.Add(item = title_txt, proportion = 1,
901 flag = wx.LEFT | wx.TOP | wx.EXPAND, border = 5)
902 title_sizer.Add(item = rtitle_txt, proportion = 0,
903 flag = wx.ALIGN_RIGHT | wx.RIGHT | wx.TOP, border = 5)
904 which_sizer.Add(item = title_sizer, proportion = 0,
906 self.label_id.append(title_txt.GetId())
909 if p.get(
'multiple',
False)
and len(p.get(
'values',
'')) == 0:
910 title = _(
"[multiple]") +
" " + title
911 if p.get(
'value',
'') ==
'' :
912 p[
'value'] = p.get(
'default',
'')
914 if (len(p.get(
'values', [])) > 0):
915 valuelist = map(str, p.get(
'values',[]))
916 valuelist_desc = map(unicode, p.get(
'values_desc',[]))
918 if p.get(
'multiple',
False)
and \
919 p.get(
'gisprompt',
False) ==
False and \
920 p.get(
'type',
'') ==
'string':
921 title_txt.SetLabel(
" %s: (%s, %s) " % (title, p[
'name'], p[
'type']))
923 hSizer = wx.StaticBoxSizer(box = title_txt, orient = wx.VERTICAL)
925 hSizer = wx.StaticBoxSizer(box = title_txt, orient = wx.HORIZONTAL)
929 p[
'value'] = p.get(
'default',
'')
931 for defval
in p.get(
'value',
'').
split(
','):
932 isEnabled[ defval ] =
'yes'
937 for val
in valuelist:
939 label = valuelist_desc[idx]
943 chkbox = wx.CheckBox(parent = which_panel,
945 p[
'wxId' ].append(chkbox.GetId())
947 chkbox.SetValue(
True)
948 hSizer.Add(item = chkbox, proportion = 0,
949 flag = wx.ADJUST_MINSIZE | wx.ALL, border = 1)
953 which_sizer.Add(item = hSizer, proportion = 0,
954 flag = wx.EXPAND | wx.TOP | wx.RIGHT | wx.LEFT, border = 5)
955 elif p.get(
'gisprompt',
False) ==
False:
956 if len(valuelist) == 1:
957 title_txt.SetLabel(
"%s (%s %s):" % (title, _(
'valid range'),
960 if p.get(
'type',
'') ==
'integer' and \
961 not p.get(
'multiple',
False):
965 minValue, maxValue = map(int, valuelist[0].
split(
'-'))
969 txt2 = wx.SpinCtrl(parent = which_panel, id = wx.ID_ANY, size = globalvar.DIALOG_SPIN_SIZE,
970 min = minValue, max = maxValue)
971 txt2.SetName(
"SpinCtrl")
972 style = wx.BOTTOM | wx.LEFT
974 txt2 = wx.TextCtrl(parent = which_panel, value = p.get(
'default',
''))
975 txt2.SetName(
"TextCtrl")
976 style = wx.EXPAND | wx.BOTTOM | wx.LEFT
981 if txt2.GetName() ==
"SpinCtrl":
982 txt2.SetValue(int(value))
986 which_sizer.Add(item = txt2, proportion = 0,
987 flag = style, border = 5)
989 p[
'wxId'] = [ txt2.GetId(), ]
992 title_txt.SetLabel(title +
':')
995 if p[
'name'] ==
'icon':
996 bitmap = wx.Bitmap(os.path.join(globalvar.ETCSYMBOLDIR, value) +
'.png')
997 bb = wx.BitmapButton(parent = which_panel, id = wx.ID_ANY,
999 iconLabel = wx.StaticText(parent = which_panel, id = wx.ID_ANY)
1000 iconLabel.SetLabel(value)
1002 p[
'wxId'] = [bb.GetId(), iconLabel.GetId()]
1004 this_sizer = wx.BoxSizer(wx.HORIZONTAL)
1005 this_sizer.Add(item = bb, proportion = 0,
1006 flag = wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT, border = 5)
1007 this_sizer.Add(item = iconLabel, proportion = 0,
1008 flag = wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT | wx.ALIGN_CENTER_VERTICAL, border = 5)
1009 which_sizer.Add(item = this_sizer, proportion = 0,
1010 flag = wx.ADJUST_MINSIZE, border = 0)
1013 cb = wx.ComboBox(parent = which_panel, id = wx.ID_ANY, value = p.get(
'default',
''),
1014 size = globalvar.DIALOG_COMBOBOX_SIZE,
1015 choices = valuelist, style = wx.CB_DROPDOWN)
1018 which_sizer.Add(item = cb, proportion = 0,
1019 flag = wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT, border = 5)
1020 p[
'wxId'] = [cb.GetId(),]
1025 if (p.get(
'type',
'string')
in (
'string',
'integer',
'float')
1026 and len(p.get(
'values',[])) == 0
1027 and p.get(
'gisprompt',
False) ==
False
1028 and p.get(
'prompt',
'') !=
'color'):
1030 title_txt.SetLabel(title +
':')
1031 if p.get(
'multiple',
False)
or \
1032 p.get(
'type',
'string') ==
'string' or \
1033 len(p.get(
'key_desc', [])) > 1:
1034 txt3 = wx.TextCtrl(parent = which_panel, value = p.get(
'default',
''))
1039 txt3.SetValue(str(value))
1042 style = wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT
1046 if p.get(
'type',
'') ==
'integer':
1047 txt3 = wx.SpinCtrl(parent = which_panel, value = p.get(
'default',
''),
1048 size = globalvar.DIALOG_SPIN_SIZE,
1049 min = minValue, max = maxValue)
1050 style = wx.BOTTOM | wx.LEFT | wx.RIGHT
1054 txt3.SetValue(int(value))
1058 txt3 = wx.TextCtrl(parent = which_panel, value = p.get(
'default',
''),
1059 validator = FloatValidator())
1060 style = wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT
1064 txt3.SetValue(str(value))
1068 which_sizer.Add(item = txt3, proportion = 0,
1069 flag = style, border = 5)
1070 p[
'wxId'] = [ txt3.GetId(), ]
1075 if p.get(
'gisprompt',
False) ==
True:
1076 title_txt.SetLabel(title +
':')
1078 if p.get(
'prompt',
'')
not in (
'color',
1091 p.get(
'element',
'') !=
'file':
1092 multiple = p.get(
'multiple',
False)
1093 if p.get(
'age',
'') ==
'new':
1094 mapsets = [grass.gisenv()[
'MAPSET'],]
1097 if self.task.name
in (
'r.proj',
'v.proj') \
1098 and p.get(
'name',
'') ==
'input':
1099 if self.task.name ==
'r.proj':
1104 isRaster = isRaster)
1105 p[
'wxId'] = [ selection.GetId(), ]
1106 selection.Bind(wx.EVT_COMBOBOX, self.
OnSetValue)
1110 size = globalvar.DIALOG_GSELECT_SIZE,
1111 type = p.get(
'element',
''),
1112 multiple = multiple, mapsets = mapsets,
1113 fullyQualified = p.get(
'age',
'old') ==
'old')
1118 textWin = selection.GetTextCtrl()
1119 p[
'wxId'] = [ textWin.GetId(), ]
1124 selection.SetValue(value)
1126 which_sizer.Add(item=selection, proportion=0,
1127 flag=wx.ADJUST_MINSIZE| wx.BOTTOM | wx.LEFT | wx.RIGHT, border=5)
1129 if p.get(
'prompt',
'')
in (
'vector',
'group'):
1132 elif p.get(
'prompt',
'') ==
'subgroup':
1134 p[
'wxId'] = [ selection.GetId() ]
1135 selection.Bind(wx.EVT_COMBOBOX, self.
OnSetValue)
1137 which_sizer.Add(item = selection, proportion = 0,
1138 flag = wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT | wx.RIGHT | wx.TOP | wx.ALIGN_CENTER_VERTICAL,
1142 elif p.get(
'prompt',
'')
in (
'dbdriver',
1152 if p.get(
'multiple',
'no') ==
'yes':
1153 win = wx.TextCtrl(parent = which_panel, value = p.get(
'default',
''),
1154 size = globalvar.DIALOG_TEXTCTRL_SIZE)
1159 if p.get(
'prompt',
'')
in (
'layer',
1163 if p.get(
'age',
'old_layer') ==
'old_layer':
1165 if p.get(
'prompt',
'') ==
'layer_all':
1166 initial.insert(0,
'-1')
1167 elif p.get(
'prompt',
'') ==
'layer_zero':
1168 initial.insert(0,
'0')
1169 lyrvalue = p.get(
'default')
1171 if lyrvalue
not in initial:
1172 initial.append(str(lyrvalue))
1173 lyrvalue = p.get(
'value')
1175 if lyrvalue
not in initial:
1176 initial.append(str(lyrvalue))
1180 default = p[
'default'])
1181 p[
'wxGetValue'] = win.GetStringSelection
1184 win.SetValue(str(value))
1186 win = wx.SpinCtrl(parent = which_panel, id = wx.ID_ANY,
1187 min = 1, max = 100, initial = int(p[
'default']))
1189 win.SetValue(int(value))
1191 elif p.get(
'prompt',
'') ==
'dbdriver':
1193 choices = p.get(
'values', []),
1195 p[
'wxGetValue'] = win.GetStringSelection
1198 elif p.get(
'prompt',
'') ==
'dbname':
1204 elif p.get(
'prompt',
'') ==
'dbtable':
1205 if p.get(
'age',
'old_dbtable') ==
'old_dbtable':
1208 p[
'wxGetValue'] = win.GetStringSelection
1212 win = wx.TextCtrl(parent = which_panel, value = p.get(
'default',
''),
1213 size = globalvar.DIALOG_TEXTCTRL_SIZE)
1215 elif p.get(
'prompt',
'') ==
'dbcolumn':
1222 elif p.get(
'prompt',
'') ==
'location':
1228 elif p.get(
'prompt',
'') ==
'mapset':
1234 elif p.get(
'prompt',
'') ==
'dbase':
1238 p[
'wxId'] = [ win.GetChildren()[1].GetId() ]
1242 p[
'wxId'] = [ win.GetId(), ]
1243 except AttributeError:
1246 which_sizer.Add(item = win, proportion = 0,
1247 flag = wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT, border = 5)
1249 elif p.get(
'prompt',
'')
in (
'color',
1251 default_color = (200,200,200)
1252 label_color = _(
"Select Color")
1253 if p.get(
'default',
'') !=
'':
1255 if p.get(
'value',
'') !=
'' and p.get(
'value',
'') !=
'none':
1257 if p.get(
'prompt',
'') ==
'color_none' or p.get(
'multiple',
False):
1258 this_sizer = wx.BoxSizer(orient = wx.HORIZONTAL)
1260 this_sizer = which_sizer
1265 p[
'wxId'] = [
None] * 3
1266 if p.get(
'multiple',
False):
1267 txt = wx.TextCtrl(parent = which_panel, id = wx.ID_ANY)
1268 this_sizer.Add(item = txt, proportion = 1,
1269 flag = wx.ADJUST_MINSIZE | wx.LEFT | wx.TOP, border = 5)
1273 p[
'wxId'][1] = txt.GetId()
1274 which_sizer.Add(this_sizer, flag = wx.EXPAND | wx.RIGHT, border = 5)
1276 btn_colour = csel.ColourSelect(parent = which_panel, id = wx.ID_ANY,
1277 label = label_color, colour = default_color,
1278 pos = wx.DefaultPosition, size = (colorSize,-1))
1279 this_sizer.Add(item = btn_colour, proportion = 0,
1280 flag = wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT, border = 5)
1282 p[
'wxId'][0] = btn_colour.GetId()
1284 if p.get(
'prompt',
'') ==
'color_none':
1285 none_check = wx.CheckBox(which_panel, wx.ID_ANY, _(
"Transparent"))
1286 if p.get(
'value',
'') !=
'' and p.get(
'value',[
''])[0] ==
"none":
1287 none_check.SetValue(
True)
1289 none_check.SetValue(
False)
1290 this_sizer.Add(item = none_check, proportion = 0,
1291 flag = wx.ADJUST_MINSIZE | wx.LEFT | wx.RIGHT | wx.TOP, border = 5)
1292 which_sizer.Add(this_sizer)
1294 p[
'wxId'][2] = none_check.GetId()
1297 elif p.get(
'prompt',
'') !=
'color' and p.get(
'element',
'') ==
'file':
1298 if p.get(
'age',
'new_file') ==
'new_file':
1302 fbb = filebrowse.FileBrowseButton(parent = which_panel, id = wx.ID_ANY, fileMask =
'*',
1303 size = globalvar.DIALOG_GSELECT_SIZE, labelText =
'',
1304 dialogTitle = _(
'Choose %s') % \
1305 p.get(
'description',_(
'File')),
1306 buttonText = _(
'Browse'),
1307 startDirectory = os.getcwd(), fileMode = fmode,
1312 which_sizer.Add(item = fbb, proportion = 0,
1313 flag = wx.EXPAND | wx.RIGHT, border = 5)
1318 p[
'wxId'] = [ fbb.GetChildren()[1].GetId() ]
1319 if p.get(
'age',
'new_file') ==
'old_file' and \
1320 UserSettings.Get(group=
'cmd', key=
'interactiveInput', subkey=
'enabled'):
1322 ifbb = wx.TextCtrl(parent = which_panel, id = wx.ID_ANY,
1323 style = wx.TE_MULTILINE,
1325 if p.get(
'value',
'')
and os.path.isfile(p[
'value']):
1326 f = open(p[
'value'])
1327 ifbb.SetValue(
''.join(f.readlines()))
1332 btnLoad = wx.Button(parent = which_panel, id = wx.ID_ANY, label = _(
"&Load"))
1334 btnSave = wx.Button(parent = which_panel, id = wx.ID_SAVEAS)
1337 which_sizer.Add(item = wx.StaticText(parent = which_panel, id = wx.ID_ANY,
1338 label = _(
'or enter values interactively')),
1340 flag = wx.EXPAND | wx.RIGHT | wx.LEFT | wx.BOTTOM, border = 5)
1341 which_sizer.Add(item = ifbb, proportion = 1,
1342 flag = wx.EXPAND | wx.RIGHT | wx.LEFT, border = 5)
1343 btnSizer = wx.BoxSizer(wx.HORIZONTAL)
1344 btnSizer.Add(item = btnLoad, proportion = 0,
1345 flag = wx.ALIGN_RIGHT | wx.RIGHT, border = 10)
1346 btnSizer.Add(item = btnSave, proportion = 0,
1347 flag = wx.ALIGN_RIGHT)
1348 which_sizer.Add(item = btnSizer, proportion = 0,
1349 flag = wx.ALIGN_RIGHT | wx.RIGHT | wx.TOP, border = 5)
1351 p[
'wxId'].append(ifbb.GetId())
1352 p[
'wxId'].append(btnLoad.GetId())
1353 p[
'wxId'].append(btnSave.GetId())
1355 if self.parent.GetName() ==
'MainFrame' and self.parent.modeler:
1356 parChk = wx.CheckBox(parent = which_panel, id = wx.ID_ANY,
1357 label = _(
"Parameterized in model"))
1358 parChk.SetName(
'ModelParam')
1359 parChk.SetValue(p.get(
'parameterized',
False))
1361 p[
'wxId'].append(parChk.GetId())
1363 p[
'wxId'] = [ parChk.GetId() ]
1364 parChk.Bind(wx.EVT_CHECKBOX, self.
OnSetValue)
1365 which_sizer.Add(item = parChk, proportion = 0,
1366 flag = wx.LEFT, border = 20)
1368 if title_txt
is not None:
1370 if len(p[
'values_desc']) > 0:
1372 tooltip += 2 * os.linesep
1375 if len(p[
'values']) == len(p[
'values_desc']):
1376 for i
in range(len(p[
'values'])):
1377 tooltip += p[
'values'][i] +
': ' + p[
'values_desc'][i] + os.linesep
1378 tooltip.strip(os.linesep)
1380 title_txt.SetToolTipString(tooltip)
1382 if p == first_param:
1383 if 'wxId' in p
and len(p[
'wxId']) > 0:
1384 win = self.FindWindowById(p[
'wxId'][0])
1401 for p
in self.task.params:
1402 if p.get(
'gisprompt',
False) ==
False:
1405 prompt = p.get(
'element',
'')
1406 if prompt
in (
'cell',
'vector'):
1407 name = p.get(
'name',
'')
1408 if name
in (
'map',
'input'):
1410 elif prompt ==
'layer':
1412 elif prompt ==
'dbcolumn':
1414 elif prompt ==
'dbdriver':
1416 elif prompt ==
'dbname':
1418 elif prompt ==
'dbtable':
1420 elif prompt ==
'group':
1422 elif prompt ==
'subgroup':
1424 elif prompt ==
'dbase':
1426 elif prompt ==
'location':
1428 elif prompt ==
'mapset':
1433 pColumnIds += p[
'wxId']
1436 pLayerIds += p[
'wxId']
1439 pMap[
'wxId-bind'] = copy.copy(pColumnIds)
1441 pMap[
'wxId-bind'] += pLayerIds
1444 p[
'wxId-bind'] = copy.copy(pColumnIds)
1446 if pDriver
and pTable:
1447 pDriver[
'wxId-bind'] = pTable[
'wxId']
1449 if pDatabase
and pTable:
1450 pDatabase[
'wxId-bind'] = pTable[
'wxId']
1452 if pTable
and pColumnIds:
1453 pTable[
'wxId-bind'] = pColumnIds
1455 if pGroup
and pSubGroup:
1456 pGroup[
'wxId-bind'] = pSubGroup[
'wxId']
1458 if pDbase
and pLocation:
1459 pDbase[
'wxId-bind'] = pLocation[
'wxId']
1461 if pLocation
and pMapset:
1462 pLocation[
'wxId-bind'] = pMapset[
'wxId']
1464 if pLocation
and pMapset
and pMap:
1465 pLocation[
'wxId-bind'] += pMap[
'wxId']
1466 pMapset[
'wxId-bind'] = pMap[
'wxId']
1472 for section
in sections:
1473 tab[section].SetSizer(tabsizer[section])
1474 tabsizer[section].Fit(tab[section])
1475 tab[section].Layout()
1476 minsecsizes = tabsizer[section].GetSize()
1477 maxsizes = map(
lambda x:
max(maxsizes[x], minsecsizes[x]), (0, 1))
1482 for section
in sections:
1485 if self.manual_tab.IsLoaded():
1488 self.SetSizer(panelsizer)
1493 def _getValue(self, p):
1494 """!Get value or default value of given parameter
1496 @param p parameter directory
1498 if p.get(
'value',
'') !=
'':
1500 return p.get(
'default',
'')
1503 """!Load file to interactive input"""
1506 for p
in self.task.params:
1507 if 'wxId' in p
and me
in p[
'wxId']:
1508 win[
'file'] = self.FindWindowById(p[
'wxId'][0])
1509 win[
'text'] = self.FindWindowById(p[
'wxId'][1])
1518 message = _(
"Nothing to load."))
1531 """!Save interactive input to the file"""
1534 for p
in self.task.params:
1535 if wId
in p.get(
'wxId', []):
1536 win[
'file'] = self.FindWindowById(p[
'wxId'][0])
1537 win[
'text'] = self.FindWindowById(p[
'wxId'][1])
1546 message = _(
"Nothing to save."))
1549 dlg = wx.FileDialog(parent = self,
1550 message = _(
"Save input as..."),
1551 defaultDir = os.getcwd(),
1552 style = wx.SAVE | wx.FD_OVERWRITE_PROMPT)
1554 if dlg.ShowModal() == wx.ID_OK:
1555 path = dlg.GetPath()
1558 f.write(text + os.linesep)
1567 """File input interactively entered"""
1568 text = event.GetString()
1569 p = self.task.get_param(value = event.GetId(), element =
'wxId', raiseError =
False)
1572 win = self.FindWindowById(p[
'wxId'][0])
1574 filename = win.GetValue()
1577 filename = grass.tempfile()
1578 win.SetValue(filename)
1580 f = open(filename,
"w")
1583 if text[-1] != os.linesep:
1591 for fn, kwargs
in event.data.iteritems():
1594 self.parent.updateValuesHook()
1597 """!Verbosity level changed"""
1598 verbose = self.FindWindowById(self.task.get_flag(
'verbose')[
'wxId'][0])
1599 quiet = self.FindWindowById(self.task.get_flag(
'quiet')[
'wxId'][0])
1600 if event.IsChecked():
1601 if event.GetId() == verbose.GetId():
1602 if quiet.IsChecked():
1603 quiet.SetValue(
False)
1604 self.task.get_flag(
'quiet')[
'value'] =
False
1606 if verbose.IsChecked():
1607 verbose.SetValue(
False)
1608 self.task.get_flag(
'verbose')[
'value'] =
False
1614 sel = self.notebook.GetSelection()
1616 sel = event.GetSelection()
1618 idx = self.notebook.GetPageIndexByName(
'manual')
1619 if idx > -1
and sel == idx:
1622 if not self.manual_tab.IsLoaded():
1624 self.manual_tab.LoadPage()
1629 myId = event.GetId()
1630 for p
in self.task.params:
1631 if 'wxId' in p
and myId
in p[
'wxId']:
1632 multiple = p[
'wxId'][1]
is not None
1633 hasTransp = p[
'wxId'][2]
is not None
1636 colorchooser = wx.FindWindowById(p[
'wxId'][0])
1637 new_color = colorchooser.GetValue()[:]
1638 new_label = rgb2str.get(new_color,
':'.join(map(str, new_color)))
1639 textCtrl = wx.FindWindowById(p[
'wxId'][1])
1640 val = textCtrl.GetValue()
1642 if val
and val[-1] != sep:
1645 textCtrl.SetValue(val)
1647 elif hasTransp
and wx.FindWindowById(p[
'wxId'][2]).
GetValue():
1648 p[
'value' ] =
'none'
1650 colorchooser = wx.FindWindowById(p[
'wxId'][0])
1651 new_color = colorchooser.GetValue()[:]
1654 new_label = rgb2str.get(new_color,
':'.join(map(str,new_color)))
1655 colorchooser.SetLabel(new_label)
1656 colorchooser.SetColour(new_color)
1657 colorchooser.Refresh()
1658 p[
'value' ] = colorchooser.GetLabel()
1662 """!If we were part of a richer interface, report back the
1663 current command being built.
1665 This method should be set by the parent of this panel if
1666 needed. It's a hook, actually. Beware of what is 'self' in
1667 the method def, though. It will be called with no arguments.
1672 """!Fill the values as a ','-separated string according to
1673 current status of the checkboxes.
1677 for p
in self.task.params:
1678 if 'wxId' in p
and me
in p[
'wxId']:
1680 myIndex = p[
'wxId'].index(me)
1684 for isThere
in theParam.get(
'value',
'').
split(
','):
1685 currentValues[isThere] = 1
1686 theValue = theParam[
'values'][myIndex]
1689 currentValues[ theValue ] = 1
1691 del currentValues[ theValue ]
1694 currentValueList = []
1695 for v
in theParam[
'values']:
1696 if v
in currentValues:
1697 currentValueList.append(v)
1700 theParam[
'value'] =
','.join(currentValueList)
1702 self.OnUpdateValues()
1705 """!Retrieve the widget value and set the task value field
1708 Use for widgets that have a proper GetValue() method, i.e. not
1711 myId = event.GetId()
1712 me = wx.FindWindowById(myId)
1716 for porf
in self.task.params + self.task.flags:
1717 if 'wxId' not in porf:
1719 if myId
in porf[
'wxId']:
1726 if name
in (
'DriverSelect',
'TableSelect',
1727 'LocationSelect',
'MapsetSelect',
'ProjSelect'):
1728 porf[
'value'] = me.GetStringSelection()
1729 elif name ==
'GdalSelect':
1730 porf[
'value'] = event.dsn
1731 elif name ==
'ModelParam':
1732 porf[
'parameterized'] = me.IsChecked()
1733 elif name ==
'LayerSelect':
1734 porf[
'value'] = me.GetValue()
1736 porf[
'value'] = me.GetValue()
1743 """!Shows dialog for symbol selection"""
1744 myId = event.GetId()
1746 for p
in self.task.params:
1747 if 'wxId' in p
and myId
in p[
'wxId']:
1749 dlg = SymbolDialog(self, symbolPath = globalvar.ETCSYMBOLDIR,
1750 currentSymbol = p[
'value'])
1751 if dlg.ShowModal() == wx.ID_OK:
1752 img = dlg.GetSelectedSymbolPath()
1753 p[
'value'] = dlg.GetSelectedSymbolName()
1755 bitmapButton = wx.FindWindowById(p[
'wxId'][0])
1756 label = wx.FindWindowById(p[
'wxId'][1])
1758 bitmapButton.SetBitmapLabel(wx.Bitmap(img +
'.png'))
1759 label.SetLabel(p[
'value'])
1766 """!Update dialog (layers, tables, columns, etc.)
1768 if not hasattr(self.
parent,
"updateThread"):
1773 self.parent.updateThread.Update(UpdateDialog,
1779 self.parent.updateThread.Update(UpdateDialog,
1785 def createCmd(self, ignoreErrors = False, ignoreRequired = False):
1786 """!Produce a command line string (list) or feeding into GRASS.
1788 @param ignoreErrors True then it will return whatever has been
1789 built so far, even though it would not be a correct command
1793 cmd = self.task.get_cmd(ignoreErrors = ignoreErrors,
1794 ignoreRequired = ignoreRequired)
1795 except ValueError, err:
1796 dlg = wx.MessageDialog(parent = self,
1797 message = unicode(err),
1798 caption = _(
"Error in %s") % self.task.name,
1799 style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
1807 width = event.GetSize()[0]
1808 fontsize = self.GetFont().GetPointSize()
1809 text_width =
max(width / (fontsize - 3), 70)
1812 win = self.FindWindowById(id)
1813 label = win.GetLabel()
1814 label_new =
'\n'.join(textwrap.wrap(label, text_width))
1815 win.SetLabel(label_new)
1820 def __init__(self, parent = None, show = True, modal = False,
1821 centreOnParent =
False, checkError =
False):
1822 """!Parses GRASS commands when module is imported and used from
1836 _blackList[
'enabled'] =
True
1838 _blackList[
'enabled'] =
False
1841 """!Get validated command"""
1847 Note: cmd is given as list
1849 If command is given with options, return validated cmd list:
1850 - add key name for first parameter if not given
1851 - change mapname to mapname@mapset
1855 if completed ==
None:
1860 get_dcmd = completed[0]
1861 layer = completed[1]
1863 dcmd_params.update(completed[2])
1869 blackList = _blackList)
1870 except (grass.ScriptError, ValueError), e:
1874 if completed
is not None:
1875 if 'params' in dcmd_params:
1876 self.grass_task.params = dcmd_params[
'params']
1877 if 'flags' in dcmd_params:
1878 self.grass_task.flags = dcmd_params[
'flags']
1884 cmd_validated = [cmd[0]]
1885 for option
in cmd[1:]:
1886 if option[0] ==
'-':
1887 if option[1] ==
'-':
1888 self.grass_task.set_flag(option[2:],
True)
1890 self.grass_task.set_flag(option[1],
True)
1891 cmd_validated.append(option)
1894 key, value = option.split(
'=', 1)
1896 params = self.grass_task.get_options()[
'params']
1899 key = params[0][
'name']
1902 raise gcmd.GException, _(
"Unable to parse command '%s'") %
' '.join(cmd)
1906 element = self.grass_task.get_param(key, raiseError =
False)
1908 err.append(_(
"%(cmd)s: parameter '%(key)s' not available") % \
1912 element = element[
'element']
1914 if element
in [
'cell',
'vector']:
1916 if '@' not in value:
1917 mapset = grass.find_file(value, element)[
'mapset']
1918 curr_mapset = grass.gisenv()[
'MAPSET']
1919 if mapset
and mapset != curr_mapset:
1920 value = value +
'@' + mapset
1922 self.grass_task.set_param(key, value)
1923 cmd_validated.append(key +
'=' + value)
1929 if self.
show is not None:
1932 get_dcmd = get_dcmd, layer = layer)
1936 if get_dcmd
is not None:
1938 get_dcmd(dcmd =
None, layer = layer, params =
None,
1941 if self.
show is not None:
1942 self.mf.notebookpanel.OnUpdateSelection(
None)
1943 if self.
show is True:
1945 self.mf.CentreOnParent()
1947 self.mf.CenterOnScreen()
1948 self.mf.Show(self.
show)
1949 self.mf.MakeModal(self.
modal)
1951 self.mf.OnApply(
None)
1961 """!Get parameter key for input raster/vector map
1963 @param cmd module name
1965 @return parameter key
1966 @return None on failure
1970 enc = locale.getdefaultlocale()[1]
1971 if enc
and enc.lower() ==
"cp932":
1972 p = re.compile(
'encoding="' + enc +
'"', re.IGNORECASE)
1973 tree = etree.fromstring(p.sub(
'encoding="utf-8"',
1974 gtask.get_interface_description(cmd).
decode(enc).encode(
'utf-8')))
1976 tree = etree.fromstring(gtask.get_interface_description(cmd))
1977 self.
grass_task = gtask.processTask(tree).get_task()
1979 for p
in self.grass_task.params:
1980 if p.get(
'name',
'')
in (
'input',
'map'):
1981 age = p.get(
'age',
'')
1982 prompt = p.get(
'prompt',
'')
1983 element = p.get(
'element',
'')
1984 if age ==
'old' and \
1985 element
in (
'cell',
'grid3',
'vector')
and \
1986 prompt
in (
'raster',
'3d-raster',
'vector'):
1987 return p.get(
'name',
None)
1991 """!Stand-alone GRASS command GUI
1995 wx.App.__init__(self,
False)
1998 msg = self.grass_task.get_error_msg()
2000 gcmd.GError(msg +
'\n\nTry to set up GRASS_ADDON_PATH variable.')
2004 self.mf.CentreOnScreen()
2006 self.SetTopWindow(self.
mf)
2010 if __name__ ==
"__main__":
2012 gettext.install(
'grasswxpy', os.path.join(os.getenv(
"GISBASE"),
'locale'), unicode =
True)
2014 if len(sys.argv) == 1:
2015 sys.exit(_(
"usage: %s <grass command>") % sys.argv[0])
2017 if sys.argv[1] !=
'test':
2021 task.set_options(cmd[1:])
2026 if os.getenv(
"GISBASE")
is not None:
2027 task = gtask.grassTask(
"d.vect")
2028 task.get_param(
'map')[
'value'] =
"map_name"
2029 task.get_flag(
'v')[
'value'] =
True
2030 task.get_param(
'layer')[
'value'] = 1
2031 task.get_param(
'bcolor')[
'value'] =
"red"
2032 assert ' '.join(task.get_cmd()) ==
"d.vect -v map = map_name layer = 1 bcolor = red"
2035 task = gtask.grassTask()
2036 task.name =
"TestTask"
2037 task.description =
"This is an artificial grassTask() object intended for testing purposes."
2038 task.keywords = [
"grass",
"test",
"task"]
2042 "description" :
"Descriptions go into tooltips if labels are present, like this one",
2043 "label" :
"Enter some text",
2045 "name" :
"hidden_text",
2046 "description" :
"This text should not appear in the form",
2049 "name" :
"text_default",
2050 "description" :
"Enter text to override the default",
2051 "default" :
"default text"
2053 "name" :
"text_prefilled",
2054 "description" :
"You should see a friendly welcome message here",
2055 "value" :
"hello, world"
2057 "name" :
"plain_color",
2058 "description" :
"This is a plain color, and it is a compulsory parameter",
2063 "name" :
"transparent_color",
2064 "description" :
"This color becomes transparent when set to none",
2065 "guisection" :
"tab",
2070 "description" :
"A multiple selection",
2071 'default':
u'red,green,blue',
2073 'guisection':
'tab',
2077 'values': [
'red',
'green',
u'yellow',
u'blue',
u'purple',
u'other']
2080 "description" :
"A single multiple-choice selection",
2081 'values': [
'red',
'green',
u'yellow',
u'blue',
u'purple',
u'other'],
2082 "guisection" :
"tab"
2084 "name" :
"large_multi",
2085 "description" :
"A large multiple selection",
2086 "gisprompt" :
False,
2089 "values" : str2rgb.keys() + map(str, str2rgb.values())
2092 "description" :
"A file selector",
2100 "description" :
"Some flag, will appear in Main since it is required",
2104 "description" :
"pre-filled flag, will appear in options since it is not required",
2107 "name" :
"hidden_flag",
2108 "description" :
"hidden flag, should not be changeable",