GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
model.py
Go to the documentation of this file.
1 """!
2 @package gmodeler.model
3 
4 @brief wxGUI Graphical Modeler (base classes & read/write)
5 
6 Classes:
7  - model::Model
8  - model::ModelObject
9  - model::ModelAction
10  - model::ModelData
11  - model::ModelRelation
12  - model::ModelItem
13  - model::ModelLoop
14  - model::ModelCondition
15  - model::ProcessModelFile
16  - model::WriteModelFile
17  - model::WritePythonFile
18  - model::ModelParamDialog
19 
20 (C) 2010-2012 by the GRASS Development Team
21 
22 This program is free software under the GNU General Public License
23 (>=v2). Read the file COPYING that comes with GRASS for details.
24 
25 @author Martin Landa <landa.martin gmail.com>
26 """
27 
28 import os
29 import getpass
30 import copy
31 import re
32 import mimetypes
33 import time
34 try:
35  import xml.etree.ElementTree as etree
36 except ImportError:
37  import elementtree.ElementTree as etree # Python <= 2.4
38 
39 import wx
40 from wx.lib import ogl
41 
42 from core import globalvar
43 from core import utils
44 from core.gcmd import GMessage, GException, GError, RunCommand, EncodeString, GWarning, GetDefaultEncoding
45 from core.settings import UserSettings
46 from gui_core.forms import GUI, CmdPanel
47 from gui_core.widgets import GNotebook
48 
49 from grass.script import core as grass
50 from grass.script import task as gtask
51 
52 class Model(object):
53  """!Class representing the model"""
54  def __init__(self, canvas = None):
55  self.items = list() # list of actions/loops/...
56 
57  # model properties
58  self.properties = { 'name' : _("model"),
59  'description' : _("Script generated by wxGUI Graphical Modeler."),
60  'author' : getpass.getuser() }
61  # model variables
62  self.variables = dict()
63  self.variablesParams = dict()
64 
65  self.canvas = canvas
66 
67  def GetCanvas(self):
68  """!Get canvas or None"""
69  return self.canvas
70 
71  def GetItems(self, objType = None):
72  """!Get list of model items
73 
74  @param objType Object type to filter model objects
75  """
76  if not objType:
77  return self.items
78 
79  result = list()
80  for item in self.items:
81  if isinstance(item, objType):
82  result.append(item)
83 
84  return result
85 
86  def GetItem(self, aId):
87  """!Get item of given id
88 
89  @param aId item id
90 
91  @return Model* instance
92  @return None if no item found
93  """
94  ilist = self.GetItems()
95  for item in ilist:
96  if item.GetId() == aId:
97  return item
98 
99  return None
100 
101  def GetNumItems(self, actionOnly = False):
102  """!Get number of items"""
103  if actionOnly:
104  return len(self.GetItems(objType = ModelAction))
105 
106  return len(self.GetItems())
107 
108  def GetNextId(self):
109  """!Get next id (data ignored)
110 
111  @return next id to be used (default: 1)
112  """
113  if len(self.items) < 1:
114  return 1
115 
116  currId = self.items[-1].GetId()
117  if currId > 0:
118  return currId + 1
119 
120  return 1
121 
122  def GetProperties(self):
123  """!Get model properties"""
124  return self.properties
125 
126  def GetVariables(self, params = False):
127  """!Get model variables"""
128  if params:
129  return self.variablesParams
130 
131  return self.variables
132 
133  def SetVariables(self, data):
134  """!Set model variables"""
135  self.variables = data
136 
137  def Reset(self):
138  """!Reset model"""
139  self.items = list()
140 
141  def RemoveItem(self, item):
142  """!Remove item from model
143 
144  @return list of related items to remove/update
145  """
146  relList = list()
147  upList = list()
148 
149  if not isinstance(item, ModelData):
150  self.items.remove(item)
151 
152  if isinstance(item, ModelAction):
153  for rel in item.GetRelations():
154  relList.append(rel)
155  data = rel.GetData()
156  if len(data.GetRelations()) < 2:
157  relList.append(data)
158  else:
159  upList.append(data)
160 
161  elif isinstance(item, ModelData):
162  for rel in item.GetRelations():
163  relList.append(rel)
164  if rel.GetFrom() == self:
165  relList.append(rel.GetTo())
166  else:
167  relList.append(rel.GetFrom())
168 
169  elif isinstance(item, ModelLoop):
170  for rel in item.GetRelations():
171  relList.append(rel)
172  for action in self.GetItems():
173  action.UnSetBlock(item)
174 
175  return relList, upList
176 
177  def FindAction(self, aId):
178  """!Find action by id"""
179  alist = self.GetItems(objType = ModelAction)
180  for action in alist:
181  if action.GetId() == aId:
182  return action
183 
184  return None
185 
186  def GetData(self):
187  """!Get list of data items"""
188  result = list()
189  dataItems = self.GetItems(objType = ModelData)
190 
191  for action in self.GetItems(objType = ModelAction):
192  for rel in action.GetRelations():
193  dataItem = rel.GetData()
194  if dataItem not in result:
195  result.append(dataItem)
196  if dataItem in dataItems:
197  dataItems.remove(dataItem)
198 
199  # standalone data
200  if dataItems:
201  result += dataItems
202 
203  return result
204 
205  def FindData(self, value, prompt):
206  """!Find data item in the model
207 
208  @param value value
209  @param prompt prompt
210 
211  @return ModelData instance
212  @return None if not found
213  """
214  for data in self.GetData():
215  if data.GetValue() == value and \
216  data.GetPrompt() == prompt:
217  return data
218 
219  return None
220 
221  def LoadModel(self, filename):
222  """!Load model definition stored in GRASS Model XML file (gxm)
223 
224  @todo Validate against DTD
225 
226  Raise exception on error.
227  """
228  dtdFilename = os.path.join(globalvar.ETCWXDIR, "xml", "grass-gxm.dtd")
229 
230  # parse workspace file
231  try:
232  gxmXml = ProcessModelFile(etree.parse(filename))
233  except StandardError, e:
234  raise GException(e)
235 
236  if self.canvas:
237  win = self.canvas.parent
238  if gxmXml.pos:
239  win.SetPosition(gxmXml.pos)
240  if gxmXml.size:
241  win.SetSize(gxmXml.size)
242 
243  # load properties
244  self.properties = gxmXml.properties
245  self.variables = gxmXml.variables
246 
247  # load model.GetActions()
248  for action in gxmXml.actions:
249  actionItem = ModelAction(parent = self,
250  x = action['pos'][0],
251  y = action['pos'][1],
252  width = action['size'][0],
253  height = action['size'][1],
254  task = action['task'],
255  id = action['id'])
256 
257  if action['disabled']:
258  actionItem.Enable(False)
259 
260  self.AddItem(actionItem)
261 
262  actionItem.SetValid(actionItem.GetTask().get_options())
263  actionItem.GetLog() # substitute variables (-> valid/invalid)
264 
265  # load data & relations
266  for data in gxmXml.data:
267  dataItem = ModelData(parent = self,
268  x = data['pos'][0],
269  y = data['pos'][1],
270  width = data['size'][0],
271  height = data['size'][1],
272  prompt = data['prompt'],
273  value = data['value'])
274  dataItem.SetIntermediate(data['intermediate'])
275 
276  for rel in data['rels']:
277  actionItem = self.FindAction(rel['id'])
278  if rel['dir'] == 'from':
279  relation = ModelRelation(parent = self, fromShape = dataItem,
280  toShape = actionItem, param = rel['name'])
281  else:
282  relation = ModelRelation(parent = self, fromShape = actionItem,
283  toShape = dataItem, param = rel['name'])
284  relation.SetControlPoints(rel['points'])
285  actionItem.AddRelation(relation)
286  dataItem.AddRelation(relation)
287 
288  if self.canvas:
289  dataItem.Update()
290 
291  # load loops
292  for loop in gxmXml.loops:
293  loopItem = ModelLoop(parent = self,
294  x = loop['pos'][0],
295  y = loop['pos'][1],
296  width = loop['size'][0],
297  height = loop['size'][1],
298  text = loop['text'],
299  id = loop['id'])
300  self.AddItem(loopItem)
301 
302  # load conditions
303  for condition in gxmXml.conditions:
304  conditionItem = ModelCondition(parent = self,
305  x = condition['pos'][0],
306  y = condition['pos'][1],
307  width = condition['size'][0],
308  height = condition['size'][1],
309  text = condition['text'],
310  id = condition['id'])
311  self.AddItem(conditionItem)
312 
313  # define loops & if/else items
314  for loop in gxmXml.loops:
315  alist = list()
316  for aId in loop['items']:
317  action = self.GetItem(aId)
318  alist.append(action)
319 
320  loopItem = self.GetItem(loop['id'])
321  loopItem.SetItems(alist)
322 
323  for action in loopItem.GetItems():
324  action.SetBlock(loopItem)
325 
326  for condition in gxmXml.conditions:
327  conditionItem = self.GetItem(condition['id'])
328  for b in condition['items'].keys():
329  alist = list()
330  for aId in condition['items'][b]:
331  action = self.GetItem(aId)
332  alist.append(action)
333  conditionItem.SetItems(alist, branch = b)
334 
335  items = conditionItem.GetItems()
336  for b in items.keys():
337  for action in items[b]:
338  action.SetBlock(conditionItem)
339 
340  def AddItem(self, newItem):
341  """!Add item to the list"""
342  iId = newItem.GetId()
343 
344  i = 0
345  for item in self.items:
346  if item.GetId() > iId:
347  self.items.insert(i, newItem)
348  return
349  i += 1
350 
351  self.items.append(newItem)
352 
353  def IsValid(self):
354  """Return True if model is valid"""
355  if self.Validate():
356  return False
357 
358  return True
359 
360  def Validate(self):
361  """!Validate model, return None if model is valid otherwise
362  error string"""
363  errList = list()
364 
365  variables = self.GetVariables().keys()
366  pattern = re.compile(r'(.*)(%.+\s?)(.*)')
367  for action in self.GetItems(objType = ModelAction):
368  cmd = action.GetLog(string = False)
369 
370  task = GUI(show = None).ParseCommand(cmd = cmd)
371  errList += map(lambda x: cmd[0] + ': ' + x, task.get_cmd_error())
372 
373  # check also variables
374  for opt in cmd[1:]:
375  if '=' not in opt:
376  continue
377  key, value = opt.split('=', 1)
378  sval = pattern.search(value)
379  if sval:
380  var = sval.group(2).strip()[1:] # ignore '%'
381  if var not in variables:
382  report = True
383  for item in filter(lambda x: isinstance(x, ModelLoop), action.GetBlock()):
384  if var in item.GetText():
385  report = False
386  break
387  if report:
388  errList.append(cmd[0] + ": " + _("undefined variable '%s'") % var)
389  ### TODO: check variables in file only optionally
390  ### errList += self._substituteFile(action, checkOnly = True)
391 
392  return errList
393 
394  def _substituteFile(self, item, params = None, checkOnly = False):
395  """!Subsitute variables in command file inputs
396 
397  @param checkOnly tuble - True to check variable, don't touch files
398 
399  @return list of undefined variables
400  """
401  errList = list()
402 
403  self.fileInput = dict()
404 
405  # collect ascii inputs
406  for p in item.GetParams()['params']:
407  if p.get('element', '') == 'file' and \
408  p.get('prompt', '') == 'input' and \
409  p.get('age', '') == 'old_file':
410  filename = p.get('value', p.get('default', ''))
411  if filename and \
412  mimetypes.guess_type(filename)[0] == 'text/plain':
413  self.fileInput[filename] = None
414 
415  for finput in self.fileInput:
416  # read lines
417  fd = open(finput, "r")
418  try:
419  data = self.fileInput[finput] = fd.read()
420  finally:
421  fd.close()
422 
423  # substitute variables
424  write = False
425  variables = self.GetVariables()
426  for variable in variables:
427  pattern = re.compile('%' + variable)
428  value = ''
429  if params and 'variables' in params:
430  for p in params['variables']['params']:
431  if variable == p.get('name', ''):
432  if p.get('type', 'string') == 'string':
433  value = p.get('value', '')
434  else:
435  value = str(p.get('value', ''))
436  break
437 
438  if not value:
439  value = variables[variable].get('value', '')
440 
441  data = pattern.sub(value, data)
442  if not checkOnly:
443  write = True
444 
445  pattern = re.compile(r'(.*)(%.+\s?)(.*)')
446  sval = pattern.search(data)
447  if sval:
448  var = sval.group(2).strip()[1:] # ignore '%'
449  cmd = item.GetLog(string = False)[0]
450  errList.append(cmd + ": " + _("undefined variable '%s'") % var)
451 
452  if not checkOnly:
453  if write:
454  fd = open(finput, "w")
455  try:
456  fd.write(data)
457  finally:
458  fd.close()
459  else:
460  self.fileInput[finput] = None
461 
462  return errList
463 
464  def OnPrepare(self, item, params):
465  self._substituteFile(item, params, checkOnly = False)
466 
467  def RunAction(self, item, params, log, onDone, onPrepare = None, statusbar = None):
468  """!Run given action
469 
470  @param item action item
471  @param params parameters dict
472  @param log logging window
473  @param onDone on-done method
474  @param onPrepare on-prepare method
475  @param statusbar wx.StatusBar instance or None
476  """
477  name = item.GetName()
478  if name in params:
479  paramsOrig = item.GetParams(dcopy = True)
480  item.MergeParams(params[name])
481 
482  if statusbar:
483  statusbar.SetStatusText(_('Running model...'), 0)
484 
485  data = { 'item' : item,
486  'params' : copy.deepcopy(params) }
487  log.RunCmd(command = item.GetLog(string = False, substitute = params),
488  onDone = onDone, onPrepare = self.OnPrepare, userData = data)
489 
490  if name in params:
491  item.SetParams(paramsOrig)
492 
493  def Run(self, log, onDone, parent = None):
494  """!Run model
495 
496  @param log logging window (see goutput.GMConsole)
497  @param onDone on-done method
498  @param parent window for messages or None
499  """
500  if self.GetNumItems() < 1:
501  GMessage(parent = parent,
502  message = _('Model is empty. Nothing to run.'))
503  return
504 
505  statusbar = None
506  if isinstance(parent, wx.Frame):
507  statusbar = parent.GetStatusBar()
508 
509  # validation
510  if statusbar:
511  statusbar.SetStatusText(_('Validating model...'), 0)
512  errList = self.Validate()
513  if statusbar:
514  statusbar.SetStatusText('', 0)
515  if errList:
516  dlg = wx.MessageDialog(parent = parent,
517  message = _('Model is not valid. Do you want to '
518  'run the model anyway?\n\n%s') % '\n'.join(errList),
519  caption = _("Run model?"),
520  style = wx.YES_NO | wx.NO_DEFAULT |
521  wx.ICON_QUESTION | wx.CENTRE)
522  ret = dlg.ShowModal()
523  dlg.Destroy()
524  if ret != wx.ID_YES:
525  return
526 
527  # parametrization
528  params = self.Parameterize()
529  delInterData = False
530  if params:
531  dlg = ModelParamDialog(parent = parent,
532  params = params)
533  dlg.CenterOnParent()
534 
535  ret = dlg.ShowModal()
536  if ret != wx.ID_OK:
537  dlg.Destroy()
538  return
539 
540  err = dlg.GetErrors()
541  delInterData = dlg.DeleteIntermediateData()
542  dlg.Destroy()
543  if err:
544  GError(parent = parent, message = unicode('\n'.join(err)))
545  return
546 
547  err = list()
548  for key, item in params.iteritems():
549  for p in item['params']:
550  if p.get('value', '') == '':
551  err.append((key, p.get('name', ''), p.get('description', '')))
552  if err:
553  GError(parent = parent,
554  message = _("Variables below not defined:") + \
555  "\n\n" + unicode('\n'.join(map(lambda x: "%s: %s (%s)" % (x[0], x[1], x[2]), err))))
556  return
557 
558  log.cmdThread.SetId(-1)
559  for item in self.GetItems():
560  if not item.IsEnabled():
561  continue
562  if isinstance(item, ModelAction):
563  if item.GetBlockId():
564  continue
565  self.RunAction(item, params, log, onDone)
566  elif isinstance(item, ModelLoop):
567  cond = item.GetText()
568  # substitute variables in condition
569  variables = self.GetVariables()
570  for variable in variables:
571  pattern = re.compile('%' + variable)
572  if pattern.search(cond):
573  value = ''
574  if params and 'variables' in params:
575  for p in params['variables']['params']:
576  if variable == p.get('name', ''):
577  value = p.get('value', '')
578  break
579 
580  if not value:
581  value = variables[variable].get('value', '')
582 
583  if not value:
584  continue
585 
586  vtype = variables[variable].get('type', 'string')
587  if vtype == 'string':
588  value = '"' + value + '"'
589  cond = pattern.sub(value, cond)
590 
591  # split condition
592  condVar, condText = map(lambda x: x.strip(), re.split('\s*in\s*', cond))
593  pattern = re.compile('%' + condVar)
594  ### for vars()[condVar] in eval(condText): ?
595  if condText[0] == '`' and condText[-1] == '`':
596  # run command
597  cmd, dcmd = utils.CmdToTuple(condText[1:-1].split(' '))
598  ret = RunCommand(cmd,
599  read = True,
600  **dcmd)
601  if ret:
602  vlist = ret.splitlines()
603  else:
604  vlist = eval(condText)
605 
606  if 'variables' not in params:
607  params['variables'] = { 'params' : [] }
608  varDict = { 'name' : condVar, 'value' : '' }
609  params['variables']['params'].append(varDict)
610 
611  for var in vlist:
612  for action in item.GetItems():
613  if not isinstance(action, ModelAction) or \
614  not action.IsEnabled():
615  continue
616 
617  varDict['value'] = var
618 
619  self.RunAction(item = action, params = params,
620  log = log, onDone = onDone)
621  params['variables']['params'].remove(varDict)
622 
623  if delInterData:
624  self.DeleteIntermediateData(log)
625 
626  # discard values
627  if params:
628  for item in params.itervalues():
629  for p in item['params']:
630  p['value'] = ''
631 
632  def DeleteIntermediateData(self, log):
633  """!Detele intermediate data"""
634  rast, vect, rast3d, msg = self.GetIntermediateData()
635 
636  if rast:
637  log.RunCmd(['g.remove', 'rast=%s' %','.join(rast)])
638  if rast3d:
639  log.RunCmd(['g.remove', 'rast3d=%s' %','.join(rast3d)])
640  if vect:
641  log.RunCmd(['g.remove', 'vect=%s' %','.join(vect)])
642 
644  """!Get info about intermediate data"""
645  rast = list()
646  rast3d = list()
647  vect = list()
648  for data in self.GetData():
649  if not data.IsIntermediate():
650  continue
651  name = data.GetValue()
652  prompt = data.GetPrompt()
653  if prompt == 'raster':
654  rast.append(name)
655  elif prompt == 'vector':
656  vect.append(name)
657  elif prompt == 'rast3d':
658  rast3d.append(name)
659 
660  msg = ''
661  if rast:
662  msg += '\n\n%s: ' % _('Raster maps')
663  msg += ', '.join(rast)
664  if rast3d:
665  msg += '\n\n%s: ' % _('3D raster maps')
666  msg += ', '.join(rast3d)
667  if vect:
668  msg += '\n\n%s: ' % _('Vector maps')
669  msg += ', '.join(vect)
670 
671  return rast, vect, rast3d, msg
672 
673  def Update(self):
674  """!Update model"""
675  for item in self.items:
676  item.Update()
677 
678  def IsParameterized(self):
679  """!Return True if model is parameterized"""
680  if self.Parameterize():
681  return True
682 
683  return False
684 
685  def Parameterize(self):
686  """!Return parameterized options"""
687  result = dict()
688  idx = 0
689  if self.variables:
690  params = list()
691  result["variables"] = { 'flags' : list(),
692  'params' : params,
693  'idx' : idx }
694  for name, values in self.variables.iteritems():
695  gtype = values.get('type', 'string')
696  if gtype in ('raster', 'vector', 'mapset', 'file'):
697  gisprompt = True
698  prompt = gtype
699  if gtype == 'raster':
700  element = 'cell'
701  else:
702  element = gtype
703  ptype = 'string'
704  else:
705  gisprompt = False
706  prompt = None
707  element = None
708  ptype = gtype
709  params.append({ 'gisprompt' : gisprompt,
710  'multiple' : False,
711  'description' : values.get('description', ''),
712  'guidependency' : '',
713  'default' : '',
714  'age' : None,
715  'required' : True,
716  'value' : values.get('value', ''),
717  'label' : '',
718  'guisection' : '',
719  'key_desc' : '',
720  'values' : list(),
721  'parameterized' : False,
722  'values_desc' : list(),
723  'prompt' : prompt,
724  'element' : element,
725  'type' : ptype,
726  'name' : name })
727 
728  idx += 1
729 
730  for action in self.GetItems(objType = ModelAction):
731  if not action.IsEnabled():
732  continue
733  name = action.GetName()
734  params = action.GetParams()
735  for f in params['flags']:
736  if f.get('parameterized', False):
737  if name not in result:
738  result[name] = { 'flags' : list(),
739  'params': list(),
740  'idx' : idx }
741  result[name]['flags'].append(f)
742  for p in params['params']:
743  if p.get('parameterized', False):
744  if name not in result:
745  result[name] = { 'flags' : list(),
746  'params': list(),
747  'idx' : idx }
748  result[name]['params'].append(p)
749  if name in result:
750  idx += 1
751 
752  self.variablesParams = result # record parameters
753 
754  return result
755 
756 class ModelObject(object):
757  def __init__(self, id = -1):
758  self.id = id
759  self.rels = list() # list of ModelRelations
760 
761  self.isEnabled = True
762  self.inBlock = list() # list of related loops/conditions
763 
764  def __del__(self):
765  pass
766 
767  def GetId(self):
768  """!Get id"""
769  return self.id
770 
771  def AddRelation(self, rel):
772  """!Record new relation
773  """
774  self.rels.append(rel)
775 
776  def GetRelations(self, fdir = None):
777  """!Get list of relations
778 
779  @param fdir True for 'from'
780  """
781  if fdir is None:
782  return self.rels
783 
784  result = list()
785  for rel in self.rels:
786  if fdir == 'from':
787  if rel.GetFrom() == self:
788  result.append(rel)
789  else:
790  if rel.GetTo() == self:
791  result.append(rel)
792 
793  return result
794 
795  def IsEnabled(self):
796  """!Get True if action is enabled, otherwise False"""
797  return self.isEnabled
798 
799  def Enable(self, enabled = True):
800  """!Enable/disable action"""
801  self.isEnabled = enabled
802  self.Update()
803 
804  def Update(self):
805  pass
806 
807  def SetBlock(self, item):
808  """!Add object to the block (loop/condition)
809 
810  @param item reference to ModelLoop or ModelCondition which
811  defines loops/condition
812  """
813  if item not in self.inBlock:
814  self.inBlock.append(item)
815 
816  def UnSetBlock(self, item):
817  """!Remove object from the block (loop/consition)
818 
819  @param item reference to ModelLoop or ModelCondition which
820  defines loops/codition
821  """
822  if item in self.inBlock:
823  self.inBlock.remove(item)
824 
825  def GetBlock(self):
826  """!Get list of related ModelObject(s) which defines block
827  (loop/condition)
828 
829  @return list of ModelObjects
830  """
831  return self.inBlock
832 
833  def GetBlockId(self):
834  """!Get list of related ids which defines block
835 
836  @return list of ids
837  """
838  ret = list()
839  for mo in self.inBlock:
840  ret.append(mo.GetId())
841 
842  return ret
843 
844 class ModelAction(ModelObject, ogl.RectangleShape):
845  """!Action class (GRASS module)"""
846  def __init__(self, parent, x, y, id = -1, cmd = None, task = None, width = None, height = None):
847  ModelObject.__init__(self, id)
848 
849  self.parent = parent
850  self.task = task
851 
852  if not width:
853  width = UserSettings.Get(group='modeler', key='action', subkey=('size', 'width'))
854  if not height:
855  height = UserSettings.Get(group='modeler', key='action', subkey=('size', 'height'))
856 
857  if cmd and cmd[0] in ('r.mapcalc', 'v.type'):
858  cmd[0] += '_wrapper'
859 
860  if cmd:
861  self.task = GUI(show = None).ParseCommand(cmd = cmd)
862  else:
863  if task:
864  self.task = task
865  else:
866  self.task = None
867 
868  self.propWin = None
869 
870  self.data = list() # list of connected data items
871 
872  self.isValid = False
873  self.isParameterized = False
874 
875  if self.parent.GetCanvas():
876  ogl.RectangleShape.__init__(self, width, height)
877 
878  self.SetCanvas(self.parent)
879  self.SetX(x)
880  self.SetY(y)
881  self.SetPen(wx.BLACK_PEN)
882  self._setPen()
883  self._setBrush()
884  self.SetId(id)
885 
886  if self.task:
887  self.SetValid(self.task.get_options())
888 
889  def _setBrush(self, running = False):
890  """!Set brush"""
891  if running:
892  color = UserSettings.Get(group='modeler', key='action',
893  subkey=('color', 'running'))
894  elif not self.isEnabled:
895  color = UserSettings.Get(group='modeler', key='disabled',
896  subkey='color')
897  elif self.isValid:
898  color = UserSettings.Get(group='modeler', key='action',
899  subkey=('color', 'valid'))
900  else:
901  color = UserSettings.Get(group='modeler', key='action',
902  subkey=('color', 'invalid'))
903 
904  wxColor = wx.Colour(color[0], color[1], color[2])
905  self.SetBrush(wx.Brush(wxColor))
906 
907  def _setPen(self):
908  """!Set pen"""
909  if self.isParameterized:
910  width = int(UserSettings.Get(group='modeler', key='action',
911  subkey=('width', 'parameterized')))
912  else:
913  width = int(UserSettings.Get(group='modeler', key='action',
914  subkey=('width', 'default')))
915  pen = self.GetPen()
916  pen.SetWidth(width)
917  self.SetPen(pen)
918 
919  def SetId(self, id):
920  """!Set id"""
921  self.id = id
922  cmd = self.task.get_cmd(ignoreErrors = True)
923  if cmd and len(cmd) > 0:
924  self.ClearText()
925  self.AddText('(%d) %s' % (self.id, cmd[0]))
926  else:
927  self.AddText('(%d) <<%s>>' % (self.id, _("unknown")))
928 
929  def SetProperties(self, params, propwin):
930  """!Record properties dialog"""
931  self.task.params = params['params']
932  self.task.flags = params['flags']
933  self.propWin = propwin
934 
935  def GetPropDialog(self):
936  """!Get properties dialog"""
937  return self.propWin
938 
939  def GetLog(self, string = True, substitute = None):
940  """!Get logging info
941 
942  @param string True to get cmd as a string otherwise a list
943  @param substitute dictionary of parameter to substitute or None
944  """
945  cmd = self.task.get_cmd(ignoreErrors = True, ignoreRequired = True,
946  ignoreDefault = False)
947 
948  # substitute variables
949  if substitute:
950  variables = []
951  if 'variables' in substitute:
952  for p in substitute['variables']['params']:
953  variables.append(p.get('name', ''))
954  else:
955  variables = self.parent.GetVariables()
956  for variable in variables:
957  pattern= re.compile('%' + variable)
958  value = ''
959  if substitute and 'variables' in substitute:
960  for p in substitute['variables']['params']:
961  if variable == p.get('name', ''):
962  if p.get('type', 'string') == 'string':
963  value = p.get('value', '')
964  else:
965  value = str(p.get('value', ''))
966  break
967 
968  if not value:
969  value = variables[variable].get('value', '')
970 
971  if not value:
972  continue
973 
974  for idx in range(len(cmd)):
975  if pattern.search(cmd[idx]):
976  cmd[idx] = pattern.sub(value, cmd[idx])
977  break
978  idx += 1
979 
980  if string:
981  if cmd is None:
982  return ''
983  else:
984  return ' '.join(cmd)
985 
986  return cmd
987 
988  def GetName(self):
989  """!Get name"""
990  cmd = self.task.get_cmd(ignoreErrors = True)
991  if cmd and len(cmd) > 0:
992  return cmd[0]
993 
994  return _('unknown')
995 
996  def GetParams(self, dcopy = False):
997  """!Get dictionary of parameters"""
998  if dcopy:
999  return copy.deepcopy(self.task.get_options())
1000 
1001  return self.task.get_options()
1002 
1003  def GetTask(self):
1004  """!Get grassTask instance"""
1005  return self.task
1006 
1007  def SetParams(self, params):
1008  """!Set dictionary of parameters"""
1009  self.task.params = params['params']
1010  self.task.flags = params['flags']
1011 
1012  def MergeParams(self, params):
1013  """!Merge dictionary of parameters"""
1014  if 'flags' in params:
1015  for f in params['flags']:
1016  self.task.set_flag(f['name'],
1017  f.get('value', False))
1018  if 'params' in params:
1019  for p in params['params']:
1020  self.task.set_param(p['name'],
1021  p.get('value', ''))
1022 
1023  def SetValid(self, options):
1024  """!Set validity for action
1025 
1026  @param options dictionary with flags and params (gtask)
1027  """
1028  self.isValid = True
1029  self.isParameterized = False
1030 
1031  for f in options['flags']:
1032  if f.get('parameterized', False):
1033  self.IsParameterized = True
1034  break
1035 
1036  for p in options['params']:
1037  if self.isValid and p.get('required', False) and \
1038  p.get('value', '') == '' and \
1039  p.get('default', '') == '':
1040  self.isValid = False
1041  if not self.isParameterized and p.get('parameterized', False):
1042  self.isParameterized = True
1043 
1044  if self.parent.GetCanvas():
1045  self._setBrush()
1046  self._setPen()
1047 
1048  def IsValid(self):
1049  """!Check validity (all required parameters set)"""
1050  return self.isValid
1051 
1052  def IsParameterized(self):
1053  """!Check if action is parameterized"""
1054  return self.isParameterized
1055 
1056  def FindData(self, name):
1057  """!Find data item by name"""
1058  for rel in self.GetRelations():
1059  data = rel.GetData()
1060  if name == rel.GetName() and name in data.GetName():
1061  return data
1062 
1063  return None
1064 
1065  def Update(self, running = False):
1066  """!Update action"""
1067  if running:
1068  self._setBrush(running = True)
1069  else:
1070  self._setBrush()
1071  self._setPen()
1072 
1073  def OnDraw(self, dc):
1074  """!Draw action in canvas"""
1075  self._setBrush()
1076  self._setPen()
1077  ogl.RectangleShape.Recentre(self, dc) # re-center text
1078  ogl.RectangleShape.OnDraw(self, dc)
1079 
1080 class ModelData(ModelObject, ogl.EllipseShape):
1081  def __init__(self, parent, x, y, value = '', prompt = '', width = None, height = None):
1082  """Data item class
1083 
1084  @param parent window parent
1085  @param x, y position of the shape
1086  @param fname, tname list of parameter names from / to
1087  @param value value
1088  @param prompt type of GIS element
1089  @param width,height dimension of the shape
1090  """
1091  ModelObject.__init__(self)
1092 
1093  self.parent = parent
1094  self.value = value
1095  self.prompt = prompt
1096  self.intermediate = False
1097  self.propWin = None
1098  if not width:
1099  width = UserSettings.Get(group='modeler', key='data', subkey=('size', 'width'))
1100  if not height:
1101  height = UserSettings.Get(group='modeler', key='data', subkey=('size', 'height'))
1102 
1103  if self.parent.GetCanvas():
1104  ogl.EllipseShape.__init__(self, width, height)
1105 
1106  self.SetCanvas(self.parent)
1107  self.SetX(x)
1108  self.SetY(y)
1109  self.SetPen(wx.BLACK_PEN)
1110  self._setBrush()
1111 
1112  self._setText()
1113 
1114  def IsIntermediate(self):
1115  """!Checks if data item is intermediate"""
1116  return self.intermediate
1117 
1118  def SetIntermediate(self, im):
1119  """!Set intermediate flag"""
1120  self.intermediate = im
1121 
1122  def OnDraw(self, dc):
1123  pen = self.GetPen()
1124  pen.SetWidth(1)
1125  if self.intermediate:
1126  pen.SetStyle(wx.SHORT_DASH)
1127  else:
1128  pen.SetStyle(wx.SOLID)
1129  self.SetPen(pen)
1130 
1131  ogl.EllipseShape.OnDraw(self, dc)
1132 
1133  def GetLog(self, string = True):
1134  """!Get logging info"""
1135  name = list()
1136  for rel in self.GetRelations():
1137  name.append(rel.GetName())
1138  if name:
1139  return '/'.join(name) + '=' + self.value + ' (' + self.prompt + ')'
1140  else:
1141  return self.value + ' (' + self.prompt + ')'
1142 
1143  def GetName(self):
1144  """!Get list of names"""
1145  name = list()
1146  for rel in self.GetRelations():
1147  name.append(rel.GetName())
1148 
1149  return name
1150 
1151  def GetPrompt(self):
1152  """!Get prompt"""
1153  return self.prompt
1154 
1155  def SetPrompt(self, prompt):
1156  """!Set prompt
1157 
1158  @param prompt
1159  """
1160  self.prompt = prompt
1161 
1162  def GetValue(self):
1163  """!Get value"""
1164  return self.value
1165 
1166  def SetValue(self, value):
1167  """!Set value
1168 
1169  @param value
1170  """
1171  self.value = value
1172  self._setText()
1173  for direction in ('from', 'to'):
1174  for rel in self.GetRelations(direction):
1175  if direction == 'from':
1176  action = rel.GetTo()
1177  else:
1178  action = rel.GetFrom()
1179 
1180  task = GUI(show = None).ParseCommand(cmd = action.GetLog(string = False))
1181  task.set_param(rel.GetName(), self.value)
1182  action.SetParams(params = task.get_options())
1183 
1184  def GetPropDialog(self):
1185  """!Get properties dialog"""
1186  return self.propWin
1187 
1188  def SetPropDialog(self, win):
1189  """!Get properties dialog"""
1190  self.propWin = win
1191 
1192  def _setBrush(self):
1193  """!Set brush"""
1194  if self.prompt == 'raster':
1195  color = UserSettings.Get(group = 'modeler', key = 'data',
1196  subkey = ('color', 'raster'))
1197  elif self.prompt == 'raster3d':
1198  color = UserSettings.Get(group = 'modeler', key = 'data',
1199  subkey = ('color', 'raster3d'))
1200  elif self.prompt == 'vector':
1201  color = UserSettings.Get(group = 'modeler', key = 'data',
1202  subkey = ('color', 'vector'))
1203  else:
1204  color = UserSettings.Get(group = 'modeler', key = 'action',
1205  subkey = ('color', 'invalid'))
1206  wxColor = wx.Colour(color[0], color[1], color[2])
1207  self.SetBrush(wx.Brush(wxColor))
1208 
1209  def _setPen(self):
1210  """!Set pen"""
1211  isParameterized = False
1212  for rel in self.GetRelations('from'):
1213  if rel.GetTo().IsParameterized():
1214  isParameterized = True
1215  break
1216  if not isParameterized:
1217  for rel in self.GetRelations('to'):
1218  if rel.GetFrom().IsParameterized():
1219  isParameterized = True
1220  break
1221 
1222  if isParameterized:
1223  width = int(UserSettings.Get(group = 'modeler', key = 'action',
1224  subkey = ('width', 'parameterized')))
1225  else:
1226  width = int(UserSettings.Get(group = 'modeler', key = 'action',
1227  subkey = ('width', 'default')))
1228  pen = self.GetPen()
1229  pen.SetWidth(width)
1230  self.SetPen(pen)
1231 
1232  def _setText(self):
1233  """!Update text"""
1234  self.ClearText()
1235  name = []
1236  for rel in self.GetRelations():
1237  name.append(rel.GetName())
1238  self.AddText('/'.join(name))
1239  if self.value:
1240  self.AddText(self.value)
1241  else:
1242  self.AddText(_('<not defined>'))
1243 
1244  def Update(self):
1245  """!Update action"""
1246  self._setBrush()
1247  self._setPen()
1248  self._setText()
1249 
1250 class ModelRelation(ogl.LineShape):
1251  """!Data - action relation"""
1252  def __init__(self, parent, fromShape, toShape, param = ''):
1253  self.fromShape = fromShape
1254  self.toShape = toShape
1255  self.param = param
1256  self.parent = parent
1257 
1258  self._points = None
1259 
1260  if self.parent.GetCanvas():
1261  ogl.LineShape.__init__(self)
1262 
1263  def __del__(self):
1264  if self in self.fromShape.rels:
1265  self.fromShape.rels.remove(self)
1266  if self in self.toShape.rels:
1267  self.toShape.rels.remove(self)
1268 
1269  def GetFrom(self):
1270  """!Get id of 'from' shape"""
1271  return self.fromShape
1272 
1273  def GetTo(self):
1274  """!Get id of 'to' shape"""
1275  return self.toShape
1276 
1277  def GetData(self):
1278  """!Get related ModelData instance
1279 
1280  @return ModelData instance
1281  @return None if not found
1282  """
1283  if isinstance(self.fromShape, ModelData):
1284  return self.fromShape
1285  elif isinstance(self.toShape, ModelData):
1286  return self.toShape
1287 
1288  return None
1289 
1290  def GetName(self):
1291  """!Get parameter name"""
1292  return self.param
1293 
1294  def ResetShapes(self):
1295  """!Reset related objects"""
1296  self.fromShape.ResetControlPoints()
1297  self.toShape.ResetControlPoints()
1298  self.ResetControlPoints()
1299 
1300  def SetControlPoints(self, points):
1301  """!Set control points"""
1302  self._points = points
1303 
1304  def GetControlPoints(self):
1305  """!Get list of control points"""
1306  return self._points
1307 
1308  def _setPen(self):
1309  """!Set pen"""
1310  pen = self.GetPen()
1311  pen.SetWidth(1)
1312  pen.SetStyle(wx.SOLID)
1313  self.SetPen(pen)
1314 
1315  def OnDraw(self, dc):
1316  """!Draw relation"""
1317  self._setPen()
1318  ogl.LineShape.OnDraw(self, dc)
1319 
1320  def SetName(self, param):
1321  self.param = param
1322 
1324  def __init__(self, parent, x, y, id = -1, width = None, height = None, text = '', items = []):
1325  """!Abstract class for loops and conditions"""
1326  ModelObject.__init__(self, id)
1327  self.parent = parent
1328  self.text = text
1329  self.items = items # list of items in the loop
1330 
1331  def GetText(self):
1332  """!Get loop text"""
1333  return self.text
1334 
1335  def GetItems(self):
1336  """!Get items (id)"""
1337  return self.items
1338 
1339  def SetId(self, id):
1340  """!Set loop id"""
1341  self.id = id
1342 
1343  def SetText(self, cond):
1344  """!Set loop text (condition)"""
1345  self.text = cond
1346  self.ClearText()
1347  self.AddText('(' + str(self.id) + ') ' + self.text)
1348 
1349  def GetLog(self):
1350  """!Get log info"""
1351  if self.text:
1352  return _("Condition: ") + self.text
1353  else:
1354  return _("Condition: not defined")
1355 
1356  def AddRelation(self, rel):
1357  """!Record relation"""
1358  self.rels.append(rel)
1359 
1360  def Clear(self):
1361  """!Clear object, remove rels"""
1362  self.rels = list()
1363 
1364 class ModelLoop(ModelItem, ogl.RectangleShape):
1365  def __init__(self, parent, x, y, id = -1, width = None, height = None, text = '', items = []):
1366  """!Defines a loop"""
1367  ModelItem.__init__(self, parent, x, y, id, width, height, text, items)
1368 
1369  if not width:
1370  width = UserSettings.Get(group='modeler', key='loop', subkey=('size', 'width'))
1371  if not height:
1372  height = UserSettings.Get(group='modeler', key='loop', subkey=('size', 'height'))
1373 
1374  if self.parent.GetCanvas():
1375  ogl.RectangleShape.__init__(self, width, height)
1376 
1377  self.SetCanvas(self.parent)
1378  self.SetX(x)
1379  self.SetY(y)
1380  self.SetPen(wx.BLACK_PEN)
1381  self.SetCornerRadius(100)
1382  if text:
1383  self.AddText('(' + str(self.id) + ') ' + text)
1384  else:
1385  self.AddText('(' + str(self.id) + ')')
1386 
1387  self._setBrush()
1388 
1389  def _setBrush(self):
1390  """!Set brush"""
1391  if not self.isEnabled:
1392  color = UserSettings.Get(group='modeler', key='disabled',
1393  subkey='color')
1394  else:
1395  color = UserSettings.Get(group='modeler', key='loop',
1396  subkey=('color', 'valid'))
1397 
1398  wxColor = wx.Colour(color[0], color[1], color[2])
1399  self.SetBrush(wx.Brush(wxColor))
1400 
1401  def Enable(self, enabled = True):
1402  """!Enable/disable action"""
1403  for item in self.items:
1404  if not isinstance(item, ModelAction):
1405  continue
1406  item.Enable(enabled)
1407 
1408  ModelObject.Enable(self, enabled)
1409 
1410  def Update(self):
1411  self._setBrush()
1412 
1413  def GetName(self):
1414  """!Get name"""
1415  return _("loop")
1416 
1417  def SetItems(self, items):
1418  """!Set items (id)"""
1419  self.items = items
1420 
1421  def OnDraw(self, dc):
1422  """!Draw loop in canvas"""
1423  self._setBrush()
1424  ogl.RectangleShape.Recentre(self, dc) # re-center text
1425  ogl.RectangleShape.OnDraw(self, dc)
1426 
1427 class ModelCondition(ModelItem, ogl.PolygonShape):
1428  def __init__(self, parent, x, y, id = -1, width = None, height = None, text = '',
1429  items = { 'if' : [], 'else' : [] }):
1430  """!Defines a if-else condition"""
1431  ModelItem.__init__(self, parent, x, y, id, width, height, text, items)
1432 
1433  if not width:
1434  self.width = UserSettings.Get(group='modeler', key='if-else', subkey=('size', 'width'))
1435  else:
1436  self.width = width
1437  if not height:
1438  self.height = UserSettings.Get(group='modeler', key='if-else', subkey=('size', 'height'))
1439  else:
1440  self.height = height
1441 
1442  if self.parent.GetCanvas():
1443  ogl.PolygonShape.__init__(self)
1444 
1445  points = [(0, - self.height / 2),
1446  (self.width / 2, 0),
1447  (0, self.height / 2),
1448  (- self.width / 2, 0)]
1449  self.Create(points)
1450 
1451  self.SetCanvas(self.parent)
1452  self.SetX(x)
1453  self.SetY(y)
1454  self.SetPen(wx.BLACK_PEN)
1455  if text:
1456  self.AddText('(' + str(self.id) + ') ' + text)
1457  else:
1458  self.AddText('(' + str(self.id) + ')')
1459 
1460  def GetName(self):
1461  """!Get name"""
1462  return _("if-else")
1463 
1464  def GetWidth(self):
1465  """!Get object width"""
1466  return self.width
1467 
1468  def GetHeight(self):
1469  """!Get object height"""
1470  return self.height
1471 
1472  def SetItems(self, items, branch = 'if'):
1473  """!Set items (id)
1474 
1475  @param items list of items
1476  @param branch 'if' / 'else'
1477  """
1478  if branch in ['if', 'else']:
1479  self.items[branch] = items
1480 
1482  """!Process GRASS model file (gxm)"""
1483  def __init__(self, tree):
1484  """!A ElementTree handler for the GXM XML file, as defined in
1485  grass-gxm.dtd.
1486  """
1487  self.tree = tree
1488  self.root = self.tree.getroot()
1489 
1490  # list of actions, data
1491  self.properties = dict()
1492  self.variables = dict()
1493  self.actions = list()
1494  self.data = list()
1495  self.loops = list()
1496  self.conditions = list()
1497 
1498  self._processWindow()
1499  self._processProperties()
1500  self._processVariables()
1501  self._processItems()
1502  self._processData()
1503 
1504  def _filterValue(self, value):
1505  """!Filter value
1506 
1507  @param value
1508  """
1509  value = value.replace('&lt;', '<')
1510  value = value.replace('&gt;', '>')
1511 
1512  return value
1513 
1514  def _getNodeText(self, node, tag, default = ''):
1515  """!Get node text"""
1516  p = node.find(tag)
1517  if p is not None:
1518  if p.text:
1519  return utils.normalize_whitespace(p.text)
1520  else:
1521  return ''
1522 
1523  return default
1524 
1525  def _processWindow(self):
1526  """!Process window properties"""
1527  node = self.root.find('window')
1528  if node is None:
1529  self.pos = self.size = None
1530  return
1531 
1532  self.pos, self.size = self._getDim(node)
1533 
1534  def _processProperties(self):
1535  """!Process model properties"""
1536  node = self.root.find('properties')
1537  if node is None:
1538  return
1539  for key in ('name', 'description', 'author'):
1540  self._processProperty(node, key)
1541 
1542  for f in node.findall('flag'):
1543  name = f.get('name', '')
1544  if name == 'overwrite':
1545  self.properties['overwrite'] = True
1546 
1547  def _processProperty(self, pnode, name):
1548  """!Process given property"""
1549  node = pnode.find(name)
1550  if node is not None:
1551  self.properties[name] = node.text
1552  else:
1553  self.properties[name] = ''
1554 
1555  def _processVariables(self):
1556  """!Process model variables"""
1557  vnode = self.root.find('variables')
1558  if vnode is None:
1559  return
1560  for node in vnode.findall('variable'):
1561  name = node.get('name', '')
1562  if not name:
1563  continue # should not happen
1564  self.variables[name] = { 'type' : node.get('type', 'string') }
1565  for key in ('description', 'value'):
1566  self._processVariable(node, name, key)
1567 
1568  def _processVariable(self, pnode, name, key):
1569  """!Process given variable"""
1570  node = pnode.find(key)
1571  if node is not None:
1572  if node.text:
1573  self.variables[name][key] = node.text
1574 
1575  def _processItems(self):
1576  """!Process model items (actions, loops, conditions)"""
1577  self._processActions()
1578  self._processLoops()
1579  self._processConditions()
1580 
1581  def _processActions(self):
1582  """!Process model file"""
1583  for action in self.root.findall('action'):
1584  pos, size = self._getDim(action)
1585  disabled = False
1586 
1587  task = action.find('task')
1588  if task is not None:
1589  if task.find('disabled') is not None:
1590  disabled = True
1591  task = self._processTask(task)
1592  else:
1593  task = None
1594 
1595  aId = int(action.get('id', -1))
1596 
1597  self.actions.append({ 'pos' : pos,
1598  'size' : size,
1599  'task' : task,
1600  'id' : aId,
1601  'disabled' : disabled })
1602 
1603  def _getDim(self, node):
1604  """!Get position and size of shape"""
1605  pos = size = None
1606  posAttr = node.get('pos', None)
1607  if posAttr:
1608  posVal = map(int, posAttr.split(','))
1609  try:
1610  pos = (posVal[0], posVal[1])
1611  except:
1612  pos = None
1613 
1614  sizeAttr = node.get('size', None)
1615  if sizeAttr:
1616  sizeVal = map(int, sizeAttr.split(','))
1617  try:
1618  size = (sizeVal[0], sizeVal[1])
1619  except:
1620  size = None
1621 
1622  return pos, size
1623 
1624  def _processData(self):
1625  """!Process model file"""
1626  for data in self.root.findall('data'):
1627  pos, size = self._getDim(data)
1628  param = data.find('data-parameter')
1629  prompt = value = None
1630  if param is not None:
1631  prompt = param.get('prompt', None)
1632  value = self._filterValue(self._getNodeText(param, 'value'))
1633 
1634  if data.find('intermediate') is None:
1635  intermediate = False
1636  else:
1637  intermediate = True
1638 
1639  rels = list()
1640  for rel in data.findall('relation'):
1641  defrel = { 'id' : int(rel.get('id', -1)),
1642  'dir' : rel.get('dir', 'to'),
1643  'name' : rel.get('name', '') }
1644  points = list()
1645  for point in rel.findall('point'):
1646  x = self._filterValue(self._getNodeText(point, 'x'))
1647  y = self._filterValue(self._getNodeText(point, 'y'))
1648  points.append((float(x), float(y)))
1649  defrel['points'] = points
1650  rels.append(defrel)
1651 
1652  self.data.append({ 'pos' : pos,
1653  'size': size,
1654  'prompt' : prompt,
1655  'value' : value,
1656  'intermediate' : intermediate,
1657  'rels' : rels })
1658 
1659  def _processTask(self, node):
1660  """!Process task
1661 
1662  @return grassTask instance
1663  @return None on error
1664  """
1665  cmd = list()
1666  parameterized = list()
1667 
1668  name = node.get('name', None)
1669  if not name:
1670  return None
1671 
1672  cmd.append(name)
1673 
1674  # flags
1675  for f in node.findall('flag'):
1676  flag = f.get('name', '')
1677  if f.get('parameterized', '0') == '1':
1678  parameterized.append(('flag', flag))
1679  if f.get('value', '1') == '0':
1680  continue
1681  if len(flag) > 1:
1682  cmd.append('--' + flag)
1683  else:
1684  cmd.append('-' + flag)
1685  # parameters
1686  for p in node.findall('parameter'):
1687  name = p.get('name', '')
1688  if p.find('parameterized') is not None:
1689  parameterized.append(('param', name))
1690  cmd.append('%s=%s' % (name,
1691  self._filterValue(self._getNodeText(p, 'value'))))
1692 
1693  task, err = GUI(show = None, checkError = True).ParseCommand(cmd = cmd)
1694  if err:
1695  GWarning(os.linesep.join(err))
1696 
1697  for opt, name in parameterized:
1698  if opt == 'flag':
1699  task.set_flag(name, True, element = 'parameterized')
1700  else:
1701  task.set_param(name, True, element = 'parameterized')
1702 
1703  return task
1704 
1705  def _processLoops(self):
1706  """!Process model loops"""
1707  for node in self.root.findall('loop'):
1708  pos, size = self._getDim(node)
1709  text = self._filterValue(self._getNodeText(node, 'condition')).strip()
1710  aid = list()
1711  for anode in node.findall('item'):
1712  try:
1713  aid.append(int(anode.text))
1714  except ValueError:
1715  pass
1716 
1717  self.loops.append({ 'pos' : pos,
1718  'size' : size,
1719  'text' : text,
1720  'id' : int(node.get('id', -1)),
1721  'items' : aid })
1722 
1723  def _processConditions(self):
1724  """!Process model conditions"""
1725  for node in self.root.findall('if-else'):
1726  pos, size = self._getDim(node)
1727  text = self._filterValue(self._getNodeText(node, 'condition')).strip()
1728  aid = { 'if' : list(),
1729  'else' : list() }
1730  for b in aid.keys():
1731  bnode = node.find(b)
1732  if bnode is None:
1733  continue
1734  for anode in bnode.findall('item'):
1735  try:
1736  aid[b].append(int(anode.text))
1737  except ValueError:
1738  pass
1739 
1740  self.conditions.append({ 'pos' : pos,
1741  'size' : size,
1742  'text' : text,
1743  'id' : int(node.get('id', -1)),
1744  'items' : aid })
1745 
1747  """!Generic class for writing model file"""
1748  def __init__(self, fd, model):
1749  self.fd = fd
1750  self.model = model
1751  self.properties = model.GetProperties()
1752  self.variables = model.GetVariables()
1753  self.items = model.GetItems()
1754 
1755  self.indent = 0
1756 
1757  self._header()
1758 
1759  self._window()
1760  self._properties()
1761  self._variables()
1762  self._items()
1763 
1764  dataList = list()
1765  for action in model.GetItems(objType = ModelAction):
1766  for rel in action.GetRelations():
1767  dataItem = rel.GetData()
1768  if dataItem not in dataList:
1769  dataList.append(dataItem)
1770  self._data(dataList)
1771 
1772  self._footer()
1773 
1774  def _filterValue(self, value):
1775  """!Make value XML-valid"""
1776  value = value.replace('<', '&lt;')
1777  value = value.replace('>', '&gt;')
1778 
1779  return value
1780 
1781  def _header(self):
1782  """!Write header"""
1783  self.fd.write('<?xml version="1.0" encoding="%s"?>\n' % GetDefaultEncoding(forceUTF8 = True))
1784  self.fd.write('<!DOCTYPE gxm SYSTEM "grass-gxm.dtd">\n')
1785  self.fd.write('%s<gxm>\n' % (' ' * self.indent))
1786  self.indent += 4
1787 
1788  def _footer(self):
1789  """!Write footer"""
1790  self.indent -= 4
1791  self.fd.write('%s</gxm>\n' % (' ' * self.indent))
1792 
1793  def _window(self):
1794  """!Write window properties"""
1795  canvas = self.model.GetCanvas()
1796  if canvas is None:
1797  return
1798  win = canvas.parent
1799  pos = win.GetPosition()
1800  size = win.GetSize()
1801  self.fd.write('%s<window pos="%d,%d" size="%d,%d" />\n' % \
1802  (' ' * self.indent, pos[0], pos[1], size[0], size[1]))
1803 
1804  def _properties(self):
1805  """!Write model properties"""
1806  self.fd.write('%s<properties>\n' % (' ' * self.indent))
1807  self.indent += 4
1808  if self.properties['name']:
1809  self.fd.write('%s<name>%s</name>\n' % (' ' * self.indent, EncodeString(self.properties['name'])))
1810  if self.properties['description']:
1811  self.fd.write('%s<description>%s</description>\n' % (' ' * self.indent,
1812  utils.EncodeString(self.properties['description'])))
1813  if self.properties['author']:
1814  self.fd.write('%s<author>%s</author>\n' % (' ' * self.indent,
1815  utils.EncodeString(self.properties['author'])))
1816 
1817  if 'overwrite' in self.properties and \
1818  self.properties['overwrite']:
1819  self.fd.write('%s<flag name="overwrite" />\n' % (' ' * self.indent))
1820  self.indent -= 4
1821  self.fd.write('%s</properties>\n' % (' ' * self.indent))
1822 
1823  def _variables(self):
1824  """!Write model variables"""
1825  if not self.variables:
1826  return
1827  self.fd.write('%s<variables>\n' % (' ' * self.indent))
1828  self.indent += 4
1829  for name, values in self.variables.iteritems():
1830  self.fd.write('%s<variable name="%s" type="%s">\n' % \
1831  (' ' * self.indent, EncodeString(name), values['type']))
1832  self.indent += 4
1833  if 'value' in values:
1834  self.fd.write('%s<value>%s</value>\n' % \
1835  (' ' * self.indent, EncodeString(values['value'])))
1836  if 'description' in values:
1837  self.fd.write('%s<description>%s</description>\n' % \
1838  (' ' * self.indent, EncodeString(values['description'])))
1839  self.indent -= 4
1840  self.fd.write('%s</variable>\n' % (' ' * self.indent))
1841  self.indent -= 4
1842  self.fd.write('%s</variables>\n' % (' ' * self.indent))
1843 
1844  def _items(self):
1845  """!Write actions/loops/conditions"""
1846  for item in self.items:
1847  if isinstance(item, ModelAction):
1848  self._action(item)
1849  elif isinstance(item, ModelLoop):
1850  self._loop(item)
1851  elif isinstance(item, ModelCondition):
1852  self._condition(item)
1853 
1854  def _action(self, action):
1855  """!Write actions"""
1856  self.fd.write('%s<action id="%d" name="%s" pos="%d,%d" size="%d,%d">\n' % \
1857  (' ' * self.indent, action.GetId(), action.GetName(), action.GetX(), action.GetY(),
1858  action.GetWidth(), action.GetHeight()))
1859  self.indent += 4
1860  self.fd.write('%s<task name="%s">\n' % (' ' * self.indent, action.GetLog(string = False)[0]))
1861  self.indent += 4
1862  if not action.IsEnabled():
1863  self.fd.write('%s<disabled />\n' % (' ' * self.indent))
1864  for key, val in action.GetParams().iteritems():
1865  if key == 'flags':
1866  for f in val:
1867  if f.get('value', False) or f.get('parameterized', False):
1868  if f.get('parameterized', False):
1869  if f.get('value', False) == False:
1870  self.fd.write('%s<flag name="%s" value="0" parameterized="1" />\n' %
1871  (' ' * self.indent, f.get('name', '')))
1872  else:
1873  self.fd.write('%s<flag name="%s" parameterized="1" />\n' %
1874  (' ' * self.indent, f.get('name', '')))
1875  else:
1876  self.fd.write('%s<flag name="%s" />\n' %
1877  (' ' * self.indent, f.get('name', '')))
1878  else: # parameter
1879  for p in val:
1880  if not p.get('value', '') and not p.get('parameterized', False):
1881  continue
1882  self.fd.write('%s<parameter name="%s">\n' %
1883  (' ' * self.indent, p.get('name', '')))
1884  self.indent += 4
1885  if p.get('parameterized', False):
1886  self.fd.write('%s<parameterized />\n' % (' ' * self.indent))
1887  self.fd.write('%s<value>%s</value>\n' %
1888  (' ' * self.indent, self._filterValue(p.get('value', ''))))
1889  self.indent -= 4
1890  self.fd.write('%s</parameter>\n' % (' ' * self.indent))
1891  self.indent -= 4
1892  self.fd.write('%s</task>\n' % (' ' * self.indent))
1893  self.indent -= 4
1894  self.fd.write('%s</action>\n' % (' ' * self.indent))
1895 
1896  def _data(self, dataList):
1897  """!Write data"""
1898  for data in dataList:
1899  self.fd.write('%s<data pos="%d,%d" size="%d,%d">\n' % \
1900  (' ' * self.indent, data.GetX(), data.GetY(),
1901  data.GetWidth(), data.GetHeight()))
1902  self.indent += 4
1903  self.fd.write('%s<data-parameter prompt="%s">\n' % \
1904  (' ' * self.indent, data.GetPrompt()))
1905  self.indent += 4
1906  self.fd.write('%s<value>%s</value>\n' %
1907  (' ' * self.indent, self._filterValue(data.GetValue())))
1908  self.indent -= 4
1909  self.fd.write('%s</data-parameter>\n' % (' ' * self.indent))
1910 
1911  if data.IsIntermediate():
1912  self.fd.write('%s<intermediate />\n' % (' ' * self.indent))
1913 
1914  # relations
1915  for ft in ('from', 'to'):
1916  for rel in data.GetRelations(ft):
1917  if ft == 'from':
1918  aid = rel.GetTo().GetId()
1919  else:
1920  aid = rel.GetFrom().GetId()
1921  self.fd.write('%s<relation dir="%s" id="%d" name="%s">\n' % \
1922  (' ' * self.indent, ft, aid, rel.GetName()))
1923  self.indent += 4
1924  for point in rel.GetLineControlPoints()[1:-1]:
1925  self.fd.write('%s<point>\n' % (' ' * self.indent))
1926  self.indent += 4
1927  x, y = point.Get()
1928  self.fd.write('%s<x>%d</x>\n' % (' ' * self.indent, int(x)))
1929  self.fd.write('%s<y>%d</y>\n' % (' ' * self.indent, int(y)))
1930  self.indent -= 4
1931  self.fd.write('%s</point>\n' % (' ' * self.indent))
1932  self.indent -= 4
1933  self.fd.write('%s</relation>\n' % (' ' * self.indent))
1934 
1935  self.indent -= 4
1936  self.fd.write('%s</data>\n' % (' ' * self.indent))
1937 
1938  def _loop(self, loop):
1939  """!Write loops"""
1940  self.fd.write('%s<loop id="%d" pos="%d,%d" size="%d,%d">\n' % \
1941  (' ' * self.indent, loop.GetId(), loop.GetX(), loop.GetY(),
1942  loop.GetWidth(), loop.GetHeight()))
1943  text = loop.GetText()
1944  self.indent += 4
1945  if text:
1946  self.fd.write('%s<condition>%s</condition>\n' %
1947  (' ' * self.indent, self._filterValue(text)))
1948  for item in loop.GetItems():
1949  self.fd.write('%s<item>%d</item>\n' %
1950  (' ' * self.indent, item.GetId()))
1951  self.indent -= 4
1952  self.fd.write('%s</loop>\n' % (' ' * self.indent))
1953 
1954  def _condition(self, condition):
1955  """!Write conditions"""
1956  bbox = condition.GetBoundingBoxMin()
1957  self.fd.write('%s<if-else id="%d" pos="%d,%d" size="%d,%d">\n' % \
1958  (' ' * self.indent, condition.GetId(), condition.GetX(), condition.GetY(),
1959  bbox[0], bbox[1]))
1960  text = condition.GetText()
1961  self.indent += 4
1962  if text:
1963  self.fd.write('%s<condition>%s</condition>\n' %
1964  (' ' * self.indent, self._filterValue(text)))
1965  items = condition.GetItems()
1966  for b in items.keys():
1967  if len(items[b]) < 1:
1968  continue
1969  self.fd.write('%s<%s>\n' % (' ' * self.indent, b))
1970  self.indent += 4
1971  for item in items[b]:
1972  self.fd.write('%s<item>%d</item>\n' %
1973  (' ' * self.indent, item.GetId()))
1974  self.indent -= 4
1975  self.fd.write('%s</%s>\n' % (' ' * self.indent, b))
1976 
1977  self.indent -= 4
1978  self.fd.write('%s</if-else>\n' % (' ' * self.indent))
1979 
1981  def __init__(self, fd, model):
1982  """!Class for exporting model to Python script
1983 
1984  @param fd file desciptor
1985  """
1986  self.fd = fd
1987  self.model = model
1988  self.indent = 4
1989 
1990  self._writePython()
1991 
1992  def _writePython(self):
1993  """!Write model to file"""
1994  properties = self.model.GetProperties()
1995 
1996  self.fd.write(
1997 r"""#!/usr/bin/env python
1998 #
1999 #%s
2000 #
2001 # MODULE: %s
2002 #
2003 # AUTHOR(S): %s
2004 #
2005 # PURPOSE: %s
2006 #
2007 # DATE: %s
2008 #
2009 #%s
2010 """ % ('#' * 79,
2011  EncodeString(properties['name']),
2012  EncodeString(properties['author']),
2013  EncodeString('\n# '.join(properties['description'].splitlines())),
2014  time.asctime(),
2015  '#' * 79))
2016 
2017  self.fd.write(
2018 r"""
2019 import sys
2020 import os
2021 import atexit
2022 
2023 import grass.script as grass
2024 """)
2025 
2026  # cleanup()
2027  rast, vect, rast3d, msg = self.model.GetIntermediateData()
2028  self.fd.write(
2029 r"""
2030 def cleanup():
2031 """)
2032  if rast:
2033  self.fd.write(
2034 r""" grass.run_command('g.remove',
2035  rast=%s)
2036 """ % ','.join(map(lambda x: "'" + x + "'", rast)))
2037  if vect:
2038  self.fd.write(
2039 r""" grass.run_command('g.remove',
2040  vect = %s)
2041 """ % ','.join(map(lambda x: "'" + x + "'", vect)))
2042  if rast3d:
2043  self.fd.write(
2044 r""" grass.run_command('g.remove',
2045  rast3d = %s)
2046 """ % ','.join(map(lambda x: "'" + x + "'", rast3d)))
2047  if not rast and not vect and not rast3d:
2048  self.fd.write(' pass\n')
2049 
2050  self.fd.write("\ndef main():\n")
2051  for item in self.model.GetItems():
2052  self._writePythonItem(item)
2053 
2054  self.fd.write("\n return 0\n")
2055 
2056  self.fd.write(
2057 r"""
2058 if __name__ == "__main__":
2059  options, flags = grass.parser()
2060  atexit.register(cleanup)
2061  sys.exit(main())
2062 """)
2063 
2064  def _writePythonItem(self, item, ignoreBlock = True, variables = []):
2065  """!Write model object to Python file"""
2066  if isinstance(item, ModelAction):
2067  if ignoreBlock and item.GetBlockId(): # ignore items in loops of conditions
2068  return
2069  self._writePythonAction(item, variables = variables)
2070  elif isinstance(item, ModelLoop) or isinstance(item, ModelCondition):
2071  # substitute condition
2072  variables = self.model.GetVariables()
2073  cond = item.GetText()
2074  for variable in variables:
2075  pattern = re.compile('%' + variable)
2076  if pattern.search(cond):
2077  value = variables[variable].get('value', '')
2078  if variables[variable].get('type', 'string') == 'string':
2079  value = '"' + value + '"'
2080  cond = pattern.sub(value, cond)
2081  if isinstance(item, ModelLoop):
2082  condVar, condText = map(lambda x: x.strip(), re.split('\s*in\s*', cond))
2083  cond = "%sfor %s in " % (' ' * self.indent, condVar)
2084  if condText[0] == '`' and condText[-1] == '`':
2085  task = GUI(show = None).ParseCommand(cmd = utils.split(condText[1:-1]))
2086  cond += "grass.read_command("
2087  cond += self._getPythonActionCmd(task, len(cond), variables = [condVar]) + ".splitlines()"
2088  else:
2089  cond += condText
2090  self.fd.write('%s:\n' % cond)
2091  self.indent += 4
2092  for action in item.GetItems():
2093  self._writePythonItem(action, ignoreBlock = False, variables = [condVar])
2094  self.indent -= 4
2095  else: # ModelCondition
2096  self.fd.write('%sif %s:\n' % (' ' * self.indent, cond))
2097  self.indent += 4
2098  condItems = item.GetItems()
2099  for action in condItems['if']:
2100  self._writePythonItem(action, ignoreBlock = False)
2101  if condItems['else']:
2102  self.indent -= 4
2103  self.fd.write('%selse:\n' % (' ' * self.indent))
2104  self.indent += 4
2105  for action in condItems['else']:
2106  self._writePythonItem(action, ignoreBlock = False)
2107  self.indent += 4
2108 
2109  def _writePythonAction(self, item, variables = []):
2110  """!Write model action to Python file"""
2111  task = GUI(show = None).ParseCommand(cmd = item.GetLog(string = False, substitute = self.model.GetVariables()))
2112  strcmd = "%sgrass.run_command(" % (' ' * self.indent)
2113  self.fd.write(strcmd + self._getPythonActionCmd(task, len(strcmd), variables) + '\n')
2114 
2115  def _getPythonActionCmd(self, task, cmdIndent, variables = []):
2116  opts = task.get_options()
2117 
2118  ret = ''
2119  flags = ''
2120  params = list()
2121 
2122  for f in opts['flags']:
2123  if f.get('value', False):
2124  name = f.get('name', '')
2125  if len(name) > 1:
2126  params.append('%s = True' % name)
2127  else:
2128  flags += name
2129 
2130  for p in opts['params']:
2131  name = p.get('name', None)
2132  value = p.get('value', None)
2133  if name and value:
2134  ptype = p.get('type', 'string')
2135  if value[0] == '%':
2136  params.append("%s = %s" % (name, value[1:]))
2137  elif ptype == 'string':
2138  params.append('%s = "%s"' % (name, value))
2139  else:
2140  params.append("%s = %s" % (name, value))
2141 
2142  ret += '"%s"' % task.get_name()
2143  if flags:
2144  ret += ",\n%sflags = '%s'" % (' ' * cmdIndent, flags)
2145  if len(params) > 0:
2146  ret += ",\n"
2147  for opt in params[:-1]:
2148  ret += "%s%s,\n" % (' ' * cmdIndent, opt)
2149  ret += "%s%s)" % (' ' * cmdIndent, params[-1])
2150  else:
2151  ret += ")"
2152 
2153  return ret
2154 
2155 class ModelParamDialog(wx.Dialog):
2156  def __init__(self, parent, params, id = wx.ID_ANY, title = _("Model parameters"),
2157  style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
2158  """!Model parameters dialog
2159  """
2160  self.parent = parent
2161  self.params = params
2162  self.tasks = list() # list of tasks/pages
2163 
2164  wx.Dialog.__init__(self, parent = parent, id = id, title = title, style = style, **kwargs)
2165 
2166  self.notebook = GNotebook(parent = self,
2167  style = globalvar.FNPageDStyle)
2168 
2169  panel = self._createPages()
2170  wx.CallAfter(self.notebook.SetSelection, 0)
2171 
2172  # intermediate data?
2173  self.interData = wx.CheckBox(parent = self, label = _("Delete intermediate data when finish"))
2174  self.interData.SetValue(True)
2175  rast, vect, rast3d, msg = self.parent.GetModel().GetIntermediateData()
2176  if not rast and not vect and not rast3d:
2177  self.interData.Hide()
2178 
2179  self.btnCancel = wx.Button(parent = self, id = wx.ID_CANCEL)
2180  self.btnRun = wx.Button(parent = self, id = wx.ID_OK,
2181  label = _("&Run"))
2182  self.btnRun.SetDefault()
2183 
2184  self._layout()
2185 
2186  size = self.GetBestSize()
2187  self.SetMinSize(size)
2188  self.SetSize((size.width, size.height +
2189  panel.constrained_size[1] -
2190  panel.panelMinHeight))
2191 
2192  def _layout(self):
2193  btnSizer = wx.StdDialogButtonSizer()
2194  btnSizer.AddButton(self.btnCancel)
2195  btnSizer.AddButton(self.btnRun)
2196  btnSizer.Realize()
2197 
2198  mainSizer = wx.BoxSizer(wx.VERTICAL)
2199  mainSizer.Add(item = self.notebook, proportion = 1,
2200  flag = wx.EXPAND)
2201  if self.interData.IsShown():
2202  mainSizer.Add(item = self.interData, proportion = 0,
2203  flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
2204 
2205  mainSizer.Add(item = wx.StaticLine(parent = self, id = wx.ID_ANY,
2206  style = wx.LI_HORIZONTAL),
2207  proportion = 0,
2208  flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border = 5)
2209 
2210  mainSizer.Add(item = btnSizer, proportion = 0,
2211  flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
2212 
2213  self.SetSizer(mainSizer)
2214  mainSizer.Fit(self)
2215 
2216  def _createPages(self):
2217  """!Create for each parameterized module its own page"""
2218  nameOrdered = [''] * len(self.params.keys())
2219  for name, params in self.params.iteritems():
2220  nameOrdered[params['idx']] = name
2221  for name in nameOrdered:
2222  params = self.params[name]
2223  panel = self._createPage(name, params)
2224  if name == 'variables':
2225  name = _('Variables')
2226  self.notebook.AddPage(page = panel, text = name)
2227 
2228  return panel
2229 
2230  def _createPage(self, name, params):
2231  """!Define notebook page"""
2232  if name in globalvar.grassCmd:
2233  task = gtask.grassTask(name)
2234  else:
2235  task = gtask.grassTask()
2236  task.flags = params['flags']
2237  task.params = params['params']
2238 
2239  panel = CmdPanel(parent = self, id = wx.ID_ANY, task = task)
2240  self.tasks.append(task)
2241 
2242  return panel
2243 
2244  def GetErrors(self):
2245  """!Check for errors, get list of messages"""
2246  errList = list()
2247  for task in self.tasks:
2248  errList += task.get_cmd_error()
2249 
2250  return errList
2251 
2253  """!Check if to detele intermediate data"""
2254  if self.interData.IsShown() and self.interData.IsChecked():
2255  return True
2256 
2257  return False
def CmdToTuple
Convert command list to tuple for gcmd.RunCommand()
Definition: core/utils.py:527
variablesParams
Definition: model.py:63
def GetItems
Get list of model items.
Definition: model.py:71
def _processActions
Process model file.
Definition: model.py:1581
def normalize_whitespace
Remove redundant whitespace from a string.
Definition: core/utils.py:33
def EncodeString
Return encoded string using system locales.
Definition: gcmd.py:85
def _writePython
Write model to file.
Definition: model.py:1992
def GetPropDialog
Get properties dialog.
Definition: model.py:935
def _processVariable
Process given variable.
Definition: model.py:1568
wxGUI command interface
def GetValue
Get value.
Definition: model.py:1162
def Clear
Clear object, remove rels.
Definition: model.py:1360
def IsEnabled
Get True if action is enabled, otherwise False.
Definition: model.py:795
def _filterValue
Make value XML-valid.
Definition: model.py:1774
def _properties
Write model properties.
Definition: model.py:1804
def DeleteIntermediateData
Check if to detele intermediate data.
Definition: model.py:2252
def __init__
Model parameters dialog.
Definition: model.py:2157
def _loop
Write loops.
Definition: model.py:1938
properties
Definition: model.py:58
def SetText
Set loop text (condition)
Definition: model.py:1343
def _setPen
Set pen.
Definition: model.py:907
Generic class for writing model file.
Definition: model.py:1746
def _getDim
Get position and size of shape.
Definition: model.py:1603
def SetParams
Set dictionary of parameters.
Definition: model.py:1007
def __init__
Definition: model.py:54
def _setPen
Set pen.
Definition: model.py:1209
def FindData
Find data item by name.
Definition: model.py:1056
def _setText
Update text.
Definition: model.py:1232
def _processConditions
Process model conditions.
Definition: model.py:1723
Action class (GRASS module)
Definition: model.py:844
def GetPropDialog
Get properties dialog.
Definition: model.py:1184
def SetVariables
Set model variables.
Definition: model.py:133
def GetParams
Get dictionary of parameters.
Definition: model.py:996
def GetNumItems
Get number of items.
Definition: model.py:101
def _processProperties
Process model properties.
Definition: model.py:1534
def _processWindow
Process window properties.
Definition: model.py:1525
def _processLoops
Process model loops.
Definition: model.py:1705
def Update
Update action.
Definition: model.py:1065
Core GUI widgets.
def GetRelations
Get list of relations.
Definition: model.py:776
Class representing the model.
Definition: model.py:52
def ResetShapes
Reset related objects.
Definition: model.py:1294
def GetItems
Get items (id)
Definition: model.py:1335
def GetName
Get name.
Definition: model.py:1413
def _createPage
Define notebook page.
Definition: model.py:2230
def __init__
Abstract class for loops and conditions.
Definition: model.py:1324
def _items
Write actions/loops/conditions.
Definition: model.py:1844
def GetBlock
Get list of related ModelObject(s) which defines block (loop/condition)
Definition: model.py:825
def __init__
Defines a loop.
Definition: model.py:1365
def Parameterize
Return parameterized options.
Definition: model.py:685
def GetText
Get loop text.
Definition: model.py:1331
def RunAction
Run given action.
Definition: model.py:467
def GetLog
Get logging info.
Definition: model.py:1133
def __init__
Class for exporting model to Python script.
Definition: model.py:1981
def FindData
Find data item in the model.
Definition: model.py:205
def SetProperties
Record properties dialog.
Definition: model.py:929
def _footer
Write footer.
Definition: model.py:1788
def Enable
Enable/disable action.
Definition: model.py:1401
def Validate
Validate model, return None if model is valid otherwise error string.
Definition: model.py:360
def GetTo
Get id of &#39;to&#39; shape.
Definition: model.py:1273
def IsIntermediate
Checks if data item is intermediate.
Definition: model.py:1114
def GetBlockId
Get list of related ids which defines block.
Definition: model.py:833
def SetControlPoints
Set control points.
Definition: model.py:1300
def split
Platform spefic shlex.split.
Definition: core/utils.py:37
def AddRelation
Record relation.
Definition: model.py:1356
def _processData
Process model file.
Definition: model.py:1624
def _substituteFile
Subsitute variables in command file inputs.
Definition: model.py:394
def GetId
Get id.
Definition: model.py:767
def _condition
Write conditions.
Definition: model.py:1954
def IsParameterized
Return True if model is parameterized.
Definition: model.py:678
def GetHeight
Get object height.
Definition: model.py:1468
def GetIntermediateData
Get info about intermediate data.
Definition: model.py:643
def RemoveItem
Remove item from model.
Definition: model.py:141
def SetIntermediate
Set intermediate flag.
Definition: model.py:1118
def Update
Update model.
Definition: model.py:673
Data - action relation.
Definition: model.py:1250
def Enable
Enable/disable action.
Definition: model.py:799
def _setPen
Set pen.
Definition: model.py:1308
def SetBlock
Add object to the block (loop/condition)
Definition: model.py:807
def SetPrompt
Set prompt.
Definition: model.py:1155
def OnDraw
Draw loop in canvas.
Definition: model.py:1421
def GetLog
Get logging info.
Definition: model.py:939
def SetId
Set id.
Definition: model.py:919
def LoadModel
Load model definition stored in GRASS Model XML file (gxm)
Definition: model.py:221
def EncodeString
Return encoded string using system locales.
Definition: core/utils.py:721
def _processItems
Process model items (actions, loops, conditions)
Definition: model.py:1575
def AddItem
Add item to the list.
Definition: model.py:340
def _setBrush
Set brush.
Definition: model.py:1389
def Reset
Reset model.
Definition: model.py:137
def SetValue
Set value.
Definition: model.py:1166
def _processProperty
Process given property.
Definition: model.py:1547
def SetItems
Set items (id)
Definition: model.py:1417
def SetPropDialog
Get properties dialog.
Definition: model.py:1188
def GetErrors
Check for errors, get list of messages.
Definition: model.py:2244
def GetDefaultEncoding
Get default system encoding.
Definition: gcmd.py:701
def GetData
Get related ModelData instance.
Definition: model.py:1277
def GetNextId
Get next id (data ignored)
Definition: model.py:108
def _processTask
Process task.
Definition: model.py:1659
def _data
Write data.
Definition: model.py:1896
def AddRelation
Record new relation.
Definition: model.py:771
def IsValid
Definition: model.py:353
def MergeParams
Merge dictionary of parameters.
Definition: model.py:1012
def GetControlPoints
Get list of control points.
Definition: model.py:1304
def _filterValue
Filter value.
Definition: model.py:1504
def SetValid
Set validity for action.
Definition: model.py:1023
def __init__
A ElementTree handler for the GXM XML file, as defined in grass-gxm.dtd.
Definition: model.py:1483
def GetName
Get list of names.
Definition: model.py:1143
def OnPrepare
Definition: model.py:464
def GetPrompt
Get prompt.
Definition: model.py:1151
def GetLog
Get log info.
Definition: model.py:1349
def _setBrush
Set brush.
Definition: model.py:1192
def _processVariables
Process model variables.
Definition: model.py:1555
def GetName
Get parameter name.
Definition: model.py:1290
def OnDraw
Draw action in canvas.
Definition: model.py:1073
def Run
Run model.
Definition: model.py:493
def _action
Write actions.
Definition: model.py:1854
def _writePythonItem
Write model object to Python file.
Definition: model.py:2064
def IsValid
Check validity (all required parameters set)
Definition: model.py:1048
def OnDraw
Draw relation.
Definition: model.py:1315
Process GRASS model file (gxm)
Definition: model.py:1481
Default GUI settings.
def GetCanvas
Get canvas or None.
Definition: model.py:67
def _createPages
Create for each parameterized module its own page.
Definition: model.py:2216
def GetName
Get name.
Definition: model.py:988
def GetData
Get list of data items.
Definition: model.py:186
def GetName
Get name.
Definition: model.py:1460
def _variables
Write model variables.
Definition: model.py:1823
def _window
Write window properties.
Definition: model.py:1793
tuple range
Definition: tools.py:1406
def Update
Update action.
Definition: model.py:1244
def GetTask
Get grassTask instance.
Definition: model.py:1003
def GetItem
Get item of given id.
Definition: model.py:86
def _header
Write header.
Definition: model.py:1781
def SetId
Set loop id.
Definition: model.py:1339
def DeleteIntermediateData
Detele intermediate data.
Definition: model.py:632
def _setBrush
Set brush.
Definition: model.py:889
def GetVariables
Get model variables.
Definition: model.py:126
def GetProperties
Get model properties.
Definition: model.py:122
def FindAction
Find action by id.
Definition: model.py:177
def SetItems
Set items (id)
Definition: model.py:1472
def RunCommand
Run GRASS command.
Definition: gcmd.py:625
def _writePythonAction
Write model action to Python file.
Definition: model.py:2109
def UnSetBlock
Remove object from the block (loop/consition)
Definition: model.py:816
def GetWidth
Get object width.
Definition: model.py:1464
def _getNodeText
Get node text.
Definition: model.py:1514
def GetFrom
Get id of &#39;from&#39; shape.
Definition: model.py:1269