Temporary commit. Non working changes to the registration
[platform/core/uifw/at-spi2-atk.git] / pyatspi / applicationcache.py
1 #Copyright (C) 2008 Codethink Ltd
2
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.
6
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.
14
15 import dbus
16
17 from accessiblecache import AccessibleCache
18 from desktop import Desktop
19 from factory import accessible_factory
20 from event import Event as _Event
21
22 import interfaces
23
24 __all__ = [
25            "ApplicationCache",
26            "TestApplicationCache",
27           ]
28
29 #------------------------------------------------------------------------------
30
31 class TestApplicationCache(object):
32         """
33         Test application store, accesses a single application.
34
35         The store object acts as a central class for creating accessible objects.
36         It interfaces with the ATSPI registry to keep account of all accessible
37         applications. It contains the accessible cache objects from each application.
38
39         @registry:   Each accessible cache object must have a reference to the registry
40                      object to send update events.
41
42         @connection: D-Bus connection used to access applications.
43
44         @bus_name:   The test store only accesses one accessible application, this is its
45                      D-Bus path.
46         """
47
48         def __init__(self, registry, connection, bus_name):
49                 self._connection = connection
50
51                 self.application_list = [bus_name]
52                 self.application_cache = {bus_name:AccessibleCache(registry, connection, bus_name)}
53
54         def get_cache_data(self, app_name, acc_path):
55                 """
56                 Returns the cache tuple for the given application and accessible
57                 object path. Throws an IndexError if the cache data is not found.
58                 """
59                 return self.application_cache[app_name][acc_path]
60
61         def create_application(self, app_name):
62                 """
63                 Creates an accessible object for the root of the application
64                 available at the given D-Bus name.
65                 """
66                 cls = accessible_factory.get_accessible_class(interfaces.ATSPI_APPLICATION)
67                 return cls(app_name, self.application_cache[app_name].root, self, interfaces.ATSPI_APPLICATION)
68
69         def create_accessible(self, app_name, acc_path, interface, dbus_object=None):
70                 """
71                 Creates an accessible object.
72
73                 @app_name: D-Bus name of the application where the accessible object resides.
74
75                 @acc_path: D-Bus path of the object within the application.
76
77                 @interface: D-Bus interface of the requested object. A different accessible object
78                             class will be created depending on this. Making the function much like 
79                             an accessible object factory.
80
81                 @dbus_object: If a D-Bus object already exists for the accessible object it can be
82                               provided here so that another one is not created.
83                 """
84                 # An acc_path of '/' implies the desktop object, whatever the app_name.
85                 if acc_path == '/':
86                         return Desktop(self)
87                 else:
88                         cls = accessible_factory.get_accessible_class(interface)
89                         return cls(app_name, acc_path, self, interface, dbus_object=dbus_object)
90
91         @property
92         def connection(self):
93                 """
94                 D-Bus connection used by the store.
95                 """
96                 return self._connection
97
98 #------------------------------------------------------------------------------
99
100 class ApplicationCache(object):
101         """
102         Test application store, accesses a single application.
103
104         The store object acts as a central class for creating accessible objects.
105         It interfaces with the ATSPI registry to keep account of all accessible
106         applications. It contains the accessible cache objects from each application.
107
108         @registry:   Each accessible cache object must have a reference to the registry
109                      object to send update events.
110
111         @connection: D-Bus connection used to access applications.
112
113         @bus_name:   The test store only accesses one accessible application, this is its
114                      D-Bus path.
115         """
116
117         _REGISTRY_PATH = '/org/freedesktop/atspi/registry'
118         _REGISTRY_INTERFACE = 'org.freedesktop.atspi.Registry'
119         _REGISTRY_NAME = 'org.freedesktop.atspi.Registry'
120
121         # An accessible path of '/' implies the desktop object, whatever the application name.
122         _DESKTOP_PATH = '/'
123
124         _APPLICATIONS_ADD = 1
125         _APPLICATIONS_REMOVE = 0
126
127         def __init__(self, registry, connection):
128                 self._connection = connection
129                 self._registry = registry
130
131                 self.application_list = []
132                 self.application_cache = {}
133
134                 self._regsig = connection.add_signal_receiver(self.update_handler,
135                                                               dbus_interface=ApplicationCache._REGISTRY_INTERFACE,
136                                                               signal_name="updateApplications")
137
138                 obj = connection.get_object(ApplicationCache._REGISTRY_NAME,
139                                             ApplicationCache._REGISTRY_PATH,
140                                             introspect=False)
141                 self._app_register = dbus.Interface(obj, ApplicationCache._REGISTRY_INTERFACE)
142
143                 self.application_list.extend(self._app_register.getApplications())
144
145         def update_handler (self, update_type, bus_name):
146                 if update_type == ApplicationCache._APPLICATIONS_ADD:
147                         #TODO Check that app does not already exist
148                         self.application_list.append(bus_name)
149                         self.application_cache[bus_name] = AccessibleCache(self._registry, self._connection, bus_name)
150                         event = _Event(self,
151                                        ApplicationCache._DESKTOP_PATH,
152                                        ApplicationCache._REGISTRY_NAME,
153                                        "org.freedesktop.atspi.Event.Object",
154                                        "children-changed",
155                                        ("", 0, 0, ""))
156                 elif update_type == ApplicationCache._APPLICATIONS_REMOVE:
157                         #TODO Fail safely if app does not exist
158                         self.application_list.remove(bus_name)
159                         del(self.application_cache[bus_name])
160                         event = _Event(self,
161                                        ApplicationCache._DESKTOP_PATH,
162                                        ApplicationCache._REGISTRY_NAME,
163                                        "org.freedesktop.atspi.Event.Object",
164                                        "children-changed",
165                                        ("", 0, 0, ""))
166
167                 self._registry._notifyChildrenChange(event)
168
169         def get_cache_data(self, app_name, acc_path):
170                 """
171                 Returns the cache tuple for the given application and accessible
172                 object path. Throws an IndexError if the cache data is not found.
173                 """
174                 return self.application_cache[app_name][acc_path]
175
176         def create_application(self, app_name):
177                 """
178                 Creates an accessible object for the root of the application
179                 available at the given D-Bus name.
180                 """
181                 cls = accessible_factory.get_accessible_class(interfaces.ATSPI_APPLICATION)
182                 return cls(app_name, self.application_cache[app_name].root, self, interfaces.ATSPI_APPLICATION)
183
184         def create_accessible(self, app_name, acc_path, interface, dbus_object=None):
185                 """
186                 Creates an accessible object.
187
188                 @app_name: D-Bus name of the application where the accessible object resides.
189
190                 @acc_path: D-Bus path of the object within the application.
191
192                 @interface: D-Bus interface of the requested object. A different accessible object
193                             class will be created depending on this. Making the function much like 
194                             an accessible object factory.
195
196                 @dbus_object: If a D-Bus object already exists for the accessible object it can be
197                               provided here so that another one is not created.
198                 """
199                 if acc_path == ApplicationCache._DESKTOP_PATH:
200                         return Desktop(self)
201                 else:
202                         cls = accessible_factory.get_accessible_class(interface)
203                         return cls(app_name, acc_path, self, interface, dbus_object=dbus_object)
204
205         @property
206         def connection(self):
207                 """
208                 D-Bus connection used by the store.
209                 """
210                 return self._connection
211
212 #END----------------------------------------------------------------------------