1 #Copyright (C) 2008 Codethink Ltd
3 #This library is free software; you can redistribute it and/or
4 #modify it under the terms of the GNU Lesser General Public
5 #License version 2 as published by the Free Software Foundation.
7 #This program is distributed in the hope that it will be useful,
8 #but WITHOUT ANY WARRANTY; without even the implied warranty of
9 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 #GNU General Public License for more details.
11 #You should have received a copy of the GNU Lesser General Public License
12 #along with this program; if not, write to the Free Software
13 #Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 from event import Event as _Event
19 #------------------------------------------------------------------------------
21 class _CacheData(object):
32 def __init__(self, data):
35 def _update(self, data):
36 #Don't cache the path here, used as lookup in cache object dict.
46 #------------------------------------------------------------------------------
48 def _list_items_added_removed (l1, l2):
50 Returns a tuple (boolean, boolean).
51 The first value indicates if, when
52 moving from l1 to l2, any items have been added.
53 The second value indicates whether any items have
56 l1notl2 = [item for item in l1 if item not in l2]
57 l2notl1 = [item for item in l2 if item not in l1]
58 return ((len(l1notl2) > 0), (len(l2notl1) > 0))
60 #------------------------------------------------------------------------------
62 class AccessibleCache(object):
64 There is one accessible cache per application.
65 For each application the accessible cache stores
66 data on every accessible object within the app.
68 It also acts as the factory for creating client
69 side proxies for these accessible objects.
71 connection - DBus connection.
72 busName - Name of DBus connection where cache interface resides.
75 _PATH = '/org/freedesktop/atspi/tree'
76 _INTERFACE = 'org.freedesktop.atspi.Tree'
77 _GET_METHOD = 'getTree'
78 _UPDATE_SIGNAL = 'updateTree'
80 def __init__(self, registry, connection, bus_name):
84 connection - DBus connection.
85 busName - Name of DBus connection where cache interface resides.
87 self._registry = registry
88 self._connection = connection
89 self._bus_name = bus_name
91 obj = connection.get_object(bus_name, self._PATH, introspect=False)
92 itf = _dbus.Interface(obj, self._INTERFACE)
96 get_method = itf.get_dbus_method(self._GET_METHOD)
97 self._update_objects(get_method())
99 self._signalMatch = itf.connect_to_signal(self._UPDATE_SIGNAL, self._update_handler)
101 obj = connection.get_object(self._bus_name, self._PATH, introspect=False)
102 itf = _dbus.Interface(obj, self._INTERFACE)
104 self._root = itf.getRoot()
106 def __getitem__(self, key):
107 return self._objects[key]
109 def __contains__(self, key):
110 return key in self._objects
112 def _dispatch_event(self, olddata, newdata):
113 if olddata.name != newdata.name:
114 event = _Event(self._registry.cache,
117 "org.freedesktop.atspi.Event.Object",
119 ("name", 0, 0, newdata.name))
120 self._registry._notifyNameChange(event)
122 if olddata.description != newdata.description:
123 event = _Event(self._registry.cache,
126 "org.freedesktop.atspi.Event.Object",
128 ("description", 0, 0, description))
129 self._registry._notifyDescriptionChange(event)
131 if olddata.parent != newdata.parent:
132 event = _Event(self._registry.cache,
135 "org.freedesktop.atspi.Event.Object",
137 ("parent", 0, 0, ""))
138 self._registry._notifyParentChange(event)
140 added, removed = _list_items_added_removed (olddata.children, newdata.children)
143 event = _Event(self._registry.cache,
146 "org.freedesktop.atspi.Event.Object",
149 self._registry._notifyChildrenChange(event)
152 event = _Event(self._registry.cache,
155 "org.freedesktop.atspi.Event.Object",
157 ("remove", 0, 0, ""))
158 self._registry._notifyChildrenChange(event)
160 def _update_handler(self, update, remove):
161 self._remove_objects(remove)
162 self._update_objects(update)
164 def _update_objects(self, objects):
165 cache_update_objects = []
167 #First element is the object path.
169 if path in self._objects:
170 olddata = self._objects[path]
171 newdata = _CacheData(data)
172 cache_update_objects.append((olddata, newdata))
173 self._objects[path] = newdata
175 self._objects[path] = _CacheData(data)
176 for old, new in cache_update_objects:
177 self._dispatch_event(old, new)
179 def _remove_objects(self, paths):
181 # TODO I'm squashing a possible error here
182 # I've seen things appear to be deleted twice
183 # which needs investigation
185 del(self._objects[path])
192 root = property(fget=_get_root)
194 #END---------------------------------------------------------------------------