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