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