workspace.py 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175
  1. """!
  2. @package workspace.py
  3. @brief Open/save workspace definition file
  4. Classes:
  5. - ProcessWorkspaceFile
  6. - Nviz
  7. - WriteWorkspaceFile
  8. - ProcessGrcFile
  9. (C) 2007-2009 by the GRASS Development Team
  10. This program is free software under the GNU General Public
  11. License (>=v2). Read the file COPYING that comes with GRASS
  12. for details.
  13. @author Martin Landa <landa.martin gmail.com>
  14. """
  15. import os
  16. import sys
  17. import wx
  18. ### for gxw (workspace file) parsering
  19. # xmlproc not available on Mac OS
  20. # from xml.parsers.xmlproc import xmlproc
  21. # from xml.parsers.xmlproc import xmlval
  22. # from xml.parsers.xmlproc import xmldtd
  23. try:
  24. import xml.etree.ElementTree as etree
  25. except ImportError:
  26. import elementtree.ElementTree as etree # Python <= 2.4
  27. import utils
  28. import globalvar
  29. from preferences import globalSettings as UserSettings
  30. sys.path.append(os.path.join(globalvar.ETCWXDIR, "nviz"))
  31. try:
  32. import grass7_wxnviz as wxnviz
  33. except ImportError:
  34. wxnviz = None
  35. class ProcessWorkspaceFile():
  36. def __init__(self, tree):
  37. """!A ElementTree handler for the GXW XML file, as defined in
  38. grass-gxw.dtd.
  39. """
  40. self.tree = tree
  41. self.root = self.tree.getroot()
  42. #
  43. # layer manager properties
  44. #
  45. self.layerManager = {}
  46. self.layerManager['pos'] = None # window position
  47. self.layerManager['size'] = None # window size
  48. #
  49. # list of mapdisplays
  50. #
  51. self.displays = []
  52. #
  53. # list of map layers
  54. #
  55. self.layers = []
  56. self.displayIndex = -1 # first display has index '0'
  57. self.__processFile()
  58. self.nvizDefault = Nviz()
  59. def __filterValue(self, value):
  60. """!Filter value
  61. @param value
  62. """
  63. value = value.replace('&lt;', '<')
  64. value = value.replace('&gt;', '>')
  65. return value
  66. def __getNodeText(self, node, tag, default = ''):
  67. """!Get node text"""
  68. p = node.find(tag)
  69. if p is not None:
  70. return utils.normalize_whitespace(p.text)
  71. return default
  72. def __processFile(self):
  73. """!Process workspace file"""
  74. #
  75. # layer manager
  76. #
  77. node_lm = self.root.find('layer_manager')
  78. if node_lm is not None:
  79. posAttr = node_lm.get('dim', '')
  80. if posAttr:
  81. posVal = map(int, posAttr.split(','))
  82. try:
  83. self.layerManager['pos'] = (posVal[0], posVal[1])
  84. self.layerManager['size'] = (posVal[2], posVal[3])
  85. except:
  86. pass
  87. #
  88. # displays
  89. #
  90. for display in self.root.findall('display'):
  91. self.displayIndex += 1
  92. # window position and size
  93. posAttr = display.get('dim', '')
  94. if posAttr:
  95. posVal = map(int, posAttr.split(','))
  96. try:
  97. pos = (posVal[0], posVal[1])
  98. size = (posVal[2], posVal[3])
  99. except:
  100. pos = None
  101. size = None
  102. else:
  103. pos = None
  104. size = None
  105. extentAttr = display.get('extent', '')
  106. if extentAttr:
  107. # w, s, e, n
  108. extent = map(float, extentAttr.split(','))
  109. else:
  110. extent = None
  111. self.displays.append( {
  112. "render" : bool(int(display.get('render', "0"))),
  113. "mode" : int(display.get('mode', 0)),
  114. "showCompExtent" : bool(int(display.get('showCompExtent', "0"))),
  115. "pos" : pos,
  116. "size" : size,
  117. "extent" : extent,
  118. "constrainRes" : bool(int(display.get('constrainRes', "0"))) } )
  119. # process all layers/groups in the display
  120. self.__processLayers(display)
  121. def __processLayers(self, node):
  122. """!Process layers/groups of selected display
  123. @todo Fix group flag
  124. @param node display tree node
  125. """
  126. for item in node.getchildren():
  127. if item.tag == 'group':
  128. # -> group
  129. self.layers.append( {
  130. "type" : 'group',
  131. "name" : item.get('name', ''),
  132. "checked" : bool(int(item.get('checked', "0"))),
  133. "opacity" : None,
  134. "cmd" : None,
  135. "group" : False, #### self.inTag['group'], # ???
  136. "display" : self.displayIndex,
  137. "nviz" : None})
  138. elif item.tag == 'layer':
  139. cmd, selected, nviz = self.__processLayer(item)
  140. self.layers.append( {
  141. "type" : item.get('type', None),
  142. "name" : item.get('name', None),
  143. "checked" : bool(int(item.get('checked', "0"))),
  144. "opacity" : float(item.get('opacity', '1.0')),
  145. "cmd" : cmd,
  146. "group" : False, #### self.inTag['group'], # ???
  147. "display" : self.displayIndex,
  148. "selected" : selected,
  149. "nviz" : nviz } )
  150. def __processLayer(self, layer):
  151. """!Process layer item
  152. @param layer tree node
  153. """
  154. cmd = list()
  155. #
  156. # layer attributes (task) - 2D settings
  157. #
  158. node_task = layer.find('task')
  159. cmd.append(node_task.get('name', "unknown"))
  160. # flags
  161. flags = ''
  162. for p in node_task.findall('flag'):
  163. flags += p.get('name', '')
  164. cmd.append('-' + flags)
  165. # parameters
  166. for p in node_task.findall('parameter'):
  167. cmd.append('%s=%s' % (p.get('name', ''),
  168. self.__filterValue(self.__getNodeText(p, 'value'))))
  169. if layer.find('selected') is not None:
  170. selected = True
  171. else:
  172. selected = False
  173. #
  174. # Nviz (3D settings)
  175. #
  176. node_nviz = layer.find('nviz')
  177. if node_nviz is not None:
  178. nviz = self.__processLayerNviz(node_nviz)
  179. else:
  180. nviz = None
  181. return (cmd, selected, nviz)
  182. def __processLayerNviz(self, node_nviz):
  183. """!Process 3D layer settings
  184. @param node_nviz nviz node
  185. """
  186. # init nviz layer properties
  187. nviz = {}
  188. if node_nviz.find('surface') is not None: # -> raster
  189. nviz['surface'] = {}
  190. for sec in ('attribute', 'draw', 'mask', 'position'):
  191. nviz['surface'][sec] = {}
  192. elif node_nviz.find('vlines') is not None or \
  193. node_nviz.find('vpoints') is not None: # -> vector
  194. nviz['vector'] = {}
  195. for sec in ('lines', 'points'):
  196. nviz['vector'][sec] = {}
  197. if nviz.has_key('surface'):
  198. node_surface = node_nviz.find('surface')
  199. # attributes
  200. for attrb in node_surface.findall('attribute'):
  201. tagName = str(attrb.tag)
  202. attrbName = attrb.get('name', '')
  203. dc = nviz['surface'][tagName][attrbName] = {}
  204. if attrb.get('map', '0') == '0':
  205. dc['map'] = False
  206. else:
  207. dc['map'] = True
  208. value = self.__getNodeText(attrb, 'value')
  209. try:
  210. dc['value'] = int(value)
  211. except ValueError:
  212. try:
  213. dc['value'] = float(value)
  214. except ValueError:
  215. dc['value'] = str(value)
  216. # draw
  217. node_draw = node_surface.find('draw')
  218. if node_draw is not None:
  219. tagName = str(node_draw.tag)
  220. nviz['surface'][tagName]['all'] = False
  221. nviz['surface'][tagName]['mode'] = {}
  222. nviz['surface'][tagName]['mode']['value'] = -1 # to be calculated
  223. nviz['surface'][tagName]['mode']['desc'] = {}
  224. nviz['surface'][tagName]['mode']['desc']['shading'] = \
  225. str(node_draw.get('shading', ''))
  226. nviz['surface'][tagName]['mode']['desc']['style'] = \
  227. str(node_draw.get('style', ''))
  228. nviz['surface'][tagName]['mode']['desc']['mode'] = \
  229. str(node_draw.get('mode', ''))
  230. # resolution
  231. for node_res in node_draw.findall('resolution'):
  232. resType = str(node_res.get('type', ''))
  233. if not nviz['surface']['draw'].has_key('resolution'):
  234. nviz['surface']['draw']['resolution'] = {}
  235. value = int(self.__getNodeText(node_res, 'value'))
  236. nviz['surface']['draw']['resolution'][resType] = value
  237. # wire-color
  238. node_wire_color = node_draw.find('wire_color')
  239. if node_wire_color is not None:
  240. nviz['surface']['draw']['wire-color'] = {}
  241. value = str(self.__getNodeText(node_wire_color, 'value'))
  242. nviz['surface']['draw']['wire-color']['value'] = value
  243. # position
  244. node_pos = node_surface.find('position')
  245. if node_pos is not None:
  246. dc = self.nviz['surface']['position'] = {}
  247. for coor in ['x', 'y', 'z']:
  248. node = node_pos.find(coor)
  249. if node is None:
  250. continue
  251. value = int(self.__getNodeText(node, 'value'))
  252. dc[coor] = value
  253. elif nviz.has_key('vector'):
  254. # vpoints
  255. node_vpoints = node_nviz.find('vpoints')
  256. if node_vpoints is not None:
  257. marker = str(node_vpoints.get('marker', ''))
  258. markerId = list(UserSettings.Get(group='nviz', key='vector',
  259. subkey=['points', 'marker'], internal=True)).index(marker)
  260. nviz['vector']['points']['marker'] = markerId
  261. node_mode = node_vpoints.find('mode')
  262. if node_mode is not None:
  263. nviz['vector']['points']['mode'] = {}
  264. nviz['vector']['points']['mode']['type'] = str(node_mode.get('type', ''))
  265. nviz['vector']['points']['mode']['surface'] = ''
  266. # map
  267. nviz['vector']['points']['mode']['surface'] = \
  268. self.__processLayerNvizNode(node_vpoints, 'map', str)
  269. # color
  270. self.__processLayerNvizNode(node_vpoints, 'color', str,
  271. nviz['vector']['points'])
  272. # width
  273. self.__processLayerNvizNode(node_vpoints, 'width', int,
  274. nviz['vector']['points'])
  275. # height
  276. self.__processLayerNvizNode(node_vpoints, 'height', int,
  277. nviz['vector']['points'])
  278. # height
  279. self.__processLayerNvizNode(node_vpoints, 'size', int,
  280. nviz['vector']['points'])
  281. # vlines
  282. node_vlines = node_nviz.find('vlines')
  283. if node_vlines is not None:
  284. node_mode = node_vlines.find('mode')
  285. if node_mode is not None:
  286. nviz['vector']['lines']['mode'] = {}
  287. nviz['vector']['lines']['mode']['type'] = str(node_mode.get('type', ''))
  288. nviz['vector']['lines']['mode']['surface'] = ''
  289. # map
  290. nviz['vector']['lines']['mode']['surface'] = \
  291. self.__processLayerNvizNode(node_mode, 'map', str)
  292. # color
  293. self.__processLayerNvizNode(node_vlines, 'color', str,
  294. nviz['vector']['lines'])
  295. # width
  296. self.__processLayerNvizNode(node_vlines, 'width', int,
  297. nviz['vector']['lines'])
  298. # height
  299. self.__processLayerNvizNode(node_vlines, 'height', int,
  300. nviz['vector']['lines'])
  301. return nviz
  302. def __processLayerNvizNode(self, node, tag, cast, dc = None):
  303. """!Process given tag nviz/vector"""
  304. node_tag = node.find(tag)
  305. if node_tag is not None:
  306. value = cast(self.__getNodeText(node_tag, 'value'))
  307. if dc:
  308. dc[tag] = dict()
  309. dc[tag]['value'] = value
  310. else:
  311. return value
  312. class Nviz:
  313. def __init__(self):
  314. """Default 3D settings"""
  315. pass
  316. def SetSurfaceDefaultProp(self):
  317. """Set default surface data properties"""
  318. data = dict()
  319. for sec in ('attribute', 'draw', 'mask', 'position'):
  320. data[sec] = {}
  321. #
  322. # attributes
  323. #
  324. for attrb in ('shine', ):
  325. data['attribute'][attrb] = {}
  326. for key, value in UserSettings.Get(group='nviz', key='volume',
  327. subkey=attrb).iteritems():
  328. data['attribute'][attrb][key] = value
  329. data['attribute'][attrb]['update'] = None
  330. #
  331. # draw
  332. #
  333. data['draw']['all'] = False # apply only for current surface
  334. for control, value in UserSettings.Get(group='nviz', key='surface', subkey='draw').iteritems():
  335. if control[:3] == 'res':
  336. if not data['draw'].has_key('resolution'):
  337. data['draw']['resolution'] = {}
  338. if not data['draw']['resolution'].has_key('update'):
  339. data['draw']['resolution']['update'] = None
  340. data['draw']['resolution'][control[4:]] = value
  341. continue
  342. if control == 'wire-color':
  343. value = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  344. elif control in ('mode', 'style', 'shading'):
  345. if not data['draw'].has_key('mode'):
  346. data['draw']['mode'] = {}
  347. continue
  348. data['draw'][control] = { 'value' : value }
  349. data['draw'][control]['update'] = None
  350. value, desc = self.GetDrawMode(UserSettings.Get(group='nviz', key='surface', subkey=['draw', 'mode']),
  351. UserSettings.Get(group='nviz', key='surface', subkey=['draw', 'style']),
  352. UserSettings.Get(group='nviz', key='surface', subkey=['draw', 'shading']))
  353. data['draw']['mode'] = { 'value' : value,
  354. 'desc' : desc,
  355. 'update': None }
  356. return data
  357. def SetVolumeDefaultProp(self):
  358. """Set default volume data properties"""
  359. data = dict()
  360. for sec in ('attribute', 'draw', 'position'):
  361. data[sec] = dict()
  362. for sec in ('isosurface', 'slice'):
  363. data[sec] = list()
  364. #
  365. # draw
  366. #
  367. for control, value in UserSettings.Get(group='nviz', key='volume', subkey='draw').iteritems():
  368. if control == 'mode':
  369. continue
  370. if control == 'shading':
  371. sel = UserSettings.Get(group='nviz', key='surface', subkey=['draw', 'shading'])
  372. value, desc = self.GetDrawMode(shade=sel, string=False)
  373. data['draw']['shading'] = { 'value' : value,
  374. 'desc' : desc['shading'] }
  375. elif control == 'mode':
  376. sel = UserSettings.Get(group='nviz', key='volume', subkey=['draw', 'mode'])
  377. if sel == 0:
  378. desc = 'isosurface'
  379. else:
  380. desc = 'slice'
  381. data['draw']['mode'] = { 'value' : sel,
  382. 'desc' : desc, }
  383. else:
  384. data['draw'][control] = { 'value' : value }
  385. if not data['draw'][control].has_key('update'):
  386. data['draw'][control]['update'] = None
  387. #
  388. # isosurface attributes
  389. #
  390. for attrb in ('shine', ):
  391. data['attribute'][attrb] = {}
  392. for key, value in UserSettings.Get(group='nviz', key='volume',
  393. subkey=attrb).iteritems():
  394. data['attribute'][attrb][key] = value
  395. return data
  396. def SetVectorDefaultProp(self):
  397. """Set default vector data properties"""
  398. data = dict()
  399. for sec in ('lines', 'points'):
  400. data[sec] = {}
  401. self.SetVectorLinesDefaultProp(data['lines'])
  402. self.SetVectorPointsDefaultProp(data['points'])
  403. return data
  404. def SetVectorLinesDefaultProp(self, data):
  405. """Set default vector properties -- lines"""
  406. # width
  407. data['width'] = {'value' : UserSettings.Get(group='nviz', key='vector',
  408. subkey=['lines', 'width']) }
  409. # color
  410. value = UserSettings.Get(group='nviz', key='vector',
  411. subkey=['lines', 'color'])
  412. color = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  413. data['color'] = { 'value' : color }
  414. # mode
  415. if UserSettings.Get(group='nviz', key='vector',
  416. subkey=['lines', 'flat']):
  417. type = 'flat'
  418. map = None
  419. else:
  420. type = 'flat'
  421. map = None
  422. data['mode'] = {}
  423. data['mode']['type'] = type
  424. data['mode']['update'] = None
  425. if map:
  426. data['mode']['surface'] = map
  427. # height
  428. data['height'] = { 'value' : UserSettings.Get(group='nviz', key='vector',
  429. subkey=['lines', 'height']) }
  430. if data.has_key('object'):
  431. for attrb in ('color', 'width', 'mode', 'height'):
  432. data[attrb]['update'] = None
  433. def SetVectorPointsDefaultProp(self, data):
  434. """Set default vector properties -- points"""
  435. # size
  436. data['size'] = { 'value' : UserSettings.Get(group='nviz', key='vector',
  437. subkey=['points', 'size']) }
  438. # width
  439. data['width'] = { 'value' : UserSettings.Get(group='nviz', key='vector',
  440. subkey=['points', 'width']) }
  441. # marker
  442. data['marker'] = { 'value' : UserSettings.Get(group='nviz', key='vector',
  443. subkey=['points', 'marker']) }
  444. # color
  445. value = UserSettings.Get(group='nviz', key='vector',
  446. subkey=['points', 'color'])
  447. color = str(value[0]) + ':' + str(value[1]) + ':' + str(value[2])
  448. data['color'] = { 'value' : color }
  449. # mode
  450. data['mode'] = { 'type' : 'surface',
  451. 'surface' : '', }
  452. # height
  453. data['height'] = { 'value' : UserSettings.Get(group='nviz', key='vector',
  454. subkey=['points', 'height']) }
  455. if data.has_key('object'):
  456. for attrb in ('size', 'width', 'marker',
  457. 'color', 'surface', 'height'):
  458. data[attrb]['update'] = None
  459. def GetDrawMode(self, mode=None, style=None, shade=None, string=False):
  460. """Get surface draw mode (value) from description/selection
  461. @param mode,style,shade modes
  462. @param string if True input parameters are strings otherwise
  463. selections
  464. """
  465. if not wxnviz:
  466. return None
  467. value = 0
  468. desc = {}
  469. if string:
  470. if mode is not None:
  471. if mode == 'coarse':
  472. value |= wxnviz.DM_WIRE
  473. elif mode == 'fine':
  474. value |= wxnviz.DM_POLY
  475. else: # both
  476. value |= wxnviz.DM_WIRE_POLY
  477. if style is not None:
  478. if style == 'wire':
  479. value |= wxnviz.DM_GRID_WIRE
  480. else: # surface
  481. value |= wxnviz.DM_GRID_SURF
  482. if shade is not None:
  483. if shade == 'flat':
  484. value |= wxnviz.DM_FLAT
  485. else: # surface
  486. value |= wxnviz.DM_GOURAUD
  487. return value
  488. # -> string is False
  489. if mode is not None:
  490. if mode == 0: # coarse
  491. value |= wxnviz.DM_WIRE
  492. desc['mode'] = 'coarse'
  493. elif mode == 1: # fine
  494. value |= wxnviz.DM_POLY
  495. desc['mode'] = 'fine'
  496. else: # both
  497. value |= wxnviz.DM_WIRE_POLY
  498. desc['mode'] = 'both'
  499. if style is not None:
  500. if style == 0: # wire
  501. value |= wxnviz.DM_GRID_WIRE
  502. desc['style'] = 'wire'
  503. else: # surface
  504. value |= wxnviz.DM_GRID_SURF
  505. desc['style'] = 'surface'
  506. if shade is not None:
  507. if shade == 0:
  508. value |= wxnviz.DM_FLAT
  509. desc['shading'] = 'flat'
  510. else: # surface
  511. value |= wxnviz.DM_GOURAUD
  512. desc['shading'] = 'gouraud'
  513. return (value, desc)
  514. class WriteWorkspaceFile(object):
  515. """!Generic class for writing workspace file"""
  516. def __init__(self, lmgr, file):
  517. self.file = file
  518. self.lmgr = lmgr
  519. self.indent = 0
  520. # write header
  521. self.file.write('<?xml version="1.0" encoding="UTF-8"?>\n')
  522. self.file.write('<!DOCTYPE gxw SYSTEM "grass-gxw.dtd">\n')
  523. self.file.write('%s<gxw>\n' % (' ' * self.indent))
  524. self.indent =+ 4
  525. # layer manager
  526. windowPos = self.lmgr.GetPosition()
  527. windowSize = self.lmgr.GetSize()
  528. file.write('%s<layer_manager dim="%d,%d,%d,%d">\n' % (' ' * self.indent,
  529. windowPos[0],
  530. windowPos[1],
  531. windowSize[0],
  532. windowSize[1]
  533. ))
  534. file.write('%s</layer_manager>\n' % (' ' * self.indent))
  535. # list of displays
  536. for page in range(0, self.lmgr.gm_cb.GetPageCount()):
  537. mapTree = self.lmgr.gm_cb.GetPage(page).maptree
  538. region = mapTree.Map.region
  539. displayPos = mapTree.mapdisplay.GetPosition()
  540. displaySize = mapTree.mapdisplay.GetSize()
  541. file.write('%s<display render="%d" '
  542. 'mode="%d" showCompExtent="%d" '
  543. 'constrainRes="%d" '
  544. 'dim="%d,%d,%d,%d" '
  545. 'extent="%f,%f,%f,%f">\n' % (' ' * self.indent,
  546. int(mapTree.mapdisplay.autoRender.IsChecked()),
  547. mapTree.mapdisplay.toggleStatus.GetSelection(),
  548. int(mapTree.mapdisplay.showRegion.IsChecked()),
  549. int(mapTree.mapdisplay.compResolution.IsChecked()),
  550. displayPos[0],
  551. displayPos[1],
  552. displaySize[0],
  553. displaySize[1],
  554. region['w'],
  555. region['s'],
  556. region['e'],
  557. region['n']
  558. ))
  559. # list of layers
  560. item = mapTree.GetFirstChild(mapTree.root)[0]
  561. self.__writeLayer(mapTree, item)
  562. file.write('%s</display>\n' % (' ' * self.indent))
  563. self.indent =- 4
  564. file.write('%s</gxw>\n' % (' ' * self.indent))
  565. def __filterValue(self, value):
  566. """!Make value XML-valid"""
  567. value = value.replace('<', '&lt;')
  568. value = value.replace('>', '&gt;')
  569. return value
  570. def __writeLayer(self, mapTree, item):
  571. """!Write bunch of layers to GRASS Workspace XML file"""
  572. self.indent += 4
  573. itemSelected = mapTree.GetSelections()
  574. while item and item.IsOk():
  575. type = mapTree.GetPyData(item)[0]['type']
  576. if type != 'group':
  577. maplayer = mapTree.GetPyData(item)[0]['maplayer']
  578. else:
  579. maplayer = None
  580. checked = int(item.IsChecked())
  581. if type == 'command':
  582. cmd = mapTree.GetPyData(item)[0]['maplayer'].GetCmd(string=True)
  583. self.file.write('%s<layer type="%s" name="%s" checked="%d">\n' % \
  584. (' ' * self.indent, type, cmd, checked));
  585. self.file.write('%s</layer>\n' % (' ' * self.indent));
  586. elif type == 'group':
  587. name = mapTree.GetItemText(item)
  588. self.file.write('%s<group name="%s" checked="%d">\n' % \
  589. (' ' * self.indent, name, checked));
  590. self.indent += 4
  591. subItem = mapTree.GetFirstChild(item)[0]
  592. self.__writeLayer(mapTree, subItem)
  593. self.indent -= 4
  594. self.file.write('%s</group>\n' % (' ' * self.indent));
  595. else:
  596. cmd = mapTree.GetPyData(item)[0]['maplayer'].GetCmd(string=False)
  597. name = mapTree.GetItemText(item)
  598. # remove 'opacity' part
  599. if '(opacity' in name:
  600. name = name.split('(', -1)[0].strip()
  601. opacity = maplayer.GetOpacity(float=True)
  602. self.file.write('%s<layer type="%s" name="%s" checked="%d" opacity="%f">\n' % \
  603. (' ' * self.indent, type, name, checked, opacity));
  604. self.indent += 4
  605. # selected ?
  606. if item in itemSelected:
  607. self.file.write('%s<selected />\n' % (' ' * self.indent))
  608. # layer properties
  609. self.file.write('%s<task name="%s">\n' % (' ' * self.indent, cmd[0]))
  610. self.indent += 4
  611. for key, val in cmd[1].iteritems():
  612. if key == 'flags':
  613. for f in val:
  614. self.file.write('%s<flag name="%s" />\n' %
  615. (' ' * self.indent, f))
  616. else: # parameter
  617. self.file.write('%s<parameter name="%s">\n' %
  618. (' ' * self.indent, key))
  619. self.indent += 4
  620. self.file.write('%s<value>%s</value>\n' %
  621. (' ' * self.indent, self.__filterValue(val)))
  622. self.indent -= 4
  623. self.file.write('%s</parameter>\n' % (' ' * self.indent));
  624. self.indent -= 4
  625. self.file.write('%s</task>\n' % (' ' * self.indent));
  626. nviz = mapTree.GetPyData(item)[0]['nviz']
  627. if nviz:
  628. self.file.write('%s<nviz>\n' % (' ' * self.indent));
  629. if maplayer.type == 'raster':
  630. self.__writeNvizSurface(nviz['surface'])
  631. elif maplayer.type == 'vector':
  632. self.__writeNvizVector(nviz['vector'])
  633. self.file.write('%s</nviz>\n' % (' ' * self.indent));
  634. self.indent -= 4
  635. self.file.write('%s</layer>\n' % (' ' * self.indent));
  636. item = mapTree.GetNextSibling(item)
  637. self.indent -= 4
  638. def __writeNvizSurface(self, data):
  639. """!Save Nviz raster layer properties to workspace
  640. @param data Nviz layer properties
  641. """
  642. if not data.has_key('object'): # skip disabled
  643. return
  644. self.indent += 4
  645. self.file.write('%s<surface>\n' % (' ' * self.indent))
  646. self.indent += 4
  647. for attrb in data.iterkeys():
  648. if len(data[attrb]) < 1: # skip empty attributes
  649. continue
  650. if attrb == 'object':
  651. continue
  652. for name in data[attrb].iterkeys():
  653. # surface attribute
  654. if attrb == 'attribute':
  655. self.file.write('%s<%s name="%s" map="%d">\n' % \
  656. (' ' * self.indent, attrb, name, data[attrb][name]['map']))
  657. self.indent += 4
  658. self.file.write('%s<value>%s</value>\n' % (' ' * self.indent, data[attrb][name]['value']))
  659. self.indent -= 4
  660. # end tag
  661. self.file.write('%s</%s>\n' % (' ' * self.indent, attrb))
  662. # draw mode
  663. if attrb == 'draw':
  664. self.file.write('%s<%s' %(' ' * self.indent, attrb))
  665. if data[attrb].has_key('mode'):
  666. for tag, value in data[attrb]['mode']['desc'].iteritems():
  667. self.file.write(' %s="%s"' % (tag, value))
  668. self.file.write('>\n') # <draw ...>
  669. if data[attrb].has_key('resolution'):
  670. self.indent += 4
  671. for type in ('coarse', 'fine'):
  672. self.file.write('%s<resolution type="%s">\n' % (' ' * self.indent, type))
  673. self.indent += 4
  674. self.file.write('%s<value>%d</value>\n' % (' ' * self.indent,
  675. data[attrb]['resolution'][type]))
  676. self.indent -= 4
  677. self.file.write('%s</resolution>\n' % (' ' * self.indent))
  678. if data[attrb].has_key('wire-color'):
  679. self.file.write('%s<wire_color>\n' % (' ' * self.indent))
  680. self.indent += 4
  681. self.file.write('%s<value>%s</value>\n' % (' ' * self.indent,
  682. data[attrb]['wire-color']['value']))
  683. self.indent -= 4
  684. self.file.write('%s</wire_color>\n' % (' ' * self.indent))
  685. self.indent -= 4
  686. # position
  687. elif attrb == 'position':
  688. self.file.write('%s<%s>\n' %(' ' * self.indent, attrb))
  689. i = 0
  690. for tag in ('x', 'y', 'z'):
  691. self.indent += 4
  692. self.file.write('%s<%s>%d</%s>\n' % (' ' * self.indent, tag,
  693. data[attrb][tag], tag))
  694. i += 1
  695. self.indent -= 4
  696. if attrb != 'attribute':
  697. # end tag
  698. self.file.write('%s</%s>\n' % (' ' * self.indent, attrb))
  699. self.indent -= 4
  700. self.file.write('%s</surface>\n' % (' ' * self.indent))
  701. self.indent -= 4
  702. def __writeNvizVector(self, data):
  703. """!Save Nviz vector layer properties (lines/points) to workspace
  704. @param data Nviz layer properties
  705. """
  706. self.indent += 4
  707. for attrb in data.iterkeys():
  708. if len(data[attrb]) < 1: # skip empty attributes
  709. continue
  710. if not data[attrb].has_key('object'): # skip disabled
  711. continue
  712. if attrb == 'lines':
  713. self.file.write('%s<v%s>\n' % (' ' * self.indent, attrb))
  714. elif attrb == 'points':
  715. markerId = data[attrb]['marker']
  716. marker = UserSettings.Get(group='nviz', key='vector',
  717. subkey=['points', 'marker'], internal=True)[markerId]
  718. self.file.write('%s<v%s marker="%s">\n' % (' ' * self.indent,
  719. attrb,
  720. marker))
  721. self.indent += 4
  722. for name in data[attrb].iterkeys():
  723. if name in ('object', 'marker'):
  724. continue
  725. if name == 'mode':
  726. self.file.write('%s<%s type="%s">\n' % (' ' * self.indent, name,
  727. data[attrb][name]['type']))
  728. if data[attrb][name]['type'] == 'surface':
  729. self.indent += 4
  730. self.file.write('%s<map>%s</map>\n' % (' ' * self.indent,
  731. data[attrb][name]['surface']))
  732. self.indent -= 4
  733. self.file.write('%s</%s>\n' % ((' ' * self.indent, name)))
  734. else:
  735. self.file.write('%s<%s>\n' % (' ' * self.indent, name))
  736. self.indent += 4
  737. self.file.write('%s<value>%s</value>\n' % (' ' * self.indent, data[attrb][name]['value']))
  738. self.indent -= 4
  739. self.file.write('%s</%s>\n' % (' ' * self.indent, name))
  740. self.indent -= 4
  741. self.file.write('%s</v%s>\n' % (' ' * self.indent, attrb))
  742. self.indent -= 4
  743. class ProcessGrcFile(object):
  744. def __init__(self, filename):
  745. """!Process GRC file"""
  746. self.filename = filename
  747. # elements
  748. self.inGroup = False
  749. self.inRaster = False
  750. self.inVector = False
  751. # list of layers
  752. self.layers = []
  753. # error message
  754. self.error = ''
  755. self.num_error = 0
  756. def read(self, parent):
  757. """!Read GRC file
  758. @param parent parent window
  759. @return list of map layers
  760. """
  761. try:
  762. file = open(self.filename, "r")
  763. except IOError:
  764. wx.MessageBox(parent=parent,
  765. message=_("Unable to open file <%s> for reading.") % self.filename,
  766. caption=_("Error"), style=wx.OK | wx.ICON_ERROR)
  767. return []
  768. line_id = 1
  769. for line in file.readlines():
  770. self.process_line(line.rstrip('\n'), line_id)
  771. line_id +=1
  772. file.close()
  773. if self.num_error > 0:
  774. wx.MessageBox(parent=parent,
  775. message=_("Some lines were skipped when reading settings "
  776. "from file <%(file)s>.\nSee 'Command output' window for details.\n\n"
  777. "Number of skipped lines: %(line)d") % \
  778. { 'file' : self.filename, 'line' : self.num_error },
  779. caption=_("Warning"), style=wx.OK | wx.ICON_EXCLAMATION)
  780. parent.goutput.WriteLog('Map layers loaded from GRC file <%s>' % self.filename)
  781. parent.goutput.WriteLog('Skipped lines:\n%s' % self.error)
  782. return self.layers
  783. def process_line(self, line, line_id):
  784. """!Process line definition"""
  785. element = self._get_element(line)
  786. if element == 'Group':
  787. self.groupName = self._get_value(line)
  788. self.layers.append({
  789. "type" : 'group',
  790. "name" : self.groupName,
  791. "checked" : None,
  792. "opacity" : None,
  793. "cmd" : None,
  794. "group" : self.inGroup,
  795. "display" : 0 })
  796. self.inGroup = True
  797. elif element == '_check':
  798. if int(self._get_value(line)) == 1:
  799. self.layers[-1]['checked'] = True
  800. else:
  801. self.layers[-1]['checked'] = False
  802. elif element == 'End':
  803. if self.inRaster:
  804. self.inRaster = False
  805. elif self.inVector:
  806. self.inVector = False
  807. elif self.inGroup:
  808. self.inGroup = False
  809. elif self.inGridline:
  810. self.inGridline = False
  811. elif element == 'opacity':
  812. self.layers[-1]['opacity'] = float(self._get_value(line))
  813. # raster
  814. elif element == 'Raster':
  815. self.inRaster = True
  816. self.layers.append({
  817. "type" : 'raster',
  818. "name" : self._get_value(line),
  819. "checked" : None,
  820. "opacity" : None,
  821. "cmd" : ['d.rast'],
  822. "group" : self.inGroup,
  823. "display" : 0})
  824. elif element == 'map' and self.inRaster:
  825. self.layers[-1]['cmd'].append('map=%s' % self._get_value(line))
  826. elif element == 'overlay' and self.inRaster:
  827. if int(self._get_value(line)) == 1:
  828. self.layers[-1]['cmd'].append('-o')
  829. elif element == 'rastquery' and self.inRaster:
  830. value = self._get_value(line)
  831. if value != '':
  832. self.layers[-1]['cmd'].append('catlist=%s' % value)
  833. elif element == 'bkcolor' and self.inRaster:
  834. value = self._get_value(line)
  835. if value != '':
  836. self.layers[-1]['cmd'].append('bg=%s' % value)
  837. # vector
  838. elif element == 'Vector':
  839. self.inVector = True
  840. self.layers.append({
  841. "type" : 'vector',
  842. "name" : self._get_value(line),
  843. "checked" : None,
  844. "opacity" : None,
  845. "cmd" : ['d.vect'],
  846. "group" : self.inGroup,
  847. "display" : 0})
  848. elif element == 'vect' and self.inVector:
  849. self.layers[-1]['cmd'].append('map=%s' % self._get_value(line))
  850. elif element in ('display_shape',
  851. 'display_cat',
  852. 'display_topo',
  853. 'display_dir',
  854. 'display_attr',
  855. 'type_point',
  856. 'type_line',
  857. 'type_boundary',
  858. 'type_centroid',
  859. 'type_area',
  860. 'type_face') and self.inVector:
  861. if int(self._get_value(line)) == 1:
  862. name = element.split('_')[0]
  863. type = element.split('_')[1]
  864. paramId = self._get_cmd_param_index(self.layers[-1]['cmd'], name)
  865. if paramId == -1:
  866. self.layers[-1]['cmd'].append('%s=%s' % (name, type))
  867. else:
  868. self.layers[-1]['cmd'][paramId] += ',%s' % type
  869. elif element in ('color',
  870. 'fcolor',
  871. 'lcolor') and self.inVector:
  872. value = self._get_value(line)
  873. if value != '':
  874. self.layers[-1]['cmd'].append('%s=%s' % (element,
  875. self._color_name_to_rgb(value)))
  876. elif element == 'rdmcolor' and self.inVector:
  877. if int(self._get_value(line)) == 1:
  878. self.layers[-1]['cmd'].append('-c')
  879. elif element == 'sqlcolor' and self.inVector:
  880. if int(self._get_value(line)) == 1:
  881. self.layers[-1]['cmd'].append('-a')
  882. elif element in ('icon',
  883. 'size',
  884. 'layer',
  885. 'xref',
  886. 'yref',
  887. 'lsize',
  888. 'where',
  889. 'minreg',
  890. 'maxreg') and self.inVector:
  891. value = self._get_value(line)
  892. if value != '':
  893. self.layers[-1]['cmd'].append('%s=%s' % (element,
  894. value))
  895. elif element == 'lwidth':
  896. value = self._get_value(line)
  897. if value != '':
  898. self.layers[-1]['cmd'].append('width=%s' % value)
  899. elif element == 'lfield':
  900. value = self._get_value(line)
  901. if value != '':
  902. self.layers[-1]['cmd'].append('llayer=%s' % value)
  903. elif element == 'attribute':
  904. value = self._get_value(line)
  905. if value != '':
  906. self.layers[-1]['cmd'].append('attrcol=%s' % value)
  907. elif element == 'cat':
  908. value = self._get_value(line)
  909. if value != '':
  910. self.layers[-1]['cmd'].append('cats=%s' % value)
  911. # gridline
  912. elif element == 'gridline':
  913. self.inGridline = True
  914. self.layers.append({
  915. "type" : 'grid',
  916. "name" : self._get_value(line),
  917. "checked" : None,
  918. "opacity" : None,
  919. "cmd" : ['d.grid'],
  920. "group" : self.inGroup,
  921. "display" : 0})
  922. elif element == 'gridcolor':
  923. value = self._get_value(line)
  924. if value != '':
  925. self.layers[-1]['cmd'].append('color=%s' % self._color_name_to_rgb(value))
  926. elif element == 'gridborder':
  927. value = self._get_value(line)
  928. if value != '':
  929. self.layers[-1]['cmd'].append('bordercolor=%s' % self._color_name_to_rgb(value))
  930. elif element == 'textcolor':
  931. value = self._get_value(line)
  932. if value != '':
  933. self.layers[-1]['cmd'].append('textcolor=%s' % self._color_name_to_rgb(value))
  934. elif element in ('gridsize',
  935. 'gridorigin'):
  936. value = self._get_value(line)
  937. if value != '':
  938. self.layers[-1]['cmd'].append('%s=%s' % (element[4:], value))
  939. elif element in 'fontsize':
  940. value = self._get_value(line)
  941. if value != '':
  942. self.layers[-1]['cmd'].append('%s=%s' % (element, value))
  943. elif element == 'griddraw':
  944. value = self._get_value(line)
  945. if value == '0':
  946. self.layers[-1]['cmd'].append('-n')
  947. elif element == 'gridgeo':
  948. value = self._get_value(line)
  949. if value == '1':
  950. self.layers[-1]['cmd'].append('-g')
  951. elif element == 'borderdraw':
  952. value = self._get_value(line)
  953. if value == '0':
  954. self.layers[-1]['cmd'].append('-b')
  955. elif element == 'textdraw':
  956. value = self._get_value(line)
  957. if value == '0':
  958. self.layers[-1]['cmd'].append('-t')
  959. else:
  960. self.error += _(' row %d:') % line_id + line + os.linesep
  961. self.num_error += 1
  962. def _get_value(self, line):
  963. """!Get value of element"""
  964. try:
  965. return line.strip(' ').split(' ')[1].strip(' ')
  966. except:
  967. return ''
  968. def _get_element(self, line):
  969. """!Get element tag"""
  970. return line.strip(' ').split(' ')[0].strip(' ')
  971. def _get_cmd_param_index(self, cmd, name):
  972. """!Get index of parameter in cmd list
  973. @param cmd cmd list
  974. @param name parameter name
  975. @return index
  976. @return -1 if not found
  977. """
  978. i = 0
  979. for param in cmd:
  980. if '=' not in param:
  981. i += 1
  982. continue
  983. if param.split('=')[0] == name:
  984. return i
  985. i += 1
  986. return -1
  987. def _color_name_to_rgb(self, value):
  988. """!Convert color name (#) to rgb values"""
  989. col = wx.NamedColour(value)
  990. return str(col.Red()) + ':' + \
  991. str(col.Green()) + ':' + \
  992. str(col.Blue())