From 07a72c5850fd19faf551c2847b2b29cdd5af03f4 Mon Sep 17 00:00:00 2001 From: Cyrille Bougot Date: Fri, 13 Dec 2024 15:48:27 +0100 Subject: [PATCH 1/8] MS Word: The result of Word commands to expand or collapse a heading is now reported --- source/appModules/winword.py | 38 ++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/source/appModules/winword.py b/source/appModules/winword.py index 24a8ce69e7c..8742e40e51d 100644 --- a/source/appModules/winword.py +++ b/source/appModules/winword.py @@ -17,6 +17,11 @@ from utils.displayString import DisplayStringIntEnum +# From WdOutlineLevel enumeration +# See https://learn.microsoft.com/fr-fr/office/vba/api/word.wdoutlinelevel +wdOutlineLevelBodyText = 10 + + class ViewType(DisplayStringIntEnum): """Enumeration containing the possible view types in Word documents:. https://learn.microsoft.com/en-us/office/vba/api/word.wdviewtype @@ -79,6 +84,39 @@ def script_toggleChangeTracking(self, gesture): # Translators: a message when toggling change tracking in Microsoft word ui.message(_("Change tracking off")) + @script(gestures=["kb:alt+shift+-", "kb:alt+shift+="]) + def script_collapseOrExpandHeading(self, gesture: "inputCore.InputGesture"): + if not self.WinwordSelectionObject: + # We cannot fetch the Word object model, so we therefore cannot report the format change. + # The object model may be unavailable because this is a pure UIA implementation such as Windows 10 Mail, + # or it's within Windows Defender Application Guard. + # In this case, just let the gesture through and don't report anything. + return gesture.send() + maxParagraphs = 50 + for (nParagraph, paragraph) in enumerate(self.WinwordSelectionObject.paragraphs): + if paragraph.outlineLevel != wdOutlineLevelBodyText: + break + if nParagraph >= maxParagraphs: + log.debugWarning('Too many paragraphs selected') + gesture.send() + return + else: + gesture.send() + # Translators: a message when collapsing or expanding headings in MS Word + ui.message(_("No heading selected")) + return + val = self._WaitForValueChangeForAction( + lambda: gesture.send(), + lambda: paragraph.CollapsedState, + ) + if val: + # Translators: a message when collapsing a heading in MS Word + msg = _("Collapsed") + else: + # Translators: a message when expanding a heading in MS Word + msg = _("Expanded") + ui.message(msg) + __gestures = { "kb:control+shift+b": "toggleBold", "kb:control+shift+w": "toggleUnderline", From 0ca371f24cf254da06a6a7d862445bd3a4367e4d Mon Sep 17 00:00:00 2001 From: Cyrille Bougot Date: Tue, 17 Dec 2024 23:17:24 +0100 Subject: [PATCH 2/8] Change log --- user_docs/en/changes.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/user_docs/en/changes.md b/user_docs/en/changes.md index 37ab4b9e3b8..3fcd26001c1 100644 --- a/user_docs/en/changes.md +++ b/user_docs/en/changes.md @@ -38,7 +38,9 @@ To use this feature, "allow NVDA to control the volume of other applications" mu * It now starts with a more user friendly explanation of its purpose, instead of a warning. (#12351) * The initial window can now be exited with `escape` or `alt+f4`. (#10799) * 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. -* In Word and Outlook the result of more font formatting shortcuts is now reported. (#10271, @CyrilleB79) +* In Word and Outlook the result of more shortcuts is reported: + * font formatting shortcuts (#10271, @CyrilleB79) + * Collapse or expand heading (#17545, @CyrilleB79) * Default input and output braille tables can now be determined based on the NVDA language. (#17306, #16390, #290, @nvdaes) * 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) * 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) From 2721d4797a82e7f7e2a0abc807a2f1f170903b08 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 17 Dec 2024 22:19:21 +0000 Subject: [PATCH 3/8] Pre-commit auto-fix --- source/appModules/winword.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/appModules/winword.py b/source/appModules/winword.py index 8742e40e51d..cd7678945fd 100644 --- a/source/appModules/winword.py +++ b/source/appModules/winword.py @@ -93,11 +93,11 @@ def script_collapseOrExpandHeading(self, gesture: "inputCore.InputGesture"): # In this case, just let the gesture through and don't report anything. return gesture.send() maxParagraphs = 50 - for (nParagraph, paragraph) in enumerate(self.WinwordSelectionObject.paragraphs): + for nParagraph, paragraph in enumerate(self.WinwordSelectionObject.paragraphs): if paragraph.outlineLevel != wdOutlineLevelBodyText: break if nParagraph >= maxParagraphs: - log.debugWarning('Too many paragraphs selected') + log.debugWarning("Too many paragraphs selected") gesture.send() return else: From 4e193f1835d601f169e00fa31e02b38b5e07c9d0 Mon Sep 17 00:00:00 2001 From: Cyrille Bougot Date: Wed, 18 Dec 2024 08:31:03 +0100 Subject: [PATCH 4/8] Add missing imports --- source/appModules/winword.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/appModules/winword.py b/source/appModules/winword.py index cd7678945fd..85354fac497 100644 --- a/source/appModules/winword.py +++ b/source/appModules/winword.py @@ -11,10 +11,15 @@ import appModuleHandler from scriptHandler import script import ui +from logHandler import log from NVDAObjects.IAccessible.winword import WordDocument as IAccessibleWordDocument from NVDAObjects.UIA.wordDocument import WordDocument as UIAWordDocument from NVDAObjects.window.winword import WordDocument from utils.displayString import DisplayStringIntEnum +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + import inputCore # From WdOutlineLevel enumeration From 2d06c28e4445304808c9a13d20227c74c3be5e5f Mon Sep 17 00:00:00 2001 From: Cyrille Bougot Date: Wed, 22 Jan 2025 13:00:14 +0100 Subject: [PATCH 5/8] Add numpad gestures --- source/appModules/winword.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/appModules/winword.py b/source/appModules/winword.py index 85354fac497..b2b3de3feeb 100644 --- a/source/appModules/winword.py +++ b/source/appModules/winword.py @@ -89,7 +89,7 @@ def script_toggleChangeTracking(self, gesture): # Translators: a message when toggling change tracking in Microsoft word ui.message(_("Change tracking off")) - @script(gestures=["kb:alt+shift+-", "kb:alt+shift+="]) + @script(gestures=["kb:alt+shift+-", "kb:alt+shift+=", "kb:alt+shift+numpadPlus", "kb:alt+shift+numpadMinus"]) def script_collapseOrExpandHeading(self, gesture: "inputCore.InputGesture"): if not self.WinwordSelectionObject: # We cannot fetch the Word object model, so we therefore cannot report the format change. From 14b14a5c8f7a6d9c158c634282bd03ffae28579c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 22 Jan 2025 12:04:17 +0000 Subject: [PATCH 6/8] Pre-commit auto-fix --- source/appModules/winword.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/appModules/winword.py b/source/appModules/winword.py index b2b3de3feeb..93c396ca3ec 100644 --- a/source/appModules/winword.py +++ b/source/appModules/winword.py @@ -89,7 +89,9 @@ def script_toggleChangeTracking(self, gesture): # Translators: a message when toggling change tracking in Microsoft word ui.message(_("Change tracking off")) - @script(gestures=["kb:alt+shift+-", "kb:alt+shift+=", "kb:alt+shift+numpadPlus", "kb:alt+shift+numpadMinus"]) + @script( + gestures=["kb:alt+shift+-", "kb:alt+shift+=", "kb:alt+shift+numpadPlus", "kb:alt+shift+numpadMinus"] + ) def script_collapseOrExpandHeading(self, gesture: "inputCore.InputGesture"): if not self.WinwordSelectionObject: # We cannot fetch the Word object model, so we therefore cannot report the format change. From bcddbeaa81f7208af741480da2d75185a0b3eed6 Mon Sep 17 00:00:00 2001 From: Cyrille Bougot Date: Sun, 26 Jan 2025 22:07:05 +0100 Subject: [PATCH 7/8] Do not report anything in Outline or Draft mode --- source/appModules/winword.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/source/appModules/winword.py b/source/appModules/winword.py index 93c396ca3ec..334328cb841 100644 --- a/source/appModules/winword.py +++ b/source/appModules/winword.py @@ -1,7 +1,7 @@ # A part of NonVisual Desktop Access (NVDA) # This file is covered by the GNU General Public License. # See the file COPYING for more details. -# Copyright (C) 2019-2024 NV Access Limited, Cyrille Bougot +# Copyright (C) 2019-2025 NV Access Limited, Cyrille Bougot """App module for Microsoft Word. Word and Outlook share a lot of code and components. This app module gathers the code that is relevant for @@ -92,13 +92,20 @@ def script_toggleChangeTracking(self, gesture): @script( gestures=["kb:alt+shift+-", "kb:alt+shift+=", "kb:alt+shift+numpadPlus", "kb:alt+shift+numpadMinus"] ) - def script_collapseOrExpandHeading(self, gesture: "inputCore.InputGesture"): + def script_collapseOrExpandHeading(self, gesture: "inputCore.InputGesture") -> None: if not self.WinwordSelectionObject: - # We cannot fetch the Word object model, so we therefore cannot report the format change. + # We cannot fetch the Word object model, so we therefore cannot report the collapsed state change. # The object model may be unavailable because this is a pure UIA implementation such as Windows 10 Mail, # or it's within Windows Defender Application Guard. # In this case, just let the gesture through and don't report anything. - return gesture.send() + gesture.send() + return + if self.WinwordWindowObject.view.Type in [ViewType.OUTLINE, ViewType.DRAFT]: + # In draft mode, collapsing headings is not available. + # In Outline view, paragraph.CollapsedState does not report the correct value. + # So do not report anything in these modes + gesture.send() + return maxParagraphs = 50 for nParagraph, paragraph in enumerate(self.WinwordSelectionObject.paragraphs): if paragraph.outlineLevel != wdOutlineLevelBodyText: From 79648f5ba00fe53683a0eef724a8c4c0b81acf59 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 26 Jan 2025 21:07:47 +0000 Subject: [PATCH 8/8] Pre-commit auto-fix --- source/appModules/winword.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/appModules/winword.py b/source/appModules/winword.py index 334328cb841..081e9c832bc 100644 --- a/source/appModules/winword.py +++ b/source/appModules/winword.py @@ -90,7 +90,7 @@ def script_toggleChangeTracking(self, gesture): ui.message(_("Change tracking off")) @script( - gestures=["kb:alt+shift+-", "kb:alt+shift+=", "kb:alt+shift+numpadPlus", "kb:alt+shift+numpadMinus"] + gestures=["kb:alt+shift+-", "kb:alt+shift+=", "kb:alt+shift+numpadPlus", "kb:alt+shift+numpadMinus"], ) def script_collapseOrExpandHeading(self, gesture: "inputCore.InputGesture") -> None: if not self.WinwordSelectionObject: