|
@@ -1,4 +1,4 @@
|
|
|
-"""
|
|
|
+"""!
|
|
|
@package goutput
|
|
|
|
|
|
@brief Command output log widget
|
|
@@ -9,7 +9,7 @@ Classes:
|
|
|
- GMStdout
|
|
|
- GMStderr
|
|
|
|
|
|
-(C) 2007-2008 by the GRASS Development Team
|
|
|
+(C) 2007-2009 by the GRASS Development Team
|
|
|
This program is free software under the GNU General Public
|
|
|
License (>=v2). Read the file COPYING that comes with GRASS
|
|
|
for details.
|
|
@@ -36,6 +36,8 @@ import gcmd
|
|
|
import utils
|
|
|
import preferences
|
|
|
import menuform
|
|
|
+import prompt
|
|
|
+
|
|
|
from debug import Debug as Debug
|
|
|
from preferences import globalSettings as UserSettings
|
|
|
|
|
@@ -127,15 +129,17 @@ class CmdThread(threading.Thread):
|
|
|
def abort(self):
|
|
|
self.requestCmd.abort()
|
|
|
|
|
|
-class GMConsole(wx.Panel):
|
|
|
+class GMConsole(wx.SplitterWindow):
|
|
|
"""!Create and manage output console for commands run by GUI.
|
|
|
"""
|
|
|
def __init__(self, parent, id=wx.ID_ANY, margin=False, pageid=0,
|
|
|
notebook = None,
|
|
|
style=wx.TAB_TRAVERSAL | wx.FULL_REPAINT_ON_RESIZE,
|
|
|
**kwargs):
|
|
|
- wx.Panel.__init__(self, parent, id, style = style, *kwargs)
|
|
|
+ wx.SplitterWindow.__init__(self, parent, id, style = style, *kwargs)
|
|
|
self.SetName("GMConsole")
|
|
|
+
|
|
|
+ self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
|
|
|
|
|
|
# initialize variables
|
|
|
self.Map = None
|
|
@@ -146,6 +150,7 @@ class GMConsole(wx.Panel):
|
|
|
self._notebook = self.parent.notebook
|
|
|
self.lineWidth = 80
|
|
|
self.pageid = pageid
|
|
|
+
|
|
|
# remember position of line begining (used for '\r')
|
|
|
self.linePos = -1
|
|
|
|
|
@@ -158,15 +163,10 @@ class GMConsole(wx.Panel):
|
|
|
#
|
|
|
# progress bar
|
|
|
#
|
|
|
- self.console_progressbar = wx.Gauge(parent=self, id=wx.ID_ANY,
|
|
|
+ self.console_progressbar = wx.Gauge(parent=self.panel, id=wx.ID_ANY,
|
|
|
range=100, pos=(110, 50), size=(-1, 25),
|
|
|
style=wx.GA_HORIZONTAL)
|
|
|
self.console_progressbar.Bind(EVT_CMD_PROGRESS, self.OnCmdProgress)
|
|
|
- # abort
|
|
|
- self.btn_abort = wx.Button(parent=self, id=wx.ID_STOP)
|
|
|
- self.btn_abort.SetToolTipString(_("Abort the running command"))
|
|
|
- self.btn_abort.Bind(wx.EVT_BUTTON, self.OnCmdAbort)
|
|
|
- self.btn_abort.Enable(False)
|
|
|
|
|
|
#
|
|
|
# text control for command output
|
|
@@ -178,6 +178,14 @@ class GMConsole(wx.Panel):
|
|
|
self.cmd_output.Bind(wx.EVT_TIMER, self.OnProcessPendingOutputWindowEvents)
|
|
|
self.Bind(EVT_CMD_RUN, self.OnCmdRun)
|
|
|
self.Bind(EVT_CMD_DONE, self.OnCmdDone)
|
|
|
+
|
|
|
+ #
|
|
|
+ # command prompt
|
|
|
+ #
|
|
|
+ self.cmd_prompt = prompt.GPromptSTC(parent = self.panel, id=wx.ID_ANY,
|
|
|
+ onRun = self.RunCmd)
|
|
|
+ if self.parent.GetName() != 'LayerManager':
|
|
|
+ self.cmd_prompt.Hide()
|
|
|
|
|
|
#
|
|
|
# stream redirection
|
|
@@ -193,46 +201,67 @@ class GMConsole(wx.Panel):
|
|
|
#
|
|
|
# buttons
|
|
|
#
|
|
|
- self.console_clear = wx.Button(parent=self, id=wx.ID_CLEAR)
|
|
|
- self.console_save = wx.Button(parent=self, id=wx.ID_SAVE)
|
|
|
- self.Bind(wx.EVT_BUTTON, self.ClearHistory, self.console_clear)
|
|
|
- self.Bind(wx.EVT_BUTTON, self.SaveHistory, self.console_save)
|
|
|
+ self.btn_console_clear = wx.Button(parent = self.panel, id = wx.ID_ANY,
|
|
|
+ label = _("C&lear output"), size=(125,-1))
|
|
|
+ self.btn_cmd_clear = wx.Button(parent = self.panel, id = wx.ID_ANY,
|
|
|
+ label = _("Cl&ear command"), size=(125,-1))
|
|
|
+ if self.parent.GetName() != 'LayerManager':
|
|
|
+ self.btn_cmd_clear.Hide()
|
|
|
+ self.btn_console_save = wx.Button(parent = self.panel, id = wx.ID_ANY,
|
|
|
+ label = _("&Save output"), size=(125,-1))
|
|
|
+ # abort
|
|
|
+ self.btn_abort = wx.Button(parent = self.panel, id = wx.ID_ANY, label = _("&Abort command"),
|
|
|
+ size=(125,-1))
|
|
|
+ self.btn_abort.SetToolTipString(_("Abort the running command"))
|
|
|
+ self.btn_abort.Enable(False)
|
|
|
|
|
|
- self.Bind(EVT_CMD_ABORT, self.OnCmdAbort)
|
|
|
+ self.btn_cmd_clear.Bind(wx.EVT_BUTTON, self.cmd_prompt.OnCmdErase)
|
|
|
+ self.btn_console_clear.Bind(wx.EVT_BUTTON, self.ClearHistory)
|
|
|
+ self.btn_console_save.Bind(wx.EVT_BUTTON, self.SaveHistory)
|
|
|
+ self.btn_abort.Bind(wx.EVT_BUTTON, self.OnCmdAbort)
|
|
|
+ self.btn_abort.Bind(EVT_CMD_ABORT, self.OnCmdAbort)
|
|
|
|
|
|
self.__layout()
|
|
|
|
|
|
def __layout(self):
|
|
|
"""!Do layout"""
|
|
|
- boxsizer1 = wx.BoxSizer(wx.VERTICAL)
|
|
|
- gridsizer1 = wx.GridSizer(rows=1, cols=2, vgap=0, hgap=0)
|
|
|
- boxsizer1.Add(item=self.cmd_output, proportion=1,
|
|
|
- flag=wx.EXPAND | wx.ADJUST_MINSIZE, border=0)
|
|
|
- gridsizer1.Add(item=self.console_clear, proportion=0,
|
|
|
- flag=wx.ALIGN_CENTER_HORIZONTAL | wx.ADJUST_MINSIZE, border=0)
|
|
|
- gridsizer1.Add(item=self.console_save, proportion=0,
|
|
|
- flag=wx.ALIGN_CENTER_HORIZONTAL | wx.ADJUST_MINSIZE, border=0)
|
|
|
-
|
|
|
-
|
|
|
- boxsizer1.Add(item=gridsizer1, proportion=0,
|
|
|
- flag=wx.EXPAND | wx.ALIGN_CENTRE_VERTICAL | wx.TOP | wx.BOTTOM,
|
|
|
- border=5)
|
|
|
- boxsizer2 = wx.BoxSizer(wx.HORIZONTAL)
|
|
|
- boxsizer2.Add(item=self.console_progressbar, proportion=1,
|
|
|
- flag=wx.EXPAND | wx.ALIGN_CENTRE_VERTICAL)
|
|
|
- boxsizer2.Add(item=self.btn_abort, proportion=0,
|
|
|
- flag=wx.ALIGN_CENTRE_VERTICAL | wx.LEFT,
|
|
|
- border = 5)
|
|
|
- boxsizer1.Add(item=boxsizer2, proportion=0,
|
|
|
- flag=wx.EXPAND | wx.ALIGN_CENTRE_VERTICAL | wx.ALL,
|
|
|
- border=5)
|
|
|
-
|
|
|
- boxsizer1.Fit(self)
|
|
|
- boxsizer1.SetSizeHints(self)
|
|
|
+ boxsizer = wx.BoxSizer(wx.VERTICAL)
|
|
|
+ buttonsizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
|
+
|
|
|
+ boxsizer.Add(item=self.cmd_prompt, proportion=1,
|
|
|
+ flag=wx.EXPAND | wx.ALL, border=1)
|
|
|
+
|
|
|
+ buttonsizer.Add(item=self.btn_console_clear, proportion=0,
|
|
|
+ flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE | wx.ALL, border=5)
|
|
|
+ buttonsizer.Add(item=self.btn_console_save, proportion=0,
|
|
|
+ flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE | wx.ALL, border=5)
|
|
|
+ buttonsizer.Add(item=self.btn_cmd_clear, proportion=0,
|
|
|
+ flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE | wx.ALL, border=5)
|
|
|
+ buttonsizer.Add(item=self.btn_abort, proportion=0,
|
|
|
+ flag=wx.ALIGN_CENTER | wx.FIXED_MINSIZE | wx.ALL, border=5)
|
|
|
+ boxsizer.Add(item=buttonsizer, proportion=0,
|
|
|
+ flag=wx.ALIGN_CENTER)
|
|
|
+
|
|
|
+ boxsizer.Add(item=self.console_progressbar, proportion=1,
|
|
|
+ flag=wx.EXPAND | wx.ALIGN_CENTRE_VERTICAL | wx.LEFT | wx.RIGHT | wx.BOTTOM, border=3)
|
|
|
+
|
|
|
+ boxsizer.Fit(self)
|
|
|
+ boxsizer.SetSizeHints(self)
|
|
|
|
|
|
+ self.panel.SetSizer(boxsizer)
|
|
|
+
|
|
|
+ # split window
|
|
|
+ if self.parent.GetName() == 'LayerManager':
|
|
|
+ self.SplitHorizontally(self.cmd_output, self.panel, -75)
|
|
|
+ self.SetMinimumPaneSize(100)
|
|
|
+ else:
|
|
|
+ self.SplitHorizontally(self.cmd_output, self.panel, -10)
|
|
|
+ self.SetMinimumPaneSize(65)
|
|
|
+ self.Fit()
|
|
|
+
|
|
|
# layout
|
|
|
self.SetAutoLayout(True)
|
|
|
- self.SetSizer(boxsizer1)
|
|
|
+ self.Layout()
|
|
|
|
|
|
def Redirect(self):
|
|
|
"""!Redirect stderr
|
|
@@ -270,7 +299,8 @@ class GMConsole(wx.Panel):
|
|
|
|
|
|
# p1 = self.cmd_output.GetCurrentPos()
|
|
|
p1 = self.cmd_output.GetEndStyled()
|
|
|
- self.cmd_output.GotoPos(p1)
|
|
|
+# self.cmd_output.GotoPos(p1)
|
|
|
+ self.cmd_output.DocumentEnd()
|
|
|
|
|
|
for line in text.splitlines():
|
|
|
# fill space
|
|
@@ -350,7 +380,10 @@ class GMConsole(wx.Panel):
|
|
|
self.parent.cmdinput.SetHistoryItems()
|
|
|
except AttributeError:
|
|
|
pass
|
|
|
-
|
|
|
+
|
|
|
+ # allow writing to output window
|
|
|
+ self.cmd_output.SetReadOnly(False)
|
|
|
+
|
|
|
if cmdlist[0] in globalvar.grassCmd['all']:
|
|
|
# send GRASS command without arguments to GUI command interface
|
|
|
# except display commands (they are handled differently)
|
|
@@ -411,7 +444,7 @@ class GMConsole(wx.Panel):
|
|
|
if os.environ.has_key("GRASS_REGION"):
|
|
|
del os.environ["GRASS_REGION"]
|
|
|
|
|
|
- if len(cmdlist) == 1 and cmdlist[0] not in ('v.krige'):
|
|
|
+ if len(cmdlist) == 1:
|
|
|
import menuform
|
|
|
# process GRASS command without argument
|
|
|
menuform.GUI().ParseCommand(cmdlist, parentframe=self)
|
|
@@ -432,13 +465,23 @@ class GMConsole(wx.Panel):
|
|
|
else:
|
|
|
# Send any other command to the shell. Send output to
|
|
|
# console output window
|
|
|
-
|
|
|
- self.cmdThread.RunCmd(GrassCmd,
|
|
|
- onDone,
|
|
|
- cmdlist,
|
|
|
- self.cmd_stdout, self.cmd_stderr)
|
|
|
- self.btn_abort.Enable()
|
|
|
- self.cmd_output_timer.Start(50)
|
|
|
+
|
|
|
+ # if command is not a GRASS command, treat it like a shell command
|
|
|
+ try:
|
|
|
+# gcmd.Command(cmdlist,
|
|
|
+# stdout=self.cmd_stdout,
|
|
|
+# stderr=self.cmd_stderr)
|
|
|
+ self.cmdThread.RunCmd(GrassCmd,
|
|
|
+ onDone,
|
|
|
+ cmdlist,
|
|
|
+ self.cmd_stdout, self.cmd_stderr)
|
|
|
+ self.btn_abort.Enable()
|
|
|
+ self.cmd_output_timer.Start(50)
|
|
|
+ except gcmd.CmdError, e:
|
|
|
+ print >> sys.stderr, e
|
|
|
+
|
|
|
+ # reset output window to read only
|
|
|
+ self.cmd_output.SetReadOnly(True)
|
|
|
|
|
|
return None
|
|
|
|
|
@@ -524,7 +567,7 @@ class GMConsole(wx.Panel):
|
|
|
self.cmd_output.AddTextWrapped(message, wrap=60)
|
|
|
else:
|
|
|
self.cmd_output.AddTextWrapped(message, wrap=None)
|
|
|
-
|
|
|
+
|
|
|
p2 = self.cmd_output.GetCurrentPos()
|
|
|
|
|
|
if p2 >= p1:
|
|
@@ -584,7 +627,7 @@ class GMConsole(wx.Panel):
|
|
|
|
|
|
# set focus on prompt
|
|
|
if self.parent.GetName() == "LayerManager":
|
|
|
- self.parent.cmdinput.SetFocus()
|
|
|
+ self.cmd_prompt.SetFocus()
|
|
|
self.btn_abort.Enable(False)
|
|
|
else:
|
|
|
# updated command dialog
|
|
@@ -634,7 +677,7 @@ class GMConsole(wx.Panel):
|
|
|
dialog.closebox.IsChecked():
|
|
|
time.sleep(1)
|
|
|
dialog.Close()
|
|
|
-
|
|
|
+
|
|
|
event.Skip()
|
|
|
|
|
|
def OnProcessPendingOutputWindowEvents(self, event):
|
|
@@ -750,13 +793,14 @@ class GMStc(wx.stc.StyledTextCtrl):
|
|
|
def __init__(self, parent, id, margin=False, wrap=None):
|
|
|
wx.stc.StyledTextCtrl.__init__(self, parent, id)
|
|
|
self.parent = parent
|
|
|
+ self.SetUndoCollection(True)
|
|
|
+ self.SetReadOnly(True)
|
|
|
|
|
|
#
|
|
|
# styles
|
|
|
#
|
|
|
self.SetStyle()
|
|
|
|
|
|
-
|
|
|
#
|
|
|
# line margins
|
|
|
#
|
|
@@ -780,7 +824,7 @@ class GMStc(wx.stc.StyledTextCtrl):
|
|
|
self.SetUseHorizontalScrollBar(True)
|
|
|
|
|
|
#
|
|
|
- # bindins
|
|
|
+ # bindings
|
|
|
#
|
|
|
self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
|
|
|
|
|
@@ -867,4 +911,3 @@ class GMStc(wx.stc.StyledTextCtrl):
|
|
|
txt = _('Unable to encode text. Please set encoding in GUI preferences.') + '\n'
|
|
|
|
|
|
self.AddText(txt)
|
|
|
-
|