[pyatspi2] Add children-changed event emission for top-level accessibles.



commit cfdf29c41d6e4447cfc79bfe176805da349dcfe3
Author: Mark Doffman <mark doffman codethink co uk>
Date:   Mon Jan 11 10:26:21 2010 -0800

    Add children-changed event emission for top-level accessibles.

 pyatspi/accessible.py |   42 ++++++++++++------------
 pyatspi/appevent.py   |   83 ++++++++++++++++++++++++++++++++++++++++++++++---
 pyatspi/cache.py      |   25 +++++++++++++-
 pyatspi/registry.py   |    2 +-
 4 files changed, 123 insertions(+), 29 deletions(-)
---
diff --git a/pyatspi/accessible.py b/pyatspi/accessible.py
index f430f9b..fedf09d 100644
--- a/pyatspi/accessible.py
+++ b/pyatspi/accessible.py
@@ -267,14 +267,14 @@ class Accessible(BaseProxy):
         # Cache data --------------------------------------------------------------------
 
         @property
-	def cached (self):
+	def _cached (self):
                 if self._cache is not None:
 		        return (self.app_name, self.acc_path) in self._cache
                 else:
                         return False
 
         @property
-	def cached_data (self):
+	def _cached_data (self):
                 if self._cache is not None:
 		        return self._cache[(self.app_name, self.acc_path)]
                 else:
@@ -287,8 +287,8 @@ class Accessible(BaseProxy):
                 Get the containing Application for this object.
                 @return the Application instance to which this object belongs.
                 """
-                if self.cached:
-                	return self.acc_factory (*self.cached_data.application)
+                if self._cached:
+                	return self.acc_factory (*self._cached_data.application)
 		else:
                         func = self.get_dbus_method("GetApplication", dbus_interface=ATSPI_ACCESSIBLE)
 			name, path = func ()
@@ -336,8 +336,8 @@ class Accessible(BaseProxy):
                 an in parameter indicating which child is requested (zero-indexed).
                 @return : the 'nth' Accessible child of this object.
                 """
-                if self.cached:
-                        (name, path) = self.cached_data.children[index]
+                if self._cached:
+                        (name, path) = self._cached_data.children[index]
                 else:
                         count = Int32(self._pgetter(ATSPI_ACCESSIBLE, "ChildCount"))
                         if index >= count:
@@ -353,7 +353,7 @@ class Accessible(BaseProxy):
                 @return : a long integer indicating this object's index in the
                 parent's list.
                 """
-                if self.cached:
+                if self._cached:
                         parent = self.get_parent()
                         if parent == None:
                                 return -1
@@ -396,8 +396,8 @@ class Accessible(BaseProxy):
                 @return : a Role indicating the type of UI role played by this
                 object.
                 """
-                if self.cached:
-                        return Role(self.cached_data.role)
+                if self._cached:
+                        return Role(self._cached_data.role)
                 else:
                         func = self.get_dbus_method("GetRole", dbus_interface=ATSPI_ACCESSIBLE)
                         return Role(func())
@@ -416,8 +416,8 @@ class Accessible(BaseProxy):
                 @return : a StateSet encapsulating the currently true states
                 of the object.
                 """
-                if self.cached:
-                        return _marshal_state_set(cached_data.state)
+                if self._cached:
+                        return _marshal_state_set(_cached_data.state)
                 else:
                         func = self.get_dbus_method("GetState", dbus_interface=ATSPI_ACCESSIBLE)
                         return _marshal_state_set(func())
@@ -437,8 +437,8 @@ class Accessible(BaseProxy):
                 return self.__eq__(other)
 
         def get_childCount(self):
-                if self.cached:
-                        return len(self.cached_data.children)
+                if self._cached:
+                        return len(self._cached_data.children)
                 else:
                         return Int32(self._pgetter(ATSPI_ACCESSIBLE, "ChildCount"))
         _childCountDoc = \
@@ -450,8 +450,8 @@ class Accessible(BaseProxy):
         getChildCount = get_childCount
 
         def get_description(self):
-                if self.cached:
-                        return self.cached_data.description
+                if self._cached:
+                        return self._cached_data.description
                 else:
                         return self._pgetter(ATSPI_ACCESSIBLE, "Description")
         _descriptionDoc = \
@@ -461,8 +461,8 @@ class Accessible(BaseProxy):
         description = property(fget=get_description, doc=_descriptionDoc)
 
         def get_name(self):
-                if self.cached:
-                        return self.cached_data.name
+                if self._cached:
+                        return self._cached_data.name
                 else:
                         return self._pgetter(ATSPI_ACCESSIBLE, "Name")
         _nameDoc = \
@@ -472,8 +472,8 @@ class Accessible(BaseProxy):
         name = property(fget=get_name, doc=_nameDoc)
 
         def get_parent(self):
-                if self.cached:
-                        name, path = self.cached_data.parent
+                if self._cached:
+                        name, path = self._cached_data.parent
                 else:
 		        name, path = self._pgetter (ATSPI_ACCESSIBLE, "Parent")
                 return self.acc_factory (name, path, ATSPI_ACCESSIBLE)
@@ -484,8 +484,8 @@ class Accessible(BaseProxy):
         parent = property(fget=get_parent, doc=_parentDoc)
 
         def get_interfaces(self):
-                if self.cached:
-                        return self.cached_data.interfaces
+                if self._cached:
+                        return self._cached_data.interfaces
                 else:
                         func = self.get_dbus_method("GetInterfaces", dbus_interface=ATSPI_ACCESSIBLE)
                         return func()
diff --git a/pyatspi/appevent.py b/pyatspi/appevent.py
index 6bada85..cc2dafd 100644
--- a/pyatspi/appevent.py
+++ b/pyatspi/appevent.py
@@ -257,8 +257,15 @@ class Event(object):
 
                 	data = event[3]
 
-                	if name == "object_bounds_changed":
+                	if self.type.is_subtype (EventType ("object:bounds-changed")):
                         	self.any_data = BoundingBox(*data)
+                        elif self.type.is_subtype (EventType ("object:children-changed")):
+				name, path = data;
+				self.any_data = self._acc_factory (name, path, interfaces.ATSPI_ACCESSIBLE)
+				self.any_data = ""
+			elif self.type.is_subtype (EventType ("object:property-change:parent")):
+				name, path = data;
+				self.any_data = self._acc_factory (name, path, interfaces.ATSPI_ACCESSIBLE)
                 	else:
                         	self.any_data = data
 
@@ -276,9 +283,8 @@ class Event(object):
         def source(self):
                 if not self._source:
                         try:
-                                name, path = self._source_application
-                                self._source = self._acc_factory (name,
-                                                                  path,
+                                self._source = self._acc_factory (self._source_application,
+                                                                  self._source_path,
                                                                   interfaces.ATSPI_ACCESSIBLE)
                         except AccessibleObjectNoLongerExists:
                                 pass
@@ -314,11 +320,71 @@ class _ApplicationEventRegister (object):
 
                 self._event_listeners = {}
 
+                self._children_changed_type = EventType("object:children-changed")
+                self._children_changed_listeners = {}
+
         def _callClients(self, register, event):
                 for client in register.keys():
                         client(event)
 
-        def registerEventListener(self, client, *names):
+        def notifyChildrenChange(self, name, path, childref, added):
+                if added:
+                        detail = "add"
+                else:
+                        detail = "remove"
+                event = Event((detail, 0, 0, childref),
+                              self._factory,
+                              path,
+                              name,
+                              "org.freedesktop.atspi.Event.Object",
+                              "children-changed")
+
+                self._callClients(self._children_changed_listeners, event)
+
+        def _registerFake(self, type, register, client, *names):
+                """
+                Registers a client from a register of clients
+                for 'Fake' events emitted by the cache.
+                """
+                try:
+                        registered = register[client]
+                except KeyError:
+                        registered = []
+                        register[client] = registered
+
+                for name in names:
+                        new_type = EventType(name)
+                        if new_type.is_subtype(type):
+                                registered.append(new_type.name)
+
+                if registered == []:
+                        del(register[client])
+
+        def _deregisterFake(self, type, register, client, *names):
+                """
+                Deregisters a client from a register of clients
+                for 'Fake' events emitted by the cache.
+                """
+                try:
+                        registered = register[client]
+                except KeyError:
+                        return True
+
+                for name in names:
+                        remove_type = EventType(name)
+
+                        copy = registered[:]
+                        for i in range(0, len(copy)):
+                                type_name = copy[i]
+                                registered_type = EventType(type_name)
+
+                                if remove_type.is_subtype(registered_type):
+                                        del(registered[i])
+
+                if registered == []:
+                        del(register[client])
+
+        def registerEventListener (self, client, *names):
                 try:
                         registered = self._event_listeners[client]
                 except KeyError:
@@ -330,6 +396,8 @@ class _ApplicationEventRegister (object):
                         registered.append((new_type.name,
                                            event_type_to_signal_reciever(self._bus, self._factory, client, new_type)))
 
+                self._registerFake(self._children_changed_type, self._children_changed_listeners, client, *names)
+
         def deregisterEventListener(self, client, *names):
                 try:
                         registered = self._event_listeners[client]
@@ -356,12 +424,17 @@ class _ApplicationEventRegister (object):
                 if registered == []:
                         del(self._event_listeners[client])
 
+                self._deregisterFake(self._children_changed_type, self._children_changed_listeners, client, *names)
+
                 return missing
 
 #------------------------------------------------------------------------------
 
 class _NullApplicationEventRegister (object):
 
+        def notifyChildrenChange(self, name, path, added):
+		pass
+
         def registerEventListener(self, client, *names):
                 pass
 
diff --git a/pyatspi/cache.py b/pyatspi/cache.py
index 53a3615..a95c52c 100644
--- a/pyatspi/cache.py
+++ b/pyatspi/cache.py
@@ -39,10 +39,12 @@ class ApplicationCache(object):
         _APPLICATIONS_ADD = 1
         _APPLICATIONS_REMOVE = 0
 
-        def __init__(self):
+        def __init__(self, event_dispatcher=None):
                 self._connection = AccessibilityBus ()
                 self._factory = None
 
+		self._event_dispatcher = event_dispatcher
+
                 self._application_list = []
                 self._application_cache = {}
 
@@ -81,7 +83,7 @@ class ApplicationCache(object):
 	def __getitem__ (self, key):
 		try:
 			name, path = key
-			return self._application_cache[app_name][key]
+			return self._application_cache[name][key]
 		except Exception:
 			raise KeyError ()
 
@@ -96,10 +98,21 @@ class ApplicationCache(object):
                 if update_type == ApplicationCache._APPLICATIONS_ADD:
                         self._application_list.append(bus_name)
                         self._application_cache[bus_name] = AccessibleCache(bus_name)
+			if self._event_dispatcher:
+                        	self._event_dispatcher.notifyChildrenChange(ATSPI_REGISTRY_NAME,
+                                	                                    ATSPI_DESKTOP_PATH,
+									    self._application_cache[bus_name].root, 
+                                        	                            True)
                 elif update_type == ApplicationCache._APPLICATIONS_REMOVE:
+			if self._event_dispatcher:
+                        	self._event_dispatcher.notifyChildrenChange(ATSPI_REGISTRY_NAME,
+                                	                                    ATSPI_DESKTOP_PATH,
+									    self._application_cache[bus_name].root, 
+                                        	                            False)
                         self._application_list.remove(bus_name)
                         del(self._application_cache[bus_name])
 
+
 #------------------------------------------------------------------------------
 
 class _CacheData(object):
@@ -177,6 +190,9 @@ class AccessibleCache(object):
 
         _ATSPI_EVENT_OBJECT_INTERFACE = "org.freedesktop.atspi.Event.Object"
 
+        _CACHE_PATH = '/org/at_spi/cache'
+        _CACHE_INTERFACE = 'org.freedesktop.atspi.Cache'
+
         def __init__(self, bus_name):
                 """
                 Creates a cache.
@@ -211,6 +227,11 @@ class AccessibleCache(object):
 						     sender_keyword="sender",
 						     path_keyword="path")
 
+                obj = self._connection.get_object (bus_name, self._CACHE_PATH)
+                cache = dbus.Interface (obj, self._CACHE_INTERFACE)
+
+                self.root = cache.GetRoot ()
+
         def __getitem__(self, key):
                 try:
                         name, path = key
diff --git a/pyatspi/registry.py b/pyatspi/registry.py
index be86e7d..182ad72 100644
--- a/pyatspi/registry.py
+++ b/pyatspi/registry.py
@@ -138,7 +138,7 @@ class Registry(object):
                         if app_name:
                                 cache = AccessibleCache(app_name)
                         else:
-                                cache = ApplicationCache()
+                                cache = ApplicationCache(appreg)
 
                 factory.set_cache (cache)
 		factory.set_desktop (desktop)



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