diff --git a/qt/aqt/addons.py b/qt/aqt/addons.py index 51ba38f63..baa13137c 100644 --- a/qt/aqt/addons.py +++ b/qt/aqt/addons.py @@ -426,7 +426,9 @@ class AddonManager: conflicts = manifest.get("conflicts", []) found_conflicts = self._disableConflicting(package, conflicts) meta = self.addonMeta(package) + gui_hooks.addon_manager_will_install_addon(self, package) self._install(package, zfile) + gui_hooks.addon_manager_did_install_addon(self, package) schema = self._manifest_schema["properties"] manifest_meta = { @@ -450,10 +452,11 @@ class AddonManager: base = self.addonsFolder(module) if os.path.exists(base): self.backupUserFiles(module) - if not self.deleteAddon(module): + try: + self.deleteAddon(module) + except Exception: self.restoreUserFiles(module) - return - + raise os.mkdir(base) self.restoreUserFiles(module) @@ -469,17 +472,8 @@ class AddonManager: continue zfile.extract(n, base) - # true on success - def deleteAddon(self, module: str) -> bool: - try: - send_to_trash(Path(self.addonsFolder(module))) - return True - except OSError as e: - showWarning( - tr.addons_unable_to_update_or_delete_addon(val=str(e)), - textFormat="plain", - ) - return False + def deleteAddon(self, module: str) -> None: + send_to_trash(Path(self.addonsFolder(module))) # Processing local add-on files ###################################################################### @@ -912,12 +906,17 @@ class AddonsDialog(QDialog): if not askUser(tr.addons_delete_the_numd_selected_addon(count=len(selected))): return gui_hooks.addons_dialog_will_delete_addons(self, selected) - for module in selected: - # doing this before deleting, as `enabled` is always True afterwards - if self.mgr.addon_meta(module).enabled: - self._require_restart = True - if not self.mgr.deleteAddon(module): - break + try: + for module in selected: + # doing this before deleting, as `enabled` is always True afterwards + if self.mgr.addon_meta(module).enabled: + self._require_restart = True + self.mgr.deleteAddon(module) + except OSError as e: + showWarning( + tr.addons_unable_to_update_or_delete_addon(val=str(e)), + textFormat="plain", + ) self.form.addonList.clearSelection() self.redrawAddons() diff --git a/qt/tools/genhooks_gui.py b/qt/tools/genhooks_gui.py index db8ff4629..7e049ee50 100644 --- a/qt/tools/genhooks_gui.py +++ b/qt/tools/genhooks_gui.py @@ -1211,6 +1211,22 @@ gui_hooks.webview_did_inject_style_into_page.append(mytest) args=["dialog: aqt.addons.AddonsDialog", "ids: list[str]"], doc="""Allows doing an action before an add-on is deleted.""", ), + Hook( + name="addon_manager_will_install_addon", + args=["manager: aqt.addons.AddonManager", "module: str"], + doc="""Called before installing or updating an addon. + + Can be used to release DB connections or open files that + would prevent an update from succeeding.""", + ), + Hook( + name="addon_manager_did_install_addon", + args=["manager: aqt.addons.AddonManager", "module: str"], + doc="""Called after installing or updating an addon. + + Can be used to restore DB connections or open files after + an add-on has been updated.""", + ), # Model ################### Hook(