[GRASS-SVN] r40079 - in grass/trunk/gui/wxpython: . gui_modules

svn_grass at osgeo.org svn_grass at osgeo.org
Sat Dec 19 16:35:15 EST 2009


Author: martinl
Date: 2009-12-19 16:35:15 -0500 (Sat, 19 Dec 2009)
New Revision: 40079

Modified:
   grass/trunk/gui/wxpython/gui_modules/goutput.py
   grass/trunk/gui/wxpython/gui_modules/prompt.py
   grass/trunk/gui/wxpython/wxgui.py
Log:
cmbarton: Advanced grass command console. Try again with repaired subversion
installation (merge r40068 from devbr6)
martinl: Various fixes (merge r40071, r40072, r40073, r40074, r40077
from devbr6)


Modified: grass/trunk/gui/wxpython/gui_modules/goutput.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/goutput.py	2009-12-19 21:25:49 UTC (rev 40078)
+++ grass/trunk/gui/wxpython/gui_modules/goutput.py	2009-12-19 21:35:15 UTC (rev 40079)
@@ -1,4 +1,4 @@
-"""
+"""!
 @package goutput
 
 @brief Command output log widget
@@ -9,7 +9,7 @@
  - 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 utils
 import preferences
 import menuform
+import prompt
+
 from debug import Debug as Debug
 from preferences import globalSettings as UserSettings
 
@@ -127,15 +129,17 @@
     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 @@
             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 @@
         #
         # 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 @@
         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 @@
         #
         # 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)
+        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)
 
-
-        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)
+        self.panel.SetSizer(boxsizer)
         
-        boxsizer1.Fit(self)
-        boxsizer1.SetSizeHints(self)
-
+        # 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 @@
         
         # 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 @@
                 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 @@
                     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,14 +465,24 @@
         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
 
     def ClearHistory(self, event):
@@ -524,7 +567,7 @@
                 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 @@
 
         # 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 @@
                     dialog.closebox.IsChecked():
                 time.sleep(1)
                 dialog.Close()
-        
+
         event.Skip()
         
     def OnProcessPendingOutputWindowEvents(self, event):
@@ -750,13 +793,14 @@
     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 @@
         self.SetUseHorizontalScrollBar(True)
 
         #
-        # bindins
+        # bindings
         #
         self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
         
@@ -867,4 +911,3 @@
                     txt = _('Unable to encode text. Please set encoding in GUI preferences.') + '\n'
                     
                 self.AddText(txt) 
-    

Modified: grass/trunk/gui/wxpython/gui_modules/prompt.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/prompt.py	2009-12-19 21:25:49 UTC (rev 40078)
+++ grass/trunk/gui/wxpython/gui_modules/prompt.py	2009-12-19 21:35:15 UTC (rev 40079)
@@ -4,12 +4,12 @@
 @brief wxGUI prompt
 
 Classes:
- - GPrompt
+ - GPromptPopUp
  - PromptListCtrl
  - TextCtrlAutoComplete
+ - GPromptSTC
 
- at todo: fix TextCtrlAutoComplete to work also on Macs (missing
-wx.PopupWindow())
+ at todo: reduce size of STC prompt to about 3 lines
 
 (C) 2009 by the GRASS Development Team
 This program is free software under the GNU General Public
@@ -17,6 +17,7 @@
 for details.
 
 @author Martin Landa <landa.martin gmail.com>
+ at author Michael Barton <michael.barton at asu.edu>
 """
 
 import os
@@ -24,16 +25,16 @@
 import shlex
 
 import wx
+import wx.stc
 import wx.lib.mixins.listctrl as listmix
 
 from grass.script import core as grass
 
 import globalvar
-import utils
-import menuform
 import menudata
+import gcmd
 
-class GPrompt:
+class GPromptPopUp:
     """!Interactive GRASS prompt"""
     def __init__(self, parent):
         self.parent = parent # GMFrame
@@ -664,3 +665,438 @@
             self._showDropDown(False)
         
         event.Skip()
+
+class GPromptSTC(wx.stc.StyledTextCtrl):
+    """!Styled GRASS prompt with autocomplete and calltips"""    
+    def __init__(self, parent, id, onRun, margin=False, wrap=None):
+        wx.stc.StyledTextCtrl.__init__(self, parent, id)
+        self.parent = parent
+        self.SetUndoCollection(True)        
+        self.RunCmd = onRun
+        
+        #
+        # styles
+        #                
+        self.SetWrapMode(True)
+        
+        #
+        # create command and map lists for autocompletion
+        #
+        self.AutoCompSetIgnoreCase(False) 
+        
+        self.rastlist = []
+        self.vectlist = []
+        self.imglist = []
+        self.r3list = []
+        self.dblist = []
+        self.genlist = []
+        self.displist = []
+        
+        #
+        # Get available GRASS commands and parse into lists by command type for autocomplete
+        #
+        for item in globalvar.grassCmd['all']:
+            if len(item.split('.')) > 1:
+                start,end = item.split('.',1)
+                if start == 'r': self.rastlist.append(end)
+                elif start == 'v': self.vectlist.append(end)
+                elif start == 'i': self.imglist.append(end)
+                elif start == 'r3': self.r3list.append(end)
+                elif start == 'db': self.dblist.append(end)
+                elif start == 'g': self.genlist.append(end)
+                elif start == 'd': self.displist.append(end)
+
+        self.rastlist.sort()
+        self.vectlist.sort()
+        self.imglist.sort()
+        self.r3list.sort()
+        self.dblist.sort()
+        self.genlist.sort()
+        self.displist.sort()
+                        
+        #
+        # Create lists of element types and possible arguments for autocomplete
+        #
+        self.datatypes = []
+        self.maplists = {}
+        self.maptype = ''
+        self.datatypes = ['rast',
+                        'rast3d',
+                        'vect',
+                        'oldvect',
+                        'asciivect',
+                        'labels',
+                        'region',
+                        'region3d',
+                        'group',
+                        '3dview']
+
+        self.drastcmd = ['d.rast',
+                        'd.rgb',
+                        'd.his',
+                        'd.rast.arrow',
+                        'd.rast.num']
+                    
+        self.dvectcmd = ['d.vect',
+                        'd.vect.chart'
+                        'd.thematic.area',
+                        'd.vect.thematic']
+        
+        self.rastargs = ['map',
+                        'input',
+                        'rast',
+                        'raster',
+                        'red',
+                        'green',
+                        'blue',
+                        'h_map',
+                        'i_map',
+                        's_map',
+                        'hue_input',
+                        'intensity_input',
+                        'saturation_input',
+                        'red_input',
+                        'green_input',
+                        'blue_input']
+                        
+        self.__getfiles()
+
+        #
+        # command history buffer
+        #
+        self.cmdbuffer = []
+        self.cmdindex = 0
+
+        #
+        # line margins
+        #
+        # TODO print number only from cmdlog
+        self.SetMarginWidth(1, 0)
+        self.SetMarginWidth(2, 0)
+        if margin:
+            self.SetMarginType(0, wx.stc.STC_MARGIN_NUMBER)
+            self.SetMarginWidth(0, 30)
+        else:
+            self.SetMarginWidth(0, 0)
+
+        #
+        # miscellaneous
+        #
+        self.SetViewWhiteSpace(False)
+#        self.SetTabWidth(4)
+        self.SetUseTabs(False)
+        self.UsePopUp(True)
+        self.SetSelBackground(True, "#FFFF00")
+        self.SetUseHorizontalScrollBar(True)
+
+        #
+        # bindings
+        #
+        self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
+        self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
+ 
+    def __getfiles(self):   
+        """!Get accessible files for autocomplete"""
+        for item in self.datatypes:
+            mlist = grass.read_command("g.mlist", "m", type=item).splitlines()
+            mlist.sort()
+            self.maplists[item] = mlist
+            
+    def OnKeyPressed(self, event):
+        """!Key press capture for autocompletion, calltips, and command history"""
+        
+        #keycodes used: "." = 46, "=" = 61, "," = 44 
+        line = ''
+        entry = ''
+        usage = ''
+        cmdtype = ''
+        cmdname = ''
+        cmd = ''
+                            
+        # CAN CHANGE: event.ControlDown() for manual autocomplete
+        
+        if event.GetKeyCode() == 46 and not event.ShiftDown():
+            #GRASS command autocomplete when "." is pressed after r,v,i,g,db, or d
+            listcmds = []
+            pos = self.GetCurrentPos()
+            self.InsertText(pos,'.')
+            self.CharRight()
+            
+            entry = self.GetTextLeft()
+            if entry not in ['r.','v.','i.','g.','db.','d.']:
+                return
+
+            if entry == 'r.': listcmds = self.rastlist
+            elif entry == 'v.': listcmds = self.vectlist
+            elif entry == 'i.': listcmds = self.imglist
+            elif entry == 'r3.': listcmds = self.r3list
+            elif entry == 'db.': listcmds = self.dblist
+            elif entry == 'g.': listcmds = self.genlist
+            elif entry == 'd.': listcmds = self.displist
+
+            if listcmds == []:
+                return
+            else:
+                self.AutoCompShow(0, " ".join(listcmds))                    
+            
+        elif event.GetKeyCode() == wx.WXK_TAB:
+            #GRASS command calltips
+                        
+            #Must be a command to the left somewhere
+            pos = self.GetCurrentPos()
+            entry = self.GetTextLeft()
+            cmd = entry.split()[0].strip()
+            if cmd not in globalvar.grassCmd['all']:
+                return
+            
+            usage, description = self.GetCommandUsage(cmd)
+                                        
+            self.CallTipSetBackground("PALE GREEN")
+            self.CallTipSetForeground("BLACK")
+            self.CallTipShow(pos, usage+'\n\n'+description)
+            
+        elif (event.GetKeyCode() == wx.WXK_SPACE and event.ControlDown()) or \
+            event.GetKeyCode() == 61 or event.GetKeyCode() == 44:
+            #Autocompletion for map/data file name entry after '=', ',', or manually
+            
+            pos = self.GetCurrentPos()
+            entry = self.GetTextLeft()
+            if event.GetKeyCode() != 44:
+                self.maptype = ''
+            arg = ''
+            cmdtype = ''
+            cmdname = ''
+            cmd = ''
+
+            if entry.strip()[0:2] in ['r.','v.','i.','g.','db.','d.']:
+                cmdtype =  entry.strip()[0]
+                cmd = entry.split()[0].strip()
+                if cmd in globalvar.grassCmd['all']:
+                    cmdname = cmd.split('.')[1]
+                else:
+                    #No complete GRASS command found
+                    cmd = ''
+                    cmdname = ''
+            elif entry.strip()[0:4] == 'nviz':
+                cmdtype = ''
+                cmdname = cmd = 'nviz'
+            else:
+                #No partial or complete GRASS command found
+                return
+
+            cmdargs = entry.strip('=')
+            try:
+                arg = cmdargs.rsplit(' ',1)[1]
+            except:
+                arg = ''
+                
+            if event.GetKeyCode() == 61:
+                # autocompletion after '='
+                # insert the '=' and move to after the '=', ready for a map name
+                self.InsertText(pos,'=')
+                self.CharRight()
+
+                maplist = []
+                self.maptype = ''
+
+                # what kind of map/data type is desired?
+                if (((cmdtype in ['r', 'i'] or cmd in self.drastcmd) and arg in self.rastargs) or
+                  ((cmd=='nviz' or cmdtype=='r3') and arg in ['elevation','color']) or
+                  arg in ['rast', 'raster']):
+                    self.maptype = 'rast'
+                elif (((cmdtype=='v' or cmd in self.dvectcmd) and arg in ['map', 'input']) or
+                  (cmdtype=='r3' and arg=='input') or
+                  arg in ['vect', 'vector', 'points']):
+                    self.maptype = 'vect'
+                elif ((cmdtype=='r3' and arg in ['map', 'input']) or
+                  (cmdtype=='nviz' and arg=='volume') or arg=='rast3d'):
+                    self.maptype = 'rast3d'
+                elif arg=='labels':
+                    self.maptype ='labels'
+                elif arg=='region':
+                    self.maptype ='region'
+                elif arg=='region3d':
+                    self.maptype ='region3d'
+                elif arg=='group':
+                    self.maptype ='group'
+                elif arg=='3dview':
+                    self.maptype ='3dview'
+                
+            elif event.GetKeyCode() == 44:
+                # autocompletion after ','
+                # if comma is pressed, use the same maptype as previous for multiple map entries
+                
+                # insert the comma and move to after the comma ready for a map name
+                self.InsertText(pos,',')
+                self.CharRight()
+                
+                #must apply to an entry where '=[string]' has already been entered
+                if '=' not in arg:
+                    return
+
+            elif event.GetKeyCode() == wx.WXK_SPACE and event.ControlDown():
+                # manual autocompletion
+                # map entries without arguments (as in r.info [mapname]) use ctrl-shift
+                
+                maplist = []
+                if cmdtype=='r' or cmdtype=='i':
+                    self.maptype = 'rast'
+                elif cmdtype=='v':
+                    self.maptype = 'vect'
+                elif cmdtype=='r3':
+                    self.maptype = 'rast3d'
+                    
+            if self.maptype == '': 
+                return
+            else:
+                maplist = self.maplists[self.maptype]
+                self.AutoCompShow(0, " ".join(maplist))
+                        
+        elif event.GetKeyCode() in [wx.WXK_UP,wx.WXK_DOWN] and event.ControlDown():
+            # Command history using ctrl-up and ctrl-down   
+            
+            if self.cmdbuffer == []: return
+            txt = ''
+
+            self.DocumentEnd()
+            
+            # move through command history list index values
+            if event.GetKeyCode() == wx.WXK_UP:
+                self.cmdindex = self.cmdindex - 1
+            if event.GetKeyCode() == wx.WXK_DOWN:
+                self.cmdindex = self.cmdindex + 1
+            if self.cmdindex < 0:
+                self.cmdindex = 0
+            if self.cmdindex > len(self.cmdbuffer) - 1:
+                self.cmdindex = len(self.cmdbuffer) - 1
+            
+            try:
+                txt = self.cmdbuffer[self.cmdindex]
+            except:
+                pass
+                
+            # clear current line and insert command history    
+            self.DelLineLeft()
+            self.DelLineRight()
+            pos = self.GetCurrentPos()            
+            self.InsertText(pos,txt)
+            self.LineEnd()
+            
+        elif event.GetKeyCode() == wx.WXK_RETURN and self.AutoCompActive() == False:
+            # Run command on line when <return> is pressed    
+            
+            # find the command to run
+            line = str(self.GetCurLine()[0]).strip()
+            if len(line) == 0:
+                return
+            
+            # parse command into list
+            # TODO: shell commands should probably be passed as string           
+            cmd = shlex.split(str(line))
+            
+            #send the command list to the processor 
+            self.RunCmd(cmd)
+                            
+            #add command to history    
+            self.cmdbuffer.append(line)
+            
+            #keep command history to a managable size
+            if len(self.cmdbuffer) > 200:
+                del self.cmdbuffer[0]
+            self.cmdindex = len(self.cmdbuffer)
+
+        else:
+            event.Skip()
+
+    def GetTextLeft(self):
+        """!Returns all text left of the caret"""
+        entry = ''
+        pos = self.GetCurrentPos()
+        self.HomeExtend()
+        entry = self.GetSelectedText().strip()
+        self.SetCurrentPos(pos)
+        
+        return entry
+
+    def GetCommandUsage(self, command):
+        """!Returns command syntax by running command help"""
+        usage = ''
+        description = ''
+
+        ret, out  = gcmd.RunCommand(command, 'help', getErrorMsg = True)
+               
+        if ret == 0:
+            cmdhelp = out.splitlines()
+            addline = False
+            helplist = []
+            description = ''
+            for line in cmdhelp:
+                if "Usage:" in line:
+                    addline = True
+                    continue
+                elif "Flags:" in line:
+                    addline = False
+                    break
+                elif addline == True:
+                    line = line.strip()
+                    helplist.append(line)
+
+            for line in cmdhelp:
+                if "Description:" in line:
+                    addline = True
+                    continue
+                elif "Keywords:" in line:
+                    addline = False
+                    break
+                elif addline == True:
+                    description += (line + ' ')
+                
+            description = description.strip()
+
+            for line in helplist:
+                usage += line + '\n'
+
+            return usage.strip(), description
+        else:
+            return ''   
+
+    def OnDestroy(self, evt):
+        """!The clipboard contents can be preserved after
+        the app has exited"""
+        
+        wx.TheClipboard.Flush()
+        evt.Skip()
+    
+    def OnCmdErase(self, event):
+        """!Erase command prompt"""
+        self.Home()
+        self.DelLineRight()
+        
+    def OnRunCmd(self, event):
+        """!Run command"""
+        cmdString = event.GetString()
+        
+        if self.parent.GetName() != "LayerManager":
+            return
+        
+        if cmdString[:2] == 'd.' and not self.parent.curr_page:
+            self.parent.NewDisplay(show=True)
+        
+        cmd = shlex.split(str(cmdString))
+        if len(cmd) > 1:
+            self.parent.goutput.RunCmd(cmd, switchPage = True)
+        else:
+            self.parent.goutput.RunCmd(cmd, switchPage = False)
+        
+        self.OnUpdateStatusBar(None)
+        
+    def OnUpdateStatusBar(self, event):
+        """!Update Layer Manager status bar"""
+        if self.parent.GetName() != "LayerManager":
+            return
+        
+        if event is None:
+            self.parent.statusbar.SetStatusText("")
+        else:
+            self.parent.statusbar.SetStatusText(_("Type GRASS command and run by pressing ENTER"))
+            event.Skip()

Modified: grass/trunk/gui/wxpython/wxgui.py
===================================================================
--- grass/trunk/gui/wxpython/wxgui.py	2009-12-19 21:25:49 UTC (rev 40078)
+++ grass/trunk/gui/wxpython/wxgui.py	2009-12-19 21:35:15 UTC (rev 40079)
@@ -132,7 +132,6 @@
         self.notebook  = self.__createNoteBook()
         self.menubar, self.menudata = self.__createMenuBar()
         self.statusbar = self.CreateStatusBar(number=1)
-        self.cmdprompt, self.cmdinput = self.__createCommandPrompt()
         self.toolbar   = self.__createToolBar()
         
         # bindings
@@ -146,16 +145,11 @@
         self._auimgr.AddPane(self.notebook, wx.aui.AuiPaneInfo().
                              Left().CentrePane().BestSize((-1,-1)).Dockable(False).
                              CloseButton(False).DestroyOnClose(True).Row(1).Layer(0))
-        self._auimgr.AddPane(self.cmdprompt, wx.aui.AuiPaneInfo().
-                             Bottom().BestSize((-1, -1)).Dockable(False).
-                             CloseButton(False).DestroyOnClose(True).
-                             PaneBorder(False).Row(1).Layer(0).Position(0).
-                             CaptionVisible(False))
 
         self._auimgr.Update()
 
         wx.CallAfter(self.notebook.SetSelection, 0)
-        wx.CallAfter(self.cmdinput.SetFocus)
+        wx.CallAfter(self.goutput.cmd_prompt.SetFocus)
         
         # use default window layout ?
         if UserSettings.Get(group='general', key='defWindowPos', subkey='enabled') is True:
@@ -192,13 +186,7 @@
         # start with layer manager on top
         self.curr_page.maptree.mapdisplay.Raise()
         self.Raise()
-        
-    def __createCommandPrompt(self):
-        """!Creates command-line input area"""
-        p = prompt.GPrompt(self)
-
-        return p.GetPanel(), p.GetInput()
-    
+            
     def __createMenuBar(self):
         """!Creates menubar"""
 
@@ -276,7 +264,7 @@
 
         # create command output text area and add it to main notebook page
         self.goutput = goutput.GMConsole(self, pageid=1)
-        self.outpage = self.notebook.AddPage(self.goutput, text=_("Command output"))
+        self.outpage = self.notebook.AddPage(self.goutput, text=_("Command console"))
 
         # bindings
         self.gm_cb.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.OnCBPageChanged)
@@ -367,7 +355,7 @@
         page = event.GetSelection()
         if page == self.goutput.pageid:
             # remove '(...)'
-            self.notebook.SetPageText(page, _("Command output"))
+            self.notebook.SetPageText(page, _("Command console"))
         
         event.Skip()
 
@@ -454,7 +442,7 @@
         if event:
             cmd = self.GetMenuCmd(event)
         self.goutput.RunCmd(cmd, switchPage=True)
-        
+
     def OnMenuCmd(self, event, cmd = ''):
         """!Parse command selected from menu"""
         if event:
@@ -1491,7 +1479,7 @@
         """!Quit GRASS session (wxGUI and shell)"""
         # quit wxGUI session
         self.OnCloseWindow(event)
-        
+
         # quit GRASS shell
         try:
             pid = int(os.environ['GIS_LOCK'])



More information about the grass-commit mailing list