GRASS Programmer's Manual  6.4.4(2014)-r
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 class ModelCondition(ModelItem, ogl.PolygonShape):
1422  def __init__(self, parent, x, y, id = -1, width = None, height = None, text = '',
1423  items = { 'if' : [], 'else' : [] }):
1424  """!Defines a if-else condition"""
1425  ModelItem.__init__(self, parent, x, y, id, width, height, text, items)
1426 
1427  if not width:
1428  self.width = UserSettings.Get(group='modeler', key='if-else', subkey=('size', 'width'))
1429  else:
1430  self.width = width
1431  if not height:
1432  self.height = UserSettings.Get(group='modeler', key='if-else', subkey=('size', 'height'))
1433  else:
1434  self.height = height
1435 
1436  if self.parent.GetCanvas():
1437  ogl.PolygonShape.__init__(self)
1438 
1439  points = [(0, - self.height / 2),
1440  (self.width / 2, 0),
1441  (0, self.height / 2),
1442  (- self.width / 2, 0)]
1443  self.Create(points)
1444 
1445  self.SetCanvas(self.parent)
1446  self.SetX(x)
1447  self.SetY(y)
1448  self.SetPen(wx.BLACK_PEN)
1449  if text:
1450  self.AddText('(' + str(self.id) + ') ' + text)
1451  else:
1452  self.AddText('(' + str(self.id) + ')')
1453 
1454  def GetName(self):
1455  """!Get name"""
1456  return _("if-else")
1457 
1458  def GetWidth(self):
1459  """!Get object width"""
1460  return self.width
1461 
1462  def GetHeight(self):
1463  """!Get object height"""
1464  return self.height
1465 
1466  def SetItems(self, items, branch = 'if'):
1467  """!Set items (id)
1468 
1469  @param items list of items
1470  @param branch 'if' / 'else'
1471  """
1472  if branch in ['if', 'else']:
1473  self.items[branch] = items
1474 
1476  """!Process GRASS model file (gxm)"""
1477  def __init__(self, tree):
1478  """!A ElementTree handler for the GXM XML file, as defined in
1479  grass-gxm.dtd.
1480  """
1481  self.tree = tree
1482  self.root = self.tree.getroot()
1483 
1484  # list of actions, data
1485  self.properties = dict()
1486  self.variables = dict()
1487  self.actions = list()
1488  self.data = list()
1489  self.loops = list()
1490  self.conditions = list()
1491 
1492  self._processWindow()
1493  self._processProperties()
1494  self._processVariables()
1495  self._processItems()
1496  self._processData()
1497 
1498  def _filterValue(self, value):
1499  """!Filter value
1500 
1501  @param value
1502  """
1503  value = value.replace('&lt;', '<')
1504  value = value.replace('&gt;', '>')
1505 
1506  return value
1507 
1508  def _getNodeText(self, node, tag, default = ''):
1509  """!Get node text"""
1510  p = node.find(tag)
1511  if p is not None:
1512  if p.text:
1513  return utils.normalize_whitespace(p.text)
1514  else:
1515  return ''
1516 
1517  return default
1518 
1519  def _processWindow(self):
1520  """!Process window properties"""
1521  node = self.root.find('window')
1522  if node is None:
1523  self.pos = self.size = None
1524  return
1525 
1526  self.pos, self.size = self._getDim(node)
1527 
1528  def _processProperties(self):
1529  """!Process model properties"""
1530  node = self.root.find('properties')
1531  if node is None:
1532  return
1533  for key in ('name', 'description', 'author'):
1534  self._processProperty(node, key)
1535 
1536  for f in node.findall('flag'):
1537  name = f.get('name', '')
1538  if name == 'overwrite':
1539  self.properties['overwrite'] = True
1540 
1541  def _processProperty(self, pnode, name):
1542  """!Process given property"""
1543  node = pnode.find(name)
1544  if node is not None:
1545  self.properties[name] = node.text
1546  else:
1547  self.properties[name] = ''
1548 
1549  def _processVariables(self):
1550  """!Process model variables"""
1551  vnode = self.root.find('variables')
1552  if vnode is None:
1553  return
1554  for node in vnode.findall('variable'):
1555  name = node.get('name', '')
1556  if not name:
1557  continue # should not happen
1558  self.variables[name] = { 'type' : node.get('type', 'string') }
1559  for key in ('description', 'value'):
1560  self._processVariable(node, name, key)
1561 
1562  def _processVariable(self, pnode, name, key):
1563  """!Process given variable"""
1564  node = pnode.find(key)
1565  if node is not None:
1566  if node.text:
1567  self.variables[name][key] = node.text
1568 
1569  def _processItems(self):
1570  """!Process model items (actions, loops, conditions)"""
1571  self._processActions()
1572  self._processLoops()
1573  self._processConditions()
1574 
1575  def _processActions(self):
1576  """!Process model file"""
1577  for action in self.root.findall('action'):
1578  pos, size = self._getDim(action)
1579  disabled = False
1580 
1581  task = action.find('task')
1582  if task is not None:
1583  if task.find('disabled') is not None:
1584  disabled = True
1585  task = self._processTask(task)
1586  else:
1587  task = None
1588 
1589  aId = int(action.get('id', -1))
1590 
1591  self.actions.append({ 'pos' : pos,
1592  'size' : size,
1593  'task' : task,
1594  'id' : aId,
1595  'disabled' : disabled })
1596 
1597  def _getDim(self, node):
1598  """!Get position and size of shape"""
1599  pos = size = None
1600  posAttr = node.get('pos', None)
1601  if posAttr:
1602  posVal = map(int, posAttr.split(','))
1603  try:
1604  pos = (posVal[0], posVal[1])
1605  except:
1606  pos = None
1607 
1608  sizeAttr = node.get('size', None)
1609  if sizeAttr:
1610  sizeVal = map(int, sizeAttr.split(','))
1611  try:
1612  size = (sizeVal[0], sizeVal[1])
1613  except:
1614  size = None
1615 
1616  return pos, size
1617 
1618  def _processData(self):
1619  """!Process model file"""
1620  for data in self.root.findall('data'):
1621  pos, size = self._getDim(data)
1622  param = data.find('data-parameter')
1623  prompt = value = None
1624  if param is not None:
1625  prompt = param.get('prompt', None)
1626  value = self._filterValue(self._getNodeText(param, 'value'))
1627 
1628  if data.find('intermediate') is None:
1629  intermediate = False
1630  else:
1631  intermediate = True
1632 
1633  rels = list()
1634  for rel in data.findall('relation'):
1635  defrel = { 'id' : int(rel.get('id', -1)),
1636  'dir' : rel.get('dir', 'to'),
1637  'name' : rel.get('name', '') }
1638  points = list()
1639  for point in rel.findall('point'):
1640  x = self._filterValue(self._getNodeText(point, 'x'))
1641  y = self._filterValue(self._getNodeText(point, 'y'))
1642  points.append((float(x), float(y)))
1643  defrel['points'] = points
1644  rels.append(defrel)
1645 
1646  self.data.append({ 'pos' : pos,
1647  'size': size,
1648  'prompt' : prompt,
1649  'value' : value,
1650  'intermediate' : intermediate,
1651  'rels' : rels })
1652 
1653  def _processTask(self, node):
1654  """!Process task
1655 
1656  @return grassTask instance
1657  @return None on error
1658  """
1659  cmd = list()
1660  parameterized = list()
1661 
1662  name = node.get('name', None)
1663  if not name:
1664  return None
1665 
1666  cmd.append(name)
1667 
1668  # flags
1669  for f in node.findall('flag'):
1670  flag = f.get('name', '')
1671  if f.get('parameterized', '0') == '1':
1672  parameterized.append(('flag', flag))
1673  if f.get('value', '1') == '0':
1674  continue
1675  if len(flag) > 1:
1676  cmd.append('--' + flag)
1677  else:
1678  cmd.append('-' + flag)
1679  # parameters
1680  for p in node.findall('parameter'):
1681  name = p.get('name', '')
1682  if p.find('parameterized') is not None:
1683  parameterized.append(('param', name))
1684  cmd.append('%s=%s' % (name,
1685  self._filterValue(self._getNodeText(p, 'value'))))
1686 
1687  task, err = GUI(show = None, checkError = True).ParseCommand(cmd = cmd)
1688  if err:
1689  GWarning(os.linesep.join(err))
1690 
1691  for opt, name in parameterized:
1692  if opt == 'flag':
1693  task.set_flag(name, True, element = 'parameterized')
1694  else:
1695  task.set_param(name, True, element = 'parameterized')
1696 
1697  return task
1698 
1699  def _processLoops(self):
1700  """!Process model loops"""
1701  for node in self.root.findall('loop'):
1702  pos, size = self._getDim(node)
1703  text = self._filterValue(self._getNodeText(node, 'condition')).strip()
1704  aid = list()
1705  for anode in node.findall('item'):
1706  try:
1707  aid.append(int(anode.text))
1708  except ValueError:
1709  pass
1710 
1711  self.loops.append({ 'pos' : pos,
1712  'size' : size,
1713  'text' : text,
1714  'id' : int(node.get('id', -1)),
1715  'items' : aid })
1716 
1717  def _processConditions(self):
1718  """!Process model conditions"""
1719  for node in self.root.findall('if-else'):
1720  pos, size = self._getDim(node)
1721  text = self._filterValue(self._getNodeText(node, 'condition')).strip()
1722  aid = { 'if' : list(),
1723  'else' : list() }
1724  for b in aid.keys():
1725  bnode = node.find(b)
1726  if bnode is None:
1727  continue
1728  for anode in bnode.findall('item'):
1729  try:
1730  aid[b].append(int(anode.text))
1731  except ValueError:
1732  pass
1733 
1734  self.conditions.append({ 'pos' : pos,
1735  'size' : size,
1736  'text' : text,
1737  'id' : int(node.get('id', -1)),
1738  'items' : aid })
1739 
1741  """!Generic class for writing model file"""
1742  def __init__(self, fd, model):
1743  self.fd = fd
1744  self.model = model
1745  self.properties = model.GetProperties()
1746  self.variables = model.GetVariables()
1747  self.items = model.GetItems()
1748 
1749  self.indent = 0
1750 
1751  self._header()
1752 
1753  self._window()
1754  self._properties()
1755  self._variables()
1756  self._items()
1757 
1758  dataList = list()
1759  for action in model.GetItems(objType = ModelAction):
1760  for rel in action.GetRelations():
1761  dataItem = rel.GetData()
1762  if dataItem not in dataList:
1763  dataList.append(dataItem)
1764  self._data(dataList)
1765 
1766  self._footer()
1767 
1768  def _filterValue(self, value):
1769  """!Make value XML-valid"""
1770  value = value.replace('<', '&lt;')
1771  value = value.replace('>', '&gt;')
1772 
1773  return value
1774 
1775  def _header(self):
1776  """!Write header"""
1777  self.fd.write('<?xml version="1.0" encoding="%s"?>\n' % GetDefaultEncoding(forceUTF8 = True))
1778  self.fd.write('<!DOCTYPE gxm SYSTEM "grass-gxm.dtd">\n')
1779  self.fd.write('%s<gxm>\n' % (' ' * self.indent))
1780  self.indent += 4
1781 
1782  def _footer(self):
1783  """!Write footer"""
1784  self.indent -= 4
1785  self.fd.write('%s</gxm>\n' % (' ' * self.indent))
1786 
1787  def _window(self):
1788  """!Write window properties"""
1789  canvas = self.model.GetCanvas()
1790  if canvas is None:
1791  return
1792  win = canvas.parent
1793  pos = win.GetPosition()
1794  size = win.GetSize()
1795  self.fd.write('%s<window pos="%d,%d" size="%d,%d" />\n' % \
1796  (' ' * self.indent, pos[0], pos[1], size[0], size[1]))
1797 
1798  def _properties(self):
1799  """!Write model properties"""
1800  self.fd.write('%s<properties>\n' % (' ' * self.indent))
1801  self.indent += 4
1802  if self.properties['name']:
1803  self.fd.write('%s<name>%s</name>\n' % (' ' * self.indent, EncodeString(self.properties['name'])))
1804  if self.properties['description']:
1805  self.fd.write('%s<description>%s</description>\n' % (' ' * self.indent,
1806  utils.EncodeString(self.properties['description'])))
1807  if self.properties['author']:
1808  self.fd.write('%s<author>%s</author>\n' % (' ' * self.indent,
1809  utils.EncodeString(self.properties['author'])))
1810 
1811  if 'overwrite' in self.properties and \
1812  self.properties['overwrite']:
1813  self.fd.write('%s<flag name="overwrite" />\n' % (' ' * self.indent))
1814  self.indent -= 4
1815  self.fd.write('%s</properties>\n' % (' ' * self.indent))
1816 
1817  def _variables(self):
1818  """!Write model variables"""
1819  if not self.variables:
1820  return
1821  self.fd.write('%s<variables>\n' % (' ' * self.indent))
1822  self.indent += 4
1823  for name, values in self.variables.iteritems():
1824  self.fd.write('%s<variable name="%s" type="%s">\n' % \
1825  (' ' * self.indent, EncodeString(name), values['type']))
1826  self.indent += 4
1827  if 'value' in values:
1828  self.fd.write('%s<value>%s</value>\n' % \
1829  (' ' * self.indent, EncodeString(values['value'])))
1830  if 'description' in values:
1831  self.fd.write('%s<description>%s</description>\n' % \
1832  (' ' * self.indent, EncodeString(values['description'])))
1833  self.indent -= 4
1834  self.fd.write('%s</variable>\n' % (' ' * self.indent))
1835  self.indent -= 4
1836  self.fd.write('%s</variables>\n' % (' ' * self.indent))
1837 
1838  def _items(self):
1839  """!Write actions/loops/conditions"""
1840  for item in self.items:
1841  if isinstance(item, ModelAction):
1842  self._action(item)
1843  elif isinstance(item, ModelLoop):
1844  self._loop(item)
1845  elif isinstance(item, ModelCondition):
1846  self._condition(item)
1847 
1848  def _action(self, action):
1849  """!Write actions"""
1850  self.fd.write('%s<action id="%d" name="%s" pos="%d,%d" size="%d,%d">\n' % \
1851  (' ' * self.indent, action.GetId(), action.GetName(), action.GetX(), action.GetY(),
1852  action.GetWidth(), action.GetHeight()))
1853  self.indent += 4
1854  self.fd.write('%s<task name="%s">\n' % (' ' * self.indent, action.GetLog(string = False)[0]))
1855  self.indent += 4
1856  if not action.IsEnabled():
1857  self.fd.write('%s<disabled />\n' % (' ' * self.indent))
1858  for key, val in action.GetParams().iteritems():
1859  if key == 'flags':
1860  for f in val:
1861  if f.get('value', False) or f.get('parameterized', False):
1862  if f.get('parameterized', False):
1863  if f.get('value', False) == False:
1864  self.fd.write('%s<flag name="%s" value="0" parameterized="1" />\n' %
1865  (' ' * self.indent, f.get('name', '')))
1866  else:
1867  self.fd.write('%s<flag name="%s" parameterized="1" />\n' %
1868  (' ' * self.indent, f.get('name', '')))
1869  else:
1870  self.fd.write('%s<flag name="%s" />\n' %
1871  (' ' * self.indent, f.get('name', '')))
1872  else: # parameter
1873  for p in val:
1874  if not p.get('value', '') and not p.get('parameterized', False):
1875  continue
1876  self.fd.write('%s<parameter name="%s">\n' %
1877  (' ' * self.indent, p.get('name', '')))
1878  self.indent += 4
1879  if p.get('parameterized', False):
1880  self.fd.write('%s<parameterized />\n' % (' ' * self.indent))
1881  self.fd.write('%s<value>%s</value>\n' %
1882  (' ' * self.indent, self._filterValue(p.get('value', ''))))
1883  self.indent -= 4
1884  self.fd.write('%s</parameter>\n' % (' ' * self.indent))
1885  self.indent -= 4
1886  self.fd.write('%s</task>\n' % (' ' * self.indent))
1887  self.indent -= 4
1888  self.fd.write('%s</action>\n' % (' ' * self.indent))
1889 
1890  def _data(self, dataList):
1891  """!Write data"""
1892  for data in dataList:
1893  self.fd.write('%s<data pos="%d,%d" size="%d,%d">\n' % \
1894  (' ' * self.indent, data.GetX(), data.GetY(),
1895  data.GetWidth(), data.GetHeight()))
1896  self.indent += 4
1897  self.fd.write('%s<data-parameter prompt="%s">\n' % \
1898  (' ' * self.indent, data.GetPrompt()))
1899  self.indent += 4
1900  self.fd.write('%s<value>%s</value>\n' %
1901  (' ' * self.indent, self._filterValue(data.GetValue())))
1902  self.indent -= 4
1903  self.fd.write('%s</data-parameter>\n' % (' ' * self.indent))
1904 
1905  if data.IsIntermediate():
1906  self.fd.write('%s<intermediate />\n' % (' ' * self.indent))
1907 
1908  # relations
1909  for ft in ('from', 'to'):
1910  for rel in data.GetRelations(ft):
1911  if ft == 'from':
1912  aid = rel.GetTo().GetId()
1913  else:
1914  aid = rel.GetFrom().GetId()
1915  self.fd.write('%s<relation dir="%s" id="%d" name="%s">\n' % \
1916  (' ' * self.indent, ft, aid, rel.GetName()))
1917  self.indent += 4
1918  for point in rel.GetLineControlPoints()[1:-1]:
1919  self.fd.write('%s<point>\n' % (' ' * self.indent))
1920  self.indent += 4
1921  x, y = point.Get()
1922  self.fd.write('%s<x>%d</x>\n' % (' ' * self.indent, int(x)))
1923  self.fd.write('%s<y>%d</y>\n' % (' ' * self.indent, int(y)))
1924  self.indent -= 4
1925  self.fd.write('%s</point>\n' % (' ' * self.indent))
1926  self.indent -= 4
1927  self.fd.write('%s</relation>\n' % (' ' * self.indent))
1928 
1929  self.indent -= 4
1930  self.fd.write('%s</data>\n' % (' ' * self.indent))
1931 
1932  def _loop(self, loop):
1933  """!Write loops"""
1934  self.fd.write('%s<loop id="%d" pos="%d,%d" size="%d,%d">\n' % \
1935  (' ' * self.indent, loop.GetId(), loop.GetX(), loop.GetY(),
1936  loop.GetWidth(), loop.GetHeight()))
1937  text = loop.GetText()
1938  self.indent += 4
1939  if text:
1940  self.fd.write('%s<condition>%s</condition>\n' %
1941  (' ' * self.indent, self._filterValue(text)))
1942  for item in loop.GetItems():
1943  self.fd.write('%s<item>%d</item>\n' %
1944  (' ' * self.indent, item.GetId()))
1945  self.indent -= 4
1946  self.fd.write('%s</loop>\n' % (' ' * self.indent))
1947 
1948  def _condition(self, condition):
1949  """!Write conditions"""
1950  bbox = condition.GetBoundingBoxMin()
1951  self.fd.write('%s<if-else id="%d" pos="%d,%d" size="%d,%d">\n' % \
1952  (' ' * self.indent, condition.GetId(), condition.GetX(), condition.GetY(),
1953  bbox[0], bbox[1]))
1954  text = condition.GetText()
1955  self.indent += 4
1956  if text:
1957  self.fd.write('%s<condition>%s</condition>\n' %
1958  (' ' * self.indent, self._filterValue(text)))
1959  items = condition.GetItems()
1960  for b in items.keys():
1961  if len(items[b]) < 1:
1962  continue
1963  self.fd.write('%s<%s>\n' % (' ' * self.indent, b))
1964  self.indent += 4
1965  for item in items[b]:
1966  self.fd.write('%s<item>%d</item>\n' %
1967  (' ' * self.indent, item.GetId()))
1968  self.indent -= 4
1969  self.fd.write('%s</%s>\n' % (' ' * self.indent, b))
1970 
1971  self.indent -= 4
1972  self.fd.write('%s</if-else>\n' % (' ' * self.indent))
1973 
1975  def __init__(self, fd, model):
1976  """!Class for exporting model to Python script
1977 
1978  @param fd file desciptor
1979  """
1980  self.fd = fd
1981  self.model = model
1982  self.indent = 4
1983 
1984  self._writePython()
1985 
1986  def _writePython(self):
1987  """!Write model to file"""
1988  properties = self.model.GetProperties()
1989 
1990  self.fd.write(
1991 r"""#!/usr/bin/env python
1992 #
1993 #%s
1994 #
1995 # MODULE: %s
1996 #
1997 # AUTHOR(S): %s
1998 #
1999 # PURPOSE: %s
2000 #
2001 # DATE: %s
2002 #
2003 #%s
2004 """ % ('#' * 79,
2005  EncodeString(properties['name']),
2006  EncodeString(properties['author']),
2007  EncodeString('\n# '.join(properties['description'].splitlines())),
2008  time.asctime(),
2009  '#' * 79))
2010 
2011  self.fd.write(
2012 r"""
2013 import sys
2014 import os
2015 import atexit
2016 
2017 import grass.script as grass
2018 """)
2019 
2020  # cleanup()
2021  rast, vect, rast3d, msg = self.model.GetIntermediateData()
2022  self.fd.write(
2023 r"""
2024 def cleanup():
2025 """)
2026  if rast:
2027  self.fd.write(
2028 r""" grass.run_command('g.remove',
2029  rast=%s)
2030 """ % ','.join(map(lambda x: "'" + x + "'", rast)))
2031  if vect:
2032  self.fd.write(
2033 r""" grass.run_command('g.remove',
2034  vect = %s)
2035 """ % ','.join(map(lambda x: "'" + x + "'", vect)))
2036  if rast3d:
2037  self.fd.write(
2038 r""" grass.run_command('g.remove',
2039  rast3d = %s)
2040 """ % ','.join(map(lambda x: "'" + x + "'", rast3d)))
2041  if not rast and not vect and not rast3d:
2042  self.fd.write(' pass\n')
2043 
2044  self.fd.write("\ndef main():\n")
2045  for item in self.model.GetItems():
2046  self._writePythonItem(item)
2047 
2048  self.fd.write("\n return 0\n")
2049 
2050  self.fd.write(
2051 r"""
2052 if __name__ == "__main__":
2053  options, flags = grass.parser()
2054  atexit.register(cleanup)
2055  sys.exit(main())
2056 """)
2057 
2058  def _writePythonItem(self, item, ignoreBlock = True, variables = []):
2059  """!Write model object to Python file"""
2060  if isinstance(item, ModelAction):
2061  if ignoreBlock and item.GetBlockId(): # ignore items in loops of conditions
2062  return
2063  self._writePythonAction(item, variables = variables)
2064  elif isinstance(item, ModelLoop) or isinstance(item, ModelCondition):
2065  # substitute condition
2066  variables = self.model.GetVariables()
2067  cond = item.GetText()
2068  for variable in variables:
2069  pattern = re.compile('%' + variable)
2070  if pattern.search(cond):
2071  value = variables[variable].get('value', '')
2072  if variables[variable].get('type', 'string') == 'string':
2073  value = '"' + value + '"'
2074  cond = pattern.sub(value, cond)
2075  if isinstance(item, ModelLoop):
2076  condVar, condText = map(lambda x: x.strip(), re.split('\s*in\s*', cond))
2077  cond = "%sfor %s in " % (' ' * self.indent, condVar)
2078  if condText[0] == '`' and condText[-1] == '`':
2079  task = GUI(show = None).ParseCommand(cmd = utils.split(condText[1:-1]))
2080  cond += "grass.read_command("
2081  cond += self._getPythonActionCmd(task, len(cond), variables = [condVar]) + ".splitlines()"
2082  else:
2083  cond += condText
2084  self.fd.write('%s:\n' % cond)
2085  self.indent += 4
2086  for action in item.GetItems():
2087  self._writePythonItem(action, ignoreBlock = False, variables = [condVar])
2088  self.indent -= 4
2089  else: # ModelCondition
2090  self.fd.write('%sif %s:\n' % (' ' * self.indent, cond))
2091  self.indent += 4
2092  condItems = item.GetItems()
2093  for action in condItems['if']:
2094  self._writePythonItem(action, ignoreBlock = False)
2095  if condItems['else']:
2096  self.indent -= 4
2097  self.fd.write('%selse:\n' % (' ' * self.indent))
2098  self.indent += 4
2099  for action in condItems['else']:
2100  self._writePythonItem(action, ignoreBlock = False)
2101  self.indent += 4
2102 
2103  def _writePythonAction(self, item, variables = []):
2104  """!Write model action to Python file"""
2105  task = GUI(show = None).ParseCommand(cmd = item.GetLog(string = False, substitute = self.model.GetVariables()))
2106  strcmd = "%sgrass.run_command(" % (' ' * self.indent)
2107  self.fd.write(strcmd + self._getPythonActionCmd(task, len(strcmd), variables) + '\n')
2108 
2109  def _getPythonActionCmd(self, task, cmdIndent, variables = []):
2110  opts = task.get_options()
2111 
2112  ret = ''
2113  flags = ''
2114  params = list()
2115 
2116  for f in opts['flags']:
2117  if f.get('value', False):
2118  name = f.get('name', '')
2119  if len(name) > 1:
2120  params.append('%s = True' % name)
2121  else:
2122  flags += name
2123 
2124  for p in opts['params']:
2125  name = p.get('name', None)
2126  value = p.get('value', None)
2127  if name and value:
2128  ptype = p.get('type', 'string')
2129  if value[0] == '%':
2130  params.append("%s = %s" % (name, value[1:]))
2131  elif ptype == 'string':
2132  params.append('%s = "%s"' % (name, value))
2133  else:
2134  params.append("%s = %s" % (name, value))
2135 
2136  ret += '"%s"' % task.get_name()
2137  if flags:
2138  ret += ",\n%sflags = '%s'" % (' ' * cmdIndent, flags)
2139  if len(params) > 0:
2140  ret += ",\n"
2141  for opt in params[:-1]:
2142  ret += "%s%s,\n" % (' ' * cmdIndent, opt)
2143  ret += "%s%s)" % (' ' * cmdIndent, params[-1])
2144  else:
2145  ret += ")"
2146 
2147  return ret
2148 
2149 class ModelParamDialog(wx.Dialog):
2150  def __init__(self, parent, params, id = wx.ID_ANY, title = _("Model parameters"),
2151  style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
2152  """!Model parameters dialog
2153  """
2154  self.parent = parent
2155  self.params = params
2156  self.tasks = list() # list of tasks/pages
2157 
2158  wx.Dialog.__init__(self, parent = parent, id = id, title = title, style = style, **kwargs)
2159 
2160  self.notebook = GNotebook(parent = self,
2161  style = globalvar.FNPageDStyle)
2162 
2163  panel = self._createPages()
2164  wx.CallAfter(self.notebook.SetSelection, 0)
2165 
2166  # intermediate data?
2167  self.interData = wx.CheckBox(parent = self, label = _("Delete intermediate data when finish"))
2168  self.interData.SetValue(True)
2169  rast, vect, rast3d, msg = self.parent.GetModel().GetIntermediateData()
2170  if not rast and not vect and not rast3d:
2171  self.interData.Hide()
2172 
2173  self.btnCancel = wx.Button(parent = self, id = wx.ID_CANCEL)
2174  self.btnRun = wx.Button(parent = self, id = wx.ID_OK,
2175  label = _("&Run"))
2176  self.btnRun.SetDefault()
2177 
2178  self._layout()
2179 
2180  size = self.GetBestSize()
2181  self.SetMinSize(size)
2182  self.SetSize((size.width, size.height +
2183  panel.constrained_size[1] -
2184  panel.panelMinHeight))
2185 
2186  def _layout(self):
2187  btnSizer = wx.StdDialogButtonSizer()
2188  btnSizer.AddButton(self.btnCancel)
2189  btnSizer.AddButton(self.btnRun)
2190  btnSizer.Realize()
2191 
2192  mainSizer = wx.BoxSizer(wx.VERTICAL)
2193  mainSizer.Add(item = self.notebook, proportion = 1,
2194  flag = wx.EXPAND)
2195  if self.interData.IsShown():
2196  mainSizer.Add(item = self.interData, proportion = 0,
2197  flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
2198 
2199  mainSizer.Add(item = wx.StaticLine(parent = self, id = wx.ID_ANY,
2200  style = wx.LI_HORIZONTAL),
2201  proportion = 0,
2202  flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border = 5)
2203 
2204  mainSizer.Add(item = btnSizer, proportion = 0,
2205  flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
2206 
2207  self.SetSizer(mainSizer)
2208  mainSizer.Fit(self)
2209 
2210  def _createPages(self):
2211  """!Create for each parameterized module its own page"""
2212  nameOrdered = [''] * len(self.params.keys())
2213  for name, params in self.params.iteritems():
2214  nameOrdered[params['idx']] = name
2215  for name in nameOrdered:
2216  params = self.params[name]
2217  panel = self._createPage(name, params)
2218  if name == 'variables':
2219  name = _('Variables')
2220  self.notebook.AddPage(page = panel, text = name)
2221 
2222  return panel
2223 
2224  def _createPage(self, name, params):
2225  """!Define notebook page"""
2226  if name in globalvar.grassCmd:
2227  task = gtask.grassTask(name)
2228  else:
2229  task = gtask.grassTask()
2230  task.flags = params['flags']
2231  task.params = params['params']
2232 
2233  panel = CmdPanel(parent = self, id = wx.ID_ANY, task = task)
2234  self.tasks.append(task)
2235 
2236  return panel
2237 
2238  def GetErrors(self):
2239  """!Check for errors, get list of messages"""
2240  errList = list()
2241  for task in self.tasks:
2242  errList += task.get_cmd_error()
2243 
2244  return errList
2245 
2247  """!Check if to detele intermediate data"""
2248  if self.interData.IsShown() and self.interData.IsChecked():
2249  return True
2250 
2251  return False
def _processVariables(self)
Process model variables.
Definition: model.py:1549
variablesParams
Definition: model.py:63
def GetItems
Get list of model items.
Definition: model.py:71
def _layout(self)
Definition: model.py:2186
def GetWidth(self)
Get object width.
Definition: model.py:1458
def DeleteIntermediateData(self, log)
Detele intermediate data.
Definition: model.py:632
def SetName(self, param)
Definition: model.py:1320
def __del__(self)
Definition: model.py:1263
def LoadModel(self, filename)
Load model definition stored in GRASS Model XML file (gxm)
Definition: model.py:221
def _processProperties(self)
Process model properties.
Definition: model.py:1528
def __init__(self, fd, model)
Class for exporting model to Python script.
Definition: model.py:1975
def __init__(self, tree)
A ElementTree handler for the GXM XML file, as defined in grass-gxm.dtd.
Definition: model.py:1477
wxGUI command interface
def _footer(self)
Write footer.
Definition: model.py:1782
def SetValue(self, value)
Set value.
Definition: model.py:1166
def _processLoops(self)
Process model loops.
Definition: model.py:1699
def FindAction(self, aId)
Find action by id.
Definition: model.py:177
def Update(self)
Update action.
Definition: model.py:1244
def _filterValue(self, value)
Make value XML-valid.
Definition: model.py:1768
def GetPrompt(self)
Get prompt.
Definition: model.py:1151
def _items(self)
Write actions/loops/conditions.
Definition: model.py:1838
def Update(self)
Definition: model.py:1410
properties
Definition: model.py:58
def SetVariables(self, data)
Set model variables.
Definition: model.py:133
def _createPage(self, name, params)
Define notebook page.
Definition: model.py:2224
def GetCanvas(self)
Get canvas or None.
Definition: model.py:67
Generic class for writing model file.
Definition: model.py:1740
def _setPen(self)
Set pen.
Definition: model.py:1308
def ResetShapes(self)
Reset related objects.
Definition: model.py:1294
def __init__
Definition: model.py:54
def GetPropDialog(self)
Get properties dialog.
Definition: model.py:1184
def SetParams(self, params)
Set dictionary of parameters.
Definition: model.py:1007
def _processTask(self, node)
Process task.
Definition: model.py:1653
Action class (GRASS module)
Definition: model.py:844
def _setPen(self)
Set pen.
Definition: model.py:907
def IsEnabled(self)
Get True if action is enabled, otherwise False.
Definition: model.py:795
def GetItem(self, aId)
Get item of given id.
Definition: model.py:86
def GetParams
Get dictionary of parameters.
Definition: model.py:996
def GetNumItems
Get number of items.
Definition: model.py:101
def GetValue(self)
Get value.
Definition: model.py:1162
def _setBrush(self)
Set brush.
Definition: model.py:1389
def Update
Update action.
Definition: model.py:1065
def _condition(self, condition)
Write conditions.
Definition: model.py:1948
Core GUI widgets.
def FindData(self, value, prompt)
Find data item in the model.
Definition: model.py:205
def GetRelations
Get list of relations.
Definition: model.py:776
def _properties(self)
Write model properties.
Definition: model.py:1798
Class representing the model.
Definition: model.py:52
def __init__
Abstract class for loops and conditions.
Definition: model.py:1324
def SetItems(self, items)
Set items (id)
Definition: model.py:1417
def _getDim(self, node)
Get position and size of shape.
Definition: model.py:1597
def __init__
Defines a loop.
Definition: model.py:1365
def GetName(self)
Get name.
Definition: model.py:1413
def GetText(self)
Get loop text.
Definition: model.py:1331
def GetProperties(self)
Get model properties.
Definition: model.py:122
def AddRelation(self, rel)
Record new relation.
Definition: model.py:771
def SetText(self, cond)
Set loop text (condition)
Definition: model.py:1343
def RunAction
Run given action.
Definition: model.py:467
def GetName(self)
Get list of names.
Definition: model.py:1143
def GetLog
Get logging info.
Definition: model.py:1133
def SetControlPoints(self, points)
Set control points.
Definition: model.py:1300
def MergeParams(self, params)
Merge dictionary of parameters.
Definition: model.py:1012
def AddItem(self, newItem)
Add item to the list.
Definition: model.py:340
def SetPrompt(self, prompt)
Set prompt.
Definition: model.py:1155
def GetLog(self)
Get log info.
Definition: model.py:1349
def Enable
Enable/disable action.
Definition: model.py:1401
def _window(self)
Write window properties.
Definition: model.py:1787
def OnDraw(self, dc)
Definition: model.py:1122
def FindData(self, name)
Find data item by name.
Definition: model.py:1056
def _processWindow(self)
Process window properties.
Definition: model.py:1519
def _variables(self)
Write model variables.
Definition: model.py:1817
def GetItems(self)
Get items (id)
Definition: model.py:1335
def _loop(self, loop)
Write loops.
Definition: model.py:1932
def GetHeight(self)
Get object height.
Definition: model.py:1462
def OnDraw(self, dc)
Draw relation.
Definition: model.py:1315
def IsParameterized(self)
Return True if model is parameterized.
Definition: model.py:678
def AddRelation(self, rel)
Record relation.
Definition: model.py:1356
def GetErrors(self)
Check for errors, get list of messages.
Definition: model.py:2238
def _substituteFile
Subsitute variables in command file inputs.
Definition: model.py:394
def SetIntermediate(self, im)
Set intermediate flag.
Definition: model.py:1118
def split(s)
Platform spefic shlex.split.
Definition: core/utils.py:37
def __del__(self)
Definition: model.py:764
def IsValid(self)
Definition: model.py:353
def UnSetBlock(self, item)
Remove object from the block (loop/consition)
Definition: model.py:816
def _header(self)
Write header.
Definition: model.py:1775
def Update(self)
Definition: model.py:804
def IsValid(self)
Check validity (all required parameters set)
Definition: model.py:1048
def GetFrom(self)
Get id of 'from' shape.
Definition: model.py:1269
Data - action relation.
Definition: model.py:1250
def Enable
Enable/disable action.
Definition: model.py:799
def _processConditions(self)
Process model conditions.
Definition: model.py:1717
def _setPen(self)
Set pen.
Definition: model.py:1209
def Clear(self)
Clear object, remove rels.
Definition: model.py:1360
def GetLog
Get logging info.
Definition: model.py:939
def SetId(self, id)
Set loop id.
Definition: model.py:1339
def _createPages(self)
Create for each parameterized module its own page.
Definition: model.py:2210
def IsIntermediate(self)
Checks if data item is intermediate.
Definition: model.py:1114
def _processData(self)
Process model file.
Definition: model.py:1618
def _processActions(self)
Process model file.
Definition: model.py:1575
def GetBlockId(self)
Get list of related ids which defines block.
Definition: model.py:833
def Validate(self)
Validate model, return None if model is valid otherwise error string.
Definition: model.py:360
def GetDefaultEncoding
Get default system encoding.
Definition: gcmd.py:709
def GetNextId(self)
Get next id (data ignored)
Definition: model.py:108
def GetName(self)
Get parameter name.
Definition: model.py:1290
def EncodeString(string)
Return encoded string using system locales.
Definition: core/utils.py:721
def __init__(self, parent, params, id=wx.ID_ANY, title=_("Model parameters"), style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER, kwargs)
Model parameters dialog.
Definition: model.py:2151
def _processVariable(self, pnode, name, key)
Process given variable.
Definition: model.py:1562
def GetTask(self)
Get grassTask instance.
Definition: model.py:1003
def __init__(self, fd, model)
Definition: model.py:1742
def CmdToTuple(cmd)
Convert command list to tuple for gcmd.RunCommand()
Definition: core/utils.py:527
def GetName(self)
Get name.
Definition: model.py:1454
def _filterValue(self, value)
Filter value.
Definition: model.py:1498
def Reset(self)
Reset model.
Definition: model.py:137
def RemoveItem(self, item)
Remove item from model.
Definition: model.py:141
def Parameterize(self)
Return parameterized options.
Definition: model.py:685
def _action(self, action)
Write actions.
Definition: model.py:1848
def GetControlPoints(self)
Get list of control points.
Definition: model.py:1304
def GetData(self)
Get list of data items.
Definition: model.py:186
def SetId(self, id)
Set id.
Definition: model.py:919
def GetId(self)
Get id.
Definition: model.py:767
def GetBlock(self)
Get list of related ModelObject(s) which defines block (loop/condition)
Definition: model.py:825
def DeleteIntermediateData(self)
Check if to detele intermediate data.
Definition: model.py:2246
def GetData(self)
Get related ModelData instance.
Definition: model.py:1277
def SetBlock(self, item)
Add object to the block (loop/condition)
Definition: model.py:807
def GetTo(self)
Get id of 'to' shape.
Definition: model.py:1273
def Run
Run model.
Definition: model.py:493
def EncodeString(string)
Return encoded string using system locales.
Definition: gcmd.py:91
def GetPropDialog(self)
Get properties dialog.
Definition: model.py:935
def normalize_whitespace(text)
Remove redundant whitespace from a string.
Definition: core/utils.py:33
def _setBrush(self)
Set brush.
Definition: model.py:1192
def _writePythonItem
Write model object to Python file.
Definition: model.py:2058
def RunCommand(prog, flags="", overwrite=False, quiet=False, verbose=False, parent=None, read=False, stdin=None, getErrorMsg=False, kwargs)
Run GRASS command.
Definition: gcmd.py:633
def Update(self)
Update model.
Definition: model.py:673
def SetValid(self, options)
Set validity for action.
Definition: model.py:1023
def _setText(self)
Update text.
Definition: model.py:1232
def _processItems(self)
Process model items (actions, loops, conditions)
Definition: model.py:1569
Process GRASS model file (gxm)
Definition: model.py:1475
def OnDraw(self, dc)
Draw action in canvas.
Definition: model.py:1073
Default GUI settings.
def _data(self, dataList)
Write data.
Definition: model.py:1890
tuple range
Definition: tools.py:1406
def OnPrepare(self, item, params)
Definition: model.py:464
def SetPropDialog(self, win)
Get properties dialog.
Definition: model.py:1188
def _processProperty(self, pnode, name)
Process given property.
Definition: model.py:1541
def _setBrush
Set brush.
Definition: model.py:889
def GetVariables
Get model variables.
Definition: model.py:126
def _writePython(self)
Write model to file.
Definition: model.py:1986
def SetProperties(self, params, propwin)
Record properties dialog.
Definition: model.py:929
def SetItems
Set items (id)
Definition: model.py:1466
def GetIntermediateData(self)
Get info about intermediate data.
Definition: model.py:643
def _writePythonAction
Write model action to Python file.
Definition: model.py:2103
def GetName(self)
Get name.
Definition: model.py:988
def _getNodeText
Get node text.
Definition: model.py:1508