[orca] Create separate cell-vs-row reading options for documents, spreadsheets, and GUI



commit bccbc040800ed6e609f0ac458c332e215b7e514f
Author: Joanmarie Diggs <jdiggs igalia com>
Date:   Fri Nov 27 18:48:46 2015 -0500

    Create separate cell-vs-row reading options for documents, spreadsheets, and GUI

 help/C/howto_tables.page                           |   21 ++-
 help/C/preferences_speech.page                     |   55 +++++---
 src/orca/generator.py                              |    3 +-
 src/orca/orca-setup.ui                             |  137 ++++++++------------
 src/orca/orca_gui_prefs.py                         |   32 ++----
 src/orca/script_utilities.py                       |  117 +++++++++++++++++
 src/orca/scripts/apps/soffice/braille_generator.py |    8 +-
 src/orca/scripts/apps/soffice/script.py            |    4 +-
 src/orca/scripts/apps/soffice/script_utilities.py  |   53 +-------
 src/orca/scripts/apps/soffice/speech_generator.py  |   10 +-
 src/orca/scripts/default.py                        |   17 ++-
 src/orca/settings.py                               |    8 +-
 src/orca/tutorialgenerator.py                      |    3 +-
 13 files changed, 270 insertions(+), 198 deletions(-)
---
diff --git a/help/C/howto_tables.page b/help/C/howto_tables.page
index 1a4a8f9..9e6cbdb 100644
--- a/help/C/howto_tables.page
+++ b/help/C/howto_tables.page
@@ -35,17 +35,22 @@
     </p>
     <p>
       <app>Orca</app> allows you to customize whether only the cell should be
-      read, or if the full row should be. You can set this preference Orca wide
-      as well as on an application-by-application basis. How to do each is
-      described in the guide on <link xref="preferences"><app>Orca</app>'s
-      preferences dialogs</link>. The setting can be found in the <gui>Table
-      Rows</gui> radio button group on the <link xref="preferences_speech">
+      read, or if the full row should be, for GUI tables, document tables,
+      and spreadsheets. Because these settings are independent of one another,
+      you do not have to choose one table reading mode to fit multiple types of
+      tables.
+    </p>
+    <p>
+      You can set each of <app>Orca</app>'s table reading preferences <app>Orca</app>
+      wide as well as on an application-by-application basis. How to do each is
+      described in the guide on <link xref="preferences"><app>Orca</app>'s preferences
+      dialogs</link>. The settings can be found on the <link xref="preferences_speech">
       <gui>Speech</gui> page</link>.
     </p>
     <p>
-      In addition, there is an <app>Orca</app> command which allows you to
-      toggle this setting on the fly: <keyseq><key>Orca Modifier</key>
-      <key>F11</key></keyseq>.
+      Lastly, there is also an <app>Orca</app> command which allows you to toggle
+      cell versus row reading on the fly for the currently-active table:
+      <keyseq><key>Orca Modifier</key><key>F11</key></keyseq>.
     </p>
   </section>
   <section id="structural_navigation">
diff --git a/help/C/preferences_speech.page b/help/C/preferences_speech.page
index aebd187..3f189aa 100644
--- a/help/C/preferences_speech.page
+++ b/help/C/preferences_speech.page
@@ -40,25 +40,6 @@
       Default value: <gui>Verbose</gui>
     </p>
   </section>
-  <section id="table_rows">
-    <title>Table Rows</title>
-    <p>
-      The <gui>Table Rows</gui> radio button group determines what gets
-      spoken when navigating amongst rows in a table. The available
-      options are <gui>speak row</gui> and <gui>speak cell</gui>.
-    </p>
-    <p>
-      Consider the process of examining the list of messages in your Inbox.
-      In order to have <app>Orca</app> announce the sender, subject, date,
-      and presence of attachments you would need <gui>speak row</gui>. On
-      the other hand, when navigating amongst rows in a spreadsheet, hearing
-      the full row may not be desired. In that case, <gui>speak cell</gui>
-      should instead be chosen.
-    </p>
-    <p>
-      Default value: <gui>Speak row</gui>
-    </p>
-  </section>
   <section id="punctuation_level">
     <title>Punctuation Level</title>
     <p>
@@ -215,5 +196,41 @@
         Default value: checked
       </p>
     </section>
+    <section id="read_full_row_in_gui_tables">
+      <title>Read full row in GUI tables</title>
+      <p>
+        If <gui>Read full row in GUI tables</gui> is checked, as you arrow up
+        and down in application tables such as the list of messages in your
+        Inbox, <app>Orca</app> will speak the entire row. If you would prefer
+        to hear only the cell with focus, you should uncheck this checkbox.
+      </p>
+      <p>
+        Default value: checked
+      </p>
+    </section>
+    <section id="read_full_row_in_document_tables">
+      <title>Read full row in document tables</title>
+      <p>
+        If <gui>Read full row in document tables</gui> is checked, as you arrow
+        up and down in tables such as those found in <app>Writer</app> and web
+        documents, <app>Orca</app> will speak the entire row. If you would prefer
+        to hear only the cell with focus, you should uncheck this checkbox.
+      </p>
+      <p>
+        Default value: checked
+      </p>
+    </section>
+    <section id="read_full_row_in_spreadsheets">
+      <title>Read full row in spreadsheets</title>
+      <p>
+        If <gui>Read full row in spreadsheets</gui> is checked, as you arrow
+        up and down in spreadsheets, <app>Orca</app> will speak the entire
+        row. If you would prefer to hear only the cell with focus, you should
+        uncheck this checkbox.
+      </p>
+      <p>
+        Default value: not checked
+      </p>
+    </section>
   </section>
 </page>
diff --git a/src/orca/generator.py b/src/orca/generator.py
index 08eb0a6..5adda16 100644
--- a/src/orca/generator.py
+++ b/src/orca/generator.py
@@ -776,7 +776,8 @@ class Generator:
         except:
             parentTable = None
         isDetailedWhereAmI = args.get('formatType', None) == 'detailedWhereAmI'
-        if (settings.readTableCellRow or isDetailedWhereAmI) and parentTable \
+        readFullRow = self._script.utilities.shouldReadFullRow(obj)
+        if (readFullRow or isDetailedWhereAmI) and parentTable \
            and (not self._script.utilities.isLayoutOnly(obj.parent)):
             parent = obj.parent
             index = self._script.utilities.cellIndex(obj)
diff --git a/src/orca/orca-setup.ui b/src/orca/orca-setup.ui
index 1706c18..35a6d81 100644
--- a/src/orca/orca-setup.ui
+++ b/src/orca/orca-setup.ui
@@ -1501,85 +1501,6 @@
                           <packing>
                             <property name="left_attach">0</property>
                             <property name="top_attach">0</property>
-                            <property name="width">1</property>
-                            <property name="height">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkFrame" id="tableRowsFrame">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="label_xalign">0</property>
-                            <property name="shadow_type">none</property>
-                            <child>
-                              <object class="GtkAlignment" id="tableRowsAlignment">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="left_padding">12</property>
-                                <child>
-                                  <object class="GtkGrid" id="tableRowsGrid">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">False</property>
-                                    <child>
-                                      <object class="GtkRadioButton" id="cellSpeechButton">
-                                        <property name="label" translatable="yes" comments="Translators: 
This is one of two options available in the Preferences dialog for the Table Rows setting. If chosen, Orca 
will speak just the new cell when the user arrows Up or Down in a table.">Speak _cell</property>
-                                        <property name="use_action_appearance">False</property>
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">True</property>
-                                        <property name="receives_default">False</property>
-                                        <property name="use_action_appearance">False</property>
-                                        <property name="use_underline">True</property>
-                                        <property name="active">True</property>
-                                        <property name="draw_indicator">True</property>
-                                        <signal name="toggled" handler="tableSpeechChanged" swapped="no"/>
-                                      </object>
-                                      <packing>
-                                        <property name="left_attach">0</property>
-                                        <property name="top_attach">0</property>
-                                        <property name="width">1</property>
-                                        <property name="height">1</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkRadioButton" id="rowSpeechButton">
-                                        <property name="label" translatable="yes" comments="Translators: 
This is one of two options available in the Preferences dialog for the Table Rows setting. If chosen, Orca 
will speak the entire row when the user arrows Up or Down in a table.">Speak ro_w</property>
-                                        <property name="use_action_appearance">False</property>
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">True</property>
-                                        <property name="receives_default">False</property>
-                                        <property name="use_action_appearance">False</property>
-                                        <property name="use_underline">True</property>
-                                        <property name="draw_indicator">True</property>
-                                        <property name="group">cellSpeechButton</property>
-                                        <signal name="toggled" handler="tableSpeechChanged" swapped="no"/>
-                                      </object>
-                                      <packing>
-                                        <property name="left_attach">0</property>
-                                        <property name="top_attach">1</property>
-                                        <property name="width">1</property>
-                                        <property name="height">1</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                </child>
-                              </object>
-                            </child>
-                            <child type="label">
-                              <object class="GtkLabel" id="tableRowsLabel">
-                                <property name="visible">True</property>
-                                <property name="can_focus">False</property>
-                                <property name="label" translatable="yes" comments="Translators: This is 
label in the Preferences dialog box. It refers to what Orca will speak when the user arrows Up or Down in a 
table. The choices are to speak just the new cell or to speak the entire row.">Table Rows</property>
-                                <attributes>
-                                  <attribute name="weight" value="bold"/>
-                                </attributes>
-                              </object>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="left_attach">0</property>
-                            <property name="top_attach">1</property>
-                            <property name="width">1</property>
-                            <property name="height">1</property>
                           </packing>
                         </child>
                         <child>
@@ -1694,7 +1615,7 @@
                           </object>
                           <packing>
                             <property name="left_attach">0</property>
-                            <property name="top_attach">2</property>
+                            <property name="top_attach">1</property>
                             <property name="width">1</property>
                             <property name="height">1</property>
                           </packing>
@@ -1891,8 +1812,60 @@
                                       <packing>
                                         <property name="left_attach">0</property>
                                         <property name="top_attach">1</property>
-                                        <property name="width">1</property>
-                                        <property name="height">1</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkCheckButton" id="readFullRowInGUITableCheckButton">
+                                        <property name="label" translatable="yes" comments="Translators: 
This checkbox is associated with the setting that determines what happens if a user presses Up or Down arrow 
to move row by row in a GUI table, such as a GtkTreeView. Document tables, such as those found in Writer and 
web content, and spreadsheet tables such as those found in Calc are not considered GUI tables. If this 
setting is enabled, Orca will speak the entire row; if it is disabled, Orca will only speak the cell with 
focus.">Speak full row in _GUI tables</property>
+                                        <property name="use_action_appearance">False</property>
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="receives_default">False</property>
+                                        <property name="use_underline">True</property>
+                                        <property name="xalign">0</property>
+                                        <property name="active">True</property>
+                                        <property name="draw_indicator">True</property>
+                                        <signal name="toggled" handler="checkButtonToggled" swapped="no"/>
+                                      </object>
+                                      <packing>
+                                        <property name="left_attach">0</property>
+                                        <property name="top_attach">2</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkCheckButton" 
id="readFullRowInDocumentTableCheckButton">
+                                        <property name="label" translatable="yes" comments="Translators: 
This checkbox is associated with the setting that determines what happens if a user presses Up or Down arrow 
to move row by row in a document table. In this context, document tables include tables such as those found 
in Writer documents as well as HTML table elements, but exclude spreadsheet tables such as found in Calc. If 
this setting is enabled, Orca will speak the entire row; if it is disabled, Orca will only speak the cell 
with focus.">Speak full row in _document tables</property>
+                                        <property name="use_action_appearance">False</property>
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="receives_default">False</property>
+                                        <property name="use_underline">True</property>
+                                        <property name="xalign">0</property>
+                                        <property name="active">True</property>
+                                        <property name="draw_indicator">True</property>
+                                        <signal name="toggled" handler="checkButtonToggled" swapped="no"/>
+                                      </object>
+                                      <packing>
+                                        <property name="left_attach">0</property>
+                                        <property name="top_attach">3</property>
+                                      </packing>
+                                    </child>
+                                    <child>
+                                      <object class="GtkCheckButton" 
id="readFullRowInSpreadSheetCheckButton">
+                                        <property name="label" translatable="yes" comments="Translators: 
This checkbox is associated with the setting that determines what happens if a user presses Up or Down arrow 
to move row by row in a spreadsheet. If this setting is enabled, Orca will speak the entire row; if it is 
disabled, Orca will only speak the cell with focus.">Speak full row in sp_readsheets</property>
+                                        <property name="use_action_appearance">False</property>
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="receives_default">False</property>
+                                        <property name="use_underline">True</property>
+                                        <property name="xalign">0</property>
+                                        <property name="active">True</property>
+                                        <property name="draw_indicator">True</property>
+                                        <signal name="toggled" handler="checkButtonToggled" swapped="no"/>
+                                      </object>
+                                      <packing>
+                                        <property name="left_attach">0</property>
+                                        <property name="top_attach">4</property>
                                       </packing>
                                     </child>
                                   </object>
diff --git a/src/orca/orca_gui_prefs.py b/src/orca/orca_gui_prefs.py
index 7c23e6a..ce47fce 100644
--- a/src/orca/orca_gui_prefs.py
+++ b/src/orca/orca_gui_prefs.py
@@ -1302,11 +1302,6 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         else:
             self.get_widget("speechVerboseButton").set_active(True)
 
-        if prefs["readTableCellRow"]:
-            self.get_widget("rowSpeechButton").set_active(True)
-        else:
-            self.get_widget("cellSpeechButton").set_active(True)
-
         self.get_widget("onlySpeakDisplayedTextCheckButton").set_active(
             prefs["onlySpeakDisplayedText"])
 
@@ -1334,6 +1329,15 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
         enable = prefs.get("useColorNames", settings.useColorNames)
         self.get_widget("useColorNamesCheckButton").set_active(enable)
 
+        enable = prefs.get("readFullRowInGUITable", settings.readFullRowInGUITable)
+        self.get_widget("readFullRowInGUITableCheckButton").set_active(enable)
+
+        enable = prefs.get("readFullRowInDocumentTable", settings.readFullRowInDocumentTable)
+        self.get_widget("readFullRowInDocumentTableCheckButton").set_active(enable)
+
+        enable = prefs.get("readFullRowInSpreadSheet", settings.readFullRowInSpreadSheet)
+        self.get_widget("readFullRowInSpreadSheetCheckButton").set_active(enable)
+
         style = prefs.get("capitalizationStyle", settings.capitalizationStyle)
         combobox = self.get_widget("capitalizationStyle")
         options = [guilabels.CAPITALIZATION_STYLE_NONE,
@@ -2513,24 +2517,6 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
                 self.prefsDict["speechVerbosityLevel"] = \
                     settings.VERBOSITY_LEVEL_VERBOSE
 
-    def tableSpeechChanged(self, widget):
-        """Signal handler for the "toggled" signal for the cellSpeechButton,
-           or rowSpeechButton GtkRadioButton widgets. The user has
-           toggled the table row speech type value. If this signal was
-           generated as the result of a radio button getting selected
-           (as opposed to a radio button losing the selection), set the
-           'readTableCellRow' preference to the new value.
-
-        Arguments:
-        - widget: the component that generated the signal.
-        """
-
-        if widget.get_active():
-            if widget.get_label() == guilabels.TABLE_SPEAK_CELL:
-                self.prefsDict["readTableCellRow"] = False
-            else:
-                self.prefsDict["readTableCellRow"] = True
-
     def progressBarUpdateIntervalValueChanged(self, widget):
         """Signal handler for the "value_changed" signal for the
            progressBarUpdateIntervalSpinButton GtkSpinButton widget.
diff --git a/src/orca/script_utilities.py b/src/orca/script_utilities.py
index 94dc8b3..0249771 100644
--- a/src/orca/script_utilities.py
+++ b/src/orca/script_utilities.py
@@ -913,6 +913,123 @@ class Utilities:
 
         return int((val / (maxval - minval)) * 100)
 
+    def isDocument(self, obj):
+        documentRoles = [pyatspi.ROLE_DOCUMENT_EMAIL,
+                         pyatspi.ROLE_DOCUMENT_FRAME,
+                         pyatspi.ROLE_DOCUMENT_PRESENTATION,
+                         pyatspi.ROLE_DOCUMENT_SPREADSHEET,
+                         pyatspi.ROLE_DOCUMENT_TEXT,
+                         pyatspi.ROLE_DOCUMENT_WEB]
+        return obj and obj.getRole() in documentRoles
+
+    def inDocumentContent(self, obj=None):
+        obj = obj or orca_state.locusOfFocus
+        return self.getContainingDocument(obj) is not None
+
+    def getContainingDocument(self, obj):
+        if not obj:
+            return None
+
+        try:
+            doc = pyatspi.findAncestor(obj, self.isDocument)
+        except:
+            msg = "ERROR: Exception finding ancestor of %s" % obj
+            debug.println(debug.LEVEL_INFO, msg, True)
+            return None
+
+        msg = "INFO: Document containing %s is %s" % (obj, doc)
+        debug.println(debug.LEVEL_INFO, msg, True)
+        return doc
+
+    def getTable(self, obj):
+        if not obj:
+            return None
+
+        tableRoles = [pyatspi.ROLE_TABLE, pyatspi.ROLE_TREE_TABLE]
+        isTable = lambda x: x and x.getRole() in tableRoles
+        if isTable(obj):
+            return obj
+
+        try:
+            table = pyatspi.findAncestor(obj, isTable)
+        except:
+            msg = "ERROR: Exception finding ancestor of %s" % obj
+            debug.println(debug.LEVEL_INFO, msg, True)
+            return None
+
+        return table
+
+    def isTextDocumentTable(self, obj):
+        if not (obj and obj.getRole() == pyatspi.ROLE_TABLE):
+            return False
+
+        doc = self.getContainingDocument(obj)
+        if not doc:
+            return False
+
+        return doc.getRole() != pyatspi.ROLE_DOCUMENT_SPREADSHEET
+
+    def isGUITable(self, obj):
+        if not (obj and obj.getRole() == pyatspi.ROLE_TABLE):
+            return False
+
+        return self.getContainingDocument(obj) is None
+
+    def isSpreadSheetTable(self, obj):
+        if not (obj and obj.getRole() == pyatspi.ROLE_TABLE):
+            return False
+
+        doc = self.getContainingDocument(obj)
+        if not doc:
+            return False
+
+        if doc.getRole() == pyatspi.ROLE_DOCUMENT_SPREADSHEET:
+            return True
+
+        try:
+            table = obj.queryTable()
+        except NotImplementedError:
+            msg = 'ERROR: Table %s does not implement table interface' % obj
+            debug.println(debug.LEVEL_INFO, msg, True)
+        except:
+            msg = 'ERROR: Exception querying table interface of %s' % obj
+            debug.println(debug.LEVEL_INFO, msg, True)
+        else:
+            return table.nRows > 65536
+
+        return False
+
+    def isTextDocumentCell(self, obj):
+        cellRoles = [pyatspi.ROLE_TABLE_CELL,
+                     pyatspi.ROLE_COLUMN_HEADER,
+                     pyatspi.ROLE_ROW_HEADER]
+        if not (obj and obj.getRole() in cellRoles):
+            return False
+
+        return pyatspi.findAncestor(obj, self.isTextDocumentTable)
+
+    def isSpreadSheetCell(self, obj):
+        cellRoles = [pyatspi.ROLE_TABLE_CELL,
+                     pyatspi.ROLE_COLUMN_HEADER,
+                     pyatspi.ROLE_ROW_HEADER]
+        if not (obj and obj.getRole() in cellRoles):
+            return False
+
+        return pyatspi.findAncestor(obj, self.isSpreadSheetTable)
+
+    def shouldReadFullRow(self, obj):
+        table = self.getTable(obj)
+        if not table:
+            return False
+
+        if not self.getContainingDocument(table):
+            return _settingsManager.getSetting('readFullRowInGUITable')
+
+        if self.isSpreadSheetTable(table):
+            return _settingsManager.getSetting('readFullRowInSpreadSheet')
+
+        return _settingsManager.getSetting('readFullRowInDocumentTable')
+
     def isStatic(self, obj):
         role = obj.getRole()
         try:
diff --git a/src/orca/scripts/apps/soffice/braille_generator.py 
b/src/orca/scripts/apps/soffice/braille_generator.py
index 34fddc2..7cadcac 100644
--- a/src/orca/scripts/apps/soffice/braille_generator.py
+++ b/src/orca/scripts/apps/soffice/braille_generator.py
@@ -130,10 +130,7 @@ class BrailleGenerator(braille_generator.BrailleGenerator):
         return result
 
     def _generateTableCellRow(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.
+        """Get the speech for a table row or cell depending on settings.
 
         Arguments:
         - obj: the table cell
@@ -148,7 +145,8 @@ class BrailleGenerator(braille_generator.BrailleGenerator):
             #
             parent = obj.parent
             parentTable = parent.queryTable()
-            if _settingsManager.getSetting('readTableCellRow') and parentTable:
+            readFullRow = self._script.utilities.shouldReadFullRow(obj)
+            if readFullRow and parentTable:
                 index = self._script.utilities.cellIndex(obj)
                 row = parentTable.getRowAtIndex(index)
                 column = parentTable.getColumnAtIndex(index)
diff --git a/src/orca/scripts/apps/soffice/script.py b/src/orca/scripts/apps/soffice/script.py
index 5225a3e..b1afa8a 100644
--- a/src/orca/scripts/apps/soffice/script.py
+++ b/src/orca/scripts/apps/soffice/script.py
@@ -596,7 +596,7 @@ class Script(default.Script):
         default.Script.locusOfFocusChanged(self, event,
                                            oldLocusOfFocus, newLocusOfFocus)
 
-        if self.utilities.isDocumentCell(newLocusOfFocus):
+        if self.utilities.isTextDocumentCell(newLocusOfFocus):
             row, column, table = \
                 self.utilities.getRowColumnAndTable(newLocusOfFocus.parent)
             self.pointOfReference['lastRow'] = row
@@ -673,7 +673,7 @@ class Script(default.Script):
             return
 
         if anyDataRole == pyatspi.ROLE_TABLE:
-            if self.utilities.isSpreadSheetCell(event.any_data, True):
+            if self.utilities.isSpreadSheetCell(event.any_data):
                 orca.setLocusOfFocus(event, event.any_data)
             return
 
diff --git a/src/orca/scripts/apps/soffice/script_utilities.py 
b/src/orca/scripts/apps/soffice/script_utilities.py
index 271c2be..02bf1a7 100644
--- a/src/orca/scripts/apps/soffice/script_utilities.py
+++ b/src/orca/scripts/apps/soffice/script_utilities.py
@@ -84,7 +84,7 @@ class Utilities(script_utilities.Utilities):
                 return text
 
         try:
-            text = script_utilities.Utilities.displayedText(self, obj)
+            text = super().displayedText(obj)
         except:
             return ""
 
@@ -92,22 +92,13 @@ class Utilities(script_utilities.Utilities):
         # back on the name, which is bogus. Once that has been fixed, this
         # hack can go.
         if role == pyatspi.ROLE_TABLE_CELL and text == obj.name \
-           and (self.isSpreadSheetCell(obj) or self.isDocumentCell(obj)):
+           and (self.isSpreadSheetCell(obj) or self.isTextDocumentCell(obj)):
             return ""
 
         return text
 
-    def isReadOnlyTextArea(self, obj):
-        """Returns True if obj is a text entry area that is read only."""
-
-        if not obj.getRole() == pyatspi.ROLE_TEXT:
-            return False
-
-        state = obj.getState()
-        readOnly = state.contains(pyatspi.STATE_FOCUSABLE) \
-                   and not state.contains(pyatspi.STATE_EDITABLE)
-
-        return readOnly
+    def isTextArea(self, obj):
+        return obj and obj.getRole() == pyatspi.ROLE_TEXT
 
     def isCellBeingEdited(self, obj):
         if not obj:
@@ -120,40 +111,6 @@ class Utilities(script_utilities.Utilities):
 
         return False
 
-    def isSpreadSheetCell(self, obj, startFromTable=False):
-        """Return an indication of whether the given obj is a spread sheet
-        table cell.
-
-        Arguments:
-        - obj: the object to check.
-        - startFromTable: if True, then the component hierarchy check should
-          start from a table (as opposed to a table cell).
-
-        Returns True if this is a table cell, False otherwise.
-        """
-
-        cell = obj
-        if not startFromTable:
-            obj = obj.parent
-
-        try:
-            table = obj.queryTable()
-        except:
-            return self.isCellBeingEdited(cell)
-        else:
-            return table.nRows in [65536, 1048576]
-
-    def isDocumentCell(self, cell):
-        isCell = lambda x: x and x.getRole() == pyatspi.ROLE_TABLE_CELL
-        if not isCell(cell):
-            cell = pyatspi.findAncestor(cell, isCell)
-
-        if not cell or self.isSpreadSheetCell(cell):
-            return False
-
-        isDocument = lambda x: x and x.getRole() == pyatspi.ROLE_DOCUMENT_FRAME
-        return pyatspi.findAncestor(cell, isDocument) != None
-
     def spreadSheetCellName(self, cell):
         nameList = cell.name.split()
         for name in nameList:
@@ -672,7 +629,7 @@ class Utilities(script_utilities.Utilities):
         # Things only seem broken for certain tables, e.g. the Paths table.
         # TODO - JD: File the LibreOffice bugs and reference them here.
         if obj.getRole() != pyatspi.ROLE_TABLE \
-           or self.isSpreadSheetCell(obj, True):
+           or self.isSpreadSheetCell(obj):
             return script_utilities.Utilities.selectedChildren(self, obj)
 
         try:
diff --git a/src/orca/scripts/apps/soffice/speech_generator.py 
b/src/orca/scripts/apps/soffice/speech_generator.py
index 5a50bd8..e176ef8 100644
--- a/src/orca/scripts/apps/soffice/speech_generator.py
+++ b/src/orca/scripts/apps/soffice/speech_generator.py
@@ -170,7 +170,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
         """
 
         result = []
-        if not self._script.utilities.isSpreadSheetCell(obj, startFromTable=True):
+        if not self._script.utilities.isSpreadSheetCell(obj):
             result.extend(speech_generator.SpeechGenerator.\
                 _generateAvailability(self, obj, **args))
 
@@ -209,7 +209,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
         return result
 
     def _generateCurrentLineText(self, obj, **args):
-        if self._script.utilities.isDocumentCell(obj.parent):
+        if self._script.utilities.isTextDocumentCell(obj.parent):
             priorObj = args.get('priorObj', None)
             if priorObj and priorObj.parent != obj.parent:
                 return []
@@ -251,7 +251,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
         row header(s).
         """
 
-        if _settingsManager.getSetting('readTableCellRow'):
+        if self._script.utilities.shouldReadFullRow(obj):
             return []
 
         newOnly = args.get('newOnly', False)
@@ -370,7 +370,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
         if speakCoordinates and not isBasicWhereAmI:
             result.append(self._script.utilities.spreadSheetCellName(obj))
 
-        if _settingsManager.getSetting('readTableCellRow'):
+        if self._script.utilities.shouldReadFullRow(obj):
             row, col, table = self._script.utilities.getRowColumnAndTable(obj)
             lastRow = self._script.pointOfReference.get("lastRow")
             if row != lastRow:
@@ -392,7 +392,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
         """Get the speech for a table cell row if the user wants to hear
         the full row and if the row has actually changed."""
 
-        speakFullRow = _settingsManager.getSetting('readTableCellRow')
+        speakFullRow = self._script.utilities.shouldReadFullRow(obj)
         if speakFullRow:
             row, column, table = \
                 self._script.utilities.getRowColumnAndTable(obj)
diff --git a/src/orca/scripts/default.py b/src/orca/scripts/default.py
index fd2c0ff..9a1f3fb 100644
--- a/src/orca/scripts/default.py
+++ b/src/orca/scripts/default.py
@@ -2003,8 +2003,21 @@ class Script(script.Script):
         """Toggles an indicator for whether we should just read the current
         table cell or read the whole row."""
 
-        speakRow = _settingsManager.getSetting('readTableCellRow')
-        _settingsManager.setSetting('readTableCellRow', not speakRow)
+        table = self.utilities.getTable(orca_state.locusOfFocus)
+        if not table:
+            self.presentMessage(messages.TABLE_NOT_IN_A)
+            return True
+
+        if not self.utilities.getContainingDocument(table):
+            settingName = 'readFullRowInGUITable'
+        elif self.utilities.isSpreadSheetTable(table):
+            settingName = 'readFullRowInSpreadsheet'
+        else:
+            settingName = 'readFullRowInDocumentTable'
+
+        speakRow = _settingsManager.getSetting(settingName)
+        _settingsManager.setSetting(settingName, not speakRow)
+
         if not speakRow:
             line = messages.TABLE_MODE_ROW
         else:
diff --git a/src/orca/settings.py b/src/orca/settings.py
index 34486aa..bd5dabc 100644
--- a/src/orca/settings.py
+++ b/src/orca/settings.py
@@ -40,7 +40,9 @@ userCustomizableSettings = [
     "speechServerInfo",
     "voices",
     "speechVerbosityLevel",
-    "readTableCellRow",
+    "readFullRowInGUITable",
+    "readFullRowInDocumentTable",
+    "readFullRowInSpreadSheet",
     "enableSpeechIndentation",
     "enableEchoByCharacter",
     "enableEchoByWord",
@@ -203,7 +205,9 @@ onlySpeakDisplayedText       = False
 presentToolTips              = False
 speakBlankLines              = True
 repeatCharacterLimit         = 4
-readTableCellRow             = True
+readFullRowInGUITable        = True
+readFullRowInDocumentTable   = True
+readFullRowInSpreadSheet     = False
 speakCellCoordinates         = True
 speakCellSpan                = True
 speakCellHeaders             = True
diff --git a/src/orca/tutorialgenerator.py b/src/orca/tutorialgenerator.py
index 6150248..994d554 100644
--- a/src/orca/tutorialgenerator.py
+++ b/src/orca/tutorialgenerator.py
@@ -615,7 +615,8 @@ class TutorialGenerator:
                 parent_table = obj.parent.queryTable()
             except:
                 parent_table = None
-            if settings.readTableCellRow and parent_table \
+            readFullRow = self._script.utilities.shouldReadFullRow(obj)
+            if readFullRow and parent_table \
                 and not self._script.utilities.isLayoutOnly(obj.parent):
                 parent = obj.parent
                 index = self._script.utilities.cellIndex(obj)


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