3 @brief Construct simple wx.Python 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 Copyright(C) 2000-2011 by the GRASS Development Team
29 This program is free software under the GPL(>=v2) Read the file
30 COPYING coming with GRASS for details.
32 @author Jan-Oliver Wagner <jan@intevation.de>
33 @author Bernhard Reiter <bernhard@intevation.de>
34 @author Michael Barton, Arizona State University
35 @author Daniel Calvelo <dca.gis@gmail.com>
36 @author Martin Landa <landa.martin@gmail.com>
39 - verify option value types
51 from threading
import Thread
57 gettext.install(
'grasswxpy', os.path.join(os.getenv(
"GISBASE"),
'locale'), unicode =
True)
63 import wx.lib.agw.flatnotebook
as FN
65 import wx.lib.flatnotebook
as FN
66 import wx.lib.colourselect
as csel
67 import wx.lib.filebrowsebutton
as filebrowse
68 import wx.lib.scrolledpanel
as scrolled
69 from wx.lib.expando
import ExpandoTextCtrl, EVT_ETC_LAYOUT_NEEDED
70 from wx.lib.newevent
import NewEvent
73 import xml.etree.ElementTree
as etree
75 import elementtree.ElementTree
as etree
78 from ghelp
import HelpPanel
80 gisbase = os.getenv(
"GISBASE")
82 print >>sys.stderr,
"We don't seem to be properly installed, or we are being run outside GRASS. Expect glitches."
83 gisbase = os.path.join(os.path.dirname(sys.argv[0]), os.path.pardir)
86 wxbase = os.path.join(globalvar.ETCWXDIR)
88 sys.path.append(wxbase)
97 from preferences
import globalSettings
as UserSettings
101 from compat
import subprocess
103 wxUpdateDialog, EVT_DIALOG_UPDATE = NewEvent()
107 str2rgb = {
'aqua': (100, 128, 255),
110 'brown': (180, 77, 25),
111 'cyan': (0, 255, 255),
112 'gray': (128, 128, 128),
113 'green': (0, 255, 0),
114 'grey': (128, 128, 128),
115 'indigo': (0, 128, 255),
116 'magenta': (255, 0, 255),
117 'orange': (255, 128, 0),
118 'purple': (128, 0, 128),
120 'violet': (128, 0, 255),
121 'white': (255, 255, 255),
122 'yellow': (255, 255, 0)}
124 for (s,r)
in str2rgb.items():
127 """!Hide some options in the GUI"""
128 _blackList = {
'enabled' :
False,
129 'items' : {
'd.legend' : {
'flags' : [
'm'] } }
133 if len(color) > 0
and color[0]
in "0123456789":
134 rgb = tuple(
map(int, color.split(
':')))
139 rgb = str2rgb[ color ]
143 label = _(
'Select Color')
148 Make really long texts shorter, clean up whitespace and
149 remove trailing punctuation.
153 os.linesep.join(textwrap.wrap(utils.normalize_whitespace(someString), width)),
156 return escape_ampersand(string.strip(utils.normalize_whitespace(someString),
".,;:"))
159 """!Escapes ampersands with additional ampersand for GUI"""
160 return string.replace(text,
"&",
"&&")
163 """!Update dialog widgets in the thread"""
165 Thread.__init__(self)
179 for p
in self.task.params:
180 if p.get(
'gisprompt',
False) ==
False:
182 prompt = p.get(
'element',
'')
183 if prompt ==
'vector':
184 name = p.get(
'name',
'')
185 if name
in (
'map',
'input'):
190 p = self.task.get_param(self.
eventId, element =
'wxId', raiseError =
False)
191 if not p
or 'wxId-bind' not in p:
195 pType = p.get(
'prompt',
'')
200 pMap = self.task.get_param(
'map', raiseError =
False)
203 pMap = self.task.get_param(
'input', raiseError =
False)
206 map = pMap.get(
'value',
'')
212 cparams[map] = {
'dbInfo' :
None,
216 for uid
in p[
'wxId-bind']:
217 win = self.parent.FindWindowById(uid)
223 if name ==
'LayerSelect':
224 if map
in cparams
and not cparams[map][
'layers']:
225 win.InsertLayers(vector = map)
227 cparams[map][
'layers'] = win.GetItems()
229 elif name ==
'TableSelect':
230 pDriver = self.task.get_param(
'dbdriver', element=
'prompt', raiseError=
False)
233 driver = pDriver[
'value']
234 pDb = self.task.get_param(
'dbname', element=
'prompt', raiseError=
False)
238 self.
data[win.InsertTables] = {
'driver' : driver,
241 elif name ==
'ColumnSelect':
242 pLayer = self.task.get_param(
'layer', element=
'element', raiseError=
False)
244 if pLayer.get(
'value',
'') !=
'':
245 layer = pLayer.get(
'value',
'')
247 layer = pLayer.get(
'default',
'')
253 if not cparams[map][
'dbInfo']:
255 self.
data[win.InsertColumns] = {
'vector' : map,
'layer' : layer,
256 'dbInfo' : cparams[map][
'dbInfo'] }
259 pDriver = self.task.get_param(
'dbdriver', element=
'prompt', raiseError=
False)
261 driver = pDriver.get(
'value',
None)
262 pDb = self.task.get_param(
'dbname', element=
'prompt', raiseError=
False)
264 db = pDb.get(
'value',
None)
265 pTable = self.task.get_param(
'dbtable', element=
'element', raiseError=
False)
267 pTable.get(
'value',
'') !=
'':
269 self.
data[win.InsertTableColumns] = {
'table' : pTable.get(
'value'),
273 self.
data[win.InsertTableColumns] = {
'table' : pTable.get(
'value') }
275 elif name ==
'SubGroupSelect':
276 pGroup = self.task.get_param(
'group', element =
'element', raiseError =
False)
278 self.
data[win.Insert] = {
'group' : pGroup.get(
'value',
'')}
280 elif name ==
'LocationSelect':
281 pDbase = self.task.get_param(
'dbase', element =
'element', raiseError =
False)
283 self.
data[win.UpdateItems] = {
'dbase' : pDbase.get(
'value',
'')}
285 elif name ==
'MapsetSelect':
286 pDbase = self.task.get_param(
'dbase', element =
'element', raiseError =
False)
287 pLocation = self.task.get_param(
'location', element =
'element', raiseError =
False)
288 if pDbase
and pLocation:
289 self.
data[win.UpdateItems] = {
'dbase' : pDbase.get(
'value',
''),
290 'location' : pLocation.get(
'value',
'')}
292 elif name ==
'ProjSelect':
293 pDbase = self.task.get_param(
'dbase', element =
'element', raiseError =
False)
294 pLocation = self.task.get_param(
'location', element =
'element', raiseError =
False)
295 pMapset = self.task.get_param(
'mapset', element =
'element', raiseError =
False)
296 if pDbase
and pLocation
and pMapset:
297 self.
data[win.UpdateItems] = {
'dbase' : pDbase.get(
'value',
''),
298 'location' : pLocation.get(
'value',
''),
299 'mapset' : pMapset.get(
'value',
'')}
305 """!Update dialog widgets in the thread"""
307 def __init__(self, parent, requestQ, resultQ, **kwds):
308 Thread.__init__(self, **kwds)
318 def Update(self, callable, *args, **kwds):
319 UpdateQThread.requestId += 1
322 self.requestQ.put((UpdateQThread.requestId, callable, args, kwds))
324 return UpdateQThread.requestId
328 requestId, callable, args, kwds = self.requestQ.get()
330 requestTime = time.time()
332 self.
request = callable(*args, **kwds)
334 self.resultQ.put((requestId, self.request.run()))
337 event = wxUpdateDialog(data = self.request.data)
338 wx.PostEvent(self.
parent, event)
341 """!This is the Frame containing the dialog for options input.
343 The dialog is organized in a notebook according to the guisections
344 defined by each GRASS command.
346 If run with a parent, it may Apply, Ok or Cancel; the latter two
347 close the dialog. The former two trigger a callback.
349 If run standalone, it will allow execution of the command.
351 The command is checked and sent to the clipboard when clicking
354 def __init__(self, parent, ID, task_description,
355 get_dcmd =
None, layer =
None):
360 if parent
and parent.GetName() ==
'Modeler':
366 if self.task.name.split(
'.')[-1]
in (
'py',
'sh'):
367 title = str(self.task.name.rsplit(
'.',1)[0])
369 title = self.task.name
371 if self.task.keywords != [
'']:
372 title +=
" [" +
', '.join(self.task.keywords) +
"]"
376 wx.Frame.__init__(self, parent = parent, id = ID, title = title,
377 pos = wx.DefaultPosition, style = wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL,
380 self.
locale = wx.Locale(language = wx.LANGUAGE_DEFAULT)
382 self.
panel = wx.Panel(parent = self, id = wx.ID_ANY)
385 self.CreateStatusBar()
388 self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR,
'grass_dialog.ico'), wx.BITMAP_TYPE_ICO))
390 guisizer = wx.BoxSizer(wx.VERTICAL)
399 topsizer = wx.BoxSizer(wx.HORIZONTAL)
403 bitmap = wx.Bitmap(name = os.path.join(globalvar.ETCIMGDIR,
405 type = wx.BITMAP_TYPE_PNG))
406 topsizer.Add(item = self.
logo, proportion = 0, border = 3,
407 flag = wx.ALL | wx.ALIGN_CENTER_VERTICAL)
411 module_desc = self.task.label +
' ' + self.task.description
413 module_desc = self.task.description
416 topsizer.Add(item = self.
description, proportion = 1, border = 5,
417 flag = wx.ALL | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)
419 guisizer.Add(item = topsizer, proportion = 0, flag = wx.EXPAND)
421 self.panel.SetSizerAndFit(guisizer)
429 guisizer.Add(item = self.
notebookpanel, proportion = 1, flag = wx.EXPAND)
432 status_text = _(
"Enter parameters for '") + self.task.name +
"'"
437 self.SetStatusText(status_text)
440 btnsizer = wx.BoxSizer(orient = wx.HORIZONTAL)
443 self.btn_cancel.SetToolTipString(_(
"Close this window without executing the command (Ctrl+Q)"))
444 btnsizer.Add(item = self.
btn_cancel, proportion = 0, flag = wx.ALL | wx.ALIGN_CENTER, border = 10)
445 self.btn_cancel.Bind(wx.EVT_BUTTON, self.
OnCancel)
447 btn_apply = wx.Button(parent = self.
panel, id = wx.ID_APPLY)
448 btn_ok = wx.Button(parent = self.
panel, id = wx.ID_OK)
451 btnsizer.Add(item = btn_apply, proportion = 0,
452 flag = wx.ALL | wx.ALIGN_CENTER,
454 btnsizer.Add(item = btn_ok, proportion = 0,
455 flag = wx.ALL | wx.ALIGN_CENTER,
458 btn_apply.Bind(wx.EVT_BUTTON, self.
OnApply)
459 btn_ok.Bind(wx.EVT_BUTTON, self.
OnOK)
462 self.
btn_run = wx.Button(parent = self.
panel, id = wx.ID_OK, label = _(
"&Run"))
463 self.btn_run.SetToolTipString(_(
"Run the command (Ctrl+R)"))
464 self.btn_run.SetDefault()
467 self.btn_clipboard.SetToolTipString(_(
"Copy the current command string to the clipboard (Ctrl+C)"))
469 btnsizer.Add(item = self.
btn_run, proportion = 0,
470 flag = wx.ALL | wx.ALIGN_CENTER,
474 flag = wx.ALL | wx.ALIGN_CENTER,
477 self.btn_run.Bind(wx.EVT_BUTTON, self.
OnRun)
478 self.btn_clipboard.Bind(wx.EVT_BUTTON, self.
OnCopy)
481 self.btn_help.SetToolTipString(_(
"Show manual page of the command (Ctrl+H)"))
482 self.btn_help.Bind(wx.EVT_BUTTON, self.
OnHelp)
483 if self.notebookpanel.notebook.GetPageIndexByName(
'manual') < 0:
487 btnsizer.Add(item = self.
btn_help, proportion = 0, flag = wx.ALL | wx.ALIGN_CENTER, border = 10)
489 guisizer.Add(item = btnsizer, proportion = 0, flag = wx.ALIGN_CENTER | wx.LEFT | wx.RIGHT,
494 for p
in self.task.params:
495 if p.get(
'age',
'old') ==
'new' and \
496 p.get(
'prompt',
'')
in (
'raster',
'vector',
'3d-raster'):
502 label = _(
'Add created map(s) into layer tree'), style = wx.NO_BORDER)
503 self.addbox.SetValue(UserSettings.Get(group =
'cmd', key =
'addNewLayer', subkey =
'enabled'))
504 guisizer.Add(item = self.
addbox, proportion = 0,
505 flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
509 for p
in self.task.params:
510 if p.get(
'age',
'old') ==
'new':
514 if self.
get_dcmd is None and hasNew:
517 label = _(
'Close dialog on finish'), style = wx.NO_BORDER)
518 self.closebox.SetValue(UserSettings.Get(group =
'cmd', key =
'closeDlg', subkey =
'enabled'))
519 self.closebox.SetToolTipString(_(
"Close dialog when command is successfully finished. "
520 "Change this settings in Preferences dialog ('Command' tab)."))
521 guisizer.Add(item = self.
closebox, proportion = 0,
522 flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
525 self.Bind(wx.EVT_CLOSE, self.
OnCancel)
526 self.Bind(wx.EVT_KEY_UP, self.
OnKeyUp)
530 self.panel.SetAutoLayout(
True)
531 self.panel.SetSizerAndFit(guisizer)
533 sizeFrame = self.GetBestSize()
534 self.SetMinSize(sizeFrame)
535 self.SetSize(wx.Size(sizeFrame[0], sizeFrame[1] + 0.33 *
max(self.notebookpanel.panelMinHeight,
536 self.notebookpanel.constrained_size[1])))
547 width, height = self.GetSizeTuple()
548 self.SetSize(wx.Size(
min(width, 650),
553 self.goutput.SetSashPosition(int(self.GetSize()[1] * .75))
556 """!Update status bar data"""
557 self.SetStatusText(
' '.join(self.notebookpanel.createCmd(ignoreErrors =
True)))
562 """!Key released (check hot-keys)"""
564 kc = chr(event.GetKeyCode())
569 if not event.ControlDown():
587 """!This function is launched from OnRun() when command is
590 @param returncode command's return code (0 for success)
592 if not self.
parent or returncode != 0:
594 if self.parent.GetName()
not in (
'LayerTree',
'LayerManager'):
597 if self.parent.GetName() ==
'LayerTree':
598 display = self.parent.GetMapDisplay()
600 display = self.parent.GetLayerTree().GetMapDisplay()
602 if not display
or not display.IsAutoRendered():
605 mapLayers =
map(
lambda x: x.GetName(),
606 display.GetRender().GetListOfLayers(l_type =
'raster') +
607 display.GetRender().GetListOfLayers(l_type =
'vector'))
609 task =
GUI(show =
None).ParseCommand(cmd)
610 for p
in task.get_options()[
'params']:
611 if p.get(
'prompt',
'')
not in (
'raster',
'vector'):
613 mapName = p.get(
'value',
'')
614 if '@' not in mapName:
615 mapName = mapName +
'@' + grass.gisenv()[
'MAPSET']
616 if mapName
in mapLayers:
617 display.GetWindow().UpdateMap(render =
True)
621 """!OK button pressed"""
623 if cmd
is not None and self.
get_dcmd is not None:
627 """!Apply the command"""
629 cmd = self.
createCmd(ignoreErrors =
True, ignoreRequired =
True)
633 if cmd
is not None and self.
get_dcmd is not None:
636 "flags" : self.task.flags},
644 """!Run the command"""
647 if not cmd
or len(cmd) < 1:
653 self.notebookpanel.notebook.SetSelectionByName(
'output')
657 self.goutput.RunCmd(cmd, onDone = self.
OnDone)
658 except AttributeError, e:
659 print >> sys.stderr,
"%s: Probably not running in wxgui.py session?" % (e)
660 print >> sys.stderr,
"parent window is: %s" % (str(self.
parent))
672 """!Abort running command"""
673 event = goutput.wxCmdAbort(aborted =
True)
674 wx.PostEvent(self.
goutput, event)
677 """!Copy the command"""
678 cmddata = wx.TextDataObject()
680 cmdstring =
' '.join(self.
createCmd(ignoreErrors =
True))
681 cmddata.SetText(cmdstring)
682 if wx.TheClipboard.Open():
684 wx.TheClipboard.SetData(cmddata)
685 wx.TheClipboard.Close()
686 self.SetStatusText(_(
"'%s' copied to clipboard") % \
690 """!Cancel button pressed"""
691 self.MakeModal(
False)
695 self.parent.GetName()
in (
'LayerTree',
699 if self.task.name
in [
'd.barscale',
'd.legend',
'd.histogram'] \
700 or len(self.parent.GetPyData(self.
layer)[0][
'cmd']) >= 1:
703 elif len(self.parent.GetPyData(self.
layer)[0][
'cmd']) < 1:
704 self.parent.Delete(self.
layer)
711 """!Show manual page (switch to the 'Manual' notebook page)"""
712 if self.notebookpanel.notebook.GetPageIndexByName(
'manual') > -1:
713 self.notebookpanel.notebook.SetSelectionByName(
'manual')
714 self.notebookpanel.OnPageChange(
None)
719 def createCmd(self, ignoreErrors = False, ignoreRequired = False):
720 """!Create command string (python list)"""
721 return self.notebookpanel.createCmd(ignoreErrors = ignoreErrors,
722 ignoreRequired = ignoreRequired)
725 """!A panel containing a notebook dividing in tabs the different
726 guisections of the GRASS cmd.
728 def __init__(self, parent, task, id = wx.ID_ANY, mainFrame = None, *args, **kwargs):
735 wx.Panel.__init__(self, parent, id = id, *args, **kwargs)
740 not_hidden = [ p
for p
in self.task.params + self.task.flags
if not p.get(
'hidden',
False) ==
True ]
744 self.Bind(wx.EVT_SIZE, self.
OnSize)
746 for task
in not_hidden:
747 if task.get(
'required',
False):
749 task[
'guisection'] = _(
'Required')
750 if task.get(
'guisection',
'') ==
'':
752 task[
'guisection'] = _(
'Optional')
753 if task[
'guisection']
not in is_section:
755 is_section[task[
'guisection']] = 1
756 sections.append(task[
'guisection'])
758 is_section[ task[
'guisection'] ] += 1
762 for (newidx,content)
in [ (0,_(
'Required')), (len(sections)-1,_(
'Optional')) ]:
763 if content
in sections:
764 idx = sections.index(content)
765 sections[idx:idx+1] = []
766 sections[newidx:newidx] = [content]
768 panelsizer = wx.BoxSizer(orient = wx.VERTICAL)
772 self.notebook.SetTabAreaColour(globalvar.FNPageColor)
773 self.notebook.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.
OnPageChange)
777 for section
in sections:
778 tab[section] = scrolled.ScrolledPanel(parent = self.
notebook)
779 tab[section].SetScrollRate(10, 10)
780 tabsizer[section] = wx.BoxSizer(orient = wx.VERTICAL)
781 self.notebook.AddPage(page = tab[section], text = section)
785 if self.parent.GetName() ==
"MainFrame" and self.parent.get_dcmd
is None:
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.IsFile():
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(), ]
993 title_txt.SetLabel(title +
':')
994 cb = wx.ComboBox(parent = which_panel, id = wx.ID_ANY, value = p.get(
'default',
''),
995 size = globalvar.DIALOG_COMBOBOX_SIZE,
996 choices = valuelist, style = wx.CB_DROPDOWN)
1000 which_sizer.Add( item=cb, proportion=0,
1001 flag=wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT, border=5)
1002 p[
'wxId'] = [ cb.GetId(), ]
1007 if (p.get(
'type',
'string')
in (
'string',
'integer',
'float')
1008 and len(p.get(
'values',[])) == 0
1009 and p.get(
'gisprompt',
False) ==
False
1010 and p.get(
'prompt',
'') !=
'color'):
1012 title_txt.SetLabel(title +
':')
1013 if p.get(
'multiple',
False)
or \
1014 p.get(
'type',
'string') ==
'string' or \
1015 len(p.get(
'key_desc', [])) > 1:
1016 txt3 = wx.TextCtrl(parent = which_panel, value = p.get(
'default',
''))
1021 txt3.SetValue(str(value))
1024 style = wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT
1028 if p.get(
'type',
'') ==
'integer':
1029 txt3 = wx.SpinCtrl(parent = which_panel, value = p.get(
'default',
''),
1030 size = globalvar.DIALOG_SPIN_SIZE,
1031 min = minValue, max = maxValue)
1032 style = wx.BOTTOM | wx.LEFT | wx.RIGHT
1036 txt3.SetValue(int(value))
1040 txt3 = wx.TextCtrl(parent = which_panel, value = p.get(
'default',
''),
1042 style = wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT
1046 txt3.SetValue(str(value))
1050 which_sizer.Add(item = txt3, proportion = 0,
1051 flag = style, border = 5)
1052 p[
'wxId'] = [ txt3.GetId(), ]
1057 if p.get(
'gisprompt',
False) ==
True:
1058 title_txt.SetLabel(title +
':')
1060 if p.get(
'prompt',
'')
not in (
'color',
1073 p.get(
'element',
'') !=
'file':
1074 multiple = p.get(
'multiple',
False)
1075 if p.get(
'age',
'') ==
'new':
1076 mapsets = [grass.gisenv()[
'MAPSET'],]
1079 if self.task.name
in (
'r.proj',
'v.proj') \
1080 and p.get(
'name',
'') ==
'input':
1081 if self.task.name ==
'r.proj':
1086 isRaster = isRaster)
1087 p[
'wxId'] = [ selection.GetId(), ]
1088 selection.Bind(wx.EVT_COMBOBOX, self.
OnSetValue)
1092 size = globalvar.DIALOG_GSELECT_SIZE,
1093 type = p.get(
'element',
''),
1094 multiple = multiple, mapsets = mapsets)
1098 textWin = selection.GetTextCtrl()
1099 p[
'wxId'] = [ textWin.GetId(), ]
1104 selection.SetValue(value)
1106 which_sizer.Add(item=selection, proportion=0,
1107 flag=wx.ADJUST_MINSIZE| wx.BOTTOM | wx.LEFT | wx.RIGHT, border=5)
1109 if p.get(
'prompt',
'')
in (
'vector',
'group'):
1112 elif p.get(
'prompt',
'') ==
'subgroup':
1114 p[
'wxId'] = [ selection.GetId() ]
1115 selection.Bind(wx.EVT_COMBOBOX, self.
OnSetValue)
1116 which_sizer.Add(item = selection, proportion = 0,
1117 flag = wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT | wx.RIGHT | wx.TOP | wx.ALIGN_CENTER_VERTICAL,
1121 elif p.get(
'prompt',
'')
in (
'dbdriver',
1131 if p.get(
'multiple',
'no') ==
'yes':
1132 win = wx.TextCtrl(parent = which_panel, value = p.get(
'default',
''),
1133 size = globalvar.DIALOG_TEXTCTRL_SIZE)
1138 if p.get(
'prompt',
'')
in (
'layer',
1142 if p.get(
'age',
'old_layer') ==
'old_layer':
1144 if p.get(
'prompt',
'') ==
'layer_all':
1145 initial.insert(0,
'-1')
1146 elif p.get(
'prompt',
'') ==
'layer_zero':
1147 initial.insert(0,
'0')
1148 lyrvalue = p.get(
'default')
1150 if lyrvalue
not in initial:
1151 initial.append(str(lyrvalue))
1152 lyrvalue = p.get(
'value')
1154 if lyrvalue
not in initial:
1155 initial.append(str(lyrvalue))
1159 default = p[
'default'])
1160 p[
'wxGetValue'] = win.GetStringSelection
1163 win.SetValue(str(value))
1165 win = wx.SpinCtrl(parent = which_panel, id = wx.ID_ANY,
1166 min = 1, max = 100, initial = int(p[
'default']))
1168 win.SetValue(int(value))
1170 elif p.get(
'prompt',
'') ==
'dbdriver':
1172 choices = p.get(
'values', []),
1174 p[
'wxGetValue'] = win.GetStringSelection
1177 elif p.get(
'prompt',
'') ==
'dbname':
1183 elif p.get(
'prompt',
'') ==
'dbtable':
1184 if p.get(
'age',
'old_dbtable') ==
'old_dbtable':
1187 p[
'wxGetValue'] = win.GetStringSelection
1191 win = wx.TextCtrl(parent = which_panel, value = p.get(
'default',
''),
1192 size = globalvar.DIALOG_TEXTCTRL_SIZE)
1194 elif p.get(
'prompt',
'') ==
'dbcolumn':
1201 elif p.get(
'prompt',
'') ==
'location':
1207 elif p.get(
'prompt',
'') ==
'mapset':
1213 elif p.get(
'prompt',
'') ==
'dbase':
1217 p[
'wxId'] = [ win.GetChildren()[1].GetId() ]
1221 p[
'wxId'] = [ win.GetId(), ]
1222 except AttributeError:
1225 which_sizer.Add(item = win, proportion = 0,
1226 flag = wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT, border = 5)
1228 elif p.get(
'prompt',
'')
in (
'color',
1230 default_color = (200,200,200)
1231 label_color = _(
"Select Color")
1232 if p.get(
'default',
'') !=
'':
1234 if p.get(
'value',
'') !=
'':
1236 if p.get(
'prompt',
'') ==
'color_none':
1237 this_sizer = wx.BoxSizer(orient = wx.HORIZONTAL)
1239 this_sizer = which_sizer
1240 btn_colour = csel.ColourSelect(parent = which_panel, id = wx.ID_ANY,
1241 label = label_color, colour = default_color,
1242 pos = wx.DefaultPosition, size = (150,-1))
1243 this_sizer.Add(item = btn_colour, proportion = 0,
1244 flag = wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT, border = 5)
1247 p[
'wxId'] = [btn_colour.GetId(),]
1249 if p.get(
'prompt',
'') ==
'color_none':
1250 none_check = wx.CheckBox(which_panel, wx.ID_ANY, _(
"Transparent"))
1251 if p.get(
'value',
'') !=
'' and p.get(
'value',[
''])[0] ==
"none":
1252 none_check.SetValue(
True)
1254 none_check.SetValue(
False)
1255 this_sizer.Add(item = none_check, proportion = 0,
1256 flag = wx.ADJUST_MINSIZE | wx.LEFT | wx.RIGHT | wx.TOP, border = 5)
1257 which_sizer.Add(this_sizer)
1259 p[
'wxId'].append(none_check.GetId())
1261 p[
'wxId'].append(
None)
1263 elif p.get(
'prompt',
'') !=
'color' and p.get(
'element',
'') ==
'file':
1264 fbb = filebrowse.FileBrowseButton(parent = which_panel, id = wx.ID_ANY, fileMask =
'*',
1265 size = globalvar.DIALOG_GSELECT_SIZE, labelText =
'',
1266 dialogTitle = _(
'Choose %s') % \
1267 p.get(
'description',_(
'File')),
1268 buttonText = _(
'Browse'),
1269 startDirectory = os.getcwd(), fileMode = 0,
1274 which_sizer.Add(item = fbb, proportion = 0,
1275 flag = wx.EXPAND | wx.RIGHT, border = 5)
1280 p[
'wxId'] = [ fbb.GetChildren()[1].GetId() ]
1281 if p.get(
'age',
'new_file') ==
'old_file' and \
1282 UserSettings.Get(group=
'cmd', key=
'interactiveInput', subkey=
'enabled'):
1284 ifbb = wx.TextCtrl(parent = which_panel, id = wx.ID_ANY,
1285 style = wx.TE_MULTILINE,
1287 if p.get(
'value',
'')
and os.path.isfile(p[
'value']):
1288 f = open(p[
'value'])
1289 ifbb.SetValue(
''.join(f.readlines()))
1293 which_sizer.Add(item = wx.StaticText(parent = which_panel, id = wx.ID_ANY,
1294 label = _(
'or enter values interactively')),
1296 flag = wx.EXPAND | wx.RIGHT | wx.LEFT | wx.BOTTOM, border = 5)
1297 which_sizer.Add(item = ifbb, proportion = 1,
1298 flag = wx.EXPAND | wx.RIGHT | wx.LEFT, border = 5)
1299 p[
'wxId'].append(ifbb.GetId())
1301 if self.parent.GetName() ==
'MainFrame' and self.parent.modeler:
1302 parChk = wx.CheckBox(parent = which_panel, id = wx.ID_ANY,
1303 label = _(
"Parameterized in model"))
1304 parChk.SetName(
'ModelParam')
1305 parChk.SetValue(p.get(
'parameterized',
False))
1307 p[
'wxId'].append(parChk.GetId())
1309 p[
'wxId'] = [ parChk.GetId() ]
1310 parChk.Bind(wx.EVT_CHECKBOX, self.
OnSetValue)
1311 which_sizer.Add(item = parChk, proportion = 0,
1312 flag = wx.LEFT, border = 20)
1314 if title_txt
is not None:
1316 if len(p[
'values_desc']) > 0:
1318 tooltip += 2 * os.linesep
1321 if len(p[
'values']) == len(p[
'values_desc']):
1322 for i
in range(len(p[
'values'])):
1323 tooltip += p[
'values'][i] +
': ' + p[
'values_desc'][i] + os.linesep
1324 tooltip.strip(os.linesep)
1326 title_txt.SetToolTipString(tooltip)
1328 if p == first_param:
1329 if 'wxId' in p
and len(p[
'wxId']) > 0:
1330 win = self.FindWindowById(p[
'wxId'][0])
1347 for p
in self.task.params:
1348 if p.get(
'gisprompt',
False) ==
False:
1351 prompt = p.get(
'element',
'')
1352 if prompt
in (
'cell',
'vector'):
1353 name = p.get(
'name',
'')
1354 if name
in (
'map',
'input'):
1356 elif prompt ==
'layer':
1358 elif prompt ==
'dbcolumn':
1360 elif prompt ==
'dbdriver':
1362 elif prompt ==
'dbname':
1364 elif prompt ==
'dbtable':
1366 elif prompt ==
'group':
1368 elif prompt ==
'subgroup':
1370 elif prompt ==
'dbase':
1372 elif prompt ==
'location':
1374 elif prompt ==
'mapset':
1379 pColumnIds += p[
'wxId']
1382 pLayerIds += p[
'wxId']
1385 pMap[
'wxId-bind'] = copy.copy(pColumnIds)
1387 pMap[
'wxId-bind'] += pLayerIds
1390 p[
'wxId-bind'] = copy.copy(pColumnIds)
1392 if pDriver
and pTable:
1393 pDriver[
'wxId-bind'] = pTable[
'wxId']
1395 if pDatabase
and pTable:
1396 pDatabase[
'wxId-bind'] = pTable[
'wxId']
1398 if pTable
and pColumnIds:
1399 pTable[
'wxId-bind'] = pColumnIds
1401 if pGroup
and pSubGroup:
1402 pGroup[
'wxId-bind'] = pSubGroup[
'wxId']
1404 if pDbase
and pLocation:
1405 pDbase[
'wxId-bind'] = pLocation[
'wxId']
1407 if pLocation
and pMapset:
1408 pLocation[
'wxId-bind'] = pMapset[
'wxId']
1410 if pLocation
and pMapset
and pMap:
1411 pLocation[
'wxId-bind'] += pMap[
'wxId']
1412 pMapset[
'wxId-bind'] = pMap[
'wxId']
1418 for section
in sections:
1419 tab[section].SetSizer(tabsizer[section])
1420 tabsizer[section].Fit(tab[section])
1421 tab[section].Layout()
1422 minsecsizes = tabsizer[section].GetSize()
1423 maxsizes =
map(
lambda x:
max(maxsizes[x], minsecsizes[x]), (0, 1))
1428 for section
in sections:
1431 if self.manual_tab.IsLoaded():
1434 self.SetSizer(panelsizer)
1439 def _getValue(self, p):
1440 """!Get value or default value of given parameter
1442 @param p parameter directory
1444 if p.get(
'value',
'') !=
'':
1446 return p.get(
'default',
'')
1449 """File input interactively entered"""
1450 text = event.GetString()
1451 p = self.task.get_param(value = event.GetId(), element =
'wxId', raiseError =
False)
1454 win = self.FindWindowById(p[
'wxId'][0])
1456 filename = win.GetValue()
1459 filename = grass.tempfile()
1460 win.SetValue(filename)
1462 f = open(filename,
"w")
1471 for fn, kwargs
in event.data.iteritems():
1474 self.parent.updateValuesHook()
1477 """!Verbosity level changed"""
1478 verbose = self.FindWindowById(self.task.get_flag(
'verbose')[
'wxId'][0])
1479 quiet = self.FindWindowById(self.task.get_flag(
'quiet')[
'wxId'][0])
1480 if event.IsChecked():
1481 if event.GetId() == verbose.GetId():
1482 if quiet.IsChecked():
1483 quiet.SetValue(
False)
1484 self.task.get_flag(
'quiet')[
'value'] =
False
1486 if verbose.IsChecked():
1487 verbose.SetValue(
False)
1488 self.task.get_flag(
'verbose')[
'value'] =
False
1494 sel = self.notebook.GetSelection()
1496 sel = event.GetSelection()
1498 idx = self.notebook.GetPageIndexByName(
'manual')
1499 if idx > -1
and sel == idx:
1502 if not self.manual_tab.IsLoaded():
1504 self.manual_tab.LoadPage()
1509 myId = event.GetId()
1510 for p
in self.task.params:
1511 if 'wxId' in p
and myId
in p[
'wxId']:
1512 has_button = p[
'wxId'][1]
is not None
1513 if has_button
and wx.FindWindowById(p[
'wxId'][1]).GetValue() ==
True:
1514 p[
'value' ] =
'none'
1516 colorchooser = wx.FindWindowById(p[
'wxId'][0])
1517 new_color = colorchooser.GetValue()[:]
1520 new_label = rgb2str.get(new_color,
':'.join(
map(str,new_color)))
1521 colorchooser.SetLabel(new_label)
1522 colorchooser.SetColour(new_color)
1523 colorchooser.Refresh()
1524 p[
'value' ] = colorchooser.GetLabel()
1528 """!If we were part of a richer interface, report back the
1529 current command being built.
1531 This method should be set by the parent of this panel if
1532 needed. It's a hook, actually. Beware of what is 'self' in
1533 the method def, though. It will be called with no arguments.
1538 """!Fill the values as a ','-separated string according to
1539 current status of the checkboxes.
1543 for p
in self.task.params:
1544 if 'wxId' in p
and me
in p[
'wxId']:
1546 myIndex = p[
'wxId'].index(me)
1550 for isThere
in theParam.get(
'value',
'').
split(
','):
1551 currentValues[isThere] = 1
1552 theValue = theParam[
'values'][myIndex]
1555 currentValues[ theValue ] = 1
1557 del currentValues[ theValue ]
1560 currentValueList = []
1561 for v
in theParam[
'values']:
1562 if v
in currentValues:
1563 currentValueList.append(v)
1566 theParam[
'value'] =
','.join(currentValueList)
1568 self.OnUpdateValues()
1571 """!Retrieve the widget value and set the task value field
1574 Use for widgets that have a proper GetValue() method, i.e. not
1577 myId = event.GetId()
1578 me = wx.FindWindowById(myId)
1582 for porf
in self.task.params + self.task.flags:
1583 if 'wxId' not in porf:
1585 if myId
in porf[
'wxId']:
1592 if name
in (
'DriverSelect',
'TableSelect',
1593 'LocationSelect',
'MapsetSelect',
'ProjSelect'):
1594 porf[
'value'] = me.GetStringSelection()
1595 elif name ==
'GdalSelect':
1596 porf[
'value'] = event.dsn
1597 elif name ==
'ModelParam':
1598 porf[
'parameterized'] = me.IsChecked()
1599 elif name ==
'LayerSelect':
1600 porf[
'value'] = me.GetValue()
1602 porf[
'value'] = me.GetValue()
1609 """!Update dialog (layers, tables, columns, etc.)
1611 if not hasattr(self.
parent,
"updateThread"):
1616 self.parent.updateThread.Update(UpdateDialog,
1622 self.parent.updateThread.Update(UpdateDialog,
1628 def createCmd(self, ignoreErrors = False, ignoreRequired = False):
1629 """!Produce a command line string (list) or feeding into GRASS.
1631 @param ignoreErrors True then it will return whatever has been
1632 built so far, even though it would not be a correct command
1636 cmd = self.task.getCmd(ignoreErrors = ignoreErrors,
1637 ignoreRequired = ignoreRequired)
1638 except ValueError, err:
1639 dlg = wx.MessageDialog(parent = self,
1640 message = unicode(err),
1641 caption = _(
"Error in %s") % self.task.name,
1642 style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
1650 width = event.GetSize()[0]
1651 fontsize = self.GetFont().GetPointSize()
1652 text_width =
max(width / (fontsize - 3), 70)
1655 win = self.FindWindowById(id)
1656 label = win.GetLabel()
1657 label_new =
'\n'.join(textwrap.wrap(label, text_width))
1658 win.SetLabel(label_new)
1663 """!Stand-alone GRASS command GUI
1667 wx.App.__init__(self,
False)
1670 msg = self.grass_task.get_error_msg()
1672 gcmd.GError(msg +
'\n\nTry to set up GRASS_ADDON_PATH variable.')
1676 self.mf.CentreOnScreen()
1678 self.SetTopWindow(self.
mf)
1683 def __init__(self, parent = None, show = True, modal = False,
1684 centreOnParent =
False, checkError =
False):
1685 """!Parses GRASS commands when module is imported and used from
1699 _blackList[
'enabled'] =
True
1701 _blackList[
'enabled'] =
False
1704 """!Get validated command"""
1710 Note: cmd is given as list
1712 If command is given with options, return validated cmd list:
1713 - add key name for first parameter if not given
1714 - change mapname to mapname@mapset
1718 if completed ==
None:
1723 get_dcmd = completed[0]
1724 layer = completed[1]
1726 dcmd_params.update(completed[2])
1731 self.
grass_task = gtask.parse_interface(cmd[0],
1732 blackList = _blackList)
1733 except (grass.ScriptError, ValueError), e:
1738 if completed
is not None:
1739 if 'params' in dcmd_params:
1740 self.grass_task.params = dcmd_params[
'params']
1741 if 'flags' in dcmd_params:
1742 self.grass_task.flags = dcmd_params[
'flags']
1748 cmd_validated = [cmd[0]]
1749 for option
in cmd[1:]:
1750 if option[0] ==
'-':
1751 if option[1] ==
'-':
1752 self.grass_task.set_flag(option[2:],
True)
1754 self.grass_task.set_flag(option[1],
True)
1755 cmd_validated.append(option)
1758 key, value = option.split(
'=', 1)
1760 params = self.grass_task.get_options()[
'params']
1763 key = params[0][
'name']
1766 raise gcmd.GException, _(
"Unable to parse command '%s'") %
' '.join(cmd)
1770 element = self.grass_task.get_param(key, raiseError =
False)
1772 err.append(_(
"%(cmd)s: parameter '%(key)s' not available") % \
1776 element = element[
'element']
1778 if element
in [
'cell',
'vector']:
1780 if '@' not in value:
1781 mapset = grass.find_file(value, element)[
'mapset']
1782 curr_mapset = grass.gisenv()[
'MAPSET']
1783 if mapset
and mapset != curr_mapset:
1784 value = value +
'@' + mapset
1786 self.grass_task.set_param(key, value)
1787 cmd_validated.append(key +
'=' + value)
1793 if self.
show is not None:
1796 get_dcmd = get_dcmd, layer = layer)
1800 if get_dcmd
is not None:
1802 get_dcmd(dcmd =
None, layer = layer, params =
None,
1805 if self.
show is not None:
1806 self.mf.notebookpanel.OnUpdateSelection(
None)
1807 if self.
show is True:
1809 self.mf.CentreOnParent()
1811 self.mf.CenterOnScreen()
1812 self.mf.Show(self.
show)
1813 self.mf.MakeModal(self.
modal)
1815 self.mf.OnApply(
None)
1825 """!Get parameter key for input raster/vector map
1827 @param cmd module name
1829 @return parameter key
1830 @return None on failure
1834 enc = locale.getdefaultlocale()[1]
1835 if enc
and enc.lower() ==
"cp932":
1836 p = re.compile(
'encoding="' + enc +
'"', re.IGNORECASE)
1837 tree = etree.fromstring(p.sub(
'encoding="utf-8"',
1838 gtask.get_interface_description(cmd).
decode(enc).encode(
'utf-8')))
1840 tree = etree.fromstring(gtask.get_interface_description(cmd))
1841 self.
grass_task = gtask.processTask(tree).get_task()
1843 for p
in self.grass_task.params:
1844 if p.get(
'name',
'')
in (
'input',
'map'):
1845 age = p.get(
'age',
'')
1846 prompt = p.get(
'prompt',
'')
1847 element = p.get(
'element',
'')
1848 if age ==
'old' and \
1849 element
in (
'cell',
'grid3',
'vector')
and \
1850 prompt
in (
'raster',
'3d-raster',
'vector'):
1851 return p.get(
'name',
None)
1855 """!Validator for floating-point input"""
1857 wx.PyValidator.__init__(self)
1859 self.Bind(wx.EVT_TEXT, self.
OnText)
1862 """!Clone validator"""
1866 """Validate input"""
1867 textCtrl = self.GetWindow()
1868 text = textCtrl.GetValue()
1874 textCtrl.SetBackgroundColour(
"grey")
1879 sysColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)
1880 textCtrl.SetBackgroundColour(sysColor)
1887 """!Do validation"""
1899 """!Generic notebook widget
1902 if globalvar.hasAgw:
1903 FN.FlatNotebook.__init__(self, parent, id = wx.ID_ANY, agwStyle = style, **kwargs)
1905 FN.FlatNotebook.__init__(self, parent, id = wx.ID_ANY, style = style, **kwargs)
1912 if 'name' in kwargs:
1915 super(GNotebook, self).
AddPage(**kwargs)
1920 @param page names, eg. 'layers', 'output', 'search', 'pyshell', 'nviz'
1923 if self.GetSelection() != idx:
1924 self.SetSelection(idx)
1927 """!Get notebook page index
1936 if __name__ ==
"__main__":
1938 if len(sys.argv) == 1:
1939 sys.exit(_(
"usage: %s <grass command>") % sys.argv[0])
1940 if sys.argv[1] !=
'test':
1942 cmd = utils.split(sys.argv[1])
1943 if sys.platform ==
'win32':
1944 if cmd[0]
in globalvar.grassCmd[
'script']:
1945 cmd[0] += globalvar.EXT_SCT
1946 task = gtask.grassTask(cmd[0], blackList = _blackList)
1947 task.set_options(cmd[1:])
1952 if os.getenv(
"GISBASE")
is not None:
1953 task = gtask.grassTask(
"d.vect")
1954 task.get_param(
'map')[
'value'] =
"map_name"
1955 task.get_flag(
'v')[
'value'] =
True
1956 task.get_param(
'layer')[
'value'] = 1
1957 task.get_param(
'bcolor')[
'value'] =
"red"
1958 assert ' '.join(task.getCmd()) ==
"d.vect -v map = map_name layer = 1 bcolor = red"
1961 task = gtask.grassTask()
1962 task.name =
"TestTask"
1963 task.description =
"This is an artificial grassTask() object intended for testing purposes."
1964 task.keywords = [
"grass",
"test",
"task"]
1968 "description" :
"Descriptions go into tooltips if labels are present, like this one",
1969 "label" :
"Enter some text",
1971 "name" :
"hidden_text",
1972 "description" :
"This text should not appear in the form",
1975 "name" :
"text_default",
1976 "description" :
"Enter text to override the default",
1977 "default" :
"default text"
1979 "name" :
"text_prefilled",
1980 "description" :
"You should see a friendly welcome message here",
1981 "value" :
"hello, world"
1983 "name" :
"plain_color",
1984 "description" :
"This is a plain color, and it is a compulsory parameter",
1989 "name" :
"transparent_color",
1990 "description" :
"This color becomes transparent when set to none",
1991 "guisection" :
"tab",
1996 "description" :
"A multiple selection",
1997 'default':
u'red,green,blue',
1999 'guisection':
'tab',
2003 'values': [
'red',
'green',
u'yellow',
u'blue',
u'purple',
u'other']
2006 "description" :
"A single multiple-choice selection",
2007 'values': [
'red',
'green',
u'yellow',
u'blue',
u'purple',
u'other'],
2008 "guisection" :
"tab"
2010 "name" :
"large_multi",
2011 "description" :
"A large multiple selection",
2012 "gisprompt" :
False,
2015 "values" : str2rgb.keys() +
map(str, str2rgb.values())
2018 "description" :
"A file selector",
2026 "description" :
"Some flag, will appear in Main since it is required",
2030 "description" :
"pre-filled flag, will appear in options since it is not required",
2033 "name" :
"hidden_flag",
2034 "description" :
"hidden flag, should not be changeable",