2 @package gui_core.goutput
4 @brief Command output widgets
14 (C) 2007-2012 by the GRASS Development Team
16 This program is free software under the GNU General Public License
17 (>=v2). Read the file COPYING that comes with GRASS for details.
19 @author Michael Barton (Arizona State University)
20 @author Martin Landa <landa.martin gmail.com>
21 @author Vaclav Petras <wenzeslaus gmail.com> (copy&paste customization)
36 from wx.lib.newevent
import NewEvent
41 from core
import globalvar
42 from core
import utils
43 from core.gcmd import CommandThread, GMessage, GError, GException, EncodeString
44 from gui_core.forms
import GUI
50 wxCmdOutput, EVT_CMD_OUTPUT = NewEvent()
51 wxCmdProgress, EVT_CMD_PROGRESS = NewEvent()
52 wxCmdRun, EVT_CMD_RUN = NewEvent()
53 wxCmdDone, EVT_CMD_DONE = NewEvent()
54 wxCmdAbort, EVT_CMD_ABORT = NewEvent()
55 wxCmdPrepare, EVT_CMD_PREPARE = NewEvent()
57 def GrassCmd(cmd, env = None, stdout = None, stderr = None):
58 """!Return GRASS command thread"""
59 return CommandThread(cmd, env = env,
60 stdout = stdout, stderr = stderr)
63 """!Thread for GRASS commands"""
65 def __init__(self, parent, requestQ, resultQ, **kwds):
66 threading.Thread.__init__(self, **kwds)
79 CmdThread.requestId += 1
82 self.requestQ.put((CmdThread.requestId, args, kwds))
84 return CmdThread.requestId
87 """!Set starting id"""
88 CmdThread.requestId = id
91 os.environ[
'GRASS_MESSAGE_FORMAT'] =
'gui'
93 requestId, args, kwds = self.requestQ.get()
94 for key
in (
'callable',
'onDone',
'onPrepare',
'userData'):
96 vars()[key] = kwds[key]
101 if not vars()[
'callable']:
102 vars()[
'callable'] = GrassCmd
104 requestTime = time.time()
107 event = wxCmdPrepare(cmd = args[0],
110 onPrepare = vars()[
'onPrepare'],
111 userData = vars()[
'userData'])
112 wx.PostEvent(self.
parent, event)
115 event = wxCmdRun(cmd = args[0],
117 wx.PostEvent(self.
parent, event)
120 self.
requestCmd = vars()[
'callable'](*args, **kwds)
122 self.requestCmd.abort()
123 if self.requestQ.empty():
126 self.resultQ.put((requestId, self.requestCmd.run()))
129 returncode = self.requestCmd.module.returncode
130 except AttributeError:
134 aborted = self.requestCmd.aborted
135 except AttributeError:
141 if UserSettings.Get(group =
'cmd', key =
'rasterColorTable', subkey =
'enabled')
and \
142 args[0][0][:2] ==
'r.':
143 colorTable = UserSettings.Get(group =
'cmd', key =
'rasterColorTable', subkey =
'selection')
145 if args[0][0] ==
'r.mapcalc':
147 mapName = args[0][1].
split(
'=', 1)[0].strip()
151 moduleInterface = GUI(show =
None).ParseCommand(args[0])
152 outputParam = moduleInterface.get_param(value =
'output', raiseError =
False)
153 if outputParam
and outputParam[
'prompt'] ==
'raster':
154 mapName = outputParam[
'value']
157 argsColor = list(args)
158 argsColor[0] = [
'r.colors',
160 'color=%s' % colorTable ]
162 self.resultQ.put((requestId, self.requestCmdColor.run()))
164 event = wxCmdDone(cmd = args[0],
166 returncode = returncode,
169 onDone = vars()[
'onDone'],
170 userData = vars()[
'userData'])
173 wx.PostEvent(self.
parent, event)
176 """!Abort command(s)"""
179 self.requestCmd.abort()
180 if self.requestQ.empty():
184 """!Create and manage output console for commands run by GUI.
186 def __init__(self, parent, id = wx.ID_ANY, margin = False,
188 style = wx.TAB_TRAVERSAL | wx.FULL_REPAINT_ON_RESIZE,
190 wx.SplitterWindow.__init__(self, parent, id, style = style, *kwargs)
191 self.SetName(
"GMConsole")
213 range = 100, pos = (110, 50), size = (-1, 25),
214 style = wx.GA_HORIZONTAL)
221 self.cmdOutput.Bind(EVT_CMD_OUTPUT, self.
OnCmdOutput)
223 self.Bind(EVT_CMD_RUN, self.
OnCmdRun)
230 if self.parent.GetName() !=
'LayerManager':
232 self.cmdPrompt.Hide()
238 style = wx.CP_DEFAULT_STYLE |
239 wx.CP_NO_TLW_RESIZE | wx.EXPAND)
241 self.searchPane.Collapse(
True)
253 label =
" %s " % _(
"Output window"))
255 label =
" %s " % _(
"Command prompt"))
259 self.btnOutputClear.SetToolTipString(_(
"Clear output window content"))
261 self.btnCmdClear.SetToolTipString(_(
"Clear command prompt content"))
263 self.btnOutputSave.SetToolTipString(_(
"Save output window content to the file"))
265 self.btnCmdAbort.SetToolTipString(_(
"Abort running command"))
266 self.btnCmdAbort.Enable(
False)
268 label = _(
"&Log file"),
269 size = self.btnCmdClear.GetSize())
270 self.btnCmdProtocol.SetToolTipString(_(
"Toggle to save list of executed commands into "
271 "a file; content saved when switching off."))
273 if self.parent.GetName() !=
'LayerManager':
274 self.btnCmdClear.Hide()
275 self.btnCmdProtocol.Hide()
277 self.btnCmdClear.Bind(wx.EVT_BUTTON, self.cmdPrompt.OnCmdErase)
279 self.btnOutputSave.Bind(wx.EVT_BUTTON, self.
OnOutputSave)
280 self.btnCmdAbort.Bind(wx.EVT_BUTTON, self.
OnCmdAbort)
282 self.btnCmdProtocol.Bind(wx.EVT_TOGGLEBUTTON, self.
OnCmdProtocol)
288 outputSizer = wx.BoxSizer(wx.VERTICAL)
289 btnSizer = wx.BoxSizer(wx.HORIZONTAL)
290 outBtnSizer = wx.StaticBoxSizer(self.
outputBox, wx.HORIZONTAL)
291 cmdBtnSizer = wx.StaticBoxSizer(self.
cmdBox, wx.HORIZONTAL)
293 if self.cmdPrompt.IsShown():
294 promptSizer = wx.BoxSizer(wx.VERTICAL)
295 promptSizer.Add(item = self.
cmdPrompt, proportion = 1,
296 flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, border = 3)
298 if self.
search and self.search.IsShown():
299 outputSizer.Add(item = self.
searchPane, proportion = 0,
300 flag = wx.EXPAND | wx.ALL, border = 3)
301 outputSizer.Add(item = self.
cmdOutput, proportion = 1,
302 flag = wx.EXPAND | wx.ALL, border = 3)
303 outputSizer.Add(item = self.
progressbar, proportion = 0,
304 flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border = 3)
306 flag = wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT, border = 5)
308 flag = wx.ALIGN_RIGHT | wx.RIGHT, border = 5)
311 flag = wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT, border = 5)
312 cmdBtnSizer.Add(item = self.
btnCmdClear, proportion = 1,
313 flag = wx.ALIGN_CENTER | wx.RIGHT, border = 5)
314 cmdBtnSizer.Add(item = self.
btnCmdAbort, proportion = 1,
315 flag = wx.ALIGN_CENTER | wx.RIGHT, border = 5)
317 if self.parent.GetName() !=
'LayerManager':
322 btnSizer.Add(item = outBtnSizer, proportion = proportion[0],
323 flag = wx.ALL | wx.ALIGN_CENTER, border = 5)
324 btnSizer.Add(item = cmdBtnSizer, proportion = proportion[1],
325 flag = wx.ALIGN_CENTER | wx.TOP | wx.BOTTOM | wx.RIGHT, border = 5)
326 outputSizer.Add(item = btnSizer, proportion = 0,
329 outputSizer.Fit(self)
330 outputSizer.SetSizeHints(self)
331 self.panelOutput.SetSizer(outputSizer)
333 if self.cmdPrompt.IsShown():
334 promptSizer.Fit(self)
335 promptSizer.SetSizeHints(self)
336 self.panelPrompt.SetSizer(promptSizer)
339 if self.cmdPrompt.IsShown():
344 self.SetMinimumPaneSize(self.btnCmdClear.GetSize()[1] + 25)
346 self.SetSashGravity(1.0)
349 self.SetAutoLayout(
True)
353 """!Create search pane"""
354 border = wx.BoxSizer(wx.VERTICAL)
356 self.
search = SearchModuleWindow(parent = pane, cmdPrompt = self.
cmdPrompt)
358 border.Add(item = self.
search, proportion = 0,
359 flag = wx.EXPAND | wx.ALL, border = 1)
361 pane.SetSizer(border)
365 """!Collapse search module box"""
366 if self.searchPane.IsExpanded():
371 self.panelOutput.Layout()
372 self.panelOutput.SendSizeEvent()
377 @param prompt get prompt / output panel
379 @return wx.Panel reference
387 """!Redirect stdout/stderr
389 if Debug.GetLevel() == 0
and int(grass.gisenv().get(
'DEBUG', 0)) == 0:
394 enc = locale.getdefaultlocale()[1]
396 sys.stdout = codecs.getwriter(enc)(sys.__stdout__)
397 sys.stderr = codecs.getwriter(enc)(sys.__stderr__)
399 sys.stdout = sys.__stdout__
400 sys.stderr = sys.__stderr__
402 def WriteLog(self, text, style = None, wrap = None,
404 """!Generic method for writing log message in
407 @param line text line
408 @param style text style (see GMStc)
409 @param stdout write to stdout or stderr
412 self.cmdOutput.SetStyle()
415 self._notebook.SetSelectionByName(
'output')
418 style = self.cmdOutput.StyleDefault
421 p1 = self.cmdOutput.GetEndStyled()
423 self.cmdOutput.DocumentEnd()
425 for line
in text.splitlines():
431 self.cmdOutput.AddTextWrapped(line, wrap = wrap)
433 p2 = self.cmdOutput.GetCurrentPos()
435 self.cmdOutput.StartStyling(p1, 0xff)
436 self.cmdOutput.SetStyling(p2 - p1, style)
438 self.cmdOutput.EnsureCaretVisible()
441 """!Write message in selected style"""
443 line =
'(' + str(pid) +
') ' + line
445 self.
WriteLog(line, style = self.cmdOutput.StyleCommand, switchPage = switchPage)
448 """!Write message in warning style"""
449 self.
WriteLog(line, style = self.cmdOutput.StyleWarning, switchPage =
True)
452 """!Write message in error style"""
453 self.
WriteLog(line, style = self.cmdOutput.StyleError, switchPage =
True)
455 def RunCmd(self, command, compReg = True, switchPage = False, skipInterface = False,
456 onDone =
None, onPrepare =
None, userData =
None):
457 """!Run command typed into console command prompt (GPrompt).
459 @todo Display commands (*.d) are captured and processed
460 separately by mapdisp.py. Display commands are rendered in map
461 display widget that currently has the focus (as indicted by
464 @param command command given as a list (produced e.g. by utils.split())
465 @param compReg True use computation region
466 @param switchPage switch to output page
467 @param skipInterface True to do not launch GRASS interface
468 parser when command has no arguments given
469 @param onDone function to be called when command is finished
470 @param onPrepare function to be called before command is launched
471 @param userData data defined for the command
473 if len(command) == 0:
474 Debug.msg(2,
"GPrompt:RunCmd(): empty command")
480 filePath = os.path.join(env[
'GISDBASE'],
481 env[
'LOCATION_NAME'],
484 fileHistory = codecs.open(filePath, encoding =
'utf-8', mode =
'a')
486 GError(_(
"Unable to write file '%(filePath)s'.\n\nDetails: %(error)s") %
487 {
'filePath': filePath,
'error' : e },
493 fileHistory.write(
' '.join(command) + os.linesep)
497 if command[0]
in globalvar.grassCmd:
500 if self.parent.GetName() ==
"LayerManager" and \
501 command[0][0:2] ==
"d." and \
502 'help' not in ' '.join(command[1:]):
505 layertype = {
'd.rast' :
'raster',
506 'd.rast3d' :
'3d-raster',
509 'd.shadedmap' :
'shaded',
510 'd.legend' :
'rastleg',
511 'd.rast.arrow' :
'rastarrow',
512 'd.rast.num' :
'rastnum',
514 'd.vect.thematic':
'thememap',
515 'd.vect.chart' :
'themechart',
517 'd.geodesic' :
'geodesic',
518 'd.rhumbline' :
'rhumb',
519 'd.labels' :
'labels',
520 'd.barscale' :
'barscale',
521 'd.redraw' :
'redraw'}[command[0]]
523 GMessage(parent = self.
parent,
524 message = _(
"Command '%s' not yet implemented in the WxGUI. "
525 "Try adding it as a command layer instead.") % command[0])
528 if layertype ==
'barscale':
530 self.parent.curr_page.maptree.GetMapDisplay().AddBarscale(cmd = command, showDialog =
False)
532 self.parent.curr_page.maptree.GetMapDisplay().AddBarscale(showDialog =
True)
533 elif layertype ==
'rastleg':
535 self.parent.curr_page.maptree.GetMapDisplay().AddLegend(cmd = command, showDialog =
False)
537 self.parent.curr_page.maptree.GetMapDisplay().AddLegend(showDialog =
True)
538 elif layertype ==
'redraw':
539 self.parent.curr_page.maptree.GetMapDisplay().OnRender(
None)
543 layerType = layertype)
544 if self.parent.GetName() ==
"LayerManager":
545 self.parent.curr_page.maptree.AddLayer(ltype = layertype,
552 if command[0]
not in (
'r.mapcalc',
'r3.mapcalc'):
554 task = GUI(show =
None).ParseCommand(command)
555 except GException, e:
556 GError(parent = self,
557 message = unicode(e),
558 showTraceback =
False)
562 options = task.get_options()
563 hasParams = options[
'params']
and options[
'flags']
565 for p
in options[
'params']:
566 if p.get(
'prompt',
'') ==
'input' and \
567 p.get(
'element',
'') ==
'file' and \
568 p.get(
'age',
'new') ==
'old' and \
569 p.get(
'value',
'') ==
'-':
570 GError(parent = self,
571 message = _(
"Unable to run command:\n%(cmd)s\n\n"
572 "Option <%(opt)s>: read from standard input is not "
573 "supported by wxGUI") % {
'cmd':
' '.join(command),
574 'opt': p.get(
'name',
'') })
579 if len(command) == 1
and hasParams
and \
580 command[0] !=
'v.krige.py':
583 GUI(parent = self).ParseCommand(command)
584 except GException, e:
585 print >> sys.stderr, e
590 self._notebook.SetSelectionByName(
'output')
592 self.parent.SetFocus()
598 tmpreg = os.getenv(
"GRASS_REGION")
599 if "GRASS_REGION" in os.environ:
600 del os.environ[
"GRASS_REGION"]
604 onDone = onDone, onPrepare = onPrepare, userData = userData,
605 env = os.environ.copy())
606 self.cmdOutputTimer.Start(50)
609 if compReg
and tmpreg:
610 os.environ[
"GRASS_REGION"] = tmpreg
614 if len(command) == 1
and not skipInterface:
616 task = gtask.parse_interface(command[0])
624 GUI(parent = self).ParseCommand(command)
627 onDone = onDone, onPrepare = onPrepare, userData = userData)
628 self.cmdOutputTimer.Start(50)
631 """!Clear content of output window"""
632 self.cmdOutput.SetReadOnly(
False)
633 self.cmdOutput.ClearAll()
634 self.cmdOutput.SetReadOnly(
True)
635 self.progressbar.SetValue(0)
638 """!Return progress bar widget"""
642 """!Get widget used for logging
644 @param err True to get stderr widget
652 """!Save (selected) text from output window to the file"""
653 text = self.cmdOutput.GetSelectedText()
655 text = self.cmdOutput.GetText()
658 if len(text) > 0
and text[-1] !=
'\n':
661 dlg = wx.FileDialog(self, message = _(
"Save file as..."),
662 defaultFile =
"grass_cmd_output.txt",
663 wildcard = _(
"%(txt)s (*.txt)|*.txt|%(files)s (*)|*") %
664 {
'txt': _(
"Text files"),
'files': _(
"Files")},
665 style = wx.SAVE | wx.FD_OVERWRITE_PROMPT)
669 if dlg.ShowModal() == wx.ID_OK:
673 output = open(path,
"w")
676 GError(_(
"Unable to write file '%(path)s'.\n\nDetails: %(error)s") % {
'path': path,
'error': e})
679 message = _(
"Command output saved into '%s'") % path
680 if hasattr(self.
parent,
'SetStatusText'):
681 self.parent.SetStatusText(message)
683 self.parent.parent.SetStatusText(message)
688 """!Get running command or None"""
689 return self.requestQ.get()
692 """!Enable or disable copying of selected text in to clipboard.
693 Effects prompt and output.
695 @param copy True for enable, False for disable
698 self.cmdPrompt.Bind(stc.EVT_STC_PAINTED, self.cmdPrompt.OnTextSelectionChanged)
699 self.cmdOutput.Bind(stc.EVT_STC_PAINTED, self.cmdOutput.OnTextSelectionChanged)
701 self.cmdPrompt.Unbind(stc.EVT_STC_PAINTED)
702 self.cmdOutput.Unbind(stc.EVT_STC_PAINTED)
705 """!Update statusbar text"""
706 if event.GetString():
707 nItems = len(self.cmdPrompt.GetCommandItems())
708 self.parent.SetStatusText(_(
'%d modules match') % nItems, 0)
710 self.parent.SetStatusText(
'', 0)
715 """!Print command output"""
718 if self._notebook.GetSelection() != self._notebook.GetPageIndexByName(
'output'):
719 page = self._notebook.GetPageIndexByName(
'output')
720 textP = self._notebook.GetPageText(page)
723 self._notebook.SetPageText(page, textP)
726 if type ==
'warning':
727 message =
'WARNING: ' + message
728 elif type ==
'error':
729 message =
'ERROR: ' + message
731 p1 = self.cmdOutput.GetEndStyled()
732 self.cmdOutput.GotoPos(p1)
743 pos = self.cmdOutput.GetCurLine()[1]
746 self.cmdOutput.SetCurrentPos(self.
linePos)
747 self.cmdOutput.ReplaceSelection(c)
748 self.
linePos = self.cmdOutput.GetCurrentPos()
751 if last_c
not in (
'0123456789'):
752 self.cmdOutput.AddTextWrapped(
'\n', wrap =
None)
756 if '\n' not in message:
757 self.cmdOutput.AddTextWrapped(message, wrap = 60)
759 self.cmdOutput.AddTextWrapped(message, wrap =
None)
761 p2 = self.cmdOutput.GetCurrentPos()
764 self.cmdOutput.StartStyling(p1, 0xff)
767 self.cmdOutput.SetStyling(p2 - p1, self.cmdOutput.StyleError)
768 elif type ==
'warning':
769 self.cmdOutput.SetStyling(p2 - p1, self.cmdOutput.StyleWarning)
770 elif type ==
'message':
771 self.cmdOutput.SetStyling(p2 - p1, self.cmdOutput.StyleMessage)
773 self.cmdOutput.SetStyling(p2 - p1, self.cmdOutput.StyleUnknown)
775 self.cmdOutput.EnsureCaretVisible()
778 """!Update progress message info"""
779 self.progressbar.SetValue(event.value)
782 """Save list of manually entered commands into a text log file"""
783 if not hasattr(self,
'cmdFileProtocol'):
788 cmds = self.cmdPrompt.GetCommands()
789 output.write(
'\n'.join(cmds))
793 GError(_(
"Unable to write file '%(filePath)s'.\n\nDetails: %(error)s") %
798 self.parent.SetStatusText(_(
"Command log saved to '%s'") % self.
cmdFileProtocol)
802 """!Save commands into file"""
803 if not event.IsChecked():
809 self.cmdPrompt.ClearCommands()
811 dlg = wx.FileDialog(self, message = _(
"Save file as..."),
812 defaultFile =
"grass_cmd_log.txt",
813 wildcard = _(
"%(txt)s (*.txt)|*.txt|%(files)s (*)|*") %
814 {
'txt': _(
"Text files"),
'files': _(
"Files")},
816 if dlg.ShowModal() == wx.ID_OK:
819 wx.CallAfter(self.btnCmdProtocol.SetValue,
False)
826 """!Abort running command"""
827 self.cmdThread.abort()
831 if self.parent.GetName() ==
'Modeler':
832 self.parent.OnCmdRun(event)
834 self.
WriteCmdLog(
'(%s)\n%s' % (str(time.ctime()),
' '.join(event.cmd)))
835 self.btnCmdAbort.Enable()
838 """!Prepare for running command"""
839 if self.parent.GetName() ==
'Modeler':
840 self.parent.OnCmdPrepare(event)
845 """!Command done (or aborted)"""
846 if self.parent.GetName() ==
'Modeler':
847 self.parent.OnCmdDone(event)
851 ctime = time.time() - event.time
853 stime = _(
"%d sec") %
int(ctime)
855 mtime =
int(ctime / 60)
856 stime = _(
"%(min)d min %(sec)d sec") % {
'min' : mtime,
857 'sec' :
int(ctime - (mtime * 60)) }
864 self.
WriteLog(_(
'Please note that the data are left in inconsistent state '
865 'and may be corrupted'), self.cmdOutput.StyleWarning)
866 msg = _(
'Command aborted')
868 msg = _(
'Command finished')
870 self.
WriteCmdLog(
'(%s) %s (%s)' % (str(time.ctime()), msg, stime))
871 self.btnCmdAbort.Enable(
False)
874 event.onDone(cmd = event.cmd, returncode = event.returncode)
876 self.progressbar.SetValue(0)
878 self.cmdOutputTimer.Stop()
880 if event.cmd[0] ==
'g.gisenv':
884 if self.parent.GetName() ==
"LayerManager":
885 self.btnCmdAbort.Enable(
False)
886 if event.cmd[0]
not in globalvar.grassCmd
or \
887 event.cmd[0]
in (
'r.mapcalc',
'r3.mapcalc'):
890 tree = self.parent.GetLayerTree()
893 display = tree.GetMapDisplay()
894 if not display
or not display.IsAutoRendered():
896 mapLayers = map(
lambda x: x.GetName(),
897 display.GetMap().GetListOfLayers(l_type =
'raster') +
898 display.GetMap().GetListOfLayers(l_type =
'vector'))
901 task = GUI(show =
None).ParseCommand(event.cmd)
902 except GException, e:
903 print >> sys.stderr, e
907 for p
in task.get_options()[
'params']:
908 if p.get(
'prompt',
'')
not in (
'raster',
'vector'):
910 mapName = p.get(
'value',
'')
911 if '@' not in mapName:
912 mapName = mapName +
'@' + grass.gisenv()[
'MAPSET']
913 if mapName
in mapLayers:
914 display.GetWindow().UpdateMap(render =
True)
916 elif self.parent.GetName() ==
'Modeler':
919 dialog = self.parent.parent
920 if hasattr(self.parent.parent,
"btn_abort"):
921 dialog.btn_abort.Enable(
False)
923 if hasattr(self.parent.parent,
"btn_cancel"):
924 dialog.btn_cancel.Enable(
True)
926 if hasattr(self.parent.parent,
"btn_clipboard"):
927 dialog.btn_clipboard.Enable(
True)
929 if hasattr(self.parent.parent,
"btn_help"):
930 dialog.btn_help.Enable(
True)
932 if hasattr(self.parent.parent,
"btn_run"):
933 dialog.btn_run.Enable(
True)
935 if event.returncode == 0
and not event.aborted:
937 winName = self.parent.parent.parent.GetName()
938 except AttributeError:
941 if winName ==
'LayerManager':
942 mapTree = self.parent.parent.parent.GetLayerTree()
943 elif winName ==
'LayerTree':
944 mapTree = self.parent.parent.parent
946 mapTree = self.parent.parent.parent.parent.GetLayerTree()
950 cmd = dialog.notebookpanel.createCmd(ignoreErrors =
True)
951 if mapTree
and hasattr(dialog,
"addbox")
and dialog.addbox.IsChecked():
953 for p
in dialog.task.get_options()[
'params']:
954 prompt = p.get(
'prompt',
'')
955 if prompt
in (
'raster',
'vector',
'3d-raster')
and \
956 p.get(
'age',
'old') ==
'new' and \
957 p.get(
'value',
None):
959 param = p.get(
'name',
''))
961 if mapTree.GetMap().GetListOfLayers(l_name = name):
962 display = mapTree.GetMapDisplay()
963 if display
and display.IsAutoRendered():
964 display.GetWindow().UpdateMap(render =
True)
967 if prompt ==
'raster':
970 elif prompt ==
'3d-raster':
976 mapTree.AddLayer(ltype = prompt,
980 if hasattr(dialog,
"get_dcmd")
and \
981 dialog.get_dcmd
is None and \
982 hasattr(dialog,
"closebox")
and \
983 dialog.closebox.IsChecked()
and \
984 (event.returncode == 0
or event.aborted):
985 self.cmdOutput.Update()
990 wx.GetApp().ProcessPendingEvents()
994 self.cmdPrompt.SetFocus()
1001 """!GMConsole standard output
1003 Based on FrameOutErr.py
1005 Name: FrameOutErr.py
1006 Purpose: Redirecting stdout / stderr
1007 Author: Jean-Michel Fauth, Switzerland
1008 Copyright: (c) 2005-2007 Jean-Michel Fauth
1015 if len(s) == 0
or s ==
'\n':
1018 for line
in s.splitlines():
1022 evt = wxCmdOutput(text = line +
'\n',
1024 wx.PostEvent(self.parent.cmdOutput, evt)
1027 """!GMConsole standard error output
1029 Based on FrameOutErr.py
1031 Name: FrameOutErr.py
1032 Purpose: Redirecting stdout / stderr
1033 Author: Jean-Michel Fauth, Switzerland
1034 Copyright: (c) 2005-2007 Jean-Michel Fauth
1054 for line
in s.splitlines():
1058 if 'GRASS_INFO_PERCENT' in line:
1059 value =
int(line.rsplit(
':', 1)[1].strip())
1060 if value >= 0
and value < 100:
1061 progressValue = value
1064 elif 'GRASS_INFO_MESSAGE' in line:
1065 self.type =
'message'
1066 self.message += line.split(
':', 1)[1].strip() +
'\n'
1067 elif 'GRASS_INFO_WARNING' in line:
1068 self.type =
'warning'
1069 self.message += line.split(
':', 1)[1].strip() +
'\n'
1070 elif 'GRASS_INFO_ERROR' in line:
1072 self.message += line.split(
':', 1)[1].strip() +
'\n'
1073 elif 'GRASS_INFO_END' in line:
1074 self.printMessage =
True
1075 elif self.type ==
'':
1078 evt = wxCmdOutput(text = line,
1080 wx.PostEvent(self.parent.cmdOutput, evt)
1082 self.message += line.strip() +
'\n'
1084 if self.printMessage
and len(self.message) > 0:
1085 evt = wxCmdOutput(text = self.message,
1087 wx.PostEvent(self.parent.cmdOutput, evt)
1091 self.printMessage =
False
1094 if progressValue > -1:
1096 evt = wxCmdProgress(value = progressValue)
1097 wx.PostEvent(self.parent.progressbar, evt)
1100 """!Styled GMConsole
1102 Based on FrameOutErr.py
1104 Name: FrameOutErr.py
1105 Purpose: Redirecting stdout / stderr
1106 Author: Jean-Michel Fauth, Switzerland
1107 Copyright: (c) 2005-2007 Jean-Michel Fauth
1110 def __init__(self, parent, id, margin = False, wrap = None):
1111 stc.StyledTextCtrl.__init__(self, parent, id)
1113 self.SetUndoCollection(
True)
1114 self.SetReadOnly(
True)
1125 self.SetMarginWidth(1, 0)
1126 self.SetMarginWidth(2, 0)
1128 self.SetMarginType(0, stc.STC_MARGIN_NUMBER)
1129 self.SetMarginWidth(0, 30)
1131 self.SetMarginWidth(0, 0)
1136 self.SetViewWhiteSpace(
False)
1138 self.SetUseTabs(
False)
1140 self.SetSelBackground(
True,
"#FFFF00")
1141 self.SetUseHorizontalScrollBar(
True)
1146 self.Bind(wx.EVT_WINDOW_DESTROY, self.
OnDestroy)
1149 """!Copy selected text to clipboard and skip event.
1150 The same function is in TextCtrlAutoComplete class (prompt.py).
1156 """!Set styles for styled text output windows with type face
1157 and point size selected by user (Courier New 10 is default)"""
1159 typeface = UserSettings.Get(group =
'appearance', key =
'outputfont', subkey =
'type')
1161 typeface =
"Courier New"
1163 typesize = UserSettings.Get(group =
'appearance', key =
'outputfont', subkey =
'size')
1164 if typesize ==
None or typesize <= 0:
1166 typesize = float(typesize)
1173 self.
StyleOutputSpec =
"face:%s,size:%d,,fore:#000000,back:#FFFFFF" % (typeface, typesize)
1176 self.
StyleErrorSpec =
"face:%s,size:%d,,fore:#7F0000,back:#FFFFFF" % (typeface, typesize)
1189 self.StyleClearAll()
1198 """!The clipboard contents can be preserved after
1199 the app has exited"""
1201 wx.TheClipboard.Flush()
1205 """!Add string to text area.
1207 String is wrapped and linesep is also added to the end
1210 self.SetReadOnly(
False)
1213 txt = textwrap.fill(txt, wrap) +
'\n'
1219 self.parent.linePos = -1
1220 for seg
in txt.split(
'\r'):
1221 if self.parent.linePos > -1:
1222 self.SetCurrentPos(self.parent.linePos)
1223 self.ReplaceSelection(seg)
1225 self.parent.linePos = self.GetCurrentPos()
1228 self.parent.linePos = self.GetCurrentPos()
1231 except UnicodeDecodeError:
1232 enc = UserSettings.Get(group =
'atm', key =
'encoding', subkey =
'value')
1234 txt = unicode(txt, enc)
1235 elif 'GRASS_DB_ENCODING' in os.environ:
1236 txt = unicode(txt, os.environ[
'GRASS_DB_ENCODING'])
1243 self.SetReadOnly(
True)
1246 """!Styled Python output (see gmodeler::frame::PythonPanel for
1249 Based on StyledTextCtrl_2 from wxPython demo
1251 def __init__(self, parent, id = wx.ID_ANY, statusbar = None):
1252 stc.StyledTextCtrl.__init__(self, parent, id)
1259 self.
faces = {
'times':
'Times New Roman',
1260 'mono' :
'Courier New',
1262 'other':
'Comic Sans MS',
1267 self.CmdKeyAssign(ord(
'B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
1268 self.CmdKeyAssign(ord(
'N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
1270 self.SetLexer(stc.STC_LEX_PYTHON)
1271 self.SetKeyWords(0,
" ".join(keyword.kwlist))
1273 self.SetProperty(
"fold",
"1")
1274 self.SetProperty(
"tab.timmy.whinge.level",
"1")
1275 self.SetMargins(0, 0)
1277 self.SetUseTabs(
False)
1279 self.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
1280 self.SetEdgeColumn(78)
1283 self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
1284 self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
1285 self.SetMarginSensitive(2,
True)
1286 self.SetMarginWidth(2, 12)
1289 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS,
"white",
"#808080")
1290 self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS,
"white",
"#808080")
1291 self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE,
"white",
"#808080")
1292 self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER,
"white",
"#808080")
1293 self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED,
"white",
"#808080")
1294 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED,
"white",
"#808080")
1295 self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER,
"white",
"#808080")
1297 self.Bind(stc.EVT_STC_UPDATEUI, self.
OnUpdateUI)
1306 self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
"face:%(helv)s,size:%(size)d" % self.
faces)
1307 self.StyleClearAll()
1310 self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
"face:%(helv)s,size:%(size)d" % self.
faces)
1311 self.StyleSetSpec(stc.STC_STYLE_LINENUMBER,
"back:#C0C0C0,face:%(helv)s,size:%(size2)d" % self.
faces)
1312 self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR,
"face:%(other)s" % self.
faces)
1313 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,
"fore:#FFFFFF,back:#0000FF,bold")
1314 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,
"fore:#000000,back:#FF0000,bold")
1318 self.StyleSetSpec(stc.STC_P_DEFAULT,
"fore:#000000,face:%(helv)s,size:%(size)d" % self.
faces)
1320 self.StyleSetSpec(stc.STC_P_COMMENTLINE,
"fore:#007F00,face:%(other)s,size:%(size)d" % self.
faces)
1322 self.StyleSetSpec(stc.STC_P_NUMBER,
"fore:#007F7F,size:%(size)d" % self.
faces)
1324 self.StyleSetSpec(stc.STC_P_STRING,
"fore:#7F007F,face:%(helv)s,size:%(size)d" % self.
faces)
1326 self.StyleSetSpec(stc.STC_P_CHARACTER,
"fore:#7F007F,face:%(helv)s,size:%(size)d" % self.
faces)
1328 self.StyleSetSpec(stc.STC_P_WORD,
"fore:#00007F,bold,size:%(size)d" % self.
faces)
1330 self.StyleSetSpec(stc.STC_P_TRIPLE,
"fore:#7F0000,size:%(size)d" % self.
faces)
1332 self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE,
"fore:#7F0000,size:%(size)d" % self.
faces)
1334 self.StyleSetSpec(stc.STC_P_CLASSNAME,
"fore:#0000FF,bold,underline,size:%(size)d" % self.
faces)
1336 self.StyleSetSpec(stc.STC_P_DEFNAME,
"fore:#007F7F,bold,size:%(size)d" % self.
faces)
1338 self.StyleSetSpec(stc.STC_P_OPERATOR,
"bold,size:%(size)d" % self.
faces)
1340 self.StyleSetSpec(stc.STC_P_IDENTIFIER,
"fore:#000000,face:%(helv)s,size:%(size)d" % self.
faces)
1342 self.StyleSetSpec(stc.STC_P_COMMENTBLOCK,
"fore:#7F7F7F,size:%(size)d" % self.
faces)
1344 self.StyleSetSpec(stc.STC_P_STRINGEOL,
"fore:#000000,face:%(mono)s,back:#E0C0E0,eol,size:%(size)d" % self.
faces)
1346 self.SetCaretForeground(
"BLUE")
1351 @todo implement code completion (see wxPython demo)
1356 self.statusbar.SetStatusText(_(
'Python script contains local modifications'), 0)
1365 caretPos = self.GetCurrentPos()
1368 charBefore = self.GetCharAt(caretPos - 1)
1369 styleBefore = self.GetStyleAt(caretPos - 1)
1372 if charBefore
and chr(charBefore)
in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
1373 braceAtCaret = caretPos - 1
1376 if braceAtCaret < 0:
1377 charAfter = self.GetCharAt(caretPos)
1378 styleAfter = self.GetStyleAt(caretPos)
1380 if charAfter
and chr(charAfter)
in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
1381 braceAtCaret = caretPos
1383 if braceAtCaret >= 0:
1384 braceOpposite = self.BraceMatch(braceAtCaret)
1386 if braceAtCaret != -1
and braceOpposite == -1:
1387 self.BraceBadLight(braceAtCaret)
1389 self.BraceHighlight(braceAtCaret, braceOpposite)
1393 if evt.GetMargin() == 2:
1394 if evt.GetShift()
and evt.GetControl():
1397 lineClicked = self.LineFromPosition(evt.GetPosition())
1399 if self.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
1401 self.SetFoldExpanded(lineClicked,
True)
1402 self.
Expand(lineClicked,
True,
True, 1)
1403 elif evt.GetControl():
1404 if self.GetFoldExpanded(lineClicked):
1405 self.SetFoldExpanded(lineClicked,
False)
1406 self.
Expand(lineClicked,
False,
True, 0)
1408 self.SetFoldExpanded(lineClicked,
True)
1409 self.
Expand(lineClicked,
True,
True, 100)
1411 self.ToggleFold(lineClicked)
1414 lineCount = self.GetLineCount()
1418 for lineNum
in range(lineCount):
1419 if self.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG:
1420 expanding =
not self.GetFoldExpanded(lineNum)
1424 while lineNum < lineCount:
1425 level = self.GetFoldLevel(lineNum)
1426 if level & stc.STC_FOLDLEVELHEADERFLAG
and \
1427 (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
1430 self.SetFoldExpanded(lineNum,
True)
1431 lineNum = self.
Expand(lineNum,
True)
1432 lineNum = lineNum - 1
1434 lastChild = self.GetLastChild(lineNum, -1)
1435 self.SetFoldExpanded(lineNum,
False)
1437 if lastChild > lineNum:
1438 self.HideLines(lineNum+1, lastChild)
1440 lineNum = lineNum + 1
1442 def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
1443 lastChild = self.GetLastChild(line, level)
1446 while line <= lastChild:
1449 self.ShowLines(line, line)
1451 self.HideLines(line, line)
1454 self.ShowLines(line, line)
1457 level = self.GetFoldLevel(line)
1459 if level & stc.STC_FOLDLEVELHEADERFLAG:
1462 self.SetFoldExpanded(line,
True)
1464 self.SetFoldExpanded(line,
False)
1466 line = self.
Expand(line, doExpand, force, visLevels-1)
1468 if doExpand
and self.GetFoldExpanded(line):
1469 line = self.
Expand(line,
True, force, visLevels-1)
1471 line = self.
Expand(line,
False, force, visLevels-1)
def EncodeString
Return encoded string using system locales.
def AddTextWrapped
Add string to text area.
def abort
Abort command(s)
def WriteCmdLog
Write message in selected style.
def OnOutputSave
Save (selected) text from output window to the file.
def OnTextSelectionChanged
Copy selected text to clipboard and skip event.
def SetCopyingOfSelectedText
Enable or disable copying of selected text in to clipboard.
def WriteWarning
Write message in warning style.
def OnCmdOutput
Print command output.
def SetId
Set starting id.
def GetProgressBar
Return progress bar widget.
Create and manage output console for commands run by GUI.
def OnSearchPaneChanged
Collapse search module box.
def GetCmd
Get running command or None.
def GetLog
Get widget used for logging.
GMConsole standard output.
def Redirect
Redirect stdout/stderr.
def OnCmdProgress
Update progress message info.
def RunCmd
Run command typed into console command prompt (GPrompt).
def split
Platform spefic shlex.split.
def MakeSearchPaneContent
Create search pane.
def GetLayerNameFromCmd
Get map name from GRASS command.
def SetStyle
Set styles for styled text output windows with type face and point size selected by user (Courier New...
def WriteLog
Generic method for writing log message in given style.
def OnDestroy
The clipboard contents can be preserved after the app has exited.
Styled Python output (see gmodeler::frame::PythonPanel for usage)
def OnOutputClear
Clear content of output window.
def WriteError
Write message in error style.
def OnKeyPressed
Key pressed.
def GrassCmd
Return GRASS command thread.
def OnUpdateStatusBar
Update statusbar text.
def OnCmdPrepare
Prepare for running command.
def ResetFocus
Reset focus.
def OnCmdAbort
Abort running command.
Thread for GRASS commands.
def OnProcessPendingOutputWindowEvents
def OnCmdDone
Command done (or aborted)
def OnCmdProtocol
Save commands into file.
GMConsole standard error output.