GRASS Programmer's Manual  6.4.2(2012)
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
preferences.py
Go to the documentation of this file.
1 """!
2 @package preferences
3 
4 @brief User preferences dialog
5 
6 Sets default display font, etc.
7 If you want to add some value to settings you have to add default value
8 to defaultSettings and set constraints in internalSettings in Settings class.
9 Everything can be used in PreferencesDialog.
10 
11 Classes:
12  - Settings
13  - PreferencesBaseDialog
14  - PreferencesDialog
15  - DefaultFontDialog
16  - MapsetAccess
17  - NvizPreferencesDialog
18 
19 (C) 2007-2011 by the GRASS Development Team
20 This program is free software under the GNU General Public
21 License (>=v2). Read the file COPYING that comes with GRASS
22 for details.
23 
24 @author Michael Barton (Arizona State University)
25 @author Martin Landa <landa.martin gmail.com>
26 @author Vaclav Petras <wenzeslaus gmail.com> (menu customization)
27 """
28 
29 import os
30 import sys
31 import copy
32 import stat
33 import types
34 try:
35  import pwd
36  havePwd = True
37 except ImportError:
38  havePwd = False
39 
40 ### i18N
41 import gettext
42 gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode = True)
43 
44 import wx
45 import wx.lib.filebrowsebutton as filebrowse
46 import wx.lib.colourselect as csel
47 import wx.lib.mixins.listctrl as listmix
48 
49 from grass.script import core as grass
50 
51 import gcmd
52 import utils
53 import globalvar
54 from debug import Debug as Debug
55 
56 from wx.lib.newevent import NewEvent
57 
58 wxSettingsChanged, EVT_SETTINGS_CHANGED = NewEvent()
59 
60 class Settings:
61  """!Generic class where to store settings"""
62  def __init__(self):
63  # settings file
64  self.filePath = os.path.join(utils.GetSettingsPath(), 'wx')
65 
66  # key/value separator
67  self.sep = ';'
68 
69  try:
70  projFile = utils.PathJoin(os.environ["GRASS_PROJSHARE"], 'epsg')
71  except KeyError:
72  projFile = ''
73 
74  #
75  # default settings
76  #
77  self.defaultSettings = {
78  #
79  # general
80  #
81  'general': {
82  # use default window layout (layer manager, displays, ...)
83  'defWindowPos' : {
84  'enabled' : True,
85  'dim' : '0,0,%d,%d,%d,0,%d,%d' % \
86  (globalvar.GM_WINDOW_SIZE[0],
87  globalvar.GM_WINDOW_SIZE[1],
88  globalvar.GM_WINDOW_SIZE[0],
89  globalvar.MAP_WINDOW_SIZE[0],
90  globalvar.MAP_WINDOW_SIZE[1])
91  },
92  # workspace
93  'workspace' : {
94  'posDisplay' : {
95  'enabled' : False
96  },
97  'posManager' : {
98  'enabled' : False
99  },
100  },
101  },
102  'manager' : {
103  # show opacity level widget
104  'changeOpacityLevel' : {
105  'enabled' : False
106  },
107  # ask when removing layer from layer tree
108  'askOnRemoveLayer' : {
109  'enabled' : True
110  },
111  # ask when quiting wxGUI or closing display
112  'askOnQuit' : {
113  'enabled' : True
114  },
115  # hide tabs
116  'hideTabs' : {
117  'search' : False,
118  'pyshell' : False,
119  },
120  'copySelectedTextToClipboard' : {
121  'enabled' : False
122  },
123  },
124  #
125  # appearance
126  #
127  'appearance': {
128  'outputfont' : {
129  'type' : 'Courier New',
130  'size': '10',
131  },
132  # expand/collapse element list
133  'elementListExpand' : {
134  'selection' : 0
135  },
136  'menustyle' : {
137  'selection' : 1
138  },
139  'gSelectPopupHeight' : {
140  'value' : 200
141  },
142  'iconTheme' : {
143  'type' : 'grass2'
144  }, # grass2, grass, silk
145  },
146  #
147  # display
148  #
149  'display': {
150  'font' : {
151  'type' : '',
152  'encoding': 'ISO-8859-1',
153  },
154  'driver': {
155  'type': 'default'
156  },
157  'compResolution' : {
158  'enabled' : False
159  },
160  'autoRendering': {
161  'enabled' : True
162  },
163  'autoZooming' : {
164  'enabled' : False
165  },
166  'statusbarMode': {
167  'selection' : 0
168  },
169  'bgcolor': {
170  'color' : (255, 255, 255, 255),
171  },
172  },
173  #
174  # projection
175  #
176  'projection' : {
177  'statusbar' : {
178  'proj4' : '',
179  'epsg' : '',
180  'projFile' : projFile,
181  },
182  'format' : {
183  'll' : 'DMS',
184  'precision' : 2,
185  },
186  },
187  #
188  # Attribute Table Manager
189  #
190  'atm' : {
191  'highlight' : {
192  'color' : (255, 255, 0, 255),
193  'width' : 2
194  },
195  'leftDbClick' : {
196  'selection' : 1 # draw selected
197  },
198  'askOnDeleteRec' : {
199  'enabled' : True
200  },
201  'keycolumn' : {
202  'value' : 'cat'
203  },
204  'encoding' : {
205  'value' : '',
206  }
207  },
208  #
209  # Command
210  #
211  'cmd': {
212  'overwrite' : {
213  'enabled' : False
214  },
215  'closeDlg' : {
216  'enabled' : False
217  },
218  'verbosity' : {
219  'selection' : 'grassenv'
220  },
221  # d.rast
222  'rasterOverlay' : {
223  'enabled' : True
224  },
225  'rasterColorTable' : {
226  'enabled' : False,
227  'selection' : 'rainbow',
228  },
229  # d.vect
230  'showType': {
231  'point' : {
232  'enabled' : True
233  },
234  'line' : {
235  'enabled' : True
236  },
237  'centroid' : {
238  'enabled' : True
239  },
240  'boundary' : {
241  'enabled' : True
242  },
243  'area' : {
244  'enabled' : True
245  },
246  'face' : {
247  'enabled' : True
248  },
249  },
250  'addNewLayer' : {
251  'enabled' : True,
252  },
253  'interactiveInput' : {
254  'enabled' : True,
255  },
256  },
257  #
258  # vdigit
259  #
260  'vdigit' : {
261  # symbology
262  'symbol' : {
263  'highlight' : {
264  'enabled' : None,
265  'color' : (255, 255, 0, 255)
266  }, # yellow
267  'highlightDupl' : {
268  'enabled' : None,
269  'color' : (255, 72, 0, 255)
270  }, # red
271  'point' : {
272  'enabled' : True,
273  'color' : (0, 0, 0, 255)
274  }, # black
275  'line' : {
276  'enabled' : True,
277  'color' : (0, 0, 0, 255)
278  }, # black
279  'boundaryNo' : {
280  'enabled' : True,
281  'color' : (126, 126, 126, 255)
282  }, # grey
283  'boundaryOne' : {
284  'enabled' : True,
285  'color' : (0, 255, 0, 255)
286  }, # green
287  'boundaryTwo' : {
288  'enabled' : True,
289  'color' : (255, 135, 0, 255)
290  }, # orange
291  'centroidIn' : {
292  'enabled' : True,
293  'color' : (0, 0, 255, 255)
294  }, # blue
295  'centroidOut' : {
296  'enabled' : True,
297  'color' : (165, 42, 42, 255)
298  }, # brown
299  'centroidDup' : {
300  'enabled' : True,
301  'color' : (156, 62, 206, 255)
302  }, # violet
303  'nodeOne' : {
304  'enabled' : True,
305  'color' : (255, 0, 0, 255)
306  }, # red
307  'nodeTwo' : {
308  'enabled' : True,
309  'color' : (0, 86, 45, 255)
310  }, # dark green
311  'vertex' : {
312  'enabled' : False,
313  'color' : (255, 20, 147, 255)
314  }, # deep pink
315  'area' : {
316  'enabled' : False,
317  'color' : (217, 255, 217, 255)
318  }, # green
319  'direction' : {
320  'enabled' : False,
321  'color' : (255, 0, 0, 255)
322  }, # red
323  },
324  # display
325  'lineWidth' : {
326  'value' : 2,
327  'units' : 'screen pixels'
328  },
329  # snapping
330  'snapping' : {
331  'value' : 10,
332  'units' : 'screen pixels'
333  },
334  'snapToVertex' : {
335  'enabled' : False
336  },
337  # digitize new record
338  'addRecord' : {
339  'enabled' : True
340  },
341  'layer' :{
342  'value' : 1
343  },
344  'category' : {
345  'value' : 1
346  },
347  'categoryMode' : {
348  'selection' : 0
349  },
350  # delete existing feature(s)
351  'delRecord' : {
352  'enabled' : True
353  },
354  # query tool
355  'query' : {
356  'selection' : 0,
357  'box' : True
358  },
359  'queryLength' : {
360  'than-selection' : 0,
361  'thresh' : 0
362  },
363  'queryDangle' : {
364  'than-selection' : 0,
365  'thresh' : 0
366  },
367  # select feature (point, line, centroid, boundary)
368  'selectType': {
369  'point' : {
370  'enabled' : True
371  },
372  'line' : {
373  'enabled' : True
374  },
375  'centroid' : {
376  'enabled' : True
377  },
378  'boundary' : {
379  'enabled' : True
380  },
381  },
382  'selectThresh' : {
383  'value' : 10,
384  'units' : 'screen pixels'
385  },
386  'checkForDupl' : {
387  'enabled' : False
388  },
389  'selectInside' : {
390  'enabled' : False
391  },
392  # exit
393  'saveOnExit' : {
394  'enabled' : False,
395  },
396  # break lines on intersection
397  'breakLines' : {
398  'enabled' : False,
399  },
400  },
401  'profile': {
402  'raster0' : {
403  'pcolor' : (0, 0, 255, 255), # profile line color
404  'pwidth' : 1, # profile line width
405  'pstyle' : 'solid', # profile line pen style
406  },
407  'raster1' : {
408  'pcolor' : (255, 0, 0, 255),
409  'pwidth' : 1,
410  'pstyle' : 'solid',
411  },
412  'raster2' : {
413  'pcolor' : (0, 255, 0, 255),
414  'pwidth' : 1,
415  'pstyle' : 'solid',
416  },
417  'font' : {
418  'titleSize' : 12,
419  'axisSize' : 11,
420  'legendSize' : 10,
421  },
422  'marker' : {
423  'color' : (0, 0, 0, 255),
424  'fill' : 'transparent',
425  'size' : 2,
426  'type' : 'triangle',
427  'legend' : _('Segment break'),
428  },
429  'grid' : {
430  'color' : (200, 200, 200, 255),
431  'enabled' : True,
432  },
433  'x-axis' : {
434  'type' : 'auto', # axis format
435  'min' : 0, # axis min for custom axis range
436  'max': 0, # axis max for custom axis range
437  'log' : False,
438  },
439  'y-axis' : {
440  'type' : 'auto', # axis format
441  'min' : 0, # axis min for custom axis range
442  'max': 0, # axis max for custom axis range
443  'log' : False,
444  },
445  'legend' : {
446  'enabled' : True
447  },
448  },
449  'gcpman' : {
450  'rms' : {
451  'highestonly' : True,
452  'sdfactor' : 1,
453  },
454  'symbol' : {
455  'color' : (0, 0, 255, 255),
456  'hcolor' : (255, 0, 0, 255),
457  'scolor' : (0, 255, 0, 255),
458  'ucolor' : (255, 165, 0, 255),
459  'unused' : True,
460  'size' : 8,
461  'width' : 2,
462  },
463  },
464  'georect' : {
465  'symbol' : {
466  'color' : (0, 0, 255, 255),
467  'width' : 2,
468  },
469  },
470  'nviz' : {
471  'view' : {
472  'persp' : {
473  'value' : 20,
474  'step' : 5,
475  },
476  'position' : {
477  'x' : 0.84,
478  'y' : 0.16,
479  },
480  'height' : {
481  'step' : 100,
482  },
483  'twist' : {
484  'value' : 0,
485  'step' : 5,
486  },
487  'z-exag' : {
488  'step' : 1,
489  },
490  'background' : {
491  'color' : (255, 255, 255, 255), # white
492  },
493  },
494  'surface' : {
495  'shine': {
496  'map' : False,
497  'value' : 60.0,
498  },
499  'color' : {
500  'map' : True,
501  'value' : (0, 0, 0, 255), # constant: black
502  },
503  'draw' : {
504  'wire-color' : (136, 136, 136, 255),
505  'mode' : 1, # fine
506  'style' : 1, # surface
507  'shading' : 1, # gouraud
508  'res-fine' : 6,
509  'res-coarse' : 9,
510  },
511  'position' : {
512  'x' : 0,
513  'y' : 0,
514  'z' : 0,
515  },
516  },
517  'vector' : {
518  'lines' : {
519  'show' : False,
520  'width' : 2,
521  'color' : (0, 0, 255, 255), # blue
522  'flat' : False,
523  'height' : 0,
524  },
525  'points' : {
526  'show' : False,
527  'size' : 100,
528  'width' : 2,
529  'marker' : 2,
530  'color' : (0, 0, 255, 255), # blue
531  'height' : 0,
532  }
533  },
534  'volume' : {
535  'color' : {
536  'map' : True,
537  'value' : (0, 0, 0, 255), # constant: black
538  },
539  'draw' : {
540  'mode' : 0, # isosurfaces
541  'shading' : 1, # gouraud
542  'resolution' : 3, # polygon resolution
543  },
544  'shine': {
545  'map' : False,
546  'value' : 60,
547  },
548  },
549  'light' : {
550  'position' : {
551  'x' : 0.68,
552  'y' : 0.68,
553  'z' : 80,
554  },
555  'bright' : 80,
556  'color' : (255, 255, 255, 255), # white
557  'ambient' : 20,
558  },
559  'fringe' : {
560  'elev' : 55,
561  'color' : (128, 128, 128, 255), # grey
562  },
563  },
564  'modeler' : {
565  'disabled': {
566  'color': (211, 211, 211, 255), # light grey
567  },
568  'action' : {
569  'color' : {
570  'valid' : (180, 234, 154, 255), # light green
571  'invalid' : (255, 255, 255, 255), # white
572  'running' : (255, 0, 0, 255), # red
573  },
574  'size' : {
575  'width' : 100,
576  'height' : 50,
577  },
578  'width': {
579  'parameterized' : 2,
580  'default' : 1,
581  },
582  },
583  'data' : {
584  'color': {
585  'raster' : (215, 215, 248, 255), # light blue
586  'raster3d' : (215, 248, 215, 255), # light green
587  'vector' : (248, 215, 215, 255), # light red
588  },
589  'size' : {
590  'width' : 175,
591  'height' : 50,
592  },
593  },
594  'loop' : {
595  'color' : {
596  'valid' : (234, 226, 154, 255), # light yellow
597  },
598  'size' : {
599  'width' : 175,
600  'height' : 40,
601  },
602  },
603  'if-else' : {
604  'size' : {
605  'width' : 150,
606  'height' : 40,
607  },
608  },
609  },
610  }
611 
612  # quick fix, http://trac.osgeo.org/grass/ticket/1233
613  # TODO
614  if sys.platform == 'darwin':
615  self.defaultSettings['general']['defWindowPos']['enabled'] = False
616 
617  #
618  # user settings
619  #
620  self.userSettings = copy.deepcopy(self.defaultSettings)
621  try:
622  self.ReadSettingsFile()
623  except gcmd.GException, e:
624  print >> sys.stderr, e.value
625 
626  #
627  # internal settings (based on user settings)
628  #
630  for group in self.userSettings.keys():
631  self.internalSettings[group] = {}
632  for key in self.userSettings[group].keys():
633  self.internalSettings[group][key] = {}
634 
635  # self.internalSettings['general']["mapsetPath"]['value'] = self.GetMapsetPath()
636  self.internalSettings['appearance']['elementListExpand']['choices'] = \
637  (_("Collapse all except PERMANENT and current"),
638  _("Collapse all except PERMANENT"),
639  _("Collapse all except current"),
640  _("Collapse all"),
641  _("Expand all"))
642  self.internalSettings['atm']['leftDbClick']['choices'] = (_('Edit selected record'),
643  _('Display selected'))
644 
645  self.internalSettings['cmd']['verbosity']['choices'] = ('grassenv',
646  'verbose',
647  'quiet')
648 
649  self.internalSettings['appearance']['iconTheme']['choices'] = ('grass',
650  'grass2',
651  'silk')
652  self.internalSettings['appearance']['menustyle']['choices'] = \
653  (_("Classic (labels only)"),
654  _("Combined (labels and module names)"),
655  _("Professional (module names only)"))
656  self.internalSettings['appearance']['gSelectPopupHeight']['min'] = 50
657  # there is also maxHeight given to TreeCtrlComboPopup.GetAdjustedSize
658  self.internalSettings['appearance']['gSelectPopupHeight']['max'] = 1000
659 
660  self.internalSettings['display']['driver']['choices'] = ['default']
661  self.internalSettings['display']['statusbarMode']['choices'] = globalvar.MAP_DISPLAY_STATUSBAR_MODE
662 
663  self.internalSettings['nviz']['view'] = {}
664  self.internalSettings['nviz']['view']['twist'] = {}
665  self.internalSettings['nviz']['view']['twist']['min'] = -180
666  self.internalSettings['nviz']['view']['twist']['max'] = 180
667  self.internalSettings['nviz']['view']['persp'] = {}
668  self.internalSettings['nviz']['view']['persp']['min'] = 1
669  self.internalSettings['nviz']['view']['persp']['max'] = 100
670  self.internalSettings['nviz']['view']['height'] = {}
671  self.internalSettings['nviz']['view']['height']['value'] = -1
672  self.internalSettings['nviz']['vector'] = {}
673  self.internalSettings['nviz']['vector']['points'] = {}
674  self.internalSettings['nviz']['vector']['points']['marker'] = ("x",
675  _("box"),
676  _("sphere"),
677  _("cube"),
678  _("diamond"),
679  _("dtree"),
680  _("ctree"),
681  _("aster"),
682  _("gyro"),
683  _("histogram"))
684  self.internalSettings['vdigit']['bgmap'] = {}
685  self.internalSettings['vdigit']['bgmap']['value'] = ''
686 
687  def ReadSettingsFile(self, settings = None):
688  """!Reads settings file (mapset, location, gisdbase)"""
689  if settings is None:
690  settings = self.userSettings
691 
692  self._readFile(self.filePath, settings)
693 
694  # set environment variables
695  font = self.Get(group = 'display', key = 'font', subkey = 'type')
696  enc = self.Get(group = 'display', key = 'font', subkey = 'encoding')
697  if font:
698  os.environ["GRASS_FONT"] = font
699  if enc:
700  os.environ["GRASS_ENCODING"] = enc
701 
702  def _readFile(self, filename, settings = None):
703  """!Read settings from file to dict
704 
705  @param filename settings file path
706  @param settings dict where to store settings (None for self.userSettings)
707  """
708  if settings is None:
709  settings = self.userSettings
710 
711  if not os.path.exists(filename):
712  # try alternative path
713  filename = os.path.join(os.path.expanduser("~"), '.grasswx6')
714  if not os.path.exists(filename):
715  return
716 
717  try:
718  fd = open(filename, "r")
719  except IOError:
720  sys.stderr.write(_("Unable to read settings file <%s>\n") % filename)
721  return
722 
723  try:
724  line = ''
725  for line in fd.readlines():
726  line = line.rstrip('%s' % os.linesep)
727  group, key = line.split(self.sep)[0:2]
728  kv = line.split(self.sep)[2:]
729  subkeyMaster = None
730  if len(kv) % 2 != 0: # multiple (e.g. nviz)
731  subkeyMaster = kv[0]
732  del kv[0]
733  idx = 0
734  while idx < len(kv):
735  if subkeyMaster:
736  subkey = [subkeyMaster, kv[idx]]
737  else:
738  subkey = kv[idx]
739  value = kv[idx+1]
740  value = self._parseValue(value, read = True)
741  self.Append(settings, group, key, subkey, value)
742  idx += 2
743  except ValueError, e:
744  print >> sys.stderr, _("Error: Reading settings from file <%(file)s> failed.\n"
745  "\t\tDetails: %(detail)s\n"
746  "\t\tLine: '%(line)s'\n") % { 'file' : filename,
747  'detail' : e,
748  'line' : line }
749  fd.close()
750 
751  fd.close()
752 
753  def SaveToFile(self, settings = None):
754  """!Save settings to the file"""
755  if settings is None:
756  settings = self.userSettings
757 
758  dirPath = utils.GetSettingsPath()
759  if not os.path.exists(dirPath):
760  try:
761  os.mkdir(dirPath)
762  except:
763  gcmd.GError(_('Unable to create settings directory'))
764  return
765 
766  try:
767  file = open(self.filePath, "w")
768  for group in settings.keys():
769  for key in settings[group].keys():
770  subkeys = settings[group][key].keys()
771  file.write('%s%s%s%s' % (group, self.sep, key, self.sep))
772  for idx in range(len(subkeys)):
773  value = settings[group][key][subkeys[idx]]
774  if type(value) == types.DictType:
775  if idx > 0:
776  file.write('%s%s%s%s%s' % (os.linesep, group, self.sep, key, self.sep))
777  file.write('%s%s' % (subkeys[idx], self.sep))
778  kvalues = settings[group][key][subkeys[idx]].keys()
779  srange = range(len(kvalues))
780  for sidx in srange:
781  svalue = self._parseValue(settings[group][key][subkeys[idx]][kvalues[sidx]])
782  file.write('%s%s%s' % (kvalues[sidx], self.sep,
783  svalue))
784  if sidx < len(kvalues) - 1:
785  file.write('%s' % self.sep)
786  else:
787  if idx > 0 and \
788  type(settings[group][key][subkeys[idx - 1]]) == types.DictType:
789  file.write('%s%s%s%s%s' % (os.linesep, group, self.sep, key, self.sep))
790  value = self._parseValue(settings[group][key][subkeys[idx]])
791  file.write('%s%s%s' % (subkeys[idx], self.sep, value))
792  if idx < len(subkeys) - 1 and \
793  type(settings[group][key][subkeys[idx + 1]]) != types.DictType:
794  file.write('%s' % self.sep)
795  file.write(os.linesep)
796  except IOError, e:
797  raise gcmd.GException(e)
798  except StandardError, e:
799  raise gcmd.GException(_('Writing settings to file <%(file)s> failed.'
800  '\n\nDetails: %(detail)s') % { 'file' : self.filePath,
801  'detail' : e })
802 
803  file.close()
804 
805  def _parseValue(self, value, read = False):
806  """!Parse value to be store in settings file"""
807  if read: # -> read settings (cast values)
808  if value == 'True':
809  value = True
810  elif value == 'False':
811  value = False
812  elif value == 'None':
813  value = None
814  elif ':' in value: # -> color
815  try:
816  value = tuple(map(int, value.split(':')))
817  except ValueError: # -> string
818  pass
819  else:
820  try:
821  value = int(value)
822  except ValueError:
823  try:
824  value = float(value)
825  except ValueError:
826  pass
827  else: # -> write settings
828  if type(value) == type(()): # -> color
829  value = str(value[0]) + ':' +\
830  str(value[1]) + ':' + \
831  str(value[2])
832 
833  return value
834 
835  def Get(self, group, key = None, subkey = None, internal = False):
836  """!Get value by key/subkey
837 
838  Raise KeyError if key is not found
839 
840  @param group settings group
841  @param key (value, None)
842  @param subkey (value, list or None)
843  @param internal use internal settings instead
844 
845  @return value
846  """
847  if internal is True:
848  settings = self.internalSettings
849  else:
850  settings = self.userSettings
851 
852  try:
853  if subkey is None:
854  if key is None:
855  return settings[group]
856  else:
857  return settings[group][key]
858  else:
859  if type(subkey) == type(tuple()) or \
860  type(subkey) == type(list()):
861  return settings[group][key][subkey[0]][subkey[1]]
862  else:
863  return settings[group][key][subkey]
864 
865  except KeyError:
866  print >> sys.stderr, "Settings: unable to get value '%s:%s:%s'\n" % \
867  (group, key, subkey)
868 
869  def Set(self, group, value, key = None, subkey = None, internal = False):
870  """!Set value of key/subkey
871 
872  Raise KeyError if group/key is not found
873 
874  @param group settings group
875  @param key key (value, None)
876  @param subkey subkey (value, list or None)
877  @param value value
878  @param internal use internal settings instead
879  """
880  if internal is True:
881  settings = self.internalSettings
882  else:
883  settings = self.userSettings
884 
885  try:
886  if subkey is None:
887  if key is None:
888  settings[group] = value
889  else:
890  settings[group][key] = value
891  else:
892  if type(subkey) == type(tuple()) or \
893  type(subkey) == type(list()):
894  settings[group][key][subkey[0]][subkey[1]] = value
895  else:
896  settings[group][key][subkey] = value
897  except KeyError:
898  raise gcmd.GException("%s '%s:%s:%s'" % (_("Unable to set "), group, key, subkey))
899 
900  def Append(self, dict, group, key, subkey, value):
901  """!Set value of key/subkey
902 
903  Create group/key/subkey if not exists
904 
905  @param dict settings dictionary to use
906  @param group settings group
907  @param key key
908  @param subkey subkey (value or list)
909  @param value value
910  """
911  if group not in dict:
912  dict[group] = {}
913 
914  if key not in dict[group]:
915  dict[group][key] = {}
916 
917  if type(subkey) == types.ListType:
918  # TODO: len(subkey) > 2
919  if subkey[0] not in dict[group][key]:
920  dict[group][key][subkey[0]] = {}
921  try:
922  dict[group][key][subkey[0]][subkey[1]] = value
923  except TypeError:
924  print >> sys.stderr, _("Unable to parse settings '%s'") % value + \
925  ' (' + group + ':' + key + ':' + subkey[0] + ':' + subkey[1] + ')'
926  else:
927  try:
928  dict[group][key][subkey] = value
929  except TypeError:
930  print >> sys.stderr, _("Unable to parse settings '%s'") % value + \
931  ' (' + group + ':' + key + ':' + subkey + ')'
932 
934  """!Get default user settings"""
935  return self.defaultSettings
936 
937 globalSettings = Settings()
938 
939 class PreferencesBaseDialog(wx.Dialog):
940  """!Base preferences dialog"""
941  def __init__(self, parent, settings, title = _("User settings"),
942  size = (500, 375),
943  style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
944  self.parent = parent # ModelerFrame
945  self.title = title
946  self.size = size
947  self.settings = settings
948 
949  wx.Dialog.__init__(self, parent = parent, id = wx.ID_ANY, title = title,
950  style = style)
951 
952  # notebook
953  self.notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
954 
955  # dict for window ids
956  self.winId = {}
957 
958  # create notebook pages
959 
960  # buttons
961  self.btnDefault = wx.Button(self, wx.ID_ANY, _("Set to default"))
962  self.btnSave = wx.Button(self, wx.ID_SAVE)
963  self.btnApply = wx.Button(self, wx.ID_APPLY)
964  self.btnCancel = wx.Button(self, wx.ID_CANCEL)
965  self.btnSave.SetDefault()
966 
967  # bindigs
968  self.btnDefault.Bind(wx.EVT_BUTTON, self.OnDefault)
969  self.btnDefault.SetToolTipString(_("Revert settings to default and apply changes"))
970  self.btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
971  self.btnApply.SetToolTipString(_("Apply changes for the current session"))
972  self.btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
973  self.btnSave.SetToolTipString(_("Apply and save changes to user settings file (default for next sessions)"))
974  self.btnSave.SetDefault()
975  self.btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
976  self.btnCancel.SetToolTipString(_("Close dialog and ignore changes"))
977 
978  self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
979 
980  self._layout()
981 
982  def _layout(self):
983  """!Layout window"""
984  # sizers
985  btnSizer = wx.BoxSizer(wx.HORIZONTAL)
986  btnSizer.Add(item = self.btnDefault, proportion = 1,
987  flag = wx.ALL, border = 5)
988  btnStdSizer = wx.StdDialogButtonSizer()
989  btnStdSizer.AddButton(self.btnCancel)
990  btnStdSizer.AddButton(self.btnSave)
991  btnStdSizer.AddButton(self.btnApply)
992  btnStdSizer.Realize()
993 
994  mainSizer = wx.BoxSizer(wx.VERTICAL)
995  mainSizer.Add(item = self.notebook, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 5)
996  mainSizer.Add(item = btnSizer, proportion = 0,
997  flag = wx.EXPAND, border = 0)
998  mainSizer.Add(item = btnStdSizer, proportion = 0,
999  flag = wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT, border = 5)
1000 
1001  self.SetSizer(mainSizer)
1002  mainSizer.Fit(self)
1003 
1004  def OnDefault(self, event):
1005  """!Button 'Set to default' pressed"""
1006  self.settings.userSettings = copy.deepcopy(self.settings.defaultSettings)
1007 
1008  # update widgets
1009  for gks in self.winId.keys():
1010  try:
1011  group, key, subkey = gks.split(':')
1012  value = self.settings.Get(group, key, subkey)
1013  except ValueError:
1014  group, key, subkey, subkey1 = gks.split(':')
1015  value = self.settings.Get(group, key, [subkey, subkey1])
1016  win = self.FindWindowById(self.winId[gks])
1017  if win.GetName() in ('GetValue', 'IsChecked'):
1018  value = win.SetValue(value)
1019  elif win.GetName() == 'GetSelection':
1020  value = win.SetSelection(value)
1021  elif win.GetName() == 'GetStringSelection':
1022  value = win.SetStringSelection(value)
1023  else:
1024  value = win.SetValue(value)
1025 
1026  def OnApply(self, event):
1027  """!Button 'Apply' pressed
1028  Posts event EVT_SETTINGS_CHANGED.
1029  """
1030  if self._updateSettings():
1031  self.parent.goutput.WriteLog(_('Settings applied to current session but not saved'))
1032  event = wxSettingsChanged()
1033  wx.PostEvent(self, event)
1034  self.Close()
1035 
1036  def OnCloseWindow(self, event):
1037  self.Hide()
1038 
1039  def OnCancel(self, event):
1040  """!Button 'Cancel' pressed"""
1041  self.Close()
1042 
1043  def OnSave(self, event):
1044  """!Button 'Save' pressed
1045  Posts event EVT_SETTINGS_CHANGED.
1046  """
1047  if self._updateSettings():
1048  self.settings.SaveToFile()
1049  self.parent.goutput.WriteLog(_('Settings saved to file \'%s\'.') % self.settings.filePath)
1050  event = wxSettingsChanged()
1051  wx.PostEvent(self, event)
1052  self.Close()
1053 
1054  def _updateSettings(self):
1055  """!Update user settings"""
1056  for item in self.winId.keys():
1057  try:
1058  group, key, subkey = item.split(':')
1059  subkey1 = None
1060  except ValueError:
1061  group, key, subkey, subkey1 = item.split(':')
1062 
1063  id = self.winId[item]
1064  win = self.FindWindowById(id)
1065  if win.GetName() == 'GetValue':
1066  value = win.GetValue()
1067  elif win.GetName() == 'GetSelection':
1068  value = win.GetSelection()
1069  elif win.GetName() == 'IsChecked':
1070  value = win.IsChecked()
1071  elif win.GetName() == 'GetStringSelection':
1072  value = win.GetStringSelection()
1073  elif win.GetName() == 'GetColour':
1074  value = tuple(win.GetValue())
1075  else:
1076  value = win.GetValue()
1077 
1078  if key == 'keycolumn' and value == '':
1079  wx.MessageBox(parent = self,
1080  message = _("Key column cannot be empty string."),
1081  caption = _("Error"), style = wx.OK | wx.ICON_ERROR)
1082  win.SetValue(self.settings.Get(group = 'atm', key = 'keycolumn', subkey = 'value'))
1083  return False
1084 
1085  if subkey1:
1086  self.settings.Set(group, value, key, [subkey, subkey1])
1087  else:
1088  self.settings.Set(group, value, key, subkey)
1089 
1090  if self.parent.GetName() == 'Modeler':
1091  return True
1092 
1093  #
1094  # update default window dimension
1095  #
1096  if self.settings.Get(group = 'general', key = 'defWindowPos', subkey = 'enabled') is True:
1097  dim = ''
1098  # layer manager
1099  pos = self.parent.GetPosition()
1100  size = self.parent.GetSize()
1101  dim = '%d,%d,%d,%d' % (pos[0], pos[1], size[0], size[1])
1102  # opened displays
1103  for page in range(0, self.parent.gm_cb.GetPageCount()):
1104  pos = self.parent.gm_cb.GetPage(page).maptree.mapdisplay.GetPosition()
1105  size = self.parent.gm_cb.GetPage(page).maptree.mapdisplay.GetSize()
1106 
1107  dim += ',%d,%d,%d,%d' % (pos[0], pos[1], size[0], size[1])
1108 
1109  self.settings.Set(group = 'general', key = 'defWindowPos', subkey = 'dim', value = dim)
1110  else:
1111  self.settings.Set(group = 'general', key = 'defWindowPos', subkey = 'dim', value = '')
1112 
1113  return True
1114 
1116  """!User preferences dialog"""
1117  def __init__(self, parent, title = _("GUI Settings"),
1118  settings = globalSettings):
1119 
1120  PreferencesBaseDialog.__init__(self, parent = parent, title = title,
1121  settings = settings)
1122 
1123  # create notebook pages
1124  self._createGeneralPage(self.notebook)
1125  self._createAppearancePage(self.notebook)
1126  self._createDisplayPage(self.notebook)
1127  self._createCmdPage(self.notebook)
1129  self._createProjectionPage(self.notebook)
1130 
1131  self.SetMinSize(self.GetBestSize())
1132  self.SetSize(self.size)
1133 
1134  def _createGeneralPage(self, notebook):
1135  """!Create notebook page for general settings"""
1136  panel = wx.Panel(parent = notebook, id = wx.ID_ANY)
1137  notebook.AddPage(page = panel, text = _("General"))
1138 
1139  border = wx.BoxSizer(wx.VERTICAL)
1140  #
1141  # Layer Manager settings
1142  #
1143  box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Layer Manager settings"))
1144  sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
1145 
1146  gridSizer = wx.GridBagSizer (hgap = 3, vgap = 3)
1147  gridSizer.AddGrowableCol(0)
1148 
1149  #
1150  # ask when removing map layer from layer tree
1151  #
1152  row = 0
1153  askOnRemoveLayer = wx.CheckBox(parent = panel, id = wx.ID_ANY,
1154  label = _("Ask when removing map layer from layer tree"),
1155  name = 'IsChecked')
1156  askOnRemoveLayer.SetValue(self.settings.Get(group = 'manager', key = 'askOnRemoveLayer', subkey = 'enabled'))
1157  self.winId['manager:askOnRemoveLayer:enabled'] = askOnRemoveLayer.GetId()
1158 
1159  gridSizer.Add(item = askOnRemoveLayer,
1160  pos = (row, 0), span = (1, 2))
1161 
1162  row += 1
1163  askOnQuit = wx.CheckBox(parent = panel, id = wx.ID_ANY,
1164  label = _("Ask when quiting wxGUI or closing display"),
1165  name = 'IsChecked')
1166  askOnQuit.SetValue(self.settings.Get(group = 'manager', key = 'askOnQuit', subkey = 'enabled'))
1167  self.winId['manager:askOnQuit:enabled'] = askOnQuit.GetId()
1168 
1169  gridSizer.Add(item = askOnQuit,
1170  pos = (row, 0), span = (1, 2))
1171 
1172  row += 1
1173  hideSearch = wx.CheckBox(parent = panel, id = wx.ID_ANY,
1174  label = _("Hide '%s' tab (requires GUI restart)") % _("Search module"),
1175  name = 'IsChecked')
1176  hideSearch.SetValue(self.settings.Get(group = 'manager', key = 'hideTabs', subkey = 'search'))
1177  self.winId['manager:hideTabs:search'] = hideSearch.GetId()
1178 
1179  gridSizer.Add(item = hideSearch,
1180  pos = (row, 0), span = (1, 2))
1181 
1182  row += 1
1183  hidePyShell = wx.CheckBox(parent = panel, id = wx.ID_ANY,
1184  label = _("Hide '%s' tab (requires GUI restart)") % _("Python shell"),
1185  name = 'IsChecked')
1186  hidePyShell.SetValue(self.settings.Get(group = 'manager', key = 'hideTabs', subkey = 'pyshell'))
1187  self.winId['manager:hideTabs:pyshell'] = hidePyShell.GetId()
1188 
1189  gridSizer.Add(item = hidePyShell,
1190  pos = (row, 0), span = (1, 2))
1191 
1192  #
1193  # Selected text is copied to clipboard
1194  #
1195  row += 1
1196  copySelectedTextToClipboard = wx.CheckBox(parent = panel, id = wx.ID_ANY,
1197  label = _("Automatically copy selected text to clipboard (in Command console)"),
1198  name = 'IsChecked')
1199  copySelectedTextToClipboard.SetValue(self.settings.Get(group = 'manager', key = 'copySelectedTextToClipboard', subkey = 'enabled'))
1200  self.winId['manager:copySelectedTextToClipboard:enabled'] = copySelectedTextToClipboard.GetId()
1201 
1202  gridSizer.Add(item = copySelectedTextToClipboard,
1203  pos = (row, 0), span = (1, 2))
1204 
1205  sizer.Add(item = gridSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 5)
1206  border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 3)
1207 
1208  #
1209  # workspace
1210  #
1211  box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Workspace settings"))
1212  sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
1213 
1214  gridSizer = wx.GridBagSizer (hgap = 3, vgap = 3)
1215  gridSizer.AddGrowableCol(0)
1216 
1217  row = 0
1218  posDisplay = wx.CheckBox(parent = panel, id = wx.ID_ANY,
1219  label = _("Suppress positioning Map Display Window(s)"),
1220  name = 'IsChecked')
1221  posDisplay.SetValue(self.settings.Get(group = 'general', key = 'workspace',
1222  subkey = ['posDisplay', 'enabled']))
1223  self.winId['general:workspace:posDisplay:enabled'] = posDisplay.GetId()
1224 
1225  gridSizer.Add(item = posDisplay,
1226  pos = (row, 0), span = (1, 2))
1227 
1228  row += 1
1229 
1230  posManager = wx.CheckBox(parent = panel, id = wx.ID_ANY,
1231  label = _("Suppress positioning Layer Manager window"),
1232  name = 'IsChecked')
1233  posManager.SetValue(self.settings.Get(group = 'general', key = 'workspace',
1234  subkey = ['posManager', 'enabled']))
1235  self.winId['general:workspace:posManager:enabled'] = posManager.GetId()
1236 
1237  gridSizer.Add(item = posManager,
1238  pos = (row, 0), span = (1, 2))
1239 
1240  row += 1
1241  defaultPos = wx.CheckBox(parent = panel, id = wx.ID_ANY,
1242  label = _("Save current window layout as default"),
1243  name = 'IsChecked')
1244  defaultPos.SetValue(self.settings.Get(group = 'general', key = 'defWindowPos', subkey = 'enabled'))
1245  defaultPos.SetToolTip(wx.ToolTip (_("Save current position and size of Layer Manager window and opened "
1246  "Map Display window(s) and use as default for next sessions.")))
1247  self.winId['general:defWindowPos:enabled'] = defaultPos.GetId()
1248 
1249  gridSizer.Add(item = defaultPos,
1250  pos = (row, 0), span = (1, 2))
1251 
1252  sizer.Add(item = gridSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 5)
1253  border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 3)
1254 
1255  panel.SetSizer(border)
1256 
1257  return panel
1258 
1259 
1260  panel.SetSizer(border)
1261 
1262  return panel
1263 
1264  def _createAppearancePage(self, notebook):
1265  """!Create notebook page for display settings"""
1266 
1267  panel = wx.Panel(parent = notebook, id = wx.ID_ANY)
1268  notebook.AddPage(page = panel, text = _("Appearance"))
1269 
1270  border = wx.BoxSizer(wx.VERTICAL)
1271 
1272  box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Font settings"))
1273  sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
1274 
1275  gridSizer = wx.GridBagSizer (hgap = 3, vgap = 3)
1276  gridSizer.AddGrowableCol(0)
1277 
1278  #
1279  # font settings
1280  #
1281  sizer.Add(item = gridSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 5)
1282  border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 3)
1283 
1284  row = 0
1285  gridSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY,
1286  label = _("Font for command output:")),
1287  flag = wx.ALIGN_LEFT |
1288  wx.ALIGN_CENTER_VERTICAL,
1289  pos = (row, 0))
1290  outfontButton = wx.Button(parent = panel, id = wx.ID_ANY,
1291  label = _("Set font"), size = (100, -1))
1292  gridSizer.Add(item = outfontButton,
1293  flag = wx.ALIGN_RIGHT |
1294  wx.ALIGN_CENTER_VERTICAL,
1295  pos = (row, 1))
1296 
1297  #
1298  # appearence
1299  #
1300  box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Appearance settings"))
1301  sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
1302 
1303  gridSizer = wx.GridBagSizer (hgap = 3, vgap = 3)
1304  gridSizer.AddGrowableCol(0)
1305 
1306  #
1307  # element list
1308  #
1309  row = 0
1310  gridSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY,
1311  label = _("Element list:")),
1312  flag = wx.ALIGN_LEFT |
1313  wx.ALIGN_CENTER_VERTICAL,
1314  pos = (row, 0))
1315  elementList = wx.Choice(parent = panel, id = wx.ID_ANY, size = (325, -1),
1316  choices = self.settings.Get(group = 'appearance', key = 'elementListExpand',
1317  subkey = 'choices', internal = True),
1318  name = "GetSelection")
1319  elementList.SetSelection(self.settings.Get(group = 'appearance', key = 'elementListExpand',
1320  subkey = 'selection'))
1321  self.winId['appearance:elementListExpand:selection'] = elementList.GetId()
1322 
1323  gridSizer.Add(item = elementList,
1324  flag = wx.ALIGN_RIGHT |
1325  wx.ALIGN_CENTER_VERTICAL,
1326  pos = (row, 1))
1327 
1328  #
1329  # menu style
1330  #
1331  row += 1
1332  gridSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY,
1333  label = _("Menu style (requires GUI restart):")),
1334  flag = wx.ALIGN_LEFT |
1335  wx.ALIGN_CENTER_VERTICAL,
1336  pos = (row, 0))
1337  listOfStyles = self.settings.Get(group = 'appearance', key = 'menustyle',
1338  subkey = 'choices', internal = True)
1339 
1340  menuItemText = wx.Choice(parent = panel, id = wx.ID_ANY, size = (325, -1),
1341  choices = listOfStyles,
1342  name = "GetSelection")
1343  menuItemText.SetSelection(self.settings.Get(group = 'appearance', key = 'menustyle', subkey = 'selection'))
1344 
1345  self.winId['appearance:menustyle:selection'] = menuItemText.GetId()
1346 
1347  gridSizer.Add(item = menuItemText,
1348  flag = wx.ALIGN_RIGHT,
1349  pos = (row, 1))
1350 
1351  #
1352  # gselect.TreeCtrlComboPopup height
1353  #
1354  row += 1
1355 
1356  gridSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY,
1357  label = _("Height of map selection popup window (in pixels):")),
1358  flag = wx.ALIGN_LEFT |
1359  wx.ALIGN_CENTER_VERTICAL,
1360  pos = (row, 0))
1361  min = self.settings.Get(group = 'appearance', key = 'gSelectPopupHeight', subkey = 'min', internal = True)
1362  max = self.settings.Get(group = 'appearance', key = 'gSelectPopupHeight', subkey = 'max', internal = True)
1363  value = self.settings.Get(group = 'appearance', key = 'gSelectPopupHeight', subkey = 'value')
1364 
1365  popupHeightSpin = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = (100, -1))
1366  popupHeightSpin.SetRange(min,max)
1367  popupHeightSpin.SetValue(value)
1368 
1369  self.winId['appearance:gSelectPopupHeight:value'] = popupHeightSpin.GetId()
1370 
1371  gridSizer.Add(item = popupHeightSpin,
1372  flag = wx.ALIGN_RIGHT,
1373  pos = (row, 1))
1374 
1375 
1376  #
1377  # icon theme
1378  #
1379  row += 1
1380  gridSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY,
1381  label = _("Icon theme (requires GUI restart):")),
1382  flag = wx.ALIGN_LEFT |
1383  wx.ALIGN_CENTER_VERTICAL,
1384  pos = (row, 0))
1385  iconTheme = wx.Choice(parent = panel, id = wx.ID_ANY, size = (100, -1),
1386  choices = self.settings.Get(group = 'appearance', key = 'iconTheme',
1387  subkey = 'choices', internal = True),
1388  name = "GetStringSelection")
1389  iconTheme.SetStringSelection(self.settings.Get(group = 'appearance', key = 'iconTheme', subkey = 'type'))
1390  self.winId['appearance:iconTheme:type'] = iconTheme.GetId()
1391 
1392  gridSizer.Add(item = iconTheme,
1393  flag = wx.ALIGN_RIGHT |
1394  wx.ALIGN_CENTER_VERTICAL,
1395  pos = (row, 1))
1396 
1397  sizer.Add(item = gridSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 5)
1398  border.Add(item = sizer, proportion = 0, flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
1399 
1400  panel.SetSizer(border)
1401 
1402  # bindings
1403  outfontButton.Bind(wx.EVT_BUTTON, self.OnSetOutputFont)
1404 
1405  return panel
1406 
1407  def _createDisplayPage(self, notebook):
1408  """!Create notebook page for display settings"""
1409 
1410  panel = wx.Panel(parent = notebook, id = wx.ID_ANY)
1411  notebook.AddPage(page = panel, text = _("Map Display"))
1412 
1413  border = wx.BoxSizer(wx.VERTICAL)
1414 
1415  box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Font settings"))
1416  sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
1417 
1418  gridSizer = wx.GridBagSizer (hgap = 3, vgap = 3)
1419  gridSizer.AddGrowableCol(0)
1420 
1421  #
1422  # font settings
1423  #
1424  row = 0
1425  gridSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY,
1426  label = _("Default font for GRASS displays:")),
1427  flag = wx.ALIGN_LEFT |
1428  wx.ALIGN_CENTER_VERTICAL,
1429  pos = (row, 0))
1430  fontButton = wx.Button(parent = panel, id = wx.ID_ANY,
1431  label = _("Set font"), size = (100, -1))
1432  gridSizer.Add(item = fontButton,
1433  flag = wx.ALIGN_RIGHT |
1434  wx.ALIGN_CENTER_VERTICAL,
1435  pos = (row, 1))
1436 
1437  sizer.Add(item = gridSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 5)
1438  border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 3)
1439 
1440  #
1441  # display settings
1442  #
1443  box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Default display settings"))
1444  sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
1445 
1446  gridSizer = wx.GridBagSizer (hgap = 3, vgap = 3)
1447  gridSizer.AddGrowableCol(0)
1448 
1449 
1450  #
1451  # display driver
1452  #
1453  row = 0
1454  gridSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY,
1455  label = _("Display driver:")),
1456  flag = wx.ALIGN_LEFT |
1457  wx.ALIGN_CENTER_VERTICAL,
1458  pos=(row, 0))
1459  listOfDrivers = self.settings.Get(group='display', key='driver', subkey='choices', internal=True)
1460  # check if cairo is available
1461  if 'cairo' not in listOfDrivers:
1462  for line in gcmd.RunCommand('d.mon',
1463  flags = 'l',
1464  read = True).splitlines():
1465  if 'cairo' in line:
1466  listOfDrivers.append('cairo')
1467  break
1468 
1469  driver = wx.Choice(parent=panel, id=wx.ID_ANY, size=(150, -1),
1470  choices=listOfDrivers,
1471  name="GetStringSelection")
1472  driver.SetStringSelection(self.settings.Get(group='display', key='driver', subkey='type'))
1473  self.winId['display:driver:type'] = driver.GetId()
1474 
1475  gridSizer.Add(item = driver,
1476  flag = wx.ALIGN_RIGHT,
1477  pos = (row, 1))
1478 
1479 
1480  #
1481  # Statusbar mode
1482  #
1483  row += 1
1484  gridSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY,
1485  label = _("Statusbar mode:")),
1486  flag = wx.ALIGN_LEFT |
1487  wx.ALIGN_CENTER_VERTICAL,
1488  pos = (row, 0))
1489  listOfModes = self.settings.Get(group = 'display', key = 'statusbarMode', subkey = 'choices', internal = True)
1490  statusbarMode = wx.Choice(parent = panel, id = wx.ID_ANY, size = (150, -1),
1491  choices = listOfModes,
1492  name = "GetSelection")
1493  statusbarMode.SetSelection(self.settings.Get(group = 'display', key = 'statusbarMode', subkey = 'selection'))
1494  self.winId['display:statusbarMode:selection'] = statusbarMode.GetId()
1495 
1496  gridSizer.Add(item = statusbarMode,
1497  flag = wx.ALIGN_RIGHT,
1498  pos = (row, 1))
1499 
1500  #
1501  # Background color
1502  #
1503  row += 1
1504  gridSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY,
1505  label = _("Background color:")),
1506  flag = wx.ALIGN_LEFT |
1507  wx.ALIGN_CENTER_VERTICAL,
1508  pos = (row, 0))
1509  bgColor = csel.ColourSelect(parent = panel, id = wx.ID_ANY,
1510  colour = self.settings.Get(group = 'display', key = 'bgcolor', subkey = 'color'),
1511  size = globalvar.DIALOG_COLOR_SIZE)
1512  bgColor.SetName('GetColour')
1513  self.winId['display:bgcolor:color'] = bgColor.GetId()
1514 
1515  gridSizer.Add(item = bgColor,
1516  flag = wx.ALIGN_RIGHT,
1517  pos = (row, 1))
1518 
1519  #
1520  # Use computation resolution
1521  #
1522  row += 1
1523  compResolution = wx.CheckBox(parent = panel, id = wx.ID_ANY,
1524  label = _("Constrain display resolution to computational settings"),
1525  name = "IsChecked")
1526  compResolution.SetValue(self.settings.Get(group = 'display', key = 'compResolution', subkey = 'enabled'))
1527  self.winId['display:compResolution:enabled'] = compResolution.GetId()
1528 
1529  gridSizer.Add(item = compResolution,
1530  pos = (row, 0), span = (1, 2))
1531 
1532  #
1533  # auto-rendering
1534  #
1535  row += 1
1536  autoRendering = wx.CheckBox(parent = panel, id = wx.ID_ANY,
1537  label = _("Enable auto-rendering"),
1538  name = "IsChecked")
1539  autoRendering.SetValue(self.settings.Get(group = 'display', key = 'autoRendering', subkey = 'enabled'))
1540  self.winId['display:autoRendering:enabled'] = autoRendering.GetId()
1541 
1542  gridSizer.Add(item = autoRendering,
1543  pos = (row, 0), span = (1, 2))
1544 
1545  #
1546  # auto-zoom
1547  #
1548  row += 1
1549  autoZooming = wx.CheckBox(parent = panel, id = wx.ID_ANY,
1550  label = _("Enable auto-zooming to selected map layer"),
1551  name = "IsChecked")
1552  autoZooming.SetValue(self.settings.Get(group = 'display', key = 'autoZooming', subkey = 'enabled'))
1553  self.winId['display:autoZooming:enabled'] = autoZooming.GetId()
1554 
1555  gridSizer.Add(item = autoZooming,
1556  pos = (row, 0), span = (1, 2))
1557 
1558  sizer.Add(item = gridSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 5)
1559  border.Add(item = sizer, proportion = 0, flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
1560 
1561  panel.SetSizer(border)
1562 
1563  # bindings
1564  fontButton.Bind(wx.EVT_BUTTON, self.OnSetFont)
1565 
1566  return panel
1567 
1568  def _createCmdPage(self, notebook):
1569  """!Create notebook page for commad dialog settings"""
1570  panel = wx.Panel(parent = notebook, id = wx.ID_ANY)
1571  notebook.AddPage(page = panel, text = _("Command"))
1572 
1573  border = wx.BoxSizer(wx.VERTICAL)
1574  box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Command dialog settings"))
1575  sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
1576 
1577  gridSizer = wx.GridBagSizer (hgap = 3, vgap = 3)
1578  gridSizer.AddGrowableCol(0)
1579 
1580  #
1581  # command dialog settings
1582  #
1583  row = 0
1584  # overwrite
1585  overwrite = wx.CheckBox(parent = panel, id = wx.ID_ANY,
1586  label = _("Allow output files to overwrite existing files"),
1587  name = "IsChecked")
1588  overwrite.SetValue(self.settings.Get(group = 'cmd', key = 'overwrite', subkey = 'enabled'))
1589  self.winId['cmd:overwrite:enabled'] = overwrite.GetId()
1590 
1591  gridSizer.Add(item = overwrite,
1592  pos = (row, 0), span = (1, 2))
1593  row += 1
1594  # close
1595  close = wx.CheckBox(parent = panel, id = wx.ID_ANY,
1596  label = _("Close dialog when command is successfully finished"),
1597  name = "IsChecked")
1598  close.SetValue(self.settings.Get(group = 'cmd', key = 'closeDlg', subkey = 'enabled'))
1599  self.winId['cmd:closeDlg:enabled'] = close.GetId()
1600 
1601  gridSizer.Add(item = close,
1602  pos = (row, 0), span = (1, 2))
1603  row += 1
1604  # add layer
1605  add = wx.CheckBox(parent = panel, id = wx.ID_ANY,
1606  label = _("Add created map into layer tree"),
1607  name = "IsChecked")
1608  add.SetValue(self.settings.Get(group = 'cmd', key = 'addNewLayer', subkey = 'enabled'))
1609  self.winId['cmd:addNewLayer:enabled'] = add.GetId()
1610 
1611  gridSizer.Add(item = add,
1612  pos = (row, 0), span = (1, 2))
1613 
1614  row += 1
1615  # interactive input
1616  interactive = wx.CheckBox(parent = panel, id = wx.ID_ANY,
1617  label = _("Allow interactive input"),
1618  name = "IsChecked")
1619  interactive.SetValue(self.settings.Get(group = 'cmd', key = 'interactiveInput', subkey = 'enabled'))
1620  self.winId['cmd:interactiveInput:enabled'] = interactive.GetId()
1621  gridSizer.Add(item = interactive,
1622  pos = (row, 0), span = (1, 2))
1623 
1624  row += 1
1625  # verbosity
1626  gridSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY,
1627  label = _("Verbosity level:")),
1628  flag = wx.ALIGN_LEFT |
1629  wx.ALIGN_CENTER_VERTICAL,
1630  pos = (row, 0))
1631  verbosity = wx.Choice(parent = panel, id = wx.ID_ANY, size = (200, -1),
1632  choices = self.settings.Get(group = 'cmd', key = 'verbosity', subkey = 'choices', internal = True),
1633  name = "GetStringSelection")
1634  verbosity.SetStringSelection(self.settings.Get(group = 'cmd', key = 'verbosity', subkey = 'selection'))
1635  self.winId['cmd:verbosity:selection'] = verbosity.GetId()
1636 
1637  gridSizer.Add(item = verbosity,
1638  pos = (row, 1))
1639 
1640  sizer.Add(item = gridSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 5)
1641  border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 3)
1642 
1643  #
1644  # raster settings
1645  #
1646  box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Raster settings"))
1647  sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
1648 
1649  gridSizer = wx.GridBagSizer (hgap = 3, vgap = 3)
1650  gridSizer.AddGrowableCol(0)
1651 
1652  #
1653  # raster overlay
1654  #
1655  row = 0
1656  rasterOverlay = wx.CheckBox(parent=panel, id=wx.ID_ANY,
1657  label=_("Overlay raster maps"),
1658  name='IsChecked')
1659  rasterOverlay.SetValue(self.settings.Get(group='cmd', key='rasterOverlay', subkey='enabled'))
1660  self.winId['cmd:rasterOverlay:enabled'] = rasterOverlay.GetId()
1661 
1662  gridSizer.Add(item=rasterOverlay,
1663  pos=(row, 0), span=(1, 2))
1664 
1665  # default color table
1666  row += 1
1667  rasterCTCheck = wx.CheckBox(parent = panel, id = wx.ID_ANY,
1668  label = _("Default color table"),
1669  name = 'IsChecked')
1670  rasterCTCheck.SetValue(self.settings.Get(group = 'cmd', key = 'rasterColorTable', subkey = 'enabled'))
1671  self.winId['cmd:rasterColorTable:enabled'] = rasterCTCheck.GetId()
1672  rasterCTCheck.Bind(wx.EVT_CHECKBOX, self.OnCheckColorTable)
1673 
1674  gridSizer.Add(item = rasterCTCheck,
1675  pos = (row, 0))
1676 
1677  rasterCTName = wx.Choice(parent = panel, id = wx.ID_ANY, size = (200, -1),
1678  choices = utils.GetColorTables(),
1679  name = "GetStringSelection")
1680  rasterCTName.SetStringSelection(self.settings.Get(group = 'cmd', key = 'rasterColorTable', subkey = 'selection'))
1681  self.winId['cmd:rasterColorTable:selection'] = rasterCTName.GetId()
1682  if not rasterCTCheck.IsChecked():
1683  rasterCTName.Enable(False)
1684 
1685  gridSizer.Add(item = rasterCTName,
1686  pos = (row, 1))
1687 
1688  sizer.Add(item = gridSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 5)
1689  border.Add(item = sizer, proportion = 0, flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
1690 
1691  #
1692  # vector settings
1693  #
1694  box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Vector settings"))
1695  sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
1696 
1697  gridSizer = wx.FlexGridSizer (cols = 7, hgap = 3, vgap = 3)
1698 
1699  gridSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY,
1700  label = _("Display:")),
1701  flag = wx.ALIGN_CENTER_VERTICAL)
1702 
1703  for type in ('point', 'line', 'centroid', 'boundary',
1704  'area', 'face'):
1705  chkbox = wx.CheckBox(parent = panel, label = type)
1706  checked = self.settings.Get(group = 'cmd', key = 'showType',
1707  subkey = [type, 'enabled'])
1708  chkbox.SetValue(checked)
1709  self.winId['cmd:showType:%s:enabled' % type] = chkbox.GetId()
1710  gridSizer.Add(item = chkbox)
1711 
1712  sizer.Add(item = gridSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 5)
1713  border.Add(item = sizer, proportion = 0, flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
1714 
1715  panel.SetSizer(border)
1716 
1717  return panel
1718 
1719  def _createAttributeManagerPage(self, notebook):
1720  """!Create notebook page for 'Attribute Table Manager' settings"""
1721  panel = wx.Panel(parent = notebook, id = wx.ID_ANY)
1722  notebook.AddPage(page = panel, text = _("Attributes"))
1723 
1724  pageSizer = wx.BoxSizer(wx.VERTICAL)
1725 
1726  #
1727  # highlighting
1728  #
1729  highlightBox = wx.StaticBox(parent = panel, id = wx.ID_ANY,
1730  label = " %s " % _("Highlighting"))
1731  highlightSizer = wx.StaticBoxSizer(highlightBox, wx.VERTICAL)
1732 
1733  flexSizer = wx.FlexGridSizer (cols = 2, hgap = 5, vgap = 5)
1734  flexSizer.AddGrowableCol(0)
1735 
1736  label = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Color:"))
1737  hlColor = csel.ColourSelect(parent = panel, id = wx.ID_ANY,
1738  colour = self.settings.Get(group = 'atm', key = 'highlight', subkey = 'color'),
1739  size = globalvar.DIALOG_COLOR_SIZE)
1740  hlColor.SetName('GetColour')
1741  self.winId['atm:highlight:color'] = hlColor.GetId()
1742 
1743  flexSizer.Add(label, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
1744  flexSizer.Add(hlColor, proportion = 0, flag = wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
1745 
1746  label = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Line width (in pixels):"))
1747  hlWidth = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = (50, -1),
1748  initial = self.settings.Get(group = 'atm', key = 'highlight',subkey = 'width'),
1749  min = 1, max = 1e6)
1750  self.winId['atm:highlight:width'] = hlWidth.GetId()
1751 
1752  flexSizer.Add(label, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
1753  flexSizer.Add(hlWidth, proportion = 0, flag = wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
1754 
1755  highlightSizer.Add(item = flexSizer,
1756  proportion = 0,
1757  flag = wx.ALL | wx.EXPAND,
1758  border = 5)
1759 
1760  pageSizer.Add(item = highlightSizer,
1761  proportion = 0,
1762  flag = wx.ALL | wx.EXPAND,
1763  border = 5)
1764 
1765  #
1766  # data browser related settings
1767  #
1768  dataBrowserBox = wx.StaticBox(parent = panel, id = wx.ID_ANY,
1769  label = " %s " % _("Data browser"))
1770  dataBrowserSizer = wx.StaticBoxSizer(dataBrowserBox, wx.VERTICAL)
1771 
1772  flexSizer = wx.FlexGridSizer (cols = 2, hgap = 5, vgap = 5)
1773  flexSizer.AddGrowableCol(0)
1774  label = wx.StaticText(parent = panel, id = wx.ID_ANY, label = _("Left mouse double click:"))
1775  leftDbClick = wx.Choice(parent = panel, id = wx.ID_ANY,
1776  choices = self.settings.Get(group = 'atm', key = 'leftDbClick', subkey = 'choices', internal = True),
1777  name = "GetSelection")
1778  leftDbClick.SetSelection(self.settings.Get(group = 'atm', key = 'leftDbClick', subkey = 'selection'))
1779  self.winId['atm:leftDbClick:selection'] = leftDbClick.GetId()
1780 
1781  flexSizer.Add(label, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
1782  flexSizer.Add(leftDbClick, proportion = 0, flag = wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
1783 
1784  # encoding
1785  label = wx.StaticText(parent = panel, id = wx.ID_ANY,
1786  label = _("Encoding (e.g. utf-8, ascii, iso8859-1, koi8-r):"))
1787  encoding = wx.TextCtrl(parent = panel, id = wx.ID_ANY,
1788  value = self.settings.Get(group = 'atm', key = 'encoding', subkey = 'value'),
1789  name = "GetValue", size = (200, -1))
1790  self.winId['atm:encoding:value'] = encoding.GetId()
1791 
1792  flexSizer.Add(label, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
1793  flexSizer.Add(encoding, proportion = 0, flag = wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
1794 
1795  # ask on delete record
1796  askOnDeleteRec = wx.CheckBox(parent = panel, id = wx.ID_ANY,
1797  label = _("Ask when deleting data record(s) from table"),
1798  name = 'IsChecked')
1799  askOnDeleteRec.SetValue(self.settings.Get(group = 'atm', key = 'askOnDeleteRec', subkey = 'enabled'))
1800  self.winId['atm:askOnDeleteRec:enabled'] = askOnDeleteRec.GetId()
1801 
1802  flexSizer.Add(askOnDeleteRec, proportion = 0)
1803 
1804  dataBrowserSizer.Add(item = flexSizer,
1805  proportion = 0,
1806  flag = wx.ALL | wx.EXPAND,
1807  border = 5)
1808 
1809  pageSizer.Add(item = dataBrowserSizer,
1810  proportion = 0,
1811  flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND,
1812  border = 3)
1813 
1814  #
1815  # create table
1816  #
1817  createTableBox = wx.StaticBox(parent = panel, id = wx.ID_ANY,
1818  label = " %s " % _("Create table"))
1819  createTableSizer = wx.StaticBoxSizer(createTableBox, wx.VERTICAL)
1820 
1821  flexSizer = wx.FlexGridSizer (cols = 2, hgap = 5, vgap = 5)
1822  flexSizer.AddGrowableCol(0)
1823 
1824  label = wx.StaticText(parent = panel, id = wx.ID_ANY,
1825  label = _("Key column:"))
1826  keyColumn = wx.TextCtrl(parent = panel, id = wx.ID_ANY,
1827  size = (250, -1))
1828  keyColumn.SetValue(self.settings.Get(group = 'atm', key = 'keycolumn', subkey = 'value'))
1829  self.winId['atm:keycolumn:value'] = keyColumn.GetId()
1830 
1831  flexSizer.Add(label, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
1832  flexSizer.Add(keyColumn, proportion = 0, flag = wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
1833 
1834  createTableSizer.Add(item = flexSizer,
1835  proportion = 0,
1836  flag = wx.ALL | wx.EXPAND,
1837  border = 5)
1838 
1839  pageSizer.Add(item = createTableSizer,
1840  proportion = 0,
1841  flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND,
1842  border = 3)
1843 
1844  panel.SetSizer(pageSizer)
1845 
1846  return panel
1847 
1848  def _createProjectionPage(self, notebook):
1849  """!Create notebook page for workspace settings"""
1850  panel = wx.Panel(parent = notebook, id = wx.ID_ANY)
1851  notebook.AddPage(page = panel, text = _("Projection"))
1852 
1853  border = wx.BoxSizer(wx.VERTICAL)
1854 
1855  #
1856  # projections statusbar settings
1857  #
1858  box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Projection statusbar settings"))
1859  sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
1860 
1861  gridSizer = wx.GridBagSizer (hgap = 3, vgap = 3)
1862  gridSizer.AddGrowableCol(1)
1863 
1864  # epsg
1865  row = 0
1866  label = wx.StaticText(parent = panel, id = wx.ID_ANY,
1867  label = _("EPSG code:"))
1868  epsgCode = wx.ComboBox(parent = panel, id = wx.ID_ANY,
1869  name = "GetValue",
1870  size = (150, -1))
1871  self.epsgCodeDict = dict()
1872  epsgCode.SetValue(str(self.settings.Get(group = 'projection', key = 'statusbar', subkey = 'epsg')))
1873  self.winId['projection:statusbar:epsg'] = epsgCode.GetId()
1874 
1875  gridSizer.Add(item = label,
1876  pos = (row, 0),
1877  flag = wx.ALIGN_CENTER_VERTICAL)
1878  gridSizer.Add(item = epsgCode,
1879  pos = (row, 1), span = (1, 2))
1880 
1881  # proj
1882  row += 1
1883  label = wx.StaticText(parent = panel, id = wx.ID_ANY,
1884  label = _("Proj.4 string (required):"))
1885  projString = wx.TextCtrl(parent = panel, id = wx.ID_ANY,
1886  value = self.settings.Get(group = 'projection', key = 'statusbar', subkey = 'proj4'),
1887  name = "GetValue", size = (400, -1))
1888  self.winId['projection:statusbar:proj4'] = projString.GetId()
1889 
1890  gridSizer.Add(item = label,
1891  pos = (row, 0),
1892  flag = wx.ALIGN_CENTER_VERTICAL)
1893  gridSizer.Add(item = projString,
1894  pos = (row, 1), span = (1, 2),
1895  flag = wx.ALIGN_CENTER_VERTICAL)
1896 
1897  # epsg file
1898  row += 1
1899  label = wx.StaticText(parent = panel, id = wx.ID_ANY,
1900  label = _("EPSG file:"))
1901  projFile = wx.TextCtrl(parent = panel, id = wx.ID_ANY,
1902  value = self.settings.Get(group = 'projection', key = 'statusbar', subkey = 'projFile'),
1903  name = "GetValue", size = (400, -1))
1904  self.winId['projection:statusbar:projFile'] = projFile.GetId()
1905  gridSizer.Add(item = label,
1906  pos = (row, 0),
1907  flag = wx.ALIGN_CENTER_VERTICAL)
1908  gridSizer.Add(item = projFile,
1909  pos = (row, 1),
1910  flag = wx.ALIGN_CENTER_VERTICAL)
1911 
1912  # note + button
1913  row += 1
1914  note = wx.StaticText(parent = panel, id = wx.ID_ANY,
1915  label = _("Load EPSG codes (be patient), enter EPSG code or "
1916  "insert Proj.4 string directly."))
1917  gridSizer.Add(item = note,
1918  span = (1, 2),
1919  pos = (row, 0))
1920 
1921  row += 1
1922  epsgLoad = wx.Button(parent = panel, id = wx.ID_ANY,
1923  label = _("&Load EPSG codes"))
1924  gridSizer.Add(item = epsgLoad,
1925  flag = wx.ALIGN_RIGHT,
1926  pos = (row, 1))
1927 
1928  sizer.Add(item = gridSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 5)
1929  border.Add(item = sizer, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 3)
1930 
1931  #
1932  # format
1933  #
1934  box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Coordinates format"))
1935  sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
1936 
1937  gridSizer = wx.GridBagSizer (hgap = 3, vgap = 3)
1938  gridSizer.AddGrowableCol(2)
1939 
1940  row = 0
1941  # ll format
1942  ll = wx.RadioBox(parent = panel, id = wx.ID_ANY,
1943  label = " %s " % _("LL projections"),
1944  choices = ["DMS", "DEG"],
1945  name = "GetStringSelection")
1946  self.winId['projection:format:ll'] = ll.GetId()
1947  if self.settings.Get(group = 'projection', key = 'format', subkey = 'll') == 'DMS':
1948  ll.SetSelection(0)
1949  else:
1950  ll.SetSelection(1)
1951 
1952  # precision
1953  precision = wx.SpinCtrl(parent = panel, id = wx.ID_ANY,
1954  min = 0, max = 12,
1955  name = "GetValue")
1956  precision.SetValue(int(self.settings.Get(group = 'projection', key = 'format', subkey = 'precision')))
1957  self.winId['projection:format:precision'] = precision.GetId()
1958 
1959  gridSizer.Add(item = ll,
1960  pos = (row, 0))
1961  gridSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY,
1962  label = _("Precision:")),
1963  flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT,
1964  border = 20,
1965  pos = (row, 1))
1966  gridSizer.Add(item = precision,
1967  flag = wx.ALIGN_CENTER_VERTICAL,
1968  pos = (row, 2))
1969 
1970 
1971  sizer.Add(item = gridSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 5)
1972  border.Add(item = sizer, proportion = 0, flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 3)
1973 
1974  panel.SetSizer(border)
1975 
1976  # bindings
1977  epsgLoad.Bind(wx.EVT_BUTTON, self.OnLoadEpsgCodes)
1978  epsgCode.Bind(wx.EVT_COMBOBOX, self.OnSetEpsgCode)
1979  epsgCode.Bind(wx.EVT_TEXT_ENTER, self.OnSetEpsgCode)
1980 
1981  return panel
1982 
1983  def OnCheckColorTable(self, event):
1984  """!Set/unset default color table"""
1985  win = self.FindWindowById(self.winId['cmd:rasterColorTable:selection'])
1986  if event.IsChecked():
1987  win.Enable()
1988  else:
1989  win.Enable(False)
1990 
1991  def OnLoadEpsgCodes(self, event):
1992  """!Load EPSG codes from the file"""
1993  win = self.FindWindowById(self.winId['projection:statusbar:projFile'])
1994  path = win.GetValue()
1995 
1996  self.epsgCodeDict = utils.ReadEpsgCodes(path)
1997  list = self.FindWindowById(self.winId['projection:statusbar:epsg'])
1998  if type(self.epsgCodeDict) == type(''):
1999  wx.MessageBox(parent = self,
2000  message = _("Unable to read EPSG codes: %s") % self.epsgCodeDict,
2001  caption = _("Error"), style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
2002  self.epsgCodeDict = dict()
2003  list.SetItems([])
2004  list.SetValue('')
2005  self.FindWindowById(self.winId['projection:statusbar:proj4']).SetValue('')
2006  return
2007 
2008  choices = map(str, self.epsgCodeDict.keys())
2009 
2010  list.SetItems(choices)
2011  try:
2012  code = int(list.GetValue())
2013  except ValueError:
2014  code = -1
2015  win = self.FindWindowById(self.winId['projection:statusbar:proj4'])
2016  if code in self.epsgCodeDict:
2017  win.SetValue(self.epsgCodeDict[code][1])
2018  else:
2019  list.SetSelection(0)
2020  code = int(list.GetStringSelection())
2021  win.SetValue(self.epsgCodeDict[code][1])
2022 
2023  def OnSetEpsgCode(self, event):
2024  """!EPSG code selected"""
2025  winCode = self.FindWindowById(event.GetId())
2026  win = self.FindWindowById(self.winId['projection:statusbar:proj4'])
2027  if not self.epsgCodeDict:
2028  wx.MessageBox(parent = self,
2029  message = _("EPSG code %s not found") % event.GetString(),
2030  caption = _("Error"), style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
2031  winCode.SetValue('')
2032  win.SetValue('')
2033 
2034  try:
2035  code = int(event.GetString())
2036  except ValueError:
2037  wx.MessageBox(parent = self,
2038  message = _("EPSG code %s not found") % str(code),
2039  caption = _("Error"), style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
2040  winCode.SetValue('')
2041  win.SetValue('')
2042 
2043 
2044  try:
2045  win.SetValue(self.epsgCodeDict[code][1].replace('<>', '').strip())
2046  except KeyError:
2047  wx.MessageBox(parent = self,
2048  message = _("EPSG code %s not found") % str(code),
2049  caption = _("Error"), style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
2050  winCode.SetValue('')
2051  win.SetValue('')
2052 
2053  def OnSetFont(self, event):
2054  """'Set font' button pressed"""
2055  dlg = DefaultFontDialog(parent = self,
2056  title = _('Select default display font'),
2057  style = wx.DEFAULT_DIALOG_STYLE,
2058  type = 'font')
2059 
2060  if dlg.ShowModal() == wx.ID_OK:
2061  # set default font and encoding environmental variables
2062  if dlg.font:
2063  os.environ["GRASS_FONT"] = dlg.font
2064  self.settings.Set(group = 'display', value = dlg.font,
2065  key = 'font', subkey = 'type')
2066 
2067  if dlg.encoding and \
2068  dlg.encoding != "ISO-8859-1":
2069  os.environ["GRASS_ENCODING"] = dlg.encoding
2070  self.settings.Set(group = 'display', value = dlg.encoding,
2071  key = 'font', subkey = 'encoding')
2072 
2073  dlg.Destroy()
2074 
2075  event.Skip()
2076 
2077  def OnSetOutputFont(self, event):
2078  """'Set output font' button pressed
2079  """
2080  dlg = DefaultFontDialog(parent = self,
2081  title = _('Select output font'),
2082  style = wx.DEFAULT_DIALOG_STYLE,
2083  type = 'outputfont')
2084 
2085  if dlg.ShowModal() == wx.ID_OK:
2086  # set output font and font size variables
2087  if dlg.font:
2088  self.settings.Set(group = 'appearance', value = dlg.font,
2089  key = 'outputfont', subkey = 'type')
2090 
2091  self.settings.Set(group = 'appearance', value = dlg.fontsize,
2092  key = 'outputfont', subkey = 'size')
2093 
2094 # Standard font dialog broken for Mac in OS X 10.6
2095 # type = self.settings.Get(group = 'display', key = 'outputfont', subkey = 'type')
2096 
2097 # size = self.settings.Get(group = 'display', key = 'outputfont', subkey = 'size')
2098 # if size == None or size == 0: size = 10
2099 # size = float(size)
2100 
2101 # data = wx.FontData()
2102 # data.EnableEffects(True)
2103 # data.SetInitialFont(wx.Font(pointSize = size, family = wx.FONTFAMILY_MODERN, faceName = type, style = wx.NORMAL, weight = 0))
2104 
2105 # dlg = wx.FontDialog(self, data)
2106 
2107 # if dlg.ShowModal() == wx.ID_OK:
2108 # data = dlg.GetFontData()
2109 # font = data.GetChosenFont()
2110 
2111 # self.settings.Set(group = 'display', value = font.GetFaceName(),
2112 # key = 'outputfont', subkey = 'type')
2113 # self.settings.Set(group = 'display', value = font.GetPointSize(),
2114 # key = 'outputfont', subkey = 'size')
2115 
2116  dlg.Destroy()
2117 
2118  event.Skip()
2119 
2120 class DefaultFontDialog(wx.Dialog):
2121  """
2122  Opens a file selection dialog to select default font
2123  to use in all GRASS displays
2124  """
2125  def __init__(self, parent, title, id = wx.ID_ANY,
2126  style = wx.DEFAULT_DIALOG_STYLE |
2127  wx.RESIZE_BORDER,
2128  settings = globalSettings,
2129  type = 'font'):
2130 
2131  self.settings = settings
2132  self.type = type
2133 
2134  wx.Dialog.__init__(self, parent, id, title, style = style)
2135 
2136  panel = wx.Panel(parent = self, id = wx.ID_ANY)
2137 
2138  self.fontlist = self.GetFonts()
2139 
2140  border = wx.BoxSizer(wx.VERTICAL)
2141  box = wx.StaticBox (parent = panel, id = wx.ID_ANY, label = " %s " % _("Font settings"))
2142  sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
2143 
2144  gridSizer = wx.GridBagSizer (hgap = 5, vgap = 5)
2145  gridSizer.AddGrowableCol(0)
2146 
2147  label = wx.StaticText(parent = panel, id = wx.ID_ANY,
2148  label = _("Select font:"))
2149  gridSizer.Add(item = label,
2150  flag = wx.ALIGN_TOP,
2151  pos = (0,0))
2152 
2153  self.fontlb = wx.ListBox(parent = panel, id = wx.ID_ANY, pos = wx.DefaultPosition,
2154  choices = self.fontlist,
2155  style = wx.LB_SINGLE|wx.LB_SORT)
2156  self.Bind(wx.EVT_LISTBOX, self.EvtListBox, self.fontlb)
2157  self.Bind(wx.EVT_LISTBOX_DCLICK, self.EvtListBoxDClick, self.fontlb)
2158 
2159  gridSizer.Add(item = self.fontlb,
2160  flag = wx.EXPAND, pos = (1, 0))
2161 
2162  if self.type == 'font':
2163  if "GRASS_FONT" in os.environ:
2164  self.font = os.environ["GRASS_FONT"]
2165  else:
2166  self.font = self.settings.Get(group = 'display',
2167  key = 'font', subkey = 'type')
2168  self.encoding = self.settings.Get(group = 'display',
2169  key = 'font', subkey = 'encoding')
2170 
2171  label = wx.StaticText(parent = panel, id = wx.ID_ANY,
2172  label = _("Character encoding:"))
2173  gridSizer.Add(item = label,
2174  flag = wx.ALIGN_CENTER_VERTICAL,
2175  pos = (2, 0))
2176 
2177  self.textentry = wx.TextCtrl(parent = panel, id = wx.ID_ANY,
2178  value = self.encoding)
2179  gridSizer.Add(item = self.textentry,
2180  flag = wx.EXPAND, pos = (3, 0))
2181 
2182  self.textentry.Bind(wx.EVT_TEXT, self.OnEncoding)
2183 
2184  elif self.type == 'outputfont':
2185  self.font = self.settings.Get(group = 'appearance',
2186  key = 'outputfont', subkey = 'type')
2187  self.fontsize = self.settings.Get(group = 'appearance',
2188  key = 'outputfont', subkey = 'size')
2189  label = wx.StaticText(parent = panel, id = wx.ID_ANY,
2190  label = _("Font size:"))
2191  gridSizer.Add(item = label,
2192  flag = wx.ALIGN_CENTER_VERTICAL,
2193  pos = (2, 0))
2194 
2195  self.spin = wx.SpinCtrl(parent = panel, id = wx.ID_ANY)
2196  if self.fontsize:
2197  self.spin.SetValue(int(self.fontsize))
2198  self.spin.Bind(wx.EVT_SPINCTRL, self.OnSizeSpin)
2199  self.spin.Bind(wx.EVT_TEXT, self.OnSizeSpin)
2200  gridSizer.Add(item = self.spin,
2201  flag = wx.ALIGN_CENTER_VERTICAL,
2202  pos = (3, 0))
2203 
2204  else:
2205  return
2206 
2207  if self.font:
2208  self.fontlb.SetStringSelection(self.font, True)
2209 
2210  sizer.Add(item = gridSizer, proportion = 1,
2211  flag = wx.EXPAND | wx.ALL,
2212  border = 5)
2213 
2214  border.Add(item = sizer, proportion = 1,
2215  flag = wx.ALL | wx.EXPAND, border = 3)
2216 
2217  btnsizer = wx.StdDialogButtonSizer()
2218 
2219  btn = wx.Button(parent = panel, id = wx.ID_OK)
2220  btn.SetDefault()
2221  btnsizer.AddButton(btn)
2222 
2223  btn = wx.Button(parent = panel, id = wx.ID_CANCEL)
2224  btnsizer.AddButton(btn)
2225  btnsizer.Realize()
2226 
2227  border.Add(item = btnsizer, proportion = 0,
2228  flag = wx.EXPAND | wx.ALIGN_RIGHT | wx.ALL, border = 5)
2229 
2230  panel.SetAutoLayout(True)
2231  panel.SetSizer(border)
2232  border.Fit(self)
2233 
2234  self.Layout()
2235 
2236  def EvtRadioBox(self, event):
2237  if event.GetInt() == 0:
2238  self.fonttype = 'grassfont'
2239  elif event.GetInt() == 1:
2240  self.fonttype = 'truetype'
2241 
2242  self.fontlist = self.GetFonts(self.fonttype)
2243  self.fontlb.SetItems(self.fontlist)
2244 
2245  def OnEncoding(self, event):
2246  self.encoding = event.GetString()
2247 
2248  def EvtListBox(self, event):
2249  self.font = event.GetString()
2250  event.Skip()
2251 
2252  def EvtListBoxDClick(self, event):
2253  self.font = event.GetString()
2254  event.Skip()
2255 
2256  def OnSizeSpin(self, event):
2257  self.fontsize = self.spin.GetValue()
2258  event.Skip()
2259 
2260  def GetFonts(self):
2261  """
2262  parses fonts directory or fretypecap file to get a list of fonts for the listbox
2263  """
2264  fontlist = []
2265 
2266  cmd = ["d.font", "-l"]
2267 
2268  ret = gcmd.RunCommand('d.font',
2269  read = True,
2270  flags = 'l')
2271 
2272  if not ret:
2273  return fontlist
2274 
2275  dfonts = ret.splitlines()
2276  dfonts.sort(lambda x,y: cmp(x.lower(), y.lower()))
2277  for item in range(len(dfonts)):
2278  # ignore duplicate fonts and those starting with #
2279  if not dfonts[item].startswith('#') and \
2280  dfonts[item] != dfonts[item-1]:
2281  fontlist.append(dfonts[item])
2282 
2283  return fontlist
2284 
2285 class MapsetAccess(wx.Dialog):
2286  """!Controls setting options and displaying/hiding map overlay
2287  decorations
2288  """
2289  def __init__(self, parent, id = wx.ID_ANY,
2290  title = _('Manage access to mapsets'),
2291  size = (350, 400),
2292  style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
2293 
2294  wx.Dialog.__init__(self, parent, id, title, size = size, style = style, **kwargs)
2295 
2296  self.all_mapsets_ordered = utils.ListOfMapsets(get = 'ordered')
2297  self.accessible_mapsets = utils.ListOfMapsets(get = 'accessible')
2298  self.curr_mapset = grass.gisenv()['MAPSET']
2299 
2300  # make a checklistbox from available mapsets and check those that are active
2301  sizer = wx.BoxSizer(wx.VERTICAL)
2302 
2303  label = wx.StaticText(parent = self, id = wx.ID_ANY,
2304  label = _("Check a mapset to make it accessible, uncheck it to hide it.\n"
2305  " Notes:\n"
2306  " - The current mapset is always accessible.\n"
2307  " - You may only write to the current mapset.\n"
2308  " - You may only write to mapsets which you own."))
2309 
2310  sizer.Add(item = label, proportion = 0,
2311  flag = wx.ALL, border = 5)
2312 
2313  self.mapsetlb = CheckListMapset(parent = self)
2314  self.mapsetlb.LoadData()
2315 
2316  sizer.Add(item = self.mapsetlb, proportion = 1,
2317  flag = wx.ALL | wx.EXPAND, border = 5)
2318 
2319  # check all accessible mapsets
2320  for mset in self.accessible_mapsets:
2321  self.mapsetlb.CheckItem(self.all_mapsets_ordered.index(mset), True)
2322 
2323  # FIXME (howto?): grey-out current mapset
2324  #self.mapsetlb.Enable(0, False)
2325 
2326  # dialog buttons
2327  line = wx.StaticLine(parent = self, id = wx.ID_ANY,
2328  style = wx.LI_HORIZONTAL)
2329  sizer.Add(item = line, proportion = 0,
2330  flag = wx.EXPAND | wx.ALIGN_CENTRE | wx.ALL, border = 5)
2331 
2332  btnsizer = wx.StdDialogButtonSizer()
2333  okbtn = wx.Button(self, wx.ID_OK)
2334  okbtn.SetDefault()
2335  btnsizer.AddButton(okbtn)
2336 
2337  cancelbtn = wx.Button(self, wx.ID_CANCEL)
2338  btnsizer.AddButton(cancelbtn)
2339  btnsizer.Realize()
2340 
2341  sizer.Add(item = btnsizer, proportion = 0,
2342  flag = wx.EXPAND | wx.ALIGN_RIGHT | wx.ALL, border = 5)
2343 
2344  # do layout
2345  self.Layout()
2346  self.SetSizer(sizer)
2347  sizer.Fit(self)
2348 
2349  self.SetMinSize(size)
2350 
2351  def GetMapsets(self):
2352  """!Get list of checked mapsets"""
2353  ms = []
2354  i = 0
2355  for mset in self.all_mapsets_ordered:
2356  if self.mapsetlb.IsChecked(i):
2357  ms.append(mset)
2358  i += 1
2359 
2360  return ms
2361 
2362 class CheckListMapset(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.CheckListCtrlMixin):
2363  """!List of mapset/owner/group"""
2364  def __init__(self, parent, pos = wx.DefaultPosition,
2365  log = None):
2366  self.parent = parent
2367 
2368  wx.ListCtrl.__init__(self, parent, wx.ID_ANY,
2369  style = wx.LC_REPORT)
2370  listmix.CheckListCtrlMixin.__init__(self)
2371  self.log = log
2372 
2373  # setup mixins
2374  listmix.ListCtrlAutoWidthMixin.__init__(self)
2375 
2376  def LoadData(self):
2377  """!Load data into list"""
2378  self.InsertColumn(0, _('Mapset'))
2379  self.InsertColumn(1, _('Owner'))
2380  ### self.InsertColumn(2, _('Group'))
2381  gisenv = grass.gisenv()
2382  locationPath = os.path.join(gisenv['GISDBASE'], gisenv['LOCATION_NAME'])
2383 
2384  for mapset in self.parent.all_mapsets_ordered:
2385  index = self.InsertStringItem(sys.maxint, mapset)
2386  mapsetPath = os.path.join(locationPath,
2387  mapset)
2388  stat_info = os.stat(mapsetPath)
2389  if havePwd:
2390  self.SetStringItem(index, 1, "%s" % pwd.getpwuid(stat_info.st_uid)[0])
2391  # FIXME: get group name
2392  ### self.SetStringItem(index, 2, "%-8s" % stat_info.st_gid)
2393  else:
2394  # FIXME: no pwd under MS Windows (owner: 0, group: 0)
2395  self.SetStringItem(index, 1, "%-8s" % stat_info.st_uid)
2396  ### self.SetStringItem(index, 2, "%-8s" % stat_info.st_gid)
2397 
2398  self.SetColumnWidth(col = 0, width = wx.LIST_AUTOSIZE)
2399  ### self.SetColumnWidth(col = 1, width = wx.LIST_AUTOSIZE)
2400 
2401  def OnCheckItem(self, index, flag):
2402  """!Mapset checked/unchecked"""
2403  mapset = self.parent.all_mapsets_ordered[index]
2404  if mapset == self.parent.curr_mapset:
2405  self.CheckItem(index, True)