mcalc_builder.py 25 KB

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