orca r4233 - in branches/phase2: . src/orca src/orca/plugins/bookmarks src/orca/plugins/debug_actions src/orca/plugins/flat_review src/orca/plugins/speech_parameters src/orca/plugins/where_am_i src/orca/scripts src/orca/scripts/applications src/orca/scripts/apps



Author: wwalker
Date: Tue Sep 16 17:07:35 2008
New Revision: 4233
URL: http://svn.gnome.org/viewvc/orca?rev=4233&view=rev

Log:
Add user settings capabilities.  Not tested yet.


Added:
   branches/phase2/src/orca/scripts/applications/   (props changed)
   branches/phase2/src/orca/scripts/applications/Makefile.am
   branches/phase2/src/orca/scripts/applications/__init__.py
Removed:
   branches/phase2/src/orca/scripts/apps/
Modified:
   branches/phase2/configure.in
   branches/phase2/src/orca/default.py
   branches/phase2/src/orca/input_bindings.py
   branches/phase2/src/orca/orca.py
   branches/phase2/src/orca/plugin.py
   branches/phase2/src/orca/plugins/bookmarks/plugin.py
   branches/phase2/src/orca/plugins/debug_actions/plugin.py
   branches/phase2/src/orca/plugins/flat_review/plugin.py
   branches/phase2/src/orca/plugins/speech_parameters/plugin.py
   branches/phase2/src/orca/plugins/where_am_i/plugin.py
   branches/phase2/src/orca/rolenames.py
   branches/phase2/src/orca/script.py
   branches/phase2/src/orca/script_manager.py
   branches/phase2/src/orca/scripts/Makefile.am
   branches/phase2/src/orca/settings.py
   branches/phase2/src/orca/utils.py

Modified: branches/phase2/configure.in
==============================================================================
--- branches/phase2/configure.in	(original)
+++ branches/phase2/configure.in	Tue Sep 16 17:07:35 2008
@@ -166,7 +166,7 @@
 src/orca/plugins/speech_parameters/Makefile
 src/orca/plugins/where_am_i/Makefile
 src/orca/scripts/Makefile
-src/orca/scripts/apps/Makefile
+src/orca/scripts/applications/Makefile
 src/orca/scripts/toolkits/Makefile
 src/orca/orca
 src/orca/orca_i18n.py

Modified: branches/phase2/src/orca/default.py
==============================================================================
--- branches/phase2/src/orca/default.py	(original)
+++ branches/phase2/src/orca/default.py	Tue Sep 16 17:07:35 2008
@@ -38,13 +38,13 @@
     derived.
     """
 
-    def __init__(self, application):
+    def __init__(self, application, userSettings):
         """Creates a new script for the given application.
 
         Arguments:
         - application: the application to create a script for.
         """
-        script.Script.__init__(self, application)
+        script.Script.__init__(self, application, userSettings)
 
     def _getPluginClasses(self):
         """Returns a list of classes to instantiante for plugins.

Modified: branches/phase2/src/orca/input_bindings.py
==============================================================================
--- branches/phase2/src/orca/input_bindings.py	(original)
+++ branches/phase2/src/orca/input_bindings.py	Tue Sep 16 17:07:35 2008
@@ -15,6 +15,9 @@
 # Free Software Foundation, Inc., Franklin Street, Fifth Floor,
 # Boston MA  02110-1301 USA.
 
+# TODO: change name everywhere from keybindings to keyboardbindings,
+# using the capitalization and underscores appropriate for the context.
+
 """Provides support for defining braille and key bindings and matching
 them to input events."""
 

Modified: branches/phase2/src/orca/orca.py
==============================================================================
--- branches/phase2/src/orca/orca.py	(original)
+++ branches/phase2/src/orca/orca.py	Tue Sep 16 17:07:35 2008
@@ -79,30 +79,150 @@
 
 from orca_i18n import _ # for gettext support
 
-# Command line options that override any other settings.
-#
-_commandLineSettings = settings.Settings(settings.globalSettings)
+_defaultSettings = None
+_userSettings = None
 
-def usage():
+def _usage():
     """Prints out usage information.
     """
     print _("Usage: orca [OPTION...]")
+    print
+
+    # Translators: this is the description of the command line option
+    # '-?, --help' that is used to display usage information.
+    #
+    print "-?, --help                   " + _("Show this help message")
+
+    print "-v, --version                %s" % 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.
+    #
+    print "-l, --list-apps              " + \
+          _("Print the known running applications")
+
+    # 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.
+    #
+    print "-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.
+    #
+    print "-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.
+    #
+    print "-n, --no-setup               " +  \
+          _("Skip set up of user preferences")
+
+    # Translators: by default, Orca expects to find its user preferences
+    # in a directory called .orca under the user's home directory. This
+    # is the description of the command line option
+    # '-u, --user-prefs-dir=dirname' that allows you to specify an alternate
+    # location for those user preferences.
+    #
+    print "-u, --user-prefs-dir=dirname " + \
+          _("Use alternate directory for user preferences")
+
+    print "-e, --enable=[" \
+        + "speech" + "|" \
+        + "braille" + "|" \
+        + "braille-monitor" + "|" \
+        + "magnifier" + "|" \
+        + "main-window" + "]",
+
+    # Translators: if the user supplies an option via the '-e, --enable'
+    # command line option, it will be automatically enabled as Orca is
+    # started.
+    #
+    print _("Force use of option")
+    print "-d, --disable=[" \
+        + "speech" + "|" \
+        + "braille" + "|" \
+        + "braille-monitor" + "|" \
+        + "magnifier" + "|" \
+        + "main-window" + "]",
+
+    # Translators: if the user supplies an option via the '-d, --disable'
+    # command line option, it will be automatically disabled as Orca is
+    # started.
+    #
+    print _("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.
+    #
+    print "-q, --quit                   " + \
+          _("Quits Orca (if shell script used)")
+    print
+
+    # Translators: this is text being sent to a terminal and we want to
+    # keep the text lines within terminal boundaries.
+    #
+    print _("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.")
+    print
+
+    # Translators: this is more text being sent to a terminal and we want to
+    # keep the text lines within terminal boundaries.
+    #
+    print _("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.")
+    print
+
+    print _("Report bugs to orca-list gnome org ")
 
-def start():
+def loadUserSettings(defaultSettings):
+    """Loads (and reloads) the user settings module.
+    """
+    global _userSettings
+
+    if _userSettings:
+        try:
+            reload(_userSettings)
+        except:
+            log.exception("exception handled while importing user settings:")
+    else:
+        try:
+            _userSettings = __import__("user_settings")
+        except:
+            log.exception("exception handled while importing user settings:")
+
+    try:
+        return _userSettings.getSettings(defaultSettings)
+    except:
+        log.debug("No user settings.  Creating empty one backed by default.")
+        return settings.Settings(defaultSettings)
+
+def _start(commandLineSettings):
     """Starts Orca.
     """
-    script_manager.ScriptManager() # The thing that does all the work
+    defaultSettings = settings.getSettings()
+    userSettings = loadUserSettings(defaultSettings)
+    script_manager.ScriptManager(userSettings)
     log.debug("pyatspi.Registry.start()")
     pyatspi.Registry.start()
 
-def shutdown():
+def _shutdown():
     """Exits Orca.  Unregisters any event listeners and cleans up.  Also
     quits the bonobo main loop and resets the initialized state to False.
 
     Returns True if the shutdown procedure ran or False if this module
     was never initialized.
     """
-    log.debug("pyatspi.Registry.stop()")
     pyatspi.Registry.stop()
 
 # There are a lot of decision branches and statements happening below,
@@ -110,9 +230,10 @@
 #
 # pylint: disable-msg=R0915
 
-def processArgv(desktopRunning):
+def _processArgv(desktopRunning):
     """Process the argument list passed in on the command line.
     """
+    commandLineSettings = settings.Settings()
 
     # We hack a little here because the shell script to start orca can
     # conflate all of command line arguments into one string, which is
@@ -152,7 +273,9 @@
                 userPrefsDir = val.strip()
                 try:
                     os.chdir(userPrefsDir)
-                    _commandLineSettings["userPrefsDir"] = userPrefsDir
+                    commandLineSettings.userPrefsDir = userPrefsDir
+                    sys.path.insert(0, userPrefsDir)
+                    sys.path.insert(0, '') # current directory
                 except:
                     log.exception("handled exception with user-prefs-dir:")
 
@@ -160,15 +283,15 @@
                 feature = val.strip()
 
                 if feature == "speech":
-                    _commandLineSettings["enableSpeech"] = True
+                    commandLineSettings.enableSpeech = True
                 elif feature == "braille":
-                    _commandLineSettings["enableBraille"] = True
+                    commandLineSettings.enableBraille = True
                 elif feature == "braille-monitor":
-                    _commandLineSettings["enableBrailleMonitor"] = True
+                    commandLineSettings.enableBrailleMonitor = True
                 elif feature == "magnifier":
-                    _commandLineSettings["enableMagnifier"] = True
+                    commandLineSettings.enableMagnifier = True
                 elif feature == "main-window":
-                    _commandLineSettings["showMainWindow"] = True
+                    commandLineSettings.showMainWindow = True
                 else:
                     usage()
                     utils.abort(2)
@@ -176,27 +299,27 @@
             if opt in ("-d", "--disable"):
                 feature = val.strip()
                 if feature == "speech":
-                    _commandLineSettings["enableSpeech"] = False
+                    commandLineSettings.enableSpeech = False
                 elif feature == "braille":
-                    _commandLineSettings["enableBraille"] = False
+                    commandLineSettings.enableBraille = False
                 elif feature == "braille-monitor":
-                    _commandLineSettings["enableBrailleMonitor"] = False
+                    commandLineSettings.enableBrailleMonitor = False
                 elif feature == "magnifier":
-                    _commandLineSettings["enableMagnifier"] = False
+                    commandLineSettings.enableMagnifier = False
                 elif feature == "main-window":
-                    _commandLineSettings["showMainWindow"] = False
+                    commandLineSettings.showMainWindow = False
                 else:
                     usage()
                     utils.abort(2)
 
             if opt in ("-s", "--gui-setup", "--setup"):
-                _commandLineSettings["setupRequested"] = True
-                _commandLineSettings["showGUI"] = desktopRunning
+                commandLineSettings.setupRequested = True
+                commandLineSettings.showGUI = desktopRunning
             if opt in ("-t", "--text-setup"):
-                _commandLineSettings["setupRequested"] = True
-                _commandLineSettings["showGUI"] = False
+                commandLineSettings.setupRequested = True
+                commandLineSettings.showGUI = False
             if opt in ("-n", "--no-setup"):
-                _commandLineSettings["bypassSetup"] = True
+                commandLineSettings.bypassSetup = True
             if opt in ("-?", "--help"):
                 usage()
                 utils.abort(0)
@@ -213,6 +336,8 @@
         usage()
         utils.abort(2)
 
+    return commandLineSettings
+
 def main():
     """The main entry point for Orca.  The exit codes for Orca will
     loosely be based on signals, where the exit code will be the
@@ -222,7 +347,7 @@
     """
     # Various signal handlers we want to listen for.
     #
-    utils.shutdown = shutdown
+    utils.shutdown = _shutdown
     signal.signal(signal.SIGHUP, utils.shutdownOnSignal)
     signal.signal(signal.SIGINT, utils.shutdownOnSignal)
     signal.signal(signal.SIGTERM, utils.shutdownOnSignal)
@@ -241,9 +366,11 @@
 
     # Parse the command line options.
     #
-    processArgv(desktopRunning)
+    commandLineSettings = _processArgv(desktopRunning)
 
-    start() # waits until we stop the registry
+    # Do our thing...
+    #
+    _start(commandLineSettings)
 
     return 0
 

Modified: branches/phase2/src/orca/plugin.py
==============================================================================
--- branches/phase2/src/orca/plugin.py	(original)
+++ branches/phase2/src/orca/plugin.py	Tue Sep 16 17:07:35 2008
@@ -30,16 +30,23 @@
 class Plugin(script.Script):
     """A Plugin is owned and managed by a Script.
     """
-    def __init__(self, owner):
+    def __init__(self, owner, scriptSettings):
         """Creates a Plugin for the given script.
         This method should not be called by anyone except the
         owner.
 
         Arguments:
         - owner: the Script owning this Plugin
+        - scriptSettings: the Settings for the script
         """
         self._script = owner
-        script.Script.__init__(self, owner)
+        script.Script.__init__(self, owner, scriptSettings)
+
+    def getSettingsModuleName(self):
+        name = self._script.getSettingsModuleName()
+        if name and len(name):
+            name = name + __name__.strip("orca")
+        return name
 
     def _completeInit(self):
         """Completes the __init__ step.

Modified: branches/phase2/src/orca/plugins/bookmarks/plugin.py
==============================================================================
--- branches/phase2/src/orca/plugins/bookmarks/plugin.py	(original)
+++ branches/phase2/src/orca/plugins/bookmarks/plugin.py	Tue Sep 16 17:07:35 2008
@@ -42,15 +42,16 @@
 class Plugin(plugin.Plugin):
     """A plugin for handling bookmarks.
     """
-    def __init__(self, owner):
+    def __init__(self, owner, scriptSettings):
         """Creates a Plugin for the given script.
         This method should not be called by anyone except the
         owner.
 
         Arguments:
         - owner: the Script owning this Plugin
+        - scriptSettings: the Settings for the script
         """
-        plugin.Plugin.__init__(self, owner)
+        plugin.Plugin.__init__(self, owner, scriptSettings)
 
     def _createInputEventHandlers(self):
         """Defines InputEventHandler fields for this script that can be
@@ -158,7 +159,7 @@
 
     import orca.script
     scrypt = orca.script.Script(None)
-    plugin = Plugin(scrypt)
+    plugin = Plugin(scrypt, None)
     print scrypt
     print plugin
 

Modified: branches/phase2/src/orca/plugins/debug_actions/plugin.py
==============================================================================
--- branches/phase2/src/orca/plugins/debug_actions/plugin.py	(original)
+++ branches/phase2/src/orca/plugins/debug_actions/plugin.py	Tue Sep 16 17:07:35 2008
@@ -42,15 +42,16 @@
 class Plugin(plugin.Plugin):
     """A plugin for getting debug information.
     """
-    def __init__(self, owner):
+    def __init__(self, owner, scriptSettings):
         """Creates a Plugin for the given script.
         This method should not be called by anyone except the
         owner.
 
         Arguments:
         - owner: the Script owning this Plugin
+        - scriptSettings: the Settings for the script
         """
-        plugin.Plugin.__init__(self, owner)
+        plugin.Plugin.__init__(self, owner, scriptSettings)
 
     def _createInputEventHandlers(self):
         """Defines InputEventHandler fields for this script that can be
@@ -149,7 +150,7 @@
 
     import orca.script
     scrypt = orca.script.Script(None)
-    plugin = Plugin(scrypt)
+    plugin = Plugin(scrypt, None)
     print scrypt
     print plugin
 

Modified: branches/phase2/src/orca/plugins/flat_review/plugin.py
==============================================================================
--- branches/phase2/src/orca/plugins/flat_review/plugin.py	(original)
+++ branches/phase2/src/orca/plugins/flat_review/plugin.py	Tue Sep 16 17:07:35 2008
@@ -42,15 +42,16 @@
 class Plugin(plugin.Plugin):
     """A plugin for handling flat review analysis of a window.
     """
-    def __init__(self, owner):
+    def __init__(self, owner, scriptSettings):
         """Creates a Plugin for the given script.
         This method should not be called by anyone except the
         owner.
 
         Arguments:
         - owner: the Script owning this Plugin
+        - scriptSettings: the Settings for the script
         """
-        plugin.Plugin.__init__(self, owner)
+        plugin.Plugin.__init__(self, owner, scriptSettings)
 
     def _createInputEventHandlers(self):
         """Defines InputEventHandler fields for this script that can be
@@ -619,7 +620,7 @@
 
     import orca.script
     scrypt = orca.script.Script(None)
-    plugin = Plugin(scrypt)
+    plugin = Plugin(scrypt, None)
     print scrypt
     print plugin
 

Modified: branches/phase2/src/orca/plugins/speech_parameters/plugin.py
==============================================================================
--- branches/phase2/src/orca/plugins/speech_parameters/plugin.py	(original)
+++ branches/phase2/src/orca/plugins/speech_parameters/plugin.py	Tue Sep 16 17:07:35 2008
@@ -42,15 +42,16 @@
 class Plugin(plugin.Plugin):
     """A plugin for adjusting speech parameters.
     """
-    def __init__(self, owner):
+    def __init__(self, owner, scriptSettings):
         """Creates a Plugin for the given script.
         This method should not be called by anyone except the
         owner.
 
         Arguments:
         - owner: the Script owning this Plugin
+        - scriptSettings: the Settings for the script
         """
-        plugin.Plugin.__init__(self, owner)
+        plugin.Plugin.__init__(self, owner, scriptSettings)
 
     def _createInputEventHandlers(self):
         """Defines InputEventHandler fields for this script that can be
@@ -134,7 +135,7 @@
 
     import orca.script
     scrypt = orca.script.Script(None)
-    plugin = Plugin(scrypt)
+    plugin = Plugin(scrypt, None)
     print scrypt
     print plugin
 

Modified: branches/phase2/src/orca/plugins/where_am_i/plugin.py
==============================================================================
--- branches/phase2/src/orca/plugins/where_am_i/plugin.py	(original)
+++ branches/phase2/src/orca/plugins/where_am_i/plugin.py	Tue Sep 16 17:07:35 2008
@@ -42,15 +42,16 @@
 class Plugin(plugin.Plugin):
     """A plugin for getting Where Am I information.
     """
-    def __init__(self, owner):
+    def __init__(self, owner, scriptSettings):
         """Creates a Plugin for the given script.
         This method should not be called by anyone except the
         owner.
 
         Arguments:
         - owner: the Script owning this Plugin
+        - scriptSettings: the Settings for the script
         """
-        plugin.Plugin.__init__(self, owner)
+        plugin.Plugin.__init__(self, owner, scriptSettings)
 
     def _createInputEventHandlers(self):
         """Defines InputEventHandler fields for this script that can be
@@ -140,7 +141,7 @@
 
     import orca.script
     scrypt = orca.script.Script(None)
-    plugin = Plugin(scrypt)
+    plugin = Plugin(scrypt, None)
     print scrypt
     print plugin
 

Modified: branches/phase2/src/orca/rolenames.py
==============================================================================
--- branches/phase2/src/orca/rolenames.py	(original)
+++ branches/phase2/src/orca/rolenames.py	Tue Sep 16 17:07:35 2008
@@ -28,6 +28,10 @@
 
 import pyatspi
 
+# TODO: settings is only imported because we're using the 
+# BRAILLE_ROLENAME_STYLE constants.  Those should be moved
+# into here or eliminated altogether.
+#
 import settings
 
 from orca_i18n import _  # for gettext support

Modified: branches/phase2/src/orca/script.py
==============================================================================
--- branches/phase2/src/orca/script.py	(original)
+++ branches/phase2/src/orca/script.py	Tue Sep 16 17:07:35 2008
@@ -53,18 +53,25 @@
 
 import braille
 import input_bindings
+import script_manager
+import settings
 import utils
 
+# The package where we expect to find user script settings.
+#
+settingsPackage = "script_settings"
+
 class Script:
     """The specific focus tracking scripts for applications.
     """
-    def __init__(self, application):
+    def __init__(self, application, userSettings):
         """Creates a script for the given application.
         This method should not be called by anyone except the
         focus_tracking_presenter.
 
         Arguments:
         - application: the Python Accessible application to create a script for
+        - userSettings: the Settings to use
         """
         self.application = application
 
@@ -78,6 +85,11 @@
         self._brailleBindings = \
             self._createBrailleBindings(self._inputEventHandlers)
 
+        # Load custom settings and also give the module a chance to
+        # override our keyboard and braille bindings.
+        #
+        self._loadSettings(userSettings)
+
         # The object which has the STATE_FOCUS state.
         #
         self.focus = None
@@ -92,12 +104,55 @@
         pluginClasses = self._getPluginClasses()
         for pluginClass in pluginClasses:
             try:
-                self._plugins.append(pluginClass(self))
+                self._plugins.append(pluginClass(self, self._settings))
             except:
                 log.exception("handled exception creating plugin:")
 
         self._completeInit()
 
+    def getSettingsModuleName(self):
+        name = script_manager.ScriptManager.getScriptModuleName(
+            self.application)
+        if name and len(name):
+            name = "script_settings." + name
+        return name
+
+    def _loadSettings(self, userSettings):
+        """Load the user's specific settings for a script.
+
+        Arguments:
+        - userSettings: the global user settings.
+        """
+        # TODO: Untested.  Could be buggy.
+        #
+        loaded = False
+        name = self.getSettingsModuleName()
+        if name:
+            try:
+                log.debug("looking for settings at %s.py..." % name)
+                settingsModule = __import__(name, globals(), locals(), [''])
+                log.debug("...found %s.py" % name)
+            except ImportError:
+                log.debug("...could not find %s.py" % name)
+            except:
+                log.exception("handled exception importing %s:" % name)
+            else:
+                try:
+                    self._settings = settingsModule.getSettings(userSettings)
+                except:
+                    log.exception("exception handled:")
+                else:
+                    loaded = True
+                    try:
+                        settingsModule.overrideBindings(
+                            self._keyBindings,
+                            self._brailleBindings)
+                    except:
+                        log.exception("exception handled:")
+
+        if not loaded:
+            self._settings = settings.Settings(userSettings)
+
     def _completeInit(self):
         """Completes the __init__ step.
         """

Modified: branches/phase2/src/orca/script_manager.py
==============================================================================
--- branches/phase2/src/orca/script_manager.py	(original)
+++ branches/phase2/src/orca/script_manager.py	Tue Sep 16 17:07:35 2008
@@ -24,27 +24,6 @@
 __copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-# 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,
-# the input_event.MODIFIER_ORCA bit will be set in the 'modifiers'
-# field of a KeyboardEvent input event.  The keys are currently
-# compared to the event_string of a keyboard input event from AT-SPI.
-#
-# The initial set of modifier keys is dependent upon whether the user
-# has specified a desktop or a laptop keyboard layout.
-#
-DESKTOP_MODIFIER_KEYS = ["Insert", "KP_Insert"]
-LAPTOP_MODIFIER_KEYS  = ["Caps_Lock"]
-orcaModifierKeys      = DESKTOP_MODIFIER_KEYS
-
-# Keyboard double-click period. If the same key is pressed within
-# this time period, it's considered to be a double-click and might
-# provide different functionality (for example, Numpad 5 double-click
-# spells the current word rather than speaks it).
-#
-doubleClickTimeout = 0.5
-
 # A list of toolkits whose events we need to process synchronously.
 # The only one right now is the Java toolkit (see bug #531869), but
 # we put this here to allow more toolkits to be more easily added
@@ -59,7 +38,7 @@
 # REMEMBER: to make something a package, the directory has to
 # have a __init__.py file in it.
 #
-scriptPackages = ["orca-scripts", "scripts", "scripts.apps", "scripts.toolkits"]
+scriptPackages = ["user_scripts", "scripts", "scripts.apps", "scripts.toolkits"]
 enableCustomScripts = True
 
 # A list that helps us map application names to script module
@@ -108,7 +87,14 @@
     passed to the active script only if it has indicated interest in the
     event."""
 
-    def __init__(self):
+    def __init__(self, userSettings):
+        """Creates a new ScriptManager.
+
+        Arguments:
+        - userSettings: the user settings from ~/.orca/user_settings.py
+        """
+        self._settings       = userSettings
+
         self._knownScripts   = {}
         self._activeScript   = None
         self._defaultScript  = None
@@ -174,33 +160,33 @@
     #                                                                      #
     ########################################################################
 
-    def _getScriptModuleName(app):
+    def getScriptModuleName(application):
         """Returns the module name of the script to use for a given
         application.  Any script mapping set via the setScriptMapping
         method is searched first, with the ultimate fallback being the
         name of the application itself.
 
         Arguments:
-        - app: the application to find a script module name for
+        - application: the application to find a script module name for
         """
-        if not app.name:
+        if not application.name:
             return None
 
-        name = app.name
+        name = application.name
         for mapping in scriptMappings:
             regExpression = mapping[0]
             moduleName = mapping[1]
-            if regExpression.match(app.name):
+            if regExpression.match(application.name):
                 log.debug("script mapping for %s is %s"
-                          % (app.name, moduleName))
+                          % (application.name, moduleName))
                 name = moduleName
                 break
 
         return name
 
-    _getScriptModuleName = staticmethod(_getScriptModuleName)
+    getScriptModuleName = staticmethod(getScriptModuleName)
 
-    def _createScript(self, app):
+    def _createScript(self, application):
         """For the given application name, create a new script instance.
         We'll first see if a mapping from appName to module name exists.
         If it does, we use that.  If it doesn't, we try the app name.
@@ -216,7 +202,7 @@
             # a syntax error in it, so we want to give script writers
             # a vehicle for debugging these types of things.
             #
-            moduleName = self._getScriptModuleName(app)
+            moduleName = self.getScriptModuleName(application)
             module = None
 
             if moduleName and len(moduleName):
@@ -239,7 +225,7 @@
                         log.exception("handled exception importing %s:" % name)
             if module:
                 try:
-                    script = module.Script(app)
+                    script = module.Script(application, self._settings)
                 except:
                     # We do not want the getScript method to fail.  If it does,
                     # we want to let the script developer know what went wrong,
@@ -253,20 +239,21 @@
         # default script. Note that this search is restricted to the "orca"
         # package for now.
         #
-        if (not script) and app and getattr(app, "toolkitName", None):
+        if (not script) and application \
+            and getattr(application, "toolkitName", None):
             for package in scriptPackages:
                 if package:
-                    name = '.'.join((package, app.toolkitName))
+                    name = '.'.join((package, application.toolkitName))
                 else:
-                    name = app.toolkitName
+                    name = application.toolkitName
                 try:
                     log.debug("looking for toolkit script %s.py..."
-                              % app.toolkitName)
+                              % application.toolkitName)
                     module = __import__(name,
                                         globals(),
                                         locals(),
                                         [''])
-                    script = module.Script(app)
+                    script = module.Script(application, self._settings)
                     log.debug("...found %s.py" % name)
                 except ImportError:
                     log.debug("...could not find %s.py" % name)
@@ -274,7 +261,7 @@
                     log.exception("handled exception importing %s:" % name)
 
         if not script:
-            script = default.Script(app)
+            script = default.Script(application, self._settings)
 
         return script
 
@@ -292,37 +279,37 @@
         try:
             desktop = pyatspi.Registry.getDesktop(0)
 
-            for app in self._knownScripts.keys():
-                if app not in desktop:
-                    script = self._knownScripts[app]
+            for application in self._knownScripts.keys():
+                if application not in desktop:
+                    script = self._knownScripts[application]
                     script.deactivate()
-                    del self._knownScripts[app]
-                    del app
+                    del self._knownScripts[application]
+                    del application
                     del script
         except:
             log.exception("exception while reclaiming scripts:")
 
-    def _getScript(self, app):
-        """Get a script for an app (and make it if necessary).  This is used
-        instead of a simple call to Script's constructor.
+    def _getScript(self, application):
+        """Get a script for an application (and make it if necessary).
+        This is used instead of a simple call to Script's constructor.
 
         Arguments:
-        - app: the Python app
+        - application: the Python app
 
         Returns an instance of a Script.
         """
         # We might not know what the app is.  In this case, just defer
         # to the default script for support.
         #
-        if not app:
+        if not application:
             if not self._defaultScript:
                 self._defaultScript = default.Script(None)
             script = self._defaultScript
-        elif app in self._knownScripts:
-            script = self._knownScripts[app]
+        elif application in self._knownScripts:
+            script = self._knownScripts[application]
         else:
-            script = self._createScript(app)
-            self._knownScripts[app] = script
+            script = self._createScript(application)
+            self._knownScripts[application] = script
 
         return script
 
@@ -388,7 +375,7 @@
 
         Returns True if this is a modifier key
         """
-        modifierKeys = orcaModifierKeys \
+        modifierKeys = self._settings.orcaModifierKeys \
             + [ 'Alt_L', 'Alt_R', 'Control_L', 'Control_R',
                 'Shift_L', 'Shift_R', 'Meta_L', 'Meta_R' ]
         return event_string in modifierKeys
@@ -436,7 +423,8 @@
         elif isinstance(lastInputEvent, input_event.BrailleEvent) \
             and (lastInputEvent.command != inputEvent.command):
             self._clickCount = 1
-        elif (inputEvent.time - lastInputEvent.time) < doubleClickTimeout:
+        elif (inputEvent.time - lastInputEvent.time) \
+            < self._settings.doubleClickTimeout:
             self._clickCount = min(3, self._clickCount + 1)
         else:
             self._clickCount = 1
@@ -471,7 +459,8 @@
             self._setClickCount(keyboardEvent)
             self._lastNonModifierEvent = keyboardEvent
 
-        isOrcaModifier = orcaModifierKeys.count(keyboardEvent.event_string) > 0
+        isOrcaModifier = self._settings.orcaModifierKeys.count(
+            keyboardEvent.event_string) > 0
         if keyboardEvent.type == pyatspi.KEY_PRESSED_EVENT:
             if isOrcaModifier:
                 self._orcaModifierPressed = True
@@ -725,7 +714,7 @@
     logging.basicConfig(format="%(name)s %(message)s")
     log.setLevel(logging.DEBUG)
 
-    manager = ScriptManager()
+    manager = ScriptManager(None)
 
     # Accessing the protected method is just for testing here.
     #

Modified: branches/phase2/src/orca/scripts/Makefile.am
==============================================================================
--- branches/phase2/src/orca/scripts/Makefile.am	(original)
+++ branches/phase2/src/orca/scripts/Makefile.am	Tue Sep 16 17:07:35 2008
@@ -1,4 +1,4 @@
-SUBDIRS = apps toolkits
+SUBDIRS = applications toolkits
 
 orca_pathdir=$(pyexecdir)
 

Added: branches/phase2/src/orca/scripts/applications/Makefile.am
==============================================================================
--- (empty file)
+++ branches/phase2/src/orca/scripts/applications/Makefile.am	Tue Sep 16 17:07:35 2008
@@ -0,0 +1,6 @@
+orca_pathdir=$(pyexecdir)
+
+orca_python_PYTHON = \
+	__init__.py
+
+orca_pythondir=$(pyexecdir)/orca/scripts/applications

Added: branches/phase2/src/orca/scripts/applications/__init__.py
==============================================================================

Modified: branches/phase2/src/orca/settings.py
==============================================================================
--- branches/phase2/src/orca/settings.py	(original)
+++ branches/phase2/src/orca/settings.py	Tue Sep 16 17:07:35 2008
@@ -21,53 +21,686 @@
 __copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
 __license__   = "LGPL"
 
-import logging
-log = logging.getLogger('orca.settings')
+import os
+
+from acss import ACSS
+from orca_i18n import _  # for gettext support
+from orca_i18n import Q_ # to provide qualified translatable strings
+
+screenWidth = 640
+screenHeight = 480
+tty = 7
+
+# Whether tool tips can be presented.
+#
+canPresentToolTips = False
+
+try:
+    # This can fail due to gtk not being available.  We want to
+    # be able to recover from that if possible.  The main driver
+    # for this is to allow "orca --text-setup" to work even if
+    # the desktop is not running.
+    #
+    import gtk.gdk
+    _display = gtk.gdk.display_get_default()
+    _screen = _display.get_default_screen()
+    _root_window = _screen.get_root_window()
+
+    # These are used for placing the magnifier zoomer.
+    #
+    screenWidth = _screen.get_width()
+    screenHeight = _screen.get_height()
+
+    # We want to know what the tty is so we can send it to BrlAPI
+    # if possible.
+    #
+    (_atom, _format, _data) = _root_window.property_get("XFree86_VT")
+    tty = _data[0]
+
+    # The bug that caused gnome-panel to crash is fixed in GTK 2.10.11.
+    _minimum_gtk_version = (100000 * 2) + (1000 * 10) +  11
+    _current_gtk_version  = (100000 * gtk.gtk_version[0]) \
+                            + (1000 * gtk.gtk_version[1]) \
+                            + gtk.gtk_version[2]
+    canPresentToolTips = (_current_gtk_version >= _minimum_gtk_version)
+except:
+    pass
+
+# Double-click period. If the same key is pressed within this time
+# period, it's considered to be a double-click and might provide
+# different functionality (for example, Numpad 5 double-click spells
+# the current word rather than speaks it).
+#
+doubleClickTimeout = 0.5
+
+# 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,
+# the input_event.MODIFIER_ORCA bit will be set in the 'modifiers'
+# field of a KeyboardEvent input event.  The keys are currently
+# compared to the event_string of a keyboard input event from AT-SPI.
+#
+# The initial set of modifier keys is dependent upon whether the user
+# has specified a desktop or a laptop keyboard layout.
+#
+DESKTOP_MODIFIER_KEYS = ["Insert", "KP_Insert"]
+LAPTOP_MODIFIER_KEYS  = ["Caps_Lock"]
+orcaModifierKeys      = DESKTOP_MODIFIER_KEYS
+
+# Verbosity levels (see setBrailleVerbosityLevel and
+# setSpeechVerbosityLevel).  These will have an impact on the various
+# individual verbosity levels for rolenames, accelerators, etc.
+#
+VERBOSITY_LEVEL_BRIEF   = 0
+VERBOSITY_LEVEL_VERBOSE = 1
+speechVerbosityLevel    = VERBOSITY_LEVEL_VERBOSE
+brailleVerbosityLevel   = VERBOSITY_LEVEL_VERBOSE
+
+BRAILLE_ROLENAME_STYLE_SHORT = 0 # three letter abbreviations
+BRAILLE_ROLENAME_STYLE_LONG  = 1 # full rolename
+brailleRolenameStyle    = BRAILLE_ROLENAME_STYLE_LONG
+
+# Braille Selection Indicator (see brailleSelectorIndicator).
+# The values represent the character to be used in the attrOr
+# field of brlAPI's writeStruct.
+#
+BRAILLE_SEL_NONE = 0x00 # 00000000
+BRAILLE_SEL_7    = 0x40 # 01000000
+BRAILLE_SEL_8    = 0x80 # 10000000
+BRAILLE_SEL_BOTH = 0xc0 # 11000000
+brailleSelectorIndicator = BRAILLE_SEL_BOTH
+
+# Braille Link Indicator (see brailleLinkIndicator).
+# The values represent the character to be used in the attrOr
+# field of brlAPI's writeStruct.
+#
+BRAILLE_LINK_NONE = 0x00 # 00000000
+BRAILLE_LINK_7    = 0x40 # 01000000
+BRAILLE_LINK_8    = 0x80 # 10000000
+BRAILLE_LINK_BOTH = 0xc0 # 11000000
+brailleLinkIndicator = BRAILLE_LINK_BOTH
+
+# Speech punctuation levels (see verbalizePunctuationStyle).
+#
+PUNCTUATION_STYLE_NONE = 3
+PUNCTUATION_STYLE_SOME = 2
+PUNCTUATION_STYLE_MOST = 1
+PUNCTUATION_STYLE_ALL  = 0
+verbalizePunctuationStyle = PUNCTUATION_STYLE_MOST
+
+# Say All styles (see sayAllStyle).
+#
+SAYALL_STYLE_LINE     = 0
+SAYALL_STYLE_SENTENCE = 1
+sayAllStyle = SAYALL_STYLE_SENTENCE
+
+# Settings that apply to the particular speech engine to
+# use as well details on the default voices to use.
+#
+speechFactoryModules    = ["espeechfactory", \
+                           "gnomespeechfactory", \
+                           "speechdispatcherfactory"]
+speechServerFactory     = "gnomespeechfactory"
+speechServerInfo        = None # None means let the factory decide.
+
+DEFAULT_VOICE           = "default"
+UPPERCASE_VOICE         = "uppercase"
+HYPERLINK_VOICE         = "hyperlink"
+
+voices = {
+    DEFAULT_VOICE   : ACSS({}),
+    UPPERCASE_VOICE : ACSS({ACSS.AVERAGE_PITCH : 5.6}),
+    HYPERLINK_VOICE : ACSS({})
+}
+
+# If True, enable speaking of speech indentation and justification.
+#
+enableSpeechIndentation = False
+
+# If True, enable braille.
+#
+enableBraille           = True
+
+# If True, enable the grouping of children on the braille display.
+# This is for things like displaying all items of a menu, tab list,
+# menu bar, etc., on a single line of the braille display.
+#
+enableBrailleGrouping   = False
+
+# If True, enable braille monitor.
+#
+enableBrailleMonitor    = False
+
+# string to indicate end of printed line for braille displays:
+#
+disableBrailleEOL = False
+brailleEOLIndicator = " $l"
+
+# Strings used to indicate checkbox/radio button states in braille:
+#
+brailleCheckBoxIndicators = ["< >", "<x>", "<->"]
+brailleRadioButtonIndicators = ["& y", "&=y"]
+
+# If True, enable magnification.
+#
+enableMagnifier                  = False
+
+# If True, changes made in the Magnifier pane will take place
+# immediately (i.e. without pressing the apply button).  Making
+# them permanent still requires pressing Apply or OK.
+#
+enableMagLiveUpdating            = True
+
+# If True, show the magnification cursor.
+#
+enableMagCursor                  = True
+
+# If True, allow an explicit size for the magnification cursor.
+#
+enableMagCursorExplicitSize      = False
+
+# If True, hide the system cursor.
+#
+magHideCursor                    = False
+
+# Size of the magnification cursor (in pixels).
+#
+magCursorSize                    = 32
+
+# Magnification cursor color value (hex color spec).
+#
+magCursorColor                   = '#000000'
+
+# If True, show the magnification cross-hairs.
+#
+enableMagCrossHair               = True
+
+# If True, enable magnification cross-hair clipping.
+#
+enableMagCrossHairClip           = False
+
+# Size of the magnification cross-hairs (in pixels).
+#
+magCrossHairSize                 = 16
+
+# Magnification cross-hair color value (hex color spec).
+#
+magCrossHairColor                   = '#000000'
+
+# Magnification Zoomer type.
+#
+MAG_ZOOMER_TYPE_FULL_SCREEN      = 0
+MAG_ZOOMER_TYPE_TOP_HALF         = 1
+MAG_ZOOMER_TYPE_BOTTOM_HALF      = 2
+MAG_ZOOMER_TYPE_LEFT_HALF        = 3
+MAG_ZOOMER_TYPE_RIGHT_HALF       = 4
+MAG_ZOOMER_TYPE_CUSTOM           = 5
+magZoomerType                    = MAG_ZOOMER_TYPE_FULL_SCREEN
+
+# Magnification zoomer region placement.
+#
+magZoomerLeft                    = screenWidth / 2
+magZoomerRight                   = screenWidth
+magZoomerTop                     = 0
+magZoomerBottom                  = screenHeight
+
+# Magnification zoom factor.
+#
+magZoomFactor                    = 4.0
+
+# If True, display a border around the magnification zoomer region.
+#
+enableMagZoomerBorder           = False
+
+# The color and size of the border which separates the target
+# display from the source display.
+#
+magZoomerBorderSize              = 1
+magZoomerBorderColor             = '#000000'
+
+# If True, invert the magnification zoomer colors.
+#
+enableMagZoomerColorInversion    = False
+
+# The brightness levels.  The range is from -1 to 1, with 0
+# being "normal"/no change.
+#
+magBrightnessLevel               = 0
+magBrightnessLevelRed            = 0
+magBrightnessLevelGreen          = 0
+magBrightnessLevelBlue           = 0
+
+# The contrast levels.  The range is from -1 to 1, with 0
+# being "normal"/no change.
+#
+magContrastLevel                 = 0
+magContrastLevelRed              = 0
+magContrastLevelGreen            = 0
+magContrastLevelBlue             = 0
+
+# Magnification libcolorblind color filtering mode (see magColorFilteringMode).
+#
+MAG_COLOR_FILTERING_MODE_NONE                 = 0
+MAG_COLOR_FILTERING_MODE_SATURATE_RED         = 1
+MAG_COLOR_FILTERING_MODE_SATURATE_GREEN       = 2
+MAG_COLOR_FILTERING_MODE_SATURATE_BLUE        = 3
+MAG_COLOR_FILTERING_MODE_DESATURATE_RED       = 4
+MAG_COLOR_FILTERING_MODE_DESATURATE_GREEN     = 5
+MAG_COLOR_FILTERING_MODE_DESATURATE_BLUE      = 6
+MAG_COLOR_FILTERING_MODE_POSITIVE_HUE_SHIFT   = 7
+MAG_COLOR_FILTERING_MODE_NEGATIVE_HUE_SHIFT   = 8
+magColorFilteringMode = MAG_COLOR_FILTERING_MODE_NONE
+
+# Magnification smoothing mode (see magSmoothingMode).
+#
+MAG_SMOOTHING_MODE_BILINEAR      = 0
+MAG_SMOOTHING_MODE_NONE          = 1
+magSmoothingMode                 = MAG_SMOOTHING_MODE_BILINEAR
+
+# Magnification tracking mode styles (see magMouseTrackingMode,
+# magControlTrackingMode and magTextTrackingMode).
+#
+MAG_TRACKING_MODE_CENTERED     = 0
+MAG_TRACKING_MODE_PROPORTIONAL = 1
+MAG_TRACKING_MODE_PUSH         = 2
+MAG_TRACKING_MODE_NONE         = 3
+
+# To retain backward compatibility with previous versions of Orca.
+#
+MAG_MOUSE_TRACKING_MODE_CENTERED = MAG_TRACKING_MODE_CENTERED
+MAG_MOUSE_TRACKING_MODE_PROPORTIONAL = MAG_TRACKING_MODE_PROPORTIONAL
+MAG_MOUSE_TRACKING_MODE_PUSH = MAG_TRACKING_MODE_PUSH
+MAG_MOUSE_TRACKING_MODE_NONE = MAG_TRACKING_MODE_NONE
+
+# Magnification mouse tracking mode.
+#
+magMouseTrackingMode           = MAG_TRACKING_MODE_CENTERED
+
+# Magnification control and menu item tracking mode.
+#
+magControlTrackingMode         = MAG_TRACKING_MODE_PUSH
+
+# Magnification text cursor tracking mode.
+#
+magTextTrackingMode            = MAG_TRACKING_MODE_PUSH
+
+# Magnification edge margin (percentage of screen).
+#
+magEdgeMargin                  = 0
+
+# If enabled, automatically repositions the mouse pointer to the
+# menu item or control with focus.
+#
+magPointerFollowsFocus         = False
+
+# If enabled, automatically repositions the mouse pointer into the
+# zoomer if it's not visible when initially moved.
+#
+magPointerFollowsZoomer        = True
+
+# Magnification source display
+#
+magSourceDisplay                 = ''
+
+# Magnification target display
+#
+magTargetDisplay                 = ''
+
+# if True, enable word echo.
+# Note that it is allowable for both enableEchoByWord and enableKeyEcho
+# to be True
+#
+enableEchoByWord        = False
+
+# if True, enable word echo.
+# Note that it is allowable for both enableEchoByWord and enableEchoBySentence
+# to be True.
+#
+enableEchoBySentence    = False
+
+# If True, enable key echo.
+# Note that it is allowable for both enableEchoByWord and enableKeyEcho
+# to be True
+#
+enableKeyEcho           = True
+
+# If True and key echo is enabled, echo Alphanumeric and punctuation keys.
+#
+enablePrintableKeys     = True
+
+# If True and key echo is enabled, echo Modifier keys.
+#
+enableModifierKeys      = True
+
+# If True and key echo is enabled, echo Locking keys.
+#
+enableLockingKeys       = True
+
+# If True and key echo is enabled, echo Function keys.
+#
+enableFunctionKeys      = True
+
+# If True and key echo is enabled, echo Action keys.
+#
+enableActionKeys        = True
+
+# If True and key echo is enabled, echo Navigation keys.
+#
+enableNavigationKeys    = False
+
+# If True, roles that have tutorial strings defined will be spoken.
+enableTutorialMessages = False
+
+# If True, show the main Orca window.
+#
+showMainWindow          = True
+
+# If True, quit Orca without confirmation when the user presses
+# <Orca-modifier>-q.
+#
+quitOrcaNoConfirmation  = False
+
+# Whether the user wants tooltips presented or not.
+#
+presentToolTips = False and canPresentToolTips
+
+# Keyboard layout options (see keyboardLayout).
+#
+GENERAL_KEYBOARD_LAYOUT_DESKTOP = 1
+GENERAL_KEYBOARD_LAYOUT_LAPTOP  = 2
+keyboardLayout                  = GENERAL_KEYBOARD_LAYOUT_DESKTOP
+
+# The red, green, blue values to use to outline the current item in
+# flat review mode. They are values between 0 and 65535 (0xFFFF), with
+# 65535 (0xFFFF) indicating full intensitiy
+#
+outlineColor = [ 0xFFFF, 0x0000, 0x0000 ]
+
+# Thickness in pixels of the outline around the the current item in flat 
+# review mode.
+#
+outlineThickness = 4
+
+# Margin between the object being outlined and the actual outline
+#
+outlineMargin = 1
+
+# The kind of outlining to do for flat review mode.
+#
+OUTLINE_NONE = 0
+OUTLINE_BOX = 1
+OUTLINE_LINE = 2
+OUTLINE_WEDGES = 3
+outlineStyle = OUTLINE_BOX
+
+# If True, speak blank lines.
+#
+speakBlankLines         = True
+
+# If True, reads all the table cells in the current row rather than just
+# the current one.
+#
+readTableCellRow    = True
+
+# If True, enable speaking of progress bar updates.
+#
+enableProgressBarUpdates = True
+
+# The interval (in seconds) between speaking progress bar updates. A value
+# of zero means that progress bar updates should not be spoken at all.
+#
+progressBarUpdateInterval = 10
+
+# Whether or not to present the 'read only' attribute of text areas
+# if we can detect they are read only or not.
+#
+presentReadOnlyText = True
+
+# Translators: this is used to indicate the user is in a text
+# area that is not editable.  It is meant to be spoken to the user.
+#
+# ONLY TRANSLATE THE PART AFTER THE PIPE CHARACTER |
+#
+speechReadOnlyString = Q_("text|read only")
+
+# Translators: this is used to indicate the user is in a text
+# area that is not editable.  It is meant to be a short abbreviation
+# to be presented on the braille display.
+#
+# ONLY TRANSLATE THE PART AFTER THE PIPE CHARACTER |
+#
+brailleReadOnlyString = Q_("text|rdonly")
+
+# The complete list of possible text attributes.
+#
+allTextAttributes = \
+    "bg-color:; bg-full-height:; bg-stipple:; direction:; editable:; " \
+    "family-name:; fg-color:; fg-stipple:; font-effect:none; indent:0; " \
+    "invisible:; justification:left; language:; left-margin:; " \
+    "line-height:100%; paragraph-style:Default; pixels-above-lines:; " \
+    "pixels-below-lines:; pixels-inside-wrap:; right-margin:; rise:; " \
+    "scale:; size:; stretch:; strikethrough:false; style:normal; " \
+    "text-decoration:none; text-rotation:0; text-shadow:none; " \
+    "underline:none; variant:; vertical-align:baseline; weight:400; " \
+    "wrap-mode:; writing-mode:lr-tb;"
+
+# The default set of text attributes to speak to the user. Specific
+# application scripts (or individual users can override these values if
+# so desired. Each of these text attributes is of the form <key>:<value>;
+# The <value> part will be the "default" value for that attribute. In
+# other words, if the attribute for a given piece of text has that value,
+# it won't be spoken. If no value part is given, then that attribute will
+# always be spoken.
+
+enabledSpokenTextAttributes = \
+    "size:; family-name:; weight:400; indent:0; underline:none; " \
+    "strikethrough:false; justification:left; style:normal;"
+
+# The default set of text attributes to be brailled for the user. Specific
+# application scripts (or individual users can override these values if
+# so desired. Each of these text attributes is of the form <key>:<value>;
+# The <value> part will be the "default" value for that attribute. In
+# other words, if the attribute for a given piece of text has that value,
+# it won't be spoken. If no value part is given, then that attribute will
+# always be brailled.
+
+enabledBrailledTextAttributes = \
+    "size:; family-name:; weight:400; indent:0; underline:none; " \
+    "strikethrough:false; justification:left; style:normal;"
+
+# Text Attributes Braille Indicator (see textAttributesBrailleIndicator).
+# The values represent the character to be used in the attrOr
+# field of brlAPI's writeStruct.
+#
+TEXT_ATTR_BRAILLE_NONE = 0x00 # 00000000
+TEXT_ATTR_BRAILLE_7    = 0x40 # 01000000
+TEXT_ATTR_BRAILLE_8    = 0x80 # 10000000
+TEXT_ATTR_BRAILLE_BOTH = 0xc0 # 11000000
+textAttributesBrailleIndicator = TEXT_ATTR_BRAILLE_NONE
+
+# The limit to enable a repeat character count to be spoken.
+# If set to 0, then there will be no repeat character count.
+# Each character will be spoken singularly (i.e. "dash dash
+# dash dash dash" instead of "five dash characters").
+# If the value is set to 1, 2 or 3 then it's treated as if it was
+# zero. In other words, no repeat character count is given.
+#
+repeatCharacterLimit = 4
+
+# The location of the user's preferences. By default this is ~/.orca.
+# It can be overridden by the Orca -d command line option.
+#
+userPrefsDir = os.path.join(os.environ["HOME"], ".orca")
+
+# Keyboard double-click period. If the same key is pressed within
+# this time period, it's considered to be a double-click and might
+# provide different functionality (for example, Numpad 5 double-click
+# spells the current word rather than speaks it).
+#
+doubleClickTimeout = 0.5
+
+# Listen to Live Region events.  Tells Gecko.onChildrenChanged() and 
+# onTextInserted() event handlers to monitor these events for live region
+# changes.  
+#
+inferLiveRegions = True
+
+# Contracted braille support.
+# 
+enableContractedBraille = False
+
+# Contracted braille table.
+# 
+brailleContractionTable = ''
+
+# Use Collection Interface?
+# 
+useCollection = True
+
+# Whether or not to speak the cell's coordinates when navigating
+# from cell to cell in a table.
+#
+speakCellCoordinates = True
+
+# Whether or not to speak the number of cells spanned by a cell
+# that occupies more than one row or column of a table.
+#
+speakCellSpan = True
+
+# Whether or not to announce the header that applies to the current
+# when navigating from cell to cell in a table.
+#
+speakCellHeaders = True
+
+# Whether blank cells should be skipped when navigating in a table
+# using table navigation commands.
+#
+skipBlankCells = False
+
+# The minimum size in characters to be considered a "large object"
+# or "chunk" for structural navigation.
+#
+largeObjectTextLength = 75
+
+# Whether to wrap around the document when structural navigation is used.
+wrappedStructuralNavigation = True
+
+# Report object under mouse.
+#
+enableMouseReview = False
+
+# Mouse dwell delay in milliseconds for mouse review mode. 
+# If the value is zero, the review will be read time.
+#
+mouseDwellDelay = 0
+
+# Maximum allowed drift while pointer is dwelling in mouse review mode.
+# 
+mouseDwellMaxDrift = 3
+
+# Whether or not we should present objects with STATE_REQUIRED to
+# the user. Currently, this is only seen with ARIA widgets.
+#
+presentRequiredState = False
+
+# Translators: Certain objects (such as form controls on web pages)
+# can have STATE_REQUIRED set on them to inform the user that this
+# field must be filled out. This string is the default string which
+# will be spoken and displayed in braille to indicate this state is
+# present.
+#
+brailleRequiredStateString = _("required")
+
+# Translators: Certain objects (such as form controls on web pages)
+# can have STATE_REQUIRED set on them to inform the user that this
+# field must be filled out. This string is the default string which
+# will be spoken and displayed in braille to indicate this state is
+# present.
+#
+speechRequiredStateString = _("required")
 
 class Settings(dict):
     """The class to hold settings that also delegate to other settings.
-    derived.
     """
 
-    def __init__(self, delegate=None):
+    def __init__(self, delegate=None, override=None):
         """Creates a new Settings instance backed by a delegate.
 
         Arguments:
         - delegate: a Settings instance to use if settings cannot be found here.
+        - override: a Settings instance to try first.
         """
         dict.__init__(self)
         self.delegate = delegate
+        self.override = override
+
+        if not self.override and self.delegate:
+            self.override = self.delegate.override
 
     def __getitem__(self, key):
         """Returns the settings value for the given key."""
         try:
-            return dict.__getitem__(self, key)
-        except KeyError:
+            return self.override[key]
+        except:
             try:
-                return self.delegate[key]
-            except TypeError:
-                raise KeyError(key)
+                return dict.__getitem__(self, key)
+            except KeyError:
+                try:
+                    return self.delegate[key]
+                except TypeError:
+                    raise KeyError(key)
 
-# Global settings that scripts can use when creating their own
-# Settings instances.
-#
-# TODO: fill these in with defaults from the old settings.py.
-#
-globalSettings = Settings()
+    def __getattr__(self, name):
+        if name in ["delegate", "override"]:
+            return dict.__getattr__(self, name)
+        else:
+            return self[name]
+
+    def __setattr__(self, name, value):
+        if name in ["delegate", "override"]:
+            dict.__setattr__(self, name, value)
+        else:
+            self[name] = value
+
+def getSettings():
+    moduleSettings = Settings()
+    for key in globals().keys():
+        if not key.startswith("_") \
+            and not key in ["Settings", "getSettings"]:
+            moduleSettings[key] = globals()[key]
+    return moduleSettings
 
 if __name__ == "__main__":
-    logging.basicConfig(format="%(name)s %(message)s")
-    log.setLevel(logging.DEBUG)
+    overrideSettings = Settings()
+    overrideSettings.forceThis = 4
+
+    parentSettings = Settings(None, overrideSettings)
+    parentSettings.parentSetting1 = 1
+    parentSettings.parentSetting2 = 2
+    parentSettings.forceThis = 22
+
+    print "Should be 4:", parentSettings.forceThis
+    print "Should be 1 2:", \
+        parentSettings.parentSetting1, \
+        parentSettings.parentSetting2
+
+    childSettings = Settings(parentSettings)
+    print "Should be 4:", childSettings.forceThis
+
+    childSettings["forceThis"] = 23
+    print "Should be 4:", childSettings["forceThis"]
+
+    print "Should be 1 2:", \
+        childSettings.parentSetting1, \
+        childSettings.parentSetting2
+
+    parentSettings.parentSetting2 = 42
+    print "Should be 1 42:", \
+        childSettings.parentSetting1, \
+        childSettings.parentSetting2
+
+    print getSettings()
 
-    globalSettings["foo"] = 2
-    print globalSettings["foo"]
-    blah = Settings(globalSettings)
-    blah["blah"] = 3
-    print blah["blah"]
-    print blah["foo"]
-    globalSettings["foo"] = 7
-    print blah["foo"]
-    try:
-        print blah["o"]
-    except KeyError:
-        log.exception("the following exception is expected:")
+    print "This exception is expected:"
+    print childSettings.foo
+        

Modified: branches/phase2/src/orca/utils.py
==============================================================================
--- branches/phase2/src/orca/utils.py	(original)
+++ branches/phase2/src/orca/utils.py	Tue Sep 16 17:07:35 2008
@@ -34,6 +34,12 @@
 import sys
 import traceback
 
+try:
+    import gconf
+    _gconfClient = gconf.client_get_default()
+except:
+    _gconfClient = None
+
 def logStack(logger):
     """Logs a snapshot of the stack to the given logger without
     including the stack trace for this specific method.
@@ -47,6 +53,86 @@
     logger.debug('current stack:\n %s' \
     % "".join(traceback.format_stack(sys._getframe(1), 100)).strip("\n")[1:])
 
+def isAccessibilityEnabled():
+    """Obtain/set information regarding whether accessibility is enabled
+    or not.
+    """
+    try:
+        return _gconfClient.get_bool("/desktop/gnome/interface/accessibility")
+    except:
+        return False
+
+def setAccessibilityEnabled(enable):
+    """Set whether accessibility is enabled or not.
+    """
+    try:
+        return _gconfClient.set_bool("/desktop/gnome/interface/accessibility",
+                                     enable)
+    except:
+        return False
+
+def isOrcaAutostarted():
+    """Return an indication of whether Orca autostart at login time is enabled.
+    """
+
+    userDesktopFile = os.path.join(os.environ["HOME"], ".config", \
+                                   "autostart", "orca.desktop")
+    return os.path.exists(userDesktopFile)
+
+def setOrcaAutostart(enable):
+    """Enable or disable the autostart of Orca at login time.
+
+    Arguments:
+    - enable: if True, whether Orca autostart at login time is enabled.
+
+    Returns an indication of whether the operation was successful.
+    """
+
+    status = True
+    systemDesktopFile = os.path.join(platform.prefix, platform.datadirname, \
+                                     "applications", "orca.desktop")
+    autostartDir = os.path.join(os.environ["HOME"], ".config", "autostart")
+    userDesktopFile = os.path.join(os.environ["HOME"], ".config", \
+                                   "autostart", "orca.desktop")
+
+    try:
+        # If the user wants to enable Orca autostart, then copy the
+        # orca.desktop file from /usr/share/applications to
+        # ~/.config/autostart directory (creating the autostart directory
+        # if neccessary).
+        #
+        # If the user wants to disable this feature, then just remove 
+        # ~/.config/autostart/orca.desktop (if it exists).
+        #
+        if enable:
+            try:
+                os.chdir(autostartDir)
+            except:
+                os.mkdir(autostartDir)
+            shutil.copy(systemDesktopFile, userDesktopFile)
+        else:
+            os.remove(userDesktopFile)
+    except:
+        status = False
+    return status
+
+def isGKSUGrabDisabled():
+    """Obtain/set information regarding whether the gksu keyboard grab is 
+    enabled or not.
+    """
+    try:
+        return _gconfClient.get_bool("/apps/gksu/disable-grab")
+    except:
+        return False
+
+def setGKSUGrabDisabled(disable):
+    """Set whether the gksu keyboard grab is enabled or not.
+    """
+    try:
+        return _gconfClient.set_bool("/apps/gksu/disable-grab", disable)
+    except:
+        return False
+
 ############################################################################
 #                                                                          #
 # METHODS FOR DEALING WITH SIGNALS, EXITING, ABORTING, AND TIMEOUTS        #



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