[orca] More work on custom localized role names:
- From: Joanmarie Diggs <joanied src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [orca] More work on custom localized role names:
- Date: Fri, 12 Aug 2016 20:42:49 +0000 (UTC)
commit 2fc1db1eab9e43fa97bb0dc0fd17de38ec261a04
Author: Joanmarie Diggs <jdiggs igalia com>
Date: Fri Aug 12 14:29:25 2016 -0400
More work on custom localized role names:
* Move main support from speech and braille generators to superclass
* Add support for optional keyword arguments
* Create new localized role names for horizontal and vertical
scroll bars, sliders, and splitters
src/orca/braille_generator.py | 42 ++-----------
src/orca/flat_review.py | 30 ++-------
src/orca/generator.py | 65 ++++++++++++++++++--
src/orca/object_properties.py | 56 +++++++++++++++++
.../scripts/toolkits/WebKitGtk/speech_generator.py | 6 +-
src/orca/scripts/web/braille_generator.py | 6 +-
src/orca/scripts/web/speech_generator.py | 18 +++---
src/orca/speech_generator.py | 57 ++++++-----------
src/orca/structural_navigation.py | 2 +-
9 files changed, 162 insertions(+), 120 deletions(-)
---
diff --git a/src/orca/braille_generator.py b/src/orca/braille_generator.py
index 3a4fc8c..f664367 100644
--- a/src/orca/braille_generator.py
+++ b/src/orca/braille_generator.py
@@ -26,7 +26,6 @@ __copyright__ = "Copyright (c) 2005-2009 Sun Microsystems Inc."
__license__ = "LGPL"
import pyatspi
-from gi.repository import Atspi, Atk
from . import braille
from . import debug
@@ -158,56 +157,25 @@ class BrailleGenerator(generator.Generator):
elif verbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE \
and not args.get('readingRow', False) and role not in doNotPresent:
- result.append(self.getLocalizedRoleName(obj, role))
+ result.append(self.getLocalizedRoleName(obj, **args))
return result
- def getLocalizedRoleName(self, obj, role=None):
+ def getLocalizedRoleName(self, obj, **args):
"""Returns the localized name of the given Accessible object; the name
is suitable to be brailled.
Arguments:
- obj: an Accessible object
- - role: an optional pyatspi role to use instead
"""
if _settingsManager.getSetting('brailleRolenameStyle') \
== settings.BRAILLE_ROLENAME_STYLE_SHORT:
- objRole = role or obj.getRole()
- rv = shortRoleNames.get(objRole)
+ role = args.get('role', obj.getRole())
+ rv = shortRoleNames.get(role)
if rv:
return rv
- if not isinstance(role, (pyatspi.Role, Atspi.Role)):
- try:
- return obj.getLocalizedRoleName()
- except:
- return ''
-
- if self._script.utilities.isLandmark(obj):
- if self._script.utilities.isLandmarkBanner(obj):
- return object_properties.ROLE_LANDMARK_BANNER
- if self._script.utilities.isLandmarkComplementary(obj):
- return object_properties.ROLE_LANDMARK_COMPLEMENTARY
- if self._script.utilities.isLandmarkContentInfo(obj):
- return object_properties.ROLE_LANDMARK_CONTENTINFO
- if self._script.utilities.isLandmarkMain(obj):
- return object_properties.ROLE_LANDMARK_MAIN
- if self._script.utilities.isLandmarkNavigation(obj):
- return object_properties.ROLE_LANDMARK_NAVIGATION
- if self._script.utilities.isLandmarkRegion(obj):
- return object_properties.ROLE_LANDMARK_REGION
- if self._script.utilities.isLandmarkSearch(obj):
- return object_properties.ROLE_LANDMARK_SEARCH
- if self._script.utilities.isLandmarkForm(obj):
- role = pyatspi.ROLE_FORM
-
- if not role:
- return ''
-
- nonlocalized = Atspi.role_get_name(role)
- atkRole = Atk.role_for_name(nonlocalized)
-
- return Atk.role_get_localized_name(atkRole)
+ return super().getLocalizedRoleName(obj, **args)
def _generateUnrelatedLabels(self, obj, **args):
result = []
diff --git a/src/orca/flat_review.py b/src/orca/flat_review.py
index f417b78..b8d4052 100644
--- a/src/orca/flat_review.py
+++ b/src/orca/flat_review.py
@@ -400,15 +400,6 @@ class ValueZone(Zone):
def __getattr__(self, attr):
if attr in ["string", "length", "brailleString"]:
- orientation = None
- if self.role in [pyatspi.ROLE_SLIDER,
- pyatspi.ROLE_SCROLL_BAR]:
- stateset = self.accessible.getState()
- if stateset.contains(pyatspi.STATE_HORIZONTAL):
- orientation = object_properties.STATE_HORIZONTAL
- elif stateset.contains(pyatspi.STATE_VERTICAL):
- orientation = object_properties.STATE_VERTICAL
-
try:
value = self.accessible.queryValue()
except NotImplementedError:
@@ -421,22 +412,15 @@ class ValueZone(Zone):
except:
percentValue = 0
- rolename = self.accessible.getLocalizedRoleName()
- if orientation:
- speechValue = orientation + " " + rolename
- else:
- speechValue = rolename
-
+ script = orca_state.activeScript
+ speechValue = script.speechGenerator.getLocalizedRoleName(
+ self.accessible, alreadyFocused=True)
speechValue = speechValue + " " + messages.percentage(percentValue)
- rolename = orca_state.activeScript.brailleGenerator.getLocalizedRoleName(
- self.accessible)
- if orientation:
- brailleValue = "%s %s %d%%" % (orientation,
- rolename,
- percentValue)
- else:
- brailleValue = "%s %d%%" % (rolename, percentValue)
+ brailleValue = script.brailleGenerator.getLocalizedRoleName(
+ self.accessible, alreadyFocused=True)
+ brailleValue = "%s %d%%" % (brailleValue, percentValue)
+
if attr == "string":
return speechValue
elif attr == "length":
diff --git a/src/orca/generator.py b/src/orca/generator.py
index 0f74b47..6cd0081 100644
--- a/src/orca/generator.py
+++ b/src/orca/generator.py
@@ -27,11 +27,12 @@ __copyright__ = "Copyright (c) 2009 Sun Microsystems Inc." \
"Copyright (c) 2015-2016 Igalia, S.L."
__license__ = "LGPL"
+import collections
+import pyatspi
import sys
import time
import traceback
-
-import pyatspi
+from gi.repository import Atspi, Atk
from . import braille
from . import debug
@@ -40,8 +41,6 @@ from . import object_properties
from . import settings
from . import settings_manager
-import collections
-
def _formatExceptionInfo(maxTBlevel=5):
cla, exc, trbk = sys.exc_info()
excName = cla.__name__
@@ -655,7 +654,7 @@ class Generator:
if not text:
return result
- roleString = self.getLocalizedRoleName(obj, pyatspi.ROLE_ROW_HEADER)
+ roleString = self.getLocalizedRoleName(obj, role=pyatspi.ROLE_ROW_HEADER)
if args.get('mode') == 'speech':
if settings.speechVerbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE \
and not args.get('formatType') in ['basicWhereAmI', 'detailedWhereAmI']:
@@ -681,7 +680,7 @@ class Generator:
if not text:
return result
- roleString = self.getLocalizedRoleName(obj, pyatspi.ROLE_COLUMN_HEADER)
+ roleString = self.getLocalizedRoleName(obj, role=pyatspi.ROLE_COLUMN_HEADER)
if args.get('mode') == 'speech':
if settings.speechVerbosityLevel == settings.VERBOSITY_LEVEL_VERBOSE \
and not args.get('formatType') in ['basicWhereAmI', 'detailedWhereAmI']:
@@ -1154,3 +1153,57 @@ class Generator:
return pyatspi.ROLE_LIST_ITEM
return args.get('role', obj.getRole())
+
+ def getLocalizedRoleName(self, obj, **args):
+ role = args.get('role', obj.getRole())
+
+ if "Value" in pyatspi.listInterfaces(obj):
+ state = obj.getState()
+ isVertical = state.contains(pyatspi.STATE_VERTICAL)
+ isHorizontal = state.contains(pyatspi.STATE_HORIZONTAL)
+ isFocused = state.contains(pyatspi.STATE_FOCUSED) \
+ or args.get('alreadyFocused', False)
+
+ if role == pyatspi.ROLE_SLIDER:
+ if isHorizontal:
+ return object_properties.ROLE_SLIDER_HORIZONTAL
+ if isVertical:
+ return object_properties.ROLE_SLIDER_VERTICAL
+ elif role == pyatspi.ROLE_SCROLL_BAR:
+ if isHorizontal:
+ return object_properties.ROLE_SCROLL_BAR_HORIZONTAL
+ if isVertical:
+ return object_properties.ROLE_SCROLL_BAR_VERTICAL
+ elif role == pyatspi.ROLE_SEPARATOR:
+ if isHorizontal:
+ return object_properties.ROLE_SPLITTER_HORIZONTAL
+ if isVertical:
+ return object_properties.ROLE_SPLITTER_VERTICAL
+ elif role == pyatspi.ROLE_SPLIT_PANE and isFocused:
+ # The splitter has the opposite orientation of the split pane.
+ if isHorizontal:
+ return object_properties.ROLE_SPLITTER_VERTICAL
+ if isVertical:
+ return object_properties.ROLE_SPLITTER_HORIZONTAL
+
+ if self._script.utilities.isLandmark(obj):
+ if self._script.utilities.isLandmarkBanner(obj):
+ return object_properties.ROLE_LANDMARK_BANNER
+ if self._script.utilities.isLandmarkComplementary(obj):
+ return object_properties.ROLE_LANDMARK_COMPLEMENTARY
+ if self._script.utilities.isLandmarkContentInfo(obj):
+ return object_properties.ROLE_LANDMARK_CONTENTINFO
+ if self._script.utilities.isLandmarkMain(obj):
+ return object_properties.ROLE_LANDMARK_MAIN
+ if self._script.utilities.isLandmarkNavigation(obj):
+ return object_properties.ROLE_LANDMARK_NAVIGATION
+ if self._script.utilities.isLandmarkRegion(obj):
+ return object_properties.ROLE_LANDMARK_REGION
+ if self._script.utilities.isLandmarkSearch(obj):
+ return object_properties.ROLE_LANDMARK_SEARCH
+ if self._script.utilities.isLandmarkForm(obj):
+ role = pyatspi.ROLE_FORM
+
+ nonlocalized = Atspi.role_get_name(role)
+ atkRole = Atk.role_for_name(nonlocalized)
+ return Atk.role_get_localized_name(atkRole)
diff --git a/src/orca/object_properties.py b/src/orca/object_properties.py
index 823f7ff..b88d8a7 100644
--- a/src/orca/object_properties.py
+++ b/src/orca/object_properties.py
@@ -83,6 +83,62 @@ ROLE_HEADING_LEVEL_BRAILLE = _("h%d")
# translated rolename for the heading.
ROLE_HEADING_LEVEL_SPEECH = _("%(role)s level %(level)d")
+# Translators: This string should be treated as a role describing an object.
+# Examples of roles include "checkbox", "radio button", "paragraph", and "link."
+# The reason we include the orientation as part of the role is because in some
+# applications and toolkits, it can dictate which keyboard keys should be used
+# to modify the value of the widget.
+ROLE_SCROLL_BAR_HORIZONTAL = _("horizontal scroll bar")
+
+# Translators: This string should be treated as a role describing an object.
+# Examples of roles include "checkbox", "radio button", "paragraph", and "link."
+# The reason we include the orientation as part of the role is because in some
+# applications and toolkits, it can dictate which keyboard keys should be used
+# to modify the value of the widget.
+ROLE_SCROLL_BAR_VERTICAL = _("vertical scroll bar")
+
+# Translators: This string should be treated as a role describing an object.
+# Examples of roles include "checkbox", "radio button", "paragraph", and "link."
+# A slider is a widget which looks like a bar and displays a value as a range.
+# A common example of a slider can be found in UI for modifying volume levels.
+# The reason we include the orientation as part of the role is because in some
+# applications and toolkits, it can dictate which keyboard keys should be used
+# to modify the value of the widget.
+ROLE_SLIDER_HORIZONTAL = _("horizontal slider")
+
+# Translators: This string should be treated as a role describing an object.
+# Examples of roles include "checkbox", "radio button", "paragraph", and "link."
+# A slider is a widget which looks like a bar and displays a value as a range.
+# A common example of a slider can be found in UI for modifying volume levels.
+# The reason we include the orientation as part of the role is because in some
+# applications and toolkits, it can dictate which keyboard keys should be used
+# to modify the value of the widget.
+ROLE_SLIDER_VERTICAL = _("vertical slider")
+
+# Translators: This string should be treated as a role describing an object.
+# Examples of roles include "checkbox", "radio button", "paragraph", and "link."
+# A splitter is a bar that divides a container into two parts. It is often, but
+# not necessarily, user resizable. A common example of a splitter can be found
+# in email applications, where there is a container on the left which holds a
+# list of all the mail folders and a container on the right which lists all of
+# the messages in the selected folder. The bar which you click on and drag to
+# resize these containers is the splitter. The reason we include the orientation
+# as part of the role is because in some applications and toolkits, it can
+# dictate which keyboard keys should be used to modify the value of the widget.
+ROLE_SPLITTER_HORIZONTAL = _("horizontal splitter")
+
+# Translators: This string should be treated as a role describing an object.
+# Examples of roles include "checkbox", "radio button", "paragraph", and "link."
+# A splitter is a bar that divides a container into two parts. It is often, but
+# not necessarily, user resizable. A common example of a splitter can be found
+# in email applications, where there is a container on the left which holds a
+# list of all the mail folders and a container on the right which lists all of
+# the messages in the selected folder. The bar which you click on and drag to
+# resize these containers is the splitter. The reason we include the orientation
+# as part of the role is because in some applications and toolkits, it can
+# dictate which keyboard keys should be used to modify the value of the widget.
+ROLE_SPLITTER_VERTICAL = _("vertical splitter")
+
# Translators: This is an alternative name for the parent object of a series
# of icons.
ROLE_ICON_PANEL = _("Icon panel")
diff --git a/src/orca/scripts/toolkits/WebKitGtk/speech_generator.py
b/src/orca/scripts/toolkits/WebKitGtk/speech_generator.py
index 672adfc..256c27e 100644
--- a/src/orca/scripts/toolkits/WebKitGtk/speech_generator.py
+++ b/src/orca/scripts/toolkits/WebKitGtk/speech_generator.py
@@ -84,10 +84,10 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
level = self._script.utilities.headingLevel(obj)
if level:
result.append(object_properties.ROLE_HEADING_LEVEL_SPEECH % {
- 'role': self.getLocalizedRoleName(obj, role),
+ 'role': self.getLocalizedRoleName(obj, role=role),
'level': level})
else:
- result.append(self.getLocalizedRoleName(obj, role))
+ result.append(self.getLocalizedRoleName(obj, role=role))
return result
@@ -120,7 +120,7 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
elif role == pyatspi.ROLE_HEADING:
result.extend(self.__generateHeadingRole(obj))
else:
- result.append(self.getLocalizedRoleName(obj, role))
+ result.append(self.getLocalizedRoleName(obj, role=role))
if obj.parent and obj.parent.getRole() == pyatspi.ROLE_HEADING:
result.extend(self.__generateHeadingRole(obj.parent))
diff --git a/src/orca/scripts/web/braille_generator.py b/src/orca/scripts/web/braille_generator.py
index 14ee288..b301bdb 100644
--- a/src/orca/scripts/web/braille_generator.py
+++ b/src/orca/scripts/web/braille_generator.py
@@ -41,15 +41,15 @@ class BrailleGenerator(braille_generator.BrailleGenerator):
def __init__(self, script):
super().__init__(script)
- def getLocalizedRoleName(self, obj, role=None):
+ def getLocalizedRoleName(self, obj, **args):
if not self._script.utilities.inDocumentContent(obj):
- return super().getLocalizedRoleName(obj, role)
+ return super().getLocalizedRoleName(obj, **args)
roledescription = self._script.utilities.getRoleDescription(obj)
if roledescription:
return roledescription
- return super().getLocalizedRoleName(obj, role)
+ return super().getLocalizedRoleName(obj, **args)
def _generateRoleName(self, obj, **args):
"""Prevents some roles from being displayed."""
diff --git a/src/orca/scripts/web/speech_generator.py b/src/orca/scripts/web/speech_generator.py
index a9e4659..5fd92a4 100644
--- a/src/orca/scripts/web/speech_generator.py
+++ b/src/orca/scripts/web/speech_generator.py
@@ -221,15 +221,15 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
def _generateTextRole(self, obj, **args):
return self._generateRoleName(obj, **args)
- def getLocalizedRoleName(self, obj, role=None):
+ def getLocalizedRoleName(self, obj, **args):
if not self._script.utilities.inDocumentContent(obj):
- return super().getLocalizedRoleName(obj, role)
+ return super().getLocalizedRoleName(obj, **args)
roledescription = self._script.utilities.getRoleDescription(obj)
if roledescription:
return roledescription
- return super().getLocalizedRoleName(obj, role)
+ return super().getLocalizedRoleName(obj, **args)
def _generateRoleName(self, obj, **args):
if not self._script.utilities.inDocumentContent(obj):
@@ -283,18 +283,18 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
if text and end not in [None, text.characterCount]:
return []
if role not in doNotSpeak:
- result.append(self.getLocalizedRoleName(obj, role))
+ result.append(self.getLocalizedRoleName(obj, **args))
result.extend(acss)
elif role == pyatspi.ROLE_HEADING:
level = self._script.utilities.headingLevel(obj)
if level:
result.append(object_properties.ROLE_HEADING_LEVEL_SPEECH % {
- 'role': self.getLocalizedRoleName(obj, role),
+ 'role': self.getLocalizedRoleName(obj, **args),
'level': level})
result.extend(acss)
else:
- result.append(self.getLocalizedRoleName(obj, role))
+ result.append(self.getLocalizedRoleName(obj, **args))
result.extend(acss)
elif self._script.utilities.isLink(obj):
@@ -303,13 +303,13 @@ class SpeechGenerator(speech_generator.SpeechGenerator):
result.extend(acss)
else:
if self._script.utilities.hasUselessCanvasDescendant(obj):
- result.append(self.getLocalizedRoleName(obj, pyatspi.ROLE_IMAGE))
+ result.append(self.getLocalizedRoleName(obj, role=pyatspi.ROLE_IMAGE))
result.extend(acss)
- result.append(self.getLocalizedRoleName(obj, role))
+ result.append(self.getLocalizedRoleName(obj, **args))
result.extend(acss)
elif role not in doNotSpeak:
- result.append(self.getLocalizedRoleName(obj, role))
+ result.append(self.getLocalizedRoleName(obj, **args))
result.extend(acss)
index = args.get('index', 0)
diff --git a/src/orca/speech_generator.py b/src/orca/speech_generator.py
index c423b5a..6d0cc99 100644
--- a/src/orca/speech_generator.py
+++ b/src/orca/speech_generator.py
@@ -27,7 +27,6 @@ __license__ = "LGPL"
import pyatspi
import urllib.parse, urllib.request, urllib.error, urllib.parse
-from gi.repository import Atspi, Atk
from . import chnames
from . import debug
@@ -349,12 +348,12 @@ class SpeechGenerator(generator.Generator):
level = self._script.utilities.headingLevel(obj)
if level:
result.append(object_properties.ROLE_HEADING_LEVEL_SPEECH % {
- 'role': self.getLocalizedRoleName(obj, role),
+ 'role': self.getLocalizedRoleName(obj, **args),
'level': level})
result.extend(acss)
if role not in doNotPresent and not result:
- result.append(self.getLocalizedRoleName(obj, role))
+ result.append(self.getLocalizedRoleName(obj, **args))
result.extend(acss)
return result
@@ -366,55 +365,37 @@ class SpeechGenerator(generator.Generator):
accessible role of the obj. This is provided mostly as a
method for scripts to call.
"""
- return self._generateRoleName(obj, **args)
+ generated = self._generateRoleName(obj, **args)
+ if generated:
+ return generated[0]
- def getLocalizedRoleName(self, obj, role=None):
+ return ""
+
+ def getName(self, obj, **args):
+ generated = self._generateName(obj, **args)
+ if generated:
+ return generated[0]
+
+ return ""
+
+ def getLocalizedRoleName(self, obj, **args):
"""Returns the localized name of the given Accessible object; the name
is suitable to be spoken.
Arguments:
- obj: an Accessible object
- - role: an optional pyatspi role to use instead
"""
- if not isinstance(role, (pyatspi.Role, Atspi.Role)):
- try:
- return obj.getLocalizedRoleName()
- except:
- return ''
-
- if not role:
- return ''
-
- if self._script.utilities.isLandmark(obj):
- if self._script.utilities.isLandmarkBanner(obj):
- return object_properties.ROLE_LANDMARK_BANNER
- if self._script.utilities.isLandmarkComplementary(obj):
- return object_properties.ROLE_LANDMARK_COMPLEMENTARY
- if self._script.utilities.isLandmarkContentInfo(obj):
- return object_properties.ROLE_LANDMARK_CONTENTINFO
- if self._script.utilities.isLandmarkMain(obj):
- return object_properties.ROLE_LANDMARK_MAIN
- if self._script.utilities.isLandmarkNavigation(obj):
- return object_properties.ROLE_LANDMARK_NAVIGATION
- if self._script.utilities.isLandmarkRegion(obj):
- return object_properties.ROLE_LANDMARK_REGION
- if self._script.utilities.isLandmarkSearch(obj):
- return object_properties.ROLE_LANDMARK_SEARCH
- if self._script.utilities.isLandmarkForm(obj):
- role = pyatspi.ROLE_FORM
-
if self._script.utilities.isEditableComboBox(obj) \
or self._script.utilities.isEditableDescendantOfComboBox(obj):
return object_properties.ROLE_EDITABLE_COMBO_BOX
- if role == pyatspi.ROLE_LINK and obj.getState().contains(pyatspi.STATE_VISITED):
+ role = args.get('role', obj.getRole())
+ state = obj.getState()
+ if role == pyatspi.ROLE_LINK and state.contains(pyatspi.STATE_VISITED):
return object_properties.ROLE_VISITED_LINK
- nonlocalized = Atspi.role_get_name(role)
- atkRole = Atk.role_for_name(nonlocalized)
-
- return Atk.role_get_localized_name(atkRole)
+ return super().getLocalizedRoleName(obj, **args)
def _generateUnrelatedLabels(self, obj, **args):
"""Returns, as an array of strings (and possibly voice
diff --git a/src/orca/structural_navigation.py b/src/orca/structural_navigation.py
index dc22db8..c219e33 100644
--- a/src/orca/structural_navigation.py
+++ b/src/orca/structural_navigation.py
@@ -1161,7 +1161,7 @@ class StructuralNavigation:
def _getRoleName(self, obj):
# Another case where we'll do this for now, and clean it up when
# object presentation is refactored.
- return self._script.speechGenerator.getLocalizedRoleName(obj, obj.getRole())
+ return self._script.speechGenerator.getLocalizedRoleName(obj)
def _getSelectedItem(self, obj):
# Another case where we'll do this for now, and clean it up when
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]