diff --git a/qt/aqt/addons.py b/qt/aqt/addons.py index 58be30716..e8788ee7b 100644 --- a/qt/aqt/addons.py +++ b/qt/aqt/addons.py @@ -706,6 +706,7 @@ class AddonsDialog(QDialog): self.setAcceptDrops(True) self.redrawAddons() restoreGeom(self, "addons") + gui_hooks.addons_dialog_will_show(self) self.show() def dragEnterEvent(self, event): @@ -783,6 +784,7 @@ class AddonsDialog(QDialog): or self.mgr.configAction(addon.dir_name) ) ) + gui_hooks.addons_dialog_did_change_selected_addon(self, addon) return def selectedAddons(self) -> List[str]: diff --git a/qt/aqt/gui_hooks.py b/qt/aqt/gui_hooks.py index 86fa5bdb3..73e85eeef 100644 --- a/qt/aqt/gui_hooks.py +++ b/qt/aqt/gui_hooks.py @@ -135,6 +135,67 @@ class _AddonConfigEditorWillSaveJsonFilter: addon_config_editor_will_save_json = _AddonConfigEditorWillSaveJsonFilter() +class _AddonsDialogDidChangeSelectedAddonHook: + """Allows doing an action when a single add-on is selected.""" + + _hooks: List[ + Callable[["aqt.addons.AddonsDialog", "aqt.addons.AddonMeta"], None] + ] = [] + + def append( + self, cb: Callable[["aqt.addons.AddonsDialog", "aqt.addons.AddonMeta"], None] + ) -> None: + """(dialog: aqt.addons.AddonsDialog, add_on: aqt.addons.AddonMeta)""" + self._hooks.append(cb) + + def remove( + self, cb: Callable[["aqt.addons.AddonsDialog", "aqt.addons.AddonMeta"], None] + ) -> None: + if cb in self._hooks: + self._hooks.remove(cb) + + def __call__( + self, dialog: aqt.addons.AddonsDialog, add_on: aqt.addons.AddonMeta + ) -> None: + for hook in self._hooks: + try: + hook(dialog, add_on) + except: + # if the hook fails, remove it + self._hooks.remove(hook) + raise + + +addons_dialog_did_change_selected_addon = _AddonsDialogDidChangeSelectedAddonHook() + + +class _AddonsDialogWillShowHook: + """Allows changing the add-on dialog before it is shown. E.g. add + buttons.""" + + _hooks: List[Callable[["aqt.addons.AddonsDialog"], None]] = [] + + def append(self, cb: Callable[["aqt.addons.AddonsDialog"], None]) -> None: + """(dialog: aqt.addons.AddonsDialog)""" + self._hooks.append(cb) + + def remove(self, cb: Callable[["aqt.addons.AddonsDialog"], None]) -> None: + if cb in self._hooks: + self._hooks.remove(cb) + + def __call__(self, dialog: aqt.addons.AddonsDialog) -> None: + for hook in self._hooks: + try: + hook(dialog) + except: + # if the hook fails, remove it + self._hooks.remove(hook) + raise + + +addons_dialog_will_show = _AddonsDialogWillShowHook() + + class _AvPlayerDidBeginPlayingHook: _hooks: List[Callable[["aqt.sound.Player", "anki.sound.AVTag"], None]] = [] diff --git a/qt/tools/genhooks_gui.py b/qt/tools/genhooks_gui.py index e3049cd00..fe675cb6b 100644 --- a/qt/tools/genhooks_gui.py +++ b/qt/tools/genhooks_gui.py @@ -488,6 +488,17 @@ def emptyNewCard(): received from the user before actually reading it. For example, you can replace new line in strings by some "\\\\n".""", ), + Hook( + name="addons_dialog_will_show", + args=["dialog: aqt.addons.AddonsDialog"], + doc="""Allows changing the add-on dialog before it is shown. E.g. add + buttons.""", + ), + Hook( + name="addons_dialog_did_change_selected_addon", + args=["dialog: aqt.addons.AddonsDialog", "add_on: aqt.addons.AddonMeta"], + doc="""Allows doing an action when a single add-on is selected.""", + ), # Other ################### Hook(