[orca] Get Orca doing a better job of presenting the Evolution Account Assistant



commit 1c11d4d3fc725e82363a35284f7dfe9894f9ad1e
Author: Joanmarie Diggs <jdiggs igalia com>
Date:   Sun Jan 13 14:49:13 2013 -0500

    Get Orca doing a better job of presenting the Evolution Account Assistant

 src/orca/scripts/apps/evolution/script.py          |   90 ++++++-------------
 .../scripts/apps/evolution/script_utilities.py     |   96 --------------------
 .../scripts/apps/evolution/speech_generator.py     |   41 ++-------
 3 files changed, 35 insertions(+), 192 deletions(-)
---
diff --git a/src/orca/scripts/apps/evolution/script.py b/src/orca/scripts/apps/evolution/script.py
index bb057f2..3dc8eae 100644
--- a/src/orca/scripts/apps/evolution/script.py
+++ b/src/orca/scripts/apps/evolution/script.py
@@ -1,6 +1,7 @@
 # Orca
 #
 # Copyright 2005-2008 Sun Microsystems Inc.
+# Copyright 2013 Igalia, S.L.
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -22,7 +23,8 @@
 __id__        = "$Id$"
 __version__   = "$Revision$"
 __date__      = "$Date$"
-__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
+__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc." \
+                "Copyright (c) 2013 Igalia, S.L."
 __license__   = "LGPL"
 
 import pyatspi
@@ -76,10 +78,6 @@ class Script(default.Script):
         #
         self.spellCheckDialog = None
 
-        # Last Setup Assistant panel spoken.
-        #
-        self.lastSetupPanel = None
-
         # The last row and column we were on in the mail message header list.
 
         self.lastMessageColumn = -1
@@ -148,16 +146,6 @@ class Script(default.Script):
 
         return keyBindings
 
-    def getListeners(self):
-        """Sets up the AT-SPI event listeners for this script.
-        """
-        listeners = default.Script.getListeners(self)
-
-        listeners["object:state-changed:showing"]           = \
-            self.onStateChanged
-
-        return listeners
-
     def isActivatableEvent(self, event):
         """Returns True if the given event is one that should cause this
         script to become the active script.  This is only a hint to
@@ -227,9 +215,6 @@ class Script(default.Script):
         brailleGen = self.brailleGenerator
         speechGen = self.speechGenerator
 
-        details = debug.getAccessibleDetails(self.debugLevel, event.source)
-        debug.printObjectEvent(self.debugLevel, event, details)
-
         # We always automatically go back to focus tracking mode when
         # the focus changes.
         #
@@ -1012,24 +997,38 @@ class Script(default.Script):
         default.Script.onFocus(self, event)
 
     def onStateChanged(self, event):
-        """Called whenever an object's state changes.  We are only
-        interested in "object:state-changed:showing" events for any
-        object in the Setup Assistant.
+        """Called whenever an object's state changes.
 
         Arguments:
         - event: the Event
         """
 
-        if self.utilities.isWizardNewInfoEvent(event):
-            if event.source.getRole() == pyatspi.ROLE_PANEL:
-                self.lastSetupPanel = event.source
-            self.presentWizardNewInfo(
-                self.utilities.topLevelObject(event.source))
+        if not event.detail1:
+            default.Script.onStateChanged(self, event)
+            return
+
+        # Present text in the Account Assistant
+        if event.type.startswith("object:state-changed:showing"):
+            try:
+                role = event.source.getRole()
+                relationSet = event.source.getRelationSet()
+            except:
+                return
+
+            if role != pyatspi.ROLE_LABEL or relationSet:
+                default.Script.onStateChanged(self, event)
+                return
+
+            window = self.utilities.topLevelObject(event.source)
+            focusedObj = self.utilities.focusedObject(window)
+            if self.utilities.spatialComparison(event.source, focusedObj) >= 0:
+                return
+
+            voice = self.voices.get(settings.DEFAULT_VOICE)
+            text = self.utilities.displayedText(event.source)
+            self.presentMessage(text, voice=voice)
             return
 
-        # For everything else, pass the event onto the parent class
-        # to be handled in the default way.
-        #
         default.Script.onStateChanged(self, event)
 
     def onTextInserted(self, event):
@@ -1097,39 +1096,6 @@ class Script(default.Script):
         else:
             speech.speak(line, None, False)
 
-    def presentWizardNewInfo(self, obj):
-        """Causes the new information displayed in a wizard to be presented
-        to the user.
-
-        Arguments:
-        - obj: the Accessible object
-        """
-
-        if not obj:
-            return
-
-        # TODO - JD: Presenting the Setup Assistant (or any Wizard) as a
-        # dialog means that we will repeat the dialog's name for each new
-        # "screen". We should consider a 'ROLE_WIZARD' or some other means
-        # for presenting these objects.
-        #
-        utterances = \
-            self.speechGenerator.generateSpeech(obj, role=pyatspi.ROLE_DIALOG)
-
-        # The following falls under the heading of "suck it and see." The
-        # worst case scenario is that we present the push button and then
-        # process a focus:/object:state-changed:focused event and present
-        # it.
-        #
-        if orca_state.locusOfFocus \
-           and orca_state.locusOfFocus.getRole() == pyatspi.ROLE_PUSH_BUTTON \
-           and orca_state.locusOfFocus.getState().\
-               contains(pyatspi.STATE_FOCUSED):
-            utterances.append(
-                self.speechGenerator.generateSpeech(orca_state.locusOfFocus))
-
-        speech.speak(utterances)
-
     def readPageTab(self, tab):
         """Speak/Braille the given page tab. The speech verbosity is set
            to VERBOSITY_LEVEL_BRIEF for this operation and then restored
diff --git a/src/orca/scripts/apps/evolution/script_utilities.py b/src/orca/scripts/apps/evolution/script_utilities.py
index d9ac16f..00b9f01 100644
--- a/src/orca/scripts/apps/evolution/script_utilities.py
+++ b/src/orca/scripts/apps/evolution/script_utilities.py
@@ -119,102 +119,6 @@ class Utilities(script_utilities.Utilities):
 
         return False
 
-    def isWizard(self, obj):
-        """Returns True if this object is, or is within, a wizard.
-
-        Arguments:
-        - obj: the Accessible object
-        """
-
-        # The Setup Assistant is a frame whose child is a panel. That panel
-        # holds a bunch of other panels, one for each stage in the wizard.
-        # Only the active stage's panel has STATE_SHOWING. There is also
-        # one child of ROLE_FILLER which holds the buttons.
-        #
-        window = self.topLevelObject(obj) or obj
-        if window and window.getRole() == pyatspi.ROLE_FRAME \
-           and window.childCount and window[0].getRole() == pyatspi.ROLE_PANEL:
-            allPanels = panelsNotShowing = 0
-            for child in window[0]:
-                if child.getRole() == pyatspi.ROLE_PANEL:
-                    allPanels += 1
-                    if not child.getState().contains(pyatspi.STATE_SHOWING):
-                        panelsNotShowing += 1
-            if allPanels - panelsNotShowing == 1 \
-               and window[0].childCount - allPanels == 1:
-                return True
-
-        return False
-
-    def isWizardNewInfoEvent(self, event):
-        """Returns True if the event is judged to be the presentation of
-        new information in a wizard. This method should be subclassed by
-        application scripts as needed.
-
-        Arguments:
-        - event: the Accessible event being examined
-        """
-
-        if event.source.getRole() == pyatspi.ROLE_FRAME \
-           and (event.type.startswith("window:activate") \
-                or (event.type.startswith("object:state-changed:active") \
-                    and event.detail1 == 1)):
-            return self.isWizard(event.source)
-
-        elif event.source.getRole() == pyatspi.ROLE_PANEL \
-             and event.type.startswith("object:state-changed:showing") \
-             and event.detail1 == 1 \
-             and not self.isSameObject(event.source, 
-                                       self._script.lastSetupPanel):
-            rolesList = [pyatspi.ROLE_PANEL,
-                         pyatspi.ROLE_PANEL,
-                         pyatspi.ROLE_FRAME]
-            if self.hasMatchingHierarchy(event.source, rolesList):
-                return self.isWizard(event.source)
-
-        return False
-
-    def unrelatedLabels(self, root):
-        """Returns a list containing all the unrelated (i.e., have no
-        relations to anything and are not a fundamental element of a
-        more atomic component like a combo box) labels under the given
-        root.  Note that the labels must also be showing on the display.
-
-        Arguments:
-        - root the Accessible object to traverse
-
-        Returns a list of unrelated labels under the given root.
-        """
-
-        labels = script_utilities.Utilities.unrelatedLabels(self, root)
-        for i, label in enumerate(labels):
-            if not label.getState().contains(pyatspi.STATE_SENSITIVE):
-                labels.remove(label)
-            else:
-                try:
-                    text = label.queryText()
-                except:
-                    pass
-                else:
-                    attr = text.getAttributes(0)
-                    if attr[0]:
-                        [charKeys, charDict] = \
-                            self.stringToKeysAndDict(attr[0])
-                        if charDict.get('weight', '400') == '700':
-                            if self.isWizard(root):
-                                # We've passed the wizard info at the top,
-                                # which is what we want to present. The rest
-                                # is noise.
-                                #
-                                return labels[0:i]
-                            else:
-                                # This label is bold and thus serving as a
-                                # heading. As such, it's not really unrelated.
-                                #
-                                labels.remove(label)
-
-        return labels
-
     #########################################################################
     #                                                                       #
     # Utilities for working with the accessible text interface              #
diff --git a/src/orca/scripts/apps/evolution/speech_generator.py b/src/orca/scripts/apps/evolution/speech_generator.py
index ccd6135..30cc273 100644
--- a/src/orca/scripts/apps/evolution/speech_generator.py
+++ b/src/orca/scripts/apps/evolution/speech_generator.py
@@ -139,39 +139,12 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
             result.extend(acss)
         return result
 
-    def _generateUnrelatedLabels(self, obj, **args):
-        """Returns, as an array of strings (and possibly voice
-        specifications), all the labels which are underneath the obj's
-        hierarchy and which are not in a label for or labelled by
-        relation.
-        """
+    def generateSpeech(self, obj, **args):
+        result = []
+        if obj.getRole() == pyatspi.ROLE_FRAME:
+            focusedObj = self._script.utilities.focusedObject(obj)
+            if focusedObj and focusedObj.getRole() == pyatspi.ROLE_PUSH_BUTTON:
+                args['role'] = pyatspi.ROLE_DIALOG
 
-        if not self._script.utilities.isWizard(obj):
-            return speech_generator.SpeechGenerator.\
-                _generateUnrelatedLabels(self, obj, **args)
+        return speech_generator.SpeechGenerator.generateSpeech(self, obj, **args)
 
-        result = []
-        acss = self.voice(speech_generator.DEFAULT)
-        labels = self._script.utilities.unrelatedLabels(obj)
-        for label in labels:
-            name = self._generateName(label, **args)
-            try:
-                text = label.queryText()
-            except:
-                pass
-            else:
-                attr = text.getAttributes(0)
-                if attr[0]:
-                    [charKeys, charDict] = \
-                        self._script.utilities.stringToKeysAndDict(attr[0])
-                    if charDict.get('weight', '400') == '800':
-                        # It's a new "screen" in the Setup Assistant.
-                        #
-                        name = self._script.utilities.displayedText(label)
-                        # Translators: this is the name of a setup
-                        # assistant window/screen in Evolution.
-                        #
-                        name = [_("%s screen") % name]
-            result.extend(name)
-            result.extend(acss)
-        return result



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