[orca] Add option to present page summary upon load, and include landmarks in summary
- From: Joanmarie Diggs <joanied src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [orca] Add option to present page summary upon load, and include landmarks in summary
- Date: Mon, 15 Feb 2016 01:53:08 +0000 (UTC)
commit 4e9734203eb76383d10eda48f0e06c4203b39af7
Author: Joanmarie Diggs <jdiggs igalia com>
Date: Sun Feb 14 20:34:52 2016 -0500
Add option to present page summary upon load, and include landmarks in summary
help/C/preferences_gecko.page | 11 +++++
src/orca/guilabels.py | 5 ++
src/orca/messages.py | 34 ++++++++++++--
src/orca/scripts/apps/Thunderbird/script.py | 13 +++++
src/orca/scripts/web/script.py | 19 +++++++-
src/orca/scripts/web/script_utilities.py | 66 +++++++++++++++++---------
src/orca/scripts/web/speech_generator.py | 25 +++--------
7 files changed, 125 insertions(+), 48 deletions(-)
---
diff --git a/help/C/preferences_gecko.page b/help/C/preferences_gecko.page
index a3ec260..2286357 100644
--- a/help/C/preferences_gecko.page
+++ b/help/C/preferences_gecko.page
@@ -120,6 +120,17 @@
</p>
</section>
<section>
+ <title>Present summary of a page when it is first loaded</title>
+ <p>
+ If this checkbox is checked, <app>Orca</app> will summarize details about the
+ newly opened web page or email, such as the number of headings, landmarks,
+ and links.
+ </p>
+ <p>
+ Default value: checked for Firefox; not checked for Thunderbird
+ </p>
+ </section>
+ <section>
<title>Enable layout mode for content</title>
<p>
If this checkbox is checked, <app>Orca</app>'s caret navigation will respect
diff --git a/src/orca/guilabels.py b/src/orca/guilabels.py
index 6818ea5..42af135 100644
--- a/src/orca/guilabels.py
+++ b/src/orca/guilabels.py
@@ -674,6 +674,11 @@ PAGE_NAVIGATION = _("Page Navigation")
READ_PAGE_UPON_LOAD = \
_("Automatically start speaking a page when it is first _loaded")
+# Translators: When the user loads a new web page, they can optionally have Orca
+# automatically summarize details about the page, such as the number of elements
+# (landmarks, forms, links, tables, etc.).
+PAGE_SUMMARY_UPON_LOAD = _("_Present summary of a page when it is first loaded")
+
# Translators: Different speech systems and speech engines work differently when
# it comes to handling pauses (e.g. sentence boundaries). This property allows
# the user to specify whether speech should be sent to the speech synthesis
diff --git a/src/orca/messages.py b/src/orca/messages.py
index 5e5f409..c7e5f6f 100644
--- a/src/orca/messages.py
+++ b/src/orca/messages.py
@@ -2013,11 +2013,17 @@ def filesFound(count):
# a result of a search.
return ngettext("%d file found", "%d files found", count) % count
-def formCount(count):
+def formCount(count, onlyIfFound=True):
+ if not count and onlyIfFound:
+ return ""
+
# Translators: This message presents the number of forms in a document.
return ngettext("%d form", "%d forms", count) % count
-def headingCount(count):
+def headingCount(count, onlyIfFound=True):
+ if not count and onlyIfFound:
+ return ""
+
# Translators: This message presents the number of headings in a document.
return ngettext("%d heading", "%d headings", count) % count
@@ -2026,6 +2032,15 @@ def itemCount(count):
# or table.
return ngettext("%d item", "%d items", count) % count
+def landmarkCount(count, onlyIfFound=True):
+ if not count and onlyIfFound:
+ return ""
+
+ # Translators: This message presents the number of landmarks in a document.
+ # ARIA role landmarks are the W3C defined HTML tag attribute 'role' used to
+ # identify important part of webpage like banners, main context, search etc.
+ return ngettext("%d landmark", "%d landmarks", count) % count
+
def itemsFound(count):
# Translators: Orca has several commands that search for, and present a list
# of, objects based on one or more criteria. This is a message that will be
@@ -2131,7 +2146,10 @@ def tabsCount(count):
# tab characters in a string.
return ngettext("%d tab", "%d tabs", count) % count
-def tableCount(count):
+def tableCount(count, onlyIfFound=True):
+ if not count and onlyIfFound:
+ return ""
+
# Translators: This message presents the number of tables in a document.
return ngettext("%d table", "%d tables", count) % count
@@ -2147,12 +2165,18 @@ def tableSize(nRows, nColumns):
return rowString + " " + colString
-def unvisitedLinkCount(count):
+def unvisitedLinkCount(count, onlyIfFound=True):
+ if not count and onlyIfFound:
+ return ""
+
# Translators: This message presents the number of unvisited links in a
# document.
return ngettext("%d unvisited link", "%d unvisited links", count) % count
-def visitedLinkCount(count):
+def visitedLinkCount(count, onlyIfFound=True):
+ if not count and onlyIfFound:
+ return ""
+
# Translators: This message presents the number of visited links in a
# document.
return ngettext("%d visited link", "%d visited links", count) % count
diff --git a/src/orca/scripts/apps/Thunderbird/script.py b/src/orca/scripts/apps/Thunderbird/script.py
index abe23fd..ef85697 100644
--- a/src/orca/scripts/apps/Thunderbird/script.py
+++ b/src/orca/scripts/apps/Thunderbird/script.py
@@ -65,6 +65,8 @@ class Script(Gecko.Script):
if _settingsManager.getSetting('sayAllOnLoad') == None:
_settingsManager.setSetting('sayAllOnLoad', False)
+ if _settingsManager.getSetting('pageSummaryOnLoad') == None:
+ _settingsManager.setSetting('pageSummaryOnLoad', False)
Gecko.Script.__init__(self, app)
@@ -94,6 +96,8 @@ class Script(Gecko.Script):
self._sayAllOnLoadCheckButton.set_active(
_settingsManager.getSetting('sayAllOnLoad'))
+ self._pageSummaryOnLoadCheckButton.set_active(
+ _settingsManager.getSetting('pageSummaryOnLoad'))
spellcheck = self.spellcheck.getAppPreferencesGUI()
grid.attach(spellcheck, 0, len(grid.get_children()), 1, 1)
@@ -106,6 +110,7 @@ class Script(Gecko.Script):
prefs = Gecko.Script.getPreferencesFromGUI(self)
prefs['sayAllOnLoad'] = self._sayAllOnLoadCheckButton.get_active()
+ prefs['pageSummaryOnLoad'] = self._pageSummaryOnLoadCheckButton.get_active()
prefs.update(self.spellcheck.getPreferencesFromGUI())
return prefs
@@ -356,6 +361,14 @@ class Script(Gecko.Script):
[obj, offset] = self.utilities.findFirstCaretContext(documentFrame, 0)
self.utilities.setCaretPosition(obj, offset)
self.updateBraille(obj)
+
+ if _settingsManager.getSetting('pageSummaryOnLoad'):
+ msg = "THUNDERBIRD: Getting page summary for obj %s" % obj
+ debug.println(debug.LEVEL_INFO, msg, True)
+ summary = self.utilities.getPageSummary(obj)
+ if summary:
+ self.presentMessage(summary)
+
if not _settingsManager.getSetting('sayAllOnLoad'):
msg = "THUNDERBIRD: SayAllOnLoad is False. Presenting line."
debug.println(debug.LEVEL_INFO, msg, True)
diff --git a/src/orca/scripts/web/script.py b/src/orca/scripts/web/script.py
index d8a4fe9..f787731 100644
--- a/src/orca/scripts/web/script.py
+++ b/src/orca/scripts/web/script.py
@@ -83,12 +83,15 @@ class Script(default.Script):
_settingsManager.setSetting('caretNavigationEnabled', True)
if _settingsManager.getSetting('sayAllOnLoad') == None:
_settingsManager.setSetting('sayAllOnLoad', True)
+ if _settingsManager.getSetting('pageSummaryOnLoad') == None:
+ _settingsManager.setSetting('pageSummaryOnLoad', True)
self._changedLinesOnlyCheckButton = None
self._controlCaretNavigationCheckButton = None
self._minimumFindLengthAdjustment = None
self._minimumFindLengthLabel = None
self._minimumFindLengthSpinButton = None
+ self._pageSummaryOnLoadCheckButton = None
self._sayAllOnLoadCheckButton = None
self._skipBlankCellsCheckButton = None
self._speakCellCoordinatesCheckButton = None
@@ -325,11 +328,17 @@ class Script(default.Script):
self._sayAllOnLoadCheckButton.set_active(value)
generalGrid.attach(self._sayAllOnLoadCheckButton, 0, 4, 1, 1)
+ label = guilabels.PAGE_SUMMARY_UPON_LOAD
+ value = _settingsManager.getSetting('pageSummaryOnLoad')
+ self._pageSummaryOnLoadCheckButton = Gtk.CheckButton.new_with_mnemonic(label)
+ self._pageSummaryOnLoadCheckButton.set_active(value)
+ generalGrid.attach(self._pageSummaryOnLoadCheckButton, 0, 5, 1, 1)
+
label = guilabels.CONTENT_LAYOUT_MODE
value = _settingsManager.getSetting('layoutMode')
self._layoutModeCheckButton = Gtk.CheckButton.new_with_mnemonic(label)
self._layoutModeCheckButton.set_active(value)
- generalGrid.attach(self._layoutModeCheckButton, 0, 5, 1, 1)
+ generalGrid.attach(self._layoutModeCheckButton, 0, 6, 1, 1)
tableFrame = Gtk.Frame()
grid.attach(tableFrame, 0, 1, 1, 1)
@@ -436,6 +445,7 @@ class Script(default.Script):
'findResultsVerbosity': verbosity,
'findResultsMinimumLength': self._minimumFindLengthSpinButton.get_value(),
'sayAllOnLoad': self._sayAllOnLoadCheckButton.get_active(),
+ 'pageSummaryOnLoad': self._pageSummaryOnLoadCheckButton.get_active(),
'structuralNavigationEnabled': self._structuralNavigationCheckButton.get_active(),
'structNavTriggersFocusMode': self._autoFocusModeStructNavCheckButton.get_active(),
'caretNavigationEnabled': self._controlCaretNavigationCheckButton.get_active(),
@@ -1093,6 +1103,13 @@ class Script(default.Script):
self.utilities.clearCachedObjects()
+ if _settingsManager.getSetting('pageSummaryOnLoad'):
+ msg = "WEB: Getting page summary for obj %s" % obj
+ debug.println(debug.LEVEL_INFO, msg, True)
+ summary = self.utilities.getPageSummary(obj)
+ if summary:
+ self.presentMessage(summary)
+
obj, offset = self.utilities.getCaretContext()
try:
diff --git a/src/orca/scripts/web/script_utilities.py b/src/orca/scripts/web/script_utilities.py
index ebd0517..406283c 100644
--- a/src/orca/scripts/web/script_utilities.py
+++ b/src/orca/scripts/web/script_utilities.py
@@ -168,13 +168,13 @@ class Utilities(script_utilities.Utilities):
return None
if self.isDocument(obj):
- msg = "WEB: %s is document" % obj
- debug.println(debug.LEVEL_INFO, msg, True)
return obj
document = pyatspi.findAncestor(obj, self.isDocument)
- msg = "WEB: Document for %s is %s" % (obj, document)
- debug.println(debug.LEVEL_INFO, msg, True)
+ if not document:
+ msg = "WEB: Could not find document for %s" % obj
+ debug.println(debug.LEVEL_INFO, msg, True)
+
return document
def _getDocumentsEmbeddedBy(self, frame):
@@ -2852,19 +2852,23 @@ class Utilities(script_utilities.Utilities):
return self.isLiveRegion(event.source)
- def getPageSummary(self, obj):
+ def getPageObjectCount(self, obj):
+ result = {'landmarks': 0,
+ 'headings': 0,
+ 'forms': 0,
+ 'tables': 0,
+ 'visitedLinks': 0,
+ 'unvisitedLinks': 0}
+
docframe = self.documentFrame(obj)
col = docframe.queryCollection()
- headings = 0
- forms = 0
- tables = 0
- vlinks = 0
- uvlinks = 0
- percentRead = None
-
stateset = pyatspi.StateSet()
- roles = [pyatspi.ROLE_HEADING, pyatspi.ROLE_LINK, pyatspi.ROLE_TABLE,
- pyatspi.ROLE_FORM]
+ roles = [pyatspi.ROLE_HEADING,
+ pyatspi.ROLE_LINK,
+ pyatspi.ROLE_TABLE,
+ pyatspi.ROLE_FORM,
+ pyatspi.ROLE_SECTION, # We can nuke this when Firefox correcly maps landmarks
+ pyatspi.ROLE_LANDMARK]
rule = col.createMatchRule(stateset.raw(), col.MATCH_NONE,
"", col.MATCH_NONE,
roles, col.MATCH_ANY,
@@ -2876,18 +2880,34 @@ class Utilities(script_utilities.Utilities):
for obj in matches:
role = obj.getRole()
if role == pyatspi.ROLE_HEADING:
- headings += 1
+ result['headings'] += 1
elif role == pyatspi.ROLE_FORM:
- forms += 1
+ result['forms'] += 1
elif role == pyatspi.ROLE_TABLE and not self.isLayoutOnly(obj):
- tables += 1
+ result['tables'] += 1
elif role == pyatspi.ROLE_LINK:
- if obj.getState().contains(pyatspi.STATE_VISITED):
- vlinks += 1
- else:
- uvlinks += 1
-
- return [headings, forms, tables, vlinks, uvlinks, percentRead]
+ if self.isLink(obj):
+ if obj.getState().contains(pyatspi.STATE_VISITED):
+ result['visitedLinks'] += 1
+ else:
+ result['unvisitedLinks'] += 1
+ elif self.isLandmark(obj):
+ result['landmarks'] += 1
+
+ return result
+
+ def getPageSummary(self, obj, onlyIfFound=True):
+ result = []
+ counts = self.getPageObjectCount(obj)
+ result.append(messages.landmarkCount(counts.get('landmarks', 0), onlyIfFound))
+ result.append(messages.headingCount(counts.get('headings', 0), onlyIfFound))
+ result.append(messages.formCount(counts.get('forms', 0), onlyIfFound))
+ result.append(messages.tableCount(counts.get('tables', 0), onlyIfFound))
+ result.append(messages.visitedLinkCount(counts.get('visitedLinks', 0), onlyIfFound))
+ result.append(messages.unvisitedLinkCount(counts.get('unvisitedLinks', 0), onlyIfFound))
+ result = filter(lambda x: x, result)
+
+ return ", ".join(result)
def _getCtrlShiftSelectionsStrings(self):
"""Hacky and to-be-obsoleted method."""
diff --git a/src/orca/scripts/web/speech_generator.py b/src/orca/scripts/web/speech_generator.py
index 832193f..8f4b7bd 100644
--- a/src/orca/scripts/web/speech_generator.py
+++ b/src/orca/scripts/web/speech_generator.py
@@ -317,25 +317,12 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
if not self._script.utilities.inDocumentContent(obj):
return []
- result = []
- acss = self.voice(speech_generator.DEFAULT)
- headings, forms, tables, vlinks, uvlinks, percent = \
- self._script.utilities.getPageSummary(obj)
- if headings:
- result.append(messages.headingCount(headings))
- if forms:
- result.append(messages.formCount(forms))
- if tables:
- result.append(messages.tableCount(tables))
- if vlinks:
- result.append(messages.visitedLinkCount(vlinks))
- if uvlinks:
- result.append(messages.unvisitedLinkCount(uvlinks))
- if percent is not None:
- result.append(messages.percentRead(percent))
+ string = self._script.utilities.getPageSummary(obj)
+ if not string:
+ return []
- if result:
- result.extend(acss)
+ result = [string]
+ result.extend(self.voice(speech_generator.SYSTEM))
return result
def _generateSiteDescription(self, obj, **args):
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]