[orca] Announce when one or more rows or columns gets selected/unselected in Calc
- From: Joanmarie Diggs <joanied src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [orca] Announce when one or more rows or columns gets selected/unselected in Calc
- Date: Mon, 2 Jul 2018 22:13:00 +0000 (UTC)
commit 8530a3d244438b6cd8ae524f1b5f1025a3c2f4fa
Author: Joanmarie Diggs <jdiggs igalia com>
Date: Mon Jul 2 18:11:04 2018 -0400
Announce when one or more rows or columns gets selected/unselected in Calc
Note that this functionality assumes Calc tells us; it doesn't always.
src/orca/messages.py | 55 +++++++++++++++
src/orca/scripts/apps/soffice/script.py | 29 ++------
src/orca/scripts/apps/soffice/script_utilities.py | 86 ++++++++++++++++++++++-
3 files changed, 146 insertions(+), 24 deletions(-)
---
diff --git a/src/orca/messages.py b/src/orca/messages.py
index 9e7b9e5eb..b8c39437a 100644
--- a/src/orca/messages.py
+++ b/src/orca/messages.py
@@ -423,6 +423,13 @@ DIGITS_SUPERSCRIPT = _(" superscript %s")
# document by pressing Ctrl+A.
DOCUMENT_SELECTED_ALL = _("entire document selected")
+# Translators: when the user selects (highlights) or unselects text in a
+# document, Orca will speak information about what they have selected or
+# unselected. This message is presented when the entire document had been
+# selected but the user presses a key (e.g. an arrow key) causing the
+# selection to be completely removed.
+DOCUMENT_UNSELECTED_ALL = _("entire document unselected")
+
# Translators: when the user selects (highlights) or unselects text in a
# document, Orca will speak information about what they have selected or
# unselected. This message is presented when the user selects from the
@@ -2134,6 +2141,30 @@ TABLE_COLUMN_BOTTOM = _("Bottom of column.")
# the cell above the current cell and is already in the first row.
TABLE_COLUMN_TOP = _("Top of column.")
+# Translators: this message is spoken to announce that a table column just became
+# selected (e.g as a result of navigation via Shift + Arrows). The string substitution
+# is the column label (e.g. "B").
+TABLE_COLUMN_SELECTED = _("Column %s selected")
+
+# Translators: this message is spoken to announce that multiple table columns just
+# became selected (e.g as a result of navigation via Shift + Arrows). The first
+# string substitution is the label of the first column in the range. The second string
+# substitution is the label in the last column in the range. An example message for
+# Calc would be "Columns B through F selected".
+TABLE_COLUMN_RANGE_SELECTED = _("Columns %s through %s selected")
+
+# Translators: this message is spoken to announce that multiple table columns just
+# became unselected (e.g as a result of navigation via Shift + Arrows). The first
+# string substitution is the label of the first column in the range. The second string
+# substitution is the label in the last column in the range. An example message for
+# Calc would be "Columns B through F unselected".
+TABLE_COLUMN_RANGE_UNSELECTED = _("Columns %s through %s unselected")
+
+# Translators: this message is spoken to announce that a table column just became
+# unselected (e.g as a result of navigation via Shift + Arrows). The string substitution
+# is the column label (e.g. "B").
+TABLE_COLUMN_UNSELECTED = _("Column %s unselected")
+
# Translators: this is in reference to a row in a table. The substitution is
# the index (e.g. the first row is "row 1").
TABLE_ROW = _("row %d")
@@ -2169,6 +2200,30 @@ TABLE_ROW_INSERTED = _("Row inserted.")
# user presses Tab from within the last cell of the table.
TABLE_ROW_INSERTED_AT_END = _("Row inserted at the end of the table.")
+# Translators: this message is spoken to announce that a table row just became selected
+# (e.g as a result of navigation via Shift + Arrows). The string substitution is the row
+# label (e.g. "2").
+TABLE_ROW_SELECTED = _("Row %s selected")
+
+# Translators: this message is spoken to announce that multiple table rows just
+# became selected (e.g as a result of navigation via Shift + Arrows). The first
+# string substitution is the label of the first row in the range. The second string
+# substitution is the label of the last row in the range. An example message for
+# Calc would be "Rows 2 through 10 selected".
+TABLE_ROW_RANGE_SELECTED = _("Rows %s through %s selected")
+
+# Translators: this message is spoken to announce that multiple table rows just
+# became unselected (e.g as a result of navigation via Shift + Arrows). The first
+# string substitution is the label of the first row in the range. The second string
+# substitution is the label of the last row in the range. An example message for
+# Calc would be "Rows 2 through 10 unselected".
+TABLE_ROW_RANGE_UNSELECTED = _("Rows %s through %s unselected")
+
+# Translators: this message is spoken to announce that a table row just became
+# unselected (e.g as a result of navigation via Shift + Arrows). The string
+# substitution is the row label (e.g. "2").
+TABLE_ROW_UNSELECTED = _("Row %s unselected")
+
# Translators: when the user selects (highlights) text in a document, Orca lets
# them know.
TEXT_SELECTED = C_("text", "selected")
diff --git a/src/orca/scripts/apps/soffice/script.py b/src/orca/scripts/apps/soffice/script.py
index 56e3b00cb..9b2af1931 100644
--- a/src/orca/scripts/apps/soffice/script.py
+++ b/src/orca/scripts/apps/soffice/script.py
@@ -427,28 +427,6 @@ class Script(default.Script):
return True
- def columnConvert(self, column):
- """ Convert a spreadsheet column into it's column label
-
- Arguments:
- - column: the column number to convert.
-
- Returns a string representing the spread sheet column.
- """
-
- base26 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-
- if column <= len(base26):
- return base26[column-1]
-
- res = ""
- while column > 0:
- digit = column % len(base26)
- res = " " + base26[digit-1] + res
- column /= len(base26)
-
- return res
-
def setDynamicRowHeaders(self, inputEvent):
"""Set the column for the dynamic header rows to use when speaking
calc cell entries. In order to set the column, the user should first
@@ -470,7 +448,7 @@ class Script(default.Script):
if table:
self.dynamicRowHeaders[hash(table)] = column
self.presentMessage(
- messages.DYNAMIC_ROW_HEADER_SET % self.columnConvert(column+1))
+ messages.DYNAMIC_ROW_HEADER_SET % self.utilities.columnConvert(column+1))
return True
@@ -863,6 +841,11 @@ class Script(default.Script):
def onSelectionChanged(self, event):
"""Callback for object:selection-changed accessibility events."""
+ if self.utilities.isSpreadSheetTable(event.source):
+ if not _settingsManager.getSetting('onlySpeakDisplayedText'):
+ self.utilities.handleRowAndColumnSelectionChange(event.source)
+ return
+
if not self.utilities.isComboBoxSelectionChange(event):
super().onSelectionChanged(event)
return
diff --git a/src/orca/scripts/apps/soffice/script_utilities.py
b/src/orca/scripts/apps/soffice/script_utilities.py
index cf1355697..7babe0471 100644
--- a/src/orca/scripts/apps/soffice/script_utilities.py
+++ b/src/orca/scripts/apps/soffice/script_utilities.py
@@ -32,6 +32,7 @@ import pyatspi
import orca.debug as debug
import orca.keybindings as keybindings
+import orca.messages as messages
import orca.orca_state as orca_state
import orca.script_utilities as script_utilities
@@ -52,6 +53,9 @@ class Utilities(script_utilities.Utilities):
script_utilities.Utilities.__init__(self, script)
+ self._calcSelectedRows = []
+ self._calcSelectedColumns = []
+
#########################################################################
# #
# Utilities for finding, identifying, and comparing accessibles #
@@ -709,9 +713,15 @@ 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 role != pyatspi.ROLE_TABLE or self.isSpreadSheetTable(obj):
+ if role != pyatspi.ROLE_TABLE:
return super().selectedChildren(obj)
+ # We will need to special case this due to the possibility of there
+ # being lots of children (which may also prove to be zombie objects).
+ # This is why we can't have nice things.
+ if self.isSpreadSheetTable(obj):
+ return []
+
try:
selection = obj.querySelection()
except:
@@ -748,3 +758,77 @@ class Utilities(script_utilities.Utilities):
def presentEventFromNonShowingObject(self, event):
return self.inDocumentContent(event.source)
+
+ def columnConvert(self, column):
+ """ Convert a spreadsheet column into it's column label."""
+
+ base26 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+ if column <= len(base26):
+ return base26[column-1]
+
+ res = ""
+ while column > 0:
+ digit = column % len(base26)
+ res = " " + base26[digit-1] + res
+ column = int(column / len(base26))
+
+ return res
+
+ def handleRowAndColumnSelectionChange(self, obj):
+ interfaces = pyatspi.listInterfaces(obj)
+ if not ("Table" in interfaces and "Selection" in interfaces):
+ return True
+
+ table = obj.queryTable()
+ cols = set(table.getSelectedColumns())
+ rows = set(table.getSelectedRows())
+
+ selectedCols = sorted(cols.difference(set(self._calcSelectedColumns)))
+ unselectedCols = sorted(set(self._calcSelectedColumns).difference(cols))
+ convert = lambda x: self.columnConvert(x+1)
+ selectedCols = list(map(convert, selectedCols))
+ unselectedCols = list(map(convert, unselectedCols))
+
+ selectedRows = sorted(rows.difference(set(self._calcSelectedRows)))
+ unselectedRows = sorted(set(self._calcSelectedRows).difference(rows))
+ convert = lambda x: x + 1
+ selectedRows = list(map(convert, selectedRows))
+ unselectedRows = list(map(convert, unselectedRows))
+
+ self._calcSelectedColumns = list(cols)
+ self._calcSelectedRows = list(rows)
+
+ if len(cols) == table.nColumns:
+ self._script.speakMessage(messages.DOCUMENT_SELECTED_ALL)
+ return True
+
+ if not len(cols) and len(unselectedCols) == table.nColumns:
+ self._script.speakMessage(messages.DOCUMENT_UNSELECTED_ALL)
+ return True
+
+ msgs = []
+ if len(unselectedCols) == 1:
+ msgs.append(messages.TABLE_COLUMN_UNSELECTED % unselectedCols[0])
+ elif len(unselectedCols) > 1:
+ msgs.append(messages.TABLE_COLUMN_RANGE_UNSELECTED % (unselectedCols[0], unselectedCols[-1]))
+
+ if len(unselectedRows) == 1:
+ msgs.append(messages.TABLE_ROW_UNSELECTED % unselectedRows[0])
+ elif len(unselectedRows) > 1:
+ msgs.append(messages.TABLE_ROW_RANGE_UNSELECTED % (unselectedRows[0], unselectedRows[-1]))
+
+ if len(selectedCols) == 1:
+ msgs.append(messages.TABLE_COLUMN_SELECTED % selectedCols[0])
+ elif len(selectedCols) > 1:
+ msgs.append(messages.TABLE_COLUMN_RANGE_SELECTED % (selectedCols[0], selectedCols[-1]))
+
+ if len(selectedRows) == 1:
+ msgs.append(messages.TABLE_ROW_SELECTED % selectedRows[0])
+ elif len(selectedRows) > 1:
+ msgs.append(messages.TABLE_ROW_RANGE_SELECTED % (selectedRows[0], selectedRows[-1]))
+
+ for msg in msgs:
+ self._script.speakMessage(msg, interrupt=False)
+
+ return bool(len(msgs))
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]