[GRASS-SVN] r32408 - grass/branches/develbranch_6/gui/wxpython/gui_modules

svn_grass at osgeo.org svn_grass at osgeo.org
Thu Jul 31 13:26:14 EDT 2008


Author: martinl
Date: 2008-07-31 13:26:14 -0400 (Thu, 31 Jul 2008)
New Revision: 32408

Modified:
   grass/branches/develbranch_6/gui/wxpython/gui_modules/gcmd.py
   grass/branches/develbranch_6/gui/wxpython/gui_modules/goutput.py
   grass/branches/develbranch_6/gui/wxpython/gui_modules/menuform.py
Log:
wxGUI: general goutput module reconstruction, event-based (fix problems with the last wxPython versions) [merged from trunk r32364]


Modified: grass/branches/develbranch_6/gui/wxpython/gui_modules/gcmd.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/gui_modules/gcmd.py	2008-07-31 17:22:43 UTC (rev 32407)
+++ grass/branches/develbranch_6/gui/wxpython/gui_modules/gcmd.py	2008-07-31 17:26:14 UTC (rev 32408)
@@ -4,11 +4,16 @@
 @brief GRASS command interface
 
 Classes:
- * GException
- * DigitError
- * Popen (from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440554)
- * Command
- * CommandThread
+ - GException
+ - GStdError
+ - CmdError
+ - SettingsError
+ - DigitError
+ - DBMError
+ - NvizError
+ - Popen (from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440554)
+ - Command
+ - CommandThread
 
 (C) 2007-2008 by the GRASS Development Team
 This program is free software under the GNU General Public
@@ -44,7 +49,7 @@
     import fcntl
 from threading import Thread
 
-# import wxgui_utils # log window
+import grass
 import globalvar
 import utils
 from debug import Debug as Debug
@@ -98,12 +103,19 @@
                             parent=parent)
 
 class DBMError(GException):
-    """Exception raised for Attribute Table Manager"""
+    """Attribute Table Manager exception class"""
     def __init__(self, message, parent=None):
         GException.__init__(self, message,
                             title=_("Error in Attribute Table Manager"),
                             parent=parent)
 
+class NvizError(GException):
+    """Nviz exception class"""
+    def __init__(self, message, parent=None):
+        GException.__init__(self, message,
+                            title=_("Nviz error"),
+                            parent=parent)
+
 class Popen(subprocess.Popen):
     """Subclass subprocess.Popen"""
     def recv(self, maxsize=None):
@@ -209,6 +221,7 @@
                     return ''
                 
                 r = conn.read(maxsize)
+                
                 if not r:
                     return self._close(which)
     
@@ -250,22 +263,6 @@
             raise Exception(message)
         data = buffer(data, sent)
 
-# Define notification event for thread completion
-EVT_RESULT_ID = wx.NewId()
-
-def EVT_RESULT(win, func):
-    """Define Result Event"""
-    win.Connect(-1, -1, EVT_RESULT_ID, func)
-
-class ResultEvent(wx.PyEvent):
-    """Simple event to carry arbitrary result data"""
-    def __init__(self, data):
-        wx.PyEvent.__init__(self)
-
-        self.SetEventType(EVT_RESULT_ID)
-
-        self.cmdThread = data
-
 class Command:
     """
     Run GRASS command in separate thread
@@ -299,14 +296,14 @@
                   stdout=None, stderr=sys.stderr):
 
         self.cmd = cmd
+        self.stderr = stderr
+
 	# hack around platform-specific extension for binaries
 	if self.cmd[0] in globalvar.grassCmd['script']:
 	    self.cmd[0] = self.cmd[0] + globalvar.EXT_SCT
 	else:
 	    self.cmd[0] = self.cmd[0] + globalvar.EXT_BIN
 
-        self.stderr = stderr
-
         #
         # set verbosity level
         #
@@ -323,22 +320,12 @@
                     os.environ["GRASS_VERBOSE"] = str(verbose)
 
         #
-        # set message formatting
-        #
-        message_format = os.getenv("GRASS_MESSAGE_FORMAT")
-        os.environ["GRASS_MESSAGE_FORMAT"] = "gui"
-
-        #
         # create command thread
         #
         self.cmdThread = CommandThread(cmd, stdin,
                                        stdout, stderr)
-        
-        #
-        # start thread
-        #
         self.cmdThread.start()
-            
+        
         if wait:
             self.cmdThread.join()
             if self.cmdThread.module:
@@ -374,11 +361,6 @@
             Debug.msg (3, "Command(): cmd='%s', wait=%s, returncode=?, alive=%s" % \
                            (' '.join(cmd), wait, self.cmdThread.isAlive()))
 
-        if message_format:
-            os.environ["GRASS_MESSAGE_FORMAT"] = message_format
-        else:
-            os.unsetenv("GRASS_MESSAGE_FORMAT")
-
         if verbose_orig:
             os.environ["GRASS_VERBOSE"] = verbose_orig
         else:
@@ -475,9 +457,8 @@
 
         return msgString
 
-
 class CommandThread(Thread):
-    """Run command in separate thread
+    """Create separate thread for command
 
     @param cmd GRASS command (given as list)
     @param stdin standard input stream 
@@ -485,42 +466,48 @@
     @param stderr  redirect standard error output or None
     """
     def __init__ (self, cmd, stdin=None,
-                  stdout=None, stderr=sys.stderr):
+                  stdout=sys.stdout, stderr=sys.stderr):
 
         Thread.__init__(self)
-        
+
         self.cmd    = cmd
         self.stdin  = stdin
         self.stdout = stdout
         self.stderr = stderr
-
+        
         self.module = None
-        self.rerr   = ''
-
+        self.error  = ''
+        
         self._want_abort = False
         self.aborted = False
 
-        self.startTime = None
-
         self.setDaemon(True)
+
+        # set message formatting
+        self.message_format = os.getenv("GRASS_MESSAGE_FORMAT")
+        os.environ["GRASS_MESSAGE_FORMAT"] = "gui"
         
+    def __del__(self):
+        if self.message_format:
+            os.environ["GRASS_MESSAGE_FORMAT"] = self.message_format
+        else:
+            os.unsetenv("GRASS_MESSAGE_FORMAT")
+        
     def run(self):
-        """Run command"""
         if len(self.cmd) == 0:
             return
-        
+
         self.startTime = time.time()
-        # TODO: wx.Exectute/wx.Process (?)
+        
         try:
             self.module = Popen(self.cmd,
                                 stdin=subprocess.PIPE,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
         except OSError, e:
-            self.rerr = str(e)
-            return
-            # raise CmdError(self.cmd[0], str(e))
-
+            self.error = str(e)
+            return 1
+        
         if self.stdin: # read stdin if requested ...
             self.module.stdin.write(self.stdin)
             self.module.stdin.close()
@@ -529,21 +516,6 @@
         if self.stdout or self.stderr:
             self.__redirect_stream()
 
-    def __read_all(self, fd):
-        out = ""
-        while True:
-            try:
-                bytes = fd.read(4096)
-            except IOError, e:
-                if e[0] != errno.EAGAIN:
-                    raise
-                break
-            if not bytes:
-                break
-            out += bytes
-
-        return out
-
     def __redirect_stream(self):
         """Redirect stream"""
         if self.stdout:
@@ -559,106 +531,32 @@
 	    if not subprocess.mswindows:
                 flags = fcntl.fcntl(out_fileno, fcntl.F_GETFL)
                 fcntl.fcntl(out_fileno, fcntl.F_SETFL, flags| os.O_NONBLOCK)
-                
+        
         # wait for the process to end, sucking in stuff until it does end
         while self.module.poll() is None:
-            time.sleep(.1)
             if self._want_abort: # abort running process
                 self.module.kill()
                 self.aborted = True
-                if hasattr(self.stderr, "gmstc"):
-                    # -> GMConsole
-                    wx.PostEvent(self.stderr.gmstc.parent, ResultEvent(self))
-                return 
+                return
             if self.stdout:
-                # line = self.__read_all(self.module.stdout)
                 line = recv_some(self.module, e=0, stderr=0)
                 self.stdout.write(line)
             if self.stderr:
-                # line = self.__read_all(self.module.stderr)
                 line = recv_some(self.module, e=0, stderr=1)
                 self.stderr.write(line)
                 self.rerr = line
 
         # get the last output
         if self.stdout:
-            # line = self.__read_all(self.module.stdout)
             line = recv_some(self.module, e=0, stderr=0)
             self.stdout.write(line)
         if self.stderr:
-            # line = self.__read_all(self.module.stderr)
             line = recv_some(self.module, e=0, stderr=1)
             self.stderr.write(line)
             if len(line) > 0:
                 self.rerr = line
 
-        if hasattr(self.stderr, "gmstc"):
-            # -> GMConsole
-            wx.PostEvent(self.stderr.gmstc.parent, ResultEvent(self))
-
     def abort(self):
         """Abort running process, used by main thread to signal an abort"""
         self._want_abort = True
-
-# testing ...
-if __name__ == "__main__":
-    SEP = "-----------------------------------------------------------------------------"
-
-    print SEP
-
-    # d.rast verbosely, wait for process termination
-    print "Running d.rast..."
-
-    cmd = Command(cmd=["d.rast", "elevation.dem"], verbose=3, wait=True, rerr=True)
-
-    if cmd.returncode == None:
-        print "RUNNING"
-    elif cmd.returncode == 0:
-        print "SUCCESS"
-    else:
-        print "FAILURE (%d)" % cmd.returncode
-
-    print SEP
-
-    # v.net.path silently, wait for process termination
-    print "Running v.net.path for 0 593527.6875 4925297.0625 602083.875 4917545.8125..."
-
-    cmd = Command(cmd=["v.net.path", "in=roads at PERMANENT", "out=tmp", "dmax=100000", "--o"],
-                  stdin="0 593527.6875 4925297.0625 602083.875 4917545.8125",
-                  verbose=0,
-                  wait=True, rerr=None)
-
-    if cmd.returncode == None:
-        print "RUNNING"
-    elif cmd.returncode == 0:
-        print "SUCCESS"
-    else:
-        print "FAILURE (%d)" % cmd.returncode
-
-    print SEP
-
-    # d.vect silently, do not wait for process termination
-    # returncode will be None
-    print "Running d.vect tmp..."
-
-    cmd = Command(["d.vect", "tmp"], verbose=2, wait=False, rerr=None)
-
-    if cmd.returncode == None:
-        print "RUNNING"
-    elif cmd.returncode == 0:
-        print "SUCCESS"
-    else:
-        print "FAILURE (%d)" % cmd.returncode
-
-    cmd = Command(["g.region", "-p"])
-
-    for line in cmd.ReadStdOutput():
-        print line
-
-    cmd = Command(["g.region", "-p"], stderr=None)
-
-    for line in cmd.ReadStdOutput():
-        print line
-    for line in cmd.ReadErrOutput():
-        print line
     

Modified: grass/branches/develbranch_6/gui/wxpython/gui_modules/goutput.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/gui_modules/goutput.py	2008-07-31 17:22:43 UTC (rev 32407)
+++ grass/branches/develbranch_6/gui/wxpython/gui_modules/goutput.py	2008-07-31 17:26:14 UTC (rev 32408)
@@ -15,21 +15,73 @@
 for details.
 
 @author Michael Barton (Arizona State University)
-Martin Landa <landa.martin gmail.com>
+ at author Martin Landa <landa.martin gmail.com>
 """
 
 import os
 import sys
 import textwrap
 import time
+import threading
+import Queue
 
 import wx
 import wx.stc
+from wx.lib.newevent import NewEvent
 
 import globalvar
 import gcmd
 from debug import Debug as Debug
 
+wxCmdOutput,   EVT_CMD_OUTPUT   = NewEvent()
+wxCmdProgress, EVT_CMD_PROGRESS = NewEvent()
+wxCmdDone,     EVT_CMD_DONE     = NewEvent()
+wxCmdAbort,    EVT_CMD_ABORT    = NewEvent()
+
+def GrassCmd(cmd, stdout, stderr):
+    """Return GRASS command thread"""
+    return gcmd.CommandThread(cmd=cmd,
+                              stdout=stdout, stderr=stderr)
+
+class CmdThread(threading.Thread):
+    """Thread for GRASS commands"""
+    requestId = 0
+    def __init__(self, parent, requestQ, resultQ, **kwds):
+        threading.Thread.__init__(self, **kwds)
+
+        self.setDaemon(True)
+
+        self.parent = parent # GMConsole
+        
+        self.requestQ = requestQ
+        self.resultQ = resultQ
+
+        self.start()
+
+    def RunCmd(self, callable, *args, **kwds):
+        CmdThread.requestId += 1
+
+        self.requestTime = time.time()
+        self.requestCmd = None
+        self.requestQ.put((CmdThread.requestId, callable, args, kwds))
+        
+        return CmdThread.requestId
+
+    def run(self):
+        while True:
+            requestId, callable, args, kwds = self.requestQ.get()
+            self.requestCmd = callable(*args, **kwds)
+            self.resultQ.put((requestId, self.requestCmd.run()))
+
+            event = wxCmdDone(aborted=self.requestCmd.aborted,
+                              time=self.requestTime,
+                              pid=requestId)
+            time.sleep(.1)
+            wx.PostEvent(self.parent, event)
+
+    def abort(self):
+        self.requestCmd.abort()
+    
 class GMConsole(wx.Panel):
     """
     Create and manage output console for commands entered on the
@@ -43,34 +95,58 @@
         # initialize variables
         self.Map             = None
         self.parent          = parent # GMFrame
-        self.cmdThreads      = {}     # cmdThread : cmdPID
         self.lineWidth       = 80
         self.pageid          = pageid
 
+        #
+        # create queues
+        #
+        self.requestQ = Queue.Queue()
+        self.resultQ = Queue.Queue()
+
+        #
         # progress bar
+        #
         self.console_progressbar = wx.Gauge(parent=self, 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)
+        
+        #
         # text control for command output
+        #
         self.cmd_output = GMStc(parent=self, id=wx.ID_ANY, margin=margin,
                                 wrap=None) 
+        self.cmd_output_timer = wx.Timer(self.cmd_output, id=wx.ID_ANY)
+        self.cmd_output.Bind(EVT_CMD_OUTPUT, self.OnCmdOutput)
+        self.cmd_output.Bind(wx.EVT_TIMER, self.OnProcessPendingOutputWindowEvents)
+        self.Bind(EVT_CMD_DONE, self.OnCmdDone)
         
-        # redirect
-        self.cmd_stdout = GMStdout(self.cmd_output)
-        ### sys.stdout = self.cmd_stdout
-        self.cmd_stderr = GMStderr(self.cmd_output,
-                                   self.console_progressbar,
-                                   self.parent.notebook,
-                                   pageid)
+        #
+        # stream redirection
+        #
+        self.cmd_stdout = GMStdout(self)
+        self.cmd_stderr = GMStderr(self)
 
+        #
+        # thread
+        #
+        self.cmdThread = CmdThread(self, self.requestQ, self.resultQ)
+
+        #
         # 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)
 
-        # output control layout
+        self.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,
@@ -90,9 +166,6 @@
         boxsizer1.Fit(self)
         boxsizer1.SetSizeHints(self)
 
-        # set up event handler for any command thread results
-        gcmd.EVT_RESULT(self, self.OnResult)
-        
         # layout
         self.SetAutoLayout(True)
         self.SetSizer(boxsizer1)
@@ -105,7 +178,10 @@
         """
         if Debug.get_level() == 0:
             # don't redirect when debugging is enabled
-            sys.stderr = self.cmd_stderr
+            #sys.stdout = self.cmd_stdout
+            #sys.stderr = self.cmd_stderr
+            pass
+
             return True
 
         return False
@@ -121,7 +197,7 @@
         if not style:
             style = self.cmd_output.StyleDefault
 
-        self.cmd_output.GotoPos(self.cmd_output.GetEndStyled())
+        self.cmd_output.GotoPos(self.cmd_output.GetLength())
         p1 = self.cmd_output.GetCurrentPos()
         
         # fill space
@@ -130,16 +206,17 @@
             line += diff * ' '
 
         self.cmd_output.AddTextWrapped(line, wrap=wrap) # adds os.linesep
-        self.cmd_output.EnsureCaretVisible()
+
         p2 = self.cmd_output.GetCurrentPos()
         self.cmd_output.StartStyling(p1, 0xff)
         self.cmd_output.SetStyling(p2 - p1, style)
 
+        self.cmd_output.EnsureCaretVisible()
+        
     def WriteCmdLog(self, line, pid=None):
         """Write out line in selected style"""
         if pid:
             line = '(' + str(pid) + ') ' + line
-
         self.WriteLog(line, self.cmd_output.StyleCommand)
 
     def RunCmd(self, command):
@@ -163,7 +240,7 @@
         except:
             curr_disp = None
 
-        if len(self.GetListOfCmdThreads()) > 0:
+        if not self.requestQ.empty():
             # only one running command enabled (per GMConsole instance)
             busy = wx.BusyInfo(message=_("Unable to run the command, another command is running..."),
                                parent=self)
@@ -227,16 +304,15 @@
                     menuform.GUI().ParseCommand(cmdlist, parentframe=self)
                 else:
                     # process GRASS command with argument
-                    cmdPID = len(self.cmdThreads.keys())+1
+                    cmdPID = self.cmdThread.requestId + 1
                     self.WriteCmdLog('%s' % ' '.join(cmdlist), pid=cmdPID)
+
+                    self.cmdThread.RunCmd(GrassCmd,
+                                          cmdlist, self.cmd_stdout, self.cmd_stderr)
                     
-                    grassCmd = gcmd.Command(cmdlist, wait=False,
-                                            stdout=self.cmd_stdout,
-                                            stderr=self.cmd_stderr)
-                    
-                    self.cmdThreads[grassCmd.cmdThread] = { 'cmdPID' : cmdPID }
-                    
-                    return grassCmd
+                    self.cmd_output_timer.Start(50)
+
+                    return None
                 # deactivate computational region and return to display settings
                 if tmpreg:
                     os.environ["GRASS_REGION"] = tmpreg
@@ -290,38 +366,92 @@
 
         dlg.Destroy()
 
-    def GetListOfCmdThreads(self, onlyAlive=True):
-        """Return list of command threads)"""
-        list = []
-        for t in self.cmdThreads.keys():
-            Debug.msg (4, "GMConsole.GetListOfCmdThreads(): name=%s, alive=%s" %
-                       (t.getName(), t.isAlive()))
-            if onlyAlive and not t.isAlive():
-                continue
-            list.append(t)
+    def GetCmd(self):
+        """Get running command or None"""
+        return self.requestQ.get()
+        
+    def OnCmdOutput(self, event):
+        """Print command output"""
+        message = event.text
+        type  = event.type
 
-        return list
+        # message prefix
+        if type == 'warning':
+            messege = 'WARNING: ' + message
+        elif type == 'error':
+            message = 'ERROR: ' + message
+            
+        p1 = self.cmd_output.GetCurrentPos()
 
-    def OnResult(self, event):
-        """Show result status"""
+        message = message.replace('\r', '')
+
+        pc = -1
+        if '\b' in message:
+            pc = p1
+            last_c = ''
+            for c in message:
+                if c == '\b':
+                    pc -= 1
+                else:
+                    self.cmd_output.SetCurrentPos(pc)
+                    self.cmd_output.ReplaceSelection(c)
+                    pc = self.cmd_output.GetCurrentPos()
+                    if c != ' ':
+                        last_c = c
+            if last_c not in ('0123456789'):
+                self.cmd_output.AddText('\n')
+                pc = -1
+        else:
+            if os.linesep not in message:
+                self.cmd_output.AddTextWrapped(message, wrap=60)
+            else:
+                self.cmd_output.AddText(message)
+
+        p2 = self.cmd_output.GetCurrentPos()
+        self.cmd_output.StartStyling(p1, 0xff)
+        if type == 'error':
+            self.cmd_output.SetStyling(p2 - p1 + 1, self.cmd_output.StyleError)
+        elif type == 'warning':
+            self.cmd_output.SetStyling(p2 - p1 + 1, self.cmd_output.StyleWarning)
+        elif type == 'message':
+            self.cmd_output.SetStyling(p2 - p1 + 1, self.cmd_output.StyleMessage)
+        else: # unknown
+            self.cmd_output.SetStyling(p2 - p1 + 1, self.cmd_output.StyleUnknown)
+
+        if pc > 0:
+            self.cmd_output.SetCurrentPos(pc)
+            
+        self.cmd_output.EnsureCaretVisible()
         
-        if event.cmdThread.aborted:
+    def OnCmdProgress(self, event):
+        """Update progress message info"""
+        self.console_progressbar.SetValue(event.value)
+
+    def OnCmdAbort(self, event):
+        """Abort running command"""
+        self.cmdThread.abort()
+        
+    def OnCmdDone(self, event):
+        """Command done (or aborted)"""
+        if event.aborted:
             # Thread aborted (using our convention of None return)
             self.WriteLog(_('Please note that the data are left in incosistent stage '
                             'and can be corrupted'), self.cmd_output.StyleWarning)
             self.WriteCmdLog(_('Command aborted'),
-                             pid=self.cmdThreads[event.cmdThread]['cmdPID'])
+                             pid=self.cmdThread.requestId)
         else:
             try:
                 # Process results here
-                self.WriteCmdLog(_('Command finished (%d sec)') % (time.time() - event.cmdThread.startTime),
-                                 pid=self.cmdThreads[event.cmdThread]['cmdPID'])
+                self.WriteCmdLog(_('Command finished (%d sec)') % (time.time() - event.time),
+                                 pid=event.pid)
             except KeyError:
                 # stopped deamon
                 pass
-                
+        
         self.console_progressbar.SetValue(0) # reset progress bar on '0%'
 
+        self.cmd_output_timer.Stop()
+
         # updated command dialog
         if hasattr(self.parent.parent, "btn_run"):
             dialog = self.parent.parent
@@ -339,12 +469,17 @@
                 dialog.btn_help.Enable(True)
 
             dialog.btn_run.Enable(True)
-            
+
             if dialog.get_dcmd is None and \
                    dialog.closebox.IsChecked():
                 time.sleep(1)
                 dialog.Close()
 
+        event.Skip()
+        
+    def OnProcessPendingOutputWindowEvents(self, event):
+        self.ProcessPendingEvents()
+
 class GMStdout:
     """GMConsole standard output
 
@@ -356,21 +491,23 @@
     Copyright: (c) 2005-2007 Jean-Michel Fauth
     Licence:   GPL
     """
-    def __init__(self, gmstc):
-        self.gmstc  = gmstc
+    def __init__(self, parent):
+        self.parent = parent # GMConsole
 
     def write(self, s):
-        if len(s) == 0:
+        if len(s) == 0 or s == '\n':
             return
+        
         s = s.replace('\n', os.linesep)
+        
         for line in s.split(os.linesep):
-            p1 = self.gmstc.GetCurrentPos() # get caret position
-            self.gmstc.AddTextWrapped(line, wrap=None) # no wrapping && adds os.linesep
-            # self.gmstc.EnsureCaretVisible()
-            p2 = self.gmstc.GetCurrentPos()
-            self.gmstc.StartStyling(p1, 0xff)
-            self.gmstc.SetStyling(p2 - p1 + 1, self.gmstc.StyleOutput)
-
+            if len(line) == 0:
+                continue
+            
+            evt = wxCmdOutput(text=line + os.linesep,
+                              type='')
+            wx.PostEvent(self.parent.cmd_output, evt)
+        
 class GMStderr:
     """GMConsole standard error output
 
@@ -382,89 +519,62 @@
     Copyright: (c) 2005-2007 Jean-Michel Fauth
     Licence:   GPL
     """
-    def __init__(self, gmstc, gmgauge, notebook, pageid):
-        self.gmstc    = gmstc
-        self.gmgauge  = gmgauge
-        self.notebook = notebook
-        self.pageid   = pageid
-
+    def __init__(self, parent):
+        self.parent = parent # GMConsole
+ 
         self.type = ''
         self.message = ''
         self.printMessage = False
-        
+
     def write(self, s):
-        if self.pageid > -1:
-            # swith notebook page to 'command output'
-            if self.notebook.GetSelection() != self.pageid: 
-                self.notebook.SetSelection(self.pageid)
-
         s = s.replace('\n', os.linesep)
         # remove/replace escape sequences '\b' or '\r' from stream
-        s = s.replace('\b', '').replace('\r', '%s' % os.linesep)
- 
+        progressValue = -1
+        
         for line in s.split(os.linesep):
             if len(line) == 0:
                 continue
-            
             if 'GRASS_INFO_PERCENT' in line:
-                # 'GRASS_INFO_PERCENT: 10' -> value=10
                 value = int(line.rsplit(':', 1)[1].strip())
                 if value >= 0 and value < 100:
-                    self.gmgauge.SetValue(value)
+                    progressValue = value
                 else:
-                    self.gmgauge.SetValue(0) # reset progress bar on '0%'
+                    progressValue = 0
             elif 'GRASS_INFO_MESSAGE' in line:
                 self.type = 'message'
-                if len(self.message) > 0:
-                    self.message += os.linesep
-                self.message += line.split(':', 1)[1].strip()
+                self.message = line.split(':', 1)[1].strip()
             elif 'GRASS_INFO_WARNING' in line:
                 self.type = 'warning'
-                if len(self.message) > 0:
-                    self.message += os.linesep
-                self.message += line.split(':', 1)[1].strip()
+                self.message = line.split(':', 1)[1].strip()
             elif 'GRASS_INFO_ERROR' in line:
                 self.type = 'error'
-                if len(self.message) > 0:
-                    self.message += os.linesep
-                self.message += line.split(':', 1)[1].strip()
+                self.message = line.split(':', 1)[1].strip()
             elif 'GRASS_INFO_END' in line:
                 self.printMessage = True
-            elif not self.type:
-                if len(line) > 0:
-                    p1 = self.gmstc.GetCurrentPos()
-                    self.gmstc.AddTextWrapped(line, wrap=60) # wrap && add os.linesep
-                    # self.gmstc.EnsureCaretVisible()
-                    p2 = self.gmstc.GetCurrentPos()
-                    self.gmstc.StartStyling(p1, 0xff)
-                    self.gmstc.SetStyling(p2 - p1 + 1, self.gmstc.StyleUnknown)
+            elif self.type == '':
+                if len(line) == 0:
+                    continue
+                evt = wxCmdOutput(text=line,
+                                  type='')
+                wx.PostEvent(self.parent.cmd_output, evt)
             elif len(line) > 0:
-                self.message += os.linesep + line.strip()
+                self.message += line.strip() + os.linesep
 
             if self.printMessage and len(self.message) > 0:
-                p1 = self.gmstc.GetCurrentPos()
-                if self.type == 'warning':
-                    self.message = 'WARNING: ' + self.message
-                elif self.type == 'error':
-                    self.message = 'ERROR: ' + self.message
-                if os.linesep not in self.message:
-                    self.gmstc.AddTextWrapped(self.message, wrap=60) #wrap && add os.linesep
-                else:
-                    self.gmstc.AddText(self.message + os.linesep)
-                # self.gmstc.EnsureCaretVisible()
-                p2 = self.gmstc.GetCurrentPos()
-                self.gmstc.StartStyling(p1, 0xff)
-                if self.type == 'error':
-                    self.gmstc.SetStyling(p2 - p1 + 1, self.gmstc.StyleError)
-                elif self.type == 'warning':
-                    self.gmstc.SetStyling(p2 - p1 + 1, self.gmstc.StyleWarning)
-                elif self.type == 'self.message':
-                    self.gmstc.SetStyling(p2 - p1 + 1, self.gmstc.StyleSelf.Message)
+                evt = wxCmdOutput(text=self.message,
+                                  type=self.type)
+                wx.PostEvent(self.parent.cmd_output, evt)
 
                 self.type = ''
                 self.message = ''
                 self.printMessage = False
-                
+
+        # update progress message
+        if progressValue > -1:
+            # self.gmgauge.SetValue(progressValue)
+            evt = wxCmdProgress(value=progressValue)
+            wx.PostEvent(self.parent.console_progressbar, evt)
+            
 class GMStc(wx.stc.StyledTextCtrl):
     """Styled GMConsole
 
@@ -547,7 +657,7 @@
         wx.TheClipboard.Flush()
         evt.Skip()
 
-    def AddTextWrapped(self, str, wrap=None):
+    def AddTextWrapped(self, txt, wrap=None):
         """Add string to text area.
 
         String is wrapped and linesep is also added to the end
@@ -556,12 +666,13 @@
             wrap = self.wrap
 
         if wrap is not None:
-            str = textwrap.fill(str, wrap) + os.linesep
+            txt = textwrap.fill(txt, wrap) + os.linesep
         else:
-            str += os.linesep
+            txt += os.linesep
 
-        self.AddText(str)
+        self.AddText(txt)
 
+
     def SetWrap(self, wrap):
         """Set wrapping value
 

Modified: grass/branches/develbranch_6/gui/wxpython/gui_modules/menuform.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/gui_modules/menuform.py	2008-07-31 17:22:43 UTC (rev 32407)
+++ grass/branches/develbranch_6/gui/wxpython/gui_modules/menuform.py	2008-07-31 17:26:14 UTC (rev 32408)
@@ -773,9 +773,6 @@
 
     def OnRun(self, event):
         """Run the command"""
-        if len(self.goutput.GetListOfCmdThreads()) > 0:
-            return
-
         cmd = self.createCmd()
 
         if cmd == [] or cmd == None:
@@ -807,10 +804,8 @@
 
     def OnAbort(self, event):
         """Abort running command"""
-        try:
-            self.goutput.GetListOfCmdThreads()[0].abort()
-        except IndexError:
-            pass
+        event = goutput.wxCmdAbort(aborted=True)
+        wx.PostEvent(self.goutput, event)
 
     def OnCopy(self, event):
         """Copy the command"""



More information about the grass-commit mailing list