Skip to content

Commit 268541d

Browse files
authored
Merge 5a5b982 into 290a474
2 parents 290a474 + 5a5b982 commit 268541d

3 files changed

Lines changed: 68 additions & 4 deletions

File tree

source/NVDAObjects/window/winword.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,14 @@ def _displayStringLabels(self) -> dict[Self, str]:
152152
wdAlignParagraphCenter = 1
153153
wdAlignParagraphRight = 2
154154
wdAlignParagraphJustify = 3
155+
156+
157+
# From WdOutlineLevel enumeration
158+
# See https://learn.microsoft.com/en-us/office/vba/api/word.wdoutlinelevel
159+
class WdOutlineLevel(IntEnum):
160+
BODY_TEXT = 10
161+
162+
155163
# Units
156164
wdCharacter = 1
157165
wdWord = 2
@@ -1442,7 +1450,11 @@ def _iterHeadings(self, nodeType, direction, rangeObj, includeCurrent):
14421450
while True:
14431451
if not isFirst or includeCurrent:
14441452
level = rangeObj.paragraphs[1].outlineLevel
1445-
if level and 0 < level < 10 and (not neededLevel or neededLevel == level):
1453+
if (
1454+
level
1455+
and 0 < level < WdOutlineLevel.BODY_TEXT
1456+
and (not neededLevel or neededLevel == level)
1457+
):
14461458
rangeObj.expand(wdParagraph)
14471459
yield WordDocumentHeadingQuickNavItem(
14481460
nodeType,

source/appModules/winword.py

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# A part of NonVisual Desktop Access (NVDA)
22
# This file is covered by the GNU General Public License.
33
# See the file COPYING for more details.
4-
# Copyright (C) 2019-2024 NV Access Limited, Cyrille Bougot
4+
# Copyright (C) 2019-2025 NV Access Limited, Cyrille Bougot
55

66
"""App module for Microsoft Word.
77
Word and Outlook share a lot of code and components. This app module gathers the code that is relevant for
@@ -11,10 +11,18 @@
1111
import appModuleHandler
1212
from scriptHandler import script
1313
import ui
14+
from logHandler import log
1415
from NVDAObjects.IAccessible.winword import WordDocument as IAccessibleWordDocument
1516
from NVDAObjects.UIA.wordDocument import WordDocument as UIAWordDocument
16-
from NVDAObjects.window.winword import WordDocument
17+
from NVDAObjects.window.winword import (
18+
WordDocument,
19+
WdOutlineLevel,
20+
)
1721
from utils.displayString import DisplayStringIntEnum
22+
from typing import TYPE_CHECKING
23+
24+
if TYPE_CHECKING:
25+
import inputCore
1826

1927

2028
class ViewType(DisplayStringIntEnum):
@@ -79,6 +87,48 @@ def script_toggleChangeTracking(self, gesture):
7987
# Translators: a message when toggling change tracking in Microsoft word
8088
ui.message(_("Change tracking off"))
8189

90+
@script(
91+
gestures=["kb:alt+shift+-", "kb:alt+shift+=", "kb:alt+shift+numpadPlus", "kb:alt+shift+numpadMinus"],
92+
)
93+
def script_collapseOrExpandHeading(self, gesture: "inputCore.InputGesture") -> None:
94+
if not self.WinwordSelectionObject:
95+
# We cannot fetch the Word object model, so we therefore cannot report the collapsed state change.
96+
# The object model may be unavailable because this is a pure UIA implementation such as Windows 10 Mail,
97+
# or it's within Windows Defender Application Guard.
98+
# In this case, just let the gesture through and don't report anything.
99+
gesture.send()
100+
return
101+
if self.WinwordWindowObject.view.Type in [ViewType.OUTLINE, ViewType.DRAFT]:
102+
# In draft mode, collapsing headings is not available.
103+
# In Outline view, paragraph.CollapsedState does not report the correct value.
104+
# So do not report anything in these modes
105+
gesture.send()
106+
return
107+
maxParagraphs = 50
108+
for nParagraph, paragraph in enumerate(self.WinwordSelectionObject.paragraphs):
109+
if paragraph.outlineLevel != WdOutlineLevel.BODY_TEXT:
110+
break
111+
if nParagraph >= maxParagraphs:
112+
log.debugWarning("Too many paragraphs selected")
113+
gesture.send()
114+
return
115+
else:
116+
gesture.send()
117+
# Translators: a message when collapsing or expanding headings in MS Word
118+
ui.message(_("No heading selected"))
119+
return
120+
val = self._WaitForValueChangeForAction(
121+
lambda: gesture.send(),
122+
lambda: paragraph.CollapsedState,
123+
)
124+
if val:
125+
# Translators: a message when collapsing a heading in MS Word
126+
msg = _("Collapsed")
127+
else:
128+
# Translators: a message when expanding a heading in MS Word
129+
msg = _("Expanded")
130+
ui.message(msg)
131+
82132
__gestures = {
83133
"kb:control+shift+b": "toggleBold",
84134
"kb:control+shift+w": "toggleUnderline",

user_docs/en/changes.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ As a consequence, announcement of first line indent is now supported for LibreOf
4949
* It now starts with a more user friendly explanation of its purpose, instead of a warning. (#12351)
5050
* The initial window can now be exited with `escape` or `alt+f4`. (#10799)
5151
* It will now show a message to the user, including the error, in the rare event of a Windows error while attempting COM re-registrations.
52-
* In Word and Outlook the result of more font formatting shortcuts is now reported. (#10271, @CyrilleB79)
52+
* In Word and Outlook the result of more shortcuts is reported:
53+
* font formatting shortcuts (#10271, @CyrilleB79)
54+
* Collapse or expand heading (#17545, @CyrilleB79)
5355
* Default input and output braille tables can now be determined based on the NVDA language. (#17306, #16390, #290, @nvdaes)
5456
* In Microsoft Word, when using the "report focus" command, the document layout will be announced if this information is available and reporting object descriptions is enabled. (#15088, @nvdaes)
5557
* NVDA will now only warn about add-on incompatibility when updating to a version which has an incompatible add-on API to the currently installed copy. (#17071, #17506)

0 commit comments

Comments
 (0)