[orca/570658] Initial pass on OOo speech generator



commit e36ba12a25adacb71bdc1d50af4ce4e35710bf9a
Author: Willie Walker <william walker sun com>
Date:   Tue May 26 17:24:19 2009 -0400

    Initial pass on OOo speech generator
    
    The oowriter tests seem to work well.  Still need to do:
    oocalc
    oobade
    ooimpress
---
 src/orca/scripts/apps/soffice/Makefile.am         |    3 +-
 src/orca/scripts/apps/soffice/formatting.py       |   62 +++
 src/orca/scripts/apps/soffice/script.py           |   11 +-
 src/orca/scripts/apps/soffice/speech_generator.py |  571 +++++++++------------
 test/harness/.gitignore                           |    5 +
 test/keystrokes/oowriter/bug_350219.py            |    3 +-
 test/keystrokes/oowriter/bug_361747.py            |    9 +-
 test/keystrokes/oowriter/bug_364765.py            |    4 +-
 test/keystrokes/oowriter/bug_382408.py            |    2 +-
 test/keystrokes/oowriter/bug_384893.py            |    6 +-
 test/keystrokes/oowriter/bug_385828.py            |   11 +-
 test/keystrokes/oowriter/bug_413909.py            |    1 -
 test/keystrokes/oowriter/bug_435201.py            |    6 +-
 test/keystrokes/oowriter/bug_435226.py            |   21 +-
 test/keystrokes/oowriter/bug_450210.py            |    1 -
 test/keystrokes/oowriter/bug_469367.py            |    3 +-
 test/keystrokes/oowriter/table-sample.odt         |  Bin 9900 -> 9266 bytes
 17 files changed, 338 insertions(+), 381 deletions(-)

diff --git a/src/orca/scripts/apps/soffice/Makefile.am b/src/orca/scripts/apps/soffice/Makefile.am
index 04741ad..5d9c71b 100644
--- a/src/orca/scripts/apps/soffice/Makefile.am
+++ b/src/orca/scripts/apps/soffice/Makefile.am
@@ -1,8 +1,9 @@
 orca_pathdir=$(pyexecdir)
 
 orca_python_PYTHON = \
-	braille_generator.py \
 	__init__.py \
+	braille_generator.py \
+	formatting.py \
 	script.py \
 	script_settings.py \
 	speech_generator.py \
diff --git a/src/orca/scripts/apps/soffice/formatting.py b/src/orca/scripts/apps/soffice/formatting.py
new file mode 100644
index 0000000..57dc619
--- /dev/null
+++ b/src/orca/scripts/apps/soffice/formatting.py
@@ -0,0 +1,62 @@
+# Orca
+#
+# Copyright 2005-2009 Sun Microsystems Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
+# Boston MA  02110-1301 USA.
+
+"""Custom formatting for OpenOffice and StarOffice."""
+
+__id__ = "$Id$"
+__version__   = "$Revision$"
+__date__      = "$Date$"
+__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc."
+__license__   = "LGPL"
+
+# pylint: disable-msg=C0301
+
+import copy
+
+import pyatspi
+
+import orca.formatting
+
+formatting = {
+    'speech': {
+        # Get rid of unselectedCell because we don't run into that in OOo
+        # and we'd end up always speaking "not selected" for all table cells.
+        #
+        'suffix': {
+            'focused': '[]',
+            'unfocused': 'newNodeLevel + tutorial'
+            },
+        pyatspi.ROLE_COMBO_BOX: {
+            'focused': 'name + availability',
+            'unfocused': 'labelAndName + roleName + availability'
+            },
+        pyatspi.ROLE_PUSH_BUTTON: {
+            'unfocused': 'labelAndName + roleName + toggleState + availability',
+            'focused': 'labelAndName + toggleState'
+            },
+        pyatspi.ROLE_TOGGLE_BUTTON: {
+            'focused': 'labelAndName + toggleState'
+            },
+    }
+}
+
+class Formatting(orca.formatting.Formatting):
+    def __init__(self, script):
+        orca.formatting.Formatting.__init__(self, script)
+        self.update(copy.deepcopy(formatting))
diff --git a/src/orca/scripts/apps/soffice/script.py b/src/orca/scripts/apps/soffice/script.py
index 3d6313f..8c2b799 100644
--- a/src/orca/scripts/apps/soffice/script.py
+++ b/src/orca/scripts/apps/soffice/script.py
@@ -54,6 +54,7 @@ from orca.orca_i18n import _ # for gettext support
 
 from speech_generator import SpeechGenerator
 from braille_generator import BrailleGenerator
+from formatting import Formatting
 from where_am_i import WhereAmI
 import script_settings
 
@@ -184,19 +185,20 @@ class Script(default.Script):
     def getBrailleGenerator(self):
         """Returns the braille generator for this script.
         """
-
         return BrailleGenerator(self)
 
     def getSpeechGenerator(self):
         """Returns the speech generator for this script.
         """
-
         return SpeechGenerator(self)
 
+    def getFormatting(self):
+        """Returns the formatting strings for this script."""
+        return Formatting(self)
+
     def getWhereAmI(self):
         """Returns the "where am I" class for this script.
         """
-
         return WhereAmI(self)
 
     def setupInputEventHandlers(self):
@@ -401,12 +403,13 @@ class Script(default.Script):
         isn't in a table.
         """
 
+        table = None
         obj = self.adjustForWriterTable(obj)
         if obj.getRole() == pyatspi.ROLE_TABLE_CELL and obj.parent:
             try:
                 table = obj.parent.queryTable()
             except NotImplementedError:
-                table = None
+                pass
 
         return table
 
diff --git a/src/orca/scripts/apps/soffice/speech_generator.py b/src/orca/scripts/apps/soffice/speech_generator.py
index a7363b5..f0e729e 100644
--- a/src/orca/scripts/apps/soffice/speech_generator.py
+++ b/src/orca/scripts/apps/soffice/speech_generator.py
@@ -1,6 +1,6 @@
 # Orca
 #
-# Copyright 2005-2008 Sun Microsystems Inc.
+# Copyright 2005-2009 Sun Microsystems Inc.
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Library General Public
@@ -22,7 +22,7 @@
 __id__        = "$Id$"
 __version__   = "$Revision$"
 __date__      = "$Date$"
-__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
+__copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc."
 __license__   = "LGPL"
 
 import pyatspi
@@ -35,217 +35,201 @@ from orca.orca_i18n import _ # for gettext support
 import script_settings
 
 class SpeechGenerator(speech_generator.SpeechGenerator):
-    """Overrides _getSpeechForComboBox so that we can provide a name for
-    the Calc Name combo box.
-    Overrides _getSpeechForTableCellRow so that , when we are in a
-    spread sheet, we can speak the dynamic row and column headers
-    (assuming they are set).
-    Overrides _getSpeechForTableCell so that, when we are in a spread
-    sheet, we can speak the location of the table cell as well as the
-    contents.
-    Overrides _getSpeechForToggleButton so that, when the toggle buttons
-    on the Formatting toolbar change state, we provide both the name and
-    the state (as "on" or "off")
-    Overrides _getSpeechForPushButton because sometimes the toggle buttons
-    on the Formatting toolbar claim to be push buttons.
-    """
-    def __init__(self, script):
-        speech_generator.SpeechGenerator.__init__(self, script)
-
-    def getSpeechForObjectRole(self, obj, role=None):
-        if obj.getRoleName() == "text frame" \
-           or (obj.getRole() == pyatspi.ROLE_PARAGRAPH \
-               and self._script.getAncestor(obj,
-                                            [pyatspi.ROLE_DIALOG],
-                                            [pyatspi.ROLE_APPLICATION])):
-            role = pyatspi.ROLE_TEXT
-            
-        return speech_generator.SpeechGenerator.\
-            getSpeechForObjectRole(self, obj, role)
-
-    def _getSpeechForComboBox(self, obj, already_focused):
-        """Get the speech for a combo box. If the combo box already has focus,
-        then only the selection is spoken.
-        Also provides a name for the OOo Calc Name combo box. This name is
-        provided in clause 5) of locusOfFocusChanged() below.
-
-        Arguments:
-        - obj: the combo box
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        utterances = []
-
-        if not already_focused:
-            label = self._getSpeechForObjectLabel(obj)
-            if not label:
-                label = [ obj.name ]
-            utterances.extend(label)
-        else:
-            label = None
-
-        name = self._getSpeechForObjectName(obj)
-        if name != label:
-            utterances.extend(name)
-
-        if not already_focused:
-            utterances.extend(self.getSpeechForObjectRole(obj))
-
-        utterances.extend(self._getSpeechForObjectAvailability(obj))
-
-        self._debugGenerator("_getSpeechForComboBox",
-                             obj,
-                             already_focused,
-                             utterances)
 
-        return utterances
+    # pylint: disable-msg=W0142
 
-    def _getSpeechForTable(self, obj, already_focused):
-        """Get the speech for a table
-
-        Arguments:
-        - obj: the table
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        utterances = self._getDefaultSpeech(obj, already_focused)
-
-        self._debugGenerator("_getSpeechForTable",
-                             obj,
-                             already_focused,
-                             utterances)
+    def __init__(self, script):
+        speech_generator.SpeechGenerator.__init__(self, script)
 
-        # If this is a table with no children, then let the user know.
+    def __overrideParagraph(self, obj, **args):
+        # Treat a paragraph which is serving as a text entry in a dialog
+        # as a text object.
         #
-        if not obj.childCount:
-            # Translators: this indicates that there are zero items in
-            # a layered pane or table.
+        role = args.get('role', obj.getRole())
+        override = \
+            role == "text frame" \
+            or (role == pyatspi.ROLE_PARAGRAPH \
+                and self._script.getAncestor(obj,
+                                             [pyatspi.ROLE_DIALOG],
+                                             [pyatspi.ROLE_APPLICATION]))
+        return override
+
+    def _getRoleName(self, obj, **args):
+        result = []
+        role = args.get('role', obj.getRole())
+        if role in [pyatspi.ROLE_PUSH_BUTTON, pyatspi.ROLE_TOGGLE_BUTTON] \
+           and obj.parent.getRole() == pyatspi.ROLE_TOOL_BAR:
+            # We don't speak roles for the objects in the toolbar.
             #
-            utterances.append(_("0 items"))
-
-        return utterances
-
-    def _getSpeechForTableCellRow(self, obj, already_focused):
-        """Get the speech for a table cell row or a single table cell
-        if settings.readTableCellRow is False. If this isn't inside a
-        spread sheet, just return the utterances returned by the default
-        table cell speech handler.
-
-        Arguments:
-        - obj: the table cell
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        utterances = []
-
-        if not already_focused:
-
-            # Check to see if this spread sheet cell has either a dynamic
-            # column heading or row heading (or both) associated with it.
-            # If it does, then speak those first before speaking the cell
-            # contents.
+            pass
+        else:
+            # Treat a paragraph which is serving as a text entry in a dialog
+            # as a text object.
             #
-            table = self._script.getTable(obj)
-            parent = obj.parent
-            try:
-                parentTable = parent.queryTable()
-            except NotImplementedError:
-                parentTable = None
-
-            index = self._script.getCellIndex(obj)
-            if "lastColumn" in self._script.pointOfReference and \
-               self._script.pointOfReference["lastColumn"] != \
-               parentTable.getColumnAtIndex(index):
-                if table in self._script.dynamicColumnHeaders:
-                    row = self._script.dynamicColumnHeaders[table]
-                    header = self._script.getDynamicRowHeaderCell(obj, row)
-                    try:
-                        headerText = header.queryText()
-                    except:
-                        headerText = None
-
-                    if header.childCount > 0:
-                        for child in header:
-                            text = self._script.getText(child, 0, -1)
-                            if text:
-                                utterances.append(text)
-                    elif headerText:
-                        text = self._script.getText(header, 0, -1)
+            override = self.__overrideParagraph(obj, **args)
+            if override:
+                oldRole = self._overrideRole(pyatspi.ROLE_TEXT, args)
+            result.extend(speech_generator.SpeechGenerator._getRoleName(
+                          self, obj, **args))
+            if override:
+                self._restoreRole(oldRole, args)
+        return result
+
+    def _getTextRole(self, obj, **args):
+        result = []
+        role = args.get('role', obj.getRole())
+        if role != pyatspi.ROLE_PARAGRAPH \
+           or self.__overrideParagraph(obj, **args):
+            result.extend(self._getRoleName(obj, **args))
+        return result
+
+    def _getLabelOrName(self, obj, **args):
+        """Gets the label or the name if the label is not preset."""
+        result = []
+        override = self.__overrideParagraph(obj, **args)
+        # Treat a paragraph which is serving as a text entry in a dialog
+        # as a text object.
+        #
+        if override:
+            result.extend(self._getLabel(obj, **args))
+            if len(result) == 0 and obj.parent:
+                parentLabel = self._getLabel(obj.parent, **args)
+                # If we aren't already focused, we will have spoken the
+                # parent as part of the speech context and do not want
+                # to repeat it.
+                #
+                already_focused = args.get('already_focused', False)
+                if already_focused:
+                    result.extend(parentLabel)
+                # If we still don't have a label, look to the name.
+                #
+                if not parentLabel and obj.name and len(obj.name):
+                    result.append(obj.name)
+        else:
+            result.extend(speech_generator.SpeechGenerator._getLabelOrName(
+                self, obj, **args))
+        return result
+
+    def _getToggleState(self, obj, **args):
+        """Treat push buttons (which act like toggle buttons) and toggle
+        buttons in the toolbar specially.  This is so we can have more
+        natural sounding speech such as "bold on", "bold off", etc."""
+        result = []
+        role = args.get('role', obj.getRole())
+        if role in [pyatspi.ROLE_PUSH_BUTTON, pyatspi.ROLE_TOGGLE_BUTTON] \
+           and obj.parent.getRole() == pyatspi.ROLE_TOOL_BAR:
+            if obj.getState().contains(pyatspi.STATE_CHECKED):
+                # Translators: this represents the state of a check box
+                #
+                result.append(_("on"))
+            else:
+                # Translators: this represents the state of a check box
+                #
+                result.append(_("off"))
+        elif role == pyatspi.ROLE_TOGGLE_BUTTON:
+            result.extend(speech_generator.SpeechGenerator._getToggleState(
+                self, obj, **args))
+        return result
+
+    def _getNewRowHeader(self, obj, **args):
+        result = []
+        # Check to see if this spread sheet cell has either a dynamic
+        # row heading associated with it.
+        #
+        table = self._script.getTable(obj)
+        parent = obj.parent
+        try:
+            parentTable = parent.queryTable()
+        except NotImplementedError:
+            parentTable = None
+        index = self._script.getCellIndex(obj)
+        if "lastRow" in self._script.pointOfReference and \
+           self._script.pointOfReference["lastRow"] != \
+           parentTable.getRowAtIndex(index):
+            if table in self._script.dynamicRowHeaders:
+                column = self._script.dynamicRowHeaders[table]
+                header = self._script.getDynamicColumnHeaderCell(obj, column)
+                try:
+                    headerText = header.queryText()
+                except:
+                    headerText = None
+                if header.childCount > 0:
+                    for child in header:
+                        text = self._script.getText(child, 0, -1)
                         if text:
-                            utterances.append(text)
-
-            if "lastRow" in self._script.pointOfReference and \
-               self._script.pointOfReference["lastRow"] != \
-               parentTable.getRowAtIndex(index):
-                if table in self._script.dynamicRowHeaders:
-                    column = self._script.dynamicRowHeaders[table]
-                    header = self._script.getDynamicColumnHeaderCell(obj,
-                                                                     column)
-                    try:
-                        headerText = header.queryText()
-                    except:
-                        headerText = None
-
-                    if header.childCount > 0:
-                        for child in header:
-                            text = self._script.getText(child, 0, -1)
-                            if text:
-                                utterances.append(text)
-                    elif headerText:
-                        text = self._script.getText(header, 0, -1)
+                            result.append(text)
+                elif headerText:
+                    text = self._script.getText(header, 0, -1)
+                    if text:
+                        result.append(text)
+        return result
+
+    def _getNewColumnHeader(self, obj, **args):
+        result = []
+        # Check to see if this spread sheet cell has either a dynamic
+        # row heading associated with it.
+        #
+        table = self._script.getTable(obj)
+        parent = obj.parent
+        try:
+            parentTable = parent.queryTable()
+        except NotImplementedError:
+            parentTable = None
+        index = self._script.getCellIndex(obj)
+        if "lastColumn" in self._script.pointOfReference and \
+           self._script.pointOfReference["lastColumn"] != \
+           parentTable.getColumnAtIndex(index):
+            if table in self._script.dynamicColumnHeaders:
+                row = self._script.dynamicColumnHeaders[table]
+                header = self._script.getDynamicRowHeaderCell(obj, row)
+                try:
+                    headerText = header.queryText()
+                except:
+                    headerText = None
+                if header.childCount > 0:
+                    for child in header:
+                        text = self._script.getText(child, 0, -1)
                         if text:
-                            utterances.append(text)
-
-        if self._script.isSpreadSheetCell(obj):
-            if not already_focused:
-                if settings.readTableCellRow:
-                    parent = obj.parent
-                    index = self._script.getCellIndex(obj)
-                    row = parentTable.getRowAtIndex(index)
-                    column = parentTable.getColumnAtIndex(index)
-
-                    # This is an indication of whether we should speak all the
-                    # table cells (the user has moved focus up or down a row),
-                    # or just the current one (focus has moved left or right in
-                    # the same row).
+                            result.append(text)
+                elif headerText:
+                    text = self._script.getText(header, 0, -1)
+                    if text:
+                        result.append(text)
+        return result
+
+    def _getSpreadSheetCell(self, obj, **args):
+        result = []
+        if self._script.inputLineForCell == None:
+            self._script.inputLineForCell = \
+                self._script.locateInputLine(obj)
+        try:
+            if obj.queryText():
+                objectText = self._script.getText(obj, 0, -1)
+                if not script_settings.speakCellCoordinates \
+                   and len(objectText) == 0:
+                    # Translators: this indicates an empty (blank) spread
+                    # sheet cell.
                     #
-                    speakAll = True
-                    if "lastRow" in self._script.pointOfReference and \
-                        "lastColumn" in self._script.pointOfReference:
-                        pointOfReference = self._script.pointOfReference
-                        speakAll = (pointOfReference["lastRow"] != row) or \
-                               ((row == 0 or row == parentTable.nRows-1) and \
-                                pointOfReference["lastColumn"] == column)
-
-                    if speakAll:
-                        [startIndex, endIndex] = \
-                            self._script.getSpreadSheetRowRange(obj)
-                        for i in range(startIndex, endIndex+1):
-                            cell = parentTable.getAccessibleAt(row, i)
-                            showing = cell.getState().contains( \
-                                          pyatspi.STATE_SHOWING)
-                            if showing:
-                                utterances.extend(self._getSpeechForTableCell(\
-                                                  cell, already_focused))
-                    else:
-                        utterances.extend(self._getSpeechForTableCell(obj,
-                                                             already_focused))
-                else:
-                    utterances.extend(self._getSpeechForTableCell(obj,
-                                                             already_focused))
-        else:
-            utterances.extend(speech_generator.SpeechGenerator.\
-                _getSpeechForTableCellRow(self, obj, already_focused))
-
-        return utterances
+                    objectText = _("blank")
+                    result.append(objectText)
+        except NotImplementedError:
+            pass
+
+        if script_settings.speakCellCoordinates:
+            nameList = obj.name.split()
+            # We were assuming that the word for "cell" would always
+            # precede the coordinates. This is not the case for all
+            # languages (e.g. Hungarian). See bug #562532. Therefore
+            # examine each item and choose the one which contains a
+            # digit.
+            #
+            for name in nameList:                    
+                for char in name.decode("UTF-8"):
+                    if char.isdigit():
+                        result.append(name)
+        return result
 
-    def _getSpeechForTableCell(self, obj, already_focused):
+    def _getRealTableCell(self, obj, **args):
         """Get the speech for a table cell. If this isn't inside a
         spread sheet, just return the utterances returned by the default
         table cell speech handler.
@@ -256,41 +240,9 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
 
         Returns a list of utterances to be spoken for the object.
         """
-
+        result = []
         if self._script.isSpreadSheetCell(obj):
-            utterances = []
-
-            if self._script.inputLineForCell == None:
-                self._script.inputLineForCell = \
-                            self._script.locateInputLine(obj)
-
-            try:
-                if obj.queryText():
-                    objectText = self._script.getText(obj, 0, -1)
-                    if not script_settings.speakCellCoordinates and \
-                            len(objectText) == 0:
-                        # Translators: this indicates an empty (blank) spread
-                        # sheet cell.
-                        #
-                        objectText = _("blank")
-
-                    utterances.append(objectText)
-            except NotImplementedError:
-                pass
-
-            if script_settings.speakCellCoordinates:
-                nameList = obj.name.split()
-                # We were assuming that the word for "cell" would always
-                # precede the coordinates. This is not the case for all
-                # languages (e.g. Hungarian). See bug #562532. Therefore
-                # examine each item and choose the one which contains a
-                # digit.
-                #
-                for name in nameList:                    
-                    for char in name.decode("UTF-8"):
-                        if char.isdigit():
-                            utterances.append(name)
-                            return utterances
+            result.extend(self._getSpreadSheetCell(obj, **args))
         else:
             # Check to see how many children this table cell has. If it's
             # just one (or none), then pass it on to the superclass to be
@@ -300,115 +252,60 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
             # and call this method again.
             #
             if obj.childCount <= 1:
-                utterances = speech_generator.SpeechGenerator.\
-                    _getSpeechForTableCell(self, obj, already_focused)
+                result.extend(speech_generator.SpeechGenerator.\
+                              _getRealTableCell(self, obj, **args))
             else:
-                utterances = []
                 for child in obj:
-                    utterances.extend(self._getSpeechForTableCell(child,
-                                                        already_focused))
-
-        return utterances
-
-    def _getSpeechForText(self, obj, already_focused):
-        """Get the speech for a paragraph which is serving as a text object
-        in a dialog.
-
-        Arguments:
-        - obj: the text component
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        utterances = []
-        if obj.getRole() == pyatspi.ROLE_PARAGRAPH \
-           and self._script.getAncestor(obj,
-                                        [pyatspi.ROLE_DIALOG],
-                                        [pyatspi.ROLE_APPLICATION]):
-            utterances.extend(self._getSpeechForObjectLabel(obj))
-            if len(utterances) == 0 and obj.parent:
-                parentLabel = self._getSpeechForObjectLabel(obj.parent)
-                # If we aren't already focused, we will have spoken the
-                # parent as part of the speech context and do not want
-                # to repeat it.
-                #
-                if already_focused:
-                    utterances.extend(parentLabel)
-                # If we still don't have a label, look to the name.
-                #
-                if not parentLabel and obj.name and len(obj.name):
-                    utterances.append(obj.name)
-
-            utterances.append(self._script.getTextLineAtCaret(obj)[0])
-            utterances.extend(self._getSpeechForAllTextSelection(obj))
-
-            self._debugGenerator("soffice _getSpeechForText",
-                                 obj,
-                                 already_focused,
-                                 utterances)
-        else:
-            utterances.extend(speech_generator.SpeechGenerator.\
-                _getSpeechForText(self, obj, already_focused))
+                    result.extend(self._getRealTableCell(child, **args))
+        return result
 
-        return utterances
-
-    def _getSpeechForToggleButton(self, obj, already_focused):
-        """Get the speech for a toggle button.  We always want to speak the
-        state if it's on a toolbar.
-
-        Arguments:
-        - obj: the toggle button
-        - already_focused: False if object just received focus
-
-        Returns a list of utterances to be spoken for the object.
-        """
-
-        utterances = []
-        if obj.parent.getRole() == pyatspi.ROLE_TOOL_BAR:
-            if obj.getState().contains(pyatspi.STATE_CHECKED):
-                # Translators: this represents the state of a check box
-                #
-                checkedState = _("on")
-            else:
-                # Translators: this represents the state of a check box
-                #
-                checkedState = _("off")
-
-            utterances.append(obj.name)
-            utterances.append(checkedState)
-        else:
-            utterances.extend(speech_generator.SpeechGenerator.\
-                _getSpeechForToggleButton(self, obj, already_focused))
-
-        return utterances
-
-    def _getSpeechForPushButton(self, obj, already_focused):
-        """Get the speech for a push button.  We always want to speak the
-        state if it's on a toolbar.
+    def _getTableCellRow(self, obj, **args):
+        """Get the speech for a table cell row or a single table cell
+        if settings.readTableCellRow is False. If this isn't inside a
+        spread sheet, just return the utterances returned by the default
+        table cell speech handler.
 
         Arguments:
-        - obj: the push button
+        - obj: the table cell
         - already_focused: False if object just received focus
 
         Returns a list of utterances to be spoken for the object.
         """
-
-        utterances = []
-        if obj.parent.getRole() == pyatspi.ROLE_TOOL_BAR:
-            if obj.getState().contains(pyatspi.STATE_CHECKED):
-                # Translators: this represents the state of a check box
+        result = []
+        if self._script.isSpreadSheetCell(obj):
+            if settings.readTableCellRow:
+                parent = obj.parent
+                parentTable = parent.queryTable()
+                index = self._script.getCellIndex(obj)
+                row = parentTable.getRowAtIndex(index)
+                column = parentTable.getColumnAtIndex(index)
+                # This is an indication of whether we should speak all the
+                # table cells (the user has moved focus up or down a row),
+                # or just the current one (focus has moved left or right in
+                # the same row).
                 #
-                checkedState = _("on")
+                speakAll = True
+                if "lastRow" in self._script.pointOfReference and \
+                    "lastColumn" in self._script.pointOfReference:
+                    pointOfReference = self._script.pointOfReference
+                    speakAll = (pointOfReference["lastRow"] != row) or \
+                           ((row == 0 or row == parentTable.nRows-1) and \
+                            pointOfReference["lastColumn"] == column)
+                if speakAll:
+                    [startIndex, endIndex] = \
+                        self._script.getSpreadSheetRowRange(obj)
+                    for i in range(startIndex, endIndex+1):
+                        cell = parentTable.getAccessibleAt(row, i)
+                        showing = cell.getState().contains( \
+                                      pyatspi.STATE_SHOWING)
+                        if showing:
+                            result.extend(self._getRealTableCell(cell, **args))
+                else:
+                    result.extend(self._getRealTableCell(obj, **args))
             else:
-                # Translators: this represents the state of a check box
-                #
-                checkedState = _("off")
-
-            utterances.append(obj.name)
-            utterances.append(checkedState)
+                result.extend(self._getRealTableCell(obj, **args))
         else:
-            utterances.extend(speech_generator.SpeechGenerator.\
-                _getSpeechForPushButton(self, obj, already_focused))
-
-        return utterances
+            print "HERE", settings.readTableCellRow
+            result.extend(speech_generator.SpeechGenerator._getTableCellRow(
+                          self, obj, **args))
+        return result
diff --git a/test/harness/.gitignore b/test/harness/.gitignore
new file mode 100644
index 0000000..21d9e04
--- /dev/null
+++ b/test/harness/.gitignore
@@ -0,0 +1,5 @@
+orca-customizations.py
+orca-customizations.pyc
+user-settings.py
+user-settings.pyc
+utils.pyc
diff --git a/test/keystrokes/oowriter/bug_350219.py b/test/keystrokes/oowriter/bug_350219.py
index 02c2d93..8c4ae6d 100644
--- a/test/keystrokes/oowriter/bug_350219.py
+++ b/test/keystrokes/oowriter/bug_350219.py
@@ -36,8 +36,7 @@ sequence.append(utils.AssertPresentationAction(
      "BRAILLE LINE:  'soffice Application Untitled[ ]*2 - " + utils.getOOoName("Writer") + " Frame Untitled[ ]*2 - " + utils.getOOoName("Writer") + " RootPane ScrollPane Document view  \$l'",
      "     VISIBLE:  ' $l', cursor=1",
      "SPEECH OUTPUT: 'Untitled[ ]*2 - " + utils.getOOoName("Writer") + " frame'",
-     "SPEECH OUTPUT: 'blank'",
-     "SPEECH OUTPUT: ''"]))
+     "SPEECH OUTPUT: 'blank'"]))
 
 ######################################################################
 # 3. Enter Alt-f, Alt-c to close the Writer application.
diff --git a/test/keystrokes/oowriter/bug_361747.py b/test/keystrokes/oowriter/bug_361747.py
index 36d00c5..72750e7 100644
--- a/test/keystrokes/oowriter/bug_361747.py
+++ b/test/keystrokes/oowriter/bug_361747.py
@@ -59,7 +59,8 @@ sequence.append(utils.AssertPresentationAction(
     "Text information for bold word",
     ["SPEECH OUTPUT: 'size 12'",
      "SPEECH OUTPUT: 'family name FreeSerif'",
-     "SPEECH OUTPUT: 'bold'"]))
+     "SPEECH OUTPUT: 'bold'",
+     "SPEECH OUTPUT: 'paragraph style Default'"]))
 
 ######################################################################
 # 7. Type Control-right and Insert-f to get the text information
@@ -77,7 +78,8 @@ sequence.append(utils.AssertPresentationAction(
      "SPEECH OUTPUT: 'Italic '",
      "SPEECH OUTPUT: 'size 12'",
      "SPEECH OUTPUT: 'family name FreeSerif'",
-     "SPEECH OUTPUT: 'style italic'"]))
+     "SPEECH OUTPUT: 'style italic'",
+     "SPEECH OUTPUT: 'paragraph style Default'"]))
 
 ######################################################################
 # 8. Type Control-right and Insert-f to get the text information
@@ -94,7 +96,8 @@ sequence.append(utils.AssertPresentationAction(
      "     VISIBLE:  'Bold Italic Normal $l', cursor=13",
      "SPEECH OUTPUT: 'Normal'",
      "SPEECH OUTPUT: 'size 12'",
-     "SPEECH OUTPUT: 'family name FreeSerif'"]))
+     "SPEECH OUTPUT: 'family name FreeSerif'",
+     "SPEECH OUTPUT: 'paragraph style Default'"]))
 
 ######################################################################
 # 9. Enter Alt-f, Alt-c to close the Writer application.
diff --git a/test/keystrokes/oowriter/bug_364765.py b/test/keystrokes/oowriter/bug_364765.py
index fcdf664..e7214e3 100644
--- a/test/keystrokes/oowriter/bug_364765.py
+++ b/test/keystrokes/oowriter/bug_364765.py
@@ -32,8 +32,7 @@ sequence.append(utils.AssertPresentationAction(
     "Press W to open the Wizards submenu",
     ["BRAILLE LINE:  'soffice Application Untitled[ ]*1 - " + utils.getOOoName("Writer") + " Frame Untitled[ ]*1 - " + utils.getOOoName("Writer") + " RootPane MenuBar File Menu Letter...'",
      "     VISIBLE:  'Letter...', cursor=1",
-     "SPEECH OUTPUT: 'Wizards menu'",
-     "SPEECH OUTPUT: 'Letter...'"]))
+     "SPEECH OUTPUT: 'Wizards menu Letter...'"]))
 
 ######################################################################
 # 4. Press Escape to close the Wizards submenu.
@@ -45,7 +44,6 @@ sequence.append(utils.AssertPresentationAction(
     "Press Escape to close the Wizards submenu",
     ["BRAILLE LINE:  'soffice Application Untitled[ ]*1 - " + utils.getOOoName("Writer") + " Frame Untitled[ ]*1 - " + utils.getOOoName("Writer") + " RootPane MenuBar Wizards Menu'",
      "     VISIBLE:  'Wizards Menu', cursor=1",
-     "SPEECH OUTPUT: ''",
      "SPEECH OUTPUT: 'Wizards menu'"]))
 
 ######################################################################
diff --git a/test/keystrokes/oowriter/bug_382408.py b/test/keystrokes/oowriter/bug_382408.py
index 3426b3a..40aad1e 100644
--- a/test/keystrokes/oowriter/bug_382408.py
+++ b/test/keystrokes/oowriter/bug_382408.py
@@ -51,7 +51,7 @@ sequence.append(utils.AssertPresentationAction(
     "Type a down arrow to move to the Mon table column header",
     ["BRAILLE LINE:  '" + utils.getOOoBrailleLine("Writer", "table-sample(.odt|)", "Calendar-1 Table Sun Mon Tue Wed Thu Fri Sat") + "'",
      "     VISIBLE:  'Mon Tue Wed Thu Fri Sat', cursor=1",
-     "SPEECH OUTPUT: 'table with 7 rows and 7 columns",
+     "SPEECH OUTPUT: 'table with 7 rows and 7 columns.'",
      "SPEECH OUTPUT: 'Sun Mon Tue Wed Thu Fri Sat'"]))
 
 ######################################################################
diff --git a/test/keystrokes/oowriter/bug_384893.py b/test/keystrokes/oowriter/bug_384893.py
index 1280937..281e318 100644
--- a/test/keystrokes/oowriter/bug_384893.py
+++ b/test/keystrokes/oowriter/bug_384893.py
@@ -62,7 +62,8 @@ sequence.append(utils.AssertPresentationAction(
     "Enter Insert-f to get text information on the underlined word",
     ["SPEECH OUTPUT: 'size 12'",
      "SPEECH OUTPUT: 'family name FreeSerif'",
-     "SPEECH OUTPUT: 'underline single'"]))
+     "SPEECH OUTPUT: 'underline single'",
+     "SPEECH OUTPUT: 'paragraph style Default'"]))
 
 ######################################################################
 # 6. Type Control right arrow three times to position the cursor at
@@ -83,7 +84,8 @@ sequence.append(utils.AssertPresentationAction(
     "Enter Insert-f to get text information on the bold word",
     ["SPEECH OUTPUT: 'size 12'",
      "SPEECH OUTPUT: 'family name FreeSerif'",
-     "SPEECH OUTPUT: 'bold'"]))
+     "SPEECH OUTPUT: 'bold'",
+     "SPEECH OUTPUT: 'paragraph style Default'"]))
 
 ######################################################################
 # 8. Enter Alt-f, Alt-c to close the Writer application.
diff --git a/test/keystrokes/oowriter/bug_385828.py b/test/keystrokes/oowriter/bug_385828.py
index b9f5ece..f7c068d 100644
--- a/test/keystrokes/oowriter/bug_385828.py
+++ b/test/keystrokes/oowriter/bug_385828.py
@@ -36,15 +36,14 @@ sequence.append(WaitForWindowActivate("aw-5blue (read-only) - " + utils.getOOoNa
 sequence.append(WaitForFocus("Page design", acc_role=pyatspi.ROLE_LABEL))
 sequence.append(utils.AssertPresentationAction(
     "Press 'a' to bring up the Agenda... wizard",
-    ["BRAILLE LINE:  'soffice Application aw-5blue (read-only) - " + utils.getOOoName("Writer") + " Frame (1 dialog)'",
-     "     VISIBLE:  'aw-5blue \(read-only\) - " + utils.getOOoName("Writer")[0:9] + "', cursor=1",
-     "BRAILLE LINE:  'soffice Application Agenda Wizard Dialog'",
+    ["BRAILLE LINE:  " + utils.getOOoName("Writer") + " Frame (1 dialog)'",
+     "     VISIBLE:  'Frame (1 dialog)', cursor=1",
+     "BRAILLE LINE:  " + utils.getOOoName("Writer") + "'Agenda Wizard Dialog'",
      "     VISIBLE:  'Agenda Wizard Dialog', cursor=1",
-     "BRAILLE LINE:  'soffice Application Agenda Wizard Dialog Agenda Wizard OptionPane Steps Panel  $l'",
+     "BRAILLE LINE:  " + utils.getOOoName("Writer") + "'Agenda Wizard Dialog Agenda Wizard OptionPane Steps Panel  $l'",
      "     VISIBLE:  '  $l', cursor=1",
-     "SPEECH OUTPUT: 'aw-5blue (read-only) - " + utils.getOOoName("Writer") + " frame 1 unfocused dialog'",
+     "SPEECH OUTPUT: 'frame 1 unfocused dialog'",
      "SPEECH OUTPUT: 'Agenda Wizard Please choose the page design for the agenda 1. Page design 2. General information 3. Headings to include 4. Names 5. Agenda items 6. Name and location'",
-     "SPEECH OUTPUT: ''",
      "SPEECH OUTPUT: 'Page design label'"]))
 
 ######################################################################
diff --git a/test/keystrokes/oowriter/bug_413909.py b/test/keystrokes/oowriter/bug_413909.py
index 7424f74..1c9bc91 100644
--- a/test/keystrokes/oowriter/bug_413909.py
+++ b/test/keystrokes/oowriter/bug_413909.py
@@ -101,7 +101,6 @@ sequence.append(utils.AssertPresentationAction(
      "     VISIBLE:  'Change Button', cursor=1",
      "SPEECH OUTPUT: 'Spell(ing|check): [ \(]*English \(USA\)[\)]*'",
      "SPEECH OUTPUT: 'Misspelled word: quuuiick Context is The quuuiick brown fox'",
-     "SPEECH OUTPUT: ''",
      "SPEECH OUTPUT: 'Change button'"]))
 
 ######################################################################
diff --git a/test/keystrokes/oowriter/bug_435201.py b/test/keystrokes/oowriter/bug_435201.py
index 6bb784a..72dc740 100644
--- a/test/keystrokes/oowriter/bug_435201.py
+++ b/test/keystrokes/oowriter/bug_435201.py
@@ -49,8 +49,7 @@ sequence.append(utils.AssertPresentationAction(
      "     VISIBLE:  ' \$l', cursor=1",
      "BRAILLE LINE:  ' \$l'",
      "     VISIBLE:  ' \$l', cursor=1",
-     "SPEECH OUTPUT: 'blank'",
-     "SPEECH OUTPUT: ''"]))
+     "SPEECH OUTPUT: 'blank'"]))
 
 ######################################################################
 # 5. Type Control-down to move to the next paragraph.
@@ -78,8 +77,7 @@ sequence.append(utils.AssertPresentationAction(
      "     VISIBLE:  ' \$l', cursor=1",
      "BRAILLE LINE:  ' \$l'",
      "     VISIBLE:  ' \$l', cursor=1",
-     "SPEECH OUTPUT: 'blank'",
-     "SPEECH OUTPUT: ''"]))
+     "SPEECH OUTPUT: 'blank'"]))
 
 ######################################################################
 # 7. Type Control-down to move to the next paragraph.
diff --git a/test/keystrokes/oowriter/bug_435226.py b/test/keystrokes/oowriter/bug_435226.py
index 4375a29..67bf1e3 100644
--- a/test/keystrokes/oowriter/bug_435226.py
+++ b/test/keystrokes/oowriter/bug_435226.py
@@ -74,11 +74,8 @@ sequence.append(utils.AssertPresentationAction(
     "Type KP-Enter once to do a 'single-click' where-am-I operation",
     ["BRAILLE LINE:  '" + utils.getOOoBrailleLine("Writer", "spanish(.odt|)", "Hm! She is made of harder stuff! Cardinal Fang! Fetch the COMFY CHAIR! \$l") + "'",
      "     VISIBLE:  'Hm! She is made of harder stuff!', cursor=17",
-     "SPEECH OUTPUT: ''",
-     "SPEECH OUTPUT: 'paragraph'",
-     "SPEECH OUTPUT: 'Hm! She is made '",
-     "SPEECH OUTPUT: 'selected'",
-     "SPEECH OUTPUT: ''"]))
+     "SPEECH OUTPUT: 'paragraph Hm! She is made '",
+     "SPEECH OUTPUT: 'selected '"]))
 
 ######################################################################
 # 8. Type KP-Enter twice to do a "double-click" where-am-I operation.
@@ -93,16 +90,10 @@ sequence.append(utils.AssertPresentationAction(
      "     VISIBLE:  'Hm! She is made of harder stuff!', cursor=17",
      "BRAILLE LINE:  '" + utils.getOOoBrailleLine("Writer", "spanish(.odt|)", "Hm! She is made of harder stuff! Cardinal Fang! Fetch the COMFY CHAIR! \$l") + "'",
      "     VISIBLE:  'Hm! She is made of harder stuff!', cursor=17",
-     "SPEECH OUTPUT: ''",
-     "SPEECH OUTPUT: 'paragraph'",
-     "SPEECH OUTPUT: 'Hm! She is made '",
-     "SPEECH OUTPUT: 'selected'",
-     "SPEECH OUTPUT: ''",
-     "SPEECH OUTPUT: ''",
-     "SPEECH OUTPUT: 'paragraph'",
-     "SPEECH OUTPUT: 'Spanish Inquisition! Our chief weapon is surprise. Surprise and fear. Fear and surprise. Our two weapons are fear and surprise. And ruthless efficiency. Our three weapons are fear, surprise, and ruthless efficiency. And an almost fanatical devotion to the Pope. Our four. No. Amongst our weapons. Amongst our weaponry, are such elements as fear, surprise. I'll come in again. NOBODY expects the Spanish Inquisition! Amongst our weaponry are such diverse elements as: fear, surprise, ruthless efficiency, an almost fanatical devotion to the Pope, and nice red uniforms - Oh damn! Now old lady, you have one last chance. Confess the heinous sin of heresy, reject the works of the ungodly. Two last chances. And you shall be free. Three last chances. You have three last chances, the nature of which I have divulged in my previous utterance. Hm! She is made '",
-     "SPEECH OUTPUT: 'selected'",
-     "SPEECH OUTPUT: ''"]))
+     "SPEECH OUTPUT: 'paragraph Hm! She is made '",
+     "SPEECH OUTPUT: 'selected '",
+     "SPEECH OUTPUT: 'paragraph Spanish Inquisition! Our chief weapon is surprise. Surprise and fear. Fear and surprise. Our two weapons are fear and surprise. And ruthless efficiency. Our three weapons are fear, surprise, and ruthless efficiency. And an almost fanatical devotion to the Pope. Our four. No. Amongst our weapons. Amongst our weaponry, are such elements as fear, surprise. I'll come in again. NOBODY expects the Spanish Inquisition! Amongst our weaponry are such diverse elements as: fear, surprise, ruthless efficiency, an almost fanatical devotion to the Pope, and nice red uniforms - Oh damn! Now old lady, you have one last chance. Confess the heinous sin of heresy, reject the works of the ungodly. Two last chances. And you shall be free. Three last chances. You have three last chances, the nature of which I have divulged in my previous utterance. Hm! She is made  ;  paragraph style Preformatted Text'",
+     "SPEECH OUTPUT: 'selected '"]))
 
 ######################################################################
 # 9. Enter Alt-f, Alt-c to close the Writer application.
diff --git a/test/keystrokes/oowriter/bug_450210.py b/test/keystrokes/oowriter/bug_450210.py
index a8659a6..76aa86e 100644
--- a/test/keystrokes/oowriter/bug_450210.py
+++ b/test/keystrokes/oowriter/bug_450210.py
@@ -39,7 +39,6 @@ sequence.append(utils.AssertPresentationAction(
      "BRAILLE LINE:  'soffice Application Open Dialog Open OptionPane File name:  $l'",
      "     VISIBLE:  'File name:  $l', cursor=12",
      "SPEECH OUTPUT: 'Open'",
-     "SPEECH OUTPUT: ''",
      "SPEECH OUTPUT: 'File name: text '"]))
 
 ######################################################################
diff --git a/test/keystrokes/oowriter/bug_469367.py b/test/keystrokes/oowriter/bug_469367.py
index f692e87..173bd7b 100644
--- a/test/keystrokes/oowriter/bug_469367.py
+++ b/test/keystrokes/oowriter/bug_469367.py
@@ -57,7 +57,8 @@ sequence.append(KeyReleaseAction(0, None, "KP_Insert"))
 sequence.append(utils.AssertPresentationAction(
     "Enter Insert-f to get text information",
     ["SPEECH OUTPUT: 'size 12'",
-     "SPEECH OUTPUT: 'family name FreeSerif'"]))
+     "SPEECH OUTPUT: 'family name FreeSerif'",
+     "SPEECH OUTPUT: 'paragraph style Default'"]))
 
 ######################################################################
 # 6. Enter Alt-f, Alt-c to close the Writer application.
diff --git a/test/keystrokes/oowriter/table-sample.odt b/test/keystrokes/oowriter/table-sample.odt
index 6baabed..589daf4 100644
Binary files a/test/keystrokes/oowriter/table-sample.odt and b/test/keystrokes/oowriter/table-sample.odt differ



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