"""! @package core.settings @brief Default GUI settings List of classes: - settings::Settings Usage: @code from core.settings import UserSettings @endcode (C) 2007-2011 by the GRASS Development Team This program is free software under the GNU General Public License (>=v2). Read the file COPYING that comes with GRASS for details. @author Martin Landa @author Luca Delucchi (language choice) """ import os import sys import copy import types from core import globalvar from core.gcmd import GException, GError from core.utils import GetSettingsPath, PathJoin, rgb2str class Settings: """!Generic class where to store settings""" def __init__(self): # settings file self.filePath = os.path.join(GetSettingsPath(), 'wx') # key/value separator self.sep = ';' # define default settings self._defaultSettings() # -> self.defaultSettings # read settings from the file self.userSettings = copy.deepcopy(self.defaultSettings) try: self.ReadSettingsFile() except GException, e: print >> sys.stderr, e.value # define internal settings self._internalSettings() # -> self.internalSettings def _generateLocale(self): """!Generate locales """ try: self.locs = os.listdir(os.path.join(os.environ['GISBASE'], 'locale')) self.locs.append('en') # GRASS doesn't ship EN po files self.locs.sort() # Add a default choice to not override system locale self.locs.insert(0, 'system') except: # No NLS self.locs = ['system'] return 'system' def _defaultSettings(self): """!Define default settings """ try: projFile = PathJoin(os.environ["GRASS_PROJSHARE"], 'epsg') except KeyError: projFile = '' id_loc = self._generateLocale() self.defaultSettings = { # # general # 'general': { # use default window layout (layer manager, displays, ...) 'defWindowPos' : { 'enabled' : True, 'dim' : '0,0,%d,%d,%d,0,%d,%d' % \ (globalvar.GM_WINDOW_SIZE[0], globalvar.GM_WINDOW_SIZE[1], globalvar.GM_WINDOW_SIZE[0], globalvar.MAP_WINDOW_SIZE[0], globalvar.MAP_WINDOW_SIZE[1]) }, # workspace 'workspace' : { 'posDisplay' : { 'enabled' : False }, 'posManager' : { 'enabled' : False }, }, }, 'manager' : { # show opacity level widget 'changeOpacityLevel' : { 'enabled' : False }, # ask when removing layer from layer tree 'askOnRemoveLayer' : { 'enabled' : True }, # ask when quiting wxGUI or closing display 'askOnQuit' : { 'enabled' : True }, # hide tabs 'hideTabs' : { 'search' : False, 'pyshell' : False, }, 'copySelectedTextToClipboard' : { 'enabled' : False }, }, # # appearance # 'appearance': { 'outputfont' : { 'type' : 'Courier New', 'size': '10', }, # expand/collapse element list 'elementListExpand' : { 'selection' : 0 }, 'menustyle' : { 'selection' : 1 }, 'gSelectPopupHeight' : { 'value' : 200 }, 'iconTheme' : { 'type' : 'grass' }, 'commandNotebook' : { 'selection' : 2 }, }, # # language # 'language': { 'locale': { 'lc_all' : id_loc } }, # # display # 'display': { 'font' : { 'type' : '', 'encoding': 'ISO-8859-1', }, 'driver': { 'type': 'cairo' }, 'alignExtent' : { 'enabled' : True }, 'compResolution' : { 'enabled' : False }, 'autoRendering': { 'enabled' : True }, 'autoZooming' : { 'enabled' : False }, 'statusbarMode': { 'selection' : 0 }, 'bgcolor': { 'color' : (255, 255, 255, 255), }, 'mouseWheelZoom' : { 'selection' : 1, }, 'scrollDirection' : { 'selection' : 0, }, 'nvizDepthBuffer' : { 'value' : 16, }, }, # # projection # 'projection' : { 'statusbar' : { 'proj4' : '', 'epsg' : '', 'projFile' : projFile, }, 'format' : { 'll' : 'DMS', 'precision' : 2, }, }, # # Attribute Table Manager # 'atm' : { 'highlight' : { 'color' : (255, 255, 0, 255), 'width' : 2 }, 'leftDbClick' : { 'selection' : 1 # draw selected }, 'askOnDeleteRec' : { 'enabled' : True }, 'keycolumn' : { 'value' : 'cat' }, 'encoding' : { 'value' : '', } }, # # Command # 'cmd': { 'overwrite' : { 'enabled' : False }, 'closeDlg' : { 'enabled' : False }, 'verbosity' : { 'selection' : 'grassenv' }, 'addNewLayer' : { 'enabled' : True, }, 'interactiveInput' : { 'enabled' : True, }, }, # # d.rast # 'rasterLayer': { 'opaque': { 'enabled' : False }, 'colorTable': { 'enabled' : False, 'selection' : 'rainbow' }, }, # # d.vect # 'vectorLayer': { 'featureColor': { 'color' : (0, 0, 0), 'transparent' : { 'enabled': False } }, 'areaFillColor': { 'color' : (200, 200, 200), 'transparent' : { 'enabled': False } }, 'line': { 'width' : 0, }, 'point': { 'symbol': 'basic/x', 'size' : 5, }, 'showType': { 'point' : { 'enabled' : True }, 'line' : { 'enabled' : True }, 'centroid' : { 'enabled' : False }, 'boundary' : { 'enabled' : True }, 'area' : { 'enabled' : True }, 'face' : { 'enabled' : True }, }, }, # # vdigit # 'vdigit' : { # symbology 'symbol' : { 'newSegment' : { 'enabled' : None, 'color' : (255, 0, 0, 255) }, # red 'newLine' : { 'enabled' : None, 'color' : (0, 86, 45, 255) }, # dark green 'highlight' : { 'enabled' : None, 'color' : (255, 255, 0, 255) }, # yellow 'highlightDupl' : { 'enabled' : None, 'color' : (255, 72, 0, 255) }, # red 'point' : { 'enabled' : True, 'color' : (0, 0, 0, 255) }, # black 'line' : { 'enabled' : True, 'color' : (0, 0, 0, 255) }, # black 'boundaryNo' : { 'enabled' : True, 'color' : (126, 126, 126, 255) }, # grey 'boundaryOne' : { 'enabled' : True, 'color' : (0, 255, 0, 255) }, # green 'boundaryTwo' : { 'enabled' : True, 'color' : (255, 135, 0, 255) }, # orange 'centroidIn' : { 'enabled' : True, 'color' : (0, 0, 255, 255) }, # blue 'centroidOut' : { 'enabled' : True, 'color' : (165, 42, 42, 255) }, # brown 'centroidDup' : { 'enabled' : True, 'color' : (156, 62, 206, 255) }, # violet 'nodeOne' : { 'enabled' : True, 'color' : (255, 0, 0, 255) }, # red 'nodeTwo' : { 'enabled' : True, 'color' : (0, 86, 45, 255) }, # dark green 'vertex' : { 'enabled' : False, 'color' : (255, 20, 147, 255) }, # deep pink 'area' : { 'enabled' : True, 'color' : (217, 255, 217, 255) }, # green 'direction' : { 'enabled' : False, 'color' : (255, 0, 0, 255) }, # red }, # display 'lineWidth' : { 'value' : 2, 'units' : 'screen pixels' }, # snapping 'snapping' : { 'value' : 10, 'units' : 'screen pixels' }, 'snapToVertex' : { 'enabled' : False }, # digitize new record 'addRecord' : { 'enabled' : True }, 'layer' :{ 'value' : 1 }, 'category' : { 'value' : 1 }, 'categoryMode' : { 'selection' : 0 }, # delete existing feature(s) 'delRecord' : { 'enabled' : True }, # query tool 'query' : { 'selection' : 0, 'box' : True }, 'queryLength' : { 'than-selection' : 0, 'thresh' : 0 }, 'queryDangle' : { 'than-selection' : 0, 'thresh' : 0 }, # select feature (point, line, centroid, boundary) 'selectType': { 'point' : { 'enabled' : True }, 'line' : { 'enabled' : True }, 'centroid' : { 'enabled' : True }, 'boundary' : { 'enabled' : True }, }, 'selectThresh' : { 'value' : 10, 'units' : 'screen pixels' }, 'checkForDupl' : { 'enabled' : False }, 'selectInside' : { 'enabled' : False }, # exit 'saveOnExit' : { 'enabled' : False, }, # break lines on intersection 'breakLines' : { 'enabled' : False, }, # close boundary (snap to the first node) 'closeBoundary' : { 'enabled' : False, } }, # # plots for profiles, histograms, and scatterplots # 'profile': { 'raster' : { 'pcolor' : (0, 0, 255, 255), # line color 'pwidth' : 1, # line width 'pstyle' : 'solid', # line pen style 'datatype' : 'cell', # raster type }, 'font' : { 'titleSize' : 12, 'axisSize' : 11, 'legendSize' : 10, }, 'marker' : { 'color' : (0, 0, 0, 255), 'fill' : 'transparent', 'size' : 2, 'type' : 'triangle', 'legend' : _('Segment break'), }, 'grid' : { 'color' : (200, 200, 200, 255), 'enabled' : True, }, 'x-axis' : { 'type' : 'auto', # axis format 'min' : 0, # axis min for custom axis range 'max': 0, # axis max for custom axis range 'log' : False, }, 'y-axis' : { 'type' : 'auto', # axis format 'min' : 0, # axis min for custom axis range 'max': 0, # axis max for custom axis range 'log' : False, }, 'legend' : { 'enabled' : True }, }, 'histogram': { 'raster' : { 'pcolor' : (0, 0, 255, 255), # line color 'pwidth' : 1, # line width 'pstyle' : 'solid', # line pen style 'datatype' : 'cell', # raster type }, 'font' : { 'titleSize' : 12, 'axisSize' : 11, 'legendSize' : 10, }, 'grid' : { 'color' : (200, 200, 200, 255), 'enabled' : True, }, 'x-axis' : { 'type' : 'auto', # axis format 'min' : 0, # axis min for custom axis range 'max' : 0, # axis max for custom axis range 'log' : False, }, 'y-axis' : { 'type' : 'auto', # axis format 'min' : 0, # axis min for custom axis range 'max' : 0, # axis max for custom axis range 'log' : False, }, 'legend' : { 'enabled' : True }, }, 'scatter': { 'raster' : { 'pcolor' : (0, 0, 255, 255), 'pfill' : 'solid', 'psize' : 1, 'ptype' : 'dot', # FIXME: this is only a quick fix # using also names used in a base class for compatibility # probably used only for initialization # base should be rewritten to not require this 'pwidth' : 1, # required by wxplot/base, maybe useless here 'pstyle' : 'dot', # line pen style 'plegend' : _('Data point'), 0 : {'datatype' : 'CELL'}, 1 : {'datatype' : 'CELL'}, }, 'font' : { 'titleSize' : 12, 'axisSize' : 11, 'legendSize' : 10, }, 'grid' : { 'color' : (200, 200, 200, 255), 'enabled' : True, }, 'x-axis' : { 'type' : 'auto', # axis format 'min' : 0, # axis min for custom axis range 'max' : 0, # axis max for custom axis range 'log' : False, }, 'y-axis' : { 'type' : 'auto', # axis format 'min' : 0, # axis min for custom axis range 'max' : 0, # axis max for custom axis range 'log' : False, }, 'legend' : { 'enabled' : True }, }, 'gcpman' : { 'rms' : { 'highestonly' : True, 'sdfactor' : 1, }, 'symbol' : { 'color' : (0, 0, 255, 255), 'hcolor' : (255, 0, 0, 255), 'scolor' : (0, 255, 0, 255), 'ucolor' : (255, 165, 0, 255), 'unused' : True, 'size' : 8, 'width' : 2, }, }, 'nviz' : { 'view' : { 'persp' : { 'value' : 20, 'step' : 2, }, 'position' : { 'x' : 0.84, 'y' : 0.16, }, 'twist' : { 'value' : 0, }, 'z-exag' : { 'min' : 0, 'max' : 10, 'value': 1, }, 'background' : { 'color' : (255, 255, 255, 255), # white }, }, 'fly' : { 'exag' : { 'move' : 5, 'turn' : 5, } }, 'animation' : { 'fps' : 24, 'prefix' : _("animation") }, 'surface' : { 'shine': { 'map' : False, 'value' : 60.0, }, 'color' : { 'map' : True, 'value' : (100, 100, 100, 255), # constant: grey }, 'draw' : { 'wire-color' : (136, 136, 136, 255), 'mode' : 1, # fine 'style' : 1, # surface 'shading' : 1, # gouraud 'res-fine' : 6, 'res-coarse' : 9, }, 'position' : { 'x' : 0, 'y' : 0, 'z' : 0, }, }, 'constant' : { 'color' : (100, 100, 100, 255), 'value' : 0.0, 'transp' : 0, 'resolution': 6 }, 'vector' : { 'lines' : { 'show' : False, 'width' : 2, 'color' : (0, 0, 255, 255), # blue 'flat' : False, 'height' : 0, 'rgbcolumn': None, 'sizecolumn': None, }, 'points' : { 'show' : False, 'size' : 100, 'width' : 2, 'marker' : 2, 'color' : (0, 0, 255, 255), # blue 'height' : 0, 'rgbcolumn': None, 'sizecolumn': None, } }, 'volume' : { 'color' : { 'map' : True, 'value' : (100, 100, 100, 255), # constant: grey }, 'draw' : { 'mode' : 0, # isosurfaces 'shading' : 1, # gouraud 'resolution' : 3, # polygon resolution 'box' : False # draw wire box }, 'shine': { 'map' : False, 'value' : 60, }, 'topo': { 'map' : None, 'value' : 0.0 }, 'transp': { 'map' : None, 'value': 0 }, 'mask': { 'map' : None, 'value': '' }, 'slice_position': { 'x1' : 0, 'x2' : 1, 'y1' : 0, 'y2' : 1, 'z1' : 0, 'z2' : 1, 'axis' : 0, } }, 'cplane' : { 'shading': 4, 'rotation':{ 'rot': 180, 'tilt': 0 }, 'position':{ 'x' : 0, 'y' : 0, 'z' : 0 } }, 'light' : { 'position' : { 'x' : 0.68, 'y' : -0.68, 'z' : 80, }, 'bright' : 80, 'color' : (255, 255, 255, 255), # white 'ambient' : 20, }, 'fringe' : { 'elev' : 55, 'color' : (128, 128, 128, 255), # grey }, 'arrow': { 'color': (0, 0, 0), }, 'scalebar': { 'color': (0, 0, 0), } }, 'modeler' : { 'disabled': { 'color': (211, 211, 211, 255), # light grey }, 'action' : { 'color' : { 'valid' : (180, 234, 154, 255), # light green 'invalid' : (255, 255, 255, 255), # white 'running' : (255, 0, 0, 255), # red }, 'size' : { 'width' : 125, 'height' : 50, }, 'width': { 'parameterized' : 2, 'default' : 1, }, }, 'data' : { 'color': { 'raster' : (215, 215, 248, 255), # light blue 'raster3d' : (215, 248, 215, 255), # light green 'vector' : (248, 215, 215, 255), # light red }, 'size' : { 'width' : 175, 'height' : 50, }, }, 'loop' : { 'color' : { 'valid' : (234, 226, 154, 255), # light yellow }, 'size' : { 'width' : 175, 'height' : 40, }, }, 'if-else' : { 'size' : { 'width' : 150, 'height' : 40, }, }, }, } # quick fix, http://trac.osgeo.org/grass/ticket/1233 # TODO if sys.platform == 'darwin': self.defaultSettings['general']['defWindowPos']['enabled'] = False def _internalSettings(self): """!Define internal settings (based on user settings) """ self.internalSettings = {} for group in self.userSettings.keys(): self.internalSettings[group] = {} for key in self.userSettings[group].keys(): self.internalSettings[group][key] = {} # self.internalSettings['general']["mapsetPath"]['value'] = self.GetMapsetPath() self.internalSettings['appearance']['elementListExpand']['choices'] = \ (_("Collapse all except PERMANENT and current"), _("Collapse all except PERMANENT"), _("Collapse all except current"), _("Collapse all"), _("Expand all")) self.internalSettings['language']['locale']['choices'] = tuple(self.locs) self.internalSettings['atm']['leftDbClick']['choices'] = (_('Edit selected record'), _('Display selected')) self.internalSettings['cmd']['verbosity']['choices'] = ('grassenv', 'verbose', 'quiet') self.internalSettings['appearance']['iconTheme']['choices'] = ('grass',) self.internalSettings['appearance']['menustyle']['choices'] = \ (_("Classic (labels only)"), _("Combined (labels and module names)"), _("Expert (module names only)")) self.internalSettings['appearance']['gSelectPopupHeight']['min'] = 50 # there is also maxHeight given to TreeCtrlComboPopup.GetAdjustedSize self.internalSettings['appearance']['gSelectPopupHeight']['max'] = 1000 self.internalSettings['appearance']['commandNotebook']['choices'] = \ (_("Basic top"), _("Basic left"), _("Fancy green"), _("List left")) self.internalSettings['display']['driver']['choices'] = ['cairo', 'png'] self.internalSettings['display']['statusbarMode']['choices'] = None # set during MapFrame init self.internalSettings['display']['mouseWheelZoom']['choices'] = (_('Zoom and recenter'), _('Zoom to mouse cursor'), _('Nothing')) self.internalSettings['display']['scrollDirection']['choices'] = (_('Scroll forward to zoom in'), _('Scroll back to zoom in')) self.internalSettings['nviz']['view'] = {} self.internalSettings['nviz']['view']['twist'] = {} self.internalSettings['nviz']['view']['twist']['min'] = -180 self.internalSettings['nviz']['view']['twist']['max'] = 180 self.internalSettings['nviz']['view']['persp'] = {} self.internalSettings['nviz']['view']['persp']['min'] = 1 self.internalSettings['nviz']['view']['persp']['max'] = 100 self.internalSettings['nviz']['view']['height'] = {} self.internalSettings['nviz']['view']['height']['value'] = -1 self.internalSettings['nviz']['view']['z-exag'] = {} self.internalSettings['nviz']['view']['z-exag']['llRatio'] = 1 self.internalSettings['nviz']['view']['rotation'] = None self.internalSettings['nviz']['view']['focus'] = {} self.internalSettings['nviz']['view']['focus']['x'] = -1 self.internalSettings['nviz']['view']['focus']['y'] = -1 self.internalSettings['nviz']['view']['focus']['z'] = -1 self.internalSettings['nviz']['view']['dir'] = {} self.internalSettings['nviz']['view']['dir']['x'] = -1 self.internalSettings['nviz']['view']['dir']['y'] = -1 self.internalSettings['nviz']['view']['dir']['z'] = -1 self.internalSettings['nviz']['view']['dir']['use'] = False for decor in ('arrow', 'scalebar'): self.internalSettings['nviz'][decor] = {} self.internalSettings['nviz'][decor]['position'] = {} self.internalSettings['nviz'][decor]['position']['x'] = 0 self.internalSettings['nviz'][decor]['position']['y'] = 0 self.internalSettings['nviz'][decor]['size'] = 100 self.internalSettings['nviz']['vector'] = {} self.internalSettings['nviz']['vector']['points'] = {} self.internalSettings['nviz']['vector']['points']['marker'] = ("x", _("box"), _("sphere"), _("cube"), _("diamond"), _("aster"), _("gyro"), _("histogram")) self.internalSettings['vdigit']['bgmap'] = {} self.internalSettings['vdigit']['bgmap']['value'] = '' def ReadSettingsFile(self, settings = None): """!Reads settings file (mapset, location, gisdbase)""" if settings is None: settings = self.userSettings self._readFile(self.filePath, settings) # set environment variables font = self.Get(group = 'display', key = 'font', subkey = 'type') enc = self.Get(group = 'display', key = 'font', subkey = 'encoding') if font: os.environ["GRASS_FONT"] = font if enc: os.environ["GRASS_ENCODING"] = enc def _readFile(self, filename, settings = None): """!Read settings from file to dict @param filename settings file path @param settings dict where to store settings (None for self.userSettings) """ if settings is None: settings = self.userSettings if not os.path.exists(filename): return try: fd = open(filename, "r") except IOError: sys.stderr.write(_("Unable to read settings file <%s>\n") % filename) return try: line = '' for line in fd.readlines(): line = line.rstrip('%s' % os.linesep) group, key = line.split(self.sep)[0:2] kv = line.split(self.sep)[2:] subkeyMaster = None if len(kv) % 2 != 0: # multiple (e.g. nviz) subkeyMaster = kv[0] del kv[0] idx = 0 while idx < len(kv): if subkeyMaster: subkey = [subkeyMaster, kv[idx]] else: subkey = kv[idx] value = kv[idx+1] value = self._parseValue(value, read = True) self.Append(settings, group, key, subkey, value) idx += 2 except ValueError, e: print >> sys.stderr, _("Error: Reading settings from file <%(file)s> failed.\n" "\t\tDetails: %(detail)s\n" "\t\tLine: '%(line)s'\n") % { 'file' : filename, 'detail' : e, 'line' : line } fd.close() fd.close() def SaveToFile(self, settings = None): """!Save settings to the file""" if settings is None: settings = self.userSettings dirPath = GetSettingsPath() if not os.path.exists(dirPath): try: os.mkdir(dirPath) except: GError(_('Unable to create settings directory')) return try: file = open(self.filePath, "w") for group in settings.keys(): for key in settings[group].keys(): subkeys = settings[group][key].keys() file.write('%s%s%s%s' % (group, self.sep, key, self.sep)) for idx in range(len(subkeys)): value = settings[group][key][subkeys[idx]] if type(value) == types.DictType: if idx > 0: file.write('%s%s%s%s%s' % (os.linesep, group, self.sep, key, self.sep)) file.write('%s%s' % (subkeys[idx], self.sep)) kvalues = settings[group][key][subkeys[idx]].keys() srange = range(len(kvalues)) for sidx in srange: svalue = self._parseValue(settings[group][key][subkeys[idx]][kvalues[sidx]]) file.write('%s%s%s' % (kvalues[sidx], self.sep, svalue)) if sidx < len(kvalues) - 1: file.write('%s' % self.sep) else: if idx > 0 and \ type(settings[group][key][subkeys[idx - 1]]) == types.DictType: file.write('%s%s%s%s%s' % (os.linesep, group, self.sep, key, self.sep)) value = self._parseValue(settings[group][key][subkeys[idx]]) file.write('%s%s%s' % (subkeys[idx], self.sep, value)) if idx < len(subkeys) - 1 and \ type(settings[group][key][subkeys[idx + 1]]) != types.DictType: file.write('%s' % self.sep) file.write(os.linesep) except IOError, e: raise GException(e) except StandardError, e: raise GException(_('Writing settings to file <%(file)s> failed.' '\n\nDetails: %(detail)s') % { 'file' : self.filePath, 'detail' : e }) file.close() return self.filePath def _parseValue(self, value, read = False): """!Parse value to be store in settings file""" if read: # -> read settings (cast values) if value == 'True': value = True elif value == 'False': value = False elif value == 'None': value = None elif ':' in value: # -> color try: value = tuple(map(int, value.split(':'))) except ValueError: # -> string pass else: try: value = int(value) except ValueError: try: value = float(value) except ValueError: pass else: # -> write settings if type(value) == type(()): # -> color value = str(value[0]) + ':' +\ str(value[1]) + ':' + \ str(value[2]) return value def Get(self, group, key = None, subkey = None, internal = False): """!Get value by key/subkey Raise KeyError if key is not found @param group settings group @param key (value, None) @param subkey (value, list or None) @param internal use internal settings instead @return value """ if internal is True: settings = self.internalSettings else: settings = self.userSettings try: if subkey is None: if key is None: return settings[group] else: return settings[group][key] else: if type(subkey) == type(tuple()) or \ type(subkey) == type(list()): return settings[group][key][subkey[0]][subkey[1]] else: return settings[group][key][subkey] except KeyError: print >> sys.stderr, "Settings: unable to get value '%s:%s:%s'\n" % \ (group, key, subkey) def Set(self, group, value, key = None, subkey = None, internal = False): """!Set value of key/subkey Raise KeyError if group/key is not found @param group settings group @param key key (value, None) @param subkey subkey (value, list or None) @param value value @param internal use internal settings instead """ if internal is True: settings = self.internalSettings else: settings = self.userSettings try: if subkey is None: if key is None: settings[group] = value else: settings[group][key] = value else: if type(subkey) == type(tuple()) or \ type(subkey) == type(list()): settings[group][key][subkey[0]][subkey[1]] = value else: settings[group][key][subkey] = value except KeyError: raise GException("%s '%s:%s:%s'" % (_("Unable to set "), group, key, subkey)) def Append(self, dict, group, key, subkey, value, overwrite = True): """!Set value of key/subkey Create group/key/subkey if not exists @param dict settings dictionary to use @param group settings group @param key key @param subkey subkey (value or list) @param value value @param overwrite True to overwrite existing value """ hasValue = True if group not in dict: dict[group] = {} hasValue = False if key not in dict[group]: dict[group][key] = {} hasValue = False if type(subkey) == types.ListType: # TODO: len(subkey) > 2 if subkey[0] not in dict[group][key]: dict[group][key][subkey[0]] = {} hasValue = False if subkey[1] not in dict[group][key][subkey[0]]: hasValue = False try: if overwrite or (not overwrite and not hasValue): dict[group][key][subkey[0]][subkey[1]] = value except TypeError: print >> sys.stderr, _("Unable to parse settings '%s'") % value + \ ' (' + group + ':' + key + ':' + subkey[0] + ':' + subkey[1] + ')' else: if subkey not in dict[group][key]: hasValue = False try: if overwrite or (not overwrite and not hasValue): dict[group][key][subkey] = value except TypeError: print >> sys.stderr, _("Unable to parse settings '%s'") % value + \ ' (' + group + ':' + key + ':' + subkey + ')' def GetDefaultSettings(self): """!Get default user settings""" return self.defaultSettings def Reset(self, key = None): """!Reset to default settings @param key key in settings dict (None for all keys) """ if not key: self.userSettings = copy.deepcopy(self.defaultSettings) else: self.userSettings[key] = copy.deepcopy(self.defaultSettings[key]) UserSettings = Settings() def GetDisplayVectSettings(): settings = list() if not UserSettings.Get(group = 'vectorLayer', key = 'featureColor', subkey = ['transparent', 'enabled']): featureColor = UserSettings.Get(group = 'vectorLayer', key = 'featureColor', subkey = 'color') settings.append('color=%s' % rgb2str.get(featureColor, ':'.join(map(str,featureColor)))) else: settings.append('color=none') if not UserSettings.Get(group = 'vectorLayer', key = 'areaFillColor', subkey = ['transparent', 'enabled']): fillColor = UserSettings.Get(group = 'vectorLayer', key = 'areaFillColor', subkey = 'color') settings.append('fcolor=%s' % rgb2str.get(fillColor, ':'.join(map(str,fillColor)))) else: settings.append('fcolor=none') settings.append('width=%s' % UserSettings.Get(group = 'vectorLayer', key = 'line', subkey = 'width')) settings.append('icon=%s' % UserSettings.Get(group = 'vectorLayer', key = 'point', subkey = 'symbol')) settings.append('size=%s' % UserSettings.Get(group = 'vectorLayer', key = 'point', subkey = 'size')) types = [] for ftype in ['point', 'line', 'boundary', 'centroid', 'area', 'face']: if UserSettings.Get(group = 'vectorLayer', key = 'showType', subkey = [ftype, 'enabled']): types.append(ftype) settings.append('type=%s' % ','.join(types)) return settings