[pyatspi2] Move the registry settings code from settings.py to registry.py.



commit 9f0622c4b97ebdfba08bb9b7466d6946a9d21bc6
Author: Mark Doffman <mark doffman codethink co uk>
Date:   Sun Nov 8 18:43:08 2009 +0000

    Move the registry settings code from settings.py to registry.py.
    This is so that the GLib loop is not invoked by default before the registry has been used.
    
    Fix errors in non-cached version.

 pyatspi/Accessibility.py |    6 +--
 pyatspi/Makefile.am      |    1 -
 pyatspi/__init__.py      |    2 -
 pyatspi/accessible.py    |   41 +++++++++++---
 pyatspi/appevent.py      |   43 +++++++++++++--
 pyatspi/cache.py         |   40 ++------------
 pyatspi/desktop.py       |    8 +++
 pyatspi/registry.py      |  136 ++++++++++++++++++++++++++++++++++++++++++++--
 pyatspi/settings.py      |  104 -----------------------------------
 pyatspi/utils.py         |    4 +-
 10 files changed, 220 insertions(+), 165 deletions(-)
---
diff --git a/pyatspi/Accessibility.py b/pyatspi/Accessibility.py
index 8e7c82a..88d2785 100644
--- a/pyatspi/Accessibility.py
+++ b/pyatspi/Accessibility.py
@@ -12,10 +12,8 @@
 #along with this program; if not, write to the Free Software
 #Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
-from settings import get_registry, MAIN_LOOP_GLIB
-Registry = get_registry (MAIN_LOOP_GLIB)
-del get_registry
-del MAIN_LOOP_GLIB
+from registry import *
+Registry = Registry()
 
 from constants import *
 from utils import *
diff --git a/pyatspi/Makefile.am b/pyatspi/Makefile.am
index 55f1b72..8522259 100644
--- a/pyatspi/Makefile.am
+++ b/pyatspi/Makefile.am
@@ -32,7 +32,6 @@ pyatspi_PYTHON = \
 		relation.py		\
 		role.py			\
 		selection.py		\
-                settings.py             \
 		state.py		\
 		table.py		\
 		text.py			\
diff --git a/pyatspi/__init__.py b/pyatspi/__init__.py
index 4f35533..1abe86a 100644
--- a/pyatspi/__init__.py
+++ b/pyatspi/__init__.py
@@ -17,8 +17,6 @@ __version__ = (1, 9, 0)
 import constants
 from Accessibility import *
 
-from settings import *
-
 #This is a re-creation of the namespace pollution implemented
 #by PyORBit.
 import sys
diff --git a/pyatspi/accessible.py b/pyatspi/accessible.py
index e01d589..30a90ca 100644
--- a/pyatspi/accessible.py
+++ b/pyatspi/accessible.py
@@ -22,6 +22,8 @@ from role import Role, ROLE_NAMES
 from dbus.types import UInt32, Int32
 from dbus import UnknownMethodException, DBusException
 
+from exceptions import *
+
 __all__ = [
            "LOCALE_TYPE",
            "LOCALE_TYPE_COLLATE",
@@ -170,6 +172,20 @@ class BaseProxy (object):
         def dbus_object (self):
                 return self._dbus_object
 
+        # Proxy Equality ----------------------------------------------------------
+
+        def __eq__(self, other):
+                if other is None:
+                        return False
+                try:
+                        if self.app_name == other.app_name and \
+                           self.acc_path == other.acc_path:
+                                return True
+                        else:
+                                return False
+                except AttributeError:
+                        return False
+
         # D-Bus method wrapper ----------------------------------------------------------
 
         def get_dbus_method (self, *args, **kwargs):
@@ -198,7 +214,8 @@ class AccessibleImpl (BaseProxy):
 
         def getAttributes(self):
                 func = self.get_dbus_method("getAttributes", dbus_interface=ATSPI_ACCESSIBLE)
-                return [key + ':' + value for key, value in func().iteritems()]
+                attr = func ()
+                return [key + ':' + value for key, value in attr.iteritems()]
 
         def getChildAtIndex(self, index):
                 count = Int32(self._pgetter(self.dbus_interface, "childCount"))
@@ -217,6 +234,10 @@ class AccessibleImpl (BaseProxy):
                 relation_set = func()
                 return _marshal_relation_set(self.acc_factory, self._app_name, relation_set)
 
+        def getIndexInParent(self):
+                func = self.get_dbus_method("getIndexInParent", dbus_interface=ATSPI_ACCESSIBLE)
+                return func()
+
         def getRole(self):
                 func = self.get_dbus_method("getRole", dbus_interface=ATSPI_ACCESSIBLE)
                 return func()
@@ -278,6 +299,16 @@ class AccessibleImplCached (AccessibleImpl):
                         self._relation_set = _marshal_relation_set(self.acc_factory, self._app_name, relation_set)
                         return self._relation_set
 
+        def getIndexInParent(self):
+                parent = self.get_parent()
+                if parent == None:
+                        return -1
+                for i in range(0, parent.childCount):
+                        child = parent.getChildAtIndex(i)
+                        if self == child:
+                                return i
+                raise AccessibleObjectNoLongerExists("Child not found within parent")
+
         def getRole(self):
                 return Role(self.cached_data.role)
 
@@ -426,13 +457,7 @@ class Accessible(BaseProxy):
                 @return : a long integer indicating this object's index in the
                 parent's list.
                 """
-                if self.parent == None:
-                        return -1
-                for i in range(0, self.parent.childCount):
-                        child = self.parent.getChildAtIndex(i)
-                        if self.isEqual(child):
-                                return i
-                raise AccessibleObjectNoLongerExists("Child not found within parent")
+                return self._impl.getIndexInParent()
 
         def getLocalizedRoleName(self):
                 """
diff --git a/pyatspi/appevent.py b/pyatspi/appevent.py
index a75edad..05582ac 100644
--- a/pyatspi/appevent.py
+++ b/pyatspi/appevent.py
@@ -265,6 +265,7 @@ class _ApplicationEventRegister (object):
         def __init__ (self, bus):
                 self._bus = bus
                 self._cache = None
+                self._factory = None
                 self._event_listeners = {}
 
                 # All of this special casing is for the 'faked'
@@ -286,16 +287,47 @@ class _ApplicationEventRegister (object):
         def setCache (self, cache):
                 self._cache = cache
 
-        def notifyNameChange(self, event):
+        def setFactory (self, factory):
+                self._factory = factory
+
+        def notifyNameChange(self, name, path):
+                event = Event(self._factory,
+                              path,
+                              name,
+                              "org.freedesktop.atspi.Event.Object",
+                              "property-change",
+                              ("accessible-name", 0, 0, newdata.name))
                 self._callClients(self._name_listeners, event)
 
-        def notifyDescriptionChange(self, event):
+        def notifyDescriptionChange(self, name, path):
+                event = Event(self._factory,
+                              path,
+                              name,
+                              "org.freedesktop.atspi.Event.Object",
+                              "property-change",
+                              ("accessible-description", 0, 0, newdata.description))
                 self._callClients(self._description_listeners, event)
 
-        def notifyParentChange(self, event):
+        def notifyParentChange(self, name, path):
+                event = Event(self._factory,
+                              path,
+                              name,
+                              "org.freedesktop.atspi.Event.Object",
+                              "property-change",
+                              ("accessible-parent", 0, 0, ""))
                 self._callClients(self._parent_listeners, event)
 
-        def notifyChildrenChange(self, event):
+        def notifyChildrenChange(self, name, path, added):
+                if added:
+                        detail = "add"
+                else:
+                        detail = "remove"
+                event = Event(self._factory,
+                              path,
+                              name,
+                              "org.freedesktop.atspi.Event.Object",
+                              "children-changed",
+                              (detail, 0, 0, ""))
                 self._callClients(self._children_changed_listeners, event)
 
         def _registerFake(self, type, register, client, *names):
@@ -399,6 +431,9 @@ class _NullApplicationEventRegister (object):
         def setCache (self, cache):
                 pass
 
+        def setFactory (self, factory):
+                pass
+
         def notifyNameChange(self, event):
                 pass
 
diff --git a/pyatspi/cache.py b/pyatspi/cache.py
index 5761767..15ff185 100644
--- a/pyatspi/cache.py
+++ b/pyatspi/cache.py
@@ -274,51 +274,21 @@ class AccessibleCache(object):
 
         def _dispatch_event(self, olddata, newdata):
                 if olddata.name != newdata.name:
-                        event = Event(self._event_dispatcher.cache,
-                                       newdata.path,
-                                       self._bus_name,
-                                       "org.freedesktop.atspi.Event.Object",
-                                       "property-change",
-                                       ("accessible-name", 0, 0, newdata.name))
-                        self._event_dispatcher.notifyNameChange(event)
+                        self._event_dispatcher.notifyNameChange(self._bus_name, newdata.path)
 
                 if olddata.description != newdata.description:
-                        event = Event(self._event_dispatcher.cache,
-                                       newdata.path,
-                                       self._bus_name,
-                                       "org.freedesktop.atspi.Event.Object",
-                                       "property-change",
-                                       ("accessible-description", 0, 0, newdata.description))
-                        self._event_dispatcher.notifyDescriptionChange(event)
+                        self._event_dispatcher.notifyDescriptionChange(self._bus_name, newdata.path)
 
                 if olddata.parent != newdata.parent:
-                        event = Event(self._event_dispatcher.cache,
-                                       newdata.path,
-                                       self._bus_name,
-                                       "org.freedesktop.atspi.Event.Object",
-                                       "property-change",
-                                       ("accessible-parent", 0, 0, ""))
-                        self._event_dispatcher.notifyParentChange(event)
+                        self._event_dispatcher.notifyParentChange(self._bus_name, newdata.path)
 
                 removed, added = _list_items_added_removed (olddata.children, newdata.children)
 
                 if added:
-                        event = Event(self._event_dispatcher.cache,
-                                       newdata.path,
-                                       self._bus_name,
-                                       "org.freedesktop.atspi.Event.Object",
-                                       "children-changed",
-                                       ("add", 0, 0, ""))
-                        self._event_dispatcher.notifyChildrenChange(event)
+                        self._event_dispatcher.notifyChildrenChange(self._bus_name, newdata.path, True)
 
                 if removed:
-                        event = Event(self._event_dispatcher.cache,
-                                       newdata.path,
-                                       self._bus_name,
-                                       "org.freedesktop.atspi.Event.Object",
-                                       "children-changed",
-                                       ("remove", 0, 0, ""))
-                        self._event_dispatcher.notifyChildrenChange(event)
+                        self._event_dispatcher.notifyChildrenChange(self._bus_name, newdata.path, False)
 
         # TODO This should be the other way around. Single is more common than many.
         def _update_single(self, object):
diff --git a/pyatspi/desktop.py b/pyatspi/desktop.py
index 92fb1ca..31d679f 100644
--- a/pyatspi/desktop.py
+++ b/pyatspi/desktop.py
@@ -216,6 +216,14 @@ class BaseDesktop (object):
 
         # Bonobo interface --------------------------------------------------------------
 
+        def get_interfaces(self):
+                return [ATSPI_ACCESSIBLE, ATSPI_DESKTOP, ATSPI_COMPONENT]
+        _interfacesDoc = \
+                """
+                D-Bus interfaces supported by this accessible object.
+                """
+        interfaces = property(fget=get_interfaces, doc=_interfacesDoc)
+
         def queryInterface(self, interface):
                 """
                 Gets a different accessible interface for this object
diff --git a/pyatspi/registry.py b/pyatspi/registry.py
index ae3b111..726d8ae 100644
--- a/pyatspi/registry.py
+++ b/pyatspi/registry.py
@@ -21,6 +21,16 @@
 
 #------------------------------------------------------------------------------
 
+import dbus
+import os as _os
+
+from factory import CachedAccessibleFactory, AccessibleFactory
+from appevent import _ApplicationEventRegister, _NullApplicationEventRegister
+from deviceevent import _DeviceEventRegister, _NullDeviceEventRegister
+from desktop import *
+from cache import *
+from loop import *
+
 from deviceevent import KEY_PRESSED_EVENT as _KEY_PRESSED_EVENT
 from deviceevent import KEY_RELEASED_EVENT as _KEY_RELEASED_EVENT
 
@@ -28,6 +38,20 @@ from interfaces import ATSPI_REGISTRY_NAME as _ATSPI_REGISTRY_NAME
 from interfaces import ATSPI_DESKTOP_PATH as _ATSPI_DESKTOP_PATH
 from interfaces import ATSPI_DESKTOP as _ATSPI_DESKTOP
 
+__all__ = ["Registry",
+           "set_default_registry",
+           "MAIN_LOOP_GLIB",
+           "MAIN_LOOP_NONE",
+           "MAIN_LOOP_QT"]
+
+#------------------------------------------------------------------------------
+
+MAIN_LOOP_GLIB = 'GLib'
+MAIN_LOOP_NONE = 'None'
+MAIN_LOOP_QT   = 'Qt'
+
+#------------------------------------------------------------------------------
+
 class Registry(object):
         """
         Wraps the Accessibility.Registry to provide more Pythonic registration for
@@ -52,14 +76,16 @@ class Registry(object):
         """
         __shared_state = {}
 
-        def __init__(self, device_event_register, app_event_register, desktop, accessible_factory, main_loop):
+        def __init__(self):
                 self.__dict__ = self.__shared_state
 
-                self.device_event_register = device_event_register
-                self.app_event_register = app_event_register
-                self.desktop = desktop
-                self.accessible_factory = accessible_factory
-                self.main_loop = main_loop
+                self.has_implementations = False
+
+                self.device_event_register = None
+                self.app_event_register = None
+                self.desktop = None
+                self.accessible_factory = None
+                self.main_loop = None
 
         def __call__(self):
                 """
@@ -68,6 +94,80 @@ class Registry(object):
                 """
                 return self
 
+        def _set_registry (self, main_loop_type, app_name=None):
+                """
+                Creates a new 'Registry' object and sets this object
+                as the default returned by pyatspi.Registry.
+
+                The default registry (without calling this function) uses the
+                GLib main loop with caching. It connects to a registry daemon.
+
+                This function should be called before pyatspi is used if you
+                wish to change these defaults.
+
+                @param main_loop_type: 'GLib', 'None' or 'Qt'. If 'None' is selected then caching
+                                       is disabled.
+
+                @param use_registry: Whether to connect to a registry daemon for device events.
+                                     Without this the application to connect to must be declared in the
+                                     app_name parameter.
+
+                @param app_name: D-Bus name of the application to connect to when not using the registry daemon.
+                """
+                connection = dbus.SessionBus()
+
+                # Set up the main loop
+                if main_loop_type == MAIN_LOOP_GLIB:
+                        loop   = GObjectMain()
+                        proxy  = GObjectProxy
+                elif main_loop_type == MAIN_LOOP_NONE:
+                        loop    = NullMain()
+                        proxy  = dbus.connection.ProxyObject
+                else:
+                        raise Exception ("Unknown main loop specified")
+
+                # Set up the device event controllers
+                if app_name:
+                        devreg = _NullDeviceEventRegister()
+                        appreg = _NullApplicationEventRegister()
+                else:
+                        devreg = _DeviceEventRegister(connection)
+                        appreg = _ApplicationEventRegister(connection)
+
+                # Set up the cache / desktop and accesible factories.
+                if main_loop_type == MAIN_LOOP_GLIB:
+                        if app_name:
+                                cache = AccessibleCache(appreg, connection, app_name)
+                        else:
+                                cache = ApplicationCache(appreg, connection)
+                        appreg.setCache (cache)
+                        factory = CachedAccessibleFactory (cache, connection, proxy)
+                        desktop = CachedDesktop (cache, factory)
+
+                elif main_loop_type == MAIN_LOOP_NONE:
+                        factory = AccessibleFactory(connection, proxy)
+                        if app_name:
+                                desktop = TestDesktop (connection, app_name, factory)
+                        else:
+                                desktop = Desktop (connection, factory)
+
+                else:
+                        raise Exception ("Unknown main loop specified")
+       
+                appreg.setFactory (factory)
+
+                # Create the registry object
+                self.has_implementations = True
+
+                self.device_event_register = devreg
+                self.app_event_register = appreg
+                self.desktop = desktop
+                self.accessible_factory = factory
+                self.main_loop = loop
+
+        def _set_default_registry (self):
+                self._set_registry (MAIN_LOOP_GLIB)
+
         def start(self, async=False, gil=True):
                 """
                 Enter the main loop to start receiving and dispatching events.
@@ -81,6 +181,8 @@ class Registry(object):
                         Note - No Longer used.
                 @type gil: boolean
                 """
+                if not self.has_implementations:
+                        self._set_default_registry ()
                 try:
                         self.main_loop.run()
                 except KeyboardInterrupt:
@@ -90,6 +192,8 @@ class Registry(object):
                 """
                 Quits the main loop.
                 """
+                if not self.has_implementations:
+                        self._set_default_registry ()
                 self.main_loop.stop()
 
         def getDesktopCount(self):
@@ -110,6 +214,8 @@ class Registry(object):
                 @return: Desktop reference
                 @rtype: Accessibility.Desktop
                 """
+                if not self.has_implementations:
+                        self._set_default_registry ()
                 return self.desktop
 
         def registerEventListener(self, client, *names):
@@ -132,6 +238,8 @@ class Registry(object):
                 @param names: List of full or partial event names
                 @type names: list of string
                 """
+                if not self.has_implementations:
+                        self._set_default_registry ()
                 self.app_event_register.registerEventListener (client, *names)
 
         def deregisterEventListener(self, client, *names):
@@ -151,6 +259,8 @@ class Registry(object):
                         registered?
                 @rtype: boolean
                 """
+                if not self.has_implementations:
+                        self._set_default_registry ()
                 self.app_event_register.deregisterEventListener (client, *names)
 
         # -------------------------------------------------------------------------------
@@ -191,6 +301,8 @@ class Registry(object):
                         AT-SPI is in the foreground? (requires xevie)
                 @type global_: boolean
                 """
+                if not self.has_implementations:
+                        self._set_default_registry ()
                 self.device_event_register.registerKeystrokeListener (client,
                                                                       key_set,
                                                                       mask,
@@ -224,6 +336,8 @@ class Registry(object):
                 @type kind: list
                 @raise KeyError: When the client isn't already registered for events
                 """
+                if not self.has_implementations:
+                        self._set_default_registry ()
                 self.device_event_register.deregisterKeystrokeListener (client, key_set, mask, kind)
 
         # -------------------------------------------------------------------------------
@@ -256,6 +370,8 @@ class Registry(object):
                 @param kind: Kind of event to synthesize
                 @type kind: integer
                 """
+                if not self.has_implementations:
+                        self._set_default_registry ()
                 self.device_event_register.generateKeyboardEvent (keycode, keysym, kind)
 
         def generateMouseEvent(self, x, y, name):
@@ -272,4 +388,12 @@ class Registry(object):
                 @param name: Name of the event to generate
                 @type name: string
                 """
+                if not self.has_implementations:
+                        self._set_default_registry ()
                 self.device_event_register.generateMouseEvent (x, y, name)
+
+#------------------------------------------------------------------------------
+
+def set_default_registry (main_loop, app_name=None):
+        registry = Registry ()
+        registry._set_registry (main_loop, app_name)
diff --git a/pyatspi/utils.py b/pyatspi/utils.py
index 61cad1e..db3e360 100644
--- a/pyatspi/utils.py
+++ b/pyatspi/utils.py
@@ -23,6 +23,8 @@ import relation
 import state
 import registry
 
+from deviceevent import *
+
 __all__ = [
                 "setCacheLevel",
                 "getCacheLevel",
@@ -159,7 +161,7 @@ def allModifiers():
         L{registry.Registry.registerKeystrokeListener}.
         """
         mask = 0
-        while mask <= (1 << registry.MODIFIER_NUMLOCK):
+        while mask <= (1 << MODIFIER_NUMLOCK):
                 yield mask
                 mask += 1
 



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