mcalc_builder.py 25 KB

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