workspace.py 46 KB

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