[pyatspi2] Added collection support



commit 8d25a5581c406255cfb88880540ebde20dc06531
Author: Mike Gorse <mgorse novell com>
Date:   Fri Dec 18 12:06:10 2009 -0500

    Added collection support

 pyatspi/accessible.py           |    2 +-
 pyatspi/collection.py           |  192 +++++++++++++++++++++++++++------------
 pyatspi/state.py                |   16 +++
 tests/pyatspi/collectiontest.py |  160 ++++++++++++++++++++++++++++++++
 tests/pyatspi/runtests.sh       |    1 +
 5 files changed, 311 insertions(+), 60 deletions(-)
---
diff --git a/pyatspi/accessible.py b/pyatspi/accessible.py
index e98b62e..825b601 100644
--- a/pyatspi/accessible.py
+++ b/pyatspi/accessible.py
@@ -409,7 +409,7 @@ class Accessible(BaseProxy):
                 or raises a NotImplemented error if the given interface
                 is not supported.
                 """
-                if interface in self.interfaces:
+                if interface in self.interfaces or interface == "org.freedesktop.atspi.Collection":
                         return self.acc_factory.create_accessible(self.app_name,
                                                                   self.acc_path,
                                                                   interface,
diff --git a/pyatspi/collection.py b/pyatspi/collection.py
index d52b782..ffaa87c 100644
--- a/pyatspi/collection.py
+++ b/pyatspi/collection.py
@@ -16,51 +16,49 @@ from interfaces import *
 from enum import Enum
 from accessible import Accessible
 
+from dbus.types import UInt32
+
 __all__ = [
-            "Collection",
+           "Collection",
+           "MatchRule",
+           "SortOrder",
+           "MatchType",
+           "TreeTraversalType",
           ]
 
 #------------------------------------------------------------------------------
 
-class Collection(Accessible):
-
-        def createMatchRule(self, *args, **kwargs):
-                func = self.get_dbus_method("CreateMatchRule", dbus_interface=ATSPI_COLLECTION)
-                return func(*args, **kwargs)
-
-        def freeMatchRule(self, *args, **kwargs):
-                func = self.get_dbus_method("FreeMatchRule", dbus_interface=ATSPI_COLLECTION)
-                return func(*args, **kwargs)
-
-        def getActiveDescendant(self, *args, **kwargs):
-                func = self.get_dbus_method("GetActiveDescendant", dbus_interface=ATSPI_COLLECTION)
-                return func(*args, **kwargs)
+class MatchType(Enum):
+        _enum_lookup = {
+                0:'MATCH_INVALID',
+                1:'MATCH_ALL',
+                2:'MATCH_ANY',
+                3:'MATCH_NONE',
+                4:'MATCH_EMPTY',
+                5:'MATCH_LAST_DEFINED',
+        }
+
+class SortOrder(Enum):
+        _enum_lookup = {
+                0:'SORT_ORDER_INVALID',
+                1:'SORT_ORDER_CANONICAL',
+                2:'SORT_ORDER_FLOW',
+                3:'SORT_ORDER_TAB',
+                4:'SORT_ORDER_REVERSE_CANONICAL',
+                5:'SORT_ORDER_REVERSE_FLOW',
+                6:'SORT_ORDER_REVERSE_TAB',
+                7:'SORT_ORDER_LAST_DEFINED',
+        }
+
+class TreeTraversalType(Enum):
+        _enum_lookup = {
+                0:'TREE_RESTRICT_CHILDREN',
+                1:'TREE_RESTRICT_SIBLING',
+                2:'TREE_INORDER',
+                3:'TREE_LAST_DEFINED',
+        }
 
-        def getMatches(self, *args, **kwargs):
-                func = self.get_dbus_method("GetMatches", dbus_interface=ATSPI_COLLECTION)
-                return func(*args, **kwargs)
-
-        def getMatchesFrom(self, *args, **kwargs):
-                func = self.get_dbus_method("GetMatchesFrom", dbus_interface=ATSPI_COLLECTION)
-                return func(*args, **kwargs)
-
-        def getMatchesTo(self, *args, **kwargs):
-                func = self.get_dbus_method("GetMatchesTo", dbus_interface=ATSPI_COLLECTION)
-                return func(*args, **kwargs)
-
-        def isAncestorOf(self, *args, **kwargs):
-                func = self.get_dbus_method("IsAncestorOf", dbus_interface=ATSPI_COLLECTION)
-                return func(*args, **kwargs)
-
-        class MatchType(Enum):
-                _enum_lookup = {
-                        0:'MATCH_INVALID',
-                        1:'MATCH_ALL',
-                        2:'MATCH_ANY',
-                        3:'MATCH_NONE',
-                        4:'MATCH_EMPTY',
-                        5:'MATCH_LAST_DEFINED',
-                }
+class Collection(Accessible):
 
         MATCH_ALL = MatchType(1)
         MATCH_ANY = MatchType(2)
@@ -69,18 +67,6 @@ class Collection(Accessible):
         MATCH_LAST_DEFINED = MatchType(5)
         MATCH_NONE = MatchType(3)
 
-        class SortOrder(Enum):
-                _enum_lookup = {
-                        0:'SORT_ORDER_INVALID',
-                        1:'SORT_ORDER_CANONICAL',
-                        2:'SORT_ORDER_FLOW',
-                        3:'SORT_ORDER_TAB',
-                        4:'SORT_ORDER_REVERSE_CANONICAL',
-                        5:'SORT_ORDER_REVERSE_FLOW',
-                        6:'SORT_ORDER_REVERSE_TAB',
-                        7:'SORT_ORDER_LAST_DEFINED',
-                }
-
         SORT_ORDER_CANONICAL = SortOrder(1)
         SORT_ORDER_FLOW = SortOrder(2)
         SORT_ORDER_INVALID = SortOrder(0)
@@ -90,17 +76,105 @@ class Collection(Accessible):
         SORT_ORDER_REVERSE_TAB = SortOrder(6)
         SORT_ORDER_TAB = SortOrder(3)
 
-        class TreeTraversalType(Enum):
-                _enum_lookup = {
-                        0:'TREE_RESTRICT_CHILDREN',
-                        1:'TREE_RESTRICT_SIBLING',
-                        2:'TREE_INORDER',
-                        3:'TREE_LAST_DEFINED',
-                }
-
         TREE_INORDER = TreeTraversalType(2)
         TREE_LAST_DEFINED = TreeTraversalType(3)
         TREE_RESTRICT_CHILDREN = TreeTraversalType(0)
         TREE_RESTRICT_SIBLING = TreeTraversalType(1)
 
+        def isAncestorOf(self, object):
+                print "isAncestorOf unimplemented"
+                return False
+
+        def createMatchRule(self, states, stateMatchType, attributes, attributeMatchType, roles, roleMatchType, interfaces, interfaceMatchType, invert):
+                attributes_rule = str.join("\n", attributes)
+                roles_rule = [0, 0, 0, 0]
+                for role in roles:
+                        roles_rule[role/32] |= (1<<(role%32))
+                for i in range(0,4):
+                        roles_rule[i] = int(roles_rule[i])
+                return MatchRule(states, stateMatchType, attributes_rule, attributeMatchType, roles_rule, roleMatchType, interfaces, interfaceMatchType, invert)
+
+        def freeMatchRule(self, rule):
+                pass
+
+        def getAccessibles(self, ret):
+                for i in range(0, len(ret)):
+                        (name, path) = ret[i]
+                        if (name == ""):
+                                name = self._app_name
+                        ret[i] = self.acc_factory.create_accessible(name, path,
+                                ATSPI_ACCESSIBLE)
+                return ret;
+
+        def getMatches(self, rule, sortby, count, traverse):
+                func = self.get_dbus_method("GetMatches", dbus_interface=ATSPI_COLLECTION)
+                ret = func(rule, sortby, count, traverse)
+                return self.getAccessibles (ret)
+
+        def getMatchesTo(self, current_object, rule, sortby, tree, recurse, count, traverse):
+                func = self.get_dbus_method("GetMatchesTo", dbus_interface=ATSPI_COLLECTION)
+                ret = func(current_object._acc_path, rule, sortby, tree, recurse, count, traverse)
+                return self.getAccessibles (ret)
+
+        def getMatchesFrom(self, current_object, rule, sortby, tree, count, traverse):
+                func = self.get_dbus_method("GetMatchesFrom", dbus_interface=ATSPI_COLLECTION)
+                ret = func(current_object._acc_path, rule, sortby, tree, count, traverse)
+                return self.getAccessibles (ret)
+
+        def getActiveDescendant(self):
+                print "getActiveDescendant unimplemented"
+                return
+
+class MatchRule(tuple):
+        def __new__(cls, states, stateMatchType, attributes, attributeMatchType, roles, roleMatchType, interfaces, interfaceMatchType, invert):
+                return tuple.__new__(cls, (states, int(stateMatchType), attributes, int(attributeMatchType), roles, int(roleMatchType), interfaces, int(interfaceMatchType), invert))
+        #def __init__(self, states, stateMatchType, attributes, attributeMatchType, roles, roleMatchType, interfaces, interfaceMatchType, invert):
+                #tuple.__init__(self, (states, int(stateMatchType), attributes, int(attributeMatchType), roles, int(roleMatchType), interfaces, int(interfaceMatchType), invert))
+
+        def _get_states(self):
+                return self[0]
+        def _set_states(self, val):
+                self[0] = val
+        states = property(fget=_get_states, fset=_set_states)
+        def _get_stateMatchType(self):
+                return self[1]
+        def _set_stateMatchType(self, val):
+                self[1] = val
+        stateMatchType = property(fget=_get_stateMatchType, fset=_set_stateMatchType)
+        def _get_attributes(self):
+                return self[2]
+        def _set_attributes(self, val):
+                self[2] = val
+        attributes = property(fget=_get_attributes, fset=_set_attributes)
+        def _get_attributeMatchType(self):
+                return self[3]
+        def _set_attributeMatchType(self, val):
+                self[3] = val
+        attributeMatchType = property(fget=_get_attributeMatchType, fset=_set_attributeMatchType)
+        def _get_roles(self):
+                return self[4]
+        def _set_roles(self, val):
+                self[4] = val
+        roles = property(fget=_get_roles, fset=_set_roles)
+        def _get_roleMatchType(self):
+                return self[5]
+        def _set_roleMatchType(self, val):
+                self[5] = val
+        roleMatchType = property(fget=_get_roleMatchType, fset=_set_roleMatchType)
+        def _get_interfaces(self):
+                return self[6]
+        def _set_interfaces(self, val):
+                self[6] = val
+        interfaces = property(fget=_get_interfaces, fset=_set_interfaces)
+        def _get_interfaceMatchType(self):
+                return self[7]
+        def _set_interfaceMatchType(self, val):
+                self[7] = val
+        interfaceMatchType = property(fget=_get_interfaceMatchType, fset=_set_interfaceMatchType)
+        def _get_invert(self):
+                return self[8]
+        def _set_invert(self, val):
+                self[8] = val
+        invert = property(fget=_get_invert, fset=_set_invert)
+
 #END----------------------------------------------------------------------------
diff --git a/pyatspi/state.py b/pyatspi/state.py
index 0257a11..7703a4a 100644
--- a/pyatspi/state.py
+++ b/pyatspi/state.py
@@ -253,4 +253,20 @@ class StateSet(object):
                 """
                 return list(self.states)
 
+        def raw(self):
+                """
+                Gets the sequence of all states in this set as a pair of
+                32-bit flags, suitable for transmitting via dbus..
+
+                @return: List of two 32-bit flags representing the states
+                @rtype: list
+                """
+		lower = upper = 0
+                for i in range (0, 32):
+                        if (self.contains(i)):
+                                lower |= (1 << i)
+                for i in range (32, 64):
+                        if (self.contains(i)):
+                                upper |= (1 << (i - 32))
+                return [lower, upper]
 #END----------------------------------------------------------------------------
diff --git a/tests/pyatspi/collectiontest.py b/tests/pyatspi/collectiontest.py
new file mode 100644
index 0000000..d4e8403
--- /dev/null
+++ b/tests/pyatspi/collectiontest.py
@@ -0,0 +1,160 @@
+import dbus
+import gobject
+import os.path
+
+from xml.dom import minidom
+import os
+
+from pasytest import PasyTest as _PasyTest
+
+import pyatspi
+from pyatspi import StateSet
+
+st = [pyatspi.STATE_MULTI_LINE,
+      pyatspi.STATE_MODAL,
+      pyatspi.STATE_INDETERMINATE,
+      pyatspi.STATE_SUPPORTS_AUTOCOMPLETION,
+      pyatspi.STATE_VERTICAL,]
+
+def _createNode(accessible, parentElement):
+        e = minidom.Element("accessible")
+
+        e.attributes["name"] = accessible.name
+        e.attributes["role"] = str(int(accessible.getRole()))
+        e.attributes["description"] = accessible.description
+
+        for i in range(0, accessible.childCount):
+                _createNode(accessible.getChildAtIndex(i), e)
+
+        parentElement.appendChild(e)
+
+class AccessibleTest(_PasyTest):
+
+        __tests__ = ["setup",
+                     "test_basic",
+                     "test_role",
+                     "teardown",
+                     ]
+
+        def __init__(self, bus, path):
+                _PasyTest.__init__(self, "Accessible", False)
+                self._bus = bus
+                self._path = path
+
+
+        def setup(self, test):
+                self._registry = pyatspi.Registry()
+                print self._path
+                self._desktop = self._registry.getDesktop(0)
+                print "dbg: getting root"
+                self.root = pyatspi.findDescendant (self._desktop, lambda x: x.name == "main" and x.getRole() == pyatspi.ROLE_WINDOW)
+                print "root: ", self.root
+
+        def assertObjects(self,test,obj,vars,msg):
+                test.assertEqual(len(obj), len(vars) / 2, msg + " length")
+                for i in range(0, len(vars), 2):
+                        test.assertEqual (vars[i], obj[i/2].name, msg + "name" + "#" + str(i/2))
+                        test.assertEqual(vars[i+1], obj[i/2].getRole(), msg + " role" + "#" + str(i/2))
+
+	# Used to help add new tests
+        def printAsserts(self,obj,msg):
+                print "\t\tself.assertObjects(test,ret,("
+                for i in range(0,len(obj)):
+                        print "\t\t\t\"" + obj[i].name + "\", " + str(obj[i].getRole()) + ","
+                print "\t\t), \"", msg, "\")"
+
+        def test_basic(self, test):
+                collection = self.root.queryCollection()
+                stateSet = pyatspi.StateSet()
+                rule = collection.createMatchRule (stateSet.raw(),
+                        collection.MATCH_NONE,
+                [],     # attributes
+                        collection.MATCH_NONE,
+                [],     # role
+                        collection.MATCH_NONE,
+                "",     # interfaces
+                        collection.MATCH_NONE,
+                        False)
+
+                ret = collection.getMatches (rule, collection.SORT_ORDER_CANONICAL, 5, True)
+                self.assertObjects(test,ret,(
+                        "gnome-settings-daemon", 79 ,
+                        "gnome-panel", 79 ,
+                        "Bottom Expanded Edge Panel", 25 ,
+                        "Top Expanded Edge Panel", 25 ,
+                        "nautilus", 79 ,
+                ), " 1 ")
+
+                ret = collection.getMatches (rule, collection.SORT_ORDER_REVERSE_CANONICAL, 5, True)
+                self.assertObjects(test,ret,(
+                        "nautilus", 79,
+                        "Top Expanded Edge Panel", 25,
+                        "Bottom Expanded Edge Panel", 25,
+                        "gnome-panel", 79,
+                        "gnome-settings-daemon", 79,
+                ), " reverse canonical ")
+
+                obj=ret[2]
+                ret = collection.getMatchesTo (obj, rule, collection.SORT_ORDER_REVERSE_CANONICAL, collection.TREE_INORDER, True, 5, True)
+                self.assertObjects(test,ret,(
+                        "gnome-settings-daemon", 79,
+                        "gnome-panel", 79,
+                ), " getMatchesTo ")
+                ret = collection.getMatchesFrom (obj, rule, collection.SORT_ORDER_REVERSE_CANONICAL, collection.TREE_INORDER, 5, True)
+                self.assertObjects(test,ret,(
+                        "tracker-applet", 79,
+                        "metacity", 79,
+                        "Desktop", 25,
+                        "nautilus", 79,
+                        "Top Expanded Edge Panel", 25,
+                ), " getMatchesFrom ")
+                obj = self.root.getChildAtIndex(1)
+                ret = collection.getMatchesFrom (obj, rule, collection.SORT_ORDER_CANONICAL, collection.TREE_RESTRICT_CHILDREN, 5, True)
+                self.assertObjects(test,ret,(
+                        "Top Expanded Edge Panel", 25,
+                ), " Restrict Children ")
+
+        def test_role(self, test):
+                collection = self.root.queryCollection()
+                stateSet = pyatspi.StateSet()
+
+                rule = collection.createMatchRule (stateSet.raw(),
+                        collection.MATCH_NONE,
+                [],     # attributes
+                        collection.MATCH_NONE,
+                [pyatspi.ROLE_RADIO_MENU_ITEM],
+                        collection.MATCH_ANY,
+                "",     # interfaces
+                        collection.MATCH_NONE,
+                        False)
+
+                ret = collection.getMatches (rule, collection.SORT_ORDER_CANONICAL, 5, True)
+                self.assertObjects(test,ret,(
+                        "Activity Indicator", 45,
+                        "Back", 45,
+                        "Forward", 45,
+                        "", 45,
+                        "Reload", 45,
+                ), " role ")
+
+                rule = collection.createMatchRule (stateSet.raw(),
+                        collection.MATCH_NONE,
+                [],     # attributes
+                        collection.MATCH_NONE,
+                [pyatspi.ROLE_ENTRY, pyatspi.ROLE_HTML_CONTAINER],
+                        collection.MATCH_ANY,
+                "",     # interfaces
+                        collection.MATCH_NONE,
+                        False)
+
+                ret = collection.getMatches (rule, collection.SORT_ORDER_CANONICAL, 5, True)
+                self.assertObjects(test,ret,(
+                        "gnome-settings-daemon", 79,
+                        "gnome-panel", 79,
+                        "Bottom Expanded Edge Panel", 25,
+                        "Top Expanded Edge Panel", 25,
+                        "nautilus", 79,
+                        ), " role #2")
+
+        def teardown(self, test):
+                pass
diff --git a/tests/pyatspi/runtests.sh b/tests/pyatspi/runtests.sh
index 397e310..7790462 100755
--- a/tests/pyatspi/runtests.sh
+++ b/tests/pyatspi/runtests.sh
@@ -7,6 +7,7 @@ export TEST_APPLICATION=$top_builddir/tests/apps/test-application
 
 $PYTHON $top_srcdir/tests/pyatspi/testrunner -l libaccessibleapp.so -m accessibletest -n AccessibleTest
 $PYTHON $top_srcdir/tests/pyatspi/testrunner -l libactionapp.so -m actiontest -n ActionTest
+$PYTHON $top_srcdir/tests/pyatspi/testrunner -l libaccessibleapp.so -m collectiontest -n AccessibleTest
 $PYTHON $top_srcdir/tests/pyatspi/testrunner -l libcomponentapp.so -m componenttest -n ComponentTest
 $PYTHON $top_srcdir/tests/pyatspi/testrunner -l librelationapp.so -m relationtest -n RelationTest
 $PYTHON $top_srcdir/tests/pyatspi/testrunner -l libaccessibleapp.so -m statetest -n StateTest



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]