GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
mcalc_builder.py
Go to the documentation of this file.
1 """!
2 @package modules::mcalc_builder
3 
4 @brief Map calculator, GUI wrapper for r.mapcalc
5 
6 Classes:
7  - mcalc_builder::MapCalcFrame
8 
9 (C) 2008, 2011-2012 by the GRASS Development Team
10 
11 This program is free software under the GNU General Public License
12 (>=v2). Read the file COPYING that comes with GRASS for details.
13 
14 @author Michael Barton, Arizona State University
15 @author Martin Landa <landa.martin gmail.com>
16 @author Tim Michelsen (load/save expression)
17 """
18 
19 import os
20 import sys
21 import re
22 
23 import wx
24 import grass.script as grass
25 
26 if __name__ == "__main__":
27  sys.path.append(os.path.join(os.getenv('GISBASE'), 'etc', 'wxpython'))
28 
29 from core import globalvar
30 from core.gcmd import GError, RunCommand
31 from gui_core.gselect import Select
32 from core.settings import UserSettings
33 
34 
35 class MapCalcFrame(wx.Frame):
36  """!Mapcalc Frame class. Calculator-style window to create and run
37  r(3).mapcalc statements.
38  """
39  def __init__(self, parent, cmd, id = wx.ID_ANY,
40  style = wx.DEFAULT_FRAME_STYLE | wx.RESIZE_BORDER, **kwargs):
41  self.parent = parent
42  if self.parent:
43  self.log = self.parent.GetLogWindow()
44  else:
45  self.log = None
46 
47  # grass command
48  self.cmd = cmd
49 
50  if self.cmd == 'r.mapcalc':
51  self.rast3d = False
52  title = _('GRASS GIS Raster Map Calculator')
53  if self.cmd == 'r3.mapcalc':
54  self.rast3d = True
55  title = _('GRASS GIS 3D Raster Map Calculator')
56 
57  wx.Frame.__init__(self, parent, id = id, title = title, **kwargs)
58  self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
59 
60  self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
61  self.CreateStatusBar()
62 
63  #
64  # variables
65  #
66  self.heading = _('mapcalc statement')
67  self.funct_dict = {
68  'abs(x)':'abs()',
69  'acos(x)':'acos()',
70  'asin(x)':'asin()',
71  'atan(x)':'atan()',
72  'atan(x,y)':'atan( , )',
73  'cos(x)':'cos()',
74  'double(x)':'double()',
75  'eval([x,y,...,]z)':'eval()',
76  'exp(x)':'exp()',
77  'exp(x,y)':'exp( , )',
78  'float(x)':'float()',
79  'graph(x,x1,y1[x2,y2..])':'graph( , , )',
80  'if(x)':'if()',
81  'if(x,a)':'if( , )',
82  'if(x,a,b)':'if( , , )',
83  'if(x,a,b,c)':'if( , , , )',
84  'int(x)':'int()',
85  'isnull(x)':'isnull()',
86  'log(x)':'log(',
87  'log(x,b)':'log( , )',
88  'max(x,y[,z...])':'max( , )',
89  'median(x,y[,z...])':'median( , )',
90  'min(x,y[,z...])':'min( , )',
91  'mode(x,y[,z...])':'mode( , )',
92  'not(x)':'not()',
93  'pow(x,y)':'pow( , )',
94  'rand(a,b)':'rand( , )',
95  'round(x)':'round()',
96  'sin(x)':'sin()',
97  'sqrt(x)':'sqrt()',
98  'tan(x)':'tan()',
99  'xor(x,y)':'xor( , )',
100  'row()':'row()',
101  'col()':'col()',
102  'x()':'x()',
103  'y()':'y()',
104  'ewres()':'ewres()',
105  'nsres()':'nsres()',
106  'null()':'null()'
107  }
108 
109  if self.rast3d:
110  self.funct_dict['z()'] = 'z()'
111  self.funct_dict['tbres()'] = 'tbres()'
112  element = 'rast3d'
113  else:
114  element = 'cell'
115 
116  # characters which can be in raster map name but the map name must be then quoted
117  self.charactersToQuote = '+-&!<>%~?^|'
118  # stores last typed map name in Select widget to distinguish typing from selection
119  self.lastMapName = ''
120 
121  self.operatorBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
122  label=" %s " % _('Operators'))
123  self.outputBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
124  label=" %s " % _('Output'))
125  self.operandBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
126  label=" %s " % _('Operands'))
127  self.expressBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
128  label=" %s " % _('Expression'))
129 
130  #
131  # Buttons
132  #
133  self.btn_clear = wx.Button(parent = self.panel, id = wx.ID_CLEAR)
134  self.btn_help = wx.Button(parent = self.panel, id = wx.ID_HELP)
135  self.btn_run = wx.Button(parent = self.panel, id = wx.ID_ANY, label = _("&Run"))
136  self.btn_run.SetForegroundColour(wx.Colour(35, 142, 35))
137  self.btn_run.SetDefault()
138  self.btn_close = wx.Button(parent = self.panel, id = wx.ID_CLOSE)
139  self.btn_save = wx.Button(parent = self.panel, id = wx.ID_SAVE)
140  self.btn_save.SetToolTipString(_('Save expression to file'))
141  self.btn_load = wx.Button(parent = self.panel, id = wx.ID_ANY,
142  label = _("&Load"))
143  self.btn_load.SetToolTipString(_('Load expression from file'))
144 
145  self.btn = dict()
146  self.btn['pow'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "^")
147  self.btn['pow'].SetToolTipString(_('exponent'))
148  self.btn['div'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "/")
149  self.btn['div'].SetToolTipString(_('divide'))
150  self.btn['add'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "+")
151  self.btn['add'].SetToolTipString(_('add'))
152  self.btn['minus'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "-")
153  self.btn['minus'].SetToolTipString(_('subtract'))
154  self.btn['mod'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "%")
155  self.btn['mod'].SetToolTipString(_('modulus'))
156  self.btn['mult'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "*")
157  self.btn['mult'].SetToolTipString(_('multiply'))
158 
159  self.btn['parenl'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "(")
160  self.btn['parenr'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = ")")
161  self.btn['lshift'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "<<")
162  self.btn['lshift'].SetToolTipString(_('left shift'))
163  self.btn['rshift'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = ">>")
164  self.btn['rshift'].SetToolTipString(_('right shift'))
165  self.btn['rshiftu'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = ">>>")
166  self.btn['rshiftu'].SetToolTipString(_('right shift (unsigned)'))
167  self.btn['gt'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = ">")
168  self.btn['gt'].SetToolTipString(_('greater than'))
169  self.btn['gteq'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = ">=")
170  self.btn['gteq'].SetToolTipString(_('greater than or equal to'))
171  self.btn['lt'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "<")
172  self.btn['lt'].SetToolTipString(_('less than'))
173  self.btn['lteq'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "<=")
174  self.btn['lteq'].SetToolTipString(_('less than or equal to'))
175  self.btn['eq'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "==")
176  self.btn['eq'].SetToolTipString(_('equal to'))
177  self.btn['noteq'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "!=")
178  self.btn['noteq'].SetToolTipString(_('not equal to'))
179 
180  self.btn['compl'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "~")
181  self.btn['compl'].SetToolTipString(_('one\'s complement'))
182  self.btn['not'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "!")
183  self.btn['not'].SetToolTipString(_('NOT'))
184  self.btn['andbit'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = '&&')
185  self.btn['andbit'].SetToolTipString(_('bitwise AND'))
186  self.btn['orbit'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "|")
187  self.btn['orbit'].SetToolTipString(_('bitwise OR'))
188  self.btn['and'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "&&&&")
189  self.btn['and'].SetToolTipString(_('logical AND'))
190  self.btn['andnull'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "&&&&&&")
191  self.btn['andnull'].SetToolTipString(_('logical AND (ignores NULLs)'))
192  self.btn['or'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "||")
193  self.btn['or'].SetToolTipString(_('logical OR'))
194  self.btn['ornull'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "|||")
195  self.btn['ornull'].SetToolTipString(_('logical OR (ignores NULLs)'))
196  self.btn['cond'] = wx.Button(parent = self.panel, id = wx.ID_ANY, label = "a ? b : c")
197  self.btn['cond'].SetToolTipString(_('conditional'))
198 
199  #
200  # Text area
201  #
202  self.text_mcalc = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY, size = (-1, 75),
203  style = wx.TE_MULTILINE)
204  wx.CallAfter(self.text_mcalc.SetFocus)
205 
206  #
207  # Map and function insertion text and ComboBoxes
208  self.newmaplabel = wx.StaticText(parent = self.panel, id = wx.ID_ANY)
209  if self.rast3d:
210  self.newmaplabel.SetLabel(_('Name for new 3D raster map to create'))
211  else:
212  self.newmaplabel.SetLabel(_('Name for new raster map to create'))
213  self.newmaptxt = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY, size=(250, -1))
214  self.mapsellabel = wx.StaticText(parent = self.panel, id = wx.ID_ANY)
215  if self.rast3d:
216  self.mapsellabel.SetLabel(_('Insert existing 3D raster map'))
217  else:
218  self.mapsellabel.SetLabel(_('Insert existing raster map'))
219  self.mapselect = Select(parent = self.panel, id = wx.ID_ANY, size = (250, -1),
220  type = element, multiple = False)
221  self.functlabel = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
222  label = _('Insert mapcalc function'))
223  self.function = wx.ComboBox(parent = self.panel, id = wx.ID_ANY,
224  size = (250, -1), choices = sorted(self.funct_dict.keys()),
225  style = wx.CB_DROPDOWN |
226  wx.CB_READONLY | wx.TE_PROCESS_ENTER)
227 
228  self.addbox = wx.CheckBox(parent=self.panel,
229  label=_('Add created raster map into layer tree'), style = wx.NO_BORDER)
230  self.addbox.SetValue(UserSettings.Get(group='cmd', key='addNewLayer', subkey='enabled'))
231  if not self.parent or self.parent.GetName() != 'LayerManager':
232  self.addbox.Hide()
233 
234  #
235  # Bindings
236  #
237  for btn in self.btn.keys():
238  self.btn[btn].Bind(wx.EVT_BUTTON, self.AddMark)
239 
240  self.btn_close.Bind(wx.EVT_BUTTON, self.OnClose)
241  self.btn_clear.Bind(wx.EVT_BUTTON, self.OnClear)
242  self.btn_run.Bind(wx.EVT_BUTTON, self.OnMCalcRun)
243  self.btn_help.Bind(wx.EVT_BUTTON, self.OnHelp)
244  self.btn_save.Bind(wx.EVT_BUTTON, self.OnSaveExpression)
245  self.btn_load.Bind(wx.EVT_BUTTON, self.OnLoadExpression)
246 
247  self.mapselect.Bind(wx.EVT_TEXT, self.OnSelectTextEvt)
248  self.function.Bind(wx.EVT_COMBOBOX, self._return_funct)
249  self.function.Bind(wx.EVT_TEXT_ENTER, self.OnSelect)
250  self.newmaptxt.Bind(wx.EVT_TEXT, self.OnUpdateStatusBar)
251  self.text_mcalc.Bind(wx.EVT_TEXT, self.OnUpdateStatusBar)
252 
253  self._layout()
254 
255  self.SetMinSize(self.GetBestSize())
256 
257  def _return_funct(self,event):
258  i = event.GetString()
259  self._addSomething(self.funct_dict[i])
260 
261  def _layout(self):
262  sizer = wx.BoxSizer(wx.VERTICAL)
263 
264  controlSizer = wx.BoxSizer(wx.HORIZONTAL)
265  operatorSizer = wx.StaticBoxSizer(self.operatorBox, wx.HORIZONTAL)
266  outOpeSizer = wx.BoxSizer(wx.VERTICAL)
267 
268  buttonSizer1 = wx.GridBagSizer(5, 1)
269  buttonSizer1.Add(item = self.btn['add'], pos = (0,0))
270  buttonSizer1.Add(item = self.btn['minus'], pos = (0,1))
271  buttonSizer1.Add(item = self.btn['mod'], pos = (5,0))
272  buttonSizer1.Add(item = self.btn['mult'], pos = (1,0))
273  buttonSizer1.Add(item = self.btn['div'], pos = (1,1))
274  buttonSizer1.Add(item = self.btn['pow'], pos = (5,1))
275  buttonSizer1.Add(item = self.btn['gt'], pos = (2,0))
276  buttonSizer1.Add(item = self.btn['gteq'], pos = (2,1))
277  buttonSizer1.Add(item = self.btn['eq'], pos = (4,0))
278  buttonSizer1.Add(item = self.btn['lt'], pos = (3,0))
279  buttonSizer1.Add(item = self.btn['lteq'], pos = (3,1))
280  buttonSizer1.Add(item = self.btn['noteq'], pos = (4,1))
281 
282  buttonSizer2 = wx.GridBagSizer(5, 1)
283  buttonSizer2.Add(item = self.btn['and'], pos = (0,0))
284  buttonSizer2.Add(item = self.btn['andbit'], pos = (1,0))
285  buttonSizer2.Add(item = self.btn['andnull'], pos = (2,0))
286  buttonSizer2.Add(item = self.btn['or'], pos = (0,1))
287  buttonSizer2.Add(item = self.btn['orbit'], pos = (1,1))
288  buttonSizer2.Add(item = self.btn['ornull'], pos = (2,1))
289  buttonSizer2.Add(item = self.btn['lshift'], pos = (3,0))
290  buttonSizer2.Add(item = self.btn['rshift'], pos = (3,1))
291  buttonSizer2.Add(item = self.btn['rshiftu'], pos = (4,0))
292  buttonSizer2.Add(item = self.btn['cond'], pos = (5,0))
293  buttonSizer2.Add(item = self.btn['compl'], pos = (5,1))
294  buttonSizer2.Add(item = self.btn['not'], pos = (4,1))
295 
296  outputSizer = wx.StaticBoxSizer(self.outputBox, wx.VERTICAL)
297  outputSizer.Add(item = self.newmaplabel,
298  flag = wx.ALIGN_CENTER | wx.BOTTOM | wx.TOP, border = 5)
299  outputSizer.Add(item = self.newmaptxt,
300  flag = wx.EXPAND)
301 
302  operandSizer = wx.StaticBoxSizer(self.operandBox, wx.HORIZONTAL)
303  buttonSizer3 = wx.GridBagSizer(7, 1)
304  buttonSizer3.Add(item = self.functlabel, pos = (0,0),
305  span = (1,2), flag = wx.ALIGN_CENTER)
306  buttonSizer3.Add(item = self.function, pos = (1,0),
307  span = (1,2))
308  buttonSizer3.Add(item = self.mapsellabel, pos = (2,0),
309  span = (1,2), flag = wx.ALIGN_CENTER)
310  buttonSizer3.Add(item = self.mapselect, pos = (3,0),
311  span = (1,2))
312  threebutton = wx.GridBagSizer(1, 2)
313  threebutton.Add(item = self.btn['parenl'], pos = (0,0),
314  span = (1,1), flag = wx.ALIGN_LEFT)
315  threebutton.Add(item = self.btn['parenr'], pos = (0,1),
316  span = (1,1), flag = wx.ALIGN_CENTER)
317  threebutton.Add(item = self.btn_clear, pos = (0,2),
318  span = (1,1), flag = wx.ALIGN_RIGHT)
319  buttonSizer3.Add(item = threebutton, pos = (4,0),
320  span = (1,1), flag = wx.ALIGN_CENTER)
321 
322  buttonSizer4 = wx.BoxSizer(wx.HORIZONTAL)
323  buttonSizer4.AddSpacer(10)
324  buttonSizer4.Add(item = self.btn_load,
325  flag = wx.ALL, border = 5)
326  buttonSizer4.Add(item = self.btn_save,
327  flag = wx.ALL, border = 5)
328  buttonSizer4.AddSpacer(30)
329  buttonSizer4.Add(item = self.btn_help,
330  flag = wx.ALL, border = 5)
331  buttonSizer4.Add(item = self.btn_run,
332  flag = wx.ALL, border = 5)
333  buttonSizer4.Add(item = self.btn_close,
334  flag = wx.ALL, border = 5)
335 
336  operatorSizer.Add(item = buttonSizer1, proportion = 0,
337  flag = wx.ALL | wx.EXPAND, border = 5)
338  operatorSizer.Add(item = buttonSizer2, proportion = 0,
339  flag = wx.TOP | wx.BOTTOM | wx.RIGHT | wx.EXPAND, border = 5)
340 
341  operandSizer.Add(item = buttonSizer3, proportion = 0,
342  flag = wx.TOP | wx.BOTTOM | wx.RIGHT, border = 5)
343 
344  controlSizer.Add(item = operatorSizer, proportion = 1,
345  flag = wx.RIGHT | wx.EXPAND, border = 5)
346  outOpeSizer.Add(item = outputSizer, proportion = 0,
347  flag = wx.EXPAND)
348  outOpeSizer.Add(item = operandSizer, proportion = 1,
349  flag = wx.EXPAND | wx.TOP, border = 5)
350  controlSizer.Add(item = outOpeSizer, proportion = 0,
351  flag = wx.EXPAND)
352 
353  expressSizer = wx.StaticBoxSizer(self.expressBox, wx.HORIZONTAL)
354  expressSizer.Add(item = self.text_mcalc, proportion = 1,
355  flag = wx.EXPAND)
356 
357  sizer.Add(item = controlSizer, proportion = 0,
358  flag = wx.EXPAND | wx.ALL,
359  border = 5)
360  sizer.Add(item = expressSizer, proportion = 1,
361  flag = wx.EXPAND | wx.LEFT | wx.RIGHT,
362  border = 5)
363  sizer.Add(item = buttonSizer4, proportion = 0,
364  flag = wx.ALIGN_RIGHT | wx.ALL, border = 3)
365  if self.addbox.IsShown():
366  sizer.Add(item = self.addbox, proportion = 0,
367  flag = wx.LEFT | wx.RIGHT,
368  border = 5)
369 
370  self.panel.SetAutoLayout(True)
371  self.panel.SetSizer(sizer)
372  sizer.Fit(self.panel)
373 
374  self.Layout()
375 
376  def AddMark(self,event):
377  """!Sends operators to insertion method
378  """
379  if event.GetId() == self.btn['compl'].GetId(): mark = "~"
380  elif event.GetId() == self.btn['not'].GetId(): mark = "!"
381  elif event.GetId() == self.btn['pow'].GetId(): mark = "^"
382  elif event.GetId() == self.btn['div'].GetId(): mark = "/"
383  elif event.GetId() == self.btn['add'].GetId(): mark = "+"
384  elif event.GetId() == self.btn['minus'].GetId(): mark = "-"
385  elif event.GetId() == self.btn['mod'].GetId(): mark = "%"
386  elif event.GetId() == self.btn['mult'].GetId(): mark = "*"
387  elif event.GetId() == self.btn['lshift'].GetId(): mark = "<<"
388  elif event.GetId() == self.btn['rshift'].GetId(): mark = ">>"
389  elif event.GetId() == self.btn['rshiftu'].GetId(): mark = ">>>"
390  elif event.GetId() == self.btn['gt'].GetId(): mark = ">"
391  elif event.GetId() == self.btn['gteq'].GetId(): mark = ">="
392  elif event.GetId() == self.btn['lt'].GetId(): mark = "<"
393  elif event.GetId() == self.btn['lteq'].GetId(): mark = "<="
394  elif event.GetId() == self.btn['eq'].GetId(): mark = "=="
395  elif event.GetId() == self.btn['noteq'].GetId(): mark = "!="
396  elif event.GetId() == self.btn['andbit'].GetId(): mark = "&"
397  elif event.GetId() == self.btn['orbit'].GetId(): mark = "|"
398  elif event.GetId() == self.btn['or'].GetId(): mark = "||"
399  elif event.GetId() == self.btn['ornull'].GetId(): mark = "|||"
400  elif event.GetId() == self.btn['and'].GetId(): mark = "&&"
401  elif event.GetId() == self.btn['andnull'].GetId(): mark = "&&&"
402  elif event.GetId() == self.btn['cond'].GetId(): mark = " ? : "
403  elif event.GetId() == self.btn['parenl'].GetId(): mark = "("
404  elif event.GetId() == self.btn['parenr'].GetId(): mark = ")"
405  self._addSomething(mark)
406 
407  def OnSelectTextEvt(self, event):
408  """!Checks if user is typing or the event was emited by map selection.
409  Prevents from changing focus.
410  """
411  item = event.GetString()
412  if not (abs(len(item) - len(self.lastMapName)) == 1 and \
413  self.lastMapName in item or item in self.lastMapName):
414  self.OnSelect(event)
415  self.lastMapName = item
416 
417  def OnSelect(self, event):
418  """!Gets raster map or function selection and send it to
419  insertion method.
420 
421  Checks for characters which can be in raster map name but
422  the raster map name must be then quoted.
423  """
424  item = event.GetString().strip()
425  if any((char in item) for char in self.charactersToQuote):
426  item = '"' + item + '"'
427  self._addSomething(item)
428 
429  def OnUpdateStatusBar(self, event):
430  """!Update statusbar text"""
431  expr = self.text_mcalc.GetValue().strip().replace("\n", " ")
432  cmd = 'r.mapcalc'
433  if self.rast3d:
434  cmd = 'r3.mapcalc'
435  self.SetStatusText("{cmd} '{new} = {expr}'".format(cmd=cmd, expr=expr,
436  new=self.newmaptxt.GetValue()))
437  event.Skip()
438 
439  def _addSomething(self, what):
440  """!Inserts operators, map names, and functions into text area
441  """
442  self.text_mcalc.SetFocus()
443  mcalcstr = self.text_mcalc.GetValue()
444  position = self.text_mcalc.GetInsertionPoint()
445 
446  newmcalcstr = mcalcstr[:position]
447 
448  position_offset = 0
449  try:
450  if newmcalcstr[-1] != ' ':
451  newmcalcstr += ' '
452  position_offset += 1
453  except:
454  pass
455 
456  newmcalcstr += what + ' ' + mcalcstr[position:]
457 
458  self.text_mcalc.SetValue(newmcalcstr)
459  if len(what) > 1:
460  match = re.search(pattern="\(.*\)", string=what)
461  if match:
462  position_offset += match.start() + 1
463  else:
464  position_offset += len(what)
465 
466  self.text_mcalc.SetInsertionPoint(position + position_offset)
467  self.text_mcalc.Update()
468 
469  def OnMCalcRun(self,event):
470  """!Builds and runs r.mapcalc statement
471  """
472  name = self.newmaptxt.GetValue().strip()
473  if not name:
474  GError(parent = self,
475  message = _("You must enter the name of "
476  "a new raster map to create."))
477  return
478 
479  if not (name[0] == '"' and name[-1] == '"') and any((char in name) for char in self.charactersToQuote):
480  name = '"' + name + '"'
481 
482  expr = self.text_mcalc.GetValue().strip().replace("\n", " ")
483  if not expr:
484  GError(parent = self,
485  message = _("You must enter an expression "
486  "to create a new raster map."))
487  return
488 
489  if self.log:
490  cmd = [self.cmd, str('%s = %s' % (name, expr))]
491  self.log.RunCmd(cmd, onDone = self.OnDone)
492  self.parent.Raise()
493  else:
494  RunCommand(self.cmd,
495  **{name: expr})
496 
497  def OnDone(self, cmd, returncode):
498  """!Add create map to the layer tree"""
499  if not self.addbox.IsChecked():
500  return
501  name = self.newmaptxt.GetValue().strip(' "') + '@' + grass.gisenv()['MAPSET']
502  ltype = 'raster'
503  lcmd = 'd.rast'
504  if self.rast3d:
505  ltype = '3d-raster'
506  lcmd = 'd.rast3d.py'
507  mapTree = self.parent.GetLayerTree()
508  if not mapTree.GetMap().GetListOfLayers(l_name = name):
509  mapTree.AddLayer(ltype = ltype,
510  lname = name,
511  lcmd = [lcmd, 'map=%s' % name],
512  multiple = False)
513 
514  display = self.parent.GetLayerTree().GetMapDisplay()
515  if display and display.IsAutoRendered():
516  display.GetWindow().UpdateMap(render = True)
517 
518  def OnSaveExpression(self, event):
519  """!Saves expression to file
520  """
521  mctxt = self.newmaptxt.GetValue() + ' = ' + self.text_mcalc.GetValue() + os.linesep
522 
523  #dialog
524  dlg = wx.FileDialog(parent = self,
525  message = _("Choose a file name to save the expression"),
526  wildcard = _("Expression file (*)|*"),
527  style = wx.SAVE | wx.FD_OVERWRITE_PROMPT)
528  if dlg.ShowModal() == wx.ID_OK:
529  path = dlg.GetPath()
530  if not path:
531  dlg.Destroy()
532  return
533 
534  try:
535  fobj = open(path, 'w')
536  fobj.write(mctxt)
537  finally:
538  fobj.close()
539 
540  dlg.Destroy()
541 
542  def OnLoadExpression(self, event):
543  """!Load expression from file
544  """
545  dlg = wx.FileDialog(parent = self,
546  message = _("Choose a file name to load the expression"),
547  wildcard = _("Expression file (*)|*"),
548  style = wx.OPEN)
549  if dlg.ShowModal() == wx.ID_OK:
550  path = dlg.GetPath()
551  if not path:
552  dlg.Destroy()
553  return
554 
555  try:
556  fobj = open(path,'r')
557  mctxt = fobj.read()
558  finally:
559  fobj.close()
560 
561  try:
562  result, exp = mctxt.split('=', 1)
563  except ValueError:
564  result = ''
565  exp = mctxt
566 
567  self.newmaptxt.SetValue(result.strip())
568  self.text_mcalc.SetValue(exp.strip())
569  self.text_mcalc.SetFocus()
570  self.text_mcalc.SetInsertionPointEnd()
571 
572  dlg.Destroy()
573 
574  def OnClear(self, event):
575  """!Clears text area
576  """
577  self.text_mcalc.SetValue('')
578 
579  def OnHelp(self, event):
580  """!Launches r.mapcalc help
581  """
582  RunCommand('g.manual', parent = self, entry = self.cmd)
583 
584  def OnClose(self,event):
585  """!Close window"""
586  self.Destroy()
587 
588 if __name__ == "__main__":
589  import gettext
590  gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode = True)
591 
592  app = wx.App(0)
593  frame = MapCalcFrame(parent = None, cmd = 'r.mapcalc')
594  frame.Show()
595  app.MainLoop()
wxGUI command interface
def OnLoadExpression
Load expression from file.
def OnUpdateStatusBar
Update statusbar text.
Mapcalc Frame class.
Custom control that selects elements.
def OnSaveExpression
Saves expression to file.
def OnClose
Close window.
def OnSelect
Gets raster map or function selection and send it to insertion method.
def OnClear
Clears text area.
def OnDone
Add create map to the layer tree.
Default GUI settings.
def OnSelectTextEvt
Checks if user is typing or the event was emited by map selection.
def OnHelp
Launches r.mapcalc help.
def _addSomething
Inserts operators, map names, and functions into text area.
def RunCommand
Run GRASS command.
Definition: gcmd.py:625
def OnMCalcRun
Builds and runs r.mapcalc statement.
def AddMark
Sends operators to insertion method.