[GRASS-SVN] r53944 - in grass/trunk/gui/wxpython: core gmodeler gui_core lmgr

svn_grass at osgeo.org svn_grass at osgeo.org
Wed Nov 21 01:05:50 PST 2012


Author: annakrat
Date: 2012-11-21 01:05:50 -0800 (Wed, 21 Nov 2012)
New Revision: 53944

Modified:
   grass/trunk/gui/wxpython/core/events.py
   grass/trunk/gui/wxpython/gmodeler/dialogs.py
   grass/trunk/gui/wxpython/gmodeler/frame.py
   grass/trunk/gui/wxpython/gui_core/goutput.py
   grass/trunk/gui/wxpython/gui_core/prompt.py
   grass/trunk/gui/wxpython/lmgr/frame.py
Log:
wxGUI/GPrompt: decoupling GPrompt and GConsole; standalone GConsole for testing available (co-author: wenzeslaus)

Modified: grass/trunk/gui/wxpython/core/events.py
===================================================================
--- grass/trunk/gui/wxpython/core/events.py	2012-11-21 04:11:16 UTC (rev 53943)
+++ grass/trunk/gui/wxpython/core/events.py	2012-11-21 09:05:50 UTC (rev 53944)
@@ -6,7 +6,12 @@
 Put here only truly general events. Once you find that your event can be
 generated in more than one class, put your event here. Otherwise,
 leave it in your class file.
-        
+
+General notice:
+Command events are propagated to parent windows. However they do not propagate 
+beyond dialogs. Events do not propagate at all.
+
+
 (C) 2012 by the GRASS Development Team
 
 This program is free software under the GNU General Public License

Modified: grass/trunk/gui/wxpython/gmodeler/dialogs.py
===================================================================
--- grass/trunk/gui/wxpython/gmodeler/dialogs.py	2012-11-21 04:11:16 UTC (rev 53943)
+++ grass/trunk/gui/wxpython/gmodeler/dialogs.py	2012-11-21 09:05:50 UTC (rev 53944)
@@ -35,7 +35,7 @@
 from gui_core.widgets     import SearchModuleWidget, EVT_MODULE_SELECTED
 from core.gcmd            import GError, EncodeString
 from gui_core.dialogs     import ElementDialog, MapLayersDialogForModeler
-from gui_core.prompt      import GPromptSTC
+from gui_core.prompt      import GPromptSTC, EVT_GPROMPT_RUN_CMD
 from gui_core.forms       import CmdPanel
 from gui_core.gselect     import Select
 from gmodeler.model       import *
@@ -130,19 +130,21 @@
         self.SetName("ModelerDialog")
         self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
         
+        self._command = None
         self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
         
         self.cmdBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
                                    label=" %s " % _("Command"))
 
         modulesData = ModulesData()
-        self.cmd_prompt = GPromptSTC(parent = self, modulesData = modulesData)
+        self.cmd_prompt = GPromptSTC(parent = self, modulesData = modulesData, updateCmdHistory = False)
+        self.cmd_prompt.Bind(EVT_GPROMPT_RUN_CMD, self.OnCommand)
         self.search = SearchModuleWidget(parent = self.panel,
                                          modulesData = modulesData,
                                          showTip = True)
         self.search.Bind(EVT_MODULE_SELECTED,
                              lambda event:
-                                 self.cmd_prompt.SetTextAndFocus(event.name + ' '))                  
+                                 self.cmd_prompt.SetTextAndFocus(event.name + ' '))
         wx.CallAfter(self.cmd_prompt.SetFocus)
         
         self.btnCancel = wx.Button(self.panel, wx.ID_CANCEL)
@@ -186,42 +188,48 @@
         """!Get dialog panel"""
         return self.panel
 
-    def GetCmd(self):
-        """!Get command"""
+    def _getCmd(self):
         line = self.cmd_prompt.GetCurLine()[0].strip()
         if len(line) == 0:
-            list()
-        
-        try:
-            cmd = utils.split(str(line))
-        except UnicodeError:
-            cmd = utils.split(EncodeString((line)))
-            
+            cmd = list()
+        else:
+            try:
+                cmd = utils.split(str(line))
+            except UnicodeError:
+                cmd = utils.split(EncodeString((line)))
         return cmd
-    
-    def OnOk(self, event):
-        """!Button 'OK' pressed"""
-        # hide autocomplete
-        if self.cmd_prompt.AutoCompActive():
-            self.cmd_prompt.AutoCompCancel()
-        
-        self.btnOk.SetFocus()
-        cmd = self.GetCmd()
-        
+
+    def GetCmd(self):
+        """!Get command"""
+        return self._command
+
+    def ValidateCmd(self, cmd):
         if len(cmd) < 1:
             GError(parent = self,
                    message = _("Command not defined.\n\n"
                                "Unable to add new action to the model."))
-            return
+            return False
         
         if cmd[0] not in globalvar.grassCmd:
             GError(parent = self,
                    message = _("'%s' is not a GRASS module.\n\n"
                                "Unable to add new action to the model.") % cmd[0])
-            return
-        
-        self.EndModal(wx.ID_OK)
-        
+            return False
+        return True
+
+    def OnCommand(self, event):
+        """!Command in prompt confirmed"""
+        if self.ValidateCmd(event.cmd):
+            self._command = event.cmd
+            self.EndModal(wx.ID_OK)
+
+    def OnOk(self, event):
+        """!Button 'OK' pressed"""
+        cmd = self._getCmd()
+        if self.ValidateCmd(cmd):
+            self._command = cmd
+            self.EndModal(wx.ID_OK)
+
     def OnCancel(self, event):
         """Cancel pressed, close window"""
         # hide autocomplete

Modified: grass/trunk/gui/wxpython/gmodeler/frame.py
===================================================================
--- grass/trunk/gui/wxpython/gmodeler/frame.py	2012-11-21 04:11:16 UTC (rev 53943)
+++ grass/trunk/gui/wxpython/gmodeler/frame.py	2012-11-21 09:05:50 UTC (rev 53944)
@@ -36,7 +36,7 @@
 from gui_core.widgets     import GNotebook
 from gui_core.goutput     import GConsole, \
     EVT_CMD_RUN, EVT_CMD_DONE, EVT_CMD_PREPARE, EVT_OUTPUT_TEXT
-from core.events          import EVT_MAP_CREATED
+from core.events          import EVT_MAP_CREATED, EVT_SHOW_NOTIFICATION
 from core.debug           import Debug
 from core.gcmd            import GMessage, GException, GWarning, GError, RunCommand
 from gui_core.dialogs     import GetImageHandlers
@@ -112,6 +112,8 @@
         self.Bind(EVT_CMD_DONE, self.OnCmdDone)
         self.Bind(EVT_CMD_PREPARE, self.OnCmdPrepare)
         self.Bind(EVT_MAP_CREATED, self.OnMapCreated)
+        self.Bind(EVT_SHOW_NOTIFICATION,
+                  lambda event: self.SetStatusText(event.message))
 
         self.notebook.AddPage(page = self.canvas, text=_('Model'), name = 'model')
         self.notebook.AddPage(page = self.itemPanel, text=_('Items'), name = 'items')

Modified: grass/trunk/gui/wxpython/gui_core/goutput.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/goutput.py	2012-11-21 04:11:16 UTC (rev 53943)
+++ grass/trunk/gui/wxpython/gui_core/goutput.py	2012-11-21 09:05:50 UTC (rev 53944)
@@ -30,6 +30,8 @@
 import codecs
 import locale
 
+sys.path.append(os.path.join(os.environ['GISBASE'], "etc", "gui", "wxpython"))
+
 import wx
 from   wx import stc
 from wx.lib.newevent import NewEvent
@@ -42,7 +44,7 @@
 from core.gcmd       import CommandThread, GMessage, GError, GException, EncodeString
 from core.events     import gShowNotification, gMapCreated
 from gui_core.forms  import GUI
-from gui_core.prompt import GPromptSTC
+from gui_core.prompt import GPromptSTC, EVT_GPROMPT_RUN_CMD
 from core.debug      import Debug
 from core.settings   import UserSettings
 from gui_core.widgets import SearchModuleWidget, EVT_MODULE_SELECTED
@@ -276,6 +278,9 @@
         # move to the if below
         # search depends on cmd prompt
         self.cmdPrompt = GPromptSTC(parent = self, modulesData = modulesData)
+        self.cmdPrompt.Bind(EVT_GPROMPT_RUN_CMD, 
+                            lambda event: self.RunCmd(command = event.cmd))
+
         if not self._gcstyle & GC_PROMPT:
             self.cmdPrompt.Hide()
 
@@ -578,7 +583,7 @@
             # except ignored commands (event is emitted)
 
             if self._ignoredCmdPattern and \
-              re.compile(self._ignoredCmdPattern).search(command[0]) and \
+              re.compile(self._ignoredCmdPattern).search(' '.join(command)) and \
               '--help' not in command:
                 event = gIgnoredCmdRun(cmd = command)
                 wx.PostEvent(self, event)
@@ -1204,3 +1209,30 @@
                 self.SetStyling(p2 - p1, self.StyleUnknown)
         
         self.EnsureCaretVisible()
+
+
+class GConsoleFrame(wx.Frame):
+    """!Standalone GConsole for testing only"""
+    def __init__(self, parent, id = wx.ID_ANY, title = "GConsole Test Frame",
+                 style = wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL, **kwargs):
+        wx.Frame.__init__(self, parent = parent, id = id, title = title)
+
+        panel = wx.Panel(self, id = wx.ID_ANY)
+        self.goutput = GConsole(parent = panel, gcstyle = GC_SEARCH | GC_PROMPT)
+
+        mainSizer = wx.BoxSizer(wx.VERTICAL)
+        mainSizer.Add(item = self.goutput, proportion = 1, flag = wx.EXPAND, border = 0)
+
+        panel.SetSizer(mainSizer)
+        mainSizer.Fit(panel)
+        self.SetMinSize((550, 500))
+
+
+def testGConsole():
+    app = wx.PySimpleApp()
+    frame = GConsoleFrame(parent = None)
+    frame.Show()
+    app.MainLoop()
+
+if __name__ == '__main__':
+    testGConsole()

Modified: grass/trunk/gui/wxpython/gui_core/prompt.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/prompt.py	2012-11-21 04:11:16 UTC (rev 53943)
+++ grass/trunk/gui/wxpython/gui_core/prompt.py	2012-11-21 09:05:50 UTC (rev 53944)
@@ -29,12 +29,15 @@
 import wx.stc
 import wx.lib.mixins.listctrl as listmix
 
+from wx.lib.newevent import NewEvent
+
 from grass.script import core as grass
 from grass.script import task as gtask
 
 from core          import globalvar
 from core          import utils
 from core.gcmd     import EncodeString, DecodeString, GetRealCmd
+from core.events   import gShowNotification
 
 class PromptListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
     """!PopUp window used by GPromptPopUp"""
@@ -464,19 +467,17 @@
         
         event.Skip()
 
+
+gPromptRunCmd, EVT_GPROMPT_RUN_CMD = NewEvent()
+
 class GPrompt(object):
     """!Abstract class for interactive wxGUI prompt
 
     See subclass GPromptPopUp and GPromptSTC.
     """
-    def __init__(self, parent, modulesData):
+    def __init__(self, parent, modulesData, updateCmdHistory):
         self.parent = parent                 # GConsole
         self.panel  = self.parent.GetPanel()
-        
-        if self.parent.parent.GetName() not in ("LayerManager", "Modeler"):
-            self.standAlone = True
-        else:
-            self.standAlone = False
 
         # probably only subclasses need this
         self.modulesData = modulesData
@@ -490,6 +491,8 @@
         
         # command description (gtask.grassTask)
         self.cmdDesc   = None
+
+        self._updateCmdHistory = updateCmdHistory
         self.cmdbuffer = self._readHistory()
         self.cmdindex  = len(self.cmdbuffer)
         
@@ -530,16 +533,9 @@
         
         @param cmdString command to run (given as a string)
         """
-        if self.parent.GetName() == "ModelerDialog":
-            self.parent.OnOk(None)
+        if not cmdString:
             return
-        
-        if not cmdString or self.standAlone:
-            return
-        
-        if cmdString[:2] == 'd.' and not self.parent.parent.GetMapDisplay():
-            self.parent.parent.NewDisplay(show = True)
-                
+
         self.commands.append(cmdString) # trace commands
 
         # parse command into list
@@ -548,29 +544,14 @@
         except UnicodeError:
             cmd = utils.split(EncodeString((cmdString)))
         cmd = map(DecodeString, cmd)
-        
-        # send the command list to the processor 
-        if cmd[0] in ('r.mapcalc', 'r3.mapcalc') and len(cmd) == 1:
-            self.parent.parent.OnMapCalculator(event = None, cmd = cmd)
-        else:
-            self.parent.RunCmd(cmd)
-            
+
+        wx.PostEvent(self, gPromptRunCmd(cmd = cmd))
+
         # add command to history & clean prompt
         self.UpdateCmdHistory(cmd)
         self.OnCmdErase(None)
-        self.parent.parent.statusbar.SetStatusText('')
+        self.ShowStatusText('')
         
-    def OnUpdateStatusBar(self, event):
-        """!Update Layer Manager status bar"""
-        if self.standAlone:
-            return
-        
-        if event is None:
-            self.parent.parent.statusbar.SetStatusText("")
-        else:
-            self.parent.parent.statusbar.SetStatusText(_("Type GRASS command and run by pressing ENTER"))
-            event.Skip()
-        
     def GetPanel(self):
         """!Get main widget panel"""
         return self.panel
@@ -643,9 +624,10 @@
         
 class GPromptSTC(GPrompt, wx.stc.StyledTextCtrl):
     """!Styled wxGUI prompt with autocomplete and calltips"""    
-    def __init__(self, parent, modulesData, id = wx.ID_ANY, margin = False):
-        GPrompt.__init__(self, parent, modulesData)
-        wx.stc.StyledTextCtrl.__init__(self, self.panel, id)
+    def __init__(self, parent, modulesData, updateCmdHistory = True, margin = False):
+        GPrompt.__init__(self, parent = parent, 
+                         modulesData = modulesData, updateCmdHistory = updateCmdHistory)
+        wx.stc.StyledTextCtrl.__init__(self, self.panel, id = wx.ID_ANY)
         
         #
         # styles
@@ -757,17 +739,10 @@
         cmd = text.strip().split(' ')[0]
         
         if not self.cmdDesc or cmd != self.cmdDesc.get_name():
-            if cmd in ('r.mapcalc', 'r3.mapcalc') and \
-                    self.parent.parent.GetName() == 'LayerManager':
-                self.parent.parent.OnMapCalculator(event = None, cmd = [cmd])
-                # add command to history & clean prompt
-                self.UpdateCmdHistory([cmd])
-                self.OnCmdErase(None)
-            else:
-                try:
-                    self.cmdDesc = gtask.parse_interface(GetRealCmd(cmd))
-                except IOError:
-                    self.cmdDesc = None
+            try:
+                self.cmdDesc = gtask.parse_interface(GetRealCmd(cmd))
+            except IOError:
+                self.cmdDesc = None
 
     def OnKillFocus(self, event):
         """!Hides autocomplete"""
@@ -788,6 +763,8 @@
         
         @param cmd command given as a list
         """
+        if not self._updateCmdHistory:
+            return
         # add command to history    
         self.cmdbuffer.append(' '.join(cmd))
         
@@ -1057,7 +1034,8 @@
             pos = self.GetCurrentPos()            
             self.InsertText(pos,txt)
             self.LineEnd()
-            self.parent.parent.statusbar.SetStatusText('')
+
+            self.ShowStatusText('')
             
         elif event.GetKeyCode() == wx.WXK_RETURN and \
                 self.AutoCompActive() == False:
@@ -1069,9 +1047,7 @@
             if len(items) == 1:
                 cmd = items[0].strip()
                 if cmd in globalvar.grassCmd and \
-                        cmd != 'r.mapcalc' and \
                         (not self.cmdDesc or cmd != self.cmdDesc.get_name()):
-                    
                     try:
                         self.cmdDesc = gtask.parse_interface(GetRealCmd(cmd))
                     except IOError:
@@ -1083,13 +1059,12 @@
 
     def ShowStatusText(self, text):
         """!Sets statusbar text, if it's too long, it is cut off"""
-        maxLen = self.parent.parent.statusbar.GetFieldRect(0).GetWidth()/ 7 # any better way?
-        if len(text) < maxLen:
-            self.parent.parent.statusbar.SetStatusText(text)
-        else:
-            self.parent.parent.statusbar.SetStatusText(text[:maxLen]+'...')
+        # event is not propagated beyond dialog
+        # thus when GPrompt in Modeler is inside a dialog, 
+        # it does not show text in modeler statusbar which is probably
+        # the right behaviour. The dialog itself should display the text.
+        wx.PostEvent(self, gShowNotification(self.GetId(), message = text))
         
-        
     def GetTextLeft(self):
         """!Returns all text left of the caret"""
         pos = self.GetCurrentPos()

Modified: grass/trunk/gui/wxpython/lmgr/frame.py
===================================================================
--- grass/trunk/gui/wxpython/lmgr/frame.py	2012-11-21 04:11:16 UTC (rev 53943)
+++ grass/trunk/gui/wxpython/lmgr/frame.py	2012-11-21 09:05:50 UTC (rev 53944)
@@ -23,6 +23,7 @@
 import tempfile
 import stat
 import platform
+import re
 try:
     import xml.etree.ElementTree as etree
 except ImportError:
@@ -261,11 +262,11 @@
         # create 'command output' text area
         self.goutput = GConsole(self,
                                 gcstyle = GC_SEARCH | GC_PROMPT,
-                                ignoredCmdPattern = '^d\..*')
+                                ignoredCmdPattern = '^d\..*|^r[3]?\.mapcalc$')
         self.notebook.AddPage(page = self.goutput, text = _("Command console"), name = 'output')
         self.goutput.Bind(EVT_OUTPUT_TEXT, self.OnOutputText)
         self.goutput.Bind(EVT_IGNORED_CMD_RUN,
-                          lambda event: self.DisplayCmdRun(event.cmd))
+                          lambda event: self.RunSpecialCmd(event.cmd))
         self._setCopyingOfSelectedText()
         
         # create 'search module' notebook page
@@ -536,11 +537,19 @@
             self.SetFocus()
             self.Raise()
 
-    def DisplayCmdRun(self, command):
+    def RunSpecialCmd(self, command):
+        if re.compile('^d\..*').search(command[0]):
+            self.RunDisplayCmd(command)
+        elif re.compile('r[3]?\.mapcalc').search(command[0]):
+            self.OnMapCalculator(event = None, cmd = command)
+
+    def RunDisplayCmd(self, command):
         """!Handles display commands.
 
         @param command command in a list
         """
+        if not self.currentPage:
+            self.NewDisplay(show = True)
         try:
             # display GRASS commands
             layertype = {'d.rast'         : 'raster',



More information about the grass-commit mailing list