diff --git a/qt/aqt/addons.py b/qt/aqt/addons.py index 1bac9266b..b6d4b46db 100644 --- a/qt/aqt/addons.py +++ b/qt/aqt/addons.py @@ -345,7 +345,7 @@ and have been disabled: %(found)s" ###################################################################### def _installationErrorReport( - self, result: AddonInstallationResult, base: str, mode="download" + self, result: AddonInstallationResult, base: str, mode: str = "download" ) -> List[str]: messages = { @@ -370,7 +370,7 @@ and have been disabled: %(found)s" return [template % dict(base=name, id=name, error=msg)] def _installationSuccessReport( - self, result: AddonInstallationResult, base: str, mode="download" + self, result: AddonInstallationResult, base: str, mode: str = "download" ) -> List[str]: if mode == "download": # preserve old format strings for i18n @@ -385,7 +385,7 @@ and have been disabled: %(found)s" strings.append( _("The following conflicting add-ons were disabled:") + " " - + " ".join(result.conflicts) + + ", ".join(self.addonName(f) for f in result.conflicts) ) return strings @@ -666,7 +666,7 @@ class AddonsDialog(QDialog): def onGetAddons(self): GetAddons(self) - def onInstallFiles(self, paths: Optional[List[str]] = None, external: bool = False): + def onInstallFiles(self, paths: Optional[List[str]] = None): if not paths: key = _("Packaged Anki Add-on") + " (*{})".format(self.mgr.ext) paths = getFile( @@ -859,18 +859,20 @@ class ConfigEditor(QDialog): def installAddonPackages( addonsManager: AddonManager, paths: List[str], - parent: QWidget = None, - external: bool = False, + parent: Optional[QWidget] = None, + warn: bool = False, + strictly_modal: bool = False, + advise_restart: bool = False, ) -> bool: - if external: + if warn: names = ",
".join(f"{os.path.basename(p)}" for p in paths) q = _( "Important: As add-ons are programs downloaded from the internet, " "they are potentially malicious." "You should only install add-ons you trust.

" "Are you sure you want to proceed with the installation of the " - "following add-on(s)?

%(names)s" + "following Anki add-on(s)?

%(names)s" ) % dict(names=names) if ( not showInfo( @@ -888,11 +890,11 @@ def installAddonPackages( if log: log_html = "
".join(log) - if external: + if advise_restart: log_html += "

" + _( "Please restart Anki to complete the installation." ) - if len(log) == 1: + if len(log) == 1 and not strictly_modal: tooltip(log_html, parent=parent) else: showInfo( diff --git a/qt/aqt/main.py b/qt/aqt/main.py index 2cc6cf7ad..c041042f0 100644 --- a/qt/aqt/main.py +++ b/qt/aqt/main.py @@ -72,7 +72,7 @@ class AnkiQt(QMainWindow): self.safeMode = self.app.queryKeyboardModifiers() & Qt.ShiftModifier try: self.setupUI() - self.setupAddons() + self.setupAddons(args) except: showInfo(_("Error during startup:\n%s") % traceback.format_exc()) sys.exit(1) @@ -85,7 +85,7 @@ class AnkiQt(QMainWindow): ) ) # were we given a file to import? - if args and args[0]: + if args and args[0] and not self._isAddon(args[0]): self.onAppMsg(args[0]) # Load profile in a timer so we can let the window finish init and not # close on profile load error. @@ -334,7 +334,10 @@ close the profile or restart Anki.""" # import pending? if self.pendingImport: - self.handleImport(self.pendingImport) + if self._isAddon(self.pendingImport): + self.installAddon(self.pendingImport) + else: + self.handleImport(self.pendingImport) self.pendingImport = None runHook("profileLoaded") if onsuccess: @@ -747,10 +750,14 @@ title="%s" %s>%s""" % ( self.errorHandler = aqt.errors.ErrorHandler(self) - def setupAddons(self) -> None: + def setupAddons(self, args: Optional[List]) -> None: import aqt.addons self.addonManager = aqt.addons.AddonManager(self) + + if args and args[0] and self._isAddon(args[0]): + self.installAddon(args[0], startup=True) + if not self.safeMode: self.addonManager.loadAddons() @@ -1025,10 +1032,17 @@ QTreeWidget { # Installing add-ons from CLI / mimetype handler ########################################################################## - def installAddon(self, path): + def installAddon(self, path: str, startup: bool = False): from aqt.addons import installAddonPackages - installAddonPackages(self.addonManager, [path], external=True, parent=self) + installAddonPackages( + self.addonManager, + [path], + warn=True, + advise_restart=not startup, + strictly_modal=startup, + parent=None if startup else self, + ) # Cramming ########################################################################## @@ -1482,7 +1496,7 @@ will be lost. Continue?""" self.app.appMsg.connect(self.onAppMsg) def onAppMsg(self, buf: str) -> Optional[QTimer]: - is_addon = buf.endswith(".ankiaddon") + is_addon = self._isAddon(buf) if self.state == "startup": # try again in a second @@ -1531,6 +1545,9 @@ Please ensure a profile is open and Anki is not busy, then try again.""" return None + def _isAddon(self, buf: str) -> bool: + return buf.endswith(self.addonManager.ext) + # GC ########################################################################## # ensure gc runs in main thread