2008-07-29 Mark Doffman <mark.doffman@codethink.co.uk>
[platform/core/uifw/at-spi2-atk.git] / pyatspi / base.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 from weakref import proxy
16
17 from dbus.proxies import Interface, ProxyObject
18 from dbus.exceptions import *
19
20 class AccessibleObjectNoLongerExists(Exception):
21         pass
22
23 #------------------------------------------------------------------------------
24
25 class Enum(int):
26         def __str__(self):
27                 return self._enum_lookup(int(self))
28
29 #------------------------------------------------------------------------------
30
31 class BaseProxy(Interface):
32         """
33         The base D-Bus proxy for a remote object that implements one or more
34         of the AT-SPI interfaces.
35
36         This class must be further specialised as the cache stores are different
37         for Desktop objects and other Accessible objects.
38         """
39         
40         def __new__(cls, *args, **kwargs):
41                 Interface.__new__(cls, *args, **kwargs)
42
43                 queryable_interfaces = { 
44                         'Accessible':ATSPI_ACCESSIBLE,
45                         'Action':ATSPI_ACTION,
46                         'Application':ATSPI_APPLICATION,
47                         'Collection':ATSPI_COLLECTION,
48                         'Component':ATSPI_COMPONENT,
49                         'Desktop':ATSPI_DESKTOP,
50                         'Document':ATSPI_DOCUMENT,
51                         'EditableText':ATSPI_EDITABLE_TEXT,
52                         'Hypertext':ATSPI_HYPERTEXT,
53                         'Hyperlink':ATSPI_HYPERLINK,
54                         'Image':ATSPI_IMAGE,
55                         'Selection':ATSPI_SELECTION,
56                         'StreamableContent':ATSPI_STREAMABLE_CONTENT,
57                         'Table':ATSPI_TABLE,
58                         'Text':ATSPI_TEXT,
59                         'Value':ATSPI_VALUE,
60                 }
61
62                 for interface in queryable_interfaces.keys():
63                         name = 'query%s' % interface
64                         def new_query(self, object):
65                                 return self.queryInterface(object, queryable_interfaces[interface])
66                         setattr(cls, name, new_query) 
67
68         def __init__(self, obj, cache, path, interface):
69                 """
70                 Create a D-Bus Proxy for an ATSPI interface.
71
72                 obj - The D-Bus proxy object this interface uses for D-Bus calls.
73                 cache - Cache storing data for this object.
74                 path - The object path of the remote object.
75                 interface - The name of the ATSPI interface that this proxy implements.
76                 """
77                 Interface.__init__(self, obj, interface)
78
79                 self._cobj = ref(cache)
80                 self._path = path
81
82                 self._pgetter = self.get_dbus_method("Get", dbus_interface="org.freedesktop.DBus.Properties")
83                 self._psetter = self.get_dbus_method("Set", dbus_interface="org.freedesktop.DBus.Properties")
84
85         def __getattr__(self, *args, **kwargs):
86                 """
87                 The __getattr__ function must return the D-Bus method wrapped in a
88                 method to translate exceptions.
89                 """
90                 # Need to throw an AccessibleObjectNoLongerExists exception
91                 # on D-Bus error of the same type.
92                 try:
93                         return Interface.__getattr__(self, *args, **kwargs)
94                 except UnknownMethodException, e:
95                         raise NotImplementedError(e)
96                 except DBusException, e:
97                         raise LookupError(e)
98
99         @property
100         def _cache(self):
101                 c = self._cobj()
102                 if not c:
103                         raise AccessibleObjectNoLongerExits("Application has been removed")
104
105         @property
106         def _data(self):
107                 try:
108                         data = self._cache._objects[self._path]
109                 except KeyError:
110                         raise AccessibleObjectNoLongerExists, 'Cache data cannot be found for path %s' % (self._path,)
111                 return data
112
113         @property
114         def interfaces(self):
115                 return self._data.interfaces
116
117         def queryInterface(self, interface):
118                 if interface in self._data.interfaces:
119                                 return self._cache.proxyFactory(self._path, interface, dbus_obj=self._obj)
120                 else:
121                         raise NotImplementedError(
122                                 "%s not supported by accessible object at path %s"
123                                 % (interface, self.path))
124
125 #END----------------------------------------------------------------------------