From 578a83503b8290d7cfc982556bcbe3ec43734532 Mon Sep 17 00:00:00 2001 From: Adam Plaice Date: Tue, 13 Apr 2021 22:38:05 +0200 Subject: [PATCH 1/2] Prevent crash when trying to export all decks The crash was caused by the warning dialog, itself! The issue was that export is now run in a background thread, but GUI operations from a background thread cause a crash. AnkiModalNotifier is used in `anki_exporter_wrapper.py` and `github_importer.py`. The former is in a background thread, the latter in the main thread. In both cases, error messages are now correctly displayed, without crashing. Tested on Anki 2.1.40 and 2.1.43. --- crowd_anki/utils/notifier.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/crowd_anki/utils/notifier.py b/crowd_anki/utils/notifier.py index 505ec91..a245439 100644 --- a/crowd_anki/utils/notifier.py +++ b/crowd_anki/utils/notifier.py @@ -1,6 +1,7 @@ from abc import ABC, abstractmethod import aqt.utils +import aqt class Notifier(ABC): @@ -16,16 +17,27 @@ def warning(self, title: str, message: str): def error(self, title: str, message: str): pass +def run_closure_in_main(closure): + """Run the closure in the main thread. + +This is necessary, because GUI operations in a background thread cause +a crash. For instance, export is now run in a background thread. + + """ + if aqt.mw.inMainThread(): + closure() + else: + aqt.mw.taskman.run_on_main(lambda: aqt.mw.progress.timer(50, closure, False)) class AnkiModalNotifier(Notifier): def info(self, title: str, message: str): - aqt.utils.showInfo(message, title=title) + run_closure_in_main(lambda: aqt.utils.showInfo(message, title=title)) def warning(self, title: str, message: str): - aqt.utils.showWarning(message, title=title) + run_closure_in_main(lambda: aqt.utils.showWarning(message, title=title)) def error(self, title: str, message: str): - aqt.utils.showCritical(message, title=title) + run_closure_in_main(lambda: aqt.utils.showCritical(message, title=title)) class AnkiTooltipNotifier(Notifier): From b7cb5715bf01667e2ba7fc2a052f78f7932f2467 Mon Sep 17 00:00:00 2001 From: Adam Plaice Date: Fri, 4 Jun 2021 14:36:16 +0200 Subject: [PATCH 2/2] Try to run the notifier closure immediately The attempted run times (in ms) will be (0, 100, 200, 300). A timeout of 0 does not seem to be used anywhere in the main Anki codebase, but is valid: https://doc.qt.io/qt-5/qtimer.html#details --- crowd_anki/utils/notifier.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crowd_anki/utils/notifier.py b/crowd_anki/utils/notifier.py index a245439..304a135 100644 --- a/crowd_anki/utils/notifier.py +++ b/crowd_anki/utils/notifier.py @@ -27,7 +27,7 @@ def run_closure_in_main(closure): if aqt.mw.inMainThread(): closure() else: - aqt.mw.taskman.run_on_main(lambda: aqt.mw.progress.timer(50, closure, False)) + aqt.mw.taskman.run_on_main(lambda: aqt.mw.progress.timer(0, closure, False)) class AnkiModalNotifier(Notifier): def info(self, title: str, message: str):