From d10410f3534e49454665618e6b7d0da457287f4a Mon Sep 17 00:00:00 2001 From: Cyrille Bougot Date: Mon, 25 Oct 2021 23:35:17 +0200 Subject: [PATCH 1/3] Refocus multi-category settings dialog with the provided category. --- source/gui/__init__.py | 3 ++ source/gui/settingsDialogs.py | 53 ++++++++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/source/gui/__init__.py b/source/gui/__init__.py index 792f3d4ead6..8959bdc245a 100644 --- a/source/gui/__init__.py +++ b/source/gui/__init__.py @@ -26,6 +26,7 @@ from . import guiHelper from .settingsDialogs import ( SettingsDialog, + MultiCategorySettingsDialog, DefaultDictionaryDialog, VoiceDictionaryDialog, TemporaryDictionaryDialog, @@ -152,6 +153,8 @@ def _popupSettingsDialog(self, dialog, *args, **kwargs): dialog(self, *args, **kwargs).Show() except SettingsDialog.MultiInstanceErrorWithDialog as errorWithDialog: errorWithDialog.dialog.SetFocus() + if isinstance(errorWithDialog.dialog, MultiCategorySettingsDialog) and len(args) > 0: + errorWithDialog.dialog.selectNewCategory(args[0]) except MultiCategorySettingsDialog.CategoryUnavailableError: # Translators: Message shown when trying to open an unavailable category of a multi category settings dialog # (example: when trying to open touch interaction settings on an unsupported system). diff --git a/source/gui/settingsDialogs.py b/source/gui/settingsDialogs.py index 43204adfcb0..bce84da84f1 100644 --- a/source/gui/settingsDialogs.py +++ b/source/gui/settingsDialogs.py @@ -41,7 +41,7 @@ import vision import vision.providerInfo import vision.providerBase -from typing import Callable, List, Optional, Any +from typing import Callable, List, Optional, Any, Union import core import keyboardHandler import characterProcessing @@ -425,23 +425,16 @@ class MultiCategorySettingsDialog(SettingsDialog): class CategoryUnavailableError(RuntimeError): pass - def __init__(self, parent, initialCategory=None): + def __init__( + self, + parent: Union[wx.Window, None], + initialCategory: Optional[SettingsPanel] = None, + ): """ @param parent: The parent for this dialog; C{None} for no parent. - @type parent: wx.Window @param initialCategory: The initial category to select when opening this dialog - @type parent: SettingsPanel """ - if initialCategory and not issubclass(initialCategory,SettingsPanel): - if gui._isDebug(): - log.debug("Unable to open category: {}".format(initialCategory), stack_info=True) - raise TypeError("initialCategory should be an instance of SettingsPanel") - if initialCategory and initialCategory not in self.categoryClasses: - if gui._isDebug(): - log.debug("Unable to open category: {}".format(initialCategory), stack_info=True) - raise MultiCategorySettingsDialog.CategoryUnavailableError( - "The provided initial category is not a part of this dialog" - ) + self.checkCategory(initialCategory) self.initialCategory = initialCategory self.currentCategory = None self.setPostInitFocus = None @@ -552,6 +545,25 @@ def makeSettings(self, settingsSizer): self.Bind(wx.EVT_CHAR_HOOK, self.onCharHook) self.Bind(EVT_RW_LAYOUT_NEEDED, self._onPanelLayoutChanged) + def checkCategory(self, cat: Union[SettingsPanel, None]) -> None: + """ + @param cat: The class of the panel on which the dialog should be opened or C{None} if no specific panel + is targetted. + + """ + if cat is None: + return + if not issubclass(cat, SettingsPanel): + if gui._isDebug(): + log.debug("Unable to open category: {}".format(cat), stack_info=True) + raise TypeError("cat should be an instance of SettingsPanel") + if cat not in self.categoryClasses: + if gui._isDebug(): + log.debug("Unable to open category: {}".format(cat), stack_info=True) + raise MultiCategorySettingsDialog.CategoryUnavailableError( + "The provided initial category is not a part of this dialog" + ) + def _getCategoryPanel(self, catId): panel = self.catIdToInstanceMap.get(catId, None) if not panel: @@ -624,6 +636,19 @@ def _onPanelLayoutChanged(self,evt): # erase the old contents and must be redrawn self.container.Refresh() + def selectNewCategory(self, cat): + self.checkCategory(cat) + currentCat = self.currentCategory + newIndex = self.categoryClasses.index(cat) + if not currentCat or newIndex != self.categoryClasses.index(currentCat.__class__): + listHadFocus = self.catListCtrl.HasFocus() + if not listHadFocus: + self.catListCtrl.SetFocus() + self.catListCtrl.Select(newIndex) + # we must focus the new selection in the category list to trigger the change of category. + self.catListCtrl.Focus(newIndex) + self.currentCategory.SetFocus() + def _doCategoryChange(self, newCatId): oldCat = self.currentCategory # Freeze and Thaw are called to stop visual artifact's while the GUI From ff22bd000d3acb78cbcc5b039ad64a4141bd0bab Mon Sep 17 00:00:00 2001 From: Cyrille Bougot Date: Wed, 27 Oct 2021 22:34:16 +0200 Subject: [PATCH 2/3] Review suggestion: Use Optional in type annotations. --- source/gui/settingsDialogs.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/gui/settingsDialogs.py b/source/gui/settingsDialogs.py index bce84da84f1..18773380b40 100644 --- a/source/gui/settingsDialogs.py +++ b/source/gui/settingsDialogs.py @@ -41,7 +41,7 @@ import vision import vision.providerInfo import vision.providerBase -from typing import Callable, List, Optional, Any, Union +from typing import Callable, List, Optional, Any import core import keyboardHandler import characterProcessing @@ -427,7 +427,7 @@ class CategoryUnavailableError(RuntimeError): pass def __init__( self, - parent: Union[wx.Window, None], + parent: Optional[wx.Window], initialCategory: Optional[SettingsPanel] = None, ): """ @@ -545,7 +545,7 @@ def makeSettings(self, settingsSizer): self.Bind(wx.EVT_CHAR_HOOK, self.onCharHook) self.Bind(EVT_RW_LAYOUT_NEEDED, self._onPanelLayoutChanged) - def checkCategory(self, cat: Union[SettingsPanel, None]) -> None: + def checkCategory(self, cat: Optional[SettingsPanel]) -> None: """ @param cat: The class of the panel on which the dialog should be opened or C{None} if no specific panel is targetted. From 260cf7c48652647b9f488fab78b519c3489dd5e3 Mon Sep 17 00:00:00 2001 From: Cyrille Bougot Date: Thu, 6 Jun 2024 17:27:45 +0200 Subject: [PATCH 3/3] Add change log --- user_docs/en/changes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/user_docs/en/changes.md b/user_docs/en/changes.md index 2a26b7c2ae9..5102bbd6346 100644 --- a/user_docs/en/changes.md +++ b/user_docs/en/changes.md @@ -46,6 +46,7 @@ Unicode CLDR has been updated. * NVDA will correctly announce selection changes when editing a cell's text in Microsoft Excel. (#15843) * In applications using Java Access Bridge, NVDA will now correctly read the last blank line of a text instead of repeating the previous line. (#9376, @dmitrii-drobotov) * In LibreOffice Writer (version 24.8 and newer), when toggling text formatting (bold, italic, underline, subscript/superscript, alignment) using the corresponding keyboard shortcut, NVDA announces the new formatting attribute (e.g. "Bold on", "Bold off"). (#4248, @michaelweghorn) +* Opening the settings dialog a second time with a keyboard shortcut now opens the expected settings panel. (#12995) ### Changes for Developers