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

svn_grass at osgeo.org svn_grass at osgeo.org
Tue May 18 05:04:38 EDT 2010


Author: martinl
Date: 2010-05-18 05:04:38 -0400 (Tue, 18 May 2010)
New Revision: 42280

Modified:
   grass/branches/develbranch_6/gui/wxpython/gui_modules/ghelp.py
   grass/branches/develbranch_6/gui/wxpython/gui_modules/gmodeler.py
   grass/branches/develbranch_6/gui/wxpython/gui_modules/menuform.py
Log:
wxGUI/modeler: parametrization implemented (including model file
settings)
(merge r42272 from trunk)


Modified: grass/branches/develbranch_6/gui/wxpython/gui_modules/ghelp.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/gui_modules/ghelp.py	2010-05-18 06:56:03 UTC (rev 42279)
+++ grass/branches/develbranch_6/gui/wxpython/gui_modules/ghelp.py	2010-05-18 09:04:38 UTC (rev 42280)
@@ -195,6 +195,11 @@
         desc = self.cmdPrompt.GetCommandDesc(cmd)
         if self.showTip:
             self.searchTip.SetLabel(desc)
+    
+    def Reset(self):
+        """!Reset widget"""
+        self.searchBy.SetSelection(0)
+        self.search.SetValue('')
         
 class MenuTreeWindow(wx.Panel):
     """!Show menu tree"""

Modified: grass/branches/develbranch_6/gui/wxpython/gui_modules/gmodeler.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/gui_modules/gmodeler.py	2010-05-18 06:56:03 UTC (rev 42279)
+++ grass/branches/develbranch_6/gui/wxpython/gui_modules/gmodeler.py	2010-05-18 09:04:38 UTC (rev 42280)
@@ -16,7 +16,8 @@
  - WriteModelFile
  - PreferencesDialog
  - PropertiesDialog
- 
+ - ModelParamDialog
+
 (C) 2010 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.
@@ -32,6 +33,8 @@
 import getpass
 import stat
 import textwrap
+import tempfile
+import copy
 
 try:
     import xml.etree.ElementTree as etree
@@ -133,7 +136,7 @@
                                      y = action['pos'][1],
                                      width = action['size'][0],
                                      height = action['size'][1],
-                                     cmd = action['cmd'])
+                                     task = action['task'])
             actionItem.SetId(action['id'])
 
             self.actions.append(actionItem)
@@ -243,7 +246,35 @@
         
         for data in self.data:
             data.Update()
+
+    def IsParametrized(self):
+        """!Return True if model is parametrized"""
+        if self.Parametrize():
+            return True
+        
+        return False
     
+    def Parametrize(self):
+        """!Return parametrized options"""
+        result = dict()
+        for action in self.actions:
+            name   = action.GetName()
+            params = action.GetParams()
+            for f in params['flags']:
+                if f.get('parametrized', False):
+                    if not result.has_key(name):
+                        result[name] = { 'flags' : list(),
+                                         'params': list() }
+                    result[name]['flags'].append(f)
+            for p in params['params']:
+                if p.get('parametrized', False):
+                    if not result.has_key(name):
+                        result[name] = { 'flags' : list(),
+                                         'params': list() }
+                    result[name]['params'].append(p)
+        
+        return result
+    
 class ModelFrame(wx.Frame):
     def __init__(self, parent, id = wx.ID_ANY,
                  title = _("GRASS GIS Graphical Modeler"), **kwargs):
@@ -571,12 +602,34 @@
             if ret != wx.ID_YES:
                 return
         
+        params = self.model.Parametrize()
+        if params:
+            dlg = ModelParamDialog(parent = self,
+                                   params = params)
+            dlg.CenterOnParent()
+            
+            ret = dlg.ShowModal()
+            if ret != wx.ID_OK:
+                dlg.Destroy()
+                return
+        
         self.goutput.cmdThread.SetId(-1)
         for action in self.model.GetActions():
+            name = action.GetName()
+            if params.has_key(name):
+                paramsOrig = action.GetParams(dcopy = True)
+                action.MergeParams(params[name])
+            
             self.SetStatusText(_('Running model...'), 0) 
             self.goutput.RunCmd(command = action.GetLog(string = False),
                                 onDone = self.OnDone)
+            
+            if params.has_key(name):
+                action.SetParams(paramsOrig)
         
+        if params:
+            dlg.Destroy()
+        
     def OnDone(self, returncode):
         """!Computation finished"""
         self.SetStatusText('', 0)
@@ -836,12 +889,13 @@
         
         # show properties dialog
         win = action.GetPropDialog()
-        if not win:
+        if not win and action.GetLog(string = False):
             module = menuform.GUI().ParseCommand(action.GetLog(string = False),
                                                  completed = (self.GetOptData, action, action.GetParams()),
                                                  parentframe = self, show = True)
-        elif not win.IsShown():
+        elif win and not win.IsShown():
             win.Show()
+        
         if win:
             win.Raise()
 
@@ -949,7 +1003,7 @@
             self.canvas.Refresh()
         
         if dcmd:
-            layer.SetProperties(dcmd, params, propwin)
+            layer.SetProperties(params, propwin)
             
         self.SetStatusText(layer.GetLog(), 0)
         
@@ -1009,13 +1063,24 @@
         self.canvas.Refresh(True)
         
     def WriteModelFile(self, filename):
-        """!Save model to model file
+        """!Save model to model file, recover original file on error.
         
         @return True on success
         @return False on failure
         """
+        tmpfile = tempfile.TemporaryFile(mode='w+b')
         try:
-            file = open(filename, "w")
+            WriteModelFile(fd = tmpfile, actions = self.model.GetActions(), data = self.model.GetData())
+        except StandardError:
+            GMessage(parent = self,
+                     message = _("Writing current settings to model file failed."))
+            return False
+        
+        try:
+            mfile = open(filename, "w")
+            tmpfile.seek(0)
+            for line in tmpfile.readlines():
+                mfile.write(line)
         except IOError:
             wx.MessageBox(parent = self,
                           message = _("Unable to open file <%s> for writing.") % filename,
@@ -1023,18 +1088,8 @@
                           style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
             return False
         
-        try:
-            WriteModelFile(fd = file, actions = self.model.GetActions(), data = self.model.GetData())
-        except StandardError:
-            file.close()
-            
-            GMessage(parent = self,
-                     message = _("Writing current settings to model file failed."))
-            
-            return False
+        mfile.close()
         
-        file.close()
-        
         return True
     
 class ModelCanvas(ogl.ShapeCanvas):
@@ -1074,20 +1129,23 @@
         
 class ModelAction(ogl.RectangleShape):
     """!Action class (GRASS module)"""
-    def __init__(self, parent, x, y, cmd = None, width = None, height = None):
+    def __init__(self, parent, x, y, cmd = None, task = None, width = None, height = None):
         self.parent  = parent
-        self.cmd     = cmd
+        self.task    = task
         if not width:
             width = UserSettings.Get(group='modeler', key='action', subkey=('size', 'width'))
         if not height:
             height = UserSettings.Get(group='modeler', key='action', subkey=('size', 'height'))
         
-        if self.cmd:
-            task = menuform.GUI().ParseCommand(cmd = self.cmd,
-                                               show = None)
-            self.params = task.get_options()
+        if cmd:
+            self.task = menuform.GUI().ParseCommand(cmd = self.cmd,
+                                                    show = None)
         else:
-            self.params  = None
+            if task:
+                self.task = task
+            else:
+                self.task = None
+        
         self.propWin = None
         self.id      = -1    # used for gxm file
         
@@ -1103,10 +1161,11 @@
             self.SetY(y)
             self.SetPen(wx.BLACK_PEN)
             self._setBrush(False)
-            if self.cmd and len(self.cmd) > 0:
-                self.AddText(self.cmd[0])
+            cmd = self.task.getCmd(ignoreErrors = False)
+            if cmd and len(cmd) > 0:
+                self.AddText(cmd[0])
             else:
-                self.AddText('<<module>>')
+                self.AddText('<<%s>>' % _("module"))
         
     def _setBrush(self, isvalid):
         """!Set brush"""
@@ -1130,10 +1189,10 @@
         """!Set id"""
         self.id = id
     
-    def SetProperties(self, dcmd, params, propwin):
+    def SetProperties(self, params, propwin):
         """!Record properties dialog"""
-        self.cmd = dcmd
-        self.params = params
+        self.task.params = params['params']
+        self.task.flags  = params['flags']
         self.propWin = propwin
 
     def GetPropDialog(self):
@@ -1142,30 +1201,44 @@
 
     def GetLog(self, string = True):
         """!Get logging info"""
+        cmd = self.task.getCmd(ignoreErrors = True)
         if string:
-            if self.cmd is None:
+            if cmd is None:
                 return ''
             else:
-                return ' '.join(self.cmd)
+                return ' '.join(cmd)
         
-        return self.cmd
+        return cmd
     
     def GetName(self):
         """!Get name"""
-        if self.cmd and len(self.cmd) > 0:
-            return self.cmd[0]
+        cmd = self.task.getCmd(ignoreErrors = True)
+        if cmd and len(cmd) > 0:
+            return cmd[0]
         
         return _('unknown')
 
-    def GetParams(self):
+    def GetParams(self, dcopy = False):
         """!Get dictionary of parameters"""
-        return self.params
+        if dcopy:
+            return copy.deepcopy(self.task.get_options())
+        
+        return self.task.get_options()
 
-    def SetParams(self, params, cmd):
+    def SetParams(self, params):
         """!Set dictionary of parameters"""
-        self.params = params
-        self.cmd    = cmd
-
+        self.task.params = params['params']
+        self.task.flags  = params['flags']
+        
+    def MergeParams(self, params):
+        """!Merge dictionary of parameters"""
+        for f in params['flags']:
+            self.task.set_flag(f['name'],
+                               f.get('value', False))
+        for p in params['params']:
+            self.task.set_param(p['name'],
+                                p.get('value', ''))
+        
     def SetValid(self, isvalid):
         """!Set instance to be valid/invalid"""
         self.isValid = isvalid
@@ -1277,9 +1350,8 @@
                 task = menuform.GUI().ParseCommand(cmd = action.GetLog(string = False),
                                                    show = None)
                 task.set_param(self.name, self.value)
-                action.SetParams(params = task.get_options(),
-                                 cmd = task.getCmd(ignoreErrors = True))
-            
+                action.SetParams(params = task.get_options())
+        
     def GetActions(self, direction):
         """!Get related actions
 
@@ -1546,6 +1618,10 @@
         self.btnCancel = wx.Button(self.panel, wx.ID_CANCEL)
         self.btnOk     = wx.Button(self.panel, wx.ID_OK)
         self.btnOk.SetDefault()
+        self.btnOk.Enable(False)
+
+        self.cmd_prompt.Bind(wx.EVT_KEY_UP, self.OnText)
+        self.Bind(wx.EVT_BUTTON, self.OnOk, self.btnOk)
         
         self._layout()
         
@@ -1589,11 +1665,37 @@
     
     def OnOk(self, event):
         self.btnOk.SetFocus()
+        cmd = self.GetCmd()
         
+        if len(cmd) < 1:
+            GMessage(parent = self,
+                     message = _("Command not defined.\n\n"
+                                 "Unable to add new action to the model."))
+            return
+        
+        if cmd[0] not in globalvar.grassCmd['all']:
+            GMessage(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)
+        
+    def OnText(self, event):
+        if self.cmd_prompt.AutoCompActive():
+            return
+        
+        entry = self.cmd_prompt.GetTextLeft()
+        if len(entry) > 0:
+            self.btnOk.Enable()
+        else:
+            self.btnOk.Enable(False)
+            
+        event.Skip()
+        
     def Reset(self):
         """!Reset dialog"""
-        self.searchBy.SetSelection(0)
-        self.search.SetValue('')
+        self.search.Reset()
         self.cmd_prompt.OnCmdErase(None)
 
 class ModelRelation(ogl.LineShape):
@@ -1653,16 +1755,16 @@
             
             task = action.find('task')
             if task:
-                cmd = self._processTask(task)
+                task = self._processTask(task)
             else:
-                cmd = None
-
+                task = None
+            
             aId = int(action.get('id', -1))
             
-            self.actions.append({ 'pos' : pos,
-                                  'size': size,
-                                  'cmd' : cmd,
-                                  'id'  : aId })
+            self.actions.append({ 'pos'  : pos,
+                                  'size' : size,
+                                  'task' : task,
+                                  'id'   : aId })
             
     def _getDim(self, node):
         """!Get position and size of shape"""
@@ -1720,25 +1822,49 @@
                                'from' : fromDir })
         
     def _processTask(self, node):
-        """!Process task"""
+        """!Process task
+
+        @return grassTask instance
+        @return None on error
+        """
         cmd = list()
+        parametrized = list()
+        
         name = node.get('name', None)
         if not name:
-            return cmd
+            return None
+        
         cmd.append(name)
         
         # flags
-        for p in node.findall('flag'):
-            flag = p.get('name', '')
+        for f in node.findall('flag'):
+            flag = f.get('name', '')
+            if f.get('parametrized', '0') == '1':
+                parametrized.append(('flag', flag))
+                if f.get('value', '1') == '0':
+                    continue
             if len(flag) > 1:
                 cmd.append('--' + flag)
             else:
                 cmd.append('-' + flag)
         # parameters
         for p in node.findall('parameter'):
-            cmd.append('%s=%s' % (p.get('name', ''),
+            name = p.get('name', '')
+            if p.find('parametrized') is not None:
+                parametrized.append(('param', name))
+            cmd.append('%s=%s' % (name,
                                   self._filterValue(self._getNodeText(p, 'value'))))
-        return cmd
+            
+        task = menuform.GUI().ParseCommand(cmd = cmd,
+                                           show = None)
+        
+        for opt, name in parametrized:
+            if opt == 'flag':
+                task.set_flag(name, True, element = 'parametrized')
+            else:
+                task.set_param(name, True, element = 'parametrized')
+        
+        return task
     
 class WriteModelFile:
     """!Generic class for writing model file"""
@@ -1788,9 +1914,17 @@
             for key, val in action.GetParams().iteritems():
                 if key == 'flags':
                     for f in val:
-                        if f.get('value', False):
-                            self.fd.write('%s<flag name="%s" />\n' %
-                                          (' ' * self.indent, f.get('name', '')))
+                        if f.get('value', False) or f.get('parametrized', False):
+                            if f.get('parametrized', False):
+                                if f.get('value', False) == False:
+                                    self.fd.write('%s<flag name="%s" value="0" parametrized="1" />\n' %
+                                                  (' ' * self.indent, f.get('name', '')))
+                                else:
+                                    self.fd.write('%s<flag name="%s" parametrized="1" />\n' %
+                                                  (' ' * self.indent, f.get('name', '')))
+                            else:
+                                self.fd.write('%s<flag name="%s" />\n' %
+                                              (' ' * self.indent, f.get('name', '')))
                 else: # parameter
                     for p in val:
                         if not p.get('value', ''):
@@ -1798,6 +1932,8 @@
                         self.fd.write('%s<parameter name="%s">\n' %
                                       (' ' * self.indent, p.get('name', '')))
                         self.indent += 4
+                        if p.get('parametrized', False):
+                            self.fd.write('%s<parametrized />\n' % (' ' * self.indent))
                         self.fd.write('%s<value>%s</value>\n' %
                                       (' ' * self.indent, self._filterValue(p.get('value', ''))))
                         self.indent -= 4
@@ -2200,7 +2336,71 @@
         self.name.SetValue(prop['name'])
         self.desc.SetValue(prop['desc'])
         self.author.SetValue(prop['author'])
+
+class ModelParamDialog(wx.Dialog):
+    def __init__(self, parent, params, id = wx.ID_ANY, title = _("Model parameters"),
+                 style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
+        """!Model parameters dialog
+        """
+        self.parent = parent
+        self.params = params
         
+        wx.Dialog.__init__(self, parent = parent, id = id, title = title, style = style, **kwargs)
+        
+        self.notebook = FN.FlatNotebook(self, id = wx.ID_ANY,
+                                        style = FN.FNB_FANCY_TABS |
+                                        FN.FNB_BOTTOM |
+                                        FN.FNB_NO_NAV_BUTTONS |
+                                        FN.FNB_NO_X_BUTTON)
+        panel = self._createPages()
+        wx.CallAfter(self.notebook.SetSelection, 0)
+        
+        self.btnCancel = wx.Button(parent = self, id = wx.ID_CANCEL)
+        self.btnRun     = wx.Button(parent = self, id = wx.ID_OK,
+                                    label = _("&Run"))
+        self.btnRun.SetDefault()
+        
+        self._layout()
+        
+        size = self.GetBestSize()
+        self.SetMinSize(size)
+        self.SetSize((size.width, size.height +
+                      panel.constrained_size[1] -
+                      panel.panelMinHeight))
+                
+    def _layout(self):
+        btnSizer = wx.StdDialogButtonSizer()
+        btnSizer.AddButton(self.btnCancel)
+        btnSizer.AddButton(self.btnRun)
+        btnSizer.Realize()
+        
+        mainSizer = wx.BoxSizer(wx.VERTICAL)
+        mainSizer.Add(item = self.notebook, proportion = 1,
+                      flag = wx.EXPAND)
+        mainSizer.Add(item=btnSizer, proportion=0,
+                      flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
+        
+        self.SetSizer(mainSizer)
+        mainSizer.Fit(self)
+        
+    def _createPages(self):
+        """!Create for each parametrized module its own page"""
+        for name, params in self.params.iteritems():
+            panel = self._createPage(name, params)
+            self.notebook.AddPage(panel, text = name)
+    
+        return panel
+    
+    def _createPage(self, name, params):
+        """!Define notebook page"""
+        task = menuform.grassTask(name)
+        task.flags  = params['flags']
+        task.params = params['params']
+        
+        panel = menuform.cmdPanel(parent = self, id = wx.ID_ANY, task = task)
+        
+        return panel
+    
 def main():
     app = wx.PySimpleApp()
     wx.InitAllImageHandlers()

Modified: grass/branches/develbranch_6/gui/wxpython/gui_modules/menuform.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/gui_modules/menuform.py	2010-05-18 06:56:03 UTC (rev 42279)
+++ grass/branches/develbranch_6/gui/wxpython/gui_modules/menuform.py	2010-05-18 09:04:38 UTC (rev 42280)
@@ -188,12 +188,11 @@
                 if prompt == 'vector':
                     name = p.get('name', '')
                     if name in ('map', 'input'):
-                        self.eventId = p['wxId']
+                        self.eventId = p['wxId'][0]
             if self.eventId is None:
                 return
         
         p = self.task.get_param(self.eventId, element='wxId', raiseError=False)
-        
         if not p or \
                 not p.has_key('wxId-bind'):
             return
@@ -347,22 +346,30 @@
     
     def get_param(self, value, element='name', raiseError=True):
         """!Find and return a param by name."""
-        for p in self.params:
-            if p[element] is None:
-                continue
-            if type(value) == types.StringType:
-                if p[element][:len(value)] == value:
-                    return p
-            else:
-                if p[element] == value:
-                    return p
+        try:
+            for p in self.params:
+                val = p[element]
+                if val is None:
+                    continue
+                if type(val) in (types.ListType, types.TupleType):
+                    if value in val:
+                        return p
+                elif type(val) == types.StringType:
+                    if p[element][:len(value)] == value:
+                        return p
+                else:
+                    if p[element] == value:
+                        return p
+        except KeyError:
+            pass
+        
         if raiseError:
-            raise ValueError, _("Parameter not found: %s") % \
-                value
+            raise ValueError, _("Parameter element '%(element)s' not found: '%(value)s'") % \
+                { 'element' : element, 'value' : value }
         else:
             return None
-
-    def set_param(self, aParam, aValue):
+        
+    def set_param(self, aParam, aValue, element = 'value'):
         """
         Set param value/values.
         """
@@ -371,7 +378,7 @@
         except ValueError:
             return
         
-        param['value'] = aValue
+        param[element] = aValue
             
     def get_flag(self, aFlag):
         """
@@ -382,7 +389,7 @@
                 return f
         raise ValueError, _("Flag not found: %s") % aFlag
 
-    def set_flag(self, aFlag, aValue):
+    def set_flag(self, aFlag, aValue, element = 'value'):
         """
         Enable / disable flag.
         """
@@ -391,7 +398,7 @@
         except ValueError:
             return
         
-        param['value'] = aValue
+        param[element] = aValue
         
     def getCmdError(self):
         """!Get error string produced by getCmd(ignoreErrors = False)
@@ -573,12 +580,17 @@
     The command is checked and sent to the clipboard when clicking
     'Copy'.
     """
-    def __init__(self, parent, ID, task_description, get_dcmd=None, layer=None):
+    def __init__(self, parent, ID, task_description,
+                 get_dcmd = None, layer = None):
         self.get_dcmd = get_dcmd
-        self.layer = layer
-        self.task = task_description
-        self.parent = parent # LayerTree | None
-
+        self.layer    = layer
+        self.task     = task_description
+        self.parent   = parent            # LayerTree | Modeler | None | ...
+        if parent and parent.GetName() == 'Modeler':
+            self.modeler = self.parent
+        else:
+            self.modeler = None
+        
         # module name + keywords
         if self.task.name.split('.')[-1] in ('py', 'sh'):
             title = str(self.task.name.rsplit('.',1)[0])
@@ -591,7 +603,8 @@
             pass
         
         wx.Frame.__init__(self, parent=parent, id=ID, title=title,
-                          pos=wx.DefaultPosition, style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL)
+                          pos=wx.DefaultPosition, style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL,
+                          name = "MainFrame")
 
         self.locale = wx.Locale(language = wx.LANGUAGE_DEFAULT)
 
@@ -607,7 +620,7 @@
 
         # set apropriate output window
         if self.parent:
-            self.standalone   = False
+            self.standalone = False
         else:
             self.standalone = True
         
@@ -640,10 +653,8 @@
         self.Layout()
 
         # notebooks
-        self.notebookpanel = cmdPanel (parent=self.panel, task=self.task, standalone=self.standalone,
-                                       mainFrame=self)
-        ### add 'command output' tab also for dialog open from menu
-        #         if self.standalone:
+        self.notebookpanel = cmdPanel(parent = self.panel, task = self.task,
+                                      mainFrame = self)
         self.goutput = self.notebookpanel.goutput
         self.notebookpanel.OnUpdateValues = self.updateValuesHook
         guisizer.Add (item=self.notebookpanel, proportion=1, flag=wx.EXPAND)
@@ -718,7 +729,7 @@
         guisizer.Add(item=btnsizer, proportion=0, flag=wx.ALIGN_CENTER | wx.LEFT | wx.RIGHT,
                      border = 30)
 
-        if self.parent and self.parent.GetName() != 'Modeler':
+        if self.parent and not self.modeler:
             addLayer = False
             for p in self.task.params:
                 if p.get('age', 'old') == 'new' and \
@@ -774,10 +785,10 @@
         self.Layout()
 
         #keep initial window size limited for small screens
-        width,height = self.GetSizeTuple()
+        width, height = self.GetSizeTuple()
         if width > 640: width = 640
         if height > 480: height = 480
-        self.SetSize((width,height))
+        self.SetSize((width, height))
         
         # fix goutput's pane size
         if self.goutput:
@@ -820,7 +831,7 @@
 
     def OnApply(self, event):
         """!Apply the command"""
-        if self.parent and self.parent.GetName() == 'Modeler':
+        if self.modeler:
             cmd = self.createCmd(ignoreErrors = True)
         else:
             cmd = self.createCmd()
@@ -919,16 +930,18 @@
         return self.notebookpanel.createCmd(ignoreErrors=ignoreErrors)
 
 class cmdPanel(wx.Panel):
+    """!A panel containing a notebook dividing in tabs the different
+    guisections of the GRASS cmd.
     """
-    A panel containing a notebook dividing in tabs the different guisections of the GRASS cmd.
-    """
-    def __init__( self, parent, task, standalone, mainFrame, *args, **kwargs ):
-        wx.Panel.__init__( self, parent, *args, **kwargs )
-
-        self.parent = mainFrame
+    def __init__(self, parent, task, id = wx.ID_ANY, mainFrame = None, *args, **kwargs):
+        if mainFrame:
+            self.parent = mainFrame
+        else:
+            self.parent = parent
         self.task = task
-        fontsize = 10
         
+        wx.Panel.__init__(self, parent, id = id, *args, **kwargs)
+        
         # Determine tab layout
         sections = []
         is_section = {}
@@ -978,7 +991,7 @@
 
         # are we running from command line?
         ### add 'command output' tab regardless standalone dialog
-        if self.parent.get_dcmd is None:
+        if self.parent.GetName() == "MainFrame" and self.parent.get_dcmd is None:
             self.goutput = goutput.GMConsole(parent=self, margin=False,
                                              pageid=self.notebook.GetPageCount())
             self.goutputId = self.notebook.GetPageCount()
@@ -1028,8 +1041,22 @@
                             flag=wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL)
             which_sizer.Add(item=title_sizer, proportion=0,
                             flag=wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, border=5)
-            f['wxId'] = chk.GetId()
+            f['wxId'] = [ chk.GetId(), ]
             chk.Bind(wx.EVT_CHECKBOX, self.OnSetValue)
+            
+            if self.parent.GetName() == 'MainFrame' and self.parent.modeler:
+                parChk = wx.CheckBox(parent = which_panel, id = wx.ID_ANY,
+                                     label = _("Parametrized in model"))
+                parChk.SetName('ModelParam')
+                parChk.SetValue(f.get('parametrized', False))
+                if f.has_key('wxId'):
+                    f['wxId'].append(parChk.GetId())
+                else:
+                    f['wxId'] = [ parChk.GetId() ]
+                parChk.Bind(wx.EVT_CHECKBOX, self.OnSetValue)
+                which_sizer.Add(item = parChk, proportion = 0,
+                                flag = wx.LEFT, border = 20)
+            
             if f['name'] in ('verbose', 'quiet'):
                 chk.Bind(wx.EVT_CHECKBOX, self.OnVerbosity)
                 vq = UserSettings.Get(group='cmd', key='verbosity', subkey='selection')
@@ -1115,7 +1142,7 @@
                         isEnabled[ defval ] = 'yes'
                         # for multi checkboxes, this is an array of all wx IDs
                         # for each individual checkbox
-                        p[ 'wxId' ] = []
+                        p['wxId'] = list()
                     idx = 0
                     for val in valuelist:
                         try:
@@ -1125,7 +1152,7 @@
                         
                         chkbox = wx.CheckBox( parent=which_panel,
                                               label = text_beautify(label))
-                        p[ 'wxId' ].append( chkbox.GetId() )
+                        p['wxId'].append( chkbox.GetId() )
                         if isEnabled.has_key(val):
                             chkbox.SetValue( True )
                         hSizer.Add( item=chkbox, proportion=0,
@@ -1169,7 +1196,7 @@
                         which_sizer.Add(item=txt2, proportion=0,
                                         flag=style, border=5)
 
-                        p['wxId'] = txt2.GetId()
+                        p['wxId'] = [ txt2.GetId(), ]
                         txt2.Bind(wx.EVT_TEXT, self.OnSetValue)
                     else:
                         # list of values (combo)
@@ -1181,7 +1208,7 @@
                             cb.SetValue(p['value']) # parameter previously set
                         which_sizer.Add( item=cb, proportion=0,
                                          flag=wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT, border=5)
-                        p['wxId'] = cb.GetId()
+                        p['wxId'] = [ cb.GetId(), ]
                         cb.Bind( wx.EVT_COMBOBOX, self.OnSetValue)
                         cb.Bind(wx.EVT_TEXT, self.OnSetValue)
             
@@ -1237,7 +1264,7 @@
                 
                 which_sizer.Add(item=txt3, proportion=0,
                                 flag=style, border=5)
-                p['wxId'] = txt3.GetId()
+                p['wxId'] = [ txt3.GetId(), ]
 
             #
             # element selection tree combobox (maps, icons, regions, etc.)
@@ -1276,7 +1303,7 @@
                     
                     # A select.Select is a combobox with two children: a textctl and a popupwindow;
                     # we target the textctl here
-                    p['wxId'] = selection.GetChildren()[0].GetId()
+                    p['wxId'] = [ selection.GetChildren()[0].GetId(), ]
                     selection.GetChildren()[0].Bind(wx.EVT_TEXT, self.OnSetValue)
                     if p.get('prompt', '') in ('vector', 'group'):
                         selection.Bind(wx.EVT_TEXT, self.OnUpdateSelection)
@@ -1354,7 +1381,7 @@
                             ### win.Bind(wx.EVT_COMBOBOX, self.OnSetValue)
                             win.Bind(wx.EVT_TEXT, self.OnSetValue)
                             
-                    p['wxId'] = win.GetId()
+                    p['wxId'] = [ win.GetId(), ]
                     
                     which_sizer.Add(item=win, proportion=0,
                                     flag=wx.ADJUST_MINSIZE | wx.BOTTOM | wx.LEFT, border=5)
@@ -1386,7 +1413,6 @@
                             none_check.SetValue(True)
                         else:
                             none_check.SetValue(False)
-                        # none_check.SetFont( wx.Font( fontsize, wx.FONTFAMILY_DEFAULT, wx.NORMAL, text_style, 0, ''))
                         this_sizer.Add(item=none_check, proportion=0,
                                        flag=wx.ADJUST_MINSIZE | wx.LEFT | wx.RIGHT | wx.TOP, border=5)
                         which_sizer.Add( this_sizer )
@@ -1410,8 +1436,21 @@
                     # A file browse button is a combobox with two children:
                     # a textctl and a button;
                     # we have to target the button here
-                    p['wxId'] = fbb.GetChildren()[1].GetId()
-
+                    p['wxId'] = [ fbb.GetChildren()[1].GetId(), ]
+            
+            if self.parent.GetName() == 'MainFrame' and self.parent.modeler:
+                parChk = wx.CheckBox(parent = which_panel, id = wx.ID_ANY,
+                                     label = _("Parametrized in model"))
+                parChk.SetName('ModelParam')
+                parChk.SetValue(p.get('parametrized', False))
+                if p.has_key('wxId'):
+                    p['wxId'].append(parChk.GetId())
+                else:
+                    p['wxId'] = [ parChk.GetId() ]
+                parChk.Bind(wx.EVT_CHECKBOX, self.OnSetValue)
+                which_sizer.Add(item = parChk, proportion = 0,
+                                flag = wx.LEFT, border = 20)
+                
             if title_txt is not None:
                 # create tooltip if given
                 if len(p['values_desc']) > 0:
@@ -1428,7 +1467,7 @@
 
             if p == first_param:
                 if type(p['wxId']) == type(1):
-                    self.FindWindowById(p['wxId']).SetFocus()
+                    self.FindWindowById(p['wxId'][0]).SetFocus()
         
         #
         # set widget relations for OnUpdateSelection
@@ -1468,10 +1507,10 @@
         
         pColumnIds = []
         for p in pColumn:
-            pColumnIds.append(p['wxId'])
+            pColumnIds += p['wxId']
         pLayerIds = []
         for p in pLayer:
-            pLayerIds.append(p['wxId']) 
+            pLayerIds += p['wxId']
         
         if pMap:
             pMap['wxId-bind'] = copy.copy(pColumnIds)
@@ -1482,10 +1521,10 @@
             p['wxId-bind'] = copy.copy(pColumnIds)
 
         if pDriver and pTable:
-            pDriver['wxId-bind'] = [pTable['wxId'], ]
+            pDriver['wxId-bind'] = pTable['wxId']
 
         if pDatabase and pTable:
-            pDatabase['wxId-bind'] = [pTable['wxId'], ]
+            pDatabase['wxId-bind'] = pTable['wxId']
 
         if pTable and pColumnIds:
             pTable['wxId-bind'] = pColumnIds
@@ -1522,7 +1561,7 @@
         self.hasMain = tab.has_key( _('Required') ) # publish, to enclosing Frame for instance
 
         self.Bind(EVT_DIALOG_UPDATE, self.OnUpdateDialog)
-
+        
     def OnUpdateDialog(self, event):
         for fn, kwargs in event.data.iteritems():
             fn(**kwargs)
@@ -1564,7 +1603,7 @@
     def OnColorChange( self, event ):
         myId = event.GetId()
         for p in self.task.params:
-            if 'wxId' in p and type( p['wxId'] ) == type( [] ) and myId in p['wxId']:
+            if 'wxId' in p and myId in p['wxId']:
                 has_button = p['wxId'][1] is not None
                 if has_button and wx.FindWindowById( p['wxId'][1] ).GetValue() == True:
                     p[ 'value' ] = 'none'
@@ -1596,7 +1635,7 @@
         me = event.GetId()
         theParam = None
         for p in self.task.params:
-            if 'wxId' in p and type( p['wxId'] ) == type( [] ) and me in p['wxId']:
+            if 'wxId' in p and me in p['wxId']:
                 theParam = p
                 myIndex = p['wxId'].index( me )
 
@@ -1631,11 +1670,24 @@
         """
         myId = event.GetId()
         me = wx.FindWindowById( myId )
+        name = me.GetName()
         
         for porf in self.task.params + self.task.flags:
-            if 'wxId' in porf and type( porf[ 'wxId' ] ) == type( 1 ) and porf['wxId'] == myId:
-                if porf.has_key('wxGetValue') and porf['wxGetValue']:
-                    porf['value'] = porf['wxGetValue']()
+            if not porf.has_key('wxId'):
+                continue
+            found = False
+            for id in porf['wxId']:
+                if id == myId:
+                    found = True
+                    break
+            
+            if found:
+                if name in ('LayerSelect', 'DriverSelect', 'TableSelect'):
+                    porf['value'] = me.GetStringSelection()
+                elif name == 'GdalSelect':
+                    porf['value'] = event.dsn
+                elif name == 'ModelParam':
+                    porf['parametrized'] = me.IsChecked()
                 else:
                     porf['value'] = me.GetValue()
         
@@ -1753,12 +1805,12 @@
         
         return processTask(tree).GetTask()
     
-    def ParseCommand(self, cmd, gmpath=None, completed=None, parentframe=None,
-                     show=True, modal=False):
+    def ParseCommand(self, cmd, gmpath = None, completed = None, parentframe = None,
+                     show = True, modal = False):
         """!Parse command
-
+        
         Note: cmd is given as list
-
+        
         If command is given with options, return validated cmd list:
          - add key name for first parameter if not given
          - change mapname to mapname at mapset
@@ -1776,17 +1828,17 @@
                 dcmd_params.update(completed[2])
 
         self.parent = parentframe
-
+        
         # parse the interface decription
         self.grass_task = self.ParseInterface(cmd)
-
+        
         # if layer parameters previously set, re-insert them into dialog
         if completed is not None:
             if 'params' in dcmd_params:
                 self.grass_task.params = dcmd_params['params']
             if 'flags' in dcmd_params:
                 self.grass_task.flags = dcmd_params['flags']
-
+        
         # update parameters if needed && validate command
         if len(cmd) > 1:
             i = 0
@@ -1808,14 +1860,19 @@
                         else:
                             raise ValueError, _("Unable to parse command %s") % ' '.join(cmd)
 
-                    if self.grass_task.get_param(key)['element'] in ['cell', 'vector']:
+                    element = self.grass_task.get_param(key)['element']
+                    if element in ['cell', 'vector']:
                         # mapname -> mapname at mapset
                         if '@' not in value:
-                            value = value + '@' + grass.gisenv()['MAPSET']
+                            mapset = grass.find_file(value, element)['mapset']
+                            curr_mapset = grass.gisenv()['MAPSET']
+                            if mapset and mapset != curr_mapset:
+                                value = value + '@' + mapset
+                    
                     self.grass_task.set_param(key, value)
                     cmd_validated.append(key + '=' + value)
                     i = i + 1
-
+            
             # update original command list
             cmd = cmd_validated
         
@@ -1830,7 +1887,7 @@
             # update only propwin reference
             get_dcmd(dcmd=None, layer=layer, params=None,
                      propwin=self.mf)
-
+        
         if show is not None:
             self.mf.notebookpanel.OnUpdateSelection(None)
             if show is True:
@@ -1844,7 +1901,7 @@
         self.cmd = cmd
         
         return self.grass_task
-
+    
     def GetCommandInputMapParamKey(self, cmd):
         """!Get parameter key for input raster/vector map
         



More information about the grass-commit mailing list