Skip to content

Multiple dictionary dialogs can now be opened simultaneously if the dictionaries are of different types#12967

Merged
seanbudd merged 2 commits into
nvaccess:betafrom
CyrilleB79:dictDialogs
Oct 22, 2021
Merged

Multiple dictionary dialogs can now be opened simultaneously if the dictionaries are of different types#12967
seanbudd merged 2 commits into
nvaccess:betafrom
CyrilleB79:dictDialogs

Conversation

@CyrilleB79

@CyrilleB79 CyrilleB79 commented Oct 20, 2021

Copy link
Copy Markdown
Contributor

Opened against beta branch since it is a follow-up of #12800.
Cc @seanbudd

Link to issue number:

Fix-up of #12800.
Described in #12800 (comment), paragraph "Test almost successful", "Test 2".

Summary of the issue:

Since the merge of #12800, trying to re-open an already opened dialog allows to focus it rather than issuing an error as done previously. However, in the case of dictionaries, if you try to open the voice dictionary while the default is already open will lead to focus the default dictionary rather than opening the voice dictionary dialog;

Description of how this pull request fixes the issue:

Since the check of an existing opened dialog is made on the class of the dialog, I have sub-classed DictionaryDialog for the three types of dictionaries to make them distinct one from another.

Testing strategy:

Test 1:

  • Tried to open the 3 dictionary dialogs simultaneously, either with the menu or with keyboard shortcut.

Test 2:

  • Open the three dictionaries windows
  • Updated them all (at least adding one entry for each)
  • Close them all
  • Re-open them all one by one to check that the content has been correctly updated.

Known issues with pull request:

Maybe it would be interesting to forbid to instance an object of class DictionaryDialog directly, i.e. force subclassing.
I do not know however how it can be acheived and do not even know if it is pythonic.
Comments are welcome.

Change log entries:

Not needed if merged along with #12800 in 2021.3.

Code Review Checklist:

  • Pull Request description:
    • description is up to date
    • change log entries
  • Testing:
    • Unit tests
    • System (end to end) tests
    • Manual testing
  • API is compatible with existing add-ons.
  • Documentation:
    • User Documentation
    • Developer / Technical Documentation
    • Context sensitive help for GUI changes
  • UX of all users considered:
    • Speech
    • Braille
    • Low Vision
    • Different web browsers
    • Localization in other languages / culture than English

@CyrilleB79 CyrilleB79 requested a review from a team as a code owner October 20, 2021 22:10
@CyrilleB79 CyrilleB79 requested review from seanbudd and removed request for a team October 20, 2021 22:10
@seanbudd

Copy link
Copy Markdown
Member

Have you tested updating and saving a dialog, with multiple dialogs open, and then reopening the dialog to confirm the changes were saved?

Maybe it would be interesting to forbid to instance an object of class DictionaryDialog directly, i.e. force subclassing.
I do not know however how it can be acheived and do not even know if it is pythonic.

This can be done by using the Abstract Base Class pattern (other docs).

@lukaszgo1

Copy link
Copy Markdown
Contributor

Maybe it would be interesting to forbid to instance an object of class DictionaryDialog directly, i.e. force subclassing. I do not know however how it can be acheived and do not even know if it is pythonic. Comments are welcome.

Assuming this is going to be merged in 2021.3 we cannot do that, as there are some add-ons (I know about Application dictionary but there are probably others) which would be broken as a result of this change.

@CyrilleB79

Copy link
Copy Markdown
Contributor Author

Have you tested updating and saving a dialog, with multiple dialogs open, and then reopening the dialog to confirm the changes were saved?

Thanks. I have just done this test. I will update the initial description accordingly.

Maybe it would be interesting to forbid to instance an object of class DictionaryDialog directly, i.e. force subclassing.
I do not know however how it can be acheived and do not even know if it is pythonic.

This can be done by using the Abstract Base Class pattern (other docs).

So if I understand correctly:

  1. What would be required here is to make DictionaryDialog abstract and make DictionaryDialog.__init__ an abstract method.
  2. To make the class DictionaryDialog abstract, I should add metaclass=ABCMeta.
  3. To make __init__ an abstract method, I just need to decorate it with the @abstractmethod decorator.
    Is it correct?

Actually, at point 2, if I take example on the class SettingsDialog, it seems that I should rather use metaclass=guiHelper.SIPABCMeta instead of metaclass=ABCMeta for classes inheriting from wx.Something. I do not understand why however; I do not know what is wx.siplib.wrappertype

At last, as indicated by @lukaszgo1, we cannot make existing classes and methods abstract without breaking the compatibility. Thus an option could be to merge this PR as is in 2021.3 (beta) to have the fix at least for the majority of dictionaries (NVDA default, NVDA voice, NVDA temporary and Emoticons add-on which subclasses the DictionaryDialog). The bug wouldn't be resolved only in case two add-ons use DictionaryDialog without subclassing it. This probability seems quite low.
Then, for 2022.1 we could make another PR to make DictionaryDialog abstract.
Do you agree with this way to do?

@seanbudd

Copy link
Copy Markdown
Member

Then, for 2022.1 we could make another PR to make DictionaryDialog abstract.
Do you agree with this way to do?

I agree, this is probably the best approach. Making sure that DictionaryDialog is properly abstracted might be a complicated process as well, and this has the potential to be merged before the first beta as is.

@seanbudd seanbudd changed the title Two dictionary dialogs can now be opened simultaneously if the dictionaries are of different types Multiple dictionary dialogs can now be opened simultaneously if the dictionaries are of different types Oct 21, 2021

@seanbudd seanbudd left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks @CyrilleB79, I've confirmed your manual testing.
@feerrenrut - can this be included in 2021.3 beta1 ?

@seanbudd seanbudd added this to the 2021.3 milestone Oct 21, 2021
@feerrenrut

Copy link
Copy Markdown
Contributor

Yes, happy for this to be included. As far as I can tell it maintains backwards compatibility, is low risk, and fixes a regression in the release.

@seanbudd seanbudd merged commit 91a7c39 into nvaccess:beta Oct 22, 2021
@CyrilleB79 CyrilleB79 deleted the dictDialogs branch October 22, 2021 06:36
seanbudd pushed a commit that referenced this pull request Jan 25, 2022
Link to issue number:
Follow-up of #12967

Summary of the issue:
Since the merge of #12800, trying to re-open an already opened dialog allows to focus it rather than issuing an error message box. The dialog is refocused according to its class, i.e. trying to open a dialog of the same class rather refocus the first already opened dialog of the same class.

But with #12800, it was not possible to open 2 dictionaries of different type (e.g. speech and default). This was fixed with #12967 by subclassing DictionaryDialog.
However, addons which directly use DictionaryDialog will still have the issue of opening 2 dictionaries at once i.e. #5383.

Description of how this pull request fixes the issue:
force DictionaryDialog to be subclassed by making the initializer and abstract method
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants