[orca] Profiles and new settings manager. (Merged from branch 'new-settings')



commit 29ec6d4796c85ca98ee7ff6aa4ba896c00cede90
Author: Alejandro Leiva <aleiva emergya es>
Date:   Sun Dec 19 23:26:22 2010 +0100

    Profiles and new settings manager. (Merged from branch 'new-settings')

 configure.in                                       |    2 +
 po/POTFILES.in                                     |    1 +
 po/POTFILES.skip                                   |    2 +
 src/orca/Makefile.am                               |    7 +-
 src/orca/acss.py                                   |   30 +-
 src/orca/app_gui_prefs.py                          |    3 +-
 src/orca/backends/Makefile.am                      |    9 +
 src/orca/backends/gconf_backend.py                 |  408 +++++++++
 src/orca/backends/yaml_backend.py                  |  160 ++++
 src/orca/braille_generator.py                      |   13 +-
 src/orca/chat.py                                   |  113 ++--
 src/orca/default.py                                |  133 ++--
 src/orca/focus_tracking_presenter.py               |    3 +
 src/orca/mag.py                                    |  183 +++--
 src/orca/orca-profile.ui                           |  155 ++++
 src/orca/orca-setup.ui                             |  185 ++++-
 src/orca/orca.py                                   |  896 ++++++++++++--------
 src/orca/orca_console_prefs.py                     |   10 +-
 src/orca/orca_gui_prefs.py                         |  400 ++++++++--
 src/orca/orca_gui_profile.py                       |  189 ++++
 src/orca/orca_prefs.py                             |    4 +-
 src/orca/scripts/apps/Instantbird/script.py        |    7 +-
 src/orca/scripts/apps/Thunderbird/script.py        |    5 +-
 src/orca/scripts/apps/evolution/script.py          |   70 +-
 .../scripts/apps/evolution/speech_generator.py     |    6 +-
 .../scripts/apps/gnome-panel/speech_generator.py   |    6 +-
 src/orca/scripts/apps/gnome-terminal/script.py     |   10 +-
 src/orca/scripts/apps/soffice/braille_generator.py |   16 +-
 src/orca/scripts/apps/soffice/script.py            |  118 ++--
 src/orca/scripts/apps/soffice/speech_generator.py  |   14 +-
 src/orca/scripts/apps/yelp/script.py               |    5 +-
 src/orca/scripts/toolkits/Gecko/script.py          |   99 ++-
 .../scripts/toolkits/Gecko/speech_generator.py     |    8 +-
 .../J2SE-access-bridge/speech_generator.py         |   11 +-
 src/orca/settings.py                               |   50 +-
 src/orca/settings_manager.py                       |  519 +++++++++++
 src/orca/speech_generator.py                       |   87 +-
 test/harness/.gitignore                            |    3 +-
 test/harness/generalSettings.conf                  |   10 +
 test/harness/harness.sh                            |    4 +-
 test/harness/importFile.conf                       |    8 +
 test/harness/importFile2.conf                      |    3 +
 test/harness/keybindingsSettings.conf              |    4 +
 test/harness/pronunciationsSettings.conf           |    3 +
 test/harness/runall.sh                             |   12 +-
 test/harness/runone.sh                             |   11 +-
 test/harness/settings_test.py                      |   97 +++
 test/harness/user-settings.conf.in                 |  143 ++++
 test/harness/user-settings.py.in                   |   30 -
 .../gtk-demo/spoken_indentation.settings           |  175 ++++-
 50 files changed, 3461 insertions(+), 979 deletions(-)
---
diff --git a/configure.in b/configure.in
index 8558708..5679ad2 100644
--- a/configure.in
+++ b/configure.in
@@ -56,6 +56,7 @@ AM_CHECK_PYMOD(dbus,,,[AC_MSG_ERROR(Could not find python module: dbus)])
 AM_CHECK_PYMOD(pyatspi,,,[AC_MSG_ERROR(Could not find python module: pyatspi)])
 AM_CHECK_PYMOD(cairo,,,[AC_MSG_ERROR(Could not find python module: cairo)])
 AM_CHECK_PYMOD(pango,,,[AC_MSG_ERROR(Could not find python module: pango)])
+AM_CHECK_PYMOD(yaml,,,[AC_MSG_ERROR(Could not find python module: yaml)])
 AM_CHECK_PYMOD(xdg,,,[AC_MSG_ERROR(Could not find python module: xdg)])
 AM_CHECK_PYMOD(wnck,,[wnck_available="yes"],[wnck_available="no"])
 AM_CHECK_PYORBIT_MOD(GNOME_Speech,[gnome_speech_available="yes"],[gnome_speech_available="no"])
@@ -133,6 +134,7 @@ src/orca/scripts/toolkits/Gecko/Makefile
 src/orca/scripts/toolkits/J2SE-access-bridge/Makefile
 src/orca/scripts/toolkits/CALLY/Makefile
 src/orca/scripts/toolkits/WebKitGtk/Makefile
+src/orca/backends/Makefile
 src/orca/orca
 src/orca/orca_i18n.py
 src/orca/orca_platform.py
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 275b248..4a5699a 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -31,6 +31,7 @@ src/orca/orca.in
 [type: gettext/glade]src/orca/orca-mainwin.ui
 src/orca/orca.py
 [type: gettext/glade]src/orca/orca-preferences-warning.ui
+[type: gettext/glade]src/orca/orca-profile.ui
 [type: gettext/glade]src/orca/orca-quit.ui
 [type: gettext/glade]src/orca/orca-setup.ui
 [type: gettext/glade]src/orca/orca-splash.ui
diff --git a/po/POTFILES.skip b/po/POTFILES.skip
index 6d40796..8dde815 100644
--- a/po/POTFILES.skip
+++ b/po/POTFILES.skip
@@ -1 +1,3 @@
 src/louis/constants.py
+src/orca/backends/gconf_backend.py
+src/orca/settings_manager.py
diff --git a/src/orca/Makefile.am b/src/orca/Makefile.am
index d641e5b..ff6efee 100644
--- a/src/orca/Makefile.am
+++ b/src/orca/Makefile.am
@@ -48,6 +48,7 @@ orca_python_PYTHON = \
 	orca_gui_find.py \
 	orca_gui_main.py \
 	orca_gui_prefs.py \
+	orca_gui_profile.py \
 	orca_gui_splash.py \
 	orca_i18n.py \
 	orca_prefs.py \
@@ -64,6 +65,7 @@ orca_python_PYTHON = \
 	script.py \
 	script_utilities.py \
 	settings.py \
+	settings_manager.py \
 	sound.py \
 	speech.py \
 	speechdispatcherfactory.py \
@@ -76,7 +78,9 @@ orca_python_PYTHON = \
 
 orca_pythondir=$(pyexecdir)/orca
 
-SUBDIRS = scripts
+SUBDIRS = \
+        scripts \
+        backends
 
 ui_DATA = \
 	orca-advanced-magnification.ui \
@@ -85,6 +89,7 @@ ui_DATA = \
 	orca-preferences-warning.ui \
 	orca-quit.ui \
 	orca-setup.ui \
+	orca-profile.ui \
 	orca-splash.ui
 
 gfx_DATA = \
diff --git a/src/orca/acss.py b/src/orca/acss.py
index 3a25b16..4f27731 100644
--- a/src/orca/acss.py
+++ b/src/orca/acss.py
@@ -63,19 +63,23 @@ class ACSS(dict):
         """Create and initialize ACSS structure."""
         dict.__init__(self)
         props = props or {}
-        for k in props:
-            if k in ACSS.settings:
-                # Do a 'deep copy' of the family.  Otherwise,
-                # the new ACSS shares the actual data with the
-                # props passed in.  This can cause unexpected
-                # side effects.
-                #
-                if k == ACSS.FAMILY:
-                    self[k] = {}
-                    for j in props[k].keys():
-                        self[k][j] = props[k][j]
-                else:
-                    self[k] = props[k]
+        if props:
+            for k in props:
+                if k in ACSS.settings:
+                    # Do a 'deep copy' of the family.  Otherwise,
+                    # the new ACSS shares the actual data with the
+                    # props passed in.  This can cause unexpected
+                    # side effects.
+                    #
+                    if k == ACSS.FAMILY:
+                        self[k] = {}
+                        for j in props[k].keys():
+                            self[k][j] = props[k][j]
+                    else:
+                        self[k] = props[k]
+        else:
+            self['established'] = False
+
 
     def __setitem__ (self, key, value):
         """Update name when we change values."""
diff --git a/src/orca/app_gui_prefs.py b/src/orca/app_gui_prefs.py
index ac4444c..01c7d11 100644
--- a/src/orca/app_gui_prefs.py
+++ b/src/orca/app_gui_prefs.py
@@ -90,8 +90,7 @@ class OrcaSetupGUI(orca_gui_prefs.OrcaSetupGUI):
         # in gail or gtk+ (see bug #554002).  Instead, we'll just hide it.
         #
         # self.get_widget("notebook").remove_page(0)
-        generalTab = self.get_widget("notebook").get_children()[0]
-        generalTab.hide()
+        self.get_widget("generalVBox").hide()
 
         self.get_widget("speechSystemsLabel").set_sensitive(False)
         self.get_widget("speechSystems").set_sensitive(False)
diff --git a/src/orca/backends/Makefile.am b/src/orca/backends/Makefile.am
new file mode 100644
index 0000000..9519b48
--- /dev/null
+++ b/src/orca/backends/Makefile.am
@@ -0,0 +1,9 @@
+orca_pathdir=$(pyexecdir)
+
+orca_python_PYTHON = \
+        __init__.py \
+        gconf_backend.py\
+        yaml_backend.py
+
+orca_pythondir=$(pyexecdir)/orca/backends
+
diff --git a/src/orca/backends/__init__.py b/src/orca/backends/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/src/orca/backends/gconf_backend.py b/src/orca/backends/gconf_backend.py
new file mode 100644
index 0000000..655cc6a
--- /dev/null
+++ b/src/orca/backends/gconf_backend.py
@@ -0,0 +1,408 @@
+# Orca
+#
+# Copyright 2010 Consorcio Fernando de los Rios.
+# Author: Javier Hernandez Antunez <jhernandez emergya es>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
+# Boston MA  02110-1301 USA.
+
+"""Common utilities to manage the store user preferences over gconf."""
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2010 Consorcio Fernando de los Rios."
+__license__   = "LGPL"
+
+import os
+
+from orca import settings, keybindings
+import gconf
+import types
+
+# The same fields than in orca_gui_prefs.py:
+(HANDLER, DESCRIP, MOD_MASK1, MOD_USED1, KEY1, CLICK_COUNT1, OLDTEXT1, \
+ TEXT1, MOD_MASK2, MOD_USED2, KEY2, CLICK_COUNT2, OLDTEXT2, TEXT2, MODIF, \
+ EDITABLE) = range(16)
+
+(ACTUAL, REPLACEMENT) = range(2)
+
+class Backend:
+    # set gconf configuration properties
+    GCONF_BASE_DIR = '/apps/gnome-orca'
+    VALID_KEY_TYPES = (bool, str, int, list, tuple)
+
+    def __init__(self):
+        """Creates a new Backend instance that will be used to load/store
+        application specific preferences.
+        """
+
+        # init gconf
+        self.__app_key = self.GCONF_BASE_DIR
+        self._client = gconf.client_get_default()
+        self._client.add_dir(self.GCONF_BASE_DIR[:-1],
+                             gconf.CLIENT_PRELOAD_RECURSIVE)
+        self._notifications = []
+
+        self.general = {}
+        self.pronunciations = {}
+        self.keybindings = {}
+        self.profiles = {}
+
+        if not self._client.dir_exists(self.__app_key):
+            self.prefsDict = self.options
+            self.writePreferences()
+
+    def _checkProfile(self, profile=None):
+        if profile is None:
+            profile = ['Default', 'default']
+        activeProfilePath = '%s/activeProfile' % basePath
+        if not self._client.dir_exists(basePath):
+            self._client.set_list(activeProfilePath,
+                                  gconf.VALUE_STRING,
+                                  profile)
+            startingProfilePath = '%s/startingProfile' % basePath
+            self._client.set_list(startingProfilePath,
+                                  gconf.VALUE_STRING,
+                                  profile)
+        else:
+            profile = self._client.get_list(activeProfilePath,
+                                            gconf.VALUE_STRING)
+        profilePath = '%s/%s' % (basePath, profile[1])
+        if not self._client.dir_exists(profilePath):
+            self._client.add_dir(profilePath,
+                                 gconf.CLIENT_PRELOAD_RECURSIVE)
+        return profile
+
+    def _getGeneralPrefs(self, profilePath):
+        gconfEntries = client.all_entries(profilePath)
+        generalPrefs = {}
+        for entry in gconfEntries:
+            gconfPathKey = entry.get_key()
+            key = gconfPathKey.split('/')[-1]
+            value = entry.get_value()
+            if value.type == gconf.VALUE_STRING:
+                generalPrefs[key] = value.get_string()
+            elif value.type == gconf.VALUE_INT:
+                generalPrefs[key] = value.get_int()
+            elif value.type == gconf.VALUE_FLOAT:
+                generalPrefs[key] = value.get_float()
+            elif value.type == gconf.VALUE_BOOL:
+                generalPrefs[key] = value.get_bool()
+            elif value.type == gconf.VALUE_LIST:
+                values = [item.get_string() for item in value.get_list()]
+                generalPrefs[key] = values
+            else:
+                generalPrefs[key] = None
+        return generalPrefs
+
+    def _getVoicesPrefs(self, voicesPath):
+        from orca.acss import ACSS
+        gconfEntries = self._client.all_entries(voicesPath)
+        voicesPrefs = {}
+        for entry in gconfEntries:
+            gconfPathKey = entry.get_key()
+            key = gconfPathKey.split('/')[-1]
+            key = getattr(settings, key)
+            value = entry.get_value()
+            _value = value.get_string()
+            voicesPrefs[key] = eval(_value)
+        return voicesPrefs
+
+    def _getSettings(self):
+        if profile is None:
+           profile = self.checkProfile()
+        profilePath = '%s/%s' % (basePath, profile[1])
+        voicesPath = '%s/voices' % profilePath
+        generalPrefs = self._getGeneralPrefs(profilePath)
+        voicesPrefs = self._getVoicesPrefs(voicesPath)
+        prefsDict = generalPrefs
+        prefsDict['voices'] = voicesPrefs
+        return prefsDict
+
+
+
+    def __format_gconf_dir(self, path, entry):
+        formatDir = path.split('/')
+
+        for item in range(4):
+            formatDir.pop(0)
+        dictString = 'self.options'
+
+        for item in formatDir:
+            dictString += repr([item])
+        dictString += repr([entry.key.split('/')[-1]])
+
+        return dictString
+
+
+    def gconf_save(self, key = None, keyDictionary = None):
+        casts = {types.BooleanType: gconf.Client.set_bool,
+                 types.IntType:     gconf.Client.set_int,
+                 types.FloatType:   gconf.Client.set_float,
+                 types.StringType:  gconf.Client.set_string,
+                 types.ListType:    gconf.Client.set_list,
+                 types.TupleType:   gconf.Client.set_list}
+
+        if key and keyDictionary:
+            self.__app_key += '/%s' % key
+            keyDict = keyDictionary
+        else:
+            if not self.prefsDict:
+                keyDict = self.options = self.DEFAULTS
+            else:
+                keyDict = self.options = self.prefsDict
+ 
+        for name, value in keyDict.items():
+            if name in ['activeProfile', 'startingProfile']:
+                continue
+            if isinstance(value, dict) and len(value) != 0:
+                self.gconf_save(name, value)
+                self.__app_key = \
+                    self.__app_key[:len(self.__app_key) - (len(name) + 1)]
+                continue
+
+            if type(value) in (list, tuple) and value != 0:
+                string_value = [str(item) for item in value]
+                casts[type(value)](self._client, self.__app_key + '/' + name,
+                    gconf.VALUE_STRING, string_value)
+            else:
+                if name in self.need2repr and value != None:
+                    value = self._fix_quotes(value)
+                if value != None and not isinstance(value, dict):
+                    casts[type(value)](self._client, self.__app_key + '/' + \
+                                       name, value)
+
+    def writePreferences(self):
+        """Creates the gconf schema and files to hold user preferences.  Note
+        that callers of this method may want to consider using an ordered
+        dictionary so that the keys are output in a deterministic order.
+
+        Returns True if accessibility was enabled as a result of this
+        call.
+        """
+
+        self._setupPreferencesDirs()
+        
+        # JD -> JH: Another sanity check: self.prefsDict['activeProfile']
+        # might exist with a value of None.
+        #
+        defaultValue = ['Default', 'default']
+        if not self.prefsDict.get('activeProfile'):
+            self.prefsDict['activeProfile'] = defaultValue
+            self._client.set_bool('/apps/gnome-orca/firstStart', True)
+        if not self.prefsDict.get('startingProfile'):
+            self.prefsDict['startingProfile'] = defaultValue
+
+        if self.prefsDict:
+            self._client.set_list('/apps/gnome-orca/activeProfile',
+                                    gconf.VALUE_STRING,
+                                    self.prefsDict['activeProfile'])
+            self._client.set_list('/apps/gnome-orca/startingProfile',
+                                    gconf.VALUE_STRING,
+                                    self.prefsDict['startingProfile'])
+            activeProfileName = self.prefsDict['activeProfile'][1]
+            self._client.set_list('/apps/gnome-orca/%s/profile' % activeProfileName,
+                                    gconf.VALUE_STRING,
+                                    self.prefsDict['activeProfile'])
+            self.__app_key += '/%s' % activeProfileName
+
+            for key in settings.userCustomizableSettings:
+                if key not in ['voices', 'firstStart', 'speechServerInfo']:
+                    self.prefsDict[key] = self._getValueForKey(self.prefsDict, key)
+                if key in self.need2repr:
+                    self.prefsDict[key] = self._fix_quotes(self.prefsDict[key])
+
+        if self.keyBindingsTreeModel:
+            self.prefsDict['overridenKeyBindings'] = {}
+            thisIter = self.keyBindingsTreeModel.get_iter_first()
+            while thisIter != None:
+                iterChild = self.keyBindingsTreeModel.iter_children(thisIter)
+                while iterChild != None:
+                    values = self.keyBindingsTreeModel.get(iterChild,
+                                       0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
+                    if values[MODIF] and not values[KEY1]  == None:
+                        key = values[HANDLER]                         
+                        self.prefsDict['overridenKeyBindings'][key] = [values[DESCRIP], \
+                            values[MOD_MASK1], values[MOD_USED1], values[KEY1], \
+                            values[CLICK_COUNT1], values[OLDTEXT1], values[TEXT1], \
+                            values[MOD_MASK2], values[MOD_USED2], values[KEY2], \
+                            values[CLICK_COUNT2], values[OLDTEXT2], values[TEXT2], \
+                            values[MODIF], values[EDITABLE]]
+                    iterChild = self.keyBindingsTreeModel.iter_next(iterChild)
+
+                thisIter = self.keyBindingsTreeModel.iter_next(thisIter)
+            # Clear overridenkeybindings gconf's dir for a safe store/load 
+            self._client.recursive_unset(self.GCONF_BASE_DIR + '/overridenKeyBindings', 
+                gconf.UNSET_INCLUDING_SCHEMA_NAMES)           
+            self._client.suggest_sync()
+
+        if self.pronunciationTreeModel:
+            self.prefsDict['pronunciations'] = {}
+            thisIter = self.pronunciationTreeModel.get_iter_first()
+
+            while thisIter != None:
+                values = self.pronunciationTreeModel.get(thisIter, ACTUAL, REPLACEMENT)
+                word = values[ACTUAL]
+                value = values[REPLACEMENT]
+
+                if word != "" and value != "":
+                    self.prefsDict['pronunciations'][word] = value
+ 
+                thisIter = self.pronunciationTreeModel.iter_next(thisIter)
+
+            # Clear pronunciations gconf's dir for a safe store/load 
+            self._client.recursive_unset(self.GCONF_BASE_DIR + '/pronunciations',
+                gconf.UNSET_INCLUDING_SCHEMA_NAMES)
+            self._client.suggest_sync()
+            
+
+        self.gconf_save()
+
+        self.prefsDict = self.options
+
+        return self._enableAccessibility()
+
+    def loadSettings(self):
+        """Load settings"""
+        
+        # if not settings to load, save defaults
+        #
+
+        ## Now, if this the first orca exec, orca should
+        #  show preferences dialog
+        if not self._client.all_entries(self.__app_key):
+            return False
+        elif isFirstStart():
+            path = '/apps/gnome-orca/startingProfile'
+        else:
+            path = '/apps/gnome-orca/activeProfile'
+        profileKey = self._client.get_list(path, gconf.VALUE_STRING)
+        self.__app_key += '/%s' % profileKey[1]
+ 
+        self.gconf_load()
+
+        # JD -> JO: What's up with these? Why are they (all) necessary?
+        #
+        self.settingsDict = self.prefsDict = self.options
+
+        import orca.debug
+        from orca import acss
+        orca.debug.debugLevel = orca.debug.LEVEL_SEVERE
+
+        voiceSettings = ['speechServerFactory', 'speechServerInfo', 'voices']
+        for key in settings.userCustomizableSettings:
+            value = self.settingsDict.get(key)
+            #value = self._getValueForKey(self.settingsDict, key)
+            if key in voiceSettings and not value:
+                value = eval('settings.%s' % key)
+            if value == None:
+                continue
+
+            if value in ['true', 'false']:
+                value = value.capitalize()
+            if key in self.need2repr:
+                value = self._fix_quotes(value)
+            setting = 'orca.settings.%s = %s' % (key, value)
+            exec setting
+
+        # Load orca.pronunciation_dict
+        #
+        import orca.pronunciation_dict
+
+        if self.settingsDict.has_key('pronunciations'):
+            orca.pronunciation_dict.pronunciation_dict = {}
+            for key, value in self.settingsDict['pronunciations'].items():
+                orca.pronunciation_dict.setPronunciation(str(key), str(value))
+
+        import orca.orca_state
+
+        # Load keybindings
+        #
+        #FIXME: This make no sense, we need to do another thing to overwrite
+        # the overrideKeyBindings
+        #settings.overrideKeyBindings = self.__loadOverridenKeyBindings
+
+        try:
+            reload(orca.orca_state.orcaCustomizations)
+        except AttributeError:
+            try:
+                orca.orca_state.orcaCustomizations = __import__("orca-customizations")
+            except ImportError:
+                pass
+
+        self.prefsDict = self.settingsDict
+
+        return True
+
+    def __loadOverridenKeyBindings(self, script, keyB):
+        """Load overriden keybindings defined by user"""
+
+        if len(self.prefsDict['overridenKeyBindings']) == 0: return keyB
+
+        for key in self.prefsDict['overridenKeyBindings']:
+            keyB.removeByHandler(script.inputEventHandlers[key])
+            keyB.add(keybindings.KeyBinding(
+                str(self.prefsDict['overridenKeyBindings'][key][3]),
+                int(self.prefsDict['overridenKeyBindings'][key][1]),
+                int(self.prefsDict['overridenKeyBindings'][key][2]),
+                script.inputEventHandlers[key],
+                int(self.prefsDict['overridenKeyBindings'][key][4])))
+            if self.prefsDict['overridenKeyBindings'][key][9] != 'None' :
+                keyB.add(keybindings.KeyBinding(
+                    str(self.prefsDict['overridenKeyBindings'][key][9]),
+                    int(self.prefsDict['overridenKeyBindings'][key][7]),
+                    int(self.prefsDict['overridenKeyBindings'][key][8]),
+                    script.inputEventHandlers[key],
+                    int(self.prefsDict['overridenKeyBindings'][key][10])))
+
+        return keyB
+
+    def _fix_quotes(self, value):
+        """Checks for quotes and return a valid loadable setting"""
+
+        new_value = value.replace("\'", "").replace("\"", "").replace("\\", "")
+        if value.startswith("\""):
+            return "\"%s\"" % new_value
+        else:
+            return "'%s'" % new_value
+        
+    def availableProfiles(self):
+        """Returns a list of available profiles
+        It will be a list of strings list like this:
+        ['Label', 'name']
+        """
+
+        profilesKeys = self._client.all_dirs(self.GCONF_BASE_DIR)
+        profiles = []
+        for profileKey in profilesKeys:
+            name = profileKey.split('/')[-1]
+            key = path + '/%s/profile' % name
+            profile = self._client.get_list(key, gconf.VALUE_STRING)
+            profiles.append(profile)
+    
+        return profiles
+
+    def isFirstStart(self):
+        """Check if the firstStart key is True or false"""
+        firstStartPath = self.GCONF_BASE_DIR + '/firstStart'
+        return self._client.get_bool(firstStartPath)
+    
+    def setFirstStart(self, value=False):
+        """Set firstStart. This user-configurable settting is primarily
+        intended to serve as an indication as to whether or not initial
+        configuration is needed."""
+        firstStartPath = self.GCONF_BASE_DIR + '/firstStart'
+        self._client.set_bool(firstStartPath, value)
diff --git a/src/orca/backends/yaml_backend.py b/src/orca/backends/yaml_backend.py
new file mode 100644
index 0000000..8c015b0
--- /dev/null
+++ b/src/orca/backends/yaml_backend.py
@@ -0,0 +1,160 @@
+# Orca
+#
+# Copyright 2010 Consorcio Fernando de los Rios.
+# Author: Juanje Ojeda Croissier <jojeda emergya es>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
+# Boston MA  02110-1301 USA.
+
+"""YAML backend for Orca settings"""
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2010 Consorcio Fernando de los Rios."
+__license__   = "LGPL"
+
+from yaml import load, dump
+import os
+from orca import settings
+
+class Backend:
+
+    def __init__(self):
+        """ Initialize the YAML Backend.
+        """ 
+        self.general = {}
+        self.pronunciations = {}
+        self.keybindings = {}
+        self.profiles = {}
+        self.settingsFile = os.path.join(settings.userPrefsDir,
+                                         "user-settings.conf")
+
+    def saveDefaultSettings(self, general, pronunciations, keybindings):
+        """ Save default settings for all the properties from
+            orca.settings. """
+        defaultProfiles = {'default': { 'profile':  settings.profile,
+                                                    'pronunciations': {},
+                                                    'keybindings': {}
+                                      }
+                          }
+        prefs = {'general': general,
+                 'profiles': defaultProfiles,
+                 'pronunciations': pronunciations,
+                 'keybindings': keybindings}
+
+        self.general = general
+        self.profiles = defaultProfiles
+        self.pronunciations = pronunciations
+        self.keybindings = keybindings
+
+        settingsFile = open(self.settingsFile, 'w')
+        dump(prefs, settingsFile)
+        settingsFile.close()
+
+    def saveProfileSettings(self, profile, general,
+                                  pronunciations, keybindings):
+        """ Save minimal subset defined in the profile against current 
+            defaults. """
+        if profile is None:
+            profile = 'default'
+
+        general['pronunciations'] = pronunciations
+        general['keybindings'] = keybindings
+
+        with open(self.settingsFile, 'r+') as settingsFile:
+            prefs = load(settingsFile)
+            prefs['profiles'][profile] = general
+            settingsFile.seek(0)
+            settingsFile.truncate()
+            dump(prefs, settingsFile)
+
+    def _getSettings(self):
+        """ Load from config file all settings """
+        settingsFile = open(self.settingsFile)
+        prefs = load(settingsFile)
+        self.general = prefs['general'].copy()
+        self.pronunciations = prefs['pronunciations']
+        self.keybindings = prefs['keybindings']
+        self.profiles = prefs['profiles'].copy()
+
+    def getGeneral(self, profile='default'):
+        """ Get general settings from default settings and
+            override with profile values. """
+        self._getSettings()
+        generalSettings = self.general.copy()
+        profileSettings = self.profiles[profile].copy()
+        for key, value in profileSettings.items():
+            if key not in settings.excludeKeys:
+                generalSettings[key] = value
+        generalSettings['activeProfile'] = profileSettings['profile']
+        return generalSettings
+
+    def getPronunciations(self, profile='default'):
+        """ Get pronunciation settings from default settings and
+            override with profile values. """
+        self._getSettings()
+        pronunciations = self.pronunciations.copy()
+        profileSettings = self.profiles[profile].copy()
+        if profileSettings.has_key('pronunciations'):
+            pronunciations = profileSettings['pronunciations']
+        return pronunciations
+
+    def getKeybindings(self, profile='default'):
+        """ Get keybindings settings from default settings and
+            override with profile values. """
+        self._getSettings()
+        keybindings = self.keybindings.copy()
+        profileSettings = self.profiles[profile].copy()
+        if profileSettings.has_key('keybindings'):
+            keybindings = profileSettings['keybindings']
+        return keybindings
+
+    def isFirstStart(self):
+        """ Check if we're in first start. """
+ 
+        if not os.path.exists(self.settingsFile):
+            return True
+
+        self._getSettings()
+        return self.general.get('firstStart', True)
+
+    def _setProfileKey(self, key, value):
+        self.general[key] = value
+
+        with open(self.settingsFile, 'r+') as settingsFile:
+            prefs = load(settingsFile)
+            prefs['general'][key] = value
+            settingsFile.seek(0)
+            settingsFile.truncate()
+            dump(prefs, settingsFile)
+
+    def setFirstStart(self, value=False):
+        """Set firstStart. This user-configurable settting is primarily
+        intended to serve as an indication as to whether or not initial
+        configuration is needed."""
+        self.general['firstStart'] = value
+        self._setProfileKey('firstStart', value)
+
+    def availableProfiles(self):
+        """ List available profiles. """
+        self._getSettings()
+        profiles = []
+
+        for profileName in self.profiles.keys():
+            profileDict = self.profiles[profileName].copy()
+            profiles.append(profileDict.get('profile'))
+
+        return profiles
diff --git a/src/orca/braille_generator.py b/src/orca/braille_generator.py
index 5577250..213e582 100644
--- a/src/orca/braille_generator.py
+++ b/src/orca/braille_generator.py
@@ -29,12 +29,15 @@ import pyatspi
 
 import braille
 import generator
+import orca
 import orca_state
 import rolenames
 import settings
 
 from orca_i18n import ngettext  # for ngettext support
 
+_settingsManager = getattr(orca, '_settingsManager')
+
 class Space:
     """A dummy class to indicate we want to insert a space into an
     utterance, but only if there is text prior to the space."""
@@ -119,8 +122,8 @@ class BrailleGenerator(generator.Generator):
         """
         result = []
         role = args.get('role', obj.getRole())
-        if (role in settings.brailleForceRoles)\
-           or ((settings.brailleVerbosityLevel \
+        if (role in _settingsManager.getSetting('brailleForceRoles'))\
+           or ((_settingsManager.getSetting('brailleVerbosityLevel') \
                 == settings.VERBOSITY_LEVEL_VERBOSE)\
                and not args.get('readingRow', False)\
                and (role != pyatspi.ROLE_UNKNOWN)):
@@ -181,7 +184,7 @@ class BrailleGenerator(generator.Generator):
         previous object with focus.
         """
         result = []
-        if not settings.enableBrailleContext:
+        if not _settingsManager.getSetting('enableBrailleContext'):
             return result
         args['includeContext'] = False
 
@@ -293,7 +296,7 @@ class BrailleGenerator(generator.Generator):
         # are on the very first line.  Otherwise, we show only the
         # line.
         #
-        include = settings.enableBrailleContext
+        include = _settingsManager.getSetting('enableBrailleContext')
         if not include:
             return include
         try:
@@ -322,7 +325,7 @@ class BrailleGenerator(generator.Generator):
 
     def _generateEol(self, obj, **args):
         result = []
-        if not settings.disableBrailleEOL:
+        if not _settingsManager.getSetting('disableBrailleEOL'):
             if not args.get('mode', None):
                 args['mode'] = self._mode
             args['stringType'] = 'eol'
diff --git a/src/orca/chat.py b/src/orca/chat.py
index e177851..b41513b 100644
--- a/src/orca/chat.py
+++ b/src/orca/chat.py
@@ -29,12 +29,15 @@ import pyatspi
 
 import input_event
 import keybindings
+import orca
 import orca_state
 import settings
 import speech
 
 from orca_i18n import _
 
+_settingsManager = getattr(orca, '_settingsManager')
+
 #############################################################################
 #                                                                           #
 # Ring List. A fixed size circular list by Flavio Catalani                  #
@@ -412,8 +415,9 @@ class Chat:
         self.speakNameCheckButton = gtk.CheckButton(label)
         gtk.Widget.show(self.speakNameCheckButton)
         gtk.Box.pack_start(vbox, self.speakNameCheckButton, False, False, 0)
-        gtk.ToggleButton.set_active(self.speakNameCheckButton,
-                                    settings.chatSpeakRoomName)
+        gtk.ToggleButton.set_active(
+            self.speakNameCheckButton,
+            _settingsManager.getSetting('chatSpeakRoomName'))
 
         # Translators: If this checkbox is checked, then Orca will tell
         # you when one of your buddies is typing a message.
@@ -422,8 +426,9 @@ class Chat:
         self.buddyTypingCheckButton = gtk.CheckButton(label)
         gtk.Widget.show(self.buddyTypingCheckButton)
         gtk.Box.pack_start(vbox, self.buddyTypingCheckButton, False, False, 0)
-        gtk.ToggleButton.set_active(self.buddyTypingCheckButton,
-                                    settings.chatAnnounceBuddyTyping)
+        gtk.ToggleButton.set_active(
+                self.buddyTypingCheckButton,
+                _settingsManager.getSetting('chatAnnounceBuddyTyping'))
 
         # Translators: If this checkbox is checked, then Orca will provide
         # the user with chat room specific message histories rather than just
@@ -435,8 +440,9 @@ class Chat:
         gtk.Widget.show(self.chatRoomHistoriesCheckButton)
         gtk.Box.pack_start(vbox, self.chatRoomHistoriesCheckButton,
                            False, False, 0)
-        gtk.ToggleButton.set_active(self.chatRoomHistoriesCheckButton,
-                                    settings.chatRoomHistories)
+        gtk.ToggleButton.set_active(
+            self.chatRoomHistoriesCheckButton,
+            _settingsManager.getSetting('chatRoomHistories'))
 
         # "Speak Messages" frame.
         #
@@ -453,6 +459,8 @@ class Chat:
         gtk.Widget.show(messagesVBox)
         gtk.Container.add(messagesAlignment, messagesVBox)
 
+        verbosity = _settingsManager.getSetting('chatMessageVerbosity')
+
         # Translators: Orca will speak all new chat messages as they appear
         # irrespective of whether the chat application currently has focus.
         # This is the default behaviour.
@@ -461,36 +469,37 @@ class Chat:
         gtk.Widget.show(self.allMessagesRadioButton)
         gtk.Box.pack_start(messagesVBox, self.allMessagesRadioButton,
                            False, False, 0)
-        gtk.ToggleButton.set_active(self.allMessagesRadioButton,
-            (settings.chatMessageVerbosity == settings.CHAT_SPEAK_ALL))
+        gtk.ToggleButton.set_active(
+            self.allMessagesRadioButton,
+            verbosity == settings.CHAT_SPEAK_ALL)
 
         # Translators: Orca will speak only new chat messages for the channel
         # that currently has focus, irrespective of whether the chat
         # application has focus.
         #
-        self.focusedChannelRadioButton = gtk.RadioButton( \
-                             self.allMessagesRadioButton, \
-                             _("A channel only if its _window is active"))
+        self.focusedChannelRadioButton = gtk.RadioButton(
+            self.allMessagesRadioButton,
+            _("A channel only if its _window is active"))
         gtk.Widget.show(self.focusedChannelRadioButton)
         gtk.Box.pack_start(messagesVBox, self.focusedChannelRadioButton,
                            False, False, 0)
-        gtk.ToggleButton.set_active(self.focusedChannelRadioButton,
-            (settings.chatMessageVerbosity == \
-                 settings.CHAT_SPEAK_FOCUSED_CHANNEL))
+        gtk.ToggleButton.set_active(
+            self.focusedChannelRadioButton,
+            verbosity == settings.CHAT_SPEAK_FOCUSED_CHANNEL)
 
         # Translators: Orca will speak new chat messages for all channels
         # only when the chat application has focus.
         #
-        self.allChannelsRadioButton = gtk.RadioButton( \
-                        self.allMessagesRadioButton,
-                       _("All channels when an_y %s window is active") \
-                       % self._script.app.name)
+        self.allChannelsRadioButton = gtk.RadioButton(
+            self.allMessagesRadioButton,
+            _("All channels when an_y %s window is active") \
+              % self._script.app.name)
         gtk.Widget.show(self.allChannelsRadioButton)
         gtk.Box.pack_start(messagesVBox, self.allChannelsRadioButton,
                            False, False, 0)
-        gtk.ToggleButton.set_active(self.allChannelsRadioButton,
-            (settings.chatMessageVerbosity == \
-                 settings.CHAT_SPEAK_ALL_IF_FOCUSED))
+        gtk.ToggleButton.set_active(
+            self.allChannelsRadioButton,
+            verbosity == settings.CHAT_SPEAK_ALL_IF_FOCUSED)
 
         # Translators: this is the title of a panel holding options for
         # how messages in this application's chat rooms should be spoken.
@@ -512,35 +521,37 @@ class Chat:
         """
 
         prefix = "orca.settings"
-        settings.chatSpeakRoomName = \
-                self.speakNameCheckButton.get_active()
+
+        value = self.speakNameCheckButton.get_active()
+        _settingsManager.setSetting('chatSpeakRoomName', value)
         prefs.writelines("\n")
-        prefs.writelines("%s.chatSpeakRoomName = %s\n" % \
-                         (prefix, settings.chatSpeakRoomName))
+        prefs.writelines("%s.chatSpeakRoomName = %s\n" % (prefix, value))
 
-        settings.chatAnnounceBuddyTyping = \
-                self.buddyTypingCheckButton.get_active()
-        prefs.writelines("%s.chatAnnounceBuddyTyping = %s\n" % \
-                         (prefix, settings.chatAnnounceBuddyTyping))
+        value = self.buddyTypingCheckButton.get_active()
+        _settingsManager.setSetting('chatAnnounceBuddyTyping', value)
+        prefs.writelines("%s.chatAnnounceBuddyTyping = %s\n" % (prefix, value))
 
-        settings.chatRoomHistories = \
-                self.chatRoomHistoriesCheckButton.get_active()
-        prefs.writelines("%s.chatRoomHistories = %s\n" % \
-                         (prefix, settings.chatRoomHistories))
+        value = self.chatRoomHistoriesCheckButton.get_active()
+        _settingsManager.setSetting('chatRoomHistories', value)
+        prefs.writelines("%s.chatRoomHistories = %s\n" % (prefix, value))
 
+        value = None
+        option = None
         if self.allMessagesRadioButton.get_active():
-            settings.chatMessageVerbosity = settings.CHAT_SPEAK_ALL
+            value = settings.CHAT_SPEAK_ALL
             option = ("%s.CHAT_SPEAK_ALL" % prefix)
         elif self.allChannelsRadioButton.get_active():
-            settings.chatMessageVerbosity = \
-                    settings.CHAT_SPEAK_ALL_IF_FOCUSED
+            value = settings.CHAT_SPEAK_ALL_IF_FOCUSED
             option = ("%s.CHAT_SPEAK_ALL_IF_FOCUSED" % prefix)
         elif self.focusedChannelRadioButton.get_active():
-            settings.chatMessageVerbosity = \
-                settings.CHAT_SPEAK_FOCUSED_CHANNEL
+            value = settings.CHAT_SPEAK_FOCUSED_CHANNEL
             option = ("%s.CHAT_SPEAK_FOCUSED_CHANNEL" % prefix)
-        prefs.writelines("\n")
-        prefs.writelines("%s.chatMessageVerbosity = %s\n" % (prefix, option))
+
+        if value and option:
+            _settingsManager.setSetting('chatMessageVerbosity', value)
+            prefs.writelines("\n")
+            prefs.writelines("%s.chatMessageVerbosity = %s\n" % \
+                            (prefix, option))
 
     ########################################################################
     #                                                                      #
@@ -558,8 +569,9 @@ class Chat:
         """
 
         line = _("speak chat room name.")
-        settings.chatSpeakRoomName = not settings.chatSpeakRoomName
-        if not settings.chatSpeakRoomName:
+        speakRoomName = _settingsManager.getSetting('chatSpeakRoomName')
+        _settingsManager.setSetting('chatSpeakRoomName', not speakRoomName)
+        if speakRoomName:
             line = _("Do not speak chat room name.")
         self._script.presentMessage(line)
 
@@ -574,8 +586,10 @@ class Chat:
         """
 
         line = _("announce when your buddies are typing.")
-        settings.chatAnnounceBuddyTyping = not settings.chatAnnounceBuddyTyping
-        if not settings.chatAnnounceBuddyTyping:
+        announceTyping = _settingsManager.getSetting('chatAnnounceBuddyTyping')
+        _settingsManager.setSetting(
+            'chatAnnounceBuddyTyping', not announceTyping)
+        if announceTyping:
             line = _("Do not announce when your buddies are typing.")
         self._script.presentMessage(line)
 
@@ -590,8 +604,9 @@ class Chat:
         """
 
         line = _("Provide chat room specific message histories.")
-        settings.chatRoomHistories = not settings.chatRoomHistories
-        if not settings.chatRoomHistories:
+        roomHistories = _settingsManager.getSetting('chatRoomHistories')
+        _settingsManager.setSetting('chatRoomHistories', not roomHistories)
+        if roomHistories:
             line = _("Do not provide chat room specific message histories.")
         self._script.presentMessage(line)
 
@@ -617,7 +632,7 @@ class Chat:
         messageNumber = self.messageListLength - (index + 1)
         message, chatRoomName = None, None
 
-        if settings.chatRoomHistories:
+        if _settingsManager.getSetting('chatRoomHistories'):
             conversation = self.getConversation(orca_state.locusOfFocus)
             if conversation:
                 message = conversation.getNthMessage(messageNumber)
@@ -651,7 +666,7 @@ class Chat:
             return
 
         text = ""
-        if settings.chatSpeakRoomName and chatRoomName:
+        if _settingsManager.getSetting('chatSpeakRoomName') and chatRoomName:
             text = _("Message from chat room %s") % chatRoomName
         text = self._script.utilities.appendString(text, message)
 
@@ -757,7 +772,7 @@ class Chat:
         Returns True if we spoke the change; False otherwise
         """
 
-        if settings.chatAnnounceBuddyTyping:
+        if _settingsManager.getSetting('chatAnnounceBuddyTyping'):
             conversation = self.getConversation(event.source)
             if conversation and (status != conversation.getTypingStatus()):
                 speech.speak(status)
diff --git a/src/orca/default.py b/src/orca/default.py
index decd01a..163c612 100644
--- a/src/orca/default.py
+++ b/src/orca/default.py
@@ -33,6 +33,9 @@ __license__   = "LGPL"
 import locale
 import time
 
+import orca
+_settingsManager = getattr(orca, '_settingsManager')
+
 import pyatspi
 import braille
 import debug
@@ -46,8 +49,6 @@ try:
 except:
     import mag
 import outline
-import orca
-import orca_prefs
 import orca_state
 import phonnames
 import script
@@ -1194,7 +1195,8 @@ class Script(script.Script):
 
         keyBindings = script.Script.getKeyBindings(self)
 
-        if settings.keyboardLayout == settings.GENERAL_KEYBOARD_LAYOUT_DESKTOP:
+        layout = _settingsManager.getSetting('keyboardLayout')
+        if layout == settings.GENERAL_KEYBOARD_LAYOUT_DESKTOP:
             for keyBinding in self.__getDesktopBindings().keyBindings:
                 keyBindings.add(keyBinding)
         else:
@@ -1204,7 +1206,7 @@ class Script(script.Script):
         import common_keyboardmap
         keyBindings.load(common_keyboardmap.keymap, self.inputEventHandlers)
 
-        if settings.debugMemoryUsage:
+        if _settingsManager.getSetting('debugMemoryUsage'):
             keyBindings.add(
                 keybindings.KeyBinding(
                     "",
@@ -1563,7 +1565,7 @@ class Script(script.Script):
         Returns True to indicate the input event has been consumed.
         """
 
-        if settings.learnModeEnabled:
+        if _settingsManager.getSetting('learnModeEnabled'):
             return True
 
         self.speakMessage(
@@ -1588,7 +1590,7 @@ class Script(script.Script):
         # display.
         #
         self.displayBrailleMessage(_("Learn mode.  Press escape to exit."))
-        settings.learnModeEnabled = True
+        _settingsManager.setSetting('learnModeEnabled', True)
         return True
 
     def enterListShortcutsMode(self, inputEvent):
@@ -1600,8 +1602,8 @@ class Script(script.Script):
 
         Returns True to indicate the input event has been consumed.
         """
-        settings.learnModeEnabled = False
-        if settings.listShortcutsModeEnabled:
+        _settingsManager.setSetting('learnModeEnabled', False)
+        if _settingsManager.getSetting('listShortcutsModeEnabled'):
             return True
 
         # Translators: Orca has a 'List Shortcuts' mode by which a user can
@@ -1626,7 +1628,7 @@ class Script(script.Script):
         message = mode + " " + message
         self.speakMessage(message)
         self.displayBrailleMessage(message, -1, -1)
-        settings.listShortcutsModeEnabled = True
+        _settingsManager.setSetting('listShortcutsModeEnabled', True)
         return True
 
     def findNext(self, inputEvent):
@@ -1998,7 +2000,7 @@ class Script(script.Script):
             # Get a dictionary of text attributes that the user cares about.
             #
             [userAttrList, userAttrDict] = self.utilities.stringToKeysAndDict(
-                settings.enabledSpokenTextAttributes)
+                _settingsManager.getSetting('enabledSpokenTextAttributes'))
 
             # Create a dictionary of just the items we are interested in.
             # Always include size and family-name. For the others, if the
@@ -2572,9 +2574,9 @@ class Script(script.Script):
     def toggleFlatReviewMode(self, inputEvent=None):
         """Toggles between flat review mode and focus tracking mode."""
 
+        verbosity = _settingsManager.getSetting('speechVerbosityLevel')
         if self.flatReviewContext:
-            if inputEvent and (settings.speechVerbosityLevel != \
-                                   settings.VERBOSITY_LEVEL_BRIEF):
+            if inputEvent and verbosity != settings.VERBOSITY_LEVEL_BRIEF:
                 # Translators: the 'flat review' feature of Orca
                 # allows the blind user to explore the text in a
                 # window in a 2D fashion.  That is, Orca treats all
@@ -2590,8 +2592,7 @@ class Script(script.Script):
             self.flatReviewContext = None
             self.updateBraille(orca_state.locusOfFocus)
         else:
-            if inputEvent and (settings.speechVerbosityLevel != \
-                                   settings.VERBOSITY_LEVEL_BRIEF):
+            if inputEvent and verbosity != settings.VERBOSITY_LEVEL_BRIEF:
                 # Translators: the 'flat review' feature of Orca
                 # allows the blind user to explore the text in a
                 # window in a 2D fashion.  That is, Orca treats all
@@ -2614,8 +2615,9 @@ class Script(script.Script):
     def toggleSpeakingIndentationJustification(self, inputEvent=None):
         """Toggles the speaking of indentation and justification."""
 
-        settings.enableSpeechIndentation = not settings.enableSpeechIndentation 
-        if settings.enableSpeechIndentation :
+        value = _settingsManager.getSetting('enableSpeechIndentation')
+        _settingsManager.setSetting('enableSpeechIndentation', not value)
+        if _settingsManager.getSetting('enableSpeechIndentation'):
             # Translators: This is a detailed message indicating that
             # indentation and justification will be spoken.
             #
@@ -2643,7 +2645,7 @@ class Script(script.Script):
     def cycleSpeakingPunctuationLevel(self, inputEvent=None):
         """ Cycle through the punctuation levels for speech. """
 
-        currentLevel = settings.verbalizePunctuationStyle 
+        currentLevel = _settingsManager.getSetting('verbalizePunctuationStyle')
         if currentLevel == settings.PUNCTUATION_STYLE_NONE:
             newLevel = settings.PUNCTUATION_STYLE_SOME
             # Translators: This detailed message will be presented as the
@@ -2702,16 +2704,16 @@ class Script(script.Script):
             #
             brief = C_("spoken punctuation", "None")
 
-        settings.verbalizePunctuationStyle = newLevel
+        _settingsManager.setSetting('verbalizePunctuationStyle', newLevel)
         self.presentMessage(full, brief)
         speech.updatePunctuationLevel()
         return True
 
     def cycleKeyEcho(self, inputEvent=None):
         (newKey, newWord, newSentence) = (False, False, False)
-        key = settings.enableKeyEcho
-        word = settings.enableEchoByWord
-        sentence = settings.enableEchoBySentence
+        key = _settingsManager.getSetting('enableKeyEcho')
+        word = _settingsManager.getSetting('enableEchoByWord')
+        sentence = _settingsManager.getSetting('enableEchoBySentence')
 
         # check if we are in the none case.
         if (key, word, sentence) == (False, False, False):
@@ -2911,9 +2913,9 @@ class Script(script.Script):
             #
             brief = C_("key echo", "None")
 
-        settings.enableKeyEcho = newKey
-        settings.enableEchoByWord = newWord
-        settings.enableEchoBySentence = newSentence
+        _settingsManager.setSetting('enableKeyEcho', newKey)
+        _settingsManager.setSetting('enableEchoByWord', newWord)
+        _settingsManager.setSetting('enableEchoBySentence', newSentence)
         self.presentMessage(full, brief)
         return True
 
@@ -2922,8 +2924,9 @@ class Script(script.Script):
         """Toggles an indicator for whether we should just read the current
         table cell or read the whole row."""
 
-        settings.readTableCellRow = not settings.readTableCellRow
-        if settings.readTableCellRow:
+        speakRow = _settingsManager.getSetting('readTableCellRow')
+        _settingsManager.setSetting('readTableCellRow', not speakRow)
+        if not speakRow:
             # Translators: when users are navigating a table, they
             # sometimes want the entire row of a table read, or
             # they just want the current cell to be presented to them.
@@ -3279,7 +3282,7 @@ class Script(script.Script):
                 return
 
         if event.type.startswith("object:state-changed:selected") \
-           and not settings.onlySpeakDisplayedText \
+           and not _settingsManager.getSetting('onlySpeakDisplayedText') \
            and orca_state.locusOfFocus:
             # If this selection state change is for the object which
             # currently has the locus of focus, and the last keyboard
@@ -3387,7 +3390,8 @@ class Script(script.Script):
         - event: the Event
         """
 
-        if settings.speechVerbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE \
+        verbosity = _settingsManager.getSetting('speechVerbosityLevel')
+        if verbosity == settings.VERBOSITY_LEVEL_VERBOSE \
            and self.utilities.isSameObject(
                 event.source, orca_state.locusOfFocus):
             try:
@@ -3561,7 +3565,8 @@ class Script(script.Script):
             elif wasCommand or wasAutoComplete:
                 speakThis = True
             elif event.source.getRole() == pyatspi.ROLE_PASSWORD_TEXT \
-                 and settings.enableKeyEcho and settings.enablePrintableKeys:
+                 and _settingsManager.getSetting('enableKeyEcho') \
+                 and _settingsManager.getSetting('enablePrintableKeys'):
                 # Echoing "star" is preferable to echoing the descriptive
                 # name of the bullet that has appeared (e.g. "black circle")
                 #
@@ -3575,7 +3580,7 @@ class Script(script.Script):
         # We might need to echo this if it is a single character.
         #
         speakThis = speakThis \
-                    or (settings.enableEchoByCharacter \
+                    or (_settingsManager.getSetting('enableEchoByCharacter') \
                         and string \
                         and event.source.getRole() \
                             != pyatspi.ROLE_PASSWORD_TEXT \
@@ -3602,11 +3607,11 @@ class Script(script.Script):
         [previousChar, startOffset, endOffset] = \
             text.getTextAtOffset(previousOffset, pyatspi.TEXT_BOUNDARY_CHAR)
 
-        if settings.enableEchoBySentence \
+        if _settingsManager.getSetting('enableEchoBySentence') \
            and self.utilities.isSentenceDelimiter(currentChar, previousChar):
             self.echoPreviousSentence(event.source)
 
-        elif settings.enableEchoByWord \
+        elif _settingsManager.getSetting('enableEchoByWord') \
              and self.utilities.isWordDelimiter(currentChar):
             self.echoPreviousWord(event.source)
 
@@ -3796,10 +3801,10 @@ class Script(script.Script):
         notification_messages.listNotificationMessagesModeEnabled = False
 
         # disable learn mode
-        settings.learnModeEnabled = False
+        _settingsManager.setSetting('learnModeEnabled', False)
 
         # disable list shortcuts mode
-        settings.listShortcutsModeEnabled = False
+        _settingsManager.setSetting('listShortcutsModeEnabled', False)
         orca_state.listOfShortcuts = []
         orca_state.typeOfShortcuts = ""
 
@@ -4253,11 +4258,12 @@ class Script(script.Script):
         - obj:  the Accessible progress bar object.
         """
 
-        if settings.enableProgressBarUpdates:
+        if _settingsManager.getSetting('enableProgressBarUpdates'):
             makeAnnouncment = False
-            if settings.progressBarVerbosity == settings.PROGRESS_BAR_ALL:
+            verbosity = _settingsManager.getSetting('progressBarVerbosity')
+            if verbosity == settings.PROGRESS_BAR_ALL:
                 makeAnnouncement = True
-            elif settings.progressBarVerbosity == settings.PROGRESS_BAR_WINDOW:
+            elif verbosity == settings.PROGRESS_BAR_WINDOW:
                 makeAnnouncement = self.utilities.isSameObject(
                     self.utilities.topLevelObject(obj),
                     self.utilities.activeWindow())
@@ -4305,7 +4311,7 @@ class Script(script.Script):
                     (value.maximumValue - value.minimumValue)) * 100.0)
 
                 if (currentTime - lastProgressBarTime) > \
-                       settings.progressBarUpdateInterval \
+                      _settingsManager.getSetting('progressBarUpdateInterval') \
                    or percentValue == 100:
                     if lastProgressBarValue != percentValue:
                         utterances = []
@@ -4461,12 +4467,13 @@ class Script(script.Script):
         else:
             voice = self.voices[settings.DEFAULT_VOICE]
 
+        speakBlankLines = _settingsManager.getSetting('speakBlankLines')
         debug.println(debug.LEVEL_FINEST, \
             "sayCharacter: char=<%s>, startOffset=%d, " % \
             (character, startOffset))
         debug.println(debug.LEVEL_FINEST, \
             "caretOffset=%d, endOffset=%d, speakBlankLines=%s" % \
-            (offset, endOffset, settings.speakBlankLines))
+            (offset, endOffset, speakBlankLines))
 
         if character == "\n":
             line = text.getTextAtOffset(max(0, offset),
@@ -4474,7 +4481,7 @@ class Script(script.Script):
             if not line[0] or line[0] == "\n":
                 # This is a blank line. Announce it if the user requested
                 # that blank lines be spoken.
-                if settings.speakBlankLines:
+                if speakBlankLines:
                     # Translators: "blank" is a short word to mean the
                     # user has navigated to an empty line.
                     #
@@ -4484,7 +4491,7 @@ class Script(script.Script):
         if character in ["\n", "\r\n"]:
             # This is a blank line. Announce it if the user requested
             # that blank lines be spoken.
-            if settings.speakBlankLines:
+            if speakBlankLines:
                 # Translators: "blank" is a short word to mean the
                 # user has navigated to an empty line.
                 #
@@ -4511,7 +4518,7 @@ class Script(script.Script):
             (line, len(line), startOffset))
         debug.println(debug.LEVEL_FINEST, \
             "caret=%d, speakBlankLines=%s" % \
-            (caretOffset, settings.speakBlankLines))
+            (caretOffset, _settingsManager.getSetting('speakBlankLines')))
 
         if len(line) and line != "\n":
             if line.decode("UTF-8").isupper():
@@ -4877,9 +4884,10 @@ class Script(script.Script):
 
         # Determine the correct "say all by" mode to use.
         #
-        if settings.sayAllStyle == settings.SAYALL_STYLE_SENTENCE:
+        sayAllStyle = _settingsManager.getSetting('sayAllStyle')
+        if sayAllStyle == settings.SAYALL_STYLE_SENTENCE:
             mode = pyatspi.TEXT_BOUNDARY_SENTENCE_END
-        elif settings.sayAllStyle == settings.SAYALL_STYLE_LINE:
+        elif sayAllStyle == settings.SAYALL_STYLE_LINE:
             mode = pyatspi.TEXT_BOUNDARY_LINE_START
         else:
             mode = pyatspi.TEXT_BOUNDARY_LINE_START
@@ -5063,7 +5071,10 @@ class Script(script.Script):
         """Save a copy of all the existing application specific settings
         (as specified by the settings.userCustomizableSettings dictionary)."""
 
-        return orca_prefs.readPreferences()
+        generalSettings = \
+            _settingsManager.getGeneralSettings(_settingsManager.profile)
+        generalSettings.update(_settingsManager.customizedSettings)
+        return generalSettings
 
     def restoreOldAppSettings(self, prefsDict):
         """Restore a copy of all the previous saved application settings.
@@ -5132,7 +5143,7 @@ class Script(script.Script):
         - endOffset: text end offset.
         """
 
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return
 
         try:
@@ -5311,7 +5322,7 @@ class Script(script.Script):
         except:
             debug.printException(debug.LEVEL_FINEST)
 
-        if not settings.onlySpeakDisplayedText:
+        if not _settingsManager.getSetting('onlySpeakDisplayedText'):
             voice = self.voices.get(settings.SYSTEM_VOICE)
             if self.utilities.isTextSelected(obj, startOffset, endOffset):
                 # Translators: when the user selects (highlights) text in
@@ -5355,7 +5366,8 @@ class Script(script.Script):
           attributes.
         """
 
-        if settings.speechVerbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE:
+        verbosity = _settingsManager.getSetting('speechVerbosityLevel')
+        if verbosity == settings.VERBOSITY_LEVEL_VERBOSE:
             try:
                 text = obj.queryText()
             except:
@@ -5413,8 +5425,9 @@ class Script(script.Script):
         if briefMessage is None:
             briefMessage = fullMessage
 
-        if settings.enableSpeech:
-            if settings.messageVerbosityLevel == settings.VERBOSITY_LEVEL_BRIEF:
+        if _settingsManager.getSetting('enableSpeech'):
+            if _settingsManager.getSetting('messageVerbosityLevel') \
+                    == settings.VERBOSITY_LEVEL_BRIEF:
                 message = briefMessage
             else:
                 message = fullMessage
@@ -5422,9 +5435,11 @@ class Script(script.Script):
                 voice = voice or self.voices.get(settings.SYSTEM_VOICE)
                 speech.speak(message, voice)
 
-        if (settings.enableBraille or settings.enableBrailleMonitor) \
-           and settings.enableFlashMessages:
-            if settings.flashVerbosityLevel == settings.VERBOSITY_LEVEL_BRIEF:
+        if (_settingsManager.getSetting('enableBraille') \
+             or _settingsManager.getSetting('enableBrailleMonitor')) \
+           and _settingsManager.getSetting('enableFlashMessages'):
+            if _settingsManager.getSetting('flashVerbosityLevel') \
+                    == settings.VERBOSITY_LEVEL_BRIEF:
                 message = briefMessage
             else:
                 message = fullMessage
@@ -5437,10 +5452,10 @@ class Script(script.Script):
                 message = filter(lambda i: isinstance(i, str), message)
                 message = " ".join(message)
 
-            if settings.flashIsPersistent:
+            if _settingsManager.getSetting('flashIsPersistent'):
                 duration = -1
             else:
-                duration = settings.brailleFlashTime
+                duration = _settingsManager.getSetting('brailleFlashTime')
 
             braille.displayMessage(message, flashTime=duration)
 
@@ -5774,7 +5789,7 @@ class Script(script.Script):
           prior to speaking the new text.
         """
 
-        if settings.enableSpeech:
+        if _settingsManager.getSetting('enableSpeech'):
             voice = voice or self.voices.get(settings.SYSTEM_VOICE)
             speech.speak(string, voice, interrupt) 
 
@@ -5811,13 +5826,15 @@ class Script(script.Script):
 
     def presentTime(self, inputEvent):
         """ Presents the current time. """
-        message = time.strftime(settings.presentTimeFormat, time.localtime())
+        timeFormat = _settingsManager.getSetting('presentTimeFormat')
+        message = time.strftime(timeFormat, time.localtime())
         self.presentMessage(message)
         return True
 
     def presentDate(self, inputEvent):
         """ Presents the current date. """
-        message = time.strftime(settings.presentDateFormat, time.localtime())
+        dateFormat = _settingsManager.getSetting('presentDateFormat')
+        message = time.strftime(dateFormat, time.localtime())
         self.presentMessage(message)
         return True
 
diff --git a/src/orca/focus_tracking_presenter.py b/src/orca/focus_tracking_presenter.py
index f46e0e8..17d17af 100644
--- a/src/orca/focus_tracking_presenter.py
+++ b/src/orca/focus_tracking_presenter.py
@@ -339,6 +339,9 @@ class FocusTrackingPresenter(presentation_manager.PresentationManager):
         - newScript: the new script to be made active.
         """
 
+        if orca_state.activeScript == newScript:
+            return
+
         try:
             # If old ("factory") settings don't exist yet, save
             # a set, else restore the old application settings.
diff --git a/src/orca/mag.py b/src/orca/mag.py
index 26172ec..ca1991f 100644
--- a/src/orca/mag.py
+++ b/src/orca/mag.py
@@ -41,11 +41,13 @@ import pyatspi
 import debug
 import eventsynthesizer
 import settings
+import orca
 import orca_state
 
 from orca_i18n import _  # for gettext support
 
 _magnifierAvailable = False
+_settingsManager = getattr(orca, '_settingsManager')
 
 try:
     import bonobo
@@ -243,8 +245,9 @@ def __setROICursorPush(x, y, width, height, edgeMargin = 0):
     # The edge margin should not exceed 50%. (50% is a centered alignment).
     #
     edgeMargin = min(edgeMargin, 50)/100.00
-    edgeMarginX = edgeMargin * _sourceDisplayBounds.x2/settings.magZoomFactor
-    edgeMarginY = edgeMargin * _sourceDisplayBounds.y2/settings.magZoomFactor
+    magZoomFactor = _settingsManager.getSetting('magZoomFactor')
+    edgeMarginX = edgeMargin * _sourceDisplayBounds.x2/magZoomFactor
+    edgeMarginY = edgeMargin * _sourceDisplayBounds.y2/magZoomFactor
 
     # Determine if the accessible is partially to the left, right,
     # above, or below the current region of interest (ROI).
@@ -446,14 +449,16 @@ def __setupMagnifier(position, left=None, top=None, right=None, bottom=None,
     # Define where the magnifier will live.
     #
     try:
-        _magnifier.TargetDisplay = settings.magTargetDisplay
+        _magnifier.TargetDisplay = \
+            _settingsManager.getSetting('magTargetDisplay')
     except:
         pass
 
     # Define what will be magnified.
     #
     try:
-        _magnifier.SourceDisplay = settings.magSourceDisplay
+        _magnifier.SourceDisplay = \
+            _settingsManager.getSetting('magSourceDisplay')
     except:
         pass
 
@@ -469,7 +474,8 @@ def __setupMagnifier(position, left=None, top=None, right=None, bottom=None,
     # Depends upon new functionality in gnome-mag, so just catch the 
     # exception if this functionality isn't there.
     #
-    hideCursor = restore.get('magHideCursor', settings.magHideCursor)
+    hideCursor = restore.get('magHideCursor',
+                             _settingsManager.getSetting('magHideCursor'))
     if hideCursor \
        and _fullScreenCapable \
        and _magnifier.SourceDisplay == _magnifier.TargetDisplay \
@@ -514,10 +520,10 @@ def __setupMagnifier(position, left=None, top=None, right=None, bottom=None,
         prefRight = sdb.x2
         prefBottom = sdb.y2
     else:
-        prefLeft   = left or settings.magZoomerLeft
-        prefTop    = top or settings.magZoomerTop
-        prefRight  = right or settings.magZoomerRight
-        prefBottom = bottom or settings.magZoomerBottom
+        prefLeft   = left or _settingsManager.getSetting('magZoomerLeft')
+        prefTop    = top or _settingsManager.getSetting('magZoomerTop')
+        prefRight  = right or _settingsManager.getSetting('magZoomerRight')
+        prefBottom = bottom or _settingsManager.getSetting('magZoomerBottom')
     orca_state.zoomerType = position
     updateTarget = True
 
@@ -592,24 +598,30 @@ def __setupMagnifier(position, left=None, top=None, right=None, bottom=None,
 
     bonobo.pbclient_set_string(_magnifierPBag, "cursor-set", "default")
 
-    enableCursor = restore.get('enableMagCursor', settings.enableMagCursor)
-    explicitSize = restore.get('enableMagCursorExplicitSize',
-                               settings.enableMagCursorExplicitSize)
-    size = restore.get('magCursorSize', settings.magCursorSize)
+    enableCursor = restore.get(
+        'enableMagCursor', _settingsManager.getSetting('enableMagCursor'))
+    explicitSize = restore.get(
+        'enableMagCursorExplicitSize',
+        _settingsManager.getSetting('enableMagCursorExplicitSize'))
+    size = restore.get(
+        'magCursorSize', _settingsManager.getSetting('magCursorSize'))
     setMagnifierCursor(enableCursor, explicitSize, size, False)
 
-    value = restore.get('magCursorColor', settings.magCursorColor)
+    value = restore.get(
+        'magCursorColor', _settingsManager.getSetting('magCursorColor'))
     setMagnifierObjectColor("cursor-color", value, False)
 
-    value = restore.get('magCrossHairColor', settings.magCrossHairColor)
+    value = restore.get(
+        'magCrossHairColor', _settingsManager.getSetting('magCrossHairColor'))
     setMagnifierObjectColor("crosswire-color", value, False)
 
-    enableCrossHair = restore.get('enableMagCrossHair',
-                                  settings.enableMagCrossHair)
+    enableCrossHair = restore.get(
+        'enableMagCrossHair', _settingsManager.getSetting('enableMagCrossHair'))
     setMagnifierCrossHair(enableCrossHair, False)
 
-    value = restore.get('enableMagCrossHairClip',
-                        settings.enableMagCrossHairClip)
+    value = restore.get(
+        'enableMagCrossHairClip', 
+        _settingsManager.getSetting('enableMagCrossHairClip'))
     setMagnifierCrossHairClip(value, False)
 
     orca_state.mouseEnhancementsEnabled = enableCursor or enableCrossHair
@@ -637,8 +649,10 @@ def __setupZoomer(restore=None):
 
     debug.println(debug.LEVEL_ALL,
                   "Magnifier target bounds preferences: (%d, %d), (%d, %d)" \
-                  % (settings.magZoomerLeft, settings.magZoomerTop, \
-                     settings.magZoomerRight, settings.magZoomerBottom))
+                  % (_settingsManager.getSetting('magZoomerLeft'),
+                     _settingsManager.getSetting('magZoomerTop'),
+                     _settingsManager.getSetting('magZoomerRight'),
+                     _settingsManager.getSetting('magZoomerBottom')))
 
     debug.println(debug.LEVEL_ALL,
                   "Magnifier target bounds actual: (%d, %d), (%d, %d)" \
@@ -699,14 +713,15 @@ def __setupZoomer(restore=None):
 
     # Now, let's see what the ROI looks like.
     #
+    zoomFactor = _settingsManager.getSetting('magZoomFactor')
     debug.println(debug.LEVEL_ALL,
-                  "Magnifier source width: %d (viewport can show %d)" \
+                 "Magnifier source width: %d (viewport can show %d)" \
                   % (_sourceDisplayBounds.x2 - _sourceDisplayBounds.x1,
-                   viewportWidth / settings.magZoomFactor))
+                  viewportWidth / zoomFactor))
     debug.println(debug.LEVEL_ALL,
                   "Magnifier source height: %d (viewport can show %d)" \
                   % (_sourceDisplayBounds.y2 - _sourceDisplayBounds.y1,
-                   viewportHeight / settings.magZoomFactor))
+                   viewportHeight / zoomFactor))
 
     # Adjust the ROI in the event the source window is too small for the
     # target window.  This usually happens when someone expects COMPOSITE
@@ -714,9 +729,9 @@ def __setupZoomer(restore=None):
     # big grey magnifier on their screen.
     #
     _roiWidth  = min(_sourceDisplayBounds.x2 - _sourceDisplayBounds.x1,
-                     viewportWidth / settings.magZoomFactor)
+                     viewportWidth / zoomFactor)
     _roiHeight = min(_sourceDisplayBounds.y2 - _sourceDisplayBounds.y1,
-                     viewportHeight / settings.magZoomFactor)
+                     viewportHeight / zoomFactor)
 
     debug.println(debug.LEVEL_ALL,
                   "Magnifier zoomer ROI size desired: width=%d, height=%d)" \
@@ -730,58 +745,65 @@ def __setupZoomer(restore=None):
     # individual property changes (e.g. brightness, contrast) upon load.
     #
     _zoomer = _magnifier.createZoomRegion(
-        settings.magZoomFactor, settings.magZoomFactor,
+        zoomFactor, zoomFactor,
         GNOME.Magnifier.RectBounds(0, 0, _roiWidth, _roiHeight),
         GNOME.Magnifier.RectBounds(0, 0, 1, 1))
 
     _zoomerPBag = _zoomer.getProperties()
     bonobo.pbclient_set_boolean(_zoomerPBag, "is-managed", True)
 
-    value = restore.get('magZoomFactor', settings.magZoomFactor)
+    value = restore.get('magZoomFactor', zoomFactor)
     setZoomerMagFactor(value, value, False)
 
-    value = restore.get('enableMagZoomerColorInversion',
-                        settings.enableMagZoomerColorInversion)
+    value = restore.get(
+        'enableMagZoomerColorInversion',
+        _settingsManager.getSetting('enableMagZoomerColorInversion'))
     setZoomerColorInversion(value, False)
 
-    brightness = restore.get('magBrightnessLevel', settings.magBrightnessLevel)
+    brightness = restore.get(
+        'magBrightnessLevel', _settingsManager.getSetting('magBrightnessLevel'))
     r = brightness + \
         restore.get('magBrightnessLevelRed',
-                    settings.magBrightnessLevelRed)
+                    _settingsManager.getSetting('magBrightnessLevelRed'))
     g = brightness + \
         restore.get('magBrightnessLevelGreen',
-                    settings.magBrightnessLevelGreen)
+                    _settingsManager.getSetting('magBrightnessLevelGreen'))
     b = brightness + \
         restore.get('magBrightnessLevelBlue',
-                    settings.magBrightnessLevelBlue)
+                    _settingsManager.getSetting('magBrightnessLevelBlue'))
     setZoomerBrightness(r, g, b, False)
 
-    contrast = restore.get('magContrastLevel', settings.magContrastLevel)
+    contrast = restore.get(
+        'magContrastLevel', _settingsManager.getSetting('magContrastLevel'))
     r = contrast + \
         restore.get('magContrastLevelRed',
-                    settings.magContrastLevelRed)
+                    _settingsManager.getSetting('magContrastLevelRed'))
     g = contrast + \
         restore.get('magContrastLevelGreen',
-                    settings.magContrastLevelGreen)
+                    _settingsManager.getSetting('magContrastLevelGreen'))
     b = contrast + \
         restore.get('magContrastLevelBlue',
-                    settings.magContrastLevelBlue)
+                    _settingsManager.getSetting('magContrastLevelBlue'))
     setZoomerContrast(r, g, b, False)
 
     value = restore.get('magColorFilteringMode',
-                        settings.magColorFilteringMode)
+                        _settingsManager.getSetting('magColorFilteringMode'))
     setZoomerColorFilter(value, False)
 
-    value = restore.get('magZoomerType', settings.magZoomerType)
+    value = restore.get(
+        'magZoomerType', _settingsManager.getSetting('magZoomerType'))
     if value == settings.MAG_ZOOMER_TYPE_FULL_SCREEN:
         size = 0
     else:
-        size = restore.get('magZoomerBorderSize', settings.magZoomerBorderSize)
-    color = restore.get('magZoomerBorderColor', settings.magZoomerBorderColor)
+        size = restore.get('magZoomerBorderSize',
+                           _settingsManager.getSetting('magZoomerBorderSize'))
+    color = restore.get('magZoomerBorderColor',
+                        _settingsManager.getSetting('magZoomerBorderColor'))
     setZoomerObjectSize("border-size", size, False)
     setZoomerObjectColor("border-color", color, False)
 
-    value = restore.get('magSmoothingMode', settings.magSmoothingMode)
+    value = restore.get('magSmoothingMode',
+                        _settingsManager.getSetting('magSmoothingMode'))
     setZoomerSmoothingType(value, False)
 
     # Now it's safe to display the viewport.
@@ -850,15 +872,17 @@ def applySettings():
     global _pointerFollowsZoomer
     global _pointerFollowsFocus
 
-    __setupMagnifier(settings.magZoomerType)
+    __setupMagnifier(_settingsManager.getSetting('magZoomerType'))
     __setupZoomer()
   
-    _mouseTracking = settings.magMouseTrackingMode
-    _controlTracking = settings.magControlTrackingMode
-    _textTracking = settings.magTextTrackingMode
-    _edgeMargin = settings.magEdgeMargin
-    _pointerFollowsZoomer = settings.magPointerFollowsZoomer
-    _pointerFollowsFocus = settings.magPointerFollowsFocus
+    _mouseTracking = _settingsManager.getSetting('magMouseTrackingMode')
+    _controlTracking = _settingsManager.getSetting('magControlTrackingMode')
+    _textTracking = _settingsManager.getSetting('magTextTrackingMode')
+    _edgeMargin = _settingsManager.getSetting('magEdgeMargin')
+    _pointerFollowsZoomer = \
+        _settingsManager.getSetting('magPointerFollowsZoomer')
+    _pointerFollowsFocus = \
+        _settingsManager.getSetting('magPointerFollowsFocus')
 
     #print "MAGNIFIER PROPERTIES:", _magnifier
     #__dumpPropertyBag(_magnifier)
@@ -1057,7 +1081,7 @@ def setMagnifierCursor(enabled, customEnabled, size, updateScreen=True):
     try:
         mag = _zoomerPBag.getValue("mag-factor-x").value()
     except:
-        mag = settings.magZoomFactor
+        mag = _settingsManager.getSetting('magZoomFactor')
 
     if enabled:
         scale = 1.0 * mag
@@ -1086,7 +1110,7 @@ def setMagnifierCrossHair(enabled, updateScreen=True):
 
     size = 0
     if enabled:
-        size = settings.magCrossHairSize
+        size = _settingsManager.getSetting('magCrossHairSize')
 
     bonobo.pbclient_set_long(_magnifierPBag, "crosswire-size", size)
 
@@ -1505,15 +1529,16 @@ def finishLiveUpdating():
     global _pointerFollowsZoomer
 
     _liveUpdatingMagnifier = False
-    _mouseTracking = settings.magMouseTrackingMode
-    _controlTracking = settings.magControlTrackingMode
-    _textTracking = settings.magTextTrackingMode
-    _edgeMargin = settings.magEdgeMargin
-    _pointerFollowsFocus = settings.magPointerFollowsFocus
-    _pointerFollowsZoomer = settings.magPointerFollowsZoomer
-
-    if settings.enableMagnifier:
-        setupMagnifier(settings.magZoomerType)
+    _mouseTracking = _settingsManager.getSetting('magMouseTrackingMode')
+    _controlTracking = _settingsManager.getSetting('magControlTrackingMode')
+    _textTracking = _settingsManager.getSetting('magTextTrackingMode')
+    _edgeMargin = _settingsManager.getSetting('magEdgeMargin')
+    _pointerFollowsFocus = _settingsManager.getSetting('magPointerFollowsFocus')
+    _pointerFollowsZoomer = \
+        _settingsManager.getSetting('magPointerFollowsZoomer')
+
+    if _settingsManager.getSetting('enableMagnifier'):
+        setupMagnifier(_settingsManager.getSetting('magZoomerType'))
         init()
     else:
         shutdown()
@@ -1593,24 +1618,28 @@ def toggleMouseEnhancements(script=None, inputEvent=None):
         # to see *something* change. We don't know what, so enable both
         # the cursor and the cross-hairs.
         #
-        cursorEnable = settings.enableMagCursor
-        crossHairEnable = settings.enableMagCrossHair
+        cursorEnable = _settingsManager.getSetting('enableMagCursor')
+        crossHairEnable = _settingsManager.getSetting('enableMagCrossHair')
         if not (cursorEnable or crossHairEnable):
             cursorEnable = True
             crossHairEnable = True
 
-        setMagnifierCursor(cursorEnable,
-                           settings.enableMagCursorExplicitSize,
-                           settings.magCursorSize,
-                           False)
-        setMagnifierObjectColor("cursor-color",
-                                settings.magCursorColor,
-                                False)
-        setMagnifierObjectColor("crosswire-color",
-                                settings.magCrossHairColor,
-                                False)
-        setMagnifierCrossHairClip(settings.enableMagCrossHairClip,
-                                  False)
+        setMagnifierCursor(
+            cursorEnable,
+            _settingsManager.getSetting('enableMagCursorExplicitSize'),
+            _settingsManager.getSetting('magCursorSize'),
+            False)
+        setMagnifierObjectColor(
+            "cursor-color",
+            _settingsManager.getSetting('magCursorColor'),
+            False)
+        setMagnifierObjectColor(
+            "crosswire-color",
+            _settingsManager.getSetting('magCrossHairColor'),
+            False)
+        setMagnifierCrossHairClip(
+            _settingsManager.getSetting('enableMagCrossHairClip'),
+            False)
         setMagnifierCrossHair(crossHairEnable)
         # Translators: "mouse enhancements" are changes users can
         # make to the appearance of the mouse pointer to make it
@@ -1715,7 +1744,7 @@ def cycleZoomerType(script=None, inputEvent=None):
     toRestore = {}
 
     [levelX, levelY] = _zoomer.getMagFactor()
-    if levelX != settings.magZoomFactor:
+    if levelX != _settingsManager.getSetting('magZoomFactor'):
         toRestore['magZoomFactor'] = levelX
 
     if not orca_state.colorEnhancementsEnabled:
@@ -1736,7 +1765,7 @@ def cycleZoomerType(script=None, inputEvent=None):
     if not orca_state.mouseEnhancementsEnabled:
         setMagnifierCrossHair(False)
         setMagnifierObjectColor("cursor-color",
-                                settings.magCursorColor,
+                                _settingsManager.getSetting('magCursorColor'),
                                 False)
         setMagnifierCursor(False, False, 0)
 
diff --git a/src/orca/orca-profile.ui b/src/orca/orca-profile.ui
new file mode 100644
index 0000000..f314d08
--- /dev/null
+++ b/src/orca/orca-profile.ui
@@ -0,0 +1,155 @@
+<?xml version="1.0"?>
+<interface>
+  <!-- interface-requires gtk+ 2.12 -->
+  <!-- interface-naming-policy toplevel-contextual -->
+  <object class="GtkDialog" id="profileDialog">
+    <property name="title" translatable="yes">Save Profile As</property>
+    <property name="resizable">False</property>
+    <property name="modal">True</property>
+    <property name="type_hint">dialog</property>
+    <property name="skip_taskbar_hint">True</property>
+    <property name="has_separator">False</property>
+    <child internal-child="accessible">
+      <object class="AtkObject" id="profileDialog-atkobject">
+        <property name="AtkObject::accessible-name" translatable="yes">Orca Profile Dialog</property>
+      </object>
+    </child>
+    <signal name="destroy" handler="profileDialogDestroyed"/>
+    <child internal-child="vbox">
+      <object class="GtkVBox" id="dialog-vbox1">
+        <property name="visible">True</property>
+        <child>
+          <object class="GtkVBox" id="vbox1">
+            <property name="visible">True</property>
+            <property name="border_width">6</property>
+            <property name="spacing">12</property>
+            <child>
+              <object class="GtkHBox" id="hbox1">
+                <property name="visible">True</property>
+                <property name="border_width">6</property>
+                <child>
+                  <object class="GtkLabel" id="profileLabel">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">_New Profile:</property>
+                    <property name="use_markup">True</property>
+                    <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">profileEntry</property>
+                    <property name="width_chars">12</property>
+                    <child internal-child="accessible">
+                      <object class="AtkObject" id="profileLabel-atkobject">
+                        <property name="AtkObject::accessible-name" translatable="yes">New Profile:</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkEntry" id="profileEntry">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="invisible_char">&#x25CF;</property>
+                    <property name="activates_default">True</property>
+                    <child internal-child="accessible">
+                      <object class="AtkObject" id="profileEntry-atkobject">
+                        <property name="AtkObject::accessible-name" translatable="yes">New Profile:</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="profileInfoLabel">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">New settings will be saved
+as a new profile.</property>
+              </object>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="padding">5</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <object class="GtkHButtonBox" id="dialog-action_area1">
+            <property name="visible">True</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="closeButton">
+                <property name="label">gtk-close</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_stock">True</property>
+                <accelerator key="c" signal="activate" modifiers="GDK_MOD1_MASK"/>
+                <child internal-child="accessible">
+                  <object class="AtkObject" id="closeButton-atkobject">
+                    <property name="AtkObject::accessible-name" translatable="yes">Close</property>
+                  </object>
+                </child>
+                <signal name="clicked" handler="closeButtonClicked"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="saveProfileButton">
+                <property name="label">gtk-ok</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="has_default">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_stock">True</property>
+                <child internal-child="accessible">
+                  <object class="AtkObject" id="saveProfileButton-atkobject">
+                    <property name="AtkObject::accessible-name" translatable="yes">Add Profile</property>
+                  </object>
+                </child>
+                <signal name="clicked" handler="on_saveProfileButton_clicked"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-7">closeButton</action-widget>
+      <action-widget response="0">saveProfileButton</action-widget>
+    </action-widgets>
+  </object>
+  <object class="GtkListStore" id="liststore1">
+    <columns>
+      <!-- column-name profiles -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
+</interface>
diff --git a/src/orca/orca-setup.ui b/src/orca/orca-setup.ui
index 41c8ff0..8bc9d30 100644
--- a/src/orca/orca-setup.ui
+++ b/src/orca/orca-setup.ui
@@ -261,22 +261,27 @@
       <column type="gchararray"/>
     </columns>
   </object>
+  <object class="GtkListStore" id="model9">
+    <columns>
+      <!-- column-name label -->
+      <column type="gchararray"/>
+      <!-- column-name name -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
   <object class="GtkDialog" id="orcaSetupWindow">
     <property name="title" translatable="yes">Orca Preferences</property>
     <property name="type_hint">normal</property>
-    <property name="has_separator">False</property>
     <signal name="destroy" handler="windowDestroyed"/>
     <signal name="close" handler="windowClosed"/>
     <child internal-child="vbox">
       <object class="GtkVBox" id="dialog-vbox1">
         <property name="visible">True</property>
-        <property name="orientation">vertical</property>
         <property name="spacing">3</property>
         <child>
           <object class="GtkVBox" id="mainvbox">
             <property name="visible">True</property>
             <property name="border_width">6</property>
-            <property name="orientation">vertical</property>
             <property name="spacing">12</property>
             <child>
               <object class="GtkNotebook" id="notebook">
@@ -286,7 +291,6 @@
                   <object class="GtkVBox" id="generalVBox">
                     <property name="visible">True</property>
                     <property name="border_width">12</property>
-                    <property name="orientation">vertical</property>
                     <child>
                       <object class="GtkFrame" id="frame9">
                         <property name="visible">True</property>
@@ -300,7 +304,6 @@
                               <object class="GtkVBox" id="vbox22">
                                 <property name="visible">True</property>
                                 <property name="border_width">3</property>
-                                <property name="orientation">vertical</property>
                                 <child>
                                   <object class="GtkRadioButton" id="generalDesktopButton">
                                     <property name="label" translatable="yes">_Desktop</property>
@@ -537,6 +540,155 @@
                         <property name="position">7</property>
                       </packing>
                     </child>
+                    <child>
+                      <object class="GtkFrame" id="profilesFrame">
+                        <property name="visible">True</property>
+                        <property name="label_xalign">0</property>
+                        <property name="shadow_type">none</property>
+                        <child>
+                          <object class="GtkAlignment" id="alignment5">
+                            <property name="visible">True</property>
+                            <property name="left_padding">6</property>
+                            <child>
+                              <object class="GtkVBox" id="profilesVbox1">
+                                <property name="visible">True</property>
+                                <child>
+                                  <object class="GtkAspectFrame" id="aspectframe2">
+                                    <property name="visible">True</property>
+                                    <property name="label_xalign">0</property>
+                                    <property name="shadow_type">none</property>
+                                    <property name="xalign">0</property>
+                                    <child>
+                                      <object class="GtkTable" id="profilesTable1">
+                                        <property name="visible">True</property>
+                                        <property name="n_rows">2</property>
+                                        <property name="n_columns">4</property>
+                                        <property name="column_spacing">6</property>
+                                        <property name="row_spacing">2</property>
+                                        <child>
+                                          <object class="GtkLabel" id="profilesLabel1">
+                                            <property name="width_request">150</property>
+                                            <property name="visible">True</property>
+                                            <property name="xalign">0</property>
+                                            <property name="xpad">12</property>
+                                            <property name="label" translatable="yes">Active Profile:</property>
+                                            <property name="ellipsize">start</property>
+                                            <accessibility>
+                                              <relation type="label-for" target="availableProfilesComboBox1"/>
+                                            </accessibility>
+                                          </object>
+                                        </child>
+                                        <child>
+                                          <object class="GtkComboBox" id="availableProfilesComboBox1">
+                                            <property name="width_request">200</property>
+                                            <property name="visible">True</property>
+                                            <property name="model">model9</property>
+                                            <child>
+                                              <object class="GtkCellRendererText" id="cellrenderertext5"/>
+                                              <attributes>
+                                                <attribute name="text">0</attribute>
+                                              </attributes>
+                                            </child>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="right_attach">2</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkButton" id="loadProfileButton">
+                                            <property name="label" translatable="yes" comments="This button will load the selected settings profile in the application.">_Load</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                            <property name="use_underline">True</property>
+                                            <signal name="clicked" handler="loadProfileButtonClicked"/>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">2</property>
+                                            <property name="right_attach">3</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkButton" id="saveProfileButton">
+                                            <property name="label">gtk-save-as</property>
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="receives_default">True</property>
+                                            <property name="use_stock">True</property>
+                                            <signal name="clicked" handler="showProfileGUI"/>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">3</property>
+                                            <property name="right_attach">4</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkLabel" id="startupProfileLabel1">
+                                            <property name="visible">True</property>
+                                            <property name="xalign">0</property>
+                                            <property name="xpad">12</property>
+                                            <property name="label" translatable="yes">Start-up Profile:</property>
+                                            <property name="ellipsize">end</property>
+                                            <accessibility>
+                                              <relation type="label-for" target="availableProfilesComboBox2"/>
+                                            </accessibility>
+                                          </object>
+                                          <packing>
+                                            <property name="top_attach">1</property>
+                                            <property name="bottom_attach">2</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkComboBox" id="availableProfilesComboBox2">
+                                            <property name="visible">True</property>
+                                            <property name="model">model9</property>
+                                            <child>
+                                              <object class="GtkCellRendererText" id="cellrenderertext6"/>
+                                              <attributes>
+                                                <attribute name="text">0</attribute>
+                                              </attributes>
+                                            </child>
+                                          </object>
+                                          <packing>
+                                            <property name="left_attach">1</property>
+                                            <property name="right_attach">2</property>
+                                            <property name="top_attach">1</property>
+                                            <property name="bottom_attach">2</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <placeholder/>
+                                        </child>
+                                        <child>
+                                          <placeholder/>
+                                        </child>
+                                      </object>
+                                    </child>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="padding">6</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                        <child type="label">
+                          <object class="GtkLabel" id="form2">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">&lt;b&gt;Profiles&lt;/b&gt;</property>
+                            <property name="use_markup">True</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="position">8</property>
+                      </packing>
+                    </child>
                   </object>
                 </child>
                 <child type="tab">
@@ -552,7 +704,6 @@
                   <object class="GtkVBox" id="vbox20">
                     <property name="visible">True</property>
                     <property name="border_width">12</property>
-                    <property name="orientation">vertical</property>
                     <child>
                       <object class="GtkCheckButton" id="speechSupportCheckButton">
                         <property name="label" translatable="yes">_Enable speech</property>
@@ -574,7 +725,6 @@
                       <object class="GtkVBox" id="speechVbox">
                         <property name="visible">True</property>
                         <property name="border_width">12</property>
-                        <property name="orientation">vertical</property>
                         <property name="spacing">6</property>
                         <child>
                           <object class="GtkTable" id="speechTable">
@@ -974,7 +1124,6 @@
                                               <object class="GtkVBox" id="vbox17">
                                                 <property name="visible">True</property>
                                                 <property name="border_width">3</property>
-                                                <property name="orientation">vertical</property>
                                                 <child>
                                                   <object class="GtkRadioButton" id="speechBriefButton">
                                                     <property name="label" translatable="yes">Brie_f</property>
@@ -1044,7 +1193,6 @@
                                               <object class="GtkVBox" id="vbox21">
                                                 <property name="visible">True</property>
                                                 <property name="border_width">3</property>
-                                                <property name="orientation">vertical</property>
                                                 <child>
                                                   <object class="GtkRadioButton" id="cellSpeechButton">
                                                     <property name="label" translatable="yes" comments="Translators: This is one of two options available in the Preferences dialog for the Table Rows setting. If chosen, Orca will speak just the new cell when the user arrows Up or Down in a table.">Speak _cell</property>
@@ -1142,7 +1290,6 @@
                                                 <child>
                                                   <object class="GtkVBox" id="progressBarVBox">
                                                     <property name="visible">True</property>
-                                                    <property name="orientation">vertical</property>
                                                     <child>
                                                       <object class="GtkHBox" id="speakUpdateIntervalHBox">
                                                         <property name="visible">True</property>
@@ -1492,7 +1639,6 @@
                   <object class="GtkVBox" id="brailleVbox">
                     <property name="visible">True</property>
                     <property name="border_width">12</property>
-                    <property name="orientation">vertical</property>
                     <property name="spacing">12</property>
                     <child>
                       <object class="GtkTable" id="table2">
@@ -1503,7 +1649,6 @@
                         <child>
                           <object class="GtkVBox" id="vbox23">
                             <property name="visible">True</property>
-                            <property name="orientation">vertical</property>
                             <child>
                               <object class="GtkCheckButton" id="enableBrailleCheckButton">
                                 <property name="label" translatable="yes">Enable Braille _support</property>
@@ -1647,7 +1792,6 @@
                                   <object class="GtkVBox" id="vbox18">
                                     <property name="visible">True</property>
                                     <property name="border_width">3</property>
-                                    <property name="orientation">vertical</property>
                                     <child>
                                       <object class="GtkRadioButton" id="brailleBriefButton">
                                         <property name="label" translatable="yes">Brie_f</property>
@@ -1712,7 +1856,6 @@
                                   <object class="GtkVBox" id="vbox28">
                                     <property name="visible">True</property>
                                     <property name="border_width">3</property>
-                                    <property name="orientation">vertical</property>
                                     <child>
                                       <object class="GtkRadioButton" id="brailleSelectionNoneButton">
                                         <property name="label" translatable="yes">_None</property>
@@ -1810,7 +1953,6 @@
                                 <child>
                                   <object class="GtkVBox" id="vbox35">
                                     <property name="visible">True</property>
-                                    <property name="orientation">vertical</property>
                                     <child>
                                       <object class="GtkRadioButton" id="brailleLinkNoneButton">
                                         <property name="label" translatable="yes">_None</property>
@@ -1925,7 +2067,6 @@
                   <object class="GtkVBox" id="keyechoVbox">
                     <property name="visible">True</property>
                     <property name="border_width">12</property>
-                    <property name="orientation">vertical</property>
                     <child>
                       <object class="GtkCheckButton" id="keyEchoCheckButton">
                         <property name="label" translatable="yes">Enable _key echo</property>
@@ -2175,7 +2316,6 @@
                   <object class="GtkVBox" id="vbox19">
                     <property name="visible">True</property>
                     <property name="border_width">12</property>
-                    <property name="orientation">vertical</property>
                     <child>
                       <object class="GtkCheckButton" id="magnifierSupportCheckButton">
                         <property name="label" translatable="yes">Enable _magnifier</property>
@@ -2599,7 +2739,6 @@
                                     <child>
                                       <object class="GtkVBox" id="vbox33">
                                         <property name="visible">True</property>
-                                        <property name="orientation">vertical</property>
                                         <child>
                                           <object class="GtkAlignment" id="alignment83">
                                             <property name="visible">True</property>
@@ -2805,7 +2944,6 @@
                                     <child>
                                       <object class="GtkVBox" id="vbox32">
                                         <property name="visible">True</property>
-                                        <property name="orientation">vertical</property>
                                         <child>
                                           <object class="GtkAlignment" id="alignment81">
                                             <property name="visible">True</property>
@@ -3156,7 +3294,6 @@
                                     <child>
                                       <object class="GtkVBox" id="vbox31">
                                         <property name="visible">True</property>
-                                        <property name="orientation">vertical</property>
                                         <child>
                                           <object class="GtkAlignment" id="alignment78">
                                             <property name="visible">True</property>
@@ -3621,7 +3758,6 @@
                   <object class="GtkVBox" id="keyBindingsVBox">
                     <property name="visible">True</property>
                     <property name="border_width">12</property>
-                    <property name="orientation">vertical</property>
                     <property name="spacing">6</property>
                     <child>
                       <object class="GtkHBox" id="hbox36">
@@ -3651,7 +3787,7 @@
                             <child>
                               <object class="GtkCellRendererText" id="orcaModifierRenderer"/>
                               <attributes>
-                              <attribute name="text">0</attribute>
+                                <attribute name="text">0</attribute>
                               </attributes>
                             </child>
                           </object>
@@ -3706,7 +3842,6 @@
                 <child>
                   <object class="GtkVBox" id="vbox29">
                     <property name="visible">True</property>
-                    <property name="orientation">vertical</property>
                     <child>
                       <object class="GtkFrame" id="pronunciationFrame">
                         <property name="visible">True</property>
@@ -3820,7 +3955,6 @@
                             <child>
                               <object class="GtkVBox" id="vbox24">
                                 <property name="visible">True</property>
-                                <property name="orientation">vertical</property>
                                 <child>
                                   <object class="GtkScrolledWindow" id="scrolledwindow2">
                                     <property name="visible">True</property>
@@ -3914,7 +4048,6 @@
                     <child>
                       <object class="GtkVBox" id="vbox26">
                         <property name="visible">True</property>
-                        <property name="orientation">vertical</property>
                         <property name="homogeneous">True</property>
                         <child>
                           <object class="GtkFrame" id="adjustAttributesFrame">
@@ -3930,7 +4063,6 @@
                                   <object class="GtkVBox" id="vbox25">
                                     <property name="visible">True</property>
                                     <property name="border_width">5</property>
-                                    <property name="orientation">vertical</property>
                                     <child>
                                       <object class="GtkButton" id="textMoveToTopButton">
                                         <property name="label" translatable="yes" comments="Translators:  This label is on a button on the Text Attributes pane of the Orca Preferences dialog. On that pane there is a long list of possible text attributes. The user can select one and then, by using the Move to _top button, move that attribute to the top of the list. The ordering in the list is important as Orca will speak the selected text attributes in the given order.">Move to _top</property>
@@ -4028,7 +4160,6 @@ attributes&lt;/b&gt;</property>
                                   <object class="GtkVBox" id="vbox27">
                                     <property name="visible">True</property>
                                     <property name="border_width">3</property>
-                                    <property name="orientation">vertical</property>
                                     <child>
                                       <object class="GtkRadioButton" id="textBrailleNoneButton">
                                         <property name="label" translatable="yes">_None</property>
diff --git a/src/orca/orca.py b/src/orca/orca.py
index 6e3b553..ac8a6ef 100644
--- a/src/orca/orca.py
+++ b/src/orca/orca.py
@@ -27,20 +27,24 @@ __copyright__ = "Copyright (c) 2004-2009 Sun Microsystems Inc." \
                 "Copyright (c) 2010 Joanmarie Diggs, Mesar Hameed."
 __license__   = "LGPL"
 
+import getopt
+import os
+import signal
+import sys
+import time
+import unicodedata
+import shutil
+
 # We're going to force the name of the app to "orca" so pygtk
 # will end up showing us as "orca" to the AT-SPI.  If we don't
 # do this, the name can end up being "-c".  See bug 364452 at
 # http://bugzilla.gnome.org/show_bug.cgi?id=364452 for more
 # information.
 #
-import sys
 sys.argv[0] = "orca"
-
-# Tell Orca to find/use the right version of pygtk.
-#
+import pyatspi
 import pygtk
 pygtk.require('2.0')
-
 try:
     # This can fail due to gtk not being available.  We want to
     # be able to recover from that if possible.  The main driver
@@ -51,20 +55,469 @@ try:
 except:
     pass
 
+# Importing anything that requires a functioning settings manager
+# instance should NOT be done here.
+#
+import debug
+import orca_platform
+import settings
+from orca_i18n import _
+from orca_i18n import ngettext
+
+class Options:
+    """Class to handle getting run-time options."""
+
+    def __init__(self):
+        """Initialize the Options class."""
+
+        self._arglist = sys.argv[1:]
+        if len(self._arglist) == 1:
+            self._arglist = self._arglist[0].split()
+
+        self.desktopRunning = False
+        try:
+            if gtk.gdk.display_get_default():
+                self.desktopRunning = True
+        except:
+            pass
+
+        self.canEnable = {'speech':'enableSpeech',
+                          'braille':'enableBraille',
+                          'braille-monitor':'enableBrailleMonitor',
+                          'magnifier':'enableMagnifier',
+                          'main-window':'showMainWindow',
+                          'splash-window':'showSplashWindow'}
+
+        self.invalidOptions = []
+        self.settings = {}
+        self.profiles = []
+        self.disable = []
+        self.enable = []
+        self.cannotEnable = []
+        self._validFeaturesPrinted = False
+        self.setupRequested = False
+        self.bypassSetup = False
+        self.showGUI = False
+        self.debug = False
+        self.userPrefsDir = None
+        self.debugFile = time.strftime('debug-%Y-%m-%d-%H:%M:%S.out')
+
+        self.validOptions, self.validArguments = self.validate()
+        self._getPrefsDir()
+        self._getProfiles()
+        self._getSetup()
+        self._getDebug()
+        self._getHelp()
+
+    def validate(self):
+        """Parses the list of options in arglist and removes those which are
+        not valid so that typos do not prevent the user from starting Orca."""
+
+        opts = []
+        args = []
+
+        # ? is for help
+        # e is for enabling a feature
+        # d is for disabling a feature
+        # h is for help
+        # u is for alternate user preferences location
+        # s is for setup
+        # n is for no setup
+        # t is for text setup
+        # v is for version
+        # i is for importing a user profile
+        #
+        shortopts = "?stnvlmd:e:u:i:"
+        longopts = ["help",
+                    "user-prefs-dir=",
+                    "enable=",
+                    "disable=",
+                    "setup",
+                    "gui-setup",
+                    "text-setup",
+                    "no-setup",
+                    "list-apps",
+                    "debug",
+                    "debug-file=",
+                    "version",
+                    "replace",
+                    "import-file="]
+
+        try:
+            opts, args = getopt.getopt(self._arglist, shortopts, longopts)
+        except getopt.GetoptError as ex:
+            bogusOption = "-%s" % ex.opt
+            if len(bogusOption) >= 2:
+                bogusOption = "-%s" % bogusOption
+            self.invalidOptions.append(bogusOption)
+            try:
+                self._arglist.remove(bogusOption)
+            except:
+                pass
+            else:
+                return self.validate()
+        except:
+            pass
+
+        return opts, args
+
+    def _get(self, optionsList):
+        """Gets a subset of all of the valid options from the commandline.
+
+        Arguments:
+        - optionsList: a list of all of the options of interest.
+
+        Returns a list of the matches.
+        """
+
+        return filter(lambda x: x[0] in optionsList, self.validOptions)
+
+    def _getValues(self, optionsList, additionalFilter=None):
+        """Gets the values for a subset of all of the valid options from
+        the commandLine.
+
+        Arguments:
+        - optionsList: a list of all of the options of interest.
+        - additionalFilter: an optional function which can be used to
+          remove items which would otherwise be included.
+
+        Returns a tuple containing two lists: the matches and the items
+        which were filtered out.
+        """
+
+        opts = [x[1].strip() for x in self._get(optionsList)]
+        rv = opts
+        removed = []
+        if additionalFilter:
+            rv = filter(additionalFilter, opts)
+            removed = filter(lambda x: x not in rv, opts)
+
+        return rv, removed
+
+    def _getEnableAndDisable(self):
+        """Gets the options which are to be enabled and disabled and stores
+        them in self.enable and self.disable, along with adding invalid items
+        to the list in self.cannotEnable."""
+
+        isValid = lambda x: self.canEnable.get(x) != None
+        self.enable, invalid = self._getValues(["-e", "--enable"], isValid)
+        self.cannotEnable.extend(invalid)
+        self.disable, invalid = self._getValues(["-d", "--disable"], isValid)
+        self.cannotEnable.extend(invalid)
+
+    def _getPrefsDir(self):
+        """Returns the preferences directory specified by the user."""
+
+        userPrefsDir = None
+        dirs, removed = self._getValues(["-u", "--user-prefs-dir"])
+        if len(dirs):
+            userPrefsDir = dirs[0]
+            try:
+                os.chdir(userPrefsDir)
+            except:
+                debug.printException(debug.LEVEL_FINEST)
+
+        self.userPrefsDir = userPrefsDir
+
+    def _getSetup(self):
+        """Gets the options associated with setting up Orca and stores them
+        in self.setupRequested, self.showGUI, and self.bypassSetup."""
+
+        gui = self._get(["-s", "--gui-setup", "--setup"])
+        text = self._get(["-t", "--text-setup"])
+        bypass = self._get(["-n", "--no-setup"])
+
+        if gui or text:
+            self.setupRequested = True
+            self.showGUI = self.desktopRunning and not text
+
+        if bypass:
+            self.bypassSetup = True
+
+    def _getDebug(self):
+        """Gets the options associated with debugging Orca and stores them
+        in self.debug and self.debugFile."""
+
+        noFile = self._get(["--debug"])
+        debugFile = ["--debug-file"]
+        withFile = self._get(debugFile)
+        files, invalid = self._getValues(debugFile)
+
+        if noFile or withFile:
+            self.debug = True
+            if files:
+                self.debugFile = files[0]
+
+    def _getHelp(self):
+        """Gets the options associated with Orca help. If there are any,
+        the corresponding help information will be printed and this instance
+        of Orca exited."""
+
+        isHelp = self._get(["-?", "--help"])
+        isVersion = self._get(["-v", "--version"])
+        isListApps = self._get(["-l", "--list-apps"])
+
+        message = None
+        if isHelp:
+            message = self.usageString()
+        elif isVersion:
+            message = ("Orca %s" % orca_platform.version)
+        elif isListApps:
+            apps = filter(lambda x: x != None, pyatspi.Registry.getDesktop(0))
+            names = [app.name for app in apps]
+            message = "\n".join(names)
+
+        if message:
+            self._printMessageAndExit(message)
+
+    def _getProfiles(self):
+        """Gets the options associated with the profiles which should be
+        loaded and stores them in self.profiles."""
+
+        self.profiles, invalid = self._getValues(["-i", "--import-file"])
+
+    def presentInvalidOptions(self):
+        """Presents any invalid options to the user. Returns True if there
+        were invalid options to present and a message printed; otherwise
+        returns False."""
+
+        if self.invalidOptions:
+            # Translators: This message is displayed when the user tries
+            # to start Orca and includes an invalid option as an argument.
+            # After the message, the list of arguments, as typed by the
+            # user, is displayed.
+            #
+            msg = _("The following arguments are not valid: ")
+            print (msg + " ".join(self.invalidOptions))
+            return True
+
+        return False
+
+    def _printMessageAndExit(self, msg):
+        """Prints the specified message string and then exits."""
+
+        # The use of os._exit() to immediately kill a child process
+        # after a fork() is documented at docs.python.org.
+        #
+        # pylint: disable-msg=W0212
+        #
+        pid = os.fork()
+        if pid:
+            os.waitpid(pid, 0)
+            os._exit(0)
+        else:
+            print msg
+            os._exit(0)
+
+    def convertToSettings(self):
+        """Converts known items (currently just those which can be enabled
+        or disabled), stores them in the self.settings dictionary and then
+        returns that dictionary."""
+
+        self._getEnableAndDisable()
+        toEnable = map(self.canEnable.get, self.enable)
+        for item in toEnable:
+            self.settings[item] = True
+
+        toDisable = map(self.canEnable.get, self.disable)
+        for item in toDisable:
+            self.settings[item] = False
+
+        self.presentCannotEnable()
+
+        return self.settings
+
+    def presentCannotEnable(self):
+        """Presents any non-enable-able items which the user asked us to
+        enable/disable. Returns True if there were invalid items; otherwise
+        returns False."""
+
+        if self.cannotEnable:
+            valid = "\nspeech, braille, braille-monitor, magnifier, " \
+                    "main-window, splash-window"
+            # Translators: This message is displayed when the user
+            # tries to enable or disable a feature via an argument,
+            # but specified an invalid feature. Valid features are:
+            # speech, braille, braille-monitor, magnifier, main-window,
+            # and splash-window. These items are not localized and are
+            # presented in a list after this message.
+            #
+            msg = _("The following items can be enabled or disabled:")
+            if not self._validFeaturesPrinted:
+                print (msg + valid)
+                self._validFeaturesPrinted = True
+            return True
+
+        return False
+
+    def usage(self):
+        """Prints out usage information."""
+        print(self.usageString())
+
+    def usageString(self):
+        """Generates the usage information string."""
+        info = []
+        info.append(_("Usage: orca [OPTION...]"))
+
+        # Translators: this is the description of the command line option
+        # '-?, --help' that is used to display usage information.
+        #
+        info.append("-?, --help                   " + \
+                  _("Show this help message"))
+        info.append("-v, --version                %s" % orca_platform.version)
+
+        # Translators: this is a testing option for the command line.  It prints
+        # the names of applications known to the accessibility infrastructure
+        # to stdout and then exits.
+        #
+        info.append("-l, --list-apps              " + \
+                  _("Print the known running applications"))
+
+        # Translators: this enables debug output for Orca.  The
+        # YYYY-MM-DD-HH:MM:SS portion is a shorthand way of saying that
+        # the file name will be formed from the current date and time with
+        # 'debug' in front and '.out' at the end.  The 'debug' and '.out'
+        # portions of this string should not be translated (i.e., it will
+        # always start with 'debug' and end with '.out', regardless of the
+        # locale.).
+        #
+        info.append("--debug                      " + \
+                  _("Send debug output to debug-YYYY-MM-DD-HH:MM:SS.out"))
+
+        # Translators: this enables debug output for Orca and overrides
+        # the name of the debug file Orca will use for debug output if the
+        # --debug option is used.
+        #
+        info.append("--debug-file=filename        " + \
+                  _("Send debug output to the specified file"))
+
+        # Translators: this is the description of the command line option
+        # '-s, --setup, --gui-setup' that will initially display a GUI dialog
+        # that would allow the user to set their Orca preferences.
+        #
+        info.append("-s, --setup, --gui-setup     " + \
+                  _("Set up user preferences"))
+
+        # Translators: this is the description of the command line option
+        # '-t, --text-setup' that will initially display a list of questions
+        # in text form, that the user will need to answer, before Orca will
+        # startup. For this to happen properly, Orca will need to be run
+        # from a terminal window.
+        #
+        info.append("-t, --text-setup             " + \
+                  _("Set up user preferences (text version)"))
+
+        # Translators: this is the description of the command line option
+        # '-n, --no-setup' that means that Orca will startup without setting
+        # up any user preferences.
+        #
+        info.append("-n, --no-setup               " +  \
+                  _("Skip set up of user preferences"))
+
+        # Translators: this is the description of the command line option
+        # '-u, --user-prefs-dir=dirname' that allows you to specify an alternate
+        # location for the user preferences.
+        #
+        info.append("-u, --user-prefs-dir=dirname " + \
+                  _("Use alternate directory for user preferences"))
+
+        info.append("-e, --enable=[" \
+                        + "speech" + "|" \
+                        + "braille" + "|" \
+                        + "braille-monitor" + "|" \
+                        + "magnifier" + "|" \
+                        + "main-window" + "|" \
+                        + "splash-window" + "] ")
+
+        # Translators: if the user supplies an option via the '-e, --enable'
+        # command line option, it will be automatically enabled as Orca is
+        # started.
+        #
+        info[-1] += _("Force use of option")
+
+        info.append("-d, --disable=[" \
+                        + "speech" + "|" \
+                        + "braille" + "|" \
+                        + "braille-monitor" + "|" \
+                        + "magnifier" + "|" \
+                        + "main-window" + "|" \
+                        + "splash-window" + "] ")
+
+        # Translators: if the user supplies an option via the '-d, --disable'
+        # command line option, it will be automatically disabled as Orca is
+        # started.
+        #
+        info[-1] += _("Prevent use of option")
+
+        # Translators: this is the Orca command line option to import to Orca
+        # a user profile from a given file
+        #
+        info.append("-i, --import-file=filename   " + \
+                  _("Import a profile from a given orca profile file"))
+
+        # Translators: this is the Orca command line option that will quit Orca.
+        # The user would run the Orca shell script again from a terminal window.
+        # If this command line option is specified, the script will quit any
+        # instances of Orca that are already running.
+        #
+        info.append("-q, --quit                   " + \
+                  _("Quits Orca (if shell script used)"))
+
+        # Translators: this is the Orca command line option that will force
+        # the termination of Orca.
+        # The user would run the Orca shell script again from a terminal window.
+        # If this command line option is specified, the script will quit any
+        # instances of Orca that are already running.
+        #
+        info.append("-f, --forcequit              " + \
+                  _("Forces orca to be terminated immediately."))
+
+        # Translators: this is the Orca command line option to tell Orca to
+        # replace any existing Orca process(es) that might be running.
+        #
+        info.append("--replace                    " + \
+                  _("Replace a currently running Orca"))
+
+        # Translators: this is text being sent to a terminal and we want to
+        # keep the text lines within terminal boundaries.
+        #
+        info.append("\n" + \
+              _("If Orca has not been previously set up by the user, Orca\n" \
+                "will automatically launch the preferences set up unless\n" \
+                 "the -n or --no-setup option is used."))
+
+        # Translators: this is more text being sent to a terminal and we want to
+        # keep the text lines within terminal boundaries.
+        #
+        info.append("\n" + \
+              ("WARNING: suspending Orca, e.g. by pressing Control-Z, from\n" \
+               "an AT-SPI enabled shell (such as gnome-terminal), can also\n" \
+               "suspend the desktop until Orca is killed."))
+
+        info.append("\n" + _("Report bugs to orca-list gnome org "))
+
+        return ("\n".join(info))
+
+options = Options()
+if options.userPrefsDir:
+    settings.userPrefsDir = options.userPrefsDir
+
+# This needs to occur prior to our importing anything which might in turn
+# import anything which might expect to be able to use the Settings Manager
+# You have been warned.
+#
+from settings_manager import SettingsManager
+_settingsManager = SettingsManager()
+if _settingsManager is None:
+    print "Could not load the settings manager. Exiting."
+    sys.exit(1)
+
 try:
     # If we don't have an active desktop, we will get a RuntimeError.
     import mouse_review
 except RuntimeError:
     pass
 
-import getopt
-import os
-import signal
-import time
-import unicodedata
-import shutil
-
-import settings
 if settings.useDBus:
     import dbus.mainloop.glib
     dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
@@ -76,14 +529,11 @@ if settings.useDBus:
 else:
     import mag
 
-import pyatspi
 import braille
-import debug
 import httpserver
 import keynames
 import keybindings
 import orca_state
-import orca_platform
 import speech
 import notification_messages
 
@@ -92,9 +542,6 @@ from input_event import KeyboardEvent
 from input_event import MouseButtonEvent
 from input_event import keyEventToString
 
-from orca_i18n import _           # for gettext support
-from orca_i18n import ngettext
-
 if settings.debugMemoryUsage:
     import gc
     gc.set_debug(gc.DEBUG_UNCOLLECTABLE
@@ -114,15 +561,6 @@ _userSettings = None
 #
 _commandLineSettings = {}
 
-# True if --debug is used on the command line.
-#
-_debugSwitch = False
-
-# Filename of the debug file to use if --debug or --debug-file is
-# used on the command line.
-#
-_debugFile = None
-
 # A subset of the original Xmodmap info prior to our stomping on it.
 # Right now, this is just for the user's chosen Orca modifier(s).
 #
@@ -311,7 +749,7 @@ def _onChildrenChanged(e):
         #
         try:
             if desktop.childCount == 0:
-                if not settings.onlySpeakDisplayedText:
+                if not _settingsManager.getSetting('onlySpeakDisplayedText'):
                     speech.speak(_("Goodbye."))
                 shutdown()
                 return
@@ -926,7 +1364,8 @@ def _processKeyboardEvent(event):
             if settings.listShortcutsModeEnabled:
                 consumed = listShortcuts(keyboardEvent)
             elif notification_messages.listNotificationMessagesModeEnabled:
-                consumed = notification_messages.listNotificationMessages(keyboardEvent)
+                consumed = notification_messages.listNotificationMessages(
+                    keyboardEvent)
             if (not consumed):
                 consumed = _keyBindings.consumeKeyboardEvent( \
                   None, keyboardEvent)
@@ -1127,20 +1566,22 @@ def loadUserSettings(script=None, inputEvent=None):
 
     reloaded = False
     if _userSettings:
+        _profile = _settingsManager.getSetting('activeProfile')[1]
         try:
-            reload(_userSettings)
+            _userSettings = _settingsManager.getGeneralSettings(_profile)
             reloaded = True
         except ImportError:
             debug.printException(debug.LEVEL_FINEST)
         except:
             debug.printException(debug.LEVEL_SEVERE)
     else:
+        _profile = _settingsManager.profile
         try:
-            _userSettings = __import__("user-settings")
-            if _debugSwitch:
+            _userSettings = _settingsManager.getGeneralSettings(_profile)
+            if options.debug:
                 debug.debugLevel = debug.LEVEL_ALL
                 debug.eventDebugLevel = debug.LEVEL_OFF
-                debug.debugFile = open(_debugFile, 'w', 0)
+                debug.debugFile = open(options.debugFile, 'w', 0)
         except ImportError:
             debug.printException(debug.LEVEL_FINEST)
         except:
@@ -1799,221 +2240,6 @@ def abortOnSignal(signum, frame):
                   % signum)
     die(signum)
 
-def usage():
-    """Prints out usage information."""
-    print(usageString())
-
-def usageString():
-    """Generates the usage information string."""
-    info = []
-    info.append(_("Usage: orca [OPTION...]"))
-
-    # Translators: this is the description of the command line option
-    # '-?, --help' that is used to display usage information.
-    #
-    info.append("-?, --help                   " + _("Show this help message"))
-    info.append("-v, --version                %s" % orca_platform.version)
-
-    # Translators: this is a testing option for the command line.  It prints
-    # the names of the applications known to the accessibility infrastructure
-    # to stdout and then exits.
-    #
-    info.append("-l, --list-apps              " + \
-                _("Print the known running applications"))
-
-    # Translators: this enables debug output for Orca.  The
-    # YYYY-MM-DD-HH:MM:SS portion is a shorthand way of saying that
-    # the file name will be formed from the current date and time with
-    # 'debug' in front and '.out' at the end.  The 'debug' and '.out'
-    # portions of this string should not be translated (i.e., it will
-    # always start with 'debug' and end with '.out', regardless of the
-    # locale.).
-    #
-    info.append("--debug                      " + \
-                _("Send debug output to debug-YYYY-MM-DD-HH:MM:SS.out"))
-
-    # Translators: this enables debug output for Orca and overrides
-    # the name of the debug file Orca will use for debug output if the
-    # --debug option is used.
-    #
-    info.append("--debug-file=filename        " + \
-                _("Send debug output to the specified file"))
-
-    # Translators: this is the description of the command line option
-    # '-s, --setup, --gui-setup' that will initially display a GUI dialog
-    # that would allow the user to set their Orca preferences.
-    #
-    info.append("-s, --setup, --gui-setup     " + _("Set up user preferences"))
-
-    # Translators: this is the description of the command line option
-    # '-t, --text-setup' that will initially display a list of questions
-    # in text form, that the user will need to answer, before Orca will
-    # startup. For this to happen properly, Orca will need to be run
-    # from a terminal window.
-    #
-    info.append("-t, --text-setup             " + \
-                _("Set up user preferences (text version)"))
-
-    # Translators: this is the description of the command line option
-    # '-n, --no-setup' that means that Orca will startup without setting
-    # up any user preferences.
-    #
-    info.append("-n, --no-setup               " +  \
-                _("Skip set up of user preferences"))
-
-    # Translators: this is the description of the command line option
-    # '-u, --user-prefs-dir=dirname' that allows you to specify an alternate
-    # location for the user preferences.
-    #
-    info.append("-u, --user-prefs-dir=dirname " + \
-                _("Use alternate directory for user preferences"))
-
-    info.append("-e, --enable=[" \
-        + "speech" + "|" \
-        + "braille" + "|" \
-        + "braille-monitor" + "|" \
-        + "magnifier" + "|" \
-        + "main-window" + "|" \
-        + "splash-window" + "] ")
-
-    # Translators: if the user supplies an option via the '-e, --enable'
-    # command line option, it will be automatically enabled as Orca is
-    # started.
-    #
-    info[-1] += _("Force use of option")
-
-    info.append("-d, --disable=[" \
-        + "speech" + "|" \
-        + "braille" + "|" \
-        + "braille-monitor" + "|" \
-        + "magnifier" + "|" \
-        + "main-window" + "|" \
-        + "splash-window" + "] ")
-
-    # Translators: if the user supplies an option via the '-d, --disable'
-    # command line option, it will be automatically disabled as Orca is
-    # started.
-    #
-    info[-1] += _("Prevent use of option")
-
-    # Translators: this is the Orca command line option that will quit Orca.
-    # The user would run the Orca shell script again from a terminal window.
-    # If this command line option is specified, the script will quit any
-    # instances of Orca that are already running.
-    #
-    info.append("-q, --quit                   " + \
-                _("Quits Orca (if shell script used)"))
-
-    # Translators: this is the Orca command line option that will force 
-    # the termination of Orca.
-    # The user would run the Orca shell script again from a terminal window.
-    # If this command line option is specified, the script will quit any
-    # instances of Orca that are already running.
-    #
-    info.append("-f, --forcequit              " + \
-                _("Forces orca to be terminated immediately."))
-
-    # Translators: this is the Orca command line option to tell Orca to
-    # replace any existing Orca process(es) that might be running.
-    #
-    info.append("--replace                    " +\
-                _("Replace a currently running Orca"))
-
-    # Translators: this is text being sent to a terminal and we want to
-    # keep the text lines within terminal boundaries.
-    #
-    info.append("\n" + \
-                _("If Orca has not been previously set up by the user, Orca\n" \
-                  "will automatically launch the preferences set up unless\n" \
-                  "the -n or --no-setup option is used."))
-
-    # Translators: this is more text being sent to a terminal and we want to
-    # keep the text lines within terminal boundaries.
-    #
-    info.append("\n" + \
-        _("WARNING: suspending Orca, e.g. by pressing Control-Z, from\n" \
-          "an AT-SPI enabled shell (such as gnome-terminal), can also\n" \
-          "suspend the desktop until Orca is killed."))
-
-    info.append("\n" + _("Report bugs to orca-list gnome org "))
-
-    return ("\n".join(info))
-
-def printMessageAndExit(msg):
-    # The use of os._exit() to immediately kill a child process
-    # after a fork() is documented at docs.python.org.
-    #
-    # pylint: disable-msg=W0212
-    #
-    pid = os.fork()
-    if pid:
-        os.waitpid(pid, 0)
-        os._exit(0)
-    else:
-        print msg
-        os._exit(0)
-
-def validateOptions(arglist, invalid=[]):
-    """Parses the list of options in arglist and removes those
-    which are not valid so that typos do not prevent the user
-    from starting Orca.
-
-    Arguments:
-    - arglist: The list of options and arguments provided by
-      the user.
-    - invalid: Options which have already been identified as
-      being invalid.
-
-    Returns: A list containing validated options, valided
-    arguments, and any items which were deemed invalid.
-    """
-
-    opts = []
-    args = []
-
-    # ? is for help
-    # e is for enabling a feature
-    # d is for disabling a feature
-    # h is for help
-    # u is for alternate user preferences location
-    # s is for setup
-    # n is for no setup
-    # t is for text setup
-    # v is for version
-    #
-    shortopts = "?stnvlmd:e:u:"
-    longopts = ["help",
-                "user-prefs-dir=",
-                "enable=",
-                "disable=",
-                "setup",
-                "gui-setup",
-                "text-setup",
-                "no-setup",
-                "list-apps",
-                "debug",
-                "debug-file=",
-                "version",
-                "replace"]
-
-    try:
-        opts, args = getopt.getopt(arglist, shortopts, longopts)
-    except getopt.GetoptError as ex:
-        bogusOption = "-%s" % ex.opt
-        if len(bogusOption) >= 2:
-            bogusOption = "-%s" % bogusOption
-        invalid.append(bogusOption)
-        try:
-            arglist.remove(bogusOption)
-        except:
-            pass
-        else:
-            return validateOptions(arglist, invalid)
-    except:
-        pass
-
-    return opts, args, invalid
-
 def multipleOrcas():
     """Returns True if multiple instances of Orca are running
     which are owned by the same user."""
@@ -2034,9 +2260,6 @@ def main():
     an exit code of 0 means normal completion and an exit code of 50
     means Orca exited because of a hang."""
 
-    global _debugSwitch
-    global _debugFile
-
     # Method to call when we think something might be hung.
     #
     settings.timeoutCallback = timeout
@@ -2049,144 +2272,67 @@ def main():
     signal.signal(signal.SIGQUIT, shutdownOnSignal)
     signal.signal(signal.SIGSEGV, abortOnSignal)
 
-    # See if the desktop is running.  If it is, the import of gtk will
-    # succeed.  If it isn't, the import will fail.
-    #
-    desktopRunning = False
-    try:
-        if gtk.gdk.display_get_default():
-            desktopRunning = True
-    except:
-        pass
+    if options.presentInvalidOptions() and multipleOrcas():
+        die(0)
 
-    # Parse the command line options.
-    #
-    # Run the preferences setup if the user has specified
-    # "--setup" or "--text-setup" on the command line.  If the
-    # desktop is not running, we will fallback to the console-based
-    # method as appropriate.
-    #
-    bypassSetup     = False
-    setupRequested  = False
-    showGUI         = False
-
-    # We hack a little here because the shell script to start orca can
-    # conflate all of command line arguments into one string, which is
-    # not what we want.  We detect this by seeing if the length of the
-    # argument list is 1.
-    #
-    arglist = sys.argv[1:]
-    if len(arglist) == 1:
-        arglist = arglist[0].split()
-
-    validOpts, validArgs, invalidOpts = validateOptions(arglist)
-    validFeaturesListed = False
-    if invalidOpts:
-        # Translators: This message is displayed when the user tries
-        # to start Orca and includes an invalid option as an argument.
-        # After the message, the list of arguments, as typed by the
-        # user, is displayed.
+    _commandLineSettings.update(options.convertToSettings())
+    for profile in options.profiles:
+        # Translators: This message is what is presented to the user
+        # when he/she attempts to import a settings profile, but the
+        # import failed for some reason.
         #
-        msg = _("The following arguments are not valid: ")
-        print (msg + " ".join(invalidOpts))
+        msg = _("Unable to import profile.")
+        try:
+            if _settingsManager.importProfile(profile):
+                # Translators: This message is what is presented to the user
+                # when he/she successfully imports a settings profile.
+                #
+                msg = _("Profile import success.")
+        except KeyError as ex:
+            # Translators: This message is what is presented to the user
+            # when he/she attempts to import a settings profile but the
+            # import failed due to a bad key.
+            #
+            msg = _("Import failed due to an unrecognized key: %s") % ex
+        except IOError as ex:
+            msg = "%s: %s" % (ex.strerror, ex.filename)
+        except:
+            continue
+
+        print msg
         if multipleOrcas():
             die(0)
 
-    try:
-        for opt, val in validOpts:
-            if opt in ("-u", "--user-prefs-dir"):
-                userPrefsDir = val.strip()
-                try:
-                    os.chdir(userPrefsDir)
-                    settings.userPrefsDir = userPrefsDir
-                except:
-                    debug.printException(debug.LEVEL_FINEST)
-
-            if opt in ("-e", "--enable", "-d", "--disable"):
-                feature = val.strip()
-                enable = opt in ("-e", "--enable")
-                if feature == "speech":
-                    _commandLineSettings["enableSpeech"] = enable
-                elif feature == "braille":
-                    _commandLineSettings["enableBraille"] = enable
-                elif feature == "braille-monitor":
-                    _commandLineSettings["enableBrailleMonitor"] = enable
-                elif feature == "magnifier":
-                    _commandLineSettings["enableMagnifier"] = enable
-                elif feature == "main-window":
-                    _commandLineSettings["showMainWindow"] = enable
-                elif feature == "splash-window":
-                    _commandLineSettings["showSplashWindow"] = enable
-                else:
-                    valid = "\nspeech, braille, braille-monitor, magnifier, " \
-                            "main-window, splash-window"
-                    # Translators: This message is displayed when the user
-                    # tries to enable or disable a feature via an argument,
-                    # but specified an invalid feature. Valid features are:
-                    # speech, braille, braille-monitor, magnifier, main-window,
-                    # and splash-window. These items are not localized and are
-                    # presented in a list after this message.
-                    #
-                    msg = _("The following items can be enabled or disabled:")
-                    if not validFeaturesListed:
-                        print (msg + valid)
-                        validFeaturesListed = True
-
-            if opt in ("-s", "--gui-setup", "--setup"):
-                setupRequested = True
-                showGUI = desktopRunning
-            if opt in ("-t", "--text-setup"):
-                setupRequested = True
-                showGUI = False
-            if opt in ("-n", "--no-setup"):
-                bypassSetup = True
-            if opt in ("-?", "--help"):
-                printMessageAndExit(usageString())
-            if opt in ("-v", "--version"):
-                printMessageAndExit("Orca %s" % orca_platform.version)
-            if opt == "--debug":
-                _debugSwitch = True
-                if not _debugFile:
-                    _debugFile = time.strftime('debug-%Y-%m-%d-%H:%M:%S.out')
-            if opt == "--debug-file":
-                _debugSwitch = True
-                _debugFile = val.strip()
-            if opt in ("-l", "--list-apps"):
-                apps = filter(lambda x: x is not None,
-                              pyatspi.Registry.getDesktop(0))
-                names = [app.name for app in apps]
-                printMessageAndExit("\n".join(names))
-    except:
-        debug.printException(debug.LEVEL_OFF)
-        usage()
-        die(2)
-
     # Check if old config location exists, try to copy all 
     # the data from old location to the new location.
     #
-    from xdg.BaseDirectory import xdg_data_home
-    userPrefsDir = os.path.join(xdg_data_home, "orca")
+    if not options.userPrefsDir:
+        from xdg.BaseDirectory import xdg_data_home
+        options.userPrefsDir = os.path.join(xdg_data_home, "orca")
     oldUserPrefsDir = os.path.join(os.environ["HOME"], ".orca")
 
-    if not os.path.exists(userPrefsDir):
-        os.makedirs(userPrefsDir)
+    if not os.path.exists(options.userPrefsDir):
+        os.makedirs(options.userPrefsDir)
 
     for baseDirName, dirNames, fileNames in os.walk(oldUserPrefsDir):
 
         for dirName in dirNames:
             relPath = os.path.relpath(baseDirName, oldUserPrefsDir)
-            dstDir = os.path.join(os.path.join(userPrefsDir, relPath), dirName)
+            dstDir = os.path.join(os.path.join(
+                    options.userPrefsDir, relPath), dirName)
             if not os.path.exists(dstDir):
                 os.mkdir(dstDir)
 
         for fileName in fileNames:
             srcFile = os.path.join(baseDirName, fileName)
             relPath = os.path.relpath(baseDirName, oldUserPrefsDir)
-            dstFile = os.path.join(os.path.join(userPrefsDir, relPath), fileName)
+            dstFile = os.path.join(os.path.join(
+                    options.userPrefsDir, relPath),
+                                   fileName)
             if not os.path.exists(dstFile):
                 shutil.copy(srcFile, dstFile)
 
-    settings.userPrefsDir = userPrefsDir
+    settings.userPrefsDir = options.userPrefsDir
 
     # Do not run Orca if accessibility has not been enabled.
     # We do allow, however, one to force Orca to run via the
@@ -2195,15 +2341,15 @@ def main():
     # setting is typically not set since the gdm user does not
     # have a home.
     #
-    a11yEnabled = settings.isAccessibilityEnabled()
-    if (not bypassSetup) and (not a11yEnabled):
+    a11yEnabled = _settingsManager.isAccessibilityEnabled()
+    if not options.bypassSetup and not a11yEnabled:
         _showPreferencesConsole()
         die()
 
-    if setupRequested and (not bypassSetup) and (not showGUI):
+    if options.setupRequested and not (options.bypassSetup or options.showGUI):
         _showPreferencesConsole()
 
-    if not desktopRunning:
+    if not options.desktopRunning:
         print "Cannot start Orca because it cannot connect"
         print "to the Desktop.  Please make sure the DISPLAY"
         print "environment variable has been set."
@@ -2217,7 +2363,7 @@ def main():
 
     try:
         message = _("Welcome to Orca.")
-        if not settings.onlySpeakDisplayedText:
+        if not _settingsManager.getSetting('onlySpeakDisplayedText'):
             speech.speak(message, settings.voices.get(settings.SYSTEM_VOICE))
         braille.displayMessage(message)
     except:
@@ -2229,10 +2375,11 @@ def main():
     # be run if the preferences file doesn't exist, unless the
     # user has bypassed any setup via the --no-setup switch.
     #
-    if setupRequested and (not bypassSetup) and showGUI:
+    if options.setupRequested and not options.bypassSetup and options.showGUI:
         showPreferencesGUI()
-    elif (not _userSettings) and (not bypassSetup):
-        if desktopRunning:
+    elif not options.bypassSetup \
+         and (not _userSettings or _settingsManager.isFirstStart()):
+        if options.desktopRunning:
             if not os.path.exists(userprefs):
                 # Hack to work around b.g.o. 601657.
                 #
@@ -2243,6 +2390,7 @@ def main():
             showPreferencesGUI()
         else:
             _showPreferencesConsole()
+        _settingsManager.setFirstStart()
 
     try:
         start(pyatspi.Registry) # waits until we stop the registry
diff --git a/src/orca/orca_console_prefs.py b/src/orca/orca_console_prefs.py
index 89cfb4a..0a77d63 100644
--- a/src/orca/orca_console_prefs.py
+++ b/src/orca/orca_console_prefs.py
@@ -32,6 +32,7 @@ import acss
 import settings
 import speech
 import speechserver
+import orca
 import orca_prefs
 import time
 
@@ -49,6 +50,8 @@ workingFactories   = []
 speechServerChoice = None
 speechVoiceChoice  = None
 
+_settingsManager = getattr(orca, '_settingsManager')
+
 # Translators: this is a regular expression that is intended to match
 # a positive 'yes' response from a user at the command line.  The expression
 # as given means - does it begin with (that's the '^' character) any of
@@ -318,8 +321,8 @@ def setupSpeech(prefsDict):
     }
 
     prefsDict["enableSpeech"] = True
-    prefsDict["speechServerFactory"] = factory
-    prefsDict["speechServerInfo"] = speechServerChoice
+    prefsDict["speechServerFactory"] = factory.__name__
+    prefsDict["speechServerInfo"] = speechServerChoice.getInfo()
     prefsDict["voices"] = voices
 
     stop = True
@@ -582,7 +585,8 @@ def showPreferencesUI(commandLineSettings):
             stop = False
             sayAndPrint(_("Please enter y or n."))
 
-    logoutNeeded = orca_prefs.writePreferences(prefsDict)
+    prefsDict['firstStart'] = False
+    logoutNeeded = _settingsManager.saveSettings(prefsDict, {}, {})
     if logoutNeeded:
         sayAndPrint(_("Accessibility support for GNOME has just been enabled."),
                     logoutNeeded,
diff --git a/src/orca/orca_gui_prefs.py b/src/orca/orca_gui_prefs.py
index 1ce66a0..d1b6040 100644
--- a/src/orca/orca_gui_prefs.py
+++ b/src/orca/orca_gui_prefs.py
@@ -41,7 +41,6 @@ except:
     import mag
 import orca
 import orca_gtkbuilder
-import orca_prefs
 import orca_state
 import orca_platform
 import settings
@@ -54,6 +53,11 @@ import speech
 import speechserver
 import text_attribute_names
 
+import orca_gui_profile
+
+_settingsManager = getattr(orca, '_settingsManager')
+
+
 try:
     import louis
 except ImportError:
@@ -135,8 +139,16 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
 
         orca_gtkbuilder.GtkBuilderWrapper.__init__(self, fileName, windowName)
 
-        self.prefsDict = prefsDict
-        self.enableLiveUpdating = settings.enableMagLiveUpdating
+        if prefsDict is None:
+            generalSettings  = _settingsManager.getGeneralSettings()
+            activeProfile = generalSettings.get('startingProfile')
+        else:
+            activeProfile = prefsDict['activeProfile']
+
+        generalSettings = _settingsManager.getGeneralSettings(activeProfile[1])
+        self.prefsDict = generalSettings
+        self.enableLiveUpdating = \
+            _settingsManager.getSetting('enableMagLiveUpdating')
 
         # Initialize variables to None to keep pylint happy.
         #
@@ -177,6 +189,9 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         self.savedRate = None
         self._isInitialSetup = False
         self.selectedFamilyChoices = {}
+        self.profilesCombo = None
+        self.profilesComboModel = None
+        self.startingProfileCombo = None
 
     def init(self):
         """Initialize the Orca configuration GUI. Read the users current
@@ -189,7 +204,8 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         # in case the user played with the sliders.
         #        
         try:
-            defaultVoice = settings.voices[settings.DEFAULT_VOICE]
+            voices = _settingsManager.getSetting('voices')
+            defaultVoice = voices[settings.DEFAULT_VOICE]
         except KeyError:
             defaultVoice = {}
         try:
@@ -206,7 +222,13 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
             self.savedRate = 50.0
 
         # ***** Key Bindings treeview initialization *****
+
         self.keyBindView = self.get_widget("keyBindingsTreeview")
+        
+        if self.keyBindView.get_columns():
+            for column in self.keyBindView.get_columns():
+                self.keyBindView.remove_column(column)
+
         self.keyBindingsModel = gtk.TreeStore(
             gobject.TYPE_STRING,  # Handler name
             gobject.TYPE_STRING,  # Human Readable Description
@@ -462,8 +484,7 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
                         self._initComboBox(self.get_widget("speechFamilies"))
         self._initSpeechState()
 
-        path = os.path.join(settings.userPrefsDir, "user-settings.py")
-        self._isInitialSetup = not os.path.exists(path)
+        self._isInitialSetup = not os.path.exists(settings.userPrefsDir)
 
         self._initGUIState()
 
@@ -492,9 +513,11 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
     def writeUserPreferences(self):
         """Write out the user's generic Orca preferences.
         """
-
-        if orca_prefs.writePreferences(self.prefsDict, self.keyBindingsModel,
-                                       self.pronunciationModel):
+        pronunciationDict = self.getModelDict(self.pronunciationModel)
+        keyBindingsDict = self.getKeyBindingsModelDict(self.keyBindingsModel)
+        if _settingsManager.saveSettings(self.prefsDict,
+                                         pronunciationDict,
+                                         keyBindingsDict):
             self._presentMessage(
                 _("Accessibility support for GNOME has just been enabled."))
             self._presentMessage(
@@ -868,6 +891,16 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         - systemName: the speech system name to use to set the active combo
         box item.
         """
+        # JD -> JH: We aren't expecting this string in quotes, yet we
+        # seem to be getting it that way from the gconf backend. That
+        # is causing the 'endswith(systemName)' test to fail. That in
+        # turn is resulting in our failing to find a match. I'm not
+        # suggesting this hack is the solution; I'm merely trying to
+        # make your hang go away. :-) If you comment this line, you
+        # should see the hang and the debug output -- assuming your
+        # active speech factory is speechdispatcherfactory.
+        #
+        systemName = systemName.strip("'")
 
         if len(self.speechSystemsChoices) == 0:
             self.speechSystemsChoice = None
@@ -1002,8 +1035,8 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
 
         [attrList, attrDict] = \
            defScript.utilities.stringToKeysAndDict(setAttributes)
-        [allAttrList, allAttrDict] = \
-           defScript.utilities.stringToKeysAndDict(settings.allTextAttributes)
+        [allAttrList, allAttrDict] = defScript.utilities.stringToKeysAndDict(
+            _settingsManager.getSetting('allTextAttributes'))
 
         for i in range(0, len(attrList)):
             for path in range(0, len(allAttrList)):
@@ -1042,8 +1075,8 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         defScript = default.Script(None)
         [attrList, attrDict] = \
             defScript.utilities.stringToKeysAndDict(setAttributes)
-        [allAttrList, allAttrDict] = \
-            defScript.utilities.stringToKeysAndDict(settings.allTextAttributes)
+        [allAttrList, allAttrDict] = defScript.utilities.stringToKeysAndDict(
+                _settingsManager.getSetting('allTextAttributes'))
 
         for i in range(0, len(attrList)):
             for path in range(0, len(allAttrList)):
@@ -1186,6 +1219,11 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         """
 
         self.getTextAttributesView = self.get_widget("textAttributesTreeView")
+
+        if self.getTextAttributesView.get_columns():
+            for column in self.getTextAttributesView.get_columns():
+                self.getTextAttributesView.remove_column(column)
+
         model = gtk.ListStore(gobject.TYPE_STRING,
                               gobject.TYPE_BOOLEAN,
                               gobject.TYPE_BOOLEAN,
@@ -1196,7 +1234,7 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         #
         defScript = default.Script(None)
         [allAttrList, allAttrDict] = defScript.utilities.stringToKeysAndDict(
-            settings.allTextAttributes)
+            _settingsManager.getSetting('allTextAttributes'))
         for i in range(0, len(allAttrList)):
             thisIter = model.append()
             localizedKey = \
@@ -1287,13 +1325,17 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
 
         # Check all the enabled (spoken) text attributes.
         #
-        self._setSpokenTextAttributes(self.getTextAttributesView,
-                            settings.enabledSpokenTextAttributes, True, True)
+        self._setSpokenTextAttributes(
+            self.getTextAttributesView,
+            _settingsManager.getSetting('enabledSpokenTextAttributes'),
+            True, True)
 
         # Check all the enabled (brailled) text attributes.
         #
-        self._setBrailledTextAttributes(self.getTextAttributesView,
-                                settings.enabledBrailledTextAttributes, True)
+        self._setBrailledTextAttributes(
+            self.getTextAttributesView,
+            _settingsManager.getSetting('enabledBrailledTextAttributes'),
+            True)
 
         # Connect a handler for when the user changes columns within the
         # view, so that we can adjust the search column for item lookups.
@@ -1356,6 +1398,11 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         """
 
         self.pronunciationView = self.get_widget("pronunciationTreeView")
+
+        if self.pronunciationView.get_columns():
+            for column in self.pronunciationView.get_columns():
+                self.pronunciationView.remove_column(column)
+
         model = gtk.ListStore(gobject.TYPE_STRING,
                               gobject.TYPE_STRING)
 
@@ -1769,6 +1816,7 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
                             selectedTable:
                         selectedTableIter = it
                 cell = self.planeCellRendererText
+                tablesCombo.clear()
                 tablesCombo.pack_start(cell, True)
                 tablesCombo.add_attribute(cell, 'text', 0)
                 tablesCombo.set_model(tablesModel)
@@ -2140,16 +2188,19 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
 
         # Pronunciation dictionary pane.
         #
-        self._createPronunciationTreeView()
+        _profile = self.prefsDict.get('activeProfile')[1]
+        pronunciationsDict = _settingsManager.getPronunciations(_profile)
+        self._createPronunciationTreeView(pronunciationsDict)
 
         # General pane.
         #
-        self.get_widget("showMainWindowCheckButton").set_active( \
-                        prefs["showMainWindow"])
-        self.get_widget("quitOrcaNoConfirmationCheckButton").set_active( \
-                        prefs["quitOrcaNoConfirmation"])
-        self.get_widget("presentToolTipsCheckButton").set_active( \
-            prefs["presentToolTips"] and settings.canPresentToolTips)
+        self.get_widget("showMainWindowCheckButton").set_active(
+            prefs["showMainWindow"])
+        self.get_widget("quitOrcaNoConfirmationCheckButton").set_active(
+            prefs["quitOrcaNoConfirmation"])        
+        self.get_widget("presentToolTipsCheckButton").set_active(
+            prefs["presentToolTips"] \
+                and _settingsManager.getSetting('canPresentToolTips'))
 
         self.disableKeyGrabPref = settings.isGKSUGrabDisabled()
         self.get_widget("disableKeyGrabCheckButton").set_active( \
@@ -2165,6 +2216,40 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         self.enableAutostart = settings.isOrcaAutostarted()
         self.get_widget("autostartOrcaCheckButton").set_active( \
                          self.enableAutostart)
+        
+        # Orca User Profiles
+        #
+        self.profilesCombo = self.get_widget('availableProfilesComboBox1')
+        self.startingProfileCombo = self.get_widget('availableProfilesComboBox2')
+        self.profilesComboModel = self.get_widget('model9')
+        self.__initProfileCombo()
+
+    def __initProfileCombo(self):
+        """Adding available profiles and setting active as the active one"""
+
+        availableProfiles = self.__getAvailableProfiles()
+        self.profilesComboModel.clear()
+
+        defaultValue = ['Default', 'default']
+        if not len(availableProfiles):
+            self.profilesComboModel.append(defaultValue)
+        else:
+            for profile in availableProfiles:
+                self.profilesComboModel.append(profile)
+
+        activeProfile = self.prefsDict.get('activeProfile') or defaultValue
+        startingProfile = self.prefsDict.get('startingProfile') or defaultValue
+
+        activeProfileIter = self.getComboBoxIndex(self.profilesCombo,
+                                                  activeProfile[0])
+        startingProfileIter = self.getComboBoxIndex(self.startingProfileCombo,
+                                                  startingProfile[0])
+        self.profilesCombo.set_active(activeProfileIter)
+        self.startingProfileCombo.set_active(startingProfileIter)
+
+    def __getAvailableProfiles(self):
+        """Get available user profiles."""
+        return _settingsManager.availableProfiles()
 
     def _updateOrcaModifier(self):
         combobox = self.get_widget("orcaModifierComboBox")
@@ -2206,6 +2291,48 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
 
         return 0
 
+    def getComboBoxList(self, combobox):
+        """Get the list of values from the active combox
+        """
+        active = combobox.get_active()
+        model = combobox.get_model()
+        activeIter = model.get_iter(active)
+        activeLabel = model.get_value(activeIter, 0)
+        activeName = model.get_value(activeIter, 1)
+        return [activeLabel, activeName]
+
+    def getKeyBindingsModelDict(self, model, modifiedOnly=True):
+        modelDict = {}
+        node = model.get_iter_first()
+        while node:
+            child = model.iter_children(node)
+            while child:
+                key, modified = model.get(child, HANDLER, MODIF)
+                if modified or not modifiedOnly:
+                    value = []
+                    value.append(model.get(
+                            child, KEY1, MOD_MASK1, MOD_USED1, CLICK_COUNT1))
+                    value.append(model.get(
+                            child, KEY2, MOD_MASK2, MOD_USED2, CLICK_COUNT2))
+                    modelDict[key] = value
+                child = model.iter_next(child)
+            node = model.iter_next(node)
+
+        return modelDict
+
+    def getModelDict(self, model):
+        """Get the list of values from a list[str,str] model
+        """
+        pronunciation_dict.pronunciation_dict = {}
+        currentIter = model.get_iter_first()
+        while currentIter is not None:
+            key, value = model.get(currentIter, ACTUAL, REPLACEMENT)
+            if key and value:
+                pronunciation_dict.setPronunciation(key, value)
+            currentIter = model.iter_next(currentIter)
+        modelDict = pronunciation_dict.pronunciation_dict
+        return modelDict
+
     def showGUI(self):
         """Show the Orca configuration GUI window. This assumes that
         the GUI has already been created.
@@ -2232,7 +2359,7 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         #
         orcaSetupWindow.realize()
         try:
-            if settings.showMainWindow:
+            if _settingsManager.getSettings('showMainWindow'):
                 orcaSetupWindow.present()
         except:
             pass
@@ -2247,8 +2374,10 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         # We always want to re-order the text attributes page so that enabled
         # items are consistently at the top.
         #
-        self._setSpokenTextAttributes(self.getTextAttributesView,
-                            settings.enabledSpokenTextAttributes, True, True)
+        self._setSpokenTextAttributes(
+                self.getTextAttributesView,
+                _settingsManager.getSetting('enabledSpokenTextAttributes'),
+                True, True)
 
         orcaSetupWindow.show()
 
@@ -2729,7 +2858,9 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         rate = widget.get_value()
         voiceType = self.get_widget("voiceTypes").get_active()
         self._setRateForVoiceType(voiceType, rate)
-        settings.voices[settings.DEFAULT_VOICE][acss.ACSS.RATE] = rate
+        voices = _settingsManager.getSetting('voices')
+        voices[settings.DEFAULT_VOICE][acss.ACSS.RATE] = rate
+        _settingsManager.setSetting('voices', voices)
 
     def pitchValueChanged(self, widget):
         """Signal handler for the "value_changed" signal for the pitchScale
@@ -2744,7 +2875,9 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         pitch = widget.get_value()
         voiceType = self.get_widget("voiceTypes").get_active()
         self._setPitchForVoiceType(voiceType, pitch)
-        settings.voices[settings.DEFAULT_VOICE][acss.ACSS.AVERAGE_PITCH] = pitch
+        voices = _settingsManager.getSetting('voices')
+        voices[settings.DEFAULT_VOICE][acss.ACSS.AVERAGE_PITCH] = pitch
+        _settingsManager.setSetting('voices', voices)
 
     def volumeValueChanged(self, widget):
         """Signal handler for the "value_changed" signal for the voiceScale
@@ -2759,7 +2892,9 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         volume = widget.get_value()
         voiceType = self.get_widget("voiceTypes").get_active()
         self._setVolumeForVoiceType(voiceType, volume)
-        settings.voices[settings.DEFAULT_VOICE][acss.ACSS.GAIN] = volume
+        voices = _settingsManager.getSetting('voices')
+        voices[settings.DEFAULT_VOICE][acss.ACSS.GAIN] = volume
+        _settingsManager.setSetting('voices', voices)
 
     def checkButtonToggled(self, widget):
         """Signal handler for "toggled" signal for basic GtkCheckButton 
@@ -3900,6 +4035,7 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
             #
             self._presentMessage(
                 _("Key binding deleted. Press enter to confirm."))
+            self.newBinding = None
             return True
 
         clickCount = orca_state.clickCount
@@ -3995,8 +4131,9 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         - widget: the component that generated the signal.
         """
 
-        self.prefsDict["presentToolTips"] = widget.get_active() and \
-                                            settings.canPresentToolTips
+        self.prefsDict["presentToolTips"] = \
+            widget.get_active() \
+            and _settingsManager.getSetting('canPresentToolTips')
 
     def disableKeyGrabChecked(self, widget):
         """Signal handler for the "toggled" signal for the
@@ -4084,10 +4221,11 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         - widget: the component that generated the signal.
         """
 
-        self._setSpokenTextAttributes(self.getTextAttributesView,
-                                settings.allTextAttributes, True)
-        self._setBrailledTextAttributes(self.getTextAttributesView,
-                                settings.allTextAttributes, True)
+        attributes = _settingsManager.getSetting('allTextAttributes')
+        self._setSpokenTextAttributes(
+            self.getTextAttributesView, attributes, True)
+        self._setBrailledTextAttributes(
+            self.getTextAttributesView, attributes, True)
         self._updateTextDictEntry()
 
     def textUnselectAllButtonClicked(self, widget):
@@ -4101,10 +4239,11 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         - widget: the component that generated the signal.
         """
 
-        self._setSpokenTextAttributes(self.getTextAttributesView,
-                                settings.allTextAttributes, False)
-        self._setBrailledTextAttributes(self.getTextAttributesView,
-                                settings.allTextAttributes, False)
+        attributes = _settingsManager.getSetting('allTextAttributes')
+        self._setSpokenTextAttributes(
+            self.getTextAttributesView, attributes, False)
+        self._setBrailledTextAttributes(
+            self.getTextAttributesView, attributes, False)
         self._updateTextDictEntry()
 
     def textResetButtonClicked(self, widget):
@@ -4118,12 +4257,21 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         - widget: the component that generated the signal.
         """
 
-        self._setSpokenTextAttributes(self.getTextAttributesView,
-                                settings.allTextAttributes, False)
-        self._setSpokenTextAttributes(self.getTextAttributesView,
-                                settings.enabledSpokenTextAttributes, True)
-        self._setBrailledTextAttributes(self.getTextAttributesView,
-                                settings.enabledBrailledTextAttributes, True)
+        attributes = _settingsManager.getSetting('allTextAttributes')
+        self._setSpokenTextAttributes(
+            self.getTextAttributesView, attributes, False)
+        self._setBrailledTextAttributes(
+            self.getTextAttributesView, attributes, False)
+
+        attributes = _settingsManager.getSetting('enabledSpokenTextAttributes')
+        self._setSpokenTextAttributes(
+            self.getTextAttributesView, attributes, True)
+
+        attributes = \
+            _settingsManager.getSetting('enabledBrailledTextAttributes')
+        self._setBrailledTextAttributes(
+            self.getTextAttributesView, attributes, True)
+
         self._updateTextDictEntry()
 
     def textMoveToTopButtonClicked(self, widget):
@@ -4223,25 +4371,13 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         # Restore the default rate/pitch/gain,
         # in case the user played with the sliders.
         #
-        defaultVoice = settings.voices[settings.DEFAULT_VOICE]
+        voices = _settingsManager.getSetting('voices')
+        defaultVoice = voices[settings.DEFAULT_VOICE]
         defaultVoice[acss.ACSS.GAIN] = self.savedGain
         defaultVoice[acss.ACSS.AVERAGE_PITCH] = self.savedPitch
         defaultVoice[acss.ACSS.RATE] =  self.savedRate
 
-    def applyButtonClicked(self, widget):
-        """Signal handler for the "clicked" signal for the applyButton
-           GtkButton widget. The user has clicked the Apply button.
-           Write out the users preferences. If GNOME accessibility hadn't
-           previously been enabled, warn the user that they will need to
-           log out. Shut down any active speech servers that were started.
-           Reload the users preferences to get the new speech, braille and
-           key echo value to take effect. Do not dismiss the configuration
-           window.
-
-        Arguments:
-        - widget: the component that generated the signal.
-        """
-
+    def saveBasicSettings(self):
         if not self._isInitialSetup:
             self.restoreSettings()
 
@@ -4278,6 +4414,33 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
             #
             pass
 
+
+
+    def applyButtonClicked(self, widget):
+        """Signal handler for the "clicked" signal for the applyButton
+           GtkButton widget. The user has clicked the Apply button.
+           Write out the users preferences. If GNOME accessibility hadn't
+           previously been enabled, warn the user that they will need to
+           log out. Shut down any active speech servers that were started.
+           Reload the users preferences to get the new speech, braille and
+           key echo value to take effect. Do not dismiss the configuration
+           window.
+
+        Arguments:
+        - widget: the component that generated the signal.
+        """
+        self.saveBasicSettings()
+
+        activeProfile = self.getComboBoxList(self.profilesCombo)
+        startingProfile = self.getComboBoxList(self.startingProfileCombo)
+
+        self.prefsDict['profile'] = activeProfile
+        self.prefsDict['activeProfile'] = activeProfile
+        self.prefsDict['startingProfile'] = startingProfile
+        _settingsManager.setStartingProfile(startingProfile)
+
+        self.prefsDict['firstStart'] = False
+
         self.writeUserPreferences()
 
         orca.loadUserSettings()
@@ -4286,6 +4449,8 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
 
         self._populateKeyBindings()
 
+        self.__initProfileCombo()
+
     def cancelButtonClicked(self, widget):
         """Signal handler for the "clicked" signal for the cancelButton
            GtkButton widget. The user has clicked the Cancel button.
@@ -4298,7 +4463,7 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         self.windowClosed(widget)
         self.get_widget("orcaSetupWindow").destroy()
 
-    def okButtonClicked(self, widget):
+    def okButtonClicked(self, widget = None):
         """Signal handler for the "clicked" signal for the okButton
            GtkButton widget. The user has clicked the OK button.
            Write out the users preferences. If GNOME accessibility hadn't
@@ -4360,6 +4525,107 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
 
         return self.orcaMagAdvancedDialog
 
+    def showProfileGUI(self, widget):
+        """Show profile Dialog to add a new one"""
+
+        profileToSaveLabel = orca_gui_profile.showProfileUI()
+        if not profileToSaveLabel:
+            return
+        profileToSave = profileToSaveLabel.replace(' ','_').lower()
+        profile = [profileToSaveLabel, profileToSave]
+
+        def saveActiveProfile(newProfile = True):
+            if newProfile:
+                activeProfileIter = self.profilesComboModel.append(profile)
+                self.profilesCombo.set_active_iter(activeProfileIter)
+
+            self.prefsDict['profile'] = profile
+            self.prefsDict['activeProfile'] = profile
+            self.writeUserPreferences()
+
+        availableProfiles = [p[1] for p in self.__getAvailableProfiles()]
+        if isinstance(profileToSave, str) \
+                and profileToSave != '' \
+                and not profileToSave in availableProfiles \
+                and profileToSave != 'default':
+            saveActiveProfile()
+        else:
+            if profileToSave != None:
+                # We're here because given profile name exists, so we have
+                # to give that info to the user and give him the chance
+                # to continue, or not saving the profile
+                message = _("Profile <b>%s</b> already exists.\n" \
+                            "Continue updating the existing profile with " \
+                            "these new changes?") % profileToSaveLabel
+
+                dialog = gtk.MessageDialog(None,
+                        gtk.DIALOG_MODAL,
+                        type=gtk.MESSAGE_INFO,
+                        buttons=gtk.BUTTONS_YES_NO)
+
+                dialog.set_markup(_("<b>User Profile Conflict!</b>"))
+                dialog.format_secondary_markup(message)
+                dialog.set_title(_("Save Profile As Conflict"))
+                response = dialog.run()
+
+                if response == gtk.RESPONSE_YES:
+                    dialog.destroy()
+                    saveActiveProfile(False)
+                else:
+                    dialog.destroy()
+                
+
+    def loadProfileButtonClicked(self, widget):
+        """Load profile button clicked handler"""
+
+        if self._isInitialSetup:
+            return
+
+        # First of all, we give a chance of cancel profile change
+        message = _("You are about to change the active profile. If you\n" \
+                    "have just make changes in your preferences, it will\n" \
+                    "be dropped at profile load.\n\n" \
+                    "Continue loading profile discarding previous changes?")
+
+        dialog = gtk.MessageDialog(None,
+                gtk.DIALOG_MODAL,
+                type=gtk.MESSAGE_INFO,
+                buttons=gtk.BUTTONS_YES_NO)
+
+        dialog.set_markup(_("<b>Load user profile info</b>"))
+        dialog.format_secondary_markup(message)
+        dialog.set_title(_("Load User Profile"))
+        response = dialog.run()
+
+        if response == gtk.RESPONSE_YES:
+            dialog.destroy()
+            self.loadSelectedProfile()
+        else:
+            dialog.destroy()
+
+    def loadSelectedProfile(self):
+        """Load selected profile"""
+
+        self.saveBasicSettings()
+
+        activeProfile = self.getComboBoxList(self.profilesCombo)
+        self.prefsDict['activeProfile'] = activeProfile
+        _settingsManager.setProfile(activeProfile[1])
+        self.prefsDict = _settingsManager.getGeneralSettings(activeProfile[1])
+
+        orca.showMainWindowGUI()
+        if _settingsManager.getSetting('showMainWindow'):
+            self.window.present()
+
+        self._initGUIState()
+
+        self._initSpeechState()
+
+        self._populateKeyBindings()
+
+        self.__initProfileCombo()
+
+
 class OrcaAdvancedMagGUI(OrcaSetupGUI):
 
     def __init__(self, fileName, windowName, prefsDict = None):
@@ -4373,7 +4639,8 @@ class OrcaAdvancedMagGUI(OrcaSetupGUI):
         OrcaSetupGUI.__init__(self, fileName, windowName)
 
         self.prefsDict = prefsDict
-        self.enableLiveUpdating = settings.enableMagLiveUpdating
+        self.enableLiveUpdating = \
+            _settingsManager.getSetting('enableMagLiveUpdating')
 
         # To make pylint happy.
         #
@@ -4534,7 +4801,6 @@ class OrcaAdvancedMagGUI(OrcaSetupGUI):
         - green: the green brightness value.
         - blue:  the blue brightness value.
         """
-
         self.get_widget("magBrightnessRedSpinButton").set_value(red)
         self.get_widget("magBrightnessGreenSpinButton").set_value(green)
         self.get_widget("magBrightnessBlueSpinButton").set_value(blue)
@@ -5096,7 +5362,9 @@ def showPreferencesUI():
         except:
             pass
 
-        prefsDict = orca_prefs.readPreferences()
+        startingProfile = _settingsManager.profile
+        prefsDict = _settingsManager.getGeneralSettings(startingProfile)
+
         orca_state.prefsUIFile = \
             os.path.join(orca_platform.prefix,
                          orca_platform.datadirname,
diff --git a/src/orca/orca_gui_profile.py b/src/orca/orca_gui_profile.py
new file mode 100644
index 0000000..8e7b0c5
--- /dev/null
+++ b/src/orca/orca_gui_profile.py
@@ -0,0 +1,189 @@
+# Orca
+#
+# Copyright 2010 Consorcio Fernando de los Rios.
+# Author: Javier Hernandez Antunez <jhernandez emergya es>
+# Author: Alejandro Leiva <aleiva emergya es>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
+# Boston MA  02110-1301 USA.
+
+"""Displays a GUI for the Orca profiles window"""
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2010 Consorcio Fernando de los Rios."
+__license__   = "LGPL"
+
+import os
+import sys
+import debug
+import gtk
+import locale
+
+import find
+import orca_gtkbuilder
+import orca_state
+import orca_platform
+
+from orca_i18n import _  # for gettext support
+
+from settings_manager import SettingsManager
+
+
+OS = None
+newProfile = None
+
+
+class OrcaProfileGUI(orca_gtkbuilder.GtkBuilderWrapper):
+
+    def __init__(self, fileName, windowName):
+        """Initialize the Orca profile configuration GUI.
+
+        Arguments:
+        - fileName: name of the GtkBuilder file.
+        - windowName: name of the component to get from the GtkBuilder file.
+        """
+
+        orca_gtkbuilder.GtkBuilderWrapper.__init__(self, fileName, windowName)
+
+        # Initialize variables to None to keep pylint happy.
+        #
+        self.searchString = None
+
+    def init(self):
+        # Initialize the dialog box controls.
+        self.profileString = ""
+
+    def showGUI(self):
+        """Show the Orca profile dialog. This assumes that the GUI has
+        already been created.
+        """
+
+        profileDialog = self.get_widget("profileDialog")
+
+        # Set the current time on the Find GUI dialog so that it'll
+        # get focus. set_user_time is a new call in pygtk 2.9.2 or later.
+        # It's surronded by a try/except block here so that if it's not found,
+        # then we can fail gracefully.
+        #
+        try:
+            profileDialog.realize()
+            ts = orca_state.lastInputEventTimestamp
+            if ts == 0:
+                ts = gtk.get_current_event_time()
+            profileDialog.window.set_user_time(ts)
+        except AttributeError:
+            debug.printException(debug.LEVEL_FINEST)
+
+        try:
+            profileEntry = self.get_widget("profileEntry")
+            profileEntry.set_text(self.profileString)
+        except:
+            pass
+
+        profileDialog.run()
+
+    def closeButtonClicked(self, widget):
+        """Signal handler for the "clicked" signal for the cancelButton
+           GtkButton widget. The user has clicked the Cancel button.
+           Hide the dialog.
+
+        Arguments:
+        - widget: the component that generated the signal.
+        """
+
+        self.get_widget("profileDialog").hide()
+
+    def on_saveProfileButton_clicked(self, widget):
+        """Signal handler for the "clicked" signal for the findButton
+           GtkButton widget. The user has clicked the Find button.
+           Call the method to begin the search.
+
+        Arguments:
+        - widget: the component that generated the signal.
+        """
+
+        # Merely hiding the dialog causes the find to take place before
+        # the original window has fully regained focus.
+        global newProfile
+
+        if self.get_widget("profileEntry").get_text() != '':
+            newProfile = self.get_widget("profileEntry").get_text()
+            self.get_widget("profileDialog").destroy()
+
+
+    # From now, this method can't have sense ...
+    def onProfileEntryChanged(self, widget, data=None):
+        """Signal handler for the "changed" signal for the ProfileEntry
+           GtkEntry widget."""
+        
+        if self.get_widget("profileEntry").get_text() != '':
+            self.get_widget('availableProfilesCombo').set_sensitive(False)
+        else:
+            self.get_widget('availableProfilesCombo').set_sensitive(True)
+
+
+    def profileDialogDestroyed(self, widget):
+        """Signal handler for the "destroyed" signal for the findDialog
+           GtkWindow widget. Reset OS to None.
+
+        Arguments:
+        - widget: the component that generated the signal.
+        """
+
+        global OS
+
+        OS = None
+
+    def __getAvailableProfiles(self):
+        """Get available user profiles"""
+
+        import orca
+
+        _settingsManager = getattr(orca, '_settingsManager')
+
+        return _settingsManager.availableProfiles()
+
+def showProfileUI():
+    global OS
+    global newProfile
+
+    newProfile = None
+
+    if not OS:
+        uiFile = os.path.join(orca_platform.prefix,
+                              orca_platform.datadirname,
+                              orca_platform.package,
+                              "ui",
+                              "orca-profile.ui")
+        OS = OrcaProfileGUI(uiFile, "profileDialog")
+        OS.init()
+
+    OS.showGUI()
+
+    return newProfile
+ 
+
+def main():
+    locale.setlocale(locale.LC_ALL, '')
+
+    showProfileUI()
+
+    gtk.main()
+    sys.exit(0)
+
+if __name__ == "__main__":
+    main()
diff --git a/src/orca/orca_prefs.py b/src/orca/orca_prefs.py
index dcc072c..eccb73c 100644
--- a/src/orca/orca_prefs.py
+++ b/src/orca/orca_prefs.py
@@ -149,9 +149,9 @@ class OrcaPrefs:
         set prior to this call).
         """
 
-        alreadyEnabled = settings.isAccessibilityEnabled()
+        alreadyEnabled = _settingsManager.isAccessibilityEnabled()
         if not alreadyEnabled:
-            settings.setAccessibilityEnabled(True)
+            _settingsManager.setAccessibilityEnabled(True)
 
         return not alreadyEnabled
 
diff --git a/src/orca/scripts/apps/Instantbird/script.py b/src/orca/scripts/apps/Instantbird/script.py
index 7fb8910..64afc25 100644
--- a/src/orca/scripts/apps/Instantbird/script.py
+++ b/src/orca/scripts/apps/Instantbird/script.py
@@ -32,12 +32,13 @@ import orca.default as default
 import orca.orca as orca
 import orca.orca_state as orca_state
 import orca.scripts.toolkits.Gecko as Gecko
-import orca.settings as settings
 import orca.speech as speech
 
 from chat import Chat
 from script_utilities import Utilities
 
+_settingsManager = getattr(orca, '_settingsManager')
+
 ########################################################################
 #                                                                      #
 # The Instantbird script class.                                        #
@@ -207,8 +208,8 @@ class Script(Gecko.Script):
             room2 = self.chat.getChatRoomName(event.source)
             if room1 != room2:
                 speech.speak(room2)
-                self.displayBrailleMessage(
-                    room2, flashTime=settings.brailleFlashTime)
+                flashTime = _settingsManager.getSetting('brailleFlashTime')
+                self.displayBrailleMessage(room2, flashTime)
                 orca.setLocusOfFocus(event, event.source)
                 return
 
diff --git a/src/orca/scripts/apps/Thunderbird/script.py b/src/orca/scripts/apps/Thunderbird/script.py
index 024e13b..606ab55 100644
--- a/src/orca/scripts/apps/Thunderbird/script.py
+++ b/src/orca/scripts/apps/Thunderbird/script.py
@@ -32,7 +32,6 @@ import orca.orca as orca
 import orca.debug as debug
 import orca.default as default
 import orca.orca_state as orca_state
-import orca.settings as settings
 import orca.speech as speech
 import orca.scripts.toolkits.Gecko as Gecko
 
@@ -43,6 +42,8 @@ from speech_generator import SpeechGenerator
 from script_utilities import Utilities
 import script_settings
 
+_settingsManager = getattr(orca, '_settingsManager')
+
 ########################################################################
 #                                                                      #
 # The Thunderbird script class.                                        #
@@ -616,7 +617,7 @@ class Script(Gecko.Script):
         self.setCaretPosition(obj, offset)
         if not script_settings.sayAllOnLoad:
             self.presentLine(obj, offset)
-        elif settings.enableSpeech:
+        elif _settingsManager.getSetting('enableSpeech'):
             self.sayAll(None)
         self._messageLoaded = False
 
diff --git a/src/orca/scripts/apps/evolution/script.py b/src/orca/scripts/apps/evolution/script.py
index 0c41cda..53f0533 100644
--- a/src/orca/scripts/apps/evolution/script.py
+++ b/src/orca/scripts/apps/evolution/script.py
@@ -44,6 +44,8 @@ from formatting import Formatting
 from speech_generator import SpeechGenerator
 from script_utilities import Utilities
 
+_settingsManager = getattr(orca, '_settingsManager')
+
 ########################################################################
 #                                                                      #
 # The Evolution script class.                                          #
@@ -332,7 +334,7 @@ class Script(default.Script):
         self.rolesList = [pyatspi.ROLE_TEXT, \
                           pyatspi.ROLE_PANEL, \
                           pyatspi.ROLE_TABLE_CELL]
-        if settings.readTableCellRow \
+        if _settingsManager.getSetting('readTableCellRow') \
             and (self.utilities.hasMatchingHierarchy(
                     event.source, self.rolesList)):
             debug.println(self.debugLevel,
@@ -385,8 +387,9 @@ class Script(default.Script):
 
         self.rolesList = [pyatspi.ROLE_TABLE_CELL, \
                           pyatspi.ROLE_TREE_TABLE]
-        if settings.readTableCellRow and self.utilities.hasMatchingHierarchy(
-                event.source, self.rolesList):
+        if _settingsManager.getSetting('readTableCellRow') \
+                and self.utilities.hasMatchingHierarchy(event.source,
+                                                        self.rolesList):
             debug.println(self.debugLevel,
                           "evolution.locusOfFocusChanged - mail view: " \
                           + "message header list.")
@@ -397,7 +400,7 @@ class Script(default.Script):
             # for the duration of this code section, then resetting it to
             # True at the end.
             #
-            settings.readTableCellRow = False
+            _settingsManager.setSetting('readTableCellRow', False)
 
             parent = event.source.parent
             parentTable = parent.queryTable()
@@ -412,7 +415,7 @@ class Script(default.Script):
             if self.lastMessageRow == row:
                 default.Script.locusOfFocusChanged(self, event,
                                            oldLocusOfFocus, newLocusOfFocus)
-                settings.readTableCellRow = True
+                _settingsManager.setSetting('readTableCellRow', True)
                 return
 
             # This is an indication of whether we should speak all the table
@@ -432,8 +435,10 @@ class Script(default.Script):
                         self.lastMessageColumn == column) or \
                        justDeleted
 
-            savedBrailleVerbosityLevel = settings.brailleVerbosityLevel
-            savedSpeechVerbosityLevel = settings.speechVerbosityLevel
+            savedBrailleVerbosityLevel = \
+                _settingsManager.getSetting('brailleVerbosityLevel')
+            savedSpeechVerbosityLevel = \
+                _settingsManager.getSetting('speechVerbosityLevel')
 
             brailleRegions = []
             cellWithFocus = None
@@ -525,10 +530,12 @@ class Script(default.Script):
                         #
                         if (verbose or (checkbox and column == i)) \
                            and not useAlternativeName:
-                            settings.brailleVerbosityLevel = \
-                                settings.VERBOSITY_LEVEL_BRIEF
-                            settings.speechVerbosityLevel = \
-                                settings.VERBOSITY_LEVEL_BRIEF
+                            _settingsManager.setSetting(
+                                'brailleVerbosityLevel',
+                                settings.VERBOSITY_LEVEL_BRIEF)
+                            _settingsManager.setSetting(
+                                'speechVerbosityLevel',
+                                settings.VERBOSITY_LEVEL_BRIEF)
 
                             utterances = speechGen.generateSpeech(
                                 header,
@@ -552,13 +559,14 @@ class Script(default.Script):
                         # then speak/braille "attachment".
                         #
                         if verbose:
-                            settings.brailleVerbosityLevel = \
-                                settings.VERBOSITY_LEVEL_VERBOSE
+                            level = settings.VERBOSITY_LEVEL_VERBOSE
                         else:
-                            settings.brailleVerbosityLevel = \
-                                settings.VERBOSITY_LEVEL_BRIEF
-                        settings.speechVerbosityLevel = \
-                            savedSpeechVerbosityLevel
+                            level = settings.VERBOSITY_LEVEL_BRIEF
+                        _settingsManager.setSetting(
+                            'brailleVerbosityLevel', level)
+                        _settingsManager.setSetting(
+                            'speechVerbosityLevel',
+                            savedSpeechVerbosityLevel)
                         utterances = speechGen.generateSpeech(
                             cell,
                             includeContext=False,
@@ -619,11 +627,13 @@ class Script(default.Script):
             if brailleRegions != []:
                 self.displayBrailleRegions([brailleRegions, cellWithFocus])
 
-            settings.brailleVerbosityLevel = savedBrailleVerbosityLevel
-            settings.speechVerbosityLevel = savedSpeechVerbosityLevel
+            _settingsManager.setSetting(
+                'brailleVerbosityLevel', savedBrailleVerbosityLevel)
+            _settingsManager.setSetting(
+                'speechVerbosityLevel', savedSpeechVerbosityLevel)
             self.lastMessageColumn = column
             self.lastMessageRow = row
-            settings.readTableCellRow = True
+            _settingsManager.setSetting('readTableCellRow', True)
             return
 
         # 4) Calendar view: day view: tabbing to day with appts.
@@ -1187,10 +1197,12 @@ class Script(default.Script):
         speechGen = self.speechGenerator
 
         savedSpeechVerbosityLevel = settings.speechVerbosityLevel
-        settings.speechVerbosityLevel = settings.VERBOSITY_LEVEL_BRIEF
+        _settingsManager.setSetting(
+            'speechVerbosityLevel', settings.VERBOSITY_LEVEL_BRIEF)
         utterances = speechGen.generateSpeech(tab)
         speech.speak(utterances)
-        settings.speechVerbosityLevel = savedSpeechVerbosityLevel
+        _settingsManager.setSetting(
+            'speechVerbosityLevel', savedSpeechVerbosityLevel)
 
         self.displayBrailleRegions(brailleGen.generateBraille(tab))
 
@@ -1232,12 +1244,14 @@ class Script(default.Script):
 
         # Determine the correct "say all by" mode to use.
         #
-        if settings.sayAllStyle == settings.SAYALL_STYLE_SENTENCE:
+        sayAllStyle = _settingsManager.getSetting('sayAllStyle')
+        if sayAllStyle == settings.SAYALL_STYLE_SENTENCE:
             mode = pyatspi.TEXT_BOUNDARY_SENTENCE_END
-        elif settings.sayAllStyle == settings.SAYALL_STYLE_LINE:
+        elif sayAllStyle == settings.SAYALL_STYLE_LINE:
             mode = pyatspi.TEXT_BOUNDARY_LINE_START
         else:
             mode = pyatspi.TEXT_BOUNDARY_LINE_START
+        voices = _settingsManager.getSetting('voices')
 
         while not done:
             panel = htmlPanel.getChildAtIndex(i)
@@ -1261,9 +1275,9 @@ class Script(default.Script):
                        len(mystr) == 0 or mystr[len(mystr)-1] in '.?!':
                         string = self.utilities.adjustForRepeats(string)
                         if string.decode("UTF-8").isupper():
-                            voice = settings.voices[settings.UPPERCASE_VOICE]
+                            voice = voices[settings.UPPERCASE_VOICE]
                         else:
-                            voice = settings.voices[settings.DEFAULT_VOICE]
+                            voice = voices[settings.DEFAULT_VOICE]
 
                         if not textObjs:
                             textObjs.append(textObj)
@@ -1290,9 +1304,9 @@ class Script(default.Script):
         if len(string) != 0:
             string = self.utilities.adjustForRepeats(string)
             if string.decode("UTF-8").isupper():
-                voice = settings.voices[settings.UPPERCASE_VOICE]
+                voice = voices[settings.UPPERCASE_VOICE]
             else:
-                voice = settings.voices[settings.DEFAULT_VOICE]
+                voice = voices[settings.DEFAULT_VOICE]
 
             yield [speechserver.SayAllContext(textObjs, string,
                                               startOffset, endOffset),
diff --git a/src/orca/scripts/apps/evolution/speech_generator.py b/src/orca/scripts/apps/evolution/speech_generator.py
index 6c9b05f..38eb330 100644
--- a/src/orca/scripts/apps/evolution/speech_generator.py
+++ b/src/orca/scripts/apps/evolution/speech_generator.py
@@ -27,11 +27,13 @@ __license__   = "LGPL"
 
 import pyatspi
 
-import orca.settings as settings
+import orca.orca as orca
 import orca.speech_generator as speech_generator
 
 from orca.orca_i18n import _ # for gettext support
 
+_settingsManager = getattr(orca, '_settingsManager')
+
 class SpeechGenerator(speech_generator.SpeechGenerator):
     """Overrides _generateSpeechForTableCell so that, if this is an
        expanded table cell, we can strip off the "0 items".
@@ -85,7 +87,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
         # formatting string to address the headers associated with
         # toggle columns. That's really the difference here.]]]
         #
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
diff --git a/src/orca/scripts/apps/gnome-panel/speech_generator.py b/src/orca/scripts/apps/gnome-panel/speech_generator.py
index c2c8884..efa2b72 100644
--- a/src/orca/scripts/apps/gnome-panel/speech_generator.py
+++ b/src/orca/scripts/apps/gnome-panel/speech_generator.py
@@ -27,9 +27,11 @@ __license__   = "LGPL"
 
 import pyatspi
 
-import orca.settings as settings
+import orca.orca as orca
 import orca.speech_generator as speech_generator
 
+_settingsManager = getattr(orca, '_settingsManager')
+
 class SpeechGenerator(speech_generator.SpeechGenerator):
 
     def __init__(self, script):
@@ -48,7 +50,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
         acss = self.voice(speech_generator.DEFAULT)
         role = args.get('role', obj.getRole())
         if role == pyatspi.ROLE_FRAME:
-            if settings.onlySpeakDisplayedText:
+            if _settingsManager.getSetting('onlySpeakDisplayedText'):
                 return []
             else:
                 acss = self.voice(speech_generator.SYSTEM)
diff --git a/src/orca/scripts/apps/gnome-terminal/script.py b/src/orca/scripts/apps/gnome-terminal/script.py
index f387786..5378b69 100644
--- a/src/orca/scripts/apps/gnome-terminal/script.py
+++ b/src/orca/scripts/apps/gnome-terminal/script.py
@@ -36,6 +36,8 @@ import orca.orca_state as orca_state
 import orca.settings as settings
 import orca.speech as speech
 
+_settingsManager = getattr(orca, '_settingsManager')
+
 ########################################################################
 #                                                                      #
 # The GnomeTerminal script class.                                      #
@@ -251,9 +253,9 @@ class Script(default.Script):
             # We might need to echo this if it is a single character.
             #
             speakThis = speakThis \
-                or ((settings.enableEchoByCharacter \
-                     or (settings.enableKeyEcho \
-                         and settings.enablePrintableKeys)) \
+                or ((_settingsManager.getSetting('enableEchoByCharacter') \
+                     or (_settingsManager.getSetting('enableKeyEcho') \
+                     and _settingsManager.getSetting('enablePrintableKeys'))) \
                     and text \
                     and event.source.getRole() \
                         != pyatspi.ROLE_PASSWORD_TEXT \
@@ -265,7 +267,7 @@ class Script(default.Script):
             else:
                 speech.speak(text)
 
-        if settings.enableEchoByWord \
+        if _settingsManager.getSetting('enableEchoByWord') \
            and self.utilities.isWordDelimiter(text.decode("UTF-8")[-1:]):
             if matchFound:
                 self.echoPreviousWord(event.source)
diff --git a/src/orca/scripts/apps/soffice/braille_generator.py b/src/orca/scripts/apps/soffice/braille_generator.py
index d932bd6..c1caa31 100644
--- a/src/orca/scripts/apps/soffice/braille_generator.py
+++ b/src/orca/scripts/apps/soffice/braille_generator.py
@@ -29,7 +29,9 @@ import pyatspi
 
 import orca.braille as braille
 import orca.braille_generator as braille_generator
-import orca.settings as settings
+import orca.orca as orca
+
+_settingsManager = getattr(orca, '_settingsManager')
 
 class BrailleGenerator(braille_generator.BrailleGenerator):
 
@@ -162,8 +164,9 @@ class BrailleGenerator(braille_generator.BrailleGenerator):
                 for child in obj:
                     cellResult = self._generateRealTableCell(child, **args)
                     if cellResult and result and self._mode == 'braille':
-                        result.append(braille.Region(
-                                settings.brailleTableCellDelimiter))
+                        delimiter = _settingsManager.getSetting(
+                            'brailleTableCellDelimiter')
+                        result.append(braille.Region(delimiter))
                     result.extend(cellResult)
         return result
 
@@ -186,7 +189,7 @@ class BrailleGenerator(braille_generator.BrailleGenerator):
             #
             parent = obj.parent
             parentTable = parent.queryTable()
-            if settings.readTableCellRow and parentTable:
+            if _settingsManager.getSetting('readTableCellRow') and parentTable:
                 index = self._script.utilities.cellIndex(obj)
                 row = parentTable.getRowAtIndex(index)
                 column = parentTable.getColumnAtIndex(index)
@@ -216,8 +219,9 @@ class BrailleGenerator(braille_generator.BrailleGenerator):
                                                                      **args)
                             if cellResult and result \
                                and self._mode == 'braille':
-                                result.append(braille.Region(
-                                        settings.brailleTableCellDelimiter))
+                                delimiter = _settingsManager.getSetting(
+                                    'brailleTableCellDelimiter')
+                                result.append(braille.Region(delimiter))
                             result.extend(cellResult)
                 else:
                     result.extend(self._generateRealTableCell(obj, **args))
diff --git a/src/orca/scripts/apps/soffice/script.py b/src/orca/scripts/apps/soffice/script.py
index 26e1b76..b77daed 100644
--- a/src/orca/scripts/apps/soffice/script.py
+++ b/src/orca/scripts/apps/soffice/script.py
@@ -58,6 +58,8 @@ from structural_navigation import StructuralNavigation
 from script_utilities import Utilities
 import script_settings
 
+_settingsManager = getattr(orca, '_settingsManager')
+
 class Script(default.Script):
 
     def __init__(self, app):
@@ -119,48 +121,42 @@ class Script(default.Script):
 
     def activate(self):
         """Called when this script is activated."""
-        self.savedreadTableCellRow = settings.readTableCellRow
-        settings.readTableCellRow = False
+        self.savedreadTableCellRow = \
+            _settingsManager.getSetting('readTableCellRow')
+        _settingsManager.setSetting('readTableCellRow', False)
 
         self.savedEnabledBrailledTextAttributes = \
-            settings.enabledBrailledTextAttributes
+            _settingsManager.getSetting('enabledBrailledTextAttributes')
 
         self.savedEnabledSpokenTextAttributes = \
-            settings.enabledSpokenTextAttributes
+            _settingsManager.getSetting('enabledSpokenTextAttributes')
 
         # Account for the differences in how OOo expresses indent, 
         # strikethrough, and margins.
         #
-        settings.allTextAttributes = \
-            settings.allTextAttributes.replace(
-            "margin:;",
-            "margin:0mm;")
-
-        settings.enabledBrailledTextAttributes = \
-            settings.enabledBrailledTextAttributes.replace(
-            "strikethrough:false;",
-            "strikethrough:none;")
-        settings.enabledSpokenTextAttributes = \
-            settings.enabledSpokenTextAttributes.replace(
-            "strikethrough:false;",
-            "strikethrough:none;")
-
-        settings.enabledBrailledTextAttributes = \
-            settings.enabledBrailledTextAttributes.replace(
-            "indent:0;",
-            "indent:0mm;")
-        settings.enabledSpokenTextAttributes = \
-            settings.enabledSpokenTextAttributes.replace(
-            "indent:0;",
-            "indent:0mm;")
+        attributes = _settingsManager.getSetting('allTextAttributes')
+        attributes.replace("margin:;", "margin:0mm;")
+        _settingsManager.setSetting('allTextAttributes', attributes)
+
+        attributes = \
+            _settingsManager.getSetting('enabledBrailledTextAttributes')
+        attributes.replace("strikethrough:false;", "strikethrough:none;")
+        attributes.replace("indent:0;", "indent:0mm;")
+        _settingsManager.setSetting('enabledBrailledTextAttributes', attributes)
+
+        attributes = _settingsManager.getSetting('enabledSpokenTextAttributes')
+        attributes.replace("strikethrough:false;", "strikethrough:none;")
+        attributes.replace("indent:0;", "indent:0mm;")
+        _settingsManager.setSetting('enabledSpokenTextAttributes', attributes)
 
     def deactivate(self):
         """Called when this script is deactivated."""
-        settings.readTableCellRow = self.savedreadTableCellRow
-        settings.enabledBrailledTextAttributes = \
-            self.savedEnabledBrailledTextAttributes
-        settings.enabledSpokenTextAttributes = \
-            self.savedEnabledSpokenTextAttributes
+        _settingsManager.setSetting('readTableCellRow',
+                                    self.savedreadTableCellRow)
+        _settingsManager.setSetting('enabledBrailledTextAttributes',
+                                    self.savedEnabledBrailledTextAttributes)
+        _settingsManager.setSetting('enabledSpokenTextAttributes',
+                                    self.savedEnabledSpokenTextAttributes)
 
     def getListeners(self):
         """Sets up the AT-SPI event listeners for this script.
@@ -346,8 +342,9 @@ class Script(default.Script):
         gtk.Widget.show(self.speakCellCoordinatesCheckButton)
         gtk.Box.pack_start(tableVBox, self.speakCellCoordinatesCheckButton,
                            False, False, 0)
-        gtk.ToggleButton.set_active(self.speakCellCoordinatesCheckButton,
-                                    settings.speakCellCoordinates)
+        gtk.ToggleButton.set_active(
+            self.speakCellCoordinatesCheckButton,
+            _settingsManager.getSetting('speakCellCoordinates'))
 
         # Translators: this is an option to tell Orca whether or not it
         # should speak the span size of a table cell (e.g., how many
@@ -358,8 +355,9 @@ class Script(default.Script):
         gtk.Widget.show(self.speakCellSpanCheckButton)
         gtk.Box.pack_start(tableVBox, self.speakCellSpanCheckButton,
                            False, False, 0)
-        gtk.ToggleButton.set_active(self.speakCellSpanCheckButton,
-                                    settings.speakCellSpan)
+        gtk.ToggleButton.set_active(
+            self.speakCellSpanCheckButton,
+            _settingsManager.getSetting('speakCellSpan'))
 
         # Translators: this is an option for whether or not to speak
         # the header of a table cell in document content.
@@ -369,8 +367,9 @@ class Script(default.Script):
         gtk.Widget.show(self.speakCellHeadersCheckButton)
         gtk.Box.pack_start(tableVBox, self.speakCellHeadersCheckButton,
                            False, False, 0)
-        gtk.ToggleButton.set_active(self.speakCellHeadersCheckButton,
-                                    settings.speakCellHeaders)
+        gtk.ToggleButton.set_active(
+            self.speakCellHeadersCheckButton,
+            _settingsManager.getSetting('speakCellHeaders'))
 
         # Translators: this is an option to allow users to skip over
         # empty/blank cells when navigating tables in document content.
@@ -380,8 +379,9 @@ class Script(default.Script):
         gtk.Widget.show(self.skipBlankCellsCheckButton)
         gtk.Box.pack_start(tableVBox, self.skipBlankCellsCheckButton,
                            False, False, 0)
-        gtk.ToggleButton.set_active(self.skipBlankCellsCheckButton,
-                                    settings.skipBlankCells)
+        gtk.ToggleButton.set_active(
+                self.skipBlankCellsCheckButton,
+                _settingsManager.getSetting('skipBlankCells'))
 
         # Translators: this is the title of a panel containing options
         # for specifying how to navigate tables in document content.
@@ -405,27 +405,25 @@ class Script(default.Script):
         prefix = "orca.scripts.apps.soffice.script_settings"
 
         script_settings.speakSpreadsheetCoordinates = \
-                 self.speakSpreadsheetCoordinatesCheckButton.get_active()
+            self.speakSpreadsheetCoordinatesCheckButton.get_active()
         prefs.writelines("%s.speakSpreadsheetCoordinates = %s\n" % \
-                         (prefix, script_settings.speakSpreadsheetCoordinates))
+                        (prefix, script_settings.speakSpreadsheetCoordinates))
 
-        settings.speakCellCoordinates = \
-                 self.speakCellCoordinatesCheckButton.get_active()
-        prefs.writelines("orca.settings.speakCellCoordinates = %s\n" % \
-                         settings.speakCellCoordinates)
+        value = self.speakCellCoordinatesCheckButton.get_active()
+        _settingsManager.setSetting('speakCellCoordinates', value)            
+        prefs.writelines("orca.settings.speakCellCoordinates = %s\n" % value)
 
-        settings.speakCellSpan = self.speakCellSpanCheckButton.get_active()
-        prefs.writelines("orca.settings.speakCellSpan = %s\n" % \
-                         settings.speakCellSpan)
+        value = self.speakCellSpanCheckButton.get_active()
+        _settingsManager.setSetting('speakCellSpan', value)
+        prefs.writelines("orca.settings.speakCellSpan = %s\n" % value)
 
-        settings.speakCellHeaders = \
-                self.speakCellHeadersCheckButton.get_active()
-        prefs.writelines("orca.settings.speakCellHeaders = %s\n" % \
-                         settings.speakCellHeaders)
+        value = self.speakCellHeadersCheckButton.get_active()
+        _settingsManager.setSetting('speakCellHeaders', value)
+        prefs.writelines("orca.settings.speakCellHeaders = %s\n" % value)
 
-        settings.skipBlankCells = self.skipBlankCellsCheckButton.get_active()
-        prefs.writelines("orca.settings.skipBlankCells = %s\n" % \
-                         settings.skipBlankCells)
+        value = self.skipBlankCellsCheckButton.get_active()
+        _settingsManager.setSetting('skipBlankCells', value)
+        prefs.writelines("orca.settings.skipBlankCells = %s\n" % value)
 
     def getAppState(self):
         """Returns an object that can be passed to setAppState.  This
@@ -762,7 +760,7 @@ class Script(default.Script):
         self.updateBraille(cell)
         speech.speak(self.speechGenerator.generateSpeech(cell))
 
-        if not settings.readTableCellRow:
+        if not _settingsManager.getSetting('readTableCellRow'):
             self.speakCellName(cell.name)
 
         try:
@@ -810,7 +808,7 @@ class Script(default.Script):
                     debug.println(self.debugLevel,
                         "StarOffice.speakInputLine: contents: %s" % inputLine)
                     self.displayBrailleMessage(inputLine, \
-                      flashTime=settings.brailleFlashTime)
+                      flashTime=_settingsManager.getSetting('brailleFlashTime'))
                     speech.speak(inputLine)
             except NotImplementedError:
                 pass
@@ -1131,7 +1129,7 @@ class Script(default.Script):
         - endOffset: the end offset for this word
         """
 
-        voices = settings.voices
+        voices = _settingsManager.getSetting('voices')
 
         for i in range(startOffset, endOffset):
             if self.utilities.linkIndex(obj, i) >= 0:
@@ -2135,7 +2133,7 @@ class Script(default.Script):
                           pyatspi.ROLE_ROOT_PANE,
                           pyatspi.ROLE_FRAME,
                           pyatspi.ROLE_APPLICATION]
-            if settings.enableEchoByWord and \
+            if _settingsManager.getSetting('enableEchoByWord') and \
                (self.utilities.hasMatchingHierarchy(event.source, rolesList) or
                 self.utilities.hasMatchingHierarchy(event.source, rolesList1)):
                 keyString, mods = self.utilities.lastKeyAndModifiers()
@@ -2234,7 +2232,7 @@ class Script(default.Script):
         # If this is a blank line, announce it if the user requested
         # that blank lines be spoken.
         if line[1] == 0 and line[2] == 0:
-            return settings.speakBlankLines
+            return _settingsManager.getSetting('speakBlankLines')
 
     def onTextInserted(self, event):
         """Called whenever text is inserted into an object.  Overridden here
diff --git a/src/orca/scripts/apps/soffice/speech_generator.py b/src/orca/scripts/apps/soffice/speech_generator.py
index ef6c620..e458690 100644
--- a/src/orca/scripts/apps/soffice/speech_generator.py
+++ b/src/orca/scripts/apps/soffice/speech_generator.py
@@ -27,13 +27,14 @@ __license__   = "LGPL"
 
 import pyatspi
 
+import orca.orca as orca
 import orca.speech_generator as speech_generator
-import orca.settings as settings
 
 from orca.orca_i18n import ngettext # for ngettext support
 from orca.orca_i18n import _ # for gettext support
 
 import script_settings
+_settingsManager = getattr(orca, '_settingsManager')
 
 class SpeechGenerator(speech_generator.SpeechGenerator):
 
@@ -178,7 +179,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
         if that description is different from that of the name and
         label.
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -378,7 +379,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
         Returns an indication of how many characters are greater than the size
         of the spread sheet cell, or None if the message fits.
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -488,7 +489,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
 
     def _generateTableCellRow(self, obj, **args):
         """Get the speech for a table cell row or a single table cell
-        if settings.readTableCellRow is False. If this isn't inside a
+        if _settingsManager.getSetting('readTableCellRow') is False. If this isn't inside a
         spread sheet, just return the utterances returned by the default
         table cell speech handler.
 
@@ -499,7 +500,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
         """
         result = []
         if self._script.isSpreadSheetCell(obj):
-            if settings.readTableCellRow:
+            if _settingsManager.getSetting('readTableCellRow'):
                 parent = obj.parent
                 parentTable = parent.queryTable()
                 index = self._script.utilities.cellIndex(obj)
@@ -535,7 +536,8 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
             result.extend(
                 speech_generator.SpeechGenerator._generateTableCellRow(
                     self, obj, **args))
-            if not len(result) and settings.speakBlankLines:
+            if not len(result) \
+               and _settingsManager.getSetting('speakBlankLines'):
                 # Translators: "blank" is a short word to mean the
                 # user has navigated to an empty line.
                 #
diff --git a/src/orca/scripts/apps/yelp/script.py b/src/orca/scripts/apps/yelp/script.py
index 9f76b8a..f92c1d6 100644
--- a/src/orca/scripts/apps/yelp/script.py
+++ b/src/orca/scripts/apps/yelp/script.py
@@ -29,7 +29,6 @@ import gtk
 import pyatspi
 
 import orca.orca as orca
-import orca.settings as settings
 import orca.speech as speech
 
 import orca.scripts.toolkits.Gecko as Gecko
@@ -37,6 +36,8 @@ import orca.scripts.toolkits.Gecko as Gecko
 import script_settings
 from script_utilities import Utilities
 
+_settingsManager = getattr(orca, '_settingsManager')
+
 class Script(Gecko.Script):
 
     def __init__(self, app):
@@ -209,7 +210,7 @@ class Script(Gecko.Script):
                 elif not Gecko.script_settings.sayAllOnLoad:
                     self.speakContents(\
                         self.getLineContentsAtOffset(obj, characterOffset))
-                elif settings.enableSpeech:
+                elif _settingsManager.getSetting('enableSpeech'):
                     self.sayAll(None)
 
             return
diff --git a/src/orca/scripts/toolkits/Gecko/script.py b/src/orca/scripts/toolkits/Gecko/script.py
index 5932421..006fcae 100644
--- a/src/orca/scripts/toolkits/Gecko/script.py
+++ b/src/orca/scripts/toolkits/Gecko/script.py
@@ -79,6 +79,8 @@ from orca.orca_i18n import _
 from orca.speech_generator import Pause
 from orca.acss import ACSS
 
+_settingsManager = getattr(orca, '_settingsManager')
+
 ########################################################################
 #                                                                      #
 # Script                                                               #
@@ -284,25 +286,27 @@ class Script(default.Script):
     def activate(self):
         """Called when this script is activated."""
         self.savedEnabledBrailledTextAttributes = \
-            settings.enabledBrailledTextAttributes
-        settings.enabledBrailledTextAttributes = \
-            self.enabledBrailledTextAttributes
+            _settingsManager.getSetting('enabledBrailledTextAttributes')
+        _settingsManager.setSetting(
+            'enabledBrailledTextAttributes', self.enabledBrailledTextAttributes)
 
         self.savedEnabledSpokenTextAttributes = \
-            settings.enabledSpokenTextAttributes
-        settings.enabledSpokenTextAttributes = \
-            self.enabledSpokenTextAttributes
+            _settingsManager.getSetting('enabledSpokenTextAttributes')
+        _settingsManager.setSetting(
+            'enabledSpokenTextAttributes', self.enabledSpokenTextAttributes)
 
-        self.savedAllTextAttributes = settings.allTextAttributes
-        settings.allTextAttributes = self.allTextAttributes
+        self.savedAllTextAttributes = \
+            _settingsManager.getSetting('allTextAttributes')
+        _settingsManager.getSetting('allTextAttributes', self.allTextAttributes)
 
     def deactivate(self):
         """Called when this script is deactivated."""
-        settings.enabledBrailledTextAttributes = \
-            self.savedEnabledBrailledTextAttributes
-        settings.enabledSpokenTextAttributes = \
-            self.savedEnabledSpokenTextAttributes
-        settings.allTextAttributes = self.savedAllTextAttributes
+        _settingsManager.setSetting('enabledBrailledTextAttributes',
+                                    self.savedEnabledBrailledTextAttributes)
+        _settingsManager.setSetting('enabledSpokenTextAttributes',
+                                    self.savedEnabledSpokenTextAttributes)
+        _settingsManager.setSetting('allTextAttributes',
+                                    self.savedAllTextAttributes)
 
     def getBookmarks(self):
         """Returns the "bookmarks" class for this script.
@@ -635,8 +639,8 @@ class Script(default.Script):
         # load common keymap
         keyBindings.load(keymaps.commonKeymap, self.inputEventHandlers)
 
-        if orca.settings.keyboardLayout == \
-          orca.settings.GENERAL_KEYBOARD_LAYOUT_DESKTOP:
+        if _settingsManager.getSetting('keyboardLayout') == \
+                orca.settings.GENERAL_KEYBOARD_LAYOUT_DESKTOP:
             keyBindings.load(keymaps.desktopKeymap, self.inputEventHandlers)
         else:
             keyBindings.load(keymaps.laptopKeymap, self.inputEventHandlers)
@@ -780,8 +784,9 @@ class Script(default.Script):
         gtk.Widget.show(self.speakCellCoordinatesCheckButton)
         gtk.Box.pack_start(tableVBox, self.speakCellCoordinatesCheckButton,
                            False, False, 0)
-        gtk.ToggleButton.set_active(self.speakCellCoordinatesCheckButton,
-                                    settings.speakCellCoordinates)
+        gtk.ToggleButton.set_active(
+            self.speakCellCoordinatesCheckButton,
+            _settingsManager.getSetting('speakCellCoordinates'))
 
         # Translators: this is an option to tell Orca whether or not it
         # should speak the span size of a table cell (e.g., how many
@@ -792,8 +797,9 @@ class Script(default.Script):
         gtk.Widget.show(self.speakCellSpanCheckButton)
         gtk.Box.pack_start(tableVBox, self.speakCellSpanCheckButton,
                            False, False, 0)
-        gtk.ToggleButton.set_active(self.speakCellSpanCheckButton,
-                                    settings.speakCellSpan)
+        gtk.ToggleButton.set_active(
+            self.speakCellSpanCheckButton,
+            _settingsManager.getSetting('speakCellSpan'))
 
         # Translators: this is an option for whether or not to speak
         # the header of a table cell in document content.
@@ -803,8 +809,9 @@ class Script(default.Script):
         gtk.Widget.show(self.speakCellHeadersCheckButton)
         gtk.Box.pack_start(tableVBox, self.speakCellHeadersCheckButton,
                            False, False, 0)
-        gtk.ToggleButton.set_active(self.speakCellHeadersCheckButton,
-                                    settings.speakCellHeaders)
+        gtk.ToggleButton.set_active(
+            self.speakCellHeadersCheckButton,
+            _settingsManager.getSetting('speakCellHeaders'))
 
         # Translators: this is an option to allow users to skip over
         # empty/blank cells when navigating tables in document content.
@@ -814,8 +821,9 @@ class Script(default.Script):
         gtk.Widget.show(self.skipBlankCellsCheckButton)
         gtk.Box.pack_start(tableVBox, self.skipBlankCellsCheckButton,
                            False, False, 0)
-        gtk.ToggleButton.set_active(self.skipBlankCellsCheckButton,
-                                    settings.skipBlankCells)
+        gtk.ToggleButton.set_active(
+            self.skipBlankCellsCheckButton,
+            _settingsManager.getSetting('skipBlankCells'))
 
         # Translators: this is the title of a panel containing options
         # for specifying how to navigate tables in document content.
@@ -960,19 +968,19 @@ class Script(default.Script):
         # 
         value = self.speakCellCoordinatesCheckButton.get_active()
         prefs.writelines("orca.settings.speakCellCoordinates = %s\n" % value)
-        settings.speakCellCoordinates = value
+        _settingsManager.setSetting('speakCellCoordinates', value)
 
         value = self.speakCellSpanCheckButton.get_active()
         prefs.writelines("orca.settings.speakCellSpan = %s\n" % value)
-        settings.speakCellSpan = value
+        _settingsManager.setSetting('speakCellSpan', value)
 
         value = self.speakCellHeadersCheckButton.get_active()
         prefs.writelines("orca.settings.speakCellHeaders = %s\n" % value)
-        settings.speakCellHeaders = value
+        _settingsManager.setSetting('speakCellHeaders', value)
 
         value = self.skipBlankCellsCheckButton.get_active()
         prefs.writelines("orca.settings.skipBlankCells = %s\n" % value)
-        settings.skipBlankCells = value
+        _settingsManager.setSetting('skipBlankCells', value)
 
     def getAppState(self):
         """Returns an object that can be passed to setAppState.  This
@@ -1020,7 +1028,7 @@ class Script(default.Script):
         # we want to allow to control its own destiny).]]]
 
         user_bindings = None
-        user_bindings_map = settings.keyBindingsMap
+        user_bindings_map = _settingsManager.getSetting('keyBindingsMap')
         if self.__module__ in user_bindings_map:
             user_bindings = user_bindings_map[self.__module__]
         elif "default" in user_bindings_map:
@@ -1063,8 +1071,8 @@ class Script(default.Script):
 
         # Determine the correct "say all by" mode to use.
         #
-        sayAllBySentence = \
-                      (settings.sayAllStyle == settings.SAYALL_STYLE_SENTENCE)
+        sayAllStyle = _settingsManager.getSetting('sayAllStyle')
+        sayAllBySentence = sayAllStyle == settings.SAYALL_STYLE_SENTENCE
 
         [obj, characterOffset] = self.getCaretContext()
         if sayAllBySentence:
@@ -1482,8 +1490,8 @@ class Script(default.Script):
                                           pyatspi.ROLE_FRAME]:
             utterances = []
             utterances.append(rolenames.getSpeechForRoleName(event.any_data))
-            if settings.speechVerbosityLevel == \
-                    settings.VERBOSITY_LEVEL_VERBOSE:
+            verbosity = _settingsManager.getSetting('speechVerbosityLevel')
+            if verbosity == settings.VERBOSITY_LEVEL_VERBOSE:
                 utterances.extend(
                     self.speechGenerator.generateSpeech(event.any_data))
             speech.speak(utterances)
@@ -1707,8 +1715,8 @@ class Script(default.Script):
                 # or if the user forced it to appear with (Alt+)Down Arrow.
                 #
                 if self._autocompleteVisible:
-                    speakIt = (settings.speechVerbosityLevel == \
-                               settings.VERBOSITY_LEVEL_VERBOSE)
+                    level = _settingsManager.getSetting('speechVerbosityLevel')
+                    speakIt = level == settings.VERBOSITY_LEVEL_VERBOSE
                     if not speakIt \
                        and isinstance(orca_state.lastInputEvent, 
                                       input_event.KeyboardEvent):
@@ -1817,7 +1825,7 @@ class Script(default.Script):
                         self.speakContents(\
                             self.getLineContentsAtOffset(obj,
                                                          characterOffset))
-                    elif settings.enableSpeech:
+                    elif _settingsManager.getSetting('enableSpeech'):
                         self.sayAll(None)
 
             return
@@ -2885,7 +2893,7 @@ class Script(default.Script):
         # regions.  We will handle everything else as a live region.  We
         # will do the cheap tests first
         if self._loadingDocumentContent \
-              or not  settings.inferLiveRegions:
+           or not _settingsManager.getSetting('inferLiveRegions'):
             return False
 
         # Ideally, we would like to do a inDocumentContent() call to filter out
@@ -2921,7 +2929,8 @@ class Script(default.Script):
                        and not 'tooltip' in attrList:
                         return False
                     # Only present tooltips when user wants them presented
-                    elif 'tooltip' in attrList and not settings.presentToolTips:
+                    elif 'tooltip' in attrList \
+                         and not _settingsManager.getSetting('presentToolTips'):
                         return False
             else:
                 # Some alerts have been seen without the :system postfix.
@@ -3668,7 +3677,7 @@ class Script(default.Script):
         and unvisited links on the page containing obj.
         """
 
-        if settings.useCollection:
+        if _settingsManager.getSetting('useCollection'):
             try:
                 summary = self._collectionPageSummary()
             except:
@@ -5339,7 +5348,7 @@ class Script(default.Script):
                 clumped.append([element, acss])
 
         if (len(clumped) == 1) and (clumped[0][0] == "\n"):
-            if settings.speakBlankLines:
+            if _settingsManager.getSetting('speakBlankLines'):
                 # Translators: "blank" is a short word to mean the
                 # user has navigated to an empty line.
                 #
@@ -6156,7 +6165,7 @@ class Script(default.Script):
 
     def advanceLivePoliteness(self, inputEvent):
         """Advances live region politeness level."""
-        if settings.inferLiveRegions:
+        if _settingsManager.getSetting('inferLiveRegions'):
             self.liveMngr.advancePoliteness(orca_state.locusOfFocus)
         else:
             # Translators: this announces to the user that live region
@@ -6165,14 +6174,14 @@ class Script(default.Script):
             self.presentMessage(_("Live region support is off"))
 
     def monitorLiveRegions(self, inputEvent):
-        if not settings.inferLiveRegions:
-            settings.inferLiveRegions = True
+        if not _settingsManager.getSetting('inferLiveRegions'):
+            _settingsManager.setSetting('inferLiveRegions', True)
             # Translators: this announces to the user that live region
             # are being monitored.
             #
             self.presentMessage(_("Live regions monitoring on"))
         else:
-            settings.inferLiveRegions = False
+            _settingsManager.setSetting('inferLiveRegions', False)
             # Translators: this announces to the user that live region
             # are not being monitored.
             #
@@ -6180,7 +6189,7 @@ class Script(default.Script):
             self.presentMessage(_("Live regions monitoring off"))
 
     def setLivePolitenessOff(self, inputEvent):
-        if settings.inferLiveRegions:
+        if _settingsManager.getSetting('inferLiveRegions'):
             self.liveMngr.setLivePolitenessOff()
         else:
             # Translators: this announces to the user that live region
@@ -6189,7 +6198,7 @@ class Script(default.Script):
             self.presentMessage(_("Live region support is off"))
 
     def reviewLiveAnnouncement(self, inputEvent):
-        if settings.inferLiveRegions:
+        if _settingsManager.getSetting('inferLiveRegions'):
             self.liveMngr.reviewLiveAnnouncement( \
                                     int(inputEvent.event_string[1:]))
         else:
diff --git a/src/orca/scripts/toolkits/Gecko/speech_generator.py b/src/orca/scripts/toolkits/Gecko/speech_generator.py
index 6018792..81745e4 100644
--- a/src/orca/scripts/toolkits/Gecko/speech_generator.py
+++ b/src/orca/scripts/toolkits/Gecko/speech_generator.py
@@ -31,13 +31,15 @@ __license__   = "LGPL"
 
 import pyatspi
 
+import orca.orca as orca
 import orca.rolenames as rolenames
-import orca.settings as settings
 import orca.speech_generator as speech_generator
 
 from orca.orca_i18n import _
 from orca.orca_i18n import ngettext # for ngettext support
 
+_settingsManager = getattr(orca, '_settingsManager')
+
 ########################################################################
 #                                                                      #
 # Custom SpeechGenerator                                               #
@@ -286,7 +288,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
         return result
 
     def _generateNumberOfChildren(self, obj, **args):
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -420,7 +422,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
             # Finally add the role if it's not among the roles we don't
             # wish to speak.
             #
-            if not settings.onlySpeakDisplayedText:
+            if not _settingsManager.getSetting('onlySpeakDisplayedText'):
                 acss = self.voice(speech_generator.SYSTEM)
                 if not (role in dontSpeakRoles) and len(newResult):
                     roleInfo = rolenames.getSpeechForRoleName(parent)
diff --git a/src/orca/scripts/toolkits/J2SE-access-bridge/speech_generator.py b/src/orca/scripts/toolkits/J2SE-access-bridge/speech_generator.py
index 68fac1a..2d70557 100644
--- a/src/orca/scripts/toolkits/J2SE-access-bridge/speech_generator.py
+++ b/src/orca/scripts/toolkits/J2SE-access-bridge/speech_generator.py
@@ -27,11 +27,13 @@ __license__   = "LGPL"
 
 import pyatspi
 
-import orca.settings as settings
+import orca.orca as orca
 import orca.speech_generator as speech_generator
 
 from orca.orca_i18n import ngettext
 
+_settingsManager = getattr(orca, '_settingsManager')
+
 ########################################################################
 #                                                                      #
 # Speech Generator                                                     #
@@ -84,7 +86,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
         specifications) that represents the number of children the
         object has."""
 
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -110,7 +112,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
         object in a list.
         """
 
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         listObj = None
@@ -142,7 +144,8 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
             if nextName == name:
                 position = index
 
-        if (settings.enablePositionSpeaking or args.get('forceList', False)) \
+        if (_settingsManager.getSetting('enablePositionSpeaking') \
+            or args.get('forceList', False)) \
            and position >= 0:
             result.append(self._script.formatting.getString(
                               mode='speech', stringType='groupindex') \
diff --git a/src/orca/settings.py b/src/orca/settings.py
index 616d4b1..9c1e8e4 100644
--- a/src/orca/settings.py
+++ b/src/orca/settings.py
@@ -173,6 +173,7 @@ userCustomizableSettings = [
     "enabledBrailledTextAttributes",
     "textAttributesBrailleIndicator",
     "enableProgressBarUpdates",
+    "profile",
     "progressBarUpdateInterval",
     "progressBarVerbosity",
     "enableContractedBraille",
@@ -199,8 +200,17 @@ userCustomizableSettings = [
     "messageVerbosityLevel",
     "presentDateFormat",
     "presentTimeFormat",
+    "activeProfile",
+    "startingProfile",
+    "firstStart"
 ]
 
+excludeKeys = ["pronunciations",
+               "keybindings",
+               "startingProfile",
+               "activeProfile",
+               "firstStart"]
+
 # The name of the module that hold the user interface for the main window
 # for Orca. This module is expected to have two methods, showMainUI and
 # hideMainUI, which will show and hide the main window GUI.
@@ -230,6 +240,16 @@ findModule = "orca_gui_find"
 #
 splashModule = "orca_gui_splash"
 
+# Profiles
+#
+startingProfile = ['Default', 'default']
+activeProfile = ['Default', 'default']
+profile = ['Default', 'default']
+
+# First start?
+#
+firstStart = True
+
 # A list of keys that can serve as the Orca modifier key.  The list is
 # so we can provide better cross platform support (e.g., Sun keyboard
 # vs. PC-104 keyboard layouts).  When any of these keys is pressed,
@@ -384,6 +404,14 @@ UPPERCASE_VOICE         = "uppercase"
 HYPERLINK_VOICE         = "hyperlink"
 SYSTEM_VOICE            = "system"
 
+voicesKeys = {
+"DEFAULT_VOICE"     : "default",
+"UPPERCASE_VOICE"   : "uppercase",
+"HYPERLINK_VOICE"   : "hyperlink",
+"SYSTEM_VOICE"      : "system"
+}
+
+
 voices = {
     DEFAULT_VOICE   : ACSS({}),
     UPPERCASE_VOICE : ACSS({ACSS.AVERAGE_PITCH : 5.6}),
@@ -960,23 +988,6 @@ chatAnnounceBuddyTyping = False
 #
 chatRoomHistories = False
 
-# Obtain/set information regarding whether accessibility is enabled
-# or not.
-#
-def isAccessibilityEnabled():
-    try:
-        return gconfClient.get_bool("/desktop/gnome/interface/accessibility") \
-            or gconfClient.get_bool("/desktop/gnome/interface/accessibility2")
-    except:
-        return False
-
-def setAccessibilityEnabled(enable):
-    try:
-        return gconfClient.set_bool("/desktop/gnome/interface/accessibility",
-                                    enable)
-    except:
-        return False
-
 # Obtain/set information regarding whether Orca is autostarted for this
 # user at login time.
 #
@@ -1024,7 +1035,10 @@ def setGKSUGrabDisabled(disable):
 # Allow for the customization of key bindings.
 #
 def overrideKeyBindings(script, keyBindings):
-    return keyBindings
+    import orca
+    _settingsManager = getattr(orca, '_settingsManager')
+
+    return _settingsManager.overrideKeyBindings(script, keyBindings)
 
 # Allow for user customization of pronunciations.
 #
diff --git a/src/orca/settings_manager.py b/src/orca/settings_manager.py
new file mode 100644
index 0000000..d033283
--- /dev/null
+++ b/src/orca/settings_manager.py
@@ -0,0 +1,519 @@
+# Orca
+#
+# Copyright 2010 Consorcio Fernando de los Rios.
+# Author: Javier Hernandez Antunez <jhernandez emergya es>
+# Author: Alejandro Leiva <aleiva emergya es>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
+# Boston MA  02110-1301 USA.
+
+"""Settings manager module. This will load/save user settings from a 
+defined settings backend."""
+
+__id__        = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2010 Consorcio Fernando de los Rios."
+__license__   = "LGPL"
+
+import os
+import imp
+from yaml import load
+
+import debug
+from keybindings import KeyBinding
+import settings
+
+try:
+    import gconf
+    gconfClient = gconf.client_get_default()
+except:
+    gconfClient = None
+
+class SettingsManager(object):
+    """Settings backend manager. This class manages orca user's settings
+    using different backends"""
+    _instance = None
+
+    def __new__(cls, *args, **kwargs):
+        if '__instance' not in vars(cls):
+            cls.__instance = object.__new__(cls, *args, **kwargs)
+        return cls.__instance
+
+    def __init__(self, backend='yaml'):
+        """Initialize a SettingsManager Object.
+        If backend isn't defined then uses default backend, in this
+        case gconf-backend.
+        backend parameter can use the follow values:
+        backend='gconf'
+        backend='yaml'
+        """
+
+        self.backendModule = None
+        self._backend = None
+        self.profile = None
+        self.backendName = backend
+
+        # Dictionaries for store the default values
+        # The keys and values are defined at orca.settings
+        #
+        ## self.defaultGeneral contain some constants names as values
+        self.defaultGeneral = {}
+        ## self.defaultGeneralValues contain the actual values, no constants
+        self.defaultGeneralValues = {}
+        self.defaultPronunciations = {}
+        self.defaultKeybindings = {}
+
+        # Dictionaries that store the key:value pairs which values are
+        # different from the current profile and the default ones
+        #
+        self.profileGeneral = {}
+        self.profilePronunciations = {}
+        self.profileKeybindings = {}
+
+        # Dictionaries that store the current settings.
+        # They are result to overwrite the default values with
+        # the ones from the current active profile
+        self.general = {}
+        self.pronunciations = {}
+        self.keybindings = {}
+
+        if not self._loadBackend():
+            raise Exception('SettingsManager::_loadBackend fails.')
+
+        self.customizedSettings = {}
+        self._customizationCompleted = False
+
+        # Load the backend and the default values
+        self._backend = self.backendModule.Backend()
+        self._setDefaultGeneral()
+        self._setDefaultPronunciations()
+        self._setDefaultKeybindings()
+        self.defaultGeneralValues = getRealValues(self.defaultGeneral)
+        self.general = self.defaultGeneralValues.copy()
+        if not self.isFirstStart():
+            self.general.update(self._backend.getGeneral())
+        self.pronunciations = self.defaultPronunciations.copy()
+        self.keybindings = self.defaultKeybindings.copy()
+
+        # If this is the first time we launch Orca, there is no user settings
+        # yet, so we need to create the user config directories and store the
+        # initial default settings
+        #
+        if self.isFirstStart():
+            self._createDefaults()
+
+        # Set the active profile and load its stored settings
+        if self.profile is None:
+            self.profile = self.general.get('startingProfile')[1]
+        self.setProfile(self.profile)
+
+    def _loadBackend(self):
+        """Load specific backend for manage user settings"""
+
+        try:
+            backend = 'backends.%s_backend' % self.backendName
+            self.backendModule = __import__(backend, globals(), locals(),
+                                            backend, -1)
+            return True
+        except:
+            return False
+
+    def _createDefaults(self):
+        """Let the active backend to create the initial structure
+        for storing the settings and save the default ones from
+        orca.settings"""
+        def _createDir(dirName):
+            if not os.path.isdir(dirName):
+                os.mkdir(dirName)
+
+        # Set up the user's preferences directory
+        # ($XDG_DATA_HOME/orca by default).
+        #
+        orcaDir = settings.userPrefsDir
+        _createDir(orcaDir)
+
+        # Set up $XDG_DATA_HOME/orca/orca-scripts as a Python package
+        #
+        orcaScriptDir = os.path.join(orcaDir, "orca-scripts")
+        _createDir(orcaScriptDir)
+        initFile = os.path.join(orcaScriptDir, "__init__.py")
+        if not os.path.exists(initFile):
+            os.close(os.open(initFile, os.O_CREAT, 0700))
+
+        # Set up $XDG_DATA_HOME/orca/app-settings as a Python package.
+        #
+        orcaSettingsDir = os.path.join(orcaDir, "app-settings")
+        _createDir(orcaSettingsDir)
+        initFile = os.path.join(orcaSettingsDir, "__init__.py")
+        if not os.path.exists(initFile):
+            os.close(os.open(initFile, os.O_CREAT, 0700))
+
+        # Set up $XDG_DATA_HOME/orca/orca-customizations.py empty file and
+        # define orcaDir as a Python package.
+        initFile = os.path.join(orcaDir, "__init__.py")
+        if not os.path.exists(initFile):
+            os.close(os.open(initFile, os.O_CREAT, 0700))
+
+        userCustomFile = os.path.join(orcaDir, "orca-customizations.py")
+        if not os.path.exists(userCustomFile):
+            os.close(os.open(userCustomFile, os.O_CREAT, 0700))
+
+
+        self._backend.saveDefaultSettings(self.defaultGeneral,
+                                          self.defaultPronunciations,
+                                          self.defaultKeybindings)
+
+    def _setDefaultPronunciations(self):
+        """Get the pronunciations by default from orca.settings"""
+        self.defaultPronunciations = {}
+
+    def _setDefaultKeybindings(self):
+        """Get the keybindings by default from orca.settings"""
+        self.defaultKeybindings = {}
+
+    def _setDefaultGeneral(self):
+        """Get the general settings by default from orca.settings"""
+        self._getCustomizedSettings()
+        self.defaultGeneral = {}
+        for key in settings.userCustomizableSettings:
+            value = self.customizedSettings.get(key)
+            if value == None:
+                try:
+                    value = getattr(settings, key)
+                except:
+                    pass
+            self.defaultGeneral[key] = value
+
+    def _getCustomizedSettings(self):
+        if self._customizationCompleted:
+            return self.customizedSettings
+
+        originalSettings = {}
+        for key, value in settings.__dict__.items():
+            originalSettings[key] = value
+
+        self._customizationCompleted = self._loadUserCustomizations()
+
+        for key, value in originalSettings.items():
+            customValue = settings.__dict__.get(key)
+            if value != customValue:
+                self.customizedSettings[key] = customValue
+
+    def _loadUserCustomizations(self):
+        """Attempt to load the user's orca-customizations. Returns a boolean
+        indicating our success at doing so, where success is measured by the
+        likelihood that the results won't be different if we keep trying."""
+
+        success = False
+        pathList = [settings.userPrefsDir]
+        try:
+            msg = "Attempt to load orca-customizations "
+            (fileHnd, moduleName, desc) = \
+                imp.find_module("orca-customizations", pathList)
+            msg += "from %s " % moduleName
+            imp.load_module("orca-customizations", fileHnd, moduleName, desc)
+        except ImportError:
+            success = True
+            msg += "failed due to ImportError. Giving up."
+        except AttributeError:
+            msg += "failed due to AttributeError. Will try again."
+        else:
+            msg += "succeeded."
+            fileHnd.close()
+            success = True
+        debug.println(debug.LEVEL_SEVERE, msg)
+        return success
+
+    def setSetting(self, settingName, settingValue):
+        self._setSettingsRuntime({settingName:settingValue})
+
+    def getSetting(self, settingName):
+        return getattr(settings, settingName)
+
+    def _getGeneral(self, profile=None):
+        """Get from the active backend the general settings for
+        the current profile"""
+        if profile is None:
+            profile = self.profile
+        self.general = self._backend.getGeneral(profile)
+
+    def _getPronunciations(self, profile=None):
+        """Get from the active backend the pronunciations settings for
+        the current profile"""
+        if profile is None:
+            profile = self.profile
+        self.pronunciations = self._backend.getPronunciations(profile)
+
+    def _getKeybindings(self, profile=None):
+        """Get from the active backend the keybindings settings for
+        the current profile"""
+        if profile is None:
+            profile = self.profile
+        self.keybindings = self._backend.getKeybindings(profile)
+
+    def _loadProfileSettings(self, profile=None):
+        """Get from the active backend all the settings for the current
+        profile and store them in the object's attributes.
+        A profile can be passed as a parameter. This could be useful for
+        change from one profile to another."""
+        if profile is None:
+            profile = self.profile
+        self.profileGeneral = self.getGeneralSettings(profile) or {}
+        self.profilePronunciations = self.getPronunciations(profile) or {}
+        self.profileKeybindings = self.getKeybindings(profile) or {}
+
+    def _mergeSettings(self):
+        """Update the changed values on the profile settings
+        over the current and active settings"""
+        profileGeneral = getRealValues(self.profileGeneral) or {}
+        self.general.update(profileGeneral)
+        self.pronunciations.update(self.profilePronunciations)
+        self.keybindings.update(self.profileKeybindings)
+
+    def _enableAccessibility(self):
+        """Enables the GNOME accessibility flag.  Users need to log out and
+        then back in for this to take effect.
+
+        Returns True if an action was taken (i.e., accessibility was not
+        set prior to this call).
+        """
+
+        alreadyEnabled = self.isAccessibilityEnabled()
+        if not alreadyEnabled:
+            self.setAccessibility(True)
+
+        return not alreadyEnabled
+
+    def isAccessibilityEnabled(self):
+        try:
+            return gconfClient.get_bool(
+                "/desktop/gnome/interface/accessibility") \
+                or gconfClient.get_bool(
+                    "/desktop/gnome/interface/accessibility2")
+        except:
+            return False
+
+    def setAccessibility(self, enable):
+        try:
+            return gconfClient.set_bool(
+                "/desktop/gnome/interface/accessibility", enable)
+        except:
+            return False
+
+    def setStartingProfile(self, profile=None):
+        if profile is None:
+            profile = settings.profile
+        self._backend._setProfileKey('startingProfile', profile)
+
+    def setProfile(self, profile='default'):
+        """Set a specific profile as the active one.
+        Also the settings from that profile will be loading
+        and updated the current settings with them."""
+        self.profile = profile
+        self._loadProfileSettings(profile)
+        self._mergeSettings()
+        self._setSettingsRuntime(self.general)
+
+    def getPreferences(self, profile='default'):
+        general = self.getGeneralSettings(profile)
+        pronunciations = self.getPronunciations(profile)
+        keybindings = self.getKeybindings(profile)
+        return (general, pronunciations, keybindings)
+
+    def _setSettingsRuntime(self, settingsDict):
+        for key, value in settingsDict.items():
+            setattr(settings, str(key), value)
+        self._getCustomizedSettings()
+        for key, value in self.customizedSettings.items():
+            setattr(settings, str(key), value)
+
+    def getGeneralSettings(self, profile='default'):
+        """Return the current general settings.
+        Those settings comes from updating the default settings
+        with the profiles' ones"""
+        generalDict = self._backend.getGeneral(profile)
+        self._setSettingsRuntime(generalDict)
+        return generalDict
+
+    def getPronunciations(self, profile='default'):
+        """Return the current pronunciations settings.
+        Those settings comes from updating the default settings
+        with the profiles' ones"""
+        return self._backend.getPronunciations(profile)
+
+    def getKeybindings(self, profile='default'):
+        """Return the current keybindings settings.
+        Those settings comes from updating the default settings
+        with the profiles' ones"""
+        return self._backend.getKeybindings(profile)
+
+    def _setProfileGeneral(self, general):
+        """Set the changed general settings from the defaults' ones
+        as the profile's."""
+        self.profileGeneral = {}
+
+        for key, value in general.items():
+            if key in settings.excludeKeys:
+                continue
+            elif key == 'profile':
+                self.profileGeneral[key] = value
+            elif value != self.defaultGeneralValues[key]:
+                self.profileGeneral[key] = value
+            elif self.general.get(key) != value:
+                self.profileGeneral[key] = value
+
+    def _setProfilePronunciations(self, pronunciations):
+        """Set the changed pronunciations settings from the defaults' ones
+        as the profile's."""
+        self.profilePronunciations = self.defaultPronunciations.copy()
+        self.profilePronunciations.update(pronunciations)
+
+    def _setProfileKeybindings(self, keybindings):
+        """Set the changed keybindings settings from the defaults' ones
+        as the profile's."""
+        self.profileKeybindings = self.defaultKeybindings.copy()
+        self.profileKeybindings.update(keybindings)
+
+    def saveSettings(self, general, pronunciations, keybindings):
+        """Let the active backend to store the default settings and
+        the profiles' ones."""
+        # Assign current profile
+        _profile = general.get('profile', settings.profile)
+        currentProfile = _profile[1]
+
+        self.profile = currentProfile
+
+        # Elements that need to stay updated in main configuration.
+        self.defaultGeneral['startingProfile'] = general.get('startingProfile',
+                                                              _profile)
+
+        self._setProfileGeneral(general)
+        self._setProfilePronunciations(pronunciations)
+        self._setProfileKeybindings(keybindings)
+
+        self._backend.saveProfileSettings(self.profile,
+                                          self.profileGeneral,
+                                          self.profilePronunciations,
+                                          self.profileKeybindings)
+        return self._enableAccessibility()
+
+    def _adjustBindingTupleValues(self, bindingTuple):
+        """Converts the values of bindingTuple into KeyBinding-ready values."""
+
+        keysym, mask, mods, clicks = bindingTuple
+        if not keysym:
+            bindingTuple = ('', 0, 0, 0)
+        else:
+            bindingTuple = (keysym, int(mask), int(mods), int(clicks))
+
+        return bindingTuple
+
+    def overrideKeyBindings(self, script, scriptKeyBindings):
+        keybindingsSettings = self.getKeybindings(self.profile)
+        for handlerString, bindingTuples in keybindingsSettings.items():
+            handler = script.inputEventHandlers.get(handlerString)
+            if not handler:
+                continue
+
+            scriptKeyBindings.removeByHandler(handler)
+            for bindingTuple in bindingTuples:
+                bindingTuple = self._adjustBindingTupleValues(bindingTuple)
+                keysym, mask, mods, clicks = bindingTuple
+                newBinding = KeyBinding(keysym, mask, mods, handler, clicks)
+                scriptKeyBindings.add(newBinding)
+
+        return scriptKeyBindings
+
+    def isFirstStart(self):
+        """Check if the firstStart key is True or false"""
+        return self._backend.isFirstStart()
+
+    def setFirstStart(self, value=False):
+        """Set firstStart. This user-configurable settting is primarily
+        intended to serve as an indication as to whether or not initial
+        configuration is needed."""
+        self._backend.setFirstStart(value)
+
+    def availableProfiles(self):
+        """Get available profiles from active backend"""
+
+        return self._backend.availableProfiles()
+
+
+    def importProfile(self, fileName):
+        """Import profile from a given filename"""
+
+        prefs = {}
+        with open(fileName) as settingsFile:
+            prefs = load(settingsFile)
+
+        general = {}
+
+        for key, value in prefs.items():
+            if key not in settings.excludeKeys:
+                general[key] = value
+
+        pronunciations = prefs.get('pronunciations', {})
+        keybindings = prefs.get('keybindings', {})
+
+        self.saveSettings(general, pronunciations, keybindings)
+        return True
+
+def getVoiceKey(voice):
+    voicesKeys = getattr(settings, 'voicesKeys')
+    for key in voicesKeys.keys():
+        if voicesKeys[key] == voice:
+            return key
+    return ""
+
+def getValueForKey(prefsDict, key):
+    need2repr = ['brailleEOLIndicator', 'brailleContractionTable',
+                 'brailleRequiredStateString', 'enabledBrailledTextAttributes',
+                 'enabledSpokenTextAttributes', 'magZoomerBorderColor',
+                 'magCursorColor', 'magCrossHairColor', 'magTargetDisplay',
+                 'magSourceDisplay', 'speechRequiredStateString',
+                 'speechServerFactory', 'presentDateFormat',
+                 'presentTimeFormat']
+
+    value = None
+    if key in prefsDict:
+        if type(prefsDict[key]) is str:
+            if key == 'magZoomerLeft':
+                value = eval('settings.%s' % prefsDict[key])
+            elif key in need2repr:
+                value = "\'%s\'" % prefsDict[key]
+            elif key  == 'voices':
+                key = getVoiceKey(key)
+                value = prefsDict[key]
+            else:
+                try:
+                    value = getattr(settings, prefsDict[key])
+                except:
+                    debug.println(debug.LEVEL_SEVERE,
+                                  "Something went wront with key: " % key)
+                    debug.printStack(debug.LEVEL_FINEST)
+        else:
+            value = prefsDict[key]
+    return value
+
+def getRealValues(prefs):
+    """Get the actual values for any constant stored on a
+    general settings dictionary.
+    prefs is a dictionary with the userCustomizableSettings keys
+    and values."""
+    #for key in prefs.keys():
+    #    prefs[key] = getValueForKey(prefs, key)
+    return prefs
diff --git a/src/orca/speech_generator.py b/src/orca/speech_generator.py
index 6db1554..17bbcdd 100644
--- a/src/orca/speech_generator.py
+++ b/src/orca/speech_generator.py
@@ -29,6 +29,7 @@ import urlparse, urllib2
 
 import generator
 import pyatspi
+import orca
 import rolenames
 import settings
 import sound
@@ -79,6 +80,8 @@ voiceType = {
     VALUE       : settings.SYSTEM_VOICE, # Users may prefer DEFAULT_VOICE here
 }
 
+_settingsManager = getattr(orca, '_settingsManager')
+
 class SpeechGenerator(generator.Generator):
     """Takes accessible objects and produces a string to speak for
     those objects.  See the generateSpeech method, which is the primary
@@ -103,8 +106,9 @@ class SpeechGenerator(generator.Generator):
         settings.py:sounds dictionary (e.g., a pyatspi.ROLE_* value)
         or just the name of an audio file to use.
         """
+        sounds = _settingsManager.getSetting('sounds')
         try:
-            soundBite = sound.Sound(settings.sounds[key])
+            soundBite = sound.Sound(sounds[key])
         except:
             if isinstance(key, basestring):
                 soundBite = sound.Sound(key)
@@ -138,7 +142,7 @@ class SpeechGenerator(generator.Generator):
 
         role = args.get('role', obj.getRole())
         if role == pyatspi.ROLE_LAYERED_PANE:
-            if settings.onlySpeakDisplayedText:
+            if _settingsManager.getSetting('onlySpeakDisplayedText'):
                 return []
             else:
                 acss = self.voice(SYSTEM)
@@ -180,7 +184,7 @@ class SpeechGenerator(generator.Generator):
         represent the description of the object, if that description
         is different from that of the name and label.
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         acss = self.voice(SYSTEM)
@@ -212,7 +216,7 @@ class SpeechGenerator(generator.Generator):
         of a speech generator that we can update and the user can
         override.]]]
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -228,7 +232,7 @@ class SpeechGenerator(generator.Generator):
         Note that a 'role' attribute in args will override the
         accessible role of the obj.
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -294,7 +298,7 @@ class SpeechGenerator(generator.Generator):
         for check boxes. [[[WDW - should we return an empty array if
         we can guarantee we know this thing is not checkable?]]]
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         acss = self.voice(STATE)
@@ -309,7 +313,7 @@ class SpeechGenerator(generator.Generator):
         tree node. If the object is not expandable, an empty array
         will be returned.
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         acss = self.voice(STATE)
@@ -323,7 +327,7 @@ class SpeechGenerator(generator.Generator):
         represent the checked state of the menu item, only if it is
         checked. Otherwise, and empty array will be returned.
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         acss = self.voice(STATE)
@@ -339,7 +343,7 @@ class SpeechGenerator(generator.Generator):
         the object.  This is typically for check boxes. If the object
         is not multiselectable, an empty array will be returned.
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -360,7 +364,7 @@ class SpeechGenerator(generator.Generator):
         for check boxes. [[[WDW - should we return an empty array if
         we can guarantee we know this thing is not checkable?]]]
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         acss = self.voice(STATE)
@@ -375,7 +379,7 @@ class SpeechGenerator(generator.Generator):
         for check boxes. [[[WDW - should we return an empty array if
         we can guarantee we know this thing is not checkable?]]]
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         acss = self.voice(STATE)
@@ -671,7 +675,7 @@ class SpeechGenerator(generator.Generator):
         oldRole = self._overrideRole('REAL_ROLE_TABLE_CELL', args)
         result.extend(self.generate(obj, **args))
         self._restoreRole(oldRole, args)
-        if not result and settings.speakBlankLines \
+        if not result and _settingsManager.getSetting('speakBlankLines') \
            and not args.get('readingRow', False):
             # Translators: "blank" is a short word to mean the
             # user has navigated to an empty line.
@@ -690,7 +694,7 @@ class SpeechGenerator(generator.Generator):
         returned.  [[[WDW - I wonder if this string should be moved to
         settings.py.]]]
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -738,7 +742,7 @@ class SpeechGenerator(generator.Generator):
         """Returns an array of strings (and possibly voice and audio
         specifications) reflecting the column number of a cell.
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -767,7 +771,7 @@ class SpeechGenerator(generator.Generator):
         """Returns an array of strings (and possibly voice and audio
         specifications) reflecting the row number of a cell.
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -798,7 +802,7 @@ class SpeechGenerator(generator.Generator):
         of its column number, the total number of columns, its row,
         and the total number of rows.
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -833,12 +837,13 @@ class SpeechGenerator(generator.Generator):
         specifications) indicating that this cell is the last cell
         in the table.
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
         acss = self.voice(SYSTEM)
-        if settings.speechVerbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE:
+        if _settingsManager.getSetting('speechVerbosityLevel') \
+                == settings.VERBOSITY_LEVEL_VERBOSE:
             if obj.getRole() == pyatspi.ROLE_TABLE_CELL:
                 cell = obj
             else:
@@ -1024,7 +1029,7 @@ class SpeechGenerator(generator.Generator):
                 char = textObj.getTextAtOffset(caretOffset,
                     pyatspi.TEXT_BOUNDARY_CHAR)
                 if char[0] == "\n" and startOffset == caretOffset \
-                       and settings.speakBlankLines:
+                       and _settingsManager.getSetting('speakBlankLines'):
                     # Translators: "blank" is a short word to mean the
                     # user has navigated to an empty line.
                     #
@@ -1111,7 +1116,7 @@ class SpeechGenerator(generator.Generator):
         object is selected. [[[WDW - I wonder if this string should be
         moved to settings.py.]]]
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -1135,7 +1140,7 @@ class SpeechGenerator(generator.Generator):
         object is selected. [[[WDW - I wonder if this string should be
         moved to settings.py.]]]
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -1168,11 +1173,11 @@ class SpeechGenerator(generator.Generator):
         - obj: the text object.
         - line: the string to check for spaces and tabs.
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         acss = self.voice(SYSTEM)
-        if not settings.enableSpeechIndentation:
+        if not _settingsManager.getSetting('enableSpeechIndentation'):
             return []
         line =  args.get('alreadyFocused', "")
         if not line:
@@ -1236,7 +1241,7 @@ class SpeechGenerator(generator.Generator):
         is typically set by Orca to be the previous object with
         focus.
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -1260,7 +1265,7 @@ class SpeechGenerator(generator.Generator):
         object.  This is typically for progress bars. [[[WDW - we
         should consider returning an empty array if there is no value.
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -1336,7 +1341,7 @@ class SpeechGenerator(generator.Generator):
         this doesn't apply?]]] [[[WDW - I wonder if this string should
         be moved to settings.py.]]]
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -1360,7 +1365,7 @@ class SpeechGenerator(generator.Generator):
         apply?]]] [[[WDW - I wonder if this string should be moved to
         settings.py.]]]
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -1387,7 +1392,7 @@ class SpeechGenerator(generator.Generator):
         apply?]]] [[[WDW - I wonder if this string should be moved to
         settings.py.]]]
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -1406,7 +1411,7 @@ class SpeechGenerator(generator.Generator):
         and the position of the current item. This object will be an icon
         panel or a layered pane.
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -1469,7 +1474,7 @@ class SpeechGenerator(generator.Generator):
         [[[WDW - I wonder if this string should be moved to
         settings.py.]]]
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -1589,7 +1594,7 @@ class SpeechGenerator(generator.Generator):
         specifications) that represent the relative position of an
         object in a group.
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -1625,8 +1630,8 @@ class SpeechGenerator(generator.Generator):
         specifications) that represent the relative position of an
         object in a list.
         """
-        if settings.onlySpeakDisplayedText \
-           or not (settings.enablePositionSpeaking \
+        if _settingsManager.getSetting('onlySpeakDisplayedText') \
+           or not (_settingsManager.getSetting('enablePositionSpeaking') \
                    or args.get('forceList', False)):
             return []
 
@@ -1697,7 +1702,9 @@ class SpeechGenerator(generator.Generator):
                 if nextName == name:
                     position = index
 
-        if position >= 0:
+        if (_settingsManager.getSetting('enablePositionSpeaking') \
+             or args.get('forceList', False)) \
+           and position >= 0:
             result.append(self._script.formatting.getString(
                               mode='speech',
                               stringType='groupindex') \
@@ -1791,7 +1798,7 @@ class SpeechGenerator(generator.Generator):
         specifications) that represent the accelerator for the object,
         or an empty array if no accelerator can be found.
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -1809,12 +1816,13 @@ class SpeechGenerator(generator.Generator):
         specifications) that represent the mnemonic for the object, or
         an empty array if no mnemonic can be found.
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
         acss = self.voice(SYSTEM)
-        if settings.enableMnemonicSpeaking or args.get('forceMnemonic', False):
+        if _settingsManager.getSetting('enableMnemonicSpeaking') \
+           or args.get('forceMnemonic', False):
             [mnemonic, shortcut, accelerator] = \
                 self._script.utilities.mnemonicShortcutAccelerator(obj)
             if mnemonic:
@@ -1841,7 +1849,7 @@ class SpeechGenerator(generator.Generator):
         tutorial generator.  A tutorial can be forced by setting the
         'forceTutorial' attribute of the args dictionary to True.
         """
-        if settings.onlySpeakDisplayedText:
+        if _settingsManager.getSetting('onlySpeakDisplayedText'):
             return []
 
         result = []
@@ -1884,4 +1892,5 @@ class SpeechGenerator(generator.Generator):
         """
 
         voicename = voiceType.get(key) or voiceType.get(DEFAULT)
-        return [settings.voices.get(voicename)]
+        voices = _settingsManager.getSetting('voices')
+        return [voices.get(voicename)]
diff --git a/test/harness/.gitignore b/test/harness/.gitignore
index 3c6779a..047c431 100644
--- a/test/harness/.gitignore
+++ b/test/harness/.gitignore
@@ -1,7 +1,6 @@
 orca-customizations.py
 orca-customizations.pyc
-user-settings.py
-user-settings.pyc
+user-settings.conf
 utils.pyc
 *.debug
 *.speech
diff --git a/test/harness/generalSettings.conf b/test/harness/generalSettings.conf
new file mode 100644
index 0000000..5e35deb
--- /dev/null
+++ b/test/harness/generalSettings.conf
@@ -0,0 +1,10 @@
+ enableKeyEcho: false
+ keyboardLayout: 2
+ magSourceDisplay: :0.0
+ magTargetDisplay: :0.0
+ orcaModifierKeys: [Caps_Lock]
+ profile: [Laptop, laptop]
+ quitOrcaNoConfirmation: true
+ speechServerFactory: orca.speechdispatcherfactory
+ speechServerInfo: [Sintetizador predeterminado, default]
+ verbalizePunctuationStyle: 2
diff --git a/test/harness/harness.sh b/test/harness/harness.sh
index 1c5b7f3..0aa141e 100755
--- a/test/harness/harness.sh
+++ b/test/harness/harness.sh
@@ -102,7 +102,7 @@ else
     orcaCommand="orca"
 fi
 
-cp user-settings.py.in user-settings.py
+cp user-settings.conf.in user-settings.conf
 $orcaCommand&
 sleep 5
 
@@ -313,7 +313,7 @@ done
 
 sleep 5
 python quit.py
-rm -f user-settings.py user-settings.pyc
+rm -f user-settings.conf
 
 if [ "$coverageMode" -eq 1 ]
 then
diff --git a/test/harness/importFile.conf b/test/harness/importFile.conf
new file mode 100644
index 0000000..f0f052a
--- /dev/null
+++ b/test/harness/importFile.conf
@@ -0,0 +1,8 @@
+keybindings: 
+ reviewCurrentCharacterHandler:
+ - !!python/tuple [KP_4, '365', '0', '1']
+ - !!python/tuple [null, '365', '0', '3']
+profile: [Imported profile, imported_profile]
+pronunciations: 
+  asap: [ASAP, as soon as possible]
+  btw: [BTW, by the way]
diff --git a/test/harness/importFile2.conf b/test/harness/importFile2.conf
new file mode 100644
index 0000000..c786f40
--- /dev/null
+++ b/test/harness/importFile2.conf
@@ -0,0 +1,3 @@
+profile: [Laptop, laptop]
+keyboardLayout: 2
+quitOrcaNoConfirmation: true
diff --git a/test/harness/keybindingsSettings.conf b/test/harness/keybindingsSettings.conf
new file mode 100644
index 0000000..73f43bd
--- /dev/null
+++ b/test/harness/keybindingsSettings.conf
@@ -0,0 +1,4 @@
+keybindings:
+ reviewCurrentCharacterHandler:
+ - !!python/tuple [KP_2, '365', '0', '1']
+ - !!python/tuple [null, '365', '0', '1']
diff --git a/test/harness/pronunciationsSettings.conf b/test/harness/pronunciationsSettings.conf
new file mode 100644
index 0000000..7e5a958
--- /dev/null
+++ b/test/harness/pronunciationsSettings.conf
@@ -0,0 +1,3 @@
+pronunciations:
+  asap: [ASAP, as soon as possible]
+  btw: [BTW, by the way]
diff --git a/test/harness/runall.sh b/test/harness/runall.sh
index 1bd564e..b934fca 100755
--- a/test/harness/runall.sh
+++ b/test/harness/runall.sh
@@ -96,8 +96,8 @@ then
     echo generating coverage map...
     coverageDir=../coverage/`date +%Y-%m-%d_%H:%M:%S`
     mkdir -p $coverageDir
-    cp $harnessDir/user-settings.py.in user-settings.py
-    #echo $harnessDir/user-settings.py.in
+    cp $harnessDir/user-settings.conf.in user-settings.conf
+    #echo $harnessDir/user-settings.conf.in
     trace2html.py -o $coverageDir -w orca -r $harnessDir/runorca.py &
     trace_pid=$!
     sleep 10
@@ -108,7 +108,7 @@ then
     runOrcaOnce=1
     export HARNESS_ASSERT=0
     echo generating profile information...
-    cp $harnessDir/user-settings.py.in user-settings.py
+    cp $harnessDir/user-settings.conf.in user-settings.conf
     python $harnessDir/runprofiler.py&
     profiler_pid=$!
     sleep 10
@@ -232,16 +232,14 @@ done
 if [ "$coverageMode" -eq 1 ]
 then
     python $harnessDir/quit.py
-    rm user-settings.py
-    rm -f user-settings.pyc
+    rm user-settings.conf
     echo ...finished generating coverage map.
 fi
 
 if [ "$profileMode" -eq 1 ]
 then
     python $harnessDir/quit.py
-    rm -f user-settings.py
-    rm -f user-settings.pyc
+    rm -f user-settings.conf
     mkdir -p ../profile
     profileFilePrefix=../profile/`date +%Y-%m-%d_%H:%M:%S`
     python -c "import pstats; pstats.Stats('orcaprof').sort_stats('cumulative').print_stats()" > $profileFilePrefix.txt
diff --git a/test/harness/runone.sh b/test/harness/runone.sh
index f7be6f0..15e55be 100755
--- a/test/harness/runone.sh
+++ b/test/harness/runone.sh
@@ -61,18 +61,19 @@ EOF
 # Set up our local user settings file for the output format we want.
 #
 # If a <testfilename>.settings file exists, should use that instead of
-# the default user-settings.py.in.
+# the default user-settings.conf.in.
 #
-# (Orca will look in our local directory first for user-settings.py
-# before looking in ~/.orca)
+# (Orca will look in our local directory first for user-settings.conf
+# before looking in the usual location)
 #
 SETTINGS_FILE=`dirname $1`/$debugFile.settings
 if [ ! -f $SETTINGS_FILE ]
 then
-    SETTINGS_FILE=`dirname $0`/user-settings.py.in
+    SETTINGS_FILE=`dirname $0`/user-settings.conf.in
 fi
+cp $SETTINGS_FILE user-settings.conf
 #echo "Using settings file:" $SETTINGS_FILE
-cp $SETTINGS_FILE user-settings.py
+
 
 # Allow us to pass parameters to the command line of the application.
 #
diff --git a/test/harness/settings_test.py b/test/harness/settings_test.py
new file mode 100644
index 0000000..a566c06
--- /dev/null
+++ b/test/harness/settings_test.py
@@ -0,0 +1,97 @@
+from orca import settings_manager
+from yaml import load, dump
+from pprint import pprint
+
+def exerciseBackendAPI(backendName, profile):
+    settingsManager = settings_manager.SettingsManager(backendName)
+
+    print "\n\n================ Testing Backend %s ====================\n\n" % \
+            backendName
+    print 'Profile: ', profile
+    print 'Profiles list: ', settingsManager.availableProfiles()
+
+    #settingsManager.setProfile(profile)
+
+    # Getters
+    preferences = settingsManager.getPreferences(profile)
+    print 'preferences: \n',preferences,'\n\n'
+
+    generalSettings = settingsManager.getGeneralSettings(profile)
+    print 'generalSettings: \n',generalSettings,'\n\n'
+
+    pronunciations = settingsManager.getPronunciations(profile)
+    print 'pronunciations: \n',pronunciations,'\n\n'
+
+    keybindings = settingsManager.getKeybindings(profile)
+    print 'keybindings: \n',keybindings,'\n\n'
+
+    # Adding new settings to the profile and merging them
+    newGeneralSettings = getSettingsFromFile('general')
+    print "newGeneralSettings = "
+    pprint(newGeneralSettings)
+    settingsManager._setProfileGeneral(newGeneralSettings)
+    generalSettings = settingsManager.getGeneralSettings(profile)
+    print "generalSettings = "
+    pprint(generalSettings)
+
+    newKeybindingsSettings = getSettingsFromFile('keybindings')
+    print "\n\nnewKeybindingsSettings = "
+    pprint(newKeybindingsSettings)
+    settingsManager._setProfileKeybindings(newKeybindingsSettings)
+    keybindings = settingsManager.getKeybindings(profile)
+    print "keybindings = "
+    pprint(keybindings)
+
+    newPronunciationsSettings = getSettingsFromFile('pronunciations')
+    print "\n\nnewPronunciationsSettings = "
+    pprint(newPronunciationsSettings)
+    settingsManager._setProfileGeneral(newPronunciationsSettings)
+    pronunciations = settingsManager.getPronunciations(profile)
+    print "pronunciations = "
+    pprint(pronunciations)
+
+    #settingsManager.saveSettings()
+    isFirstStart = settingsManager.isFirstStart()
+    print "\n\nIs First Start? => ", isFirstStart
+    print "\n\nSetting firstStart key"
+    settingsManager.setFirstStart()
+    isFirstStart = settingsManager.isFirstStart()
+    print "\n\nIs First Start? => ", isFirstStart
+    print "\n\n===========================================================\n\n"
+
+    print "\n\nTesting import from a file I"
+    print "\n==========================================================="
+    availableProfilesBefore = settingsManager.availableProfiles()
+    print "\nAvailable Profiles BEFORE the import  => ", availableProfilesBefore
+    settingsManager.importProfile('importFile.conf')
+    availableProfilesAfter = settingsManager.availableProfiles()
+    print "\nAvailable Profiles AFTER the import  => ", availableProfilesAfter
+
+    print "\n\nTesting import from a file II"
+    print "\n==========================================================="
+    availableProfilesBefore = settingsManager.availableProfiles()
+    print "\nAvailable Profiles BEFORE the import  => ", availableProfilesBefore
+    settingsManager.importProfile('importFile2.conf')
+    availableProfilesAfter = settingsManager.availableProfiles()
+    print "\nAvailable Profiles AFTER the import  => ", availableProfilesAfter
+    
+
+def getSettingsFromFile(dictName):
+    fileName = '%sSettings.conf' % dictName
+    try:
+        dictFile = open(fileName)
+    except:
+        import sys
+        print "You should run the test from the test directory"
+        sys.exit()
+    settings = load(dictFile)
+    dictFile.close()
+    return settings
+
+# main
+profile = 'default'
+print 'profile: default backendName: yaml\n'
+exerciseBackendAPI('yaml', 'default')
+#print 'profile: default backendName: gconf\n'
+#exerciseBackendAPI('gconf', 'default')
+#exerciseBackendAPI('default', 'gsettings', s)
diff --git a/test/harness/user-settings.conf.in b/test/harness/user-settings.conf.in
new file mode 100644
index 0000000..af458d5
--- /dev/null
+++ b/test/harness/user-settings.conf.in
@@ -0,0 +1,143 @@
+general:
+  activeProfile: [Default, default]
+  brailleAlignmentStyle: 0
+  brailleContractionTable: ''
+  brailleEOLIndicator: ' $l'
+  brailleFlashTime: 5000
+  brailleLinkIndicator: 192
+  brailleRequiredStateString: required
+  brailleRolenameStyle: 1
+  brailleSelectorIndicator: 192
+  brailleVerbosityLevel: 1
+  chatAnnounceBuddyTyping: false
+  chatMessageVerbosity: 0
+  chatRoomHistories: false
+  chatSpeakRoomName: false
+  disableBrailleEOL: false
+  enableActionKeys: true
+  enableBraille: false
+  enableBrailleContext: true
+  enableBrailleGrouping: false
+  enableBrailleMonitor: true
+  enableContractedBraille: false
+  enableDiacriticalKeys: false
+  enableEchoByCharacter: false
+  enableEchoBySentence: false
+  enableEchoByWord: false
+  enableFlashMessages: true
+  enableFunctionKeys: true
+  enableKeyEcho: true
+  enableLockingKeys: true
+  enableMagCrossHair: true
+  enableMagCrossHairClip: false
+  enableMagCursor: true
+  enableMagCursorExplicitSize: false
+  enableMagLiveUpdating: true
+  enableMagZoomerBorder: false
+  enableMagZoomerColorInversion: false
+  enableMagnifier: false
+  enableMnemonicSpeaking: false
+  enableModifierKeys: true
+  enableMouseReview: false
+  enableNavigationKeys: false
+  enablePauseBreaks: true
+  enablePositionSpeaking: false
+  enablePrintableKeys: true
+  enableProgressBarUpdates: true
+  enableSpeech: true
+  enableSpeechIndentation: false
+  enableTutorialMessages: false
+  enabledBrailledTextAttributes: size:; family-name:; weight:400; indent:0; underline:none;
+    strikethrough:false; justification:left; style:normal; text-spelling:none;
+  enabledSpokenTextAttributes: size:; family-name:; weight:400; indent:0; underline:none;
+    strikethrough:false; justification:left; style:normal; paragraph-style:; text-spelling:none;
+  firstStart: false
+  flashIsPersistent: false
+  flashVerbosityLevel: 1
+  keyboardLayout: 1
+  largeObjectTextLength: 75
+  magBrightnessLevel: 0
+  magBrightnessLevelBlue: 0
+  magBrightnessLevelGreen: 0
+  magBrightnessLevelRed: 0
+  magColorFilteringMode: 0
+  magContrastLevel: 0
+  magContrastLevelBlue: 0
+  magContrastLevelGreen: 0
+  magContrastLevelRed: 0
+  magControlTrackingMode: 2
+  magCrossHairColor: '#000000'
+  magCrossHairSize: 16
+  magCursorColor: '#000000'
+  magCursorSize: 32
+  magEdgeMargin: 0
+  magHideCursor: false
+  magMouseTrackingMode: 0
+  magPointerFollowsFocus: false
+  magPointerFollowsZoomer: true
+  magSmoothingMode: 0
+  magSourceDisplay: ''
+  magTargetDisplay: ''
+  magTextTrackingMode: 2
+  magZoomFactor: 4.0
+  magZoomerBorderColor: '#000000'
+  magZoomerBorderSize: 1
+  magZoomerBottom: 1920
+  magZoomerLeft: 1200
+  magZoomerRight: 2400
+  magZoomerTop: 0
+  magZoomerType: 0
+  messageVerbosityLevel: 1
+  mouseDwellDelay: 0
+  onlySpeakDisplayedText: false
+  orcaModifierKeys: [Insert, KP_Insert]
+  presentDateFormat: '%x'
+  presentRequiredState: false
+  presentTimeFormat: '%X'
+  presentToolTips: false
+  profile: [Default, default]
+  progressBarUpdateInterval: 10
+  progressBarVerbosity: 1
+  quitOrcaNoConfirmation: false
+  readTableCellRow: true
+  sayAllStyle: 1
+  showMainWindow: true
+  skipBlankCells: false
+  speakBlankLines: true
+  speakCellCoordinates: true
+  speakCellHeaders: true
+  speakCellSpan: true
+  speakMultiCaseStringsAsWords: false
+  speechRequiredStateString: required
+  speechServerFactory: speechdispatcherfactory
+  speechServerInfo: null
+  speechVerbosityLevel: 1
+  startingProfile: [Default, default]
+  textAttributesBrailleIndicator: 0
+  verbalizePunctuationStyle: 1
+  voices:
+    default: !!python/object/new:orca.acss.ACSS
+      dictitems: {established: false}
+    hyperlink: !!python/object/new:orca.acss.ACSS
+      dictitems: {established: false}
+    system: !!python/object/new:orca.acss.ACSS
+      dictitems: {established: false}
+    uppercase: !!python/object/new:orca.acss.ACSS
+      dictitems: {average-pitch: 5.5999999999999996}
+  wrappedStructuralNavigation: true
+keybindings: {}
+profiles:
+  default:
+    profile: [Default, default]
+    enableEchoByWord: false
+    enableKeyEcho: false
+    enableBraille: false
+    enableBrailleMonitor: true
+    enableEchoByWord: False
+    enableKeyEcho: False
+    enablePrintableKeys: False
+    enableModifierKeys: False
+    enableLockingKeys: False
+    enableFunctionKeys: False
+    enableActionKeys: False
+pronunciations: {}
diff --git a/test/keystrokes/gtk-demo/spoken_indentation.settings b/test/keystrokes/gtk-demo/spoken_indentation.settings
index 1f665fe..b7c1345 100644
--- a/test/keystrokes/gtk-demo/spoken_indentation.settings
+++ b/test/keystrokes/gtk-demo/spoken_indentation.settings
@@ -1,32 +1,143 @@
-# -*- coding: utf-8 -*-
-
-# Default settings for all tests.  These can be overridden by
-# defining a *.params file for a test.  See 
-# http://live.gnome.org/Orca/RegressionTesting for more info.
-
-import re
-
-import orca.debug
-import orca.settings
-
-orca.settings.enableSpeechIndentation = True
-
-orca.settings.enableEchoByWord = False
-orca.settings.enableKeyEcho = False
-orca.settings.enablePrintableKeys = False
-orca.settings.enableModifierKeys = False
-orca.settings.enableLockingKeys = False
-orca.settings.enableFunctionKeys = False
-orca.settings.enableActionKeys = False
-
-orca.settings.enableBraille = False
-orca.settings.enableBrailleMonitor = False
-
-import orca.orca_state
-try:
-    reload(orca.orca_state.orcaCustomizations)
-except AttributeError:
-    try:
-        orca.orca_state.orcaCustomizations = __import__("orca-customizations")
-    except ImportError:
-        pass
+general:
+  activeProfile: [Default, default]
+  brailleAlignmentStyle: 0
+  brailleContractionTable: ''
+  brailleEOLIndicator: ' $l'
+  brailleFlashTime: 5000
+  brailleLinkIndicator: 192
+  brailleRequiredStateString: required
+  brailleRolenameStyle: 1
+  brailleSelectorIndicator: 192
+  brailleVerbosityLevel: 1
+  chatAnnounceBuddyTyping: false
+  chatMessageVerbosity: 0
+  chatRoomHistories: false
+  chatSpeakRoomName: false
+  disableBrailleEOL: false
+  enableActionKeys: true
+  enableBraille: false
+  enableBrailleContext: true
+  enableBrailleGrouping: false
+  enableBrailleMonitor: true
+  enableContractedBraille: false
+  enableDiacriticalKeys: false
+  enableEchoByCharacter: false
+  enableEchoBySentence: false
+  enableEchoByWord: false
+  enableFlashMessages: true
+  enableFunctionKeys: true
+  enableKeyEcho: true
+  enableLockingKeys: true
+  enableMagCrossHair: true
+  enableMagCrossHairClip: false
+  enableMagCursor: true
+  enableMagCursorExplicitSize: false
+  enableMagLiveUpdating: true
+  enableMagZoomerBorder: false
+  enableMagZoomerColorInversion: false
+  enableMagnifier: false
+  enableMnemonicSpeaking: false
+  enableModifierKeys: true
+  enableMouseReview: false
+  enableNavigationKeys: false
+  enablePauseBreaks: true
+  enablePositionSpeaking: false
+  enablePrintableKeys: true
+  enableProgressBarUpdates: true
+  enableSpeech: true
+  enableSpeechIndentation: true
+  enableTutorialMessages: false
+  enabledBrailledTextAttributes: size:; family-name:; weight:400; indent:0; underline:none;
+    strikethrough:false; justification:left; style:normal; text-spelling:none;
+  enabledSpokenTextAttributes: size:; family-name:; weight:400; indent:0; underline:none;
+    strikethrough:false; justification:left; style:normal; paragraph-style:; text-spelling:none;
+  firstStart: false
+  flashIsPersistent: false
+  flashVerbosityLevel: 1
+  keyboardLayout: 1
+  largeObjectTextLength: 75
+  magBrightnessLevel: 0
+  magBrightnessLevelBlue: 0
+  magBrightnessLevelGreen: 0
+  magBrightnessLevelRed: 0
+  magColorFilteringMode: 0
+  magContrastLevel: 0
+  magContrastLevelBlue: 0
+  magContrastLevelGreen: 0
+  magContrastLevelRed: 0
+  magControlTrackingMode: 2
+  magCrossHairColor: '#000000'
+  magCrossHairSize: 16
+  magCursorColor: '#000000'
+  magCursorSize: 32
+  magEdgeMargin: 0
+  magHideCursor: false
+  magMouseTrackingMode: 0
+  magPointerFollowsFocus: false
+  magPointerFollowsZoomer: true
+  magSmoothingMode: 0
+  magSourceDisplay: ''
+  magTargetDisplay: ''
+  magTextTrackingMode: 2
+  magZoomFactor: 4.0
+  magZoomerBorderColor: '#000000'
+  magZoomerBorderSize: 1
+  magZoomerBottom: 1920
+  magZoomerLeft: 1200
+  magZoomerRight: 2400
+  magZoomerTop: 0
+  magZoomerType: 0
+  messageVerbosityLevel: 1
+  mouseDwellDelay: 0
+  onlySpeakDisplayedText: false
+  orcaModifierKeys: [Insert, KP_Insert]
+  presentDateFormat: '%x'
+  presentRequiredState: false
+  presentTimeFormat: '%X'
+  presentToolTips: false
+  profile: [Default, default]
+  progressBarUpdateInterval: 10
+  progressBarVerbosity: 1
+  quitOrcaNoConfirmation: false
+  readTableCellRow: true
+  sayAllStyle: 1
+  showMainWindow: true
+  skipBlankCells: false
+  speakBlankLines: true
+  speakCellCoordinates: true
+  speakCellHeaders: true
+  speakCellSpan: true
+  speakMultiCaseStringsAsWords: false
+  speechRequiredStateString: required
+  speechServerFactory: speechdispatcherfactory
+  speechServerInfo: null
+  speechVerbosityLevel: 1
+  startingProfile: [Default, default]
+  textAttributesBrailleIndicator: 0
+  verbalizePunctuationStyle: 1
+  voices:
+    default: !!python/object/new:orca.acss.ACSS
+      dictitems: {established: false}
+    hyperlink: !!python/object/new:orca.acss.ACSS
+      dictitems: {established: false}
+    system: !!python/object/new:orca.acss.ACSS
+      dictitems: {established: false}
+    uppercase: !!python/object/new:orca.acss.ACSS
+      dictitems: {average-pitch: 5.5999999999999996}
+  wrappedStructuralNavigation: true
+keybindings: {}
+profiles:
+  default:
+    profile: [Default, default]
+    enableEchoByWord: false
+    enableKeyEcho: false
+    enableBraille: false
+    enableBrailleMonitor: true
+    enableEchoByWord: False
+    enableKeyEcho: False
+    enablePrintableKeys: False
+    enableModifierKeys: False
+    enableLockingKeys: False
+    enableFunctionKeys: False
+    enableActionKeys: False
+pronunciations: {}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]