pida-hacks / pida / core /

Full commit
# -*- coding: utf-8 -*-
    Options Management

    This module handles the storrage of configuration data.
    There are 3 semantical locations of configuration data:
    * global
    * workspace
    * project *todo*

    :copyright: 2005-2008 by The PIDA Project
    :license: GPL 2 or later (see README/COPYING/LICENSE)
import itertools

from pida.utils import json

import py

from pango import Font
from gtk.gdk import Color

from .base import BaseConfig
from .environment import is_safe_mode, settings_dir, workspace_name

# locale
from pida.core.locale import Locale
locale = Locale('core')
_ = locale.gettext

def list_workspaces():
    """Returns a list with all workspace names """
    workspaces = settings_dir('workspaces')
    return [x.basename for x in workspaces.listdir() if x.check(dir=True)]

def must_open_workspace_manager():
    data = json.load(settings_dir('appcontroller.json'), fallback={})
    return bool(data.get('open_workspace_manager', False))

def workspace_dir(*parts):
    get a path in the workspace settings dir
    create the workspace if missing\
    wd = settings_dir().ensure('workspaces', workspace_name(), dir=1)
    return wd.join(*parts)

class BaseChoice(str):

def choices(choices):
    """Helper to generate string options for choices"""
    class Choices(BaseChoice):
        """Option that should be one of the choices"""
        options = choices

    return Choices

class OptionItem(object):

    def __init__(self, group, name, label, rtype, default, doc, callback,
                 workspace=None): = group = name
        self.label = label
        self.type = rtype
        self.doc = doc
        self.default = default
        self.workspace = bool(workspace)
        self.callback = callback
        self.value = default

    def _get_nlabel(self):
        return self.label.replace("_", "", 1)

    def __repr__(self):
        return '<OI %s %s:%s>' % (
      , self.type.__name__,

    no_mnemomic_label = property(_get_nlabel)

class OptionsConfig(BaseConfig):

    #enable reuse for keyboard shortcuts that need different name
    ext = '.json'

    def create(self): = self.svc.get_name() + self.ext
        self._options = {}
        self._workspace_options = {}

    def create_options(self):
        """Create the options here"""

    def register_options(self):
        # in safemode we reset all dangerouse variables so pida can start
        # even if there are some settings + pida bugs that cause problems
        # default values MUST be safe
        for name, value in
                self.get_option(name).value = value
            except KeyError:
                # ignore removed options that might have config entries

        #XXX: disabled
        if is_safe_mode() and False:
            for opt in self:
                if not
                    #XXX: this writes on every change, BAD
                    self.set_value(, opt.default)

        for opt in self:
            if opt.value is None:
                self.set_value(, opt.default)

    def create_option(self, name, label, type, default, doc, callback=None,
                      safe=True, workspace=False):
        opt = OptionItem(self, name, label, type, default, doc,
                         callback, workspace)
        return opt

    def add_option(self, option):
        if option.workspace:
            self._workspace_options[] = option
            self._options[] = option

    def remove_option(self, option):
        Removes a Option from OptionManager
        if option.workspace:
            del self._workspace_options[]
            del self._options[]

    def get_option(self, optname):
        return self._options.get(optname) or self._workspace_options[optname]

    def get_value(self, name):
        return self.get_option(name).value

    def set_value(self, name, value, dbus_notify=True, save=True):
        option = self.get_option(name)
        option.value = value
        if save:

    def _on_change(self, option):
        # we dont do anything smart, till we are started
        if not self.svc.started:
        if option.callback:
        optionsmanager = self.svc.boss.get_service('optionsmanager')
        if hasattr(optionsmanager, 'events'):
            optionsmanager.emit('option_changed', option=option)

    def dump_data(self, path, data):
            json.dump(data, path)
        except Exception, e:

    def read(self):
        data = {}
        for d in (settings_dir, workspace_dir):
            except ValueError, e:
                self.svc.log.error(_('Settings file corrupted: {file}'),
            except py.error.ENOENT:
            except Exception, e:
        return data

    def filter_json(self, data):
        if isinstance(data, Color):
            return data.to_string()
        return data

    def dump(self, workspace):
        if workspace:
            config_dir = workspace_dir
            opts = self._workspace_options
            config_dir = settings_dir
            opts = self._options

        data = dict((, opt.value) for opt in opts.values())
        json.dump(data, config_dir() /

    def __len__(self):
        return len(self._options) + len(self._workspace_options)

    def __iter__(self):
        iterate the optionsitems
        return itertools.chain(self._options.itervalues(),

    def __nonzero__(self):
        shows if there are actually options defined for this config
        return bool(len(self))