From 3a046b215e491b119e1f7a7867d260ae78dc7062 Mon Sep 17 00:00:00 2001 From: Mark Doffman Date: Mon, 18 Aug 2008 15:10:59 +0100 Subject: [PATCH] 2008-08-18 Mark Doffman * pyatspi/* Move the Accessible class out of base.py Add a StateSet implementation Begin a RelationSet implementation Refactor the getParent function Refactor the __init__.py layout --- pyatspi/Makefile.am | 5 + pyatspi/__init__.py | 36 +-- pyatspi/accessible.py | 209 +++++++++++++++++ pyatspi/application.py | 127 +++++++++++ pyatspi/base.py | 248 +++----------------- pyatspi/constants.py | 19 -- pyatspi/factory.py | 14 +- pyatspi/interfaces.py | 32 +++ pyatspi/other.py | 598 +------------------------------------------------ pyatspi/relation.py | 164 ++++++++++++++ pyatspi/stateset.py | 272 +++++++++++----------- pyatspi/test.py | 11 +- pyatspi/utils.py | 12 +- 13 files changed, 754 insertions(+), 993 deletions(-) create mode 100644 pyatspi/accessible.py create mode 100644 pyatspi/application.py create mode 100644 pyatspi/interfaces.py create mode 100644 pyatspi/relation.py diff --git a/pyatspi/Makefile.am b/pyatspi/Makefile.am index 34fc8fc..859078f 100644 --- a/pyatspi/Makefile.am +++ b/pyatspi/Makefile.am @@ -3,11 +3,16 @@ pyatspi_PYTHON = \ base.py \ cache.py \ constants.py \ + event.py \ factory.py \ + interfaces.py \ __init__.py \ Makefile.am \ other.py \ stateset.py \ + registry.py \ + relation.py \ + test.py \ utils.py pyatspidir=$(pyexecdir)/pyatspi diff --git a/pyatspi/__init__.py b/pyatspi/__init__.py index be6f0d5..d0ee7c5 100644 --- a/pyatspi/__init__.py +++ b/pyatspi/__init__.py @@ -18,40 +18,12 @@ #registry.Registry = Registry #del registry -def setCacheLevel(level): - pass - -def getCacheLevel(): - return None - -def clearCache(): - pass - -def printCache(): - print "Print cache function is deprecated"; - -import other - -# Build a dictionary mapping state values to names based on the prefix of the -# enum constants. -STATE_VALUE_TO_NAME = dict(((value, name[6:].lower().replace('_', ' ')) - for name, value - in vars(other).items() - if name.startswith('STATE_'))) - -# Build a dictionary mapping relation values to names based on the prefix of -# the enum constants. -RELATION_VALUE_TO_NAME = dict(((value, name[9:].lower().replace('_', ' ')) - for name, value - in vars(other).items() - if name.startswith('RELATION_'))) - -del other - from constants import * -from base import * -from other import * +from accessible import * +from application import * +from stateset import * +from relation import * from test import * diff --git a/pyatspi/accessible.py b/pyatspi/accessible.py new file mode 100644 index 0000000..b7ac7f3 --- /dev/null +++ b/pyatspi/accessible.py @@ -0,0 +1,209 @@ +#Copyright (C) 2008 Codethink Ltd + +#This library is free software; you can redistribute it and/or +#modify it under the terms of the GNU Lesser General Public +#License version 2 as published by the Free Software Foundation. + +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. +#You should have received a copy of the GNU Lesser General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import interfaces +from base import BaseProxy +from factory import create_accessible, add_accessible_class +from stateset import StateSet, _marshal_state_set + +__all__ = [ + "Accessible", + ] + +#------------------------------------------------------------------------------ + +class Accessible(BaseProxy): + """ + The base interface which is implemented by all accessible objects. + All objects support interfaces for querying their contained + 'children' and position in the accessible-object hierarchy, + whether or not they actually have children. + """ + + def getApplication(self): + """ + Get the containing Application for this object. + @return the Application instance to which this object belongs. + """ + application_root = self._cache[self._app_name]._get_root() + #TODO Set the desktop object as the parent of this. + return create_accessible(self._cache, + self._app_name, + application_root, + interfaces.ATSPI_APPLICATION, + dbus_object=self._dbus_object) + + def getAttributes(self, *args, **kwargs): + """ + Get a list of properties applied to this object as a whole, as + an AttributeSet consisting of name-value pairs. As such these + attributes may be considered weakly-typed properties or annotations, + as distinct from the strongly-typed interface instance data declared + using the IDL "attribute" keyword. + Not all objects have explicit "name-value pair" AttributeSet + properties. + Attribute names and values may have any UTF-8 string value, however + where possible, in order to facilitate consistent use and exposure + of "attribute" properties by applications and AT clients, attribute + names and values should chosen from a publicly-specified namespace + where appropriate. + Where possible, the names and values in the name-value pairs + should be chosen from well-established attribute namespaces using + standard semantics. For example, attributes of Accessible objects + corresponding to XHTML content elements should correspond to + attribute names and values specified in the w3c XHTML specification, + at http://www.w3.org/TR/xhtml2, where such values are not already + exposed via a more strongly-typed aspect of the AT-SPI API. Metadata + names and values should be chosen from the 'Dublin Core' Metadata + namespace using Dublin Core semantics: http://dublincore.org/dcregistry/ + Similarly, relevant structural metadata should be exposed using + attribute names and values chosen from the CSS2 and WICD specification: + http://www.w3.org/TR/1998/REC-CSS2-19980512 WICD (http://www.w3.org/TR/2005/WD-WICD-20051121/). + @return : an AttributeSet encapsulating any "attribute values" + currently defined for the object. + """ + func = self.get_dbus_method("getAttributes") + return func(*args, **kwargs) + + def getChildAtIndex(self, index): + """ + Get the accessible child of this object at index. + @param : index + an in parameter indicating which child is requested (zero-indexed). + @return : the 'nth' Accessible child of this object. + """ + path = self.cached_data.children[index] + return create_accessible(self._cache, + self._app_name, + path, + interfaces.ATSPI_ACCESSIBLE, + dbus_object=self._dbus_object) + + def getIndexInParent(self, *args, **kwargs): + """ + Get the index of this object in its parent's child list. + @return : a long integer indicating this object's index in the + parent's list. + """ + for i in range(0, self.parent.childCount): + child = self.parent.getChildAtIndex(i) + if self.isEqual(child): + return i + raise AccessibleObjectNoLongerExists("Child not found within parent") + + def getLocalizedRoleName(self, *args, **kwargs): + """ + Get a string indicating the type of UI role played by this object, + translated to the current locale. + @return : a UTF-8 string indicating the type of UI role played + by this object. + """ + func = self.get_dbus_method("getLocalizedRoleName") + return func(*args, **kwargs) + + def getRelationSet(self, *args, **kwargs): + """ + Get a set defining this object's relationship to other accessible + objects. + @return : a RelationSet defining this object's relationships. + """ + func = self.get_dbus_method("getRelationSet") + return func(*args, **kwargs) + + def getRole(self): + """ + Get the Role indicating the type of UI role played by this object. + @return : a Role indicating the type of UI role played by this + object. + """ + return self.cached_data.role + + def getRoleName(self, *args, **kwargs): + """ + Get a string indicating the type of UI role played by this object. + @return : a UTF-8 string indicating the type of UI role played + by this object. + """ + func = self.get_dbus_method("getRoleName") + return func(*args, **kwargs) + + def getState(self, *args, **kwargs): + """ + Get the current state of the object as a StateSet. + @return : a StateSet encapsulating the currently true states + of the object. + """ + func = self.get_dbus_method("getState") + bitfield = func(*args, **kwargs) + return _marshal_state_set(bitfield) + + def isEqual(self, accessible): + """ + Determine whether an Accessible refers to the same object as + another. This method should be used rather than brute-force comparison + of object references (i.e. "by-value" comparison), as two object + references may have different apparent values yet refer to the + same object. + @param : obj + an Accessible object reference to compare to + @return : a boolean indicating whether the two object references + point to the same object. + """ + return (self._app_name == accessible._app_name) and \ + (self._acc_path == accessible._acc_path) + + def get_childCount(self): + return len(self.cached_data.children) + _childCountDoc = \ + """ + childCount: the number of children contained by this object. + """ + childCount = property(fget=get_childCount, doc=_childCountDoc) + + def get_description(self): + return self.cached_data.description + _descriptionDoc = \ + """ + a string describing the object in more detail than name. + """ + description = property(fget=get_description, doc=_descriptionDoc) + + def get_name(self): + return self.cached_data.name + _nameDoc = \ + """ + a (short) string representing the object's name. + """ + name = property(fget=get_name, doc=_nameDoc) + + def get_parent(self): + if self._parent: + return self._parent + else: + return create_accessible(self._cache, + self._app_name, + self.cached_data.parent, + interfaces.ATSPI_ACCESSIBLE, + dbus_object=self._dbus_object) + + _parentDoc = \ + """ + an Accessible object which is this object's containing object. + """ + parent = property(fget=get_parent, doc=_parentDoc) + +# Register the Accessible class with the accessible factory. +add_accessible_class(interfaces.ATSPI_ACCESSIBLE, Accessible) + +#END---------------------------------------------------------------------------- diff --git a/pyatspi/application.py b/pyatspi/application.py new file mode 100644 index 0000000..c0c8284 --- /dev/null +++ b/pyatspi/application.py @@ -0,0 +1,127 @@ +#Copyright (C) 2008 Codethink Ltd + +#This library is free software; you can redistribute it and/or +#modify it under the terms of the GNU Lesser General Public +#License version 2 as published by the Free Software Foundation. + +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. +#You should have received a copy of the GNU Lesser General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import interfaces +from base import BaseProxy +from factory import add_accessible_class +from accessible import Accessible + +__all__ = [ + "Application", + ] + +#------------------------------------------------------------------------------ + +class Application(Accessible): + """ + An interface identifying an object which is the root of the user + interface Accessible hierarchy associated with a running application. + Children of Application are typically, but not exclusively, top-level + windows. + """ + + def getLocale(self, *args, **kwargs): + """ + Gets the locale in which the application is currently operating. + For the current message locale, use lctype LOCALE_TYPE_MESSAGES. + @param : lctype + The LocaleType for which the locale is queried. + @return a string compliant with the POSIX standard for locale + description. + """ + func = self.get_dbus_method("getLocale") + return func(*args, **kwargs) + + def pause(self, *args, **kwargs): + """ + Request that the application temporarily stop sending events. + In most cases this should pause the application's main event + loop. + @return : true if the request succeeded, false otherwise. + """ + func = self.get_dbus_method("pause") + return func(*args, **kwargs) + + def registerObjectEventListener(self, *args, **kwargs): + """ + registerObjectEventListener: + @param : listener + an EventListener object which will receive the requested events + @param : eventName + a UTF-8 string indicating the type of (toolkit-specific) event + being requested. Register with this application toolkit for "Accessibility::Accessible" + event notifications. + """ + func = self.get_dbus_method("registerObjectEventListener") + return func(*args, **kwargs) + + def registerToolkitEventListener(self, *args, **kwargs): + """ + @param : listener + an EventListener object which will receive the requested events + from the application's toolkits via toolit 'bridges' + @param : eventName + a UTF-8 string indicating the type of (toolkit-specific) event + being requested. Not all applications can generate toolkit events + of a given type. + Register with this application's toolkit for "toolkit-specific" + event notifications. + """ + func = self.get_dbus_method("registerToolkitEventListener") + return func(*args, **kwargs) + + def resume(self, *args, **kwargs): + """ + Request that the application resume sending events. + @return : True if the request succeeded, False otherwise. + """ + func = self.get_dbus_method("resume") + return func(*args, **kwargs) + + def get_id(self): + self._pgetter(self._dbus_interface, "id") + def set_id(self, value): + self._psetter(self._dbus_interface, "id", value) + _idDoc = \ + """ + The application instance's unique ID as assigned by the registry. + """ + id = property(fget=get_id, fset=set_id, doc=_idDoc) + + def get_toolkitName(self): + self._pgetter(self._dbus_interface, "toolkitName") + def set_toolkitName(self, value): + self._psetter(self._dbus_interface, "toolkitName", value) + _toolkitNameDoc = \ + """ + A string indicating the type of user interface toolkit which + is used by the application. + """ + toolkitName = property(fget=get_toolkitName, fset=set_toolkitName, doc=_toolkitNameDoc) + + def get_version(self): + self._pgetter(self._dbus_interface, "version") + def set_version(self, value): + self._psetter(self._dbus_interface, "version", value) + _versionDoc = \ + """ + A string indicating the version number of the application's accessibility + bridge implementation. + """ + version = property(fget=get_version, fset=set_version, doc=_versionDoc) + +# ATTENTION - Register the Application class with the accessible factory. +add_accessible_class(interfaces.ATSPI_APPLICATION, Application) + +#END---------------------------------------------------------------------------- diff --git a/pyatspi/base.py b/pyatspi/base.py index 8ff71d3..7231e8a 100644 --- a/pyatspi/base.py +++ b/pyatspi/base.py @@ -12,47 +12,52 @@ #along with this program; if not, write to the Free Software #Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -import dbus as _dbus -from dbus.proxies import Interface as _Interface - +import dbus +from dbus.proxies import Interface from dbus.exceptions import * -from factory import create_accessible, add_accessible_class -import constants +import interfaces +from factory import create_accessible + +__all__ = [ + "AccessibleObjectNoLongerExists", + "Enum", + "BaseProxy", + ] class AccessibleObjectNoLongerExists(Exception): pass #------------------------------------------------------------------------------ -class _Enum(int): +class Enum(int): def __str__(self): return self._enum_lookup(int(self)) #------------------------------------------------------------------------------ -class _BaseProxyMeta(type): +class BaseProxyMeta(type): def __init__(cls, *args, **kwargs): type.__init__(cls, *args, **kwargs) queryable_interfaces = { - 'Accessible':constants.ATSPI_ACCESSIBLE, - 'Action':constants.ATSPI_ACTION, - 'Application':constants.ATSPI_APPLICATION, - 'Collection':constants.ATSPI_COLLECTION, - 'Component':constants.ATSPI_COMPONENT, - 'Desktop':constants.ATSPI_DESKTOP, - 'Document':constants.ATSPI_DOCUMENT, - 'EditableText':constants.ATSPI_EDITABLE_TEXT, - 'Hypertext':constants.ATSPI_HYPERTEXT, - 'Hyperlink':constants.ATSPI_HYPERLINK, - 'Image':constants.ATSPI_IMAGE, - 'Selection':constants.ATSPI_SELECTION, - 'StreamableContent':constants.ATSPI_STREAMABLE_CONTENT, - 'Table':constants.ATSPI_TABLE, - 'Text':constants.ATSPI_TEXT, - 'Value':constants.ATSPI_VALUE, + 'Accessible':interfaces.ATSPI_ACCESSIBLE, + 'Action':interfaces.ATSPI_ACTION, + 'Application':interfaces.ATSPI_APPLICATION, + 'Collection':interfaces.ATSPI_COLLECTION, + 'Component':interfaces.ATSPI_COMPONENT, + 'Desktop':interfaces.ATSPI_DESKTOP, + 'Document':interfaces.ATSPI_DOCUMENT, + 'EditableText':interfaces.ATSPI_EDITABLE_TEXT, + 'Hypertext':interfaces.ATSPI_HYPERTEXT, + 'Hyperlink':interfaces.ATSPI_HYPERLINK, + 'Image':interfaces.ATSPI_IMAGE, + 'Selection':interfaces.ATSPI_SELECTION, + 'StreamableContent':interfaces.ATSPI_STREAMABLE_CONTENT, + 'Table':interfaces.ATSPI_TABLE, + 'Text':interfaces.ATSPI_TEXT, + 'Value':interfaces.ATSPI_VALUE, } for interface in queryable_interfaces.keys(): @@ -63,15 +68,15 @@ class _BaseProxyMeta(type): #------------------------------------------------------------------------------ -class _BaseProxy(_Interface): +class BaseProxy(Interface): """ The base D-Bus proxy for a remote object that implements one or more of the AT-SPI interfaces. """ - __metaclass__ = _BaseProxyMeta + __metaclass__ = BaseProxyMeta - def __init__(self, cache, app_name, acc_path, parent, interface, dbus_object=None, connection=None): + def __init__(self, cache, app_name, acc_path, interface, dbus_object=None, connection=None, parent=None): """ Create a D-Bus Proxy for an ATSPI interface. @@ -91,19 +96,19 @@ class _BaseProxy(_Interface): dbus_object = connection.get_object(self._app_name, self._acc_path, introspect=False) self._dbus_object = dbus_object - _Interface.__init__(self, self._dbus_object, interface) + Interface.__init__(self, self._dbus_object, interface) self._pgetter = self.get_dbus_method("Get", dbus_interface="org.freedesktop.DBus.Properties") self._psetter = self.get_dbus_method("Set", dbus_interface="org.freedesktop.DBus.Properties") - def __getattr__(self, *args, **kwargs): - method = _Interface.__getattr__(self, *args, **kwargs) + def get_dbus_method(self, *args, **kwargs): + method = Interface.get_dbus_method(self, *args, **kwargs) def dbus_method_func(*args, **kwargs): # TODO Need to throw an AccessibleObjectNoLongerExists exception # on D-Bus error of the same type. try: - method(*args, **kwargs) + return method(*args, **kwargs) except UnknownMethodException, e: raise NotImplementedError(e) except DBusException, e: @@ -141,187 +146,4 @@ class _BaseProxy(_Interface): "%s not supported by accessible object at path %s" % (interface, self.path)) -#------------------------------------------------------------------------------ - -class Accessible(_BaseProxy): - """ - The base interface which is implemented by all accessible objects. - All objects support interfaces for querying their contained - 'children' and position in the accessible-object hierarchy, - whether or not they actually have children. - """ - - def getApplication(self): - """ - Get the containing Application for this object. - @return the Application instance to which this object belongs. - """ - application_root = self._cache.get_application_root(self._app_name) - return create_accessible(self._cache, - self._app_name, - application_root, - constants.NULL_BUS_NAME, - constants.NULL_OBJECT_PATH, - constants.ATSPI_ACCESSIBLE, - dbus_object=self._dbus_object) - - def getAttributes(self, *args, **kwargs): - """ - Get a list of properties applied to this object as a whole, as - an AttributeSet consisting of name-value pairs. As such these - attributes may be considered weakly-typed properties or annotations, - as distinct from the strongly-typed interface instance data declared - using the IDL "attribute" keyword. - Not all objects have explicit "name-value pair" AttributeSet - properties. - Attribute names and values may have any UTF-8 string value, however - where possible, in order to facilitate consistent use and exposure - of "attribute" properties by applications and AT clients, attribute - names and values should chosen from a publicly-specified namespace - where appropriate. - Where possible, the names and values in the name-value pairs - should be chosen from well-established attribute namespaces using - standard semantics. For example, attributes of Accessible objects - corresponding to XHTML content elements should correspond to - attribute names and values specified in the w3c XHTML specification, - at http://www.w3.org/TR/xhtml2, where such values are not already - exposed via a more strongly-typed aspect of the AT-SPI API. Metadata - names and values should be chosen from the 'Dublin Core' Metadata - namespace using Dublin Core semantics: http://dublincore.org/dcregistry/ - Similarly, relevant structural metadata should be exposed using - attribute names and values chosen from the CSS2 and WICD specification: - http://www.w3.org/TR/1998/REC-CSS2-19980512 WICD (http://www.w3.org/TR/2005/WD-WICD-20051121/). - @return : an AttributeSet encapsulating any "attribute values" - currently defined for the object. - """ - func = self.get_dbus_method("getAttributes") - return func(*args, **kwargs) - - def getChildAtIndex(self, index): - """ - Get the accessible child of this object at index. - @param : index - an in parameter indicating which child is requested (zero-indexed). - @return : the 'nth' Accessible child of this object. - """ - path = self.cached_data.children[index] - return create_accessible(self._cache, - self._app_name, - path, - self, - constants.ATSPI_ACCESSIBLE, - dbus_object=self._dbus_object) - - def getIndexInParent(self, *args, **kwargs): - """ - Get the index of this object in its parent's child list. - @return : a long integer indicating this object's index in the - parent's list. - """ - func = self.get_dbus_method("getIndexInParent") - return func(*args, **kwargs) - - def getLocalizedRoleName(self, *args, **kwargs): - """ - Get a string indicating the type of UI role played by this object, - translated to the current locale. - @return : a UTF-8 string indicating the type of UI role played - by this object. - """ - func = self.get_dbus_method("getLocalizedRoleName") - return func(*args, **kwargs) - - def getRelationSet(self, *args, **kwargs): - """ - Get a set defining this object's relationship to other accessible - objects. - @return : a RelationSet defining this object's relationships. - """ - func = self.get_dbus_method("getRelationSet") - return func(*args, **kwargs) - - def getRole(self): - """ - Get the Role indicating the type of UI role played by this object. - @return : a Role indicating the type of UI role played by this - object. - """ - return self.cached_data.role - - def getRoleName(self, *args, **kwargs): - """ - Get a string indicating the type of UI role played by this object. - @return : a UTF-8 string indicating the type of UI role played - by this object. - """ - func = self.get_dbus_method("getRoleName") - return func(*args, **kwargs) - - def getState(self, *args, **kwargs): - """ - Get the current state of the object as a StateSet. - @return : a StateSet encapsulating the currently true states - of the object. - """ - func = self.get_dbus_method("getState") - return func(*args, **kwargs) - - def isEqual(self, accessible): - """ - Determine whether an Accessible refers to the same object as - another. This method should be used rather than brute-force comparison - of object references (i.e. "by-value" comparison), as two object - references may have different apparent values yet refer to the - same object. - @param : obj - an Accessible object reference to compare to - @return : a boolean indicating whether the two object references - point to the same object. - """ - return (self._app_name == accessible._app_name) and \ - (self._acc_path == accessible._acc_path) - - def unimplemented(self, *args, **kwargs): - """ - /cond future expansion - """ - func = self.get_dbus_method("unimplemented") - return func(*args, **kwargs) - - def get_childCount(self): - return len(self.cached_data.children) - _childCountDoc = \ - """ - childCount: the number of children contained by this object. - """ - childCount = property(fget=get_childCount, doc=_childCountDoc) - - def get_description(self): - return self.cached_data.description - _descriptionDoc = \ - """ - a string describing the object in more detail than name. - """ - description = property(fget=get_description, doc=_descriptionDoc) - - def get_name(self): - return self.cached_data.name - _nameDoc = \ - """ - a (short) string representing the object's name. - """ - name = property(fget=get_name, doc=_nameDoc) - - def get_parent(self): - # The parent attribute is part of the base proxy - return self._parent - _parentDoc = \ - """ - an Accessible object which is this object's containing object. - """ - parent = property(fget=get_parent, doc=_parentDoc) - -# ATTENTION - Register the Accessible class with the accessible factory. -add_accessible_class(constants.ATSPI_ACCESSIBLE, Accessible) - #END---------------------------------------------------------------------------- diff --git a/pyatspi/constants.py b/pyatspi/constants.py index f4c41b2..db3b971 100644 --- a/pyatspi/constants.py +++ b/pyatspi/constants.py @@ -138,22 +138,3 @@ EVENT_TREE = { 'focus' : ['focus:'] } - -ATSPI_ACCESSIBLE = 'org.freedesktop.atspi.Accessible' -ATSPI_ACTION = 'org.freedesktop.atspi.Action' -ATSPI_APPLICATION = 'org.freedesktop.atspi.Application' -ATSPI_COMPONENT = 'org.freedesktop.atspi.Component' -ATSPI_COLLECTION = 'org.freedesktop.atspi.Collection' -ATSPI_DESKTOP = 'org.freedesktop.atspi.Desktop' -ATSPI_DOCUMENT = 'org.freedesktop.atspi.Document' -ATSPI_EDITABLE_TEXT = 'org.freedesktop.atspi.EditableText' -ATSPI_HYPERLINK = 'org.freedesktop.atspi.Hyperlink' -ATSPI_HYPERTEXT = 'org.freedesktop.atspi.Hypertext' -ATSPI_IMAGE = 'org.freedesktop.atspi.Image' -ATSPI_LOGIN_HELPER = 'org.freedesktop.atspi.LoginHelper' -ATSPI_SELECTION = 'org.freedesktop.atspi.Selection' -ATSPI_SELECTOR = 'org.freedesktop.atspi.Selector' -ATSPI_STREAMABLE_CONTENT = 'org.freedesktop.atspi.Content' -ATSPI_TABLE = 'org.freedesktop.atspi.Table' -ATSPI_TEXT = 'org.freedesktop.atspi.Text' -ATSPI_VALUE = 'org.freedesktop.atspi.Value' diff --git a/pyatspi/factory.py b/pyatspi/factory.py index 4227a24..71ea7ab 100644 --- a/pyatspi/factory.py +++ b/pyatspi/factory.py @@ -17,22 +17,22 @@ class AccessibleFactory(object): __accessible_interfaces = {} - def create_accessible(self, cache, app_name, acc_path, parent, interface, dbus_object=None, connection=None): + def create_accessible(self, cache, app_name, acc_path, interface, dbus_object=None, connection=None, parent=None): class_ = self.__accessible_interfaces[interface] return class_(cache, app_name, acc_path, - parent, interface, dbus_object=dbus_object, - connection=connection) + connection=connection, + parent=parent) def add_accessible_class(self, name, cls): self.__accessible_interfaces[name] = cls _factory = AccessibleFactory() -def create_accessible(cache, app_name, acc_path, parent, interface, dbus_object=None, connection=None): +def create_accessible(cache, app_name, acc_path, interface, dbus_object=None, connection=None, parent=None): """ Used to create different python classes for each of the accessible interfaces. @@ -42,8 +42,6 @@ def create_accessible(cache, app_name, acc_path, parent, interface, dbus_object= cache - ApplicationCache, where the cached data for the accessible can be obtained. app_name - D-Bus bus name of the application this accessible belongs to. acc_path - D-Bus object path of the server side accessible object. - app_parent - D-Bus bus name of the parent objects application. - acc_parent - D-Bus object path of the parent accessible. interface - D-Bus interface of the object. Used to decide which accessible class to instanciate. dbus_object(kwarg) - The D-Bus proxy object used by the accessible for D-Bus method calls. connection(kwarg) - Client side D-Bus connection, provided if no D-Bus proxy is available. @@ -51,10 +49,10 @@ def create_accessible(cache, app_name, acc_path, parent, interface, dbus_object= return _factory.create_accessible(cache, app_name, acc_path, - parent, interface, dbus_object=dbus_object, - connection=connection) + connection=connection, + parent=parent) def add_accessible_class(name, cls): _factory.add_accessible_class(name, cls) diff --git a/pyatspi/interfaces.py b/pyatspi/interfaces.py new file mode 100644 index 0000000..2fad9ec --- /dev/null +++ b/pyatspi/interfaces.py @@ -0,0 +1,32 @@ +#Copyright (C) 2008 Codethink Ltd + +#This library is free software; you can redistribute it and/or +#modify it under the terms of the GNU Lesser General Public +#License version 2 as published by the Free Software Foundation. + +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. +#You should have received a copy of the GNU Lesser General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +ATSPI_ACCESSIBLE = 'org.freedesktop.atspi.Accessible' +ATSPI_ACTION = 'org.freedesktop.atspi.Action' +ATSPI_APPLICATION = 'org.freedesktop.atspi.Application' +ATSPI_COMPONENT = 'org.freedesktop.atspi.Component' +ATSPI_COLLECTION = 'org.freedesktop.atspi.Collection' +ATSPI_DESKTOP = 'org.freedesktop.atspi.Desktop' +ATSPI_DOCUMENT = 'org.freedesktop.atspi.Document' +ATSPI_EDITABLE_TEXT = 'org.freedesktop.atspi.EditableText' +ATSPI_HYPERLINK = 'org.freedesktop.atspi.Hyperlink' +ATSPI_HYPERTEXT = 'org.freedesktop.atspi.Hypertext' +ATSPI_IMAGE = 'org.freedesktop.atspi.Image' +ATSPI_LOGIN_HELPER = 'org.freedesktop.atspi.LoginHelper' +ATSPI_SELECTION = 'org.freedesktop.atspi.Selection' +ATSPI_SELECTOR = 'org.freedesktop.atspi.Selector' +ATSPI_STREAMABLE_CONTENT = 'org.freedesktop.atspi.Content' +ATSPI_TABLE = 'org.freedesktop.atspi.Table' +ATSPI_TEXT = 'org.freedesktop.atspi.Text' +ATSPI_VALUE = 'org.freedesktop.atspi.Value' diff --git a/pyatspi/other.py b/pyatspi/other.py index 46dbcac..53e3e1a 100644 --- a/pyatspi/other.py +++ b/pyatspi/other.py @@ -15,9 +15,11 @@ from base import _BaseProxy, _Enum from base import Accessible as _Accessible +import constants + +from factory import add_accessible_class + class Action(_BaseProxy): - - """ An interface through which a user-actionable user interface component can be manipulated. Components which react to mouse or keyboard @@ -80,22 +82,6 @@ class Action(_BaseProxy): func = self.get_dbus_method("getName") return func(*args, **kwargs) - def unImplemented(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented") - return func(*args, **kwargs) - - def unImplemented2(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented2") - return func(*args, **kwargs) - - def unImplemented3(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented3") - return func(*args, **kwargs) - - def unImplemented4(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented4") - return func(*args, **kwargs) - def get_nActions(self): self._pgetter(self._dbus_interface, "nActions") def set_nActions(self, value): @@ -108,119 +94,7 @@ class Action(_BaseProxy): nActions = property(fget=get_nActions, fset=set_nActions, doc=_nActionsDoc) -class Application(_Accessible): - - - """ - An interface identifying an object which is the root of the user - interface Accessible hierarchy associated with a running application. - Children of Application are typically, but not exclusively, top-level - windows. - """ - - - def getLocale(self, *args, **kwargs): - """ - Gets the locale in which the application is currently operating. - For the current message locale, use lctype LOCALE_TYPE_MESSAGES. - @param : lctype - The LocaleType for which the locale is queried. - @return a string compliant with the POSIX standard for locale - description. - """ - func = self.get_dbus_method("getLocale") - return func(*args, **kwargs) - - def pause(self, *args, **kwargs): - """ - Request that the application temporarily stop sending events. - In most cases this should pause the application's main event - loop. - @return : true if the request succeeded, false otherwise. - """ - func = self.get_dbus_method("pause") - return func(*args, **kwargs) - - def registerObjectEventListener(self, *args, **kwargs): - """ - registerObjectEventListener: - @param : listener - an EventListener object which will receive the requested events - @param : eventName - a UTF-8 string indicating the type of (toolkit-specific) event - being requested. Register with this application toolkit for "Accessibility::Accessible" - event notifications. - """ - func = self.get_dbus_method("registerObjectEventListener") - return func(*args, **kwargs) - - def registerToolkitEventListener(self, *args, **kwargs): - """ - @param : listener - an EventListener object which will receive the requested events - from the application's toolkits via toolit 'bridges' - @param : eventName - a UTF-8 string indicating the type of (toolkit-specific) event - being requested. Not all applications can generate toolkit events - of a given type. - Register with this application's toolkit for "toolkit-specific" - event notifications. - """ - func = self.get_dbus_method("registerToolkitEventListener") - return func(*args, **kwargs) - - def resume(self, *args, **kwargs): - """ - Request that the application resume sending events. - @return : True if the request succeeded, False otherwise. - """ - func = self.get_dbus_method("resume") - return func(*args, **kwargs) - - def unImplemented2_(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented2_") - return func(*args, **kwargs) - - def unImplemented3_(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented3_") - return func(*args, **kwargs) - - def unImplemented_(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented_") - return func(*args, **kwargs) - - def get_id(self): - self._pgetter(self._dbus_interface, "id") - def set_id(self, value): - self._psetter(self._dbus_interface, "id", value) - _idDoc = \ - """ - The application instance's unique ID as assigned by the registry. - """ - id = property(fget=get_id, fset=set_id, doc=_idDoc) - - def get_toolkitName(self): - self._pgetter(self._dbus_interface, "toolkitName") - def set_toolkitName(self, value): - self._psetter(self._dbus_interface, "toolkitName", value) - _toolkitNameDoc = \ - """ - A string indicating the type of user interface toolkit which - is used by the application. - """ - toolkitName = property(fget=get_toolkitName, fset=set_toolkitName, doc=_toolkitNameDoc) - - def get_version(self): - self._pgetter(self._dbus_interface, "version") - def set_version(self, value): - self._psetter(self._dbus_interface, "version", value) - _versionDoc = \ - """ - A string indicating the version number of the application's accessibility - bridge implementation. - """ - version = property(fget=get_version, fset=set_version, doc=_versionDoc) - +#------------------------------------------------------------------------------ class BoundingBox(list): def __new__(cls, x, y, width, height): @@ -800,23 +674,6 @@ class DeviceEventController(_BaseProxy): func = self.get_dbus_method("registerKeystrokeListener") return func(*args, **kwargs) - def unImplemented(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented") - return func(*args, **kwargs) - - def unImplemented2(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented2") - return func(*args, **kwargs) - - def unImplemented3(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented3") - return func(*args, **kwargs) - - def unImplemented4(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented4") - return func(*args, **kwargs) - - class DeviceEventListener(_BaseProxy): """ This interface should be implemented by AT-SPI clients who wish @@ -836,31 +693,6 @@ class DeviceEventListener(_BaseProxy): func = self.get_dbus_method("notifyEvent") return func(*args, **kwargs) - def unImplemented_2_(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented_2_") - return func(*args, **kwargs) - - def unImplemented_3_(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented_3_") - return func(*args, **kwargs) - - def unImplemented_4_(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented_4_") - return func(*args, **kwargs) - - def unImplemented_5_(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented_5_") - return func(*args, **kwargs) - - def unImplemented_6_(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented_6_") - return func(*args, **kwargs) - - def unImplemented__(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented__") - return func(*args, **kwargs) - - class Document(_BaseProxy): """ Primarily a 'tagging' interface which indicates the start of @@ -1359,15 +1191,7 @@ class Text(_BaseProxy): """ func = self.get_dbus_method("setSelection") return func(*args, **kwargs) - - def unImplemented(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented") - return func(*args, **kwargs) - - def unImplemented2(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented2") - return func(*args, **kwargs) - + def get_caretOffset(self): self._pgetter(self._dbus_interface, "caretOffset") def set_caretOffset(self, value): @@ -1827,23 +1651,6 @@ class Hypertext(_BaseProxy): func = self.get_dbus_method("getNLinks") return func(*args, **kwargs) - def unImplemented(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented") - return func(*args, **kwargs) - - def unImplemented2(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented2") - return func(*args, **kwargs) - - def unImplemented3(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented3") - return func(*args, **kwargs) - - def unImplemented4(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented4") - return func(*args, **kwargs) - - class Image(_BaseProxy): """ An interface implemented by objects which render image data or @@ -1903,19 +1710,7 @@ class Image(_BaseProxy): """ func = self.get_dbus_method("getImageSize") return func(*args, **kwargs) - - def unImplemented(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented") - return func(*args, **kwargs) - - def unImplemented2(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented2") - return func(*args, **kwargs) - - def unImplemented3(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented3") - return func(*args, **kwargs) - + def get_imageDescription(self): self._pgetter(self._dbus_interface, "imageDescription") def set_imageDescription(self, value): @@ -2070,22 +1865,6 @@ class LoginHelper(_BaseProxy): func = self.get_dbus_method("setSafe") return func(*args, **kwargs) - def unImplemented(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented") - return func(*args, **kwargs) - - def unImplemented2(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented2") - return func(*args, **kwargs) - - def unImplemented3(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented3") - return func(*args, **kwargs) - - def unImplemented4(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented4") - return func(*args, **kwargs) - class DeviceReq(_Enum): _enum_lookup = { 0:'GUI_EVENTS', @@ -2271,108 +2050,8 @@ class Registry(EventListener): """ func = self.get_dbus_method("registerGlobalEventListener") return func(*args, **kwargs) - - def unImplemented(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented") - return func(*args, **kwargs) - - def unImplemented2(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented2") - return func(*args, **kwargs) - - def unImplemented3(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented3") - return func(*args, **kwargs) - - def unImplemented4(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented4") - return func(*args, **kwargs) - - def unImplemented5(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented5") - return func(*args, **kwargs) - - def unImplemented6(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented6") - return func(*args, **kwargs) - -class Relation(_BaseProxy): - """ - An interface via which objects' non-hierarchical relationships - to one another are indicated. An instance of Relations represents - a "one-to-many" correspondance. - """ - - def getNTargets(self, *args, **kwargs): - """ - @return the number of objects to which this relationship applies. - """ - func = self.get_dbus_method("getNTargets") - return func(*args, **kwargs) - - def getRelationType(self, *args, **kwargs): - """ - @return the RelationType of this Relation. - """ - func = self.get_dbus_method("getRelationType") - return func(*args, **kwargs) - - def getRelationTypeName(self, *args, **kwargs): - """ - @return an unlocalized string representing the relation type. - """ - func = self.get_dbus_method("getRelationTypeName") - return func(*args, **kwargs) - - def getTarget(self, *args, **kwargs): - """ - @return an Object which is the 'nth'target of this Relation, - e.g. the Object at index i in the list of Objects having the - specified relationship to this Accessible. - """ - func = self.get_dbus_method("getTarget") - return func(*args, **kwargs) - - def unImplemented(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented") - return func(*args, **kwargs) - def unImplemented2(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented2") - return func(*args, **kwargs) - - def unImplemented3(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented3") - return func(*args, **kwargs) - - def unImplemented4(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented4") - return func(*args, **kwargs) - - -class RelationType(_Enum): - _enum_lookup = { - 0:'RELATION_NULL', - 1:'RELATION_LABEL_FOR', - 2:'RELATION_LABELLED_BY', - 3:'RELATION_CONTROLLER_FOR', - 4:'RELATION_CONTROLLED_BY', - 5:'RELATION_MEMBER_OF', - 6:'RELATION_TOOLTIP_FOR', - 7:'RELATION_NODE_CHILD_OF', - 8:'RELATION_EXTENDED', - 9:'RELATION_FLOWS_TO', - 10:'RELATION_FLOWS_FROM', - 11:'RELATION_SUBWINDOW_OF', - 12:'RELATION_EMBEDS', - 13:'RELATION_EMBEDDED_BY', - 14:'RELATION_POPUP_FOR', - 15:'RELATION_PARENT_WINDOW_OF', - 16:'RELATION_DESCRIPTION_FOR', - 17:'RELATION_DESCRIBED_BY', - 18:'RELATION_LAST_DEFINED', - } class Role(_Enum): _enum_lookup = { @@ -2662,22 +2341,6 @@ class Selector(_BaseProxy): func = self.get_dbus_method("replaceCommands") return func(*args, **kwargs) - def unImplemented(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented") - return func(*args, **kwargs) - - def unImplemented2(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented2") - return func(*args, **kwargs) - - def unImplemented3(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented3") - return func(*args, **kwargs) - - def unImplemented4(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented4") - return func(*args, **kwargs) - def get_supportsReplace(self): self._pgetter(self._dbus_interface, "supportsReplace") def set_supportsReplace(self, value): @@ -2712,132 +2375,6 @@ class Selector(_BaseProxy): COMMAND_RESULT_SUCCESS = CommandResult(1) -class StateSet(_BaseProxy): - """ - The StateSet interface encapsulates a collection of state information. - It allows comparison of state information between object instances, - and comparisons of an object's state with some hypothetical collection - of states. - """ - - def add(self, *args, **kwargs): - """ - Add a StateType to an existing StateSet, if not already present. - """ - func = self.get_dbus_method("add") - return func(*args, **kwargs) - - def compare(self, *args, **kwargs): - """ - Compare two StateSet instances and obtain their differences. - @return a 'difference set', i.e. a StateSet consisting of those - states not shared by the two sets being compared. - """ - func = self.get_dbus_method("compare") - return func(*args, **kwargs) - - def contains(self, *args, **kwargs): - """ - Query a StateSet for a specific StateType. - @param : state - the StateType being queried for. - @return TRUE if the StateSet contains StateType state. - """ - func = self.get_dbus_method("contains") - return func(*args, **kwargs) - - def equals(self, *args, **kwargs): - """ - Compare two statesets for equivalence. - @param : tarStateSet - the StateSet to be compared with this one. - @return TRUE if the two StateSet objects are composed of the - same StateTypes. - """ - func = self.get_dbus_method("equals") - return func(*args, **kwargs) - - def getStates(self, *args, **kwargs): - func = self.get_dbus_method("getStates") - return func(*args, **kwargs) - - def isEmpty(self, *args, **kwargs): - """ - @return TRUE if the StateSet contains no states. - """ - func = self.get_dbus_method("isEmpty") - return func(*args, **kwargs) - - def remove(self, *args, **kwargs): - """ - Remove a StateType to an existing StateSet, if it is present. - """ - func = self.get_dbus_method("remove") - return func(*args, **kwargs) - - def unImplemented(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented") - return func(*args, **kwargs) - - def unImplemented2(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented2") - return func(*args, **kwargs) - - def unImplemented3(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented3") - return func(*args, **kwargs) - - def unImplemented4(self, *args, **kwargs): - func = self.get_dbus_method("unImplemented4") - return func(*args, **kwargs) - - -class StateType(_Enum): - _enum_lookup = { - 0:'STATE_INVALID', - 1:'STATE_ACTIVE', - 2:'STATE_ARMED', - 3:'STATE_BUSY', - 4:'STATE_CHECKED', - 5:'STATE_COLLAPSED', - 6:'STATE_DEFUNCT', - 7:'STATE_EDITABLE', - 8:'STATE_ENABLED', - 9:'STATE_EXPANDABLE', - 10:'STATE_EXPANDED', - 11:'STATE_FOCUSABLE', - 12:'STATE_FOCUSED', - 13:'STATE_HAS_TOOLTIP', - 14:'STATE_HORIZONTAL', - 15:'STATE_ICONIFIED', - 16:'STATE_MODAL', - 17:'STATE_MULTI_LINE', - 18:'STATE_MULTISELECTABLE', - 19:'STATE_OPAQUE', - 20:'STATE_PRESSED', - 21:'STATE_RESIZABLE', - 22:'STATE_SELECTABLE', - 23:'STATE_SELECTED', - 24:'STATE_SENSITIVE', - 25:'STATE_SHOWING', - 26:'STATE_SINGLE_LINE', - 27:'STATE_STALE', - 28:'STATE_TRANSIENT', - 29:'STATE_VERTICAL', - 30:'STATE_VISIBLE', - 31:'STATE_MANAGES_DESCENDANTS', - 32:'STATE_INDETERMINATE', - 33:'STATE_REQUIRED', - 34:'STATE_TRUNCATED', - 35:'STATE_ANIMATED', - 36:'STATE_INVALID_ENTRY', - 37:'STATE_SUPPORTS_AUTOCOMPLETION', - 38:'STATE_SELECTABLE_TEXT', - 39:'STATE_IS_DEFAULT', - 40:'STATE_VISITED', - 41:'STATE_LAST_DEFINED', - } - class StreamableContent(_BaseProxy): """ An interface whereby an object allows its backing content to @@ -3441,43 +2978,6 @@ MODIFIER_SHIFT = ModifierType(0) MODIFIER_SHIFTLOCK = ModifierType(1) -RELATION_CONTROLLED_BY = RelationType(4) - -RELATION_CONTROLLER_FOR = RelationType(3) - -RELATION_DESCRIBED_BY = RelationType(17) - -RELATION_DESCRIPTION_FOR = RelationType(16) - -RELATION_EMBEDDED_BY = RelationType(13) - -RELATION_EMBEDS = RelationType(12) - -RELATION_EXTENDED = RelationType(8) - -RELATION_FLOWS_FROM = RelationType(10) - -RELATION_FLOWS_TO = RelationType(9) - -RELATION_LABELLED_BY = RelationType(2) - -RELATION_LABEL_FOR = RelationType(1) - -RELATION_LAST_DEFINED = RelationType(18) - -RELATION_MEMBER_OF = RelationType(5) - -RELATION_NODE_CHILD_OF = RelationType(7) - -RELATION_NULL = RelationType(0) - -RELATION_PARENT_WINDOW_OF = RelationType(15) - -RELATION_POPUP_FOR = RelationType(14) - -RELATION_SUBWINDOW_OF = RelationType(11) - -RELATION_TOOLTIP_FOR = RelationType(6) ROLE_ACCELERATOR_LABEL = Role(1) @@ -3661,90 +3161,6 @@ ROLE_VIEWPORT = Role(68) ROLE_WINDOW = Role(69) -STATE_ACTIVE = StateType(1) - -STATE_ANIMATED = StateType(35) - -STATE_ARMED = StateType(2) - -STATE_BUSY = StateType(3) - -STATE_CHECKED = StateType(4) - -STATE_COLLAPSED = StateType(5) - -STATE_DEFUNCT = StateType(6) - -STATE_EDITABLE = StateType(7) - -STATE_ENABLED = StateType(8) - -STATE_EXPANDABLE = StateType(9) - -STATE_EXPANDED = StateType(10) - -STATE_FOCUSABLE = StateType(11) - -STATE_FOCUSED = StateType(12) - -STATE_HAS_TOOLTIP = StateType(13) - -STATE_HORIZONTAL = StateType(14) - -STATE_ICONIFIED = StateType(15) - -STATE_INDETERMINATE = StateType(32) - -STATE_INVALID = StateType(0) - -STATE_INVALID_ENTRY = StateType(36) - -STATE_IS_DEFAULT = StateType(39) - -STATE_LAST_DEFINED = StateType(41) - -STATE_MANAGES_DESCENDANTS = StateType(31) - -STATE_MODAL = StateType(16) - -STATE_MULTISELECTABLE = StateType(18) - -STATE_MULTI_LINE = StateType(17) - -STATE_OPAQUE = StateType(19) - -STATE_PRESSED = StateType(20) - -STATE_REQUIRED = StateType(33) - -STATE_RESIZABLE = StateType(21) - -STATE_SELECTABLE = StateType(22) - -STATE_SELECTABLE_TEXT = StateType(38) - -STATE_SELECTED = StateType(23) - -STATE_SENSITIVE = StateType(24) - -STATE_SHOWING = StateType(25) - -STATE_SINGLE_LINE = StateType(26) - -STATE_STALE = StateType(27) - -STATE_SUPPORTS_AUTOCOMPLETION = StateType(37) - -STATE_TRANSIENT = StateType(28) - -STATE_TRUNCATED = StateType(34) - -STATE_VERTICAL = StateType(29) - -STATE_VISIBLE = StateType(30) - -STATE_VISITED = StateType(40) - TEXT_BOUNDARY_CHAR = TEXT_BOUNDARY_TYPE(0) TEXT_BOUNDARY_LINE_END = TEXT_BOUNDARY_TYPE(6) diff --git a/pyatspi/relation.py b/pyatspi/relation.py new file mode 100644 index 0000000..343ab82 --- /dev/null +++ b/pyatspi/relation.py @@ -0,0 +1,164 @@ +#Copyright (C) 2008 Codethink Ltd +#copyright: Copyright (c) 2005, 2007 IBM Corporation + +#This library is free software; you can redistribute it and/or +#modify it under the terms of the GNU Lesser General Public +#License version 2 as published by the Free Software Foundation. + +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. +#You should have received a copy of the GNU Lesser General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#Portions of this code originally licensed and copyright (c) 2005, 2007 +#IBM Corporation under the BSD license, available at +#U{http://www.opensource.org/licenses/bsd-license.php} + +#authors: Peter Parente, Mark Doffman + +from base import Enum as _Enum + +#------------------------------------------------------------------------------ + +class RelationType(_Enum): + _enum_lookup = { + 0:'RELATION_NULL', + 1:'RELATION_LABEL_FOR', + 2:'RELATION_LABELLED_BY', + 3:'RELATION_CONTROLLER_FOR', + 4:'RELATION_CONTROLLED_BY', + 5:'RELATION_MEMBER_OF', + 6:'RELATION_TOOLTIP_FOR', + 7:'RELATION_NODE_CHILD_OF', + 8:'RELATION_EXTENDED', + 9:'RELATION_FLOWS_TO', + 10:'RELATION_FLOWS_FROM', + 11:'RELATION_SUBWINDOW_OF', + 12:'RELATION_EMBEDS', + 13:'RELATION_EMBEDDED_BY', + 14:'RELATION_POPUP_FOR', + 15:'RELATION_PARENT_WINDOW_OF', + 16:'RELATION_DESCRIPTION_FOR', + 17:'RELATION_DESCRIBED_BY', + 18:'RELATION_LAST_DEFINED', + } + +#------------------------------------------------------------------------------ + +RELATION_CONTROLLED_BY = RelationType(4) + +RELATION_CONTROLLER_FOR = RelationType(3) + +RELATION_DESCRIBED_BY = RelationType(17) + +RELATION_DESCRIPTION_FOR = RelationType(16) + +RELATION_EMBEDDED_BY = RelationType(13) + +RELATION_EMBEDS = RelationType(12) + +RELATION_EXTENDED = RelationType(8) + +RELATION_FLOWS_FROM = RelationType(10) + +RELATION_FLOWS_TO = RelationType(9) + +RELATION_LABELLED_BY = RelationType(2) + +RELATION_LABEL_FOR = RelationType(1) + +RELATION_LAST_DEFINED = RelationType(18) + +RELATION_MEMBER_OF = RelationType(5) + +RELATION_NODE_CHILD_OF = RelationType(7) + +RELATION_NULL = RelationType(0) + +RELATION_PARENT_WINDOW_OF = RelationType(15) + +RELATION_POPUP_FOR = RelationType(14) + +RELATION_SUBWINDOW_OF = RelationType(11) + +RELATION_TOOLTIP_FOR = RelationType(6) + +#------------------------------------------------------------------------------ + +# Build a dictionary mapping relation values to names based on the prefix of the enum constants. + +RELATION_VALUE_TO_NAME = dict(((value, name[9:].lower().replace('_', ' ')) + for name, value + in globals().items() + if name.startswith('RELATION_'))) + +#------------------------------------------------------------------------------ + +def _marshal_relation_set(bitfield): + """ + The D-Bus protocol has a relation set passed as an array of + relation types and object arrays. + + This function marshals the D-Bus message into a list of relation + objects. + """ + (lower, upper) = bitfield + + states = [] + + pos = 0 + while (lower): + if (1L)&lower: + #TODO Return the state objects rather than integers. + states.append(pos) + pos+=1 + while (upper): + if (1L)&upper: + #TODO return the state objects rather than integers. + states.append(pos) + + return StateSet(*states) + +#------------------------------------------------------------------------------ + +class Relation(object): + """ + An interface via which objects' non-hierarchical relationships + to one another are indicated. An instance of Relations represents + a "one-to-many" correspondance. + """ + + def getNTargets(self, *args, **kwargs): + """ + @return the number of objects to which this relationship applies. + """ + func = self.get_dbus_method("getNTargets") + return func(*args, **kwargs) + + def getRelationType(self, *args, **kwargs): + """ + @return the RelationType of this Relation. + """ + func = self.get_dbus_method("getRelationType") + return func(*args, **kwargs) + + def getRelationTypeName(self, *args, **kwargs): + """ + @return an unlocalized string representing the relation type. + """ + func = self.get_dbus_method("getRelationTypeName") + return func(*args, **kwargs) + + def getTarget(self, *args, **kwargs): + """ + @return an Object which is the 'nth'target of this Relation, + e.g. the Object at index i in the list of Objects having the + specified relationship to this Accessible. + """ + func = self.get_dbus_method("getTarget") + return func(*args, **kwargs) + +#END---------------------------------------------------------------------------- diff --git a/pyatspi/stateset.py b/pyatspi/stateset.py index e41306b..971bc66 100644 --- a/pyatspi/stateset.py +++ b/pyatspi/stateset.py @@ -19,115 +19,149 @@ #authors: Peter Parente, Mark Doffman -class _StateSetImpl(Accessibility__POA.StateSet): +from base import Enum as _Enum + +#------------------------------------------------------------------------------ + +class StateType(_Enum): + _enum_lookup = { + 0:'STATE_INVALID', + 1:'STATE_ACTIVE', + 2:'STATE_ARMED', + 3:'STATE_BUSY', + 4:'STATE_CHECKED', + 5:'STATE_COLLAPSED', + 6:'STATE_DEFUNCT', + 7:'STATE_EDITABLE', + 8:'STATE_ENABLED', + 9:'STATE_EXPANDABLE', + 10:'STATE_EXPANDED', + 11:'STATE_FOCUSABLE', + 12:'STATE_FOCUSED', + 13:'STATE_HAS_TOOLTIP', + 14:'STATE_HORIZONTAL', + 15:'STATE_ICONIFIED', + 16:'STATE_MODAL', + 17:'STATE_MULTI_LINE', + 18:'STATE_MULTISELECTABLE', + 19:'STATE_OPAQUE', + 20:'STATE_PRESSED', + 21:'STATE_RESIZABLE', + 22:'STATE_SELECTABLE', + 23:'STATE_SELECTED', + 24:'STATE_SENSITIVE', + 25:'STATE_SHOWING', + 26:'STATE_SINGLE_LINE', + 27:'STATE_STALE', + 28:'STATE_TRANSIENT', + 29:'STATE_VERTICAL', + 30:'STATE_VISIBLE', + 31:'STATE_MANAGES_DESCENDANTS', + 32:'STATE_INDETERMINATE', + 33:'STATE_REQUIRED', + 34:'STATE_TRUNCATED', + 35:'STATE_ANIMATED', + 36:'STATE_INVALID_ENTRY', + 37:'STATE_SUPPORTS_AUTOCOMPLETION', + 38:'STATE_SELECTABLE_TEXT', + 39:'STATE_IS_DEFAULT', + 40:'STATE_VISITED', + 41:'STATE_LAST_DEFINED', + } + +#------------------------------------------------------------------------------ + +STATE_ACTIVE = StateType(1) +STATE_ANIMATED = StateType(35) +STATE_ARMED = StateType(2) +STATE_BUSY = StateType(3) +STATE_CHECKED = StateType(4) +STATE_COLLAPSED = StateType(5) +STATE_DEFUNCT = StateType(6) +STATE_EDITABLE = StateType(7) +STATE_ENABLED = StateType(8) +STATE_EXPANDABLE = StateType(9) +STATE_EXPANDED = StateType(10) +STATE_FOCUSABLE = StateType(11) +STATE_FOCUSED = StateType(12) +STATE_HAS_TOOLTIP = StateType(13) +STATE_HORIZONTAL = StateType(14) +STATE_ICONIFIED = StateType(15) +STATE_INDETERMINATE = StateType(32) +STATE_INVALID = StateType(0) +STATE_INVALID_ENTRY = StateType(36) +STATE_IS_DEFAULT = StateType(39) +STATE_LAST_DEFINED = StateType(41) +STATE_MANAGES_DESCENDANTS = StateType(31) +STATE_MODAL = StateType(16) +STATE_MULTISELECTABLE = StateType(18) +STATE_MULTI_LINE = StateType(17) +STATE_OPAQUE = StateType(19) +STATE_PRESSED = StateType(20) +STATE_REQUIRED = StateType(33) +STATE_RESIZABLE = StateType(21) +STATE_SELECTABLE = StateType(22) +STATE_SELECTABLE_TEXT = StateType(38) +STATE_SELECTED = StateType(23) +STATE_SENSITIVE = StateType(24) +STATE_SHOWING = StateType(25) +STATE_SINGLE_LINE = StateType(26) +STATE_STALE = StateType(27) +STATE_SUPPORTS_AUTOCOMPLETION = StateType(37) +STATE_TRANSIENT = StateType(28) +STATE_TRUNCATED = StateType(34) +STATE_VERTICAL = StateType(29) +STATE_VISIBLE = StateType(30) +STATE_VISITED = StateType(40) + +#------------------------------------------------------------------------------ + +# Build a dictionary mapping state values to names based on the prefix of the enum constants. + +STATE_VALUE_TO_NAME = dict(((value, name[6:].lower().replace('_', ' ')) + for name, value + in globals().items() + if name.startswith('STATE_'))) + +#------------------------------------------------------------------------------ + +def _marshal_state_set(bitfield): """ - Implementation of the StateSet interface. Clients should not use this class - directly, but rather the L{StateSet} proxy class. - - @param states: Set of states - @type states: set + The D-Bus protocol has a stateset object passed + as a 64bit bitfield. The Bits are passed as two 32bit + integers. + + This function marshals the D-Bus message into a + StateSet object that corresponds to these states. """ - def __init__(self): - """Initializes the state set.""" - self.states = set() - - def contains(self, state): - """ - Checks if this StateSet contains the given state. - - @param state: State to check - @type state: Accessibility.StateType - @return: True if the set contains the given state - @rtype: boolean - """ - return state in self.states - - def add(self, state): - """ - Adds a state to this set. - - @param state: State to add - @type state: Accessibility.StateType - """ - self.states.add(state) - - def remove(self, state): - """ - Removes a state from this set. - - @param state: State to remove - @type state: Accessibility.StateType - """ - self.states.remove(state) - - def equals(self, state_set): - """ - Checks if this StateSet contains exactly the same members as the given - StateSet. - - @param state_set: Another set - @type state_set: Accessibility.StateSet - @return: Are the sets equivalent in terms of their contents? - @rtype: boolean - """ - # don't check private members, object might be from another process - # or implementation - return set(state_set.getStates()) == self.states - - def compare(self, state_set): - """ - Computes the symmetric differences of this L{StateSet} and the given - L{StateSet}. - - @note: This method is not currently implemented because of difficulties - with reference counting. This method needs to return a new - Accessibility.StateSet object, but the Python implementation for that - object needs to be kept alive. The problem is who will keep that - server implementation alive? As soon as it goes out of scope, it's - GC'ed. This object cannot keep it alive either as it may go out of - scope before the new object is ready to be finalized. With a global - cache of objects, we don't know when to invalidate. - - @param state_set: Another set - @type state_set: Accessibility.StateSet - @return: Elements in only one of the two sets - @rtype: Accessibility.StateSet - """ - raise ORBit.CORBA.NO_IMPLEMENT - - # don't check private members, object might be from another process - # or implementation - #states = set(state_set.getStates()) - #diff = self.states.symmetric_difference(states) - #new_ss = _StateSetImpl() - #map(new_ss._this().add, diff) - #return new_ss._this() - - def isEmpty(self): - """ - Checks if this L{StateSet} is empty. - - @return: Is it empty? - @rtype: boolean - """ - return len(self.states) == 0 + (lower, upper) = bitfield - def getStates(self): - """ - Gets the sequence of all states in this set. - - @return: List of states - @rtype: list - """ - return list(self.states) + states = [] + + pos = 0 + while (lower): + if (1L)&lower: + #TODO Return the state objects rather than integers. + states.append(pos) + pos+=1 + while (upper): + if (1L)&upper: + #TODO return the state objects rather than integers. + states.append(pos) + + return StateSet(*states) + +#------------------------------------------------------------------------------ class StateSet(object): """ - Python proxy for the L{_StateSetImpl} class. Use this to safely instantiate - new StateSet objects in Python. + The StateSet object implements a wrapper around a + bitmap of Accessible states. - @param impl: State set implementation - @type impl: L{_StateSetImpl} + The StateSet object is the instantaneous state of + the Accessible object and is not updated with its + container Accessible. This behaviour is different + to the CORBA version of AT-SPI """ def __init__(self, *states): """ @@ -136,8 +170,8 @@ class StateSet(object): @param states: States to add immediately @type states: list """ - self.impl = _StateSetImpl() - map(self.impl._this().add, states) + map(self.add, states) + self.states = set() def contains(self, state): """ @@ -148,7 +182,7 @@ class StateSet(object): @return: True if the set contains the given state @rtype: boolean """ - return self.impl._this().contains(state) + return state in self.states def add(self, *states): """ @@ -157,7 +191,7 @@ class StateSet(object): @param states: State(s) to add @type states: Accessibility.StateType """ - map(self.impl._this().add, states) + self.states.add(state) def remove(self, state): """ @@ -166,7 +200,7 @@ class StateSet(object): @param states: State(s) to remove @type states: Accessibility.StateType """ - map(self.impl._this().remove, state) + self.states.remove(state) def equals(self, state_set): """ @@ -178,10 +212,7 @@ class StateSet(object): @return: Are the sets equivalent in terms of their contents? @rtype: boolean """ - if isinstance(state_set, self.__class__): - # convenience if we're given a proxy - state_set = state_set.raw() - return self.impl._this().equals(state_set) + return set(state_set.getStates()) == self.states def compare(self, state_set): """ @@ -195,10 +226,7 @@ class StateSet(object): @return: Proxy for the new set @rtype: L{StateSet} """ - if isinstance(state_set, self.__class__): - # shortcut if it's another one of our proxies - state_set = state_set.raw() - a = set(self.impl._this().getStates()) + a = set(self.getStates()) b = set(state_set.getStates()) diff = a.symmetric_difference(b) return StateSet(*diff) @@ -210,7 +238,7 @@ class StateSet(object): @return: Is it empty? @rtype: boolean """ - return self.impl._this().isEmpty() + return len(self.states) == 0 def getStates(self): """ @@ -219,14 +247,6 @@ class StateSet(object): @return: List of states @rtype: list """ - return self.impl._this().getStates() - - def raw(self): - """ - Gets the Accessibility.StateSet object proxied for use in a remote - call. + return list(self.states) - @return: State set - @rtype: Accessibility.StateSet - """ - return self.impl._this() +#END---------------------------------------------------------------------------- diff --git a/pyatspi/test.py b/pyatspi/test.py index 3696e5e..a7b0fee 100644 --- a/pyatspi/test.py +++ b/pyatspi/test.py @@ -15,7 +15,11 @@ from cache import AccessibleCache from factory import create_accessible -import constants +import interfaces + +__all__ = [ + "TestApplicationCache", + ] #------------------------------------------------------------------------------ @@ -42,8 +46,9 @@ class TestApplicationCache(object): return create_accessible(self, self._bus_name, self._accessible_cache.root, - None, - constants.ATSPI_ACCESSIBLE, + interfaces.ATSPI_ACCESSIBLE, connection=self._connection) root = property(fget=get_root) + +#END---------------------------------------------------------------------------- diff --git a/pyatspi/utils.py b/pyatspi/utils.py index 60c8238..f086bdc 100644 --- a/pyatspi/utils.py +++ b/pyatspi/utils.py @@ -19,7 +19,17 @@ #authors: Peter Parente, Mark Doffman -#TODO Re-implement and import the stateset server +def setCacheLevel(level): + pass + +def getCacheLevel(): + return None + +def clearCache(): + pass + +def printCache(): + print "Print cache function is deprecated"; def getInterfaceIID(obj): """ -- 2.7.4