GRASS Programmer's Manual  6.5.svn(2012)-r51648
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
model.py
Go to the documentation of this file.
00001 """!
00002 @package gmodeler.model
00003 
00004 @brief wxGUI Graphical Modeler (base classes & read/write)
00005 
00006 Classes:
00007  - model::Model
00008  - model::ModelObject
00009  - model::ModelAction
00010  - model::ModelData
00011  - model::ModelRelation
00012  - model::ModelItem
00013  - model::ModelLoop
00014  - model::ModelCondition
00015  - model::ProcessModelFile
00016  - model::WriteModelFile
00017  - model::WritePythonFile
00018  - model::ModelParamDialog
00019 
00020 (C) 2010-2012 by the GRASS Development Team
00021 
00022 This program is free software under the GNU General Public License
00023 (>=v2). Read the file COPYING that comes with GRASS for details.
00024 
00025 @author Martin Landa <landa.martin gmail.com>
00026 """
00027 
00028 import os
00029 import getpass
00030 import copy
00031 import re
00032 import mimetypes
00033 import time
00034 try:
00035     import xml.etree.ElementTree as etree
00036 except ImportError:
00037     import elementtree.ElementTree as etree # Python <= 2.4
00038 
00039 import wx
00040 from wx.lib import ogl
00041 
00042 from core                import globalvar
00043 from core                import utils
00044 from core.gcmd           import GMessage, GException, GError, RunCommand, EncodeString, GWarning
00045 from core.settings       import UserSettings
00046 from gui_core.forms      import GUI, CmdPanel
00047 from gui_core.widgets    import GNotebook
00048 
00049 from grass.script import core as grass
00050 from grass.script import task as gtask
00051 
00052 class Model(object):
00053     """!Class representing the model"""
00054     def __init__(self, canvas = None):
00055         self.items      = list() # list of actions/loops/...
00056         
00057         # model properties
00058         self.properties = { 'name'        : _("model"),
00059                             'description' : _("Script generated by wxGUI Graphical Modeler."),
00060                             'author'      : getpass.getuser() }
00061         # model variables
00062         self.variables = dict()
00063         self.variablesParams = dict()
00064         
00065         self.canvas  = canvas
00066         
00067     def GetCanvas(self):
00068         """!Get canvas or None"""
00069         return self.canvas
00070     
00071     def GetItems(self, objType = None):
00072         """!Get list of model items
00073 
00074         @param objType Object type to filter model objects
00075         """
00076         if not objType:
00077             return self.items
00078         
00079         result = list()
00080         for item in self.items:
00081             if isinstance(item, objType):
00082                 result.append(item)
00083         
00084         return result
00085 
00086     def GetItem(self, aId):
00087         """!Get item of given id
00088 
00089         @param aId item id
00090         
00091         @return Model* instance
00092         @return None if no item found
00093         """
00094         ilist = self.GetItems()
00095         for item in ilist:
00096             if item.GetId() == aId:
00097                 return item
00098         
00099         return None
00100 
00101     def GetNumItems(self, actionOnly = False):
00102         """!Get number of items"""
00103         if actionOnly:
00104             return len(self.GetItems(objType = ModelAction))
00105         
00106         return len(self.GetItems())
00107 
00108     def GetNextId(self):
00109         """!Get next id (data ignored)
00110 
00111         @return next id to be used (default: 1)
00112         """
00113         if len(self.items) < 1:
00114             return 1
00115         
00116         currId = self.items[-1].GetId()
00117         if currId > 0:
00118             return currId + 1
00119         
00120         return 1
00121 
00122     def GetProperties(self):
00123         """!Get model properties"""
00124         return self.properties
00125 
00126     def GetVariables(self, params = False):
00127         """!Get model variables"""
00128         if params:
00129             return self.variablesParams
00130         
00131         return self.variables
00132     
00133     def SetVariables(self, data):
00134         """!Set model variables"""
00135         self.variables = data
00136     
00137     def Reset(self):
00138         """!Reset model"""
00139         self.items = list()
00140         
00141     def RemoveItem(self, item):
00142         """!Remove item from model
00143         
00144         @return list of related items to remove/update
00145         """
00146         relList = list()
00147         upList = list()
00148         
00149         if not isinstance(item, ModelData):
00150             self.items.remove(item)
00151         
00152         if isinstance(item, ModelAction):
00153             for rel in item.GetRelations():
00154                 relList.append(rel)
00155                 data = rel.GetData()
00156                 if len(data.GetRelations()) < 2:
00157                     relList.append(data)
00158                 else:
00159                     upList.append(data)
00160             
00161         elif isinstance(item, ModelData):
00162             for rel in item.GetRelations():
00163                 relList.append(rel)
00164                 if rel.GetFrom() == self:
00165                     relList.append(rel.GetTo())
00166                 else:
00167                     relList.append(rel.GetFrom())
00168         
00169         elif isinstance(item, ModelLoop):
00170             for rel in item.GetRelations():
00171                 relList.append(rel)
00172             for action in self.GetItems():
00173                 action.UnSetBlock(item)
00174         
00175         return relList, upList
00176     
00177     def FindAction(self, aId):
00178         """!Find action by id"""
00179         alist = self.GetItems(objType = ModelAction)
00180         for action in alist:
00181             if action.GetId() == aId:
00182                 return action
00183         
00184         return None
00185 
00186     def GetData(self):
00187         """!Get list of data items"""
00188         result = list()
00189         dataItems = self.GetItems(objType = ModelData)
00190         
00191         for action in self.GetItems(objType = ModelAction):
00192             for rel in action.GetRelations():
00193                 dataItem = rel.GetData()
00194                 if dataItem not in result:
00195                     result.append(dataItem)
00196                 if dataItem in dataItems:
00197                     dataItems.remove(dataItem)
00198         
00199         # standalone data
00200         if dataItems:
00201             result += dataItems
00202         
00203         return result
00204 
00205     def FindData(self, value, prompt):
00206         """!Find data item in the model
00207 
00208         @param value value
00209         @param prompt prompt
00210 
00211         @return ModelData instance
00212         @return None if not found
00213         """
00214         for data in self.GetData():
00215             if data.GetValue() == value and \
00216                     data.GetPrompt() == prompt:
00217                 return data
00218         
00219         return None
00220                 
00221     def LoadModel(self, filename):
00222         """!Load model definition stored in GRASS Model XML file (gxm)
00223         
00224         @todo Validate against DTD
00225         
00226         Raise exception on error.
00227         """
00228         dtdFilename = os.path.join(globalvar.ETCWXDIR, "xml", "grass-gxm.dtd")
00229         
00230         # parse workspace file
00231         try:
00232             gxmXml = ProcessModelFile(etree.parse(filename))
00233         except StandardError, e:
00234             raise GException(e)
00235         
00236         if self.canvas:
00237             win = self.canvas.parent
00238             if gxmXml.pos:
00239                 win.SetPosition(gxmXml.pos)
00240             if gxmXml.size:
00241                 win.SetSize(gxmXml.size)
00242         
00243         # load properties
00244         self.properties = gxmXml.properties
00245         self.variables  = gxmXml.variables
00246         
00247         # load model.GetActions()
00248         for action in gxmXml.actions:
00249             actionItem = ModelAction(parent = self, 
00250                                      x = action['pos'][0],
00251                                      y = action['pos'][1],
00252                                      width = action['size'][0],
00253                                      height = action['size'][1],
00254                                      task = action['task'],
00255                                      id = action['id'])
00256             
00257             if action['disabled']:
00258                 actionItem.Enable(False)
00259             
00260             self.AddItem(actionItem)
00261             
00262             actionItem.SetValid(actionItem.GetTask().get_options())
00263             actionItem.GetLog() # substitute variables (-> valid/invalid)
00264         
00265         # load data & relations
00266         for data in gxmXml.data:
00267             dataItem = ModelData(parent = self, 
00268                                  x = data['pos'][0],
00269                                  y = data['pos'][1],
00270                                  width = data['size'][0],
00271                                  height = data['size'][1],
00272                                  prompt = data['prompt'],
00273                                  value = data['value'])
00274             dataItem.SetIntermediate(data['intermediate'])
00275             
00276             for rel in data['rels']:
00277                 actionItem = self.FindAction(rel['id'])
00278                 if rel['dir'] == 'from':
00279                     relation = ModelRelation(parent = self, fromShape = dataItem,
00280                                              toShape = actionItem, param = rel['name'])
00281                 else:
00282                     relation = ModelRelation(parent = self, fromShape = actionItem,
00283                                              toShape = dataItem, param = rel['name'])
00284                 relation.SetControlPoints(rel['points'])
00285                 actionItem.AddRelation(relation)
00286                 dataItem.AddRelation(relation)
00287 
00288             if self.canvas:
00289                 dataItem.Update()
00290            
00291         # load loops
00292         for loop in gxmXml.loops:
00293             loopItem = ModelLoop(parent = self, 
00294                                  x = loop['pos'][0],
00295                                  y = loop['pos'][1],
00296                                  width = loop['size'][0],
00297                                  height = loop['size'][1],
00298                                  text = loop['text'],
00299                                  id = loop['id'])
00300             self.AddItem(loopItem)
00301 
00302         # load conditions
00303         for condition in gxmXml.conditions:
00304             conditionItem = ModelCondition(parent = self, 
00305                                            x = condition['pos'][0],
00306                                            y = condition['pos'][1],
00307                                            width = condition['size'][0],
00308                                            height = condition['size'][1],
00309                                            text = condition['text'],
00310                                            id = condition['id'])
00311             self.AddItem(conditionItem)
00312 
00313         # define loops & if/else items
00314         for loop in gxmXml.loops:
00315             alist = list()
00316             for aId in loop['items']:
00317                 action = self.GetItem(aId)
00318                 alist.append(action)
00319             
00320             loopItem = self.GetItem(loop['id'])
00321             loopItem.SetItems(alist)
00322             
00323             for action in loopItem.GetItems():
00324                 action.SetBlock(loopItem)
00325         
00326         for condition in gxmXml.conditions:
00327             conditionItem = self.GetItem(condition['id'])
00328             for b in condition['items'].keys():
00329                 alist = list()
00330                 for aId in condition['items'][b]:
00331                     action = self.GetItem(aId)
00332                     alist.append(action)
00333                 conditionItem.SetItems(alist, branch = b)
00334             
00335             items = conditionItem.GetItems()
00336             for b in items.keys():
00337                 for action in items[b]:
00338                     action.SetBlock(conditionItem)
00339         
00340     def AddItem(self, newItem):
00341         """!Add item to the list"""
00342         iId = newItem.GetId()
00343         
00344         i  = 0
00345         for item in self.items:
00346             if item.GetId() > iId:
00347                 self.items.insert(i, newItem)
00348                 return
00349             i += 1
00350         
00351         self.items.append(newItem)
00352         
00353     def IsValid(self):
00354         """Return True if model is valid"""
00355         if self.Validate():
00356             return False
00357         
00358         return True
00359     
00360     def Validate(self):
00361         """!Validate model, return None if model is valid otherwise
00362         error string"""
00363         errList = list()
00364 
00365         variables = self.GetVariables().keys()
00366         pattern = re.compile(r'(.*)(%.+\s?)(.*)')
00367         for action in self.GetItems(objType = ModelAction):
00368             cmd = action.GetLog(string = False)
00369             
00370             task = GUI(show = None).ParseCommand(cmd = cmd)
00371             errList += map(lambda x: cmd[0] + ': ' + x, task.get_cmd_error())
00372             
00373             # check also variables
00374             for opt in cmd[1:]:
00375                 if '=' not in opt:
00376                     continue
00377                 key, value = opt.split('=', 1)
00378                 sval = pattern.search(value)
00379                 if sval:
00380                     var = sval.group(2).strip()[1:] # ignore '%'
00381                     if var not in variables:
00382                         report = True
00383                         for item in filter(lambda x: isinstance(x, ModelLoop), action.GetBlock()):
00384                             if var in item.GetText():
00385                                 report = False
00386                                 break
00387                         if report:
00388                             errList.append(cmd[0] + ": " + _("undefined variable '%s'") % var)
00389             ### TODO: check variables in file only optionally
00390             ### errList += self._substituteFile(action, checkOnly = True)
00391         
00392         return errList
00393 
00394     def _substituteFile(self, item, params = None, checkOnly = False):
00395         """!Subsitute variables in command file inputs
00396 
00397         @param checkOnly tuble - True to check variable, don't touch files
00398         
00399         @return list of undefined variables
00400         """
00401         errList = list()
00402         
00403         self.fileInput = dict()
00404         
00405         # collect ascii inputs
00406         for p in item.GetParams()['params']:
00407             if p.get('element', '') == 'file' and \
00408                     p.get('prompt', '') == 'input' and \
00409                     p.get('age', '') == 'old_file':
00410                 filename = p.get('value', p.get('default', ''))
00411                 if filename and \
00412                         mimetypes.guess_type(filename)[0] == 'text/plain':
00413                     self.fileInput[filename] = None
00414         
00415         for finput in self.fileInput:
00416             # read lines
00417             fd = open(finput, "r")
00418             try:
00419                 data = self.fileInput[finput] = fd.read()
00420             finally:
00421                 fd.close()
00422             
00423             # substitute variables
00424             write = False
00425             variables = self.GetVariables()
00426             for variable in variables:
00427                 pattern = re.compile('%' + variable)
00428                 value = ''
00429                 if params and 'variables' in params:
00430                     for p in params['variables']['params']:
00431                         if variable == p.get('name', ''):
00432                             if p.get('type', 'string') == 'string':
00433                                 value = p.get('value', '')
00434                             else:
00435                                 value = str(p.get('value', ''))
00436                             break
00437                 
00438                 if not value:
00439                     value = variables[variable].get('value', '')
00440                 
00441                 data = pattern.sub(value, data)
00442                 if not checkOnly:
00443                     write = True
00444             
00445             pattern = re.compile(r'(.*)(%.+\s?)(.*)')
00446             sval = pattern.search(data)
00447             if sval:
00448                 var = sval.group(2).strip()[1:] # ignore '%'
00449                 cmd = item.GetLog(string = False)[0]
00450                 errList.append(cmd + ": " + _("undefined variable '%s'") % var)
00451             
00452             if not checkOnly:
00453                 if write:
00454                     fd = open(finput, "w")
00455                     try:
00456                         fd.write(data)
00457                     finally:
00458                         fd.close()
00459                 else:
00460                     self.fileInput[finput] = None
00461         
00462         return errList
00463     
00464     def OnPrepare(self, item, params):
00465         self._substituteFile(item, params, checkOnly = False)
00466 
00467     def RunAction(self, item, params, log, onDone, onPrepare = None, statusbar = None):
00468         """!Run given action
00469 
00470         @param item action item
00471         @param params parameters dict
00472         @param log logging window
00473         @param onDone on-done method
00474         @param onPrepare on-prepare method
00475         @param statusbar wx.StatusBar instance or None
00476         """
00477         name = item.GetName()
00478         if name in params:
00479             paramsOrig = item.GetParams(dcopy = True)
00480             item.MergeParams(params[name])
00481         
00482         if statusbar:
00483             statusbar.SetStatusText(_('Running model...'), 0)
00484             
00485         data = { 'item' : item,
00486                  'params' : copy.deepcopy(params) }
00487         log.RunCmd(command = item.GetLog(string = False, substitute = params),
00488                    onDone = onDone, onPrepare = self.OnPrepare, userData = data)
00489         
00490         if name in params:
00491             item.SetParams(paramsOrig)
00492 
00493     def Run(self, log, onDone, parent = None):
00494         """!Run model
00495 
00496         @param log logging window (see goutput.GMConsole)
00497         @param onDone on-done method
00498         @param parent window for messages or None
00499         """
00500         if self.GetNumItems() < 1:
00501             GMessage(parent = parent,
00502                      message = _('Model is empty. Nothing to run.'))
00503             return
00504         
00505         statusbar = None
00506         if isinstance(parent, wx.Frame):
00507             statusbar = parent.GetStatusBar()
00508         
00509         # validation
00510         if statusbar:
00511             statusbar.SetStatusText(_('Validating model...'), 0)
00512         errList = self.Validate()
00513         if statusbar:
00514             statusbar.SetStatusText('', 0)
00515         if errList:
00516             dlg = wx.MessageDialog(parent = parent,
00517                                    message = _('Model is not valid. Do you want to '
00518                                                'run the model anyway?\n\n%s') % '\n'.join(errList),
00519                                    caption = _("Run model?"),
00520                                    style = wx.YES_NO | wx.NO_DEFAULT |
00521                                    wx.ICON_QUESTION | wx.CENTRE)
00522             ret = dlg.ShowModal()
00523             dlg.Destroy()
00524             if ret != wx.ID_YES:
00525                 return
00526         
00527         # parametrization
00528         params = self.Parameterize()
00529         delInterData = False
00530         if params:
00531             dlg = ModelParamDialog(parent = parent,
00532                                    params = params)
00533             dlg.CenterOnParent()
00534             
00535             ret = dlg.ShowModal()
00536             if ret != wx.ID_OK:
00537                 dlg.Destroy()
00538                 return
00539             
00540             err = dlg.GetErrors()
00541             delInterData = dlg.DeleteIntermediateData()
00542             dlg.Destroy()
00543             if err:
00544                 GError(parent = parent, message = unicode('\n'.join(err)))
00545                 return
00546             
00547             err = list()
00548             for key, item in params.iteritems():
00549                 for p in item['params']:
00550                     if p.get('value', '') == '':
00551                         err.append((key, p.get('name', ''), p.get('description', '')))
00552             if err:
00553                 GError(parent = parent,
00554                        message = _("Variables below not defined:") + \
00555                            "\n\n" + unicode('\n'.join(map(lambda x: "%s: %s (%s)" % (x[0], x[1], x[2]), err))))
00556                 return
00557         
00558         log.cmdThread.SetId(-1)
00559         for item in self.GetItems():
00560             if not item.IsEnabled():
00561                 continue
00562             if isinstance(item, ModelAction):
00563                 if item.GetBlockId():
00564                     continue
00565                 self.RunAction(item, params, log, onDone)
00566             elif isinstance(item, ModelLoop):
00567                 cond = item.GetText()
00568                 # substitute variables in condition
00569                 variables = self.GetVariables()
00570                 for variable in variables:
00571                     pattern = re.compile('%' + variable)
00572                     if pattern.search(cond):
00573                         value = ''
00574                         if params and 'variables' in params:
00575                             for p in params['variables']['params']:
00576                                 if variable == p.get('name', ''):
00577                                     value = p.get('value', '')
00578                                     break
00579                         
00580                         if not value:
00581                             value = variables[variable].get('value', '')
00582                         
00583                         if not value:
00584                             continue
00585                         
00586                         vtype = variables[variable].get('type', 'string')
00587                         if vtype == 'string':
00588                             value = '"' + value + '"'
00589                         cond = pattern.sub(value, cond)
00590                 
00591                 # split condition
00592                 condVar, condText = map(lambda x: x.strip(), re.split('\s*in\s*', cond))
00593                 pattern = re.compile('%' + condVar)
00594                 ### for vars()[condVar] in eval(condText): ?
00595                 if condText[0] == '`' and condText[-1] == '`':
00596                     # run command
00597                     cmd, dcmd = utils.CmdToTuple(condText[1:-1].split(' '))
00598                     ret = RunCommand(cmd,
00599                                      read = True,
00600                                      **dcmd)
00601                     if ret:
00602                         vlist = ret.splitlines()
00603                 else:
00604                     vlist = eval(condText)
00605                 
00606                 if 'variables' not in params:
00607                     params['variables'] = { 'params' : [] }
00608                 varDict = { 'name' : condVar, 'value' : '' }
00609                 params['variables']['params'].append(varDict)
00610                                 
00611                 for var in vlist:
00612                     for action in item.GetItems():
00613                         if not isinstance(action, ModelAction) or \
00614                                 not action.IsEnabled():
00615                             continue
00616                         
00617                         varDict['value'] = var
00618                                                 
00619                         self.RunAction(item = action, params = params,
00620                                        log = log, onDone = onDone)
00621                 params['variables']['params'].remove(varDict)
00622         
00623         if delInterData:
00624             self.DeleteIntermediateData(log)
00625         
00626         # discard values
00627         if params:
00628             for item in params.itervalues():
00629                 for p in item['params']:
00630                     p['value'] = ''
00631         
00632     def DeleteIntermediateData(self, log):
00633         """!Detele intermediate data"""
00634         rast, vect, rast3d, msg = self.GetIntermediateData()
00635         
00636         if rast:
00637             log.RunCmd(['g.remove', 'rast=%s' %','.join(rast)])
00638         if rast3d:
00639             log.RunCmd(['g.remove', 'rast3d=%s' %','.join(rast3d)])
00640         if vect:
00641             log.RunCmd(['g.remove', 'vect=%s' %','.join(vect)])
00642         
00643     def GetIntermediateData(self):
00644         """!Get info about intermediate data"""
00645         rast = list()
00646         rast3d = list()
00647         vect = list()
00648         for data in self.GetData():
00649             if not data.IsIntermediate():
00650                 continue
00651             name = data.GetValue()
00652             prompt = data.GetPrompt()
00653             if prompt == 'raster':
00654                 rast.append(name)
00655             elif prompt == 'vector':
00656                 vect.append(name)
00657             elif prompt == 'rast3d':
00658                 rast3d.append(name)
00659         
00660         msg = ''
00661         if rast:
00662             msg += '\n\n%s: ' % _('Raster maps')
00663             msg += ', '.join(rast)
00664         if rast3d:
00665             msg += '\n\n%s: ' % _('3D raster maps')
00666             msg += ', '.join(rast3d)
00667         if vect:
00668             msg += '\n\n%s: ' % _('Vector maps')
00669             msg += ', '.join(vect)
00670         
00671         return rast, vect, rast3d, msg
00672 
00673     def Update(self):
00674         """!Update model"""
00675         for item in self.items:
00676             item.Update()
00677         
00678     def IsParameterized(self):
00679         """!Return True if model is parameterized"""
00680         if self.Parameterize():
00681             return True
00682         
00683         return False
00684     
00685     def Parameterize(self):
00686         """!Return parameterized options"""
00687         result = dict()
00688         idx = 0
00689         if self.variables:
00690             params = list()
00691             result["variables"] = { 'flags'  : list(),
00692                                     'params' : params,
00693                                     'idx'    : idx }
00694             for name, values in self.variables.iteritems():
00695                 gtype = values.get('type', 'string')
00696                 if gtype in ('raster', 'vector', 'mapset', 'file'):
00697                     gisprompt = True
00698                     prompt = gtype
00699                     if gtype == 'raster':
00700                         element = 'cell'
00701                     else:
00702                         element = gtype
00703                     ptype = 'string'
00704                 else:
00705                     gisprompt = False
00706                     prompt = None
00707                     element = None
00708                     ptype = gtype
00709                 params.append({ 'gisprompt' : gisprompt,
00710                                 'multiple'  : False,
00711                                 'description' : values.get('description', ''),
00712                                 'guidependency' : '',
00713                                 'default' : '',
00714                                 'age' : None,
00715                                 'required' : True,
00716                                 'value' : values.get('value', ''),
00717                                 'label' : '',
00718                                 'guisection' : '',
00719                                 'key_desc' : '',
00720                                 'values' : list(),
00721                                 'parameterized' : False,
00722                                 'values_desc' : list(),
00723                                 'prompt' : prompt,
00724                                 'element' : element,
00725                                 'type' : ptype,
00726                                 'name' : name })
00727             
00728             idx += 1
00729         
00730         for action in self.GetItems(objType = ModelAction):
00731             if not action.IsEnabled():
00732                 continue
00733             name   = action.GetName()
00734             params = action.GetParams()
00735             for f in params['flags']:
00736                 if f.get('parameterized', False):
00737                     if name not in result:
00738                         result[name] = { 'flags' : list(),
00739                                          'params': list(),
00740                                          'idx'   : idx }
00741                     result[name]['flags'].append(f)
00742             for p in params['params']:
00743                 if p.get('parameterized', False):
00744                     if name not in result:
00745                         result[name] = { 'flags' : list(),
00746                                          'params': list(),
00747                                          'idx'   : idx }
00748                     result[name]['params'].append(p)
00749             if name in result:
00750                 idx += 1
00751         
00752         self.variablesParams = result # record parameters
00753         
00754         return result
00755 
00756 class ModelObject(object):
00757     def __init__(self, id = -1):
00758         self.id   = id
00759         self.rels = list() # list of ModelRelations
00760         
00761         self.isEnabled = True
00762         self.inBlock   = list() # list of related loops/conditions
00763         
00764     def __del__(self):
00765         pass
00766     
00767     def GetId(self):
00768         """!Get id"""
00769         return self.id
00770     
00771     def AddRelation(self, rel):
00772         """!Record new relation
00773         """
00774         self.rels.append(rel)
00775 
00776     def GetRelations(self, fdir = None):
00777         """!Get list of relations
00778         
00779         @param fdir True for 'from'
00780         """
00781         if fdir is None:
00782             return self.rels
00783         
00784         result = list()
00785         for rel in self.rels:
00786             if fdir == 'from':
00787                 if rel.GetFrom() == self:
00788                     result.append(rel)
00789             else:
00790                 if rel.GetTo() == self:
00791                     result.append(rel)
00792         
00793         return result
00794     
00795     def IsEnabled(self):
00796         """!Get True if action is enabled, otherwise False"""
00797         return self.isEnabled
00798     
00799     def Enable(self, enabled = True):
00800         """!Enable/disable action"""
00801         self.isEnabled = enabled
00802         self.Update()
00803 
00804     def Update(self):
00805         pass
00806 
00807     def SetBlock(self, item):
00808         """!Add object to the block (loop/condition)
00809 
00810         @param item reference to ModelLoop or ModelCondition which
00811         defines loops/condition
00812         """
00813         if item not in self.inBlock:
00814             self.inBlock.append(item)
00815         
00816     def UnSetBlock(self, item):
00817         """!Remove object from the block (loop/consition)
00818 
00819         @param item reference to ModelLoop or ModelCondition which
00820         defines loops/codition
00821         """
00822         if item in self.inBlock:
00823             self.inBlock.remove(item)
00824         
00825     def GetBlock(self):
00826         """!Get list of related ModelObject(s) which defines block
00827         (loop/condition)
00828 
00829         @return list of ModelObjects
00830         """
00831         return self.inBlock
00832     
00833     def GetBlockId(self):
00834         """!Get list of related ids which defines block
00835 
00836         @return list of ids
00837         """
00838         ret = list()
00839         for mo in self.inBlock:
00840             ret.append(mo.GetId())
00841         
00842         return ret
00843     
00844 class ModelAction(ModelObject, ogl.RectangleShape):
00845     """!Action class (GRASS module)"""
00846     def __init__(self, parent, x, y, id = -1, cmd = None, task = None, width = None, height = None):
00847         ModelObject.__init__(self, id)
00848         
00849         self.parent  = parent
00850         self.task    = task
00851         
00852         if not width:
00853             width = UserSettings.Get(group='modeler', key='action', subkey=('size', 'width'))
00854         if not height:
00855             height = UserSettings.Get(group='modeler', key='action', subkey=('size', 'height'))
00856         
00857         if cmd and cmd[0] in ('r.mapcalc', 'v.type'):
00858             cmd[0] += '_wrapper'
00859         
00860         if cmd:
00861             self.task = GUI(show = None).ParseCommand(cmd = cmd)
00862         else:
00863             if task:
00864                 self.task = task
00865             else:
00866                 self.task = None
00867         
00868         self.propWin = None
00869         
00870         self.data = list()   # list of connected data items
00871         
00872         self.isValid = False
00873         self.isParameterized = False
00874         
00875         if self.parent.GetCanvas():
00876             ogl.RectangleShape.__init__(self, width, height)
00877             
00878             self.SetCanvas(self.parent)
00879             self.SetX(x)
00880             self.SetY(y)
00881             self.SetPen(wx.BLACK_PEN)
00882             self._setPen()
00883             self._setBrush()
00884             self.SetId(id)
00885         
00886         if self.task:
00887             self.SetValid(self.task.get_options())
00888         
00889     def _setBrush(self, running = False):
00890         """!Set brush"""
00891         if running:
00892             color = UserSettings.Get(group='modeler', key='action',
00893                                      subkey=('color', 'running'))
00894         elif not self.isEnabled:
00895             color = UserSettings.Get(group='modeler', key='disabled',
00896                                      subkey='color')
00897         elif self.isValid:
00898             color = UserSettings.Get(group='modeler', key='action',
00899                                      subkey=('color', 'valid'))
00900         else:
00901             color = UserSettings.Get(group='modeler', key='action',
00902                                      subkey=('color', 'invalid'))
00903         
00904         wxColor = wx.Color(color[0], color[1], color[2])
00905         self.SetBrush(wx.Brush(wxColor))
00906         
00907     def _setPen(self):
00908         """!Set pen"""
00909         if self.isParameterized:
00910             width = int(UserSettings.Get(group='modeler', key='action',
00911                                          subkey=('width', 'parameterized')))
00912         else:
00913             width = int(UserSettings.Get(group='modeler', key='action',
00914                                          subkey=('width', 'default')))
00915         pen = self.GetPen()
00916         pen.SetWidth(width)
00917         self.SetPen(pen)
00918 
00919     def SetId(self, id):
00920         """!Set id"""
00921         self.id = id
00922         cmd = self.task.get_cmd(ignoreErrors = True)
00923         if cmd and len(cmd) > 0:
00924             self.ClearText()
00925             self.AddText('(%d) %s' % (self.id, cmd[0]))
00926         else:
00927             self.AddText('(%d) <<%s>>' % (self.id, _("unknown")))
00928         
00929     def SetProperties(self, params, propwin):
00930         """!Record properties dialog"""
00931         self.task.params = params['params']
00932         self.task.flags  = params['flags']
00933         self.propWin = propwin
00934 
00935     def GetPropDialog(self):
00936         """!Get properties dialog"""
00937         return self.propWin
00938 
00939     def GetLog(self, string = True, substitute = None):
00940         """!Get logging info
00941 
00942         @param string True to get cmd as a string otherwise a list
00943         @param substitute dictionary of parameter to substitute or None
00944         """
00945         cmd = self.task.get_cmd(ignoreErrors = True, ignoreRequired = True,
00946                                 ignoreDefault = False)
00947         
00948         # substitute variables
00949         if substitute:
00950             variables = []
00951             if 'variables' in substitute:
00952                 for p in substitute['variables']['params']:
00953                     variables.append(p.get('name', ''))
00954             else:
00955                 variables = self.parent.GetVariables()
00956             for variable in variables:
00957                 pattern= re.compile('%' + variable)
00958                 value = ''
00959                 if substitute and 'variables' in substitute:
00960                     for p in substitute['variables']['params']:
00961                         if variable == p.get('name', ''):
00962                             if p.get('type', 'string') == 'string':
00963                                 value = p.get('value', '')
00964                             else:
00965                                 value = str(p.get('value', ''))
00966                             break
00967                     
00968                 if not value:
00969                     value = variables[variable].get('value', '')
00970                 
00971                 if not value:
00972                     continue
00973                 
00974                 for idx in range(len(cmd)):
00975                     if pattern.search(cmd[idx]):
00976                         cmd[idx] = pattern.sub(value, cmd[idx])
00977                         break
00978                     idx += 1
00979         
00980         if string:
00981             if cmd is None:
00982                 return ''
00983             else:
00984                 return ' '.join(cmd)
00985         
00986         return cmd
00987     
00988     def GetName(self):
00989         """!Get name"""
00990         cmd = self.task.get_cmd(ignoreErrors = True)
00991         if cmd and len(cmd) > 0:
00992             return cmd[0]
00993         
00994         return _('unknown')
00995 
00996     def GetParams(self, dcopy = False):
00997         """!Get dictionary of parameters"""
00998         if dcopy:
00999             return copy.deepcopy(self.task.get_options())
01000         
01001         return self.task.get_options()
01002 
01003     def GetTask(self):
01004         """!Get grassTask instance"""
01005         return self.task
01006     
01007     def SetParams(self, params):
01008         """!Set dictionary of parameters"""
01009         self.task.params = params['params']
01010         self.task.flags  = params['flags']
01011         
01012     def MergeParams(self, params):
01013         """!Merge dictionary of parameters"""
01014         if 'flags' in params:
01015             for f in params['flags']:
01016                 self.task.set_flag(f['name'],
01017                                    f.get('value', False))
01018         if 'params' in params:
01019             for p in params['params']:
01020                 self.task.set_param(p['name'],
01021                                     p.get('value', ''))
01022         
01023     def SetValid(self, options):
01024         """!Set validity for action
01025         
01026         @param options dictionary with flags and params (gtask)
01027         """
01028         self.isValid = True
01029         self.isParameterized = False
01030         
01031         for f in options['flags']:
01032             if f.get('parameterized', False):
01033                 self.IsParameterized = True
01034                 break
01035         
01036         for p in options['params']:
01037             if self.isValid and p.get('required', False) and \
01038                     p.get('value', '') == '' and \
01039                     p.get('default', '') == '':
01040                 self.isValid = False
01041             if not self.isParameterized and p.get('parameterized', False):
01042                 self.isParameterized = True
01043         
01044         if self.parent.GetCanvas():
01045             self._setBrush()
01046             self._setPen()
01047         
01048     def IsValid(self):
01049         """!Check validity (all required parameters set)"""
01050         return self.isValid
01051     
01052     def IsParameterized(self):
01053         """!Check if action is parameterized"""
01054         return self.isParameterized
01055     
01056     def FindData(self, name):
01057         """!Find data item by name"""
01058         for rel in self.GetRelations():
01059             data = rel.GetData()
01060             if name == rel.GetName() and name in data.GetName():
01061                 return data
01062         
01063         return None
01064 
01065     def Update(self, running = False):
01066         """!Update action"""
01067         if running:
01068             self._setBrush(running = True)
01069         else:
01070             self._setBrush()
01071         self._setPen()
01072 
01073     def OnDraw(self, dc):
01074         """!Draw action in canvas"""
01075         self._setBrush()
01076         self._setPen()
01077         ogl.RectangleShape.Recentre(self, dc) # re-center text
01078         ogl.RectangleShape.OnDraw(self, dc)
01079 
01080 class ModelData(ModelObject, ogl.EllipseShape):
01081     def __init__(self, parent, x, y, value = '', prompt = '', width = None, height = None):
01082         """Data item class
01083         
01084         @param parent window parent
01085         @param x, y   position of the shape
01086         @param fname, tname list of parameter names from / to
01087         @param value  value
01088         @param prompt type of GIS element
01089         @param width,height dimension of the shape
01090         """
01091         ModelObject.__init__(self)
01092         
01093         self.parent  = parent
01094         self.value   = value
01095         self.prompt  = prompt
01096         self.intermediate = False
01097         self.propWin = None
01098         if not width:
01099             width = UserSettings.Get(group='modeler', key='data', subkey=('size', 'width'))
01100         if not height:
01101             height = UserSettings.Get(group='modeler', key='data', subkey=('size', 'height'))
01102         
01103         if self.parent.GetCanvas():
01104             ogl.EllipseShape.__init__(self, width, height)
01105             
01106             self.SetCanvas(self.parent)
01107             self.SetX(x)
01108             self.SetY(y)
01109             self.SetPen(wx.BLACK_PEN)
01110             self._setBrush()
01111             
01112             self._setText()
01113             
01114     def IsIntermediate(self):
01115         """!Checks if data item is intermediate"""
01116         return self.intermediate
01117     
01118     def SetIntermediate(self, im):
01119         """!Set intermediate flag"""
01120         self.intermediate = im
01121   
01122     def OnDraw(self, dc):
01123         pen = self.GetPen()
01124         pen.SetWidth(1)
01125         if self.intermediate:
01126             pen.SetStyle(wx.SHORT_DASH)
01127         else:
01128             pen.SetStyle(wx.SOLID)
01129         self.SetPen(pen)
01130         
01131         ogl.EllipseShape.OnDraw(self, dc)
01132         
01133     def GetLog(self, string = True):
01134         """!Get logging info"""
01135         name = list()
01136         for rel in self.GetRelations():
01137             name.append(rel.GetName())
01138         if name:
01139             return '/'.join(name) + '=' + self.value + ' (' + self.prompt + ')'
01140         else:
01141             return self.value + ' (' + self.prompt + ')'
01142 
01143     def GetName(self):
01144         """!Get list of names"""
01145         name = list()
01146         for rel in self.GetRelations():
01147             name.append(rel.GetName())
01148         
01149         return name
01150     
01151     def GetPrompt(self):
01152         """!Get prompt"""
01153         return self.prompt
01154 
01155     def SetPrompt(self, prompt):
01156         """!Set prompt
01157         
01158         @param prompt
01159         """
01160         self.prompt = prompt
01161         
01162     def GetValue(self):
01163         """!Get value"""
01164         return self.value
01165 
01166     def SetValue(self, value):
01167         """!Set value
01168 
01169         @param value
01170         """
01171         self.value = value
01172         self._setText()
01173         for direction in ('from', 'to'):
01174             for rel in self.GetRelations(direction):
01175                 if direction == 'from':
01176                     action = rel.GetTo()
01177                 else:
01178                     action = rel.GetFrom()
01179                 
01180                 task = GUI(show = None).ParseCommand(cmd = action.GetLog(string = False))
01181                 task.set_param(rel.GetName(), self.value)
01182                 action.SetParams(params = task.get_options())
01183         
01184     def GetPropDialog(self):
01185         """!Get properties dialog"""
01186         return self.propWin
01187 
01188     def SetPropDialog(self, win):
01189         """!Get properties dialog"""
01190         self.propWin = win
01191 
01192     def _setBrush(self):
01193         """!Set brush"""
01194         if self.prompt == 'raster':
01195             color = UserSettings.Get(group = 'modeler', key = 'data',
01196                                      subkey = ('color', 'raster'))
01197         elif self.prompt == 'raster3d':
01198             color = UserSettings.Get(group = 'modeler', key = 'data',
01199                                      subkey = ('color', 'raster3d'))
01200         elif self.prompt == 'vector':
01201             color = UserSettings.Get(group = 'modeler', key = 'data',
01202                                      subkey = ('color', 'vector'))
01203         else:
01204             color = UserSettings.Get(group = 'modeler', key = 'action',
01205                                      subkey = ('color', 'invalid'))
01206         wxColor = wx.Color(color[0], color[1], color[2])
01207         self.SetBrush(wx.Brush(wxColor))
01208         
01209     def _setPen(self):
01210         """!Set pen"""
01211         isParameterized = False
01212         for rel in self.GetRelations('from'):
01213             if rel.GetTo().IsParameterized():
01214                 isParameterized = True
01215                 break
01216         if not isParameterized:
01217             for rel in self.GetRelations('to'):
01218                 if rel.GetFrom().IsParameterized():
01219                     isParameterized = True
01220                     break
01221 
01222         if isParameterized:
01223             width = int(UserSettings.Get(group = 'modeler', key = 'action',
01224                                          subkey = ('width', 'parameterized')))
01225         else:
01226             width = int(UserSettings.Get(group = 'modeler', key = 'action',
01227                                          subkey = ('width', 'default')))
01228         pen = self.GetPen()
01229         pen.SetWidth(width)
01230         self.SetPen(pen)
01231         
01232     def _setText(self):
01233         """!Update text"""
01234         self.ClearText()
01235         name = []
01236         for rel in self.GetRelations():
01237             name.append(rel.GetName())
01238         self.AddText('/'.join(name))
01239         if self.value:
01240             self.AddText(self.value)
01241         else:
01242             self.AddText(_('<not defined>'))
01243         
01244     def Update(self):
01245         """!Update action"""
01246         self._setBrush()
01247         self._setPen()
01248         self._setText()
01249 
01250 class ModelRelation(ogl.LineShape):
01251     """!Data - action relation"""
01252     def __init__(self, parent, fromShape, toShape, param = ''):
01253         self.fromShape = fromShape
01254         self.toShape   = toShape
01255         self.param     = param
01256         self.parent    = parent
01257         
01258         self._points    = None
01259         
01260         if self.parent.GetCanvas():        
01261             ogl.LineShape.__init__(self)
01262     
01263     def __del__(self):
01264         if self in self.fromShape.rels:
01265             self.fromShape.rels.remove(self)
01266         if self in self.toShape.rels:
01267             self.toShape.rels.remove(self)
01268         
01269     def GetFrom(self):
01270         """!Get id of 'from' shape"""
01271         return self.fromShape
01272     
01273     def GetTo(self):
01274         """!Get id of 'to' shape"""
01275         return self.toShape
01276     
01277     def GetData(self):
01278         """!Get related ModelData instance
01279 
01280         @return ModelData instance
01281         @return None if not found
01282         """
01283         if isinstance(self.fromShape, ModelData):
01284             return self.fromShape
01285         elif isinstance(self.toShape, ModelData):
01286             return self.toShape
01287         
01288         return None
01289     
01290     def GetName(self):
01291         """!Get parameter name"""
01292         return self.param
01293     
01294     def ResetShapes(self):
01295         """!Reset related objects"""
01296         self.fromShape.ResetControlPoints()
01297         self.toShape.ResetControlPoints()
01298         self.ResetControlPoints()
01299         
01300     def SetControlPoints(self, points):
01301         """!Set control points"""
01302         self._points = points
01303         
01304     def GetControlPoints(self):
01305         """!Get list of control points"""
01306         return self._points
01307     
01308     def _setPen(self):
01309         """!Set pen"""
01310         pen = self.GetPen()
01311         pen.SetWidth(1)
01312         pen.SetStyle(wx.SOLID)
01313         self.SetPen(pen)
01314         
01315     def OnDraw(self, dc):
01316         """!Draw relation"""
01317         self._setPen()
01318         ogl.LineShape.OnDraw(self, dc)
01319     
01320     def SetName(self, param):
01321         self.param = param
01322 
01323 class ModelItem(ModelObject):
01324     def __init__(self, parent, x, y, id = -1, width = None, height = None, text = '', items = []):
01325         """!Abstract class for loops and conditions"""
01326         ModelObject.__init__(self, id)
01327         self.parent  = parent
01328         self.text    = text
01329         self.items   = items  # list of items in the loop
01330         
01331     def GetText(self):
01332         """!Get loop text"""
01333         return self.text
01334 
01335     def GetItems(self):
01336         """!Get items (id)"""
01337         return self.items
01338 
01339     def SetId(self, id):
01340         """!Set loop id"""
01341         self.id = id
01342 
01343     def SetText(self, cond):
01344         """!Set loop text (condition)"""
01345         self.text = cond
01346         self.ClearText()
01347         self.AddText('(' + str(self.id) + ') ' + self.text)
01348 
01349     def GetLog(self):
01350         """!Get log info"""
01351         if self.text:
01352             return _("Condition: ") + self.text
01353         else:
01354             return _("Condition: not defined")
01355 
01356     def AddRelation(self, rel):
01357         """!Record relation"""
01358         self.rels.append(rel)
01359         
01360     def Clear(self):
01361         """!Clear object, remove rels"""
01362         self.rels = list()
01363 
01364 class ModelLoop(ModelItem, ogl.RectangleShape):
01365     def __init__(self, parent, x, y, id = -1, width = None, height = None, text = '', items = []):
01366         """!Defines a loop"""
01367         ModelItem.__init__(self, parent, x, y, id, width, height, text, items)
01368         
01369         if not width:
01370             width = UserSettings.Get(group='modeler', key='loop', subkey=('size', 'width'))
01371         if not height:
01372             height = UserSettings.Get(group='modeler', key='loop', subkey=('size', 'height'))
01373         
01374         if self.parent.GetCanvas():
01375             ogl.RectangleShape.__init__(self, width, height)
01376             
01377             self.SetCanvas(self.parent)
01378             self.SetX(x)
01379             self.SetY(y)
01380             self.SetPen(wx.BLACK_PEN)
01381             self.SetCornerRadius(100)
01382             if text:
01383                 self.AddText('(' + str(self.id) + ') ' + text)
01384             else:
01385                 self.AddText('(' + str(self.id) + ')')
01386         
01387         self._setBrush()
01388         
01389     def _setBrush(self):
01390         """!Set brush"""
01391         if not self.isEnabled:
01392             color = UserSettings.Get(group='modeler', key='disabled',
01393                                      subkey='color')
01394         else:
01395             color = UserSettings.Get(group='modeler', key='loop',
01396                                      subkey=('color', 'valid'))
01397         
01398         wxColor = wx.Color(color[0], color[1], color[2])
01399         self.SetBrush(wx.Brush(wxColor))
01400 
01401     def Enable(self, enabled = True):
01402         """!Enable/disable action"""
01403         for item in self.items:
01404             if not isinstance(item, ModelAction):
01405                 continue
01406             item.Enable(enabled)
01407         
01408         ModelObject.Enable(self, enabled)
01409         
01410     def Update(self):
01411         self._setBrush()
01412         
01413     def GetName(self):
01414         """!Get name"""
01415         return _("loop")
01416     
01417     def SetItems(self, items):
01418         """!Set items (id)"""
01419         self.items = items
01420 
01421 class ModelCondition(ModelItem, ogl.PolygonShape):
01422     def __init__(self, parent, x, y, id = -1, width = None, height = None, text = '',
01423                  items = { 'if' : [], 'else' : [] }):
01424         """!Defines a if-else condition"""
01425         ModelItem.__init__(self, parent, x, y, id, width, height, text, items)
01426         
01427         if not width:
01428             self.width = UserSettings.Get(group='modeler', key='if-else', subkey=('size', 'width'))
01429         else:
01430             self.width = width
01431         if not height:
01432             self.height = UserSettings.Get(group='modeler', key='if-else', subkey=('size', 'height'))
01433         else:
01434             self.height = height
01435         
01436         if self.parent.GetCanvas():
01437             ogl.PolygonShape.__init__(self)
01438             
01439             points = [(0, - self.height / 2),
01440                       (self.width / 2, 0),
01441                       (0, self.height / 2),
01442                       (- self.width / 2, 0)]
01443             self.Create(points)
01444             
01445             self.SetCanvas(self.parent)
01446             self.SetX(x)
01447             self.SetY(y)
01448             self.SetPen(wx.BLACK_PEN)
01449             if text:
01450                 self.AddText('(' + str(self.id) + ') ' + text)
01451             else:
01452                 self.AddText('(' + str(self.id) + ')')
01453 
01454     def GetName(self):
01455         """!Get name"""
01456         return _("if-else")
01457 
01458     def GetWidth(self):
01459         """!Get object width"""
01460         return self.width
01461 
01462     def GetHeight(self):
01463         """!Get object height"""
01464         return self.height
01465 
01466     def SetItems(self, items, branch = 'if'):
01467         """!Set items (id)
01468 
01469         @param items list of items
01470         @param branch 'if' / 'else'
01471         """
01472         if branch in ['if', 'else']:
01473             self.items[branch] = items
01474 
01475 class ProcessModelFile:
01476     """!Process GRASS model file (gxm)"""
01477     def __init__(self, tree):
01478         """!A ElementTree handler for the GXM XML file, as defined in
01479         grass-gxm.dtd.
01480         """
01481         self.tree = tree
01482         self.root = self.tree.getroot()
01483         
01484         # list of actions, data
01485         self.properties = dict()
01486         self.variables  = dict() 
01487         self.actions = list()
01488         self.data    = list()
01489         self.loops   = list()
01490         self.conditions = list()
01491         
01492         self._processWindow()
01493         self._processProperties()
01494         self._processVariables()
01495         self._processItems()
01496         self._processData()
01497         
01498     def _filterValue(self, value):
01499         """!Filter value
01500         
01501         @param value
01502         """
01503         value = value.replace('&lt;', '<')
01504         value = value.replace('&gt;', '>')
01505         
01506         return value
01507         
01508     def _getNodeText(self, node, tag, default = ''):
01509         """!Get node text"""
01510         p = node.find(tag)
01511         if p is not None:
01512             if p.text:
01513                 return utils.normalize_whitespace(p.text)
01514             else:
01515                 return ''
01516         
01517         return default
01518     
01519     def _processWindow(self):
01520         """!Process window properties"""
01521         node = self.root.find('window')
01522         if node is None:
01523             self.pos = self.size = None
01524             return
01525         
01526         self.pos, self.size = self._getDim(node)
01527         
01528     def _processProperties(self):
01529         """!Process model properties"""
01530         node = self.root.find('properties')
01531         if node is None:
01532             return
01533         for key in ('name', 'description', 'author'):
01534             self._processProperty(node, key)
01535         
01536         for f in node.findall('flag'):
01537             name = f.get('name', '')
01538             if name == 'overwrite':
01539                 self.properties['overwrite'] = True
01540         
01541     def _processProperty(self, pnode, name):
01542         """!Process given property"""
01543         node = pnode.find(name)
01544         if node is not None:
01545             self.properties[name] = node.text
01546         else:
01547             self.properties[name] = ''
01548 
01549     def _processVariables(self):
01550         """!Process model variables"""
01551         vnode = self.root.find('variables')
01552         if vnode is None:
01553             return
01554         for node in vnode.findall('variable'):
01555             name = node.get('name', '')
01556             if not name:
01557                 continue # should not happen
01558             self.variables[name] = { 'type' : node.get('type', 'string') }
01559             for key in ('description', 'value'):
01560                 self._processVariable(node, name, key)
01561         
01562     def _processVariable(self, pnode, name, key):
01563         """!Process given variable"""
01564         node = pnode.find(key)
01565         if node is not None:
01566             if node.text:
01567                 self.variables[name][key] = node.text
01568 
01569     def _processItems(self):
01570         """!Process model items (actions, loops, conditions)"""
01571         self._processActions()
01572         self._processLoops()
01573         self._processConditions()
01574         
01575     def _processActions(self):
01576         """!Process model file"""
01577         for action in self.root.findall('action'):
01578             pos, size = self._getDim(action)
01579             disabled  = False
01580             
01581             task = action.find('task')
01582             if task is not None:
01583                 if task.find('disabled') is not None:
01584                     disabled = True
01585                 task = self._processTask(task)
01586             else:
01587                 task = None
01588             
01589             aId = int(action.get('id', -1))
01590             
01591             self.actions.append({ 'pos'      : pos,
01592                                   'size'     : size,
01593                                   'task'     : task,
01594                                   'id'       : aId,
01595                                   'disabled' : disabled })
01596             
01597     def _getDim(self, node):
01598         """!Get position and size of shape"""
01599         pos = size = None
01600         posAttr = node.get('pos', None)
01601         if posAttr:
01602             posVal = map(int, posAttr.split(','))
01603             try:
01604                 pos = (posVal[0], posVal[1])
01605             except:
01606                 pos = None
01607         
01608         sizeAttr = node.get('size', None)
01609         if sizeAttr:
01610             sizeVal = map(int, sizeAttr.split(','))
01611             try:
01612                 size = (sizeVal[0], sizeVal[1])
01613             except:
01614                 size = None
01615         
01616         return pos, size        
01617     
01618     def _processData(self):
01619         """!Process model file"""
01620         for data in self.root.findall('data'):
01621             pos, size = self._getDim(data)
01622             param = data.find('data-parameter')
01623             prompt = value = None
01624             if param is not None:
01625                 prompt = param.get('prompt', None)
01626                 value = self._filterValue(self._getNodeText(param, 'value'))
01627             
01628             if data.find('intermediate') is None:
01629                 intermediate = False
01630             else:
01631                 intermediate = True
01632             
01633             rels = list()
01634             for rel in data.findall('relation'):
01635                 defrel = { 'id'  : int(rel.get('id', -1)),
01636                            'dir' : rel.get('dir', 'to'),
01637                            'name' : rel.get('name', '') }
01638                 points = list()
01639                 for point in rel.findall('point'):
01640                     x = self._filterValue(self._getNodeText(point, 'x'))
01641                     y = self._filterValue(self._getNodeText(point, 'y'))
01642                     points.append((float(x), float(y)))
01643                 defrel['points'] = points
01644                 rels.append(defrel)
01645             
01646             self.data.append({ 'pos' : pos,
01647                                'size': size,
01648                                'prompt' : prompt,
01649                                'value' : value,
01650                                'intermediate' : intermediate,
01651                                'rels' : rels })
01652         
01653     def _processTask(self, node):
01654         """!Process task
01655 
01656         @return grassTask instance
01657         @return None on error
01658         """
01659         cmd = list()
01660         parameterized = list()
01661         
01662         name = node.get('name', None)
01663         if not name:
01664             return None
01665         
01666         cmd.append(name)
01667         
01668         # flags
01669         for f in node.findall('flag'):
01670             flag = f.get('name', '')
01671             if f.get('parameterized', '0') == '1':
01672                 parameterized.append(('flag', flag))
01673                 if f.get('value', '1') == '0':
01674                     continue
01675             if len(flag) > 1:
01676                 cmd.append('--' + flag)
01677             else:
01678                 cmd.append('-' + flag)
01679         # parameters
01680         for p in node.findall('parameter'):
01681             name = p.get('name', '')
01682             if p.find('parameterized') is not None:
01683                 parameterized.append(('param', name))
01684             cmd.append('%s=%s' % (name,
01685                                   self._filterValue(self._getNodeText(p, 'value'))))
01686         
01687         task, err = GUI(show = None, checkError = True).ParseCommand(cmd = cmd)
01688         if err:
01689             GWarning(os.linesep.join(err))
01690         
01691         for opt, name in parameterized:
01692             if opt == 'flag':
01693                 task.set_flag(name, True, element = 'parameterized')
01694             else:
01695                 task.set_param(name, True, element = 'parameterized')
01696         
01697         return task
01698 
01699     def _processLoops(self):
01700         """!Process model loops"""
01701         for node in self.root.findall('loop'):
01702             pos, size = self._getDim(node)
01703             text = self._filterValue(self._getNodeText(node, 'condition')).strip()
01704             aid = list()
01705             for anode in node.findall('item'):
01706                 try:
01707                     aid.append(int(anode.text))
01708                 except ValueError:
01709                     pass
01710             
01711             self.loops.append({ 'pos'     : pos,
01712                                 'size'    : size,
01713                                 'text'    : text,
01714                                 'id'      : int(node.get('id', -1)),
01715                                 'items'   : aid })
01716         
01717     def _processConditions(self):
01718         """!Process model conditions"""
01719         for node in self.root.findall('if-else'):
01720             pos, size = self._getDim(node)
01721             text = self._filterValue(self._getNodeText(node, 'condition')).strip()
01722             aid = { 'if'   : list(),
01723                     'else' : list() }
01724             for b in aid.keys():
01725                 bnode = node.find(b)
01726                 if bnode is None:
01727                     continue
01728                 for anode in bnode.findall('item'):
01729                     try:
01730                         aid[b].append(int(anode.text))
01731                     except ValueError:
01732                         pass
01733             
01734             self.conditions.append({ 'pos'     : pos,
01735                                      'size'    : size,
01736                                      'text'    : text,
01737                                      'id'      : int(node.get('id', -1)),
01738                                      'items'   : aid })
01739         
01740 class WriteModelFile:
01741     """!Generic class for writing model file"""
01742     def __init__(self, fd, model):
01743         self.fd         = fd
01744         self.model      = model
01745         self.properties = model.GetProperties()
01746         self.variables  = model.GetVariables()
01747         self.items      = model.GetItems()
01748         
01749         self.indent = 0
01750         
01751         self._header()
01752         
01753         self._window()
01754         self._properties()
01755         self._variables()
01756         self._items()
01757         
01758         dataList = list()
01759         for action in model.GetItems(objType = ModelAction):
01760             for rel in action.GetRelations():
01761                 dataItem = rel.GetData()
01762                 if dataItem not in dataList:
01763                     dataList.append(dataItem)
01764         self._data(dataList)
01765         
01766         self._footer()
01767 
01768     def _filterValue(self, value):
01769         """!Make value XML-valid"""
01770         value = value.replace('<', '&lt;')
01771         value = value.replace('>', '&gt;')
01772         
01773         return value
01774         
01775     def _header(self):
01776         """!Write header"""
01777         self.fd.write('<?xml version="1.0" encoding="UTF-8"?>\n')
01778         self.fd.write('<!DOCTYPE gxm SYSTEM "grass-gxm.dtd">\n')
01779         self.fd.write('%s<gxm>\n' % (' ' * self.indent))
01780         self.indent += 4
01781                 
01782     def _footer(self):
01783         """!Write footer"""
01784         self.indent -= 4
01785         self.fd.write('%s</gxm>\n' % (' ' * self.indent))
01786 
01787     def _window(self):
01788         """!Write window properties"""
01789         canvas = self.model.GetCanvas()
01790         if canvas is None:
01791             return
01792         win  = canvas.parent
01793         pos  = win.GetPosition()
01794         size = win.GetSize()
01795         self.fd.write('%s<window pos="%d,%d" size="%d,%d" />\n' % \
01796                           (' ' * self.indent, pos[0], pos[1], size[0], size[1]))
01797         
01798     def _properties(self):
01799         """!Write model properties"""
01800         self.fd.write('%s<properties>\n' % (' ' * self.indent))
01801         self.indent += 4
01802         if self.properties['name']:
01803             self.fd.write('%s<name>%s</name>\n' % (' ' * self.indent, self.properties['name']))
01804         if self.properties['description']:
01805             self.fd.write('%s<description>%s</description>\n' % (' ' * self.indent,
01806                                                                  utils.EncodeString(self.properties['description'])))
01807         if self.properties['author']:
01808             self.fd.write('%s<author>%s</author>\n' % (' ' * self.indent,
01809                                                        utils.EncodeString(self.properties['author'])))
01810         
01811         if 'overwrite' in self.properties and \
01812                 self.properties['overwrite']:
01813             self.fd.write('%s<flag name="overwrite" />\n' % (' ' * self.indent))
01814         self.indent -= 4
01815         self.fd.write('%s</properties>\n' % (' ' * self.indent))
01816 
01817     def _variables(self):
01818         """!Write model variables"""
01819         if not self.variables:
01820             return
01821         self.fd.write('%s<variables>\n' % (' ' * self.indent))
01822         self.indent += 4
01823         for name, values in self.variables.iteritems():
01824             self.fd.write('%s<variable name="%s" type="%s">\n' % \
01825                               (' ' * self.indent, name, values['type']))
01826             self.indent += 4
01827             if 'value' in values:
01828                 self.fd.write('%s<value>%s</value>\n' % \
01829                                   (' ' * self.indent, values['value']))
01830             if 'description' in values:
01831                 self.fd.write('%s<description>%s</description>\n' % \
01832                                   (' ' * self.indent, values['description']))
01833             self.indent -= 4
01834             self.fd.write('%s</variable>\n' % (' ' * self.indent))
01835         self.indent -= 4
01836         self.fd.write('%s</variables>\n' % (' ' * self.indent))
01837         
01838     def _items(self):
01839         """!Write actions/loops/conditions"""
01840         for item in self.items:
01841             if isinstance(item, ModelAction):
01842                 self._action(item)
01843             elif isinstance(item, ModelLoop):
01844                 self._loop(item)
01845             elif isinstance(item, ModelCondition):
01846                 self._condition(item)
01847         
01848     def _action(self, action):
01849         """!Write actions"""
01850         self.fd.write('%s<action id="%d" name="%s" pos="%d,%d" size="%d,%d">\n' % \
01851                           (' ' * self.indent, action.GetId(), action.GetName(), action.GetX(), action.GetY(),
01852                            action.GetWidth(), action.GetHeight()))
01853         self.indent += 4
01854         self.fd.write('%s<task name="%s">\n' % (' ' * self.indent, action.GetLog(string = False)[0]))
01855         self.indent += 4
01856         if not action.IsEnabled():
01857             self.fd.write('%s<disabled />\n' % (' ' * self.indent))
01858         for key, val in action.GetParams().iteritems():
01859             if key == 'flags':
01860                 for f in val:
01861                     if f.get('value', False) or f.get('parameterized', False):
01862                         if f.get('parameterized', False):
01863                             if f.get('value', False) == False:
01864                                 self.fd.write('%s<flag name="%s" value="0" parameterized="1" />\n' %
01865                                               (' ' * self.indent, f.get('name', '')))
01866                             else:
01867                                 self.fd.write('%s<flag name="%s" parameterized="1" />\n' %
01868                                               (' ' * self.indent, f.get('name', '')))
01869                         else:
01870                             self.fd.write('%s<flag name="%s" />\n' %
01871                                           (' ' * self.indent, f.get('name', '')))
01872             else: # parameter
01873                 for p in val:
01874                     if not p.get('value', '') and not p.get('parameterized', False):
01875                         continue
01876                     self.fd.write('%s<parameter name="%s">\n' %
01877                                   (' ' * self.indent, p.get('name', '')))
01878                     self.indent += 4
01879                     if p.get('parameterized', False):
01880                         self.fd.write('%s<parameterized />\n' % (' ' * self.indent))
01881                     self.fd.write('%s<value>%s</value>\n' %
01882                                   (' ' * self.indent, self._filterValue(p.get('value', ''))))
01883                     self.indent -= 4
01884                     self.fd.write('%s</parameter>\n' % (' ' * self.indent))
01885         self.indent -= 4
01886         self.fd.write('%s</task>\n' % (' ' * self.indent))
01887         self.indent -= 4
01888         self.fd.write('%s</action>\n' % (' ' * self.indent))
01889                 
01890     def _data(self, dataList):
01891         """!Write data"""
01892         for data in dataList:
01893             self.fd.write('%s<data pos="%d,%d" size="%d,%d">\n' % \
01894                               (' ' * self.indent, data.GetX(), data.GetY(),
01895                                data.GetWidth(), data.GetHeight()))
01896             self.indent += 4
01897             self.fd.write('%s<data-parameter prompt="%s">\n' % \
01898                               (' ' * self.indent, data.GetPrompt()))
01899             self.indent += 4
01900             self.fd.write('%s<value>%s</value>\n' %
01901                           (' ' * self.indent, self._filterValue(data.GetValue())))
01902             self.indent -= 4
01903             self.fd.write('%s</data-parameter>\n' % (' ' * self.indent))
01904             
01905             if data.IsIntermediate():
01906                 self.fd.write('%s<intermediate />\n' % (' ' * self.indent))
01907 
01908             # relations
01909             for ft in ('from', 'to'):
01910                 for rel in data.GetRelations(ft):
01911                     if ft == 'from':
01912                         aid = rel.GetTo().GetId()
01913                     else:
01914                         aid  = rel.GetFrom().GetId()
01915                     self.fd.write('%s<relation dir="%s" id="%d" name="%s">\n' % \
01916                                       (' ' * self.indent, ft, aid, rel.GetName()))
01917                     self.indent += 4
01918                     for point in rel.GetLineControlPoints()[1:-1]:
01919                         self.fd.write('%s<point>\n' % (' ' * self.indent))
01920                         self.indent += 4
01921                         x, y = point.Get()
01922                         self.fd.write('%s<x>%d</x>\n' % (' ' * self.indent, int(x)))
01923                         self.fd.write('%s<y>%d</y>\n' % (' ' * self.indent, int(y)))
01924                         self.indent -= 4
01925                         self.fd.write('%s</point>\n' % (' ' * self.indent))
01926                     self.indent -= 4
01927                     self.fd.write('%s</relation>\n' % (' ' * self.indent))
01928                 
01929             self.indent -= 4
01930             self.fd.write('%s</data>\n' % (' ' * self.indent))
01931 
01932     def _loop(self, loop):
01933         """!Write loops"""
01934         self.fd.write('%s<loop id="%d" pos="%d,%d" size="%d,%d">\n' % \
01935                           (' ' * self.indent, loop.GetId(), loop.GetX(), loop.GetY(),
01936                            loop.GetWidth(), loop.GetHeight()))
01937         text = loop.GetText()
01938         self.indent += 4
01939         if text:
01940             self.fd.write('%s<condition>%s</condition>\n' %
01941                           (' ' * self.indent, self._filterValue(text)))
01942         for item in loop.GetItems():
01943             self.fd.write('%s<item>%d</item>\n' %
01944                           (' ' * self.indent, item.GetId()))
01945         self.indent -= 4
01946         self.fd.write('%s</loop>\n' % (' ' * self.indent))
01947 
01948     def _condition(self, condition):
01949         """!Write conditions"""
01950         bbox = condition.GetBoundingBoxMin()
01951         self.fd.write('%s<if-else id="%d" pos="%d,%d" size="%d,%d">\n' % \
01952                           (' ' * self.indent, condition.GetId(), condition.GetX(), condition.GetY(),
01953                            bbox[0], bbox[1]))
01954         text = condition.GetText()
01955         self.indent += 4
01956         if text:
01957             self.fd.write('%s<condition>%s</condition>\n' %
01958                           (' ' * self.indent, self._filterValue(text)))
01959         items = condition.GetItems()
01960         for b in items.keys():
01961             if len(items[b]) < 1:
01962                 continue
01963             self.fd.write('%s<%s>\n' % (' ' * self.indent, b))
01964             self.indent += 4
01965             for item in items[b]:
01966                 self.fd.write('%s<item>%d</item>\n' %
01967                               (' ' * self.indent, item.GetId()))
01968             self.indent -= 4
01969             self.fd.write('%s</%s>\n' % (' ' * self.indent, b))
01970         
01971         self.indent -= 4
01972         self.fd.write('%s</if-else>\n' % (' ' * self.indent))
01973 
01974 class WritePythonFile:
01975     def __init__(self, fd, model):
01976         """!Class for exporting model to Python script
01977 
01978         @param fd file desciptor
01979         """
01980         self.fd     = fd
01981         self.model  = model
01982         self.indent = 4
01983 
01984         self._writePython()
01985         
01986     def _writePython(self):
01987         """!Write model to file"""
01988         properties = self.model.GetProperties()
01989         
01990         self.fd.write(
01991 r"""#!/usr/bin/env python
01992 #
01993 ############################################################################
01994 #
01995 # MODULE:       %s
01996 #
01997 # AUTHOR(S):    %s
01998 #               
01999 # PURPOSE:      %s
02000 #
02001 # DATE:         %s
02002 #
02003 #############################################################################
02004 """ % (properties['name'],
02005        properties['author'],
02006        properties['description'],
02007        time.asctime()))
02008         
02009         self.fd.write(
02010 r"""
02011 import sys
02012 import os
02013 import atexit
02014 
02015 import grass.script as grass
02016 """)
02017         
02018         # cleanup()
02019         rast, vect, rast3d, msg = self.model.GetIntermediateData()
02020         self.fd.write(
02021 r"""
02022 def cleanup():
02023 """)
02024         if rast:
02025             self.fd.write(
02026 r"""    grass.run_command('g.remove',
02027                       rast=%s)
02028 """ % ','.join(map(lambda x: "'" + x + "'", rast)))
02029         if vect:
02030             self.fd.write(
02031 r"""    grass.run_command('g.remove',
02032                       vect = %s)
02033 """ % ','.join(map(lambda x: "'" + x + "'", vect)))
02034         if rast3d:
02035             self.fd.write(
02036 r"""    grass.run_command('g.remove',
02037                       rast3d = %s)
02038 """ % ','.join(map(lambda x: "'" + x + "'", rast3d)))
02039         if not rast and not vect and not rast3d:
02040             self.fd.write('    pass\n')
02041         
02042         self.fd.write("\ndef main():\n")
02043         for item in self.model.GetItems():
02044             self._writePythonItem(item)
02045         
02046         self.fd.write("\n    return 0\n")
02047         
02048         self.fd.write(
02049 r"""
02050 if __name__ == "__main__":
02051     options, flags = grass.parser()
02052     atexit.register(cleanup)
02053     sys.exit(main())
02054 """)
02055         
02056     def _writePythonItem(self, item, ignoreBlock = True, variables = []):
02057         """!Write model object to Python file"""
02058         if isinstance(item, ModelAction):
02059             if ignoreBlock and item.GetBlockId(): # ignore items in loops of conditions
02060                 return
02061             self._writePythonAction(item, variables = variables)
02062         elif isinstance(item, ModelLoop) or isinstance(item, ModelCondition):
02063             # substitute condition
02064             variables = self.model.GetVariables()
02065             cond = item.GetText()
02066             for variable in variables:
02067                 pattern = re.compile('%' + variable)
02068                 if pattern.search(cond):
02069                     value = variables[variable].get('value', '')
02070                     if variables[variable].get('type', 'string') == 'string':
02071                         value = '"' + value + '"'
02072                     cond = pattern.sub(value, cond)
02073             if isinstance(item, ModelLoop):
02074                 condVar, condText = map(lambda x: x.strip(), re.split('\s*in\s*', cond))
02075                 cond = "%sfor %s in " % (' ' * self.indent, condVar)
02076                 if condText[0] == '`' and condText[-1] == '`':
02077                     task = GUI(show = None).ParseCommand(cmd = utils.split(condText[1:-1]))
02078                     cond += "grass.read_command("
02079                     cond += self._getPythonActionCmd(task, len(cond), variables = [condVar]) + ".splitlines()"
02080                 else:
02081                     cond += condText
02082                 self.fd.write('%s:\n' % cond)
02083                 self.indent += 4
02084                 for action in item.GetItems():
02085                     self._writePythonItem(action, ignoreBlock = False, variables = [condVar])
02086                 self.indent -= 4
02087             else: # ModelCondition
02088                 self.fd.write('%sif %s:\n' % (' ' * self.indent, cond))
02089                 self.indent += 4
02090                 condItems = item.GetItems()
02091                 for action in condItems['if']:
02092                     self._writePythonItem(action, ignoreBlock = False)
02093                 if condItems['else']:
02094                     self.indent -= 4
02095                     self.fd.write('%selse:\n' % (' ' * self.indent))
02096                     self.indent += 4
02097                     for action in condItems['else']:
02098                         self._writePythonItem(action, ignoreBlock = False)
02099                 self.indent += 4
02100         
02101     def _writePythonAction(self, item, variables = []):
02102         """!Write model action to Python file"""
02103         task = GUI(show = None).ParseCommand(cmd = item.GetLog(string = False))
02104         strcmd = "%sgrass.run_command(" % (' ' * self.indent)
02105         self.fd.write(strcmd + self._getPythonActionCmd(task, len(strcmd), variables) + '\n')
02106         
02107     def _getPythonActionCmd(self, task, cmdIndent, variables = []):
02108         opts = task.get_options()
02109         
02110         ret = ''
02111         flags = ''
02112         params = list()
02113         
02114         for f in opts['flags']:
02115             if f.get('value', False):
02116                 name = f.get('name', '')
02117                 if len(name) > 1:
02118                     params.append('%s = True' % name)
02119                 else:
02120                     flags += name
02121             
02122         for p in opts['params']:
02123             name = p.get('name', None)
02124             value = p.get('value', None)
02125             if name and value:
02126                 ptype = p.get('type', 'string')
02127                 if value[0] == '%':
02128                     params.append("%s = %s" % (name, value[1:]))
02129                 elif ptype == 'string':
02130                     params.append('%s = "%s"' % (name, value))
02131                 else:
02132                     params.append("%s = %s" % (name, value))
02133         
02134         ret += '"%s"' % task.get_name()
02135         if flags:
02136             ret += ",\n%sflags = '%s'" % (' ' * cmdIndent, flags)
02137         if len(params) > 0:
02138             ret += ",\n"
02139             for opt in params[:-1]:
02140                 ret += "%s%s,\n" % (' ' * cmdIndent, opt)
02141             ret += "%s%s)" % (' ' * cmdIndent, params[-1])
02142         else:
02143             ret += ")"
02144         
02145         return ret
02146 
02147 class ModelParamDialog(wx.Dialog):
02148     def __init__(self, parent, params, id = wx.ID_ANY, title = _("Model parameters"),
02149                  style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
02150         """!Model parameters dialog
02151         """
02152         self.parent = parent
02153         self.params = params
02154         self.tasks  = list() # list of tasks/pages
02155         
02156         wx.Dialog.__init__(self, parent = parent, id = id, title = title, style = style, **kwargs)
02157         
02158         self.notebook = GNotebook(parent = self, 
02159                                   style = globalvar.FNPageDStyle)
02160         
02161         panel = self._createPages()
02162         wx.CallAfter(self.notebook.SetSelection, 0)
02163 
02164         # intermediate data?
02165         self.interData = wx.CheckBox(parent = self, label = _("Delete intermediate data when finish"))
02166         self.interData.SetValue(True)
02167         rast, vect, rast3d, msg = self.parent.GetModel().GetIntermediateData()
02168         if not rast and not vect and not rast3d:
02169             self.interData.Hide()
02170         
02171         self.btnCancel = wx.Button(parent = self, id = wx.ID_CANCEL)
02172         self.btnRun    = wx.Button(parent = self, id = wx.ID_OK,
02173                                    label = _("&Run"))
02174         self.btnRun.SetDefault()
02175         
02176         self._layout()
02177         
02178         size = self.GetBestSize()
02179         self.SetMinSize(size)
02180         self.SetSize((size.width, size.height +
02181                       panel.constrained_size[1] -
02182                       panel.panelMinHeight))
02183                 
02184     def _layout(self):
02185         btnSizer = wx.StdDialogButtonSizer()
02186         btnSizer.AddButton(self.btnCancel)
02187         btnSizer.AddButton(self.btnRun)
02188         btnSizer.Realize()
02189         
02190         mainSizer = wx.BoxSizer(wx.VERTICAL)
02191         mainSizer.Add(item = self.notebook, proportion = 1,
02192                       flag = wx.EXPAND)
02193         if self.interData.IsShown():
02194             mainSizer.Add(item = self.interData, proportion = 0,
02195                           flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
02196 
02197             mainSizer.Add(item = wx.StaticLine(parent = self, id = wx.ID_ANY,
02198                                                style = wx.LI_HORIZONTAL),
02199                           proportion = 0,
02200                           flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border = 5) 
02201         
02202         mainSizer.Add(item = btnSizer, proportion = 0,
02203                       flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
02204         
02205         self.SetSizer(mainSizer)
02206         mainSizer.Fit(self)
02207         
02208     def _createPages(self):
02209         """!Create for each parameterized module its own page"""
02210         nameOrdered = [''] * len(self.params.keys())
02211         for name, params in self.params.iteritems():
02212             nameOrdered[params['idx']] = name
02213         for name in nameOrdered:
02214             params = self.params[name]
02215             panel = self._createPage(name, params)
02216             if name == 'variables':
02217                 name = _('Variables')
02218             self.notebook.AddPage(page = panel, text = name)
02219         
02220         return panel
02221     
02222     def _createPage(self, name, params):
02223         """!Define notebook page"""
02224         if name in globalvar.grassCmd:
02225             task = gtask.grassTask(name)
02226         else:
02227             task = gtask.grassTask()
02228         task.flags  = params['flags']
02229         task.params = params['params']
02230         
02231         panel = CmdPanel(parent = self, id = wx.ID_ANY, task = task)
02232         self.tasks.append(task)
02233         
02234         return panel
02235 
02236     def GetErrors(self):
02237         """!Check for errors, get list of messages"""
02238         errList = list()
02239         for task in self.tasks:
02240             errList += task.get_cmd_error()
02241         
02242         return errList
02243 
02244     def DeleteIntermediateData(self):
02245         """!Check if to detele intermediate data"""
02246         if self.interData.IsShown() and self.interData.IsChecked():
02247             return True
02248         
02249         return False