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.
15 from base import AccessibleObjectNoLongerExists
16 from factory import interfaceFactory
18 #------------------------------------------------------------------------------
20 class _CacheData(object):
30 def __init__(self, data):
33 def update(self, data):
34 #Don't cache the path here, used as lookup in cache object dict.
41 self.description) = data
43 #------------------------------------------------------------------------------
45 class BaseCache(object):
47 Base object for the Desktop, Accessible and Application caches.
49 Abstracts common initialization.
53 def __init__(self, connection, bus_name):
57 connection - DBus connection.
58 busName - Name of DBus connection where cache interface resides.
60 self._connection = connection
61 self._bus_name = bus_name
63 obj = connection.get_object(bus_name, self._PATH)
64 itf = dbus.Interface(obj, self._INTERFACE)
68 getMethod = itf.get_dbus_method(self._GET_METHOD)
69 self._updateObjects(getMethod)
71 self._signalMatch = itf.connect_to_signal(self._UPDATE_SIGNAL, self._updateHandler)
73 def _updateHandler(self, updates):
74 update, remove = updates
75 self._removeObjects(update)
76 self._updateObjects(remove)
78 def _updateObjects(self, objects):
80 #First element is the object path.
82 if path in self._objects:
83 cachedata = self._objects[path]
84 cachedata.update(data)
86 self._objects[path] = _CacheData(data)
88 def _removeObjects(self, paths):
90 del(self._objects[path])
93 def getAccessible(self, path, interface, dbus_object=None):
95 Gets a client side proxy for the accessible object found
98 path - The D-Bus path of the remote object.
99 interface - The interface that the accessible object should support.
100 dbus_object=None - The D-Bus proxy object backing this interface.
102 if path in self._objects:
104 dbus_object = self._connection.get_object(self._bus_name, path, introspect=False)
105 return interfaceFactory(proxy, self, path, interface)
107 raise AccessibleObjectNoLongerExists, "D-Bus reference not found in cache"
109 #------------------------------------------------------------------------------
111 class AccessibleCache(BaseCache):
113 There is one accessible cache per application.
114 For each application the accessible cache stores
115 data on every accessible object within the app.
117 It also acts as the factory for creating client
118 side proxies for these accessible objects.
121 _PATH = '/org/freedesktop/atspi/tree'
122 _INTERFACE = 'org.freedesktop.atspi.Tree'
123 _GET_METHOD = 'getTree'
124 _UPDATE_SIGNAL = 'updateTree'
126 def __init__(self, connection, bus_name):
127 BaseCache.__init__(self, connection, bus_name)
129 obj = connection.get_object(_self.bus_name, self._PATH)
130 itf = dbus.Interface(obj, self._INTERFACE)
132 self._root = itf.getRoot()
134 def getRootAccessible(self):
136 Gets the accessible object at the root of the tree.
138 return self.getAccessible(self._root)
140 #------------------------------------------------------------------------------
142 class DesktopCache(BaseCache):
144 Cache of desktop objects obtained from the registry.
146 The desktop interface on the registry object is the
147 same as that of the general tree interface on the
150 The difference is that the children data refers to
151 bus names of the applications rather than the object
152 paths of particular accessible objects within an application.
155 _PATH = '/org/freedesktop/atspi/registry'
156 _INTERFACE = 'org.freedesktop.atspi.Registry'
157 _GET_METHOD = 'getDesktops'
158 _UPDATE_SIGNAL = 'updateDesktops'
160 def __init__(self, connection, bus_name):
161 self._app_cache = ApplicationCache(connection, bus_name)
163 def getApplication(self, name):
165 self._app_cache[name].getRootAccessible()
167 raise AccessibleObjectNoLongerExists("Application no longer exists")
169 #------------------------------------------------------------------------------
171 class ApplicationCache(object):
173 Holds a mapping of bus names of each accessible application
174 to the applications accessible cache.
176 Makes calls and recieves updates from the registry
177 daemon to keep the cache up to date.
180 _PATH = '/org/freedesktop/atspi/registry'
181 _INTERFACE = 'org.freedesktop.atspi.Registry'
182 _GET_METHOD = 'getApplications'
183 _UPDATE_SIGNAL = 'updateApplications'
185 def _updateApplications(self, names):
187 if name not in self._applications:
188 self._applications[name] = AccessibleCache(self._connection,
192 def _removeApplications(self, names):
194 del(self._applications[name])
196 #END---------------------------------------------------------------------------