Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MS Word documents: report when headings are collapsed in both speech and braille. #17499

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
16 changes: 16 additions & 0 deletions source/NVDAObjects/UIA/wordDocument.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ class UIACustomAttributeID(enum.IntEnum):
COLUMN_NUMBER = 2
SECTION_NUMBER = 3
BOOKMARK_NAME = 4
COLUMNS_IN_SECTION = 5
SaschaCowley marked this conversation as resolved.
Show resolved Hide resolved
EXPAND_COLLAPSE_STATE = 6


class EXPAND_COLLAPSE_STATE(enum.IntEnum):
COLLAPSED = 0
EXPANDED = 1


#: the non-printable unicode character that represents the end of cell or end of row mark in Microsoft Word
Expand Down Expand Up @@ -483,6 +490,15 @@ def _getFormatFieldAtRange(self, textRange, formatConfig, ignoreMixedValues=Fals
)
if isinstance(textColumnNumber, int):
formatField.field["text-column-number"] = textColumnNumber
expandCollapseState = UIARemote.msWord_getCustomAttributeValue(
docElement,
textRange,
UIACustomAttributeID.EXPAND_COLLAPSE_STATE,
)
if expandCollapseState == EXPAND_COLLAPSE_STATE.COLLAPSED:
formatField.field["collapsed"] = True
elif expandCollapseState == EXPAND_COLLAPSE_STATE.EXPANDED:
formatField.field["collapsed"] = False
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get the following error with an older Word version:
UnboundLocalError: cannot access local variable 'docElement' where it is not associated with a value

You should indent this code to execute it in the "if" branch where docElement is defined.

Suggested change
expandCollapseState = UIARemote.msWord_getCustomAttributeValue(
docElement,
textRange,
UIACustomAttributeID.EXPAND_COLLAPSE_STATE,
)
if expandCollapseState == EXPAND_COLLAPSE_STATE.COLLAPSED:
formatField.field["collapsed"] = True
elif expandCollapseState == EXPAND_COLLAPSE_STATE.EXPANDED:
formatField.field["collapsed"] = False
expandCollapseState = UIARemote.msWord_getCustomAttributeValue(
docElement,
textRange,
UIACustomAttributeID.EXPAND_COLLAPSE_STATE,
)
if expandCollapseState == EXPAND_COLLAPSE_STATE.COLLAPSED:
formatField.field["collapsed"] = True
elif expandCollapseState == EXPAND_COLLAPSE_STATE.EXPANDED:
formatField.field["collapsed"] = False

return formatField

def _getIndentValueDisplayString(self, val: float) -> str:
Expand Down
4 changes: 4 additions & 0 deletions source/braille.py
Original file line number Diff line number Diff line change
Expand Up @@ -1160,6 +1160,10 @@ def getFormatFieldBraille(field, fieldCache, isAtStart, formatConfig):
# Translators: Displayed in braille for a heading with a level.
# %s is replaced with the level.
textList.append(_("h%s") % headingLevel)
collapsed = field.get("collapsed")
if collapsed:
# Translators: Displayed in braille for collapsed text
textList.append(_("+"))
michaelDCurran marked this conversation as resolved.
Show resolved Hide resolved
if formatConfig["reportLinks"]:
link = field.get("link")
oldLink = fieldCache.get("link")
Expand Down
15 changes: 15 additions & 0 deletions source/speech/speech.py
Original file line number Diff line number Diff line change
Expand Up @@ -2620,6 +2620,21 @@ def getFormatFieldSpeech( # noqa: C901
# Translators: Speaks the heading level (example output: heading level 2).
text = _("heading level %d") % headingLevel
textList.append(text)
collapsed = attrs.get("collapsed")
oldCollapsed = attrsCache.get("collapsed") if attrsCache is not None else None
# collapsed state should be spoken when beginning to speak lines or paragraphs
# Ensuring a similar experience to if it was a state on a controlField
if collapsed and (
initialFormat
and (
reason in [OutputReason.FOCUS, OutputReason.QUICKNAV]
or unit in (textInfos.UNIT_LINE, textInfos.UNIT_PARAGRAPH)
)
or collapsed != oldCollapsed
):
# Translators: collapsed text (E.g. a collapsed heading in MS Word)
text = _("collapsed")
textList.append(text)
michaelDCurran marked this conversation as resolved.
Show resolved Hide resolved
if formatConfig["reportStyle"]:
style = attrs.get("style")
oldStyle = attrsCache.get("style") if attrsCache is not None else None
Expand Down
1 change: 1 addition & 0 deletions user_docs/en/changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ To use this feature, "allow NVDA to control the volume of other applications" mu
* Automatic language switching is now supported when using Microsoft Speech API version 5 (SAPI5) and Microsoft Speech Platform voices. (#17146, @gexgd0419)
* NVDA can now be configured to speak the current line or paragraph when navigating with braille navigation keys. (#17053, @nvdaes)
* In Word, the selection update is now reported when using Word commands to extend or reduce the selection (`f8` or `shift+f8`). (#3293, @CyrilleB79)
* In Word 16.0.18226 and higher, NVDA will now report if a heading is collapsed in both speech and braille. (#17499)
michaelDCurran marked this conversation as resolved.
Show resolved Hide resolved

### Changes

Expand Down