|
1 | 1 | # A part of NonVisual Desktop Access (NVDA) |
2 | 2 | # This file is covered by the GNU General Public License. |
3 | 3 | # 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 |
5 | 5 |
|
6 | 6 | """App module for Microsoft Word. |
7 | 7 | Word and Outlook share a lot of code and components. This app module gathers the code that is relevant for |
|
11 | 11 | import appModuleHandler |
12 | 12 | from scriptHandler import script |
13 | 13 | import ui |
| 14 | +from logHandler import log |
14 | 15 | from NVDAObjects.IAccessible.winword import WordDocument as IAccessibleWordDocument |
15 | 16 | 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 | +) |
17 | 21 | from utils.displayString import DisplayStringIntEnum |
| 22 | +from typing import TYPE_CHECKING |
| 23 | + |
| 24 | +if TYPE_CHECKING: |
| 25 | + import inputCore |
18 | 26 |
|
19 | 27 |
|
20 | 28 | class ViewType(DisplayStringIntEnum): |
@@ -79,6 +87,48 @@ def script_toggleChangeTracking(self, gesture): |
79 | 87 | # Translators: a message when toggling change tracking in Microsoft word |
80 | 88 | ui.message(_("Change tracking off")) |
81 | 89 |
|
| 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 | + |
82 | 132 | __gestures = { |
83 | 133 | "kb:control+shift+b": "toggleBold", |
84 | 134 | "kb:control+shift+w": "toggleUnderline", |
|
0 commit comments