From 08134c24628855770d4db5a5f29ad1400e7f3b11 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Thu, 8 Dec 2011 04:38:47 +0900 Subject: [PATCH] implement addons --- aqt/addons.py | 224 +++++++++++++++++++----------------------------- aqt/errors.py | 2 +- aqt/profiles.py | 2 +- 3 files changed, 89 insertions(+), 139 deletions(-) diff --git a/aqt/addons.py b/aqt/addons.py index fbc1bccbc..d82ad814e 100644 --- a/aqt/addons.py +++ b/aqt/addons.py @@ -10,155 +10,105 @@ from anki.hooks import runHook class AddonManager(object): def __init__(self, mw): - print "addons" - return self.mw = mw f = self.mw.form; s = SIGNAL("triggered()") - self.mw.connect(f.actionOpenPluginFolder, s, self.onOpenPluginFolder) - self.mw.connect(f.actionEnableAllPlugins, s, self.onEnableAllPlugins) - self.mw.connect(f.actionDisableAllPlugins, s, self.onDisableAllPlugins) + self.mw.connect(f.actionOpenPluginFolder, s, self.onOpenAddonFolder) + self.mw.connect(f.actionEnableAllPlugins, s, self.onEnableAllAddons) + self.mw.connect(f.actionDisableAllPlugins, s, self.onDisableAllAddons) if isWin: - self.clearPluginCache() - self.disableObsoletePlugins() - plugdir = self.pluginsFolder() - sys.path.insert(0, plugdir) - plugins = self.enabledPlugins() - plugins.sort() - self.registeredPlugins = {} - for plugin in plugins: - try: - nopy = plugin.replace(".py", "") - __import__(nopy) - except: - print "Error in %s" % plugin - traceback.print_exc() - self.rebuildPluginsMenu() - # run the obsolete init hook - try: - runHook('init') - except: - showWarning( - _("Broken plugin:\n\n%s") % - unicode(traceback.format_exc(), "utf-8", "replace")) + self.clearAddonCache() + sys.path.insert(0, self.addonsFolder()) + self.loadAddons() - def pluginsFolder(self): - dir = self.mw.config.confDir + def loadAddons(self): + on, off = self.files() + for file in on: + try: + __import__(file.replace(".py", "")) + except: + traceback.print_exc() + self.rebuildAddonsMenu() + + # Menus + ###################################################################### + + def rebuildAddonsMenu(self): + if getattr(self, "addonActions", None) is None: + self.addonActions = [] + for action in self.addonActions: + self.mw.form.menuStartup.removeAction(action) + self.addonActions = [] + on, off = self.files() + def addObjs(l, enabled): + l.sort() + for file in l: + p = re.sub("\.py(\.off)?", "", file) + a = QAction(p, self.mw) + a.setCheckable(True) + a.setChecked(enabled) + self.mw.connect(a, SIGNAL("triggered()"), + lambda f=file: self.toggleAddon(f)) + self.mw.form.menuStartup.addAction(a) + self.addonActions.append(a) + addObjs(on, True) + addObjs(off, False) + + def onOpenAddonFolder(self, path=None): + if path is None: + path = self.addonsFolder() + openFolder(path) + + # Enabled/disabled list + ###################################################################### + + def files(self): + on = [] + off = [] + for f in os.listdir(self.addonsFolder()): + if not f.endswith(".py"): + continue + if f in self.mw.pm.meta['disabledAddons']: + off.append(f) + else: + on.append(f) + return on, off + + def onEnableAllAddons(self): + self.mw.pm.meta['disabledAddons'] = [] + self.mw.pm.save() + self.rebuildAddonsMenu() + + def onDisableAllAddons(self): + on, off = self.files() + self.mw.pm.meta['disabledAddons'] = on + off + self.rebuildAddonsMenu() + + def toggleAddon(self, file): + if file in self.mw.pm.meta['disabledAddons']: + self.mw.pm.meta['disabledAddons'].remove(file) + else: + self.mw.pm.meta['disabledAddons'].append(file) + self.mw.pm.save() + self.rebuildAddonsMenu() + + # Tools + ###################################################################### + + def addonsFolder(self): + dir = self.mw.pm.addonFolder() if isWin: dir = dir.encode(sys.getfilesystemencoding()) - return os.path.join(dir, "addons") + return dir - def clearPluginCache(self): + def clearAddonCache(self): "Clear .pyc files which may cause crashes if Python version updated." - dir = self.pluginsFolder() + dir = self.addonsFolder() for curdir, dirs, files in os.walk(dir): for f in files: if not f.endswith(".pyc"): continue os.unlink(os.path.join(curdir, f)) - def disableObsoletePlugins(self): - dir = self.pluginsFolder() - native = _( - "The %s plugin has been disabled, as Anki supports "+ - "this natively now.") - plugins = [ - ("Custom Media Directory.py", - (native % "custom media folder") + _(""" \ -Please visit Settings>Preferences.""")), - ("Regenerate Reading Field.py", _("""\ -The regenerate reading field plugin has been disabled, as the Japanese \ -support plugin supports this now. Please download the latest version.""")), - ("Sync LaTeX with iPhone client.py", - native % "sync LaTeX"), - ("Incremental Reading.py", - _("""The incremental reading plugin has been disabled because \ -it needs updates.""")), - ("Learn Mode.py", _("""\ -The learn mode plugin has been disabled because it needs to be rewritten \ -to work with this version of Anki.""")) - ] - for p in plugins: - path = os.path.join(dir, p[0]) - if os.path.exists(path): - new = path.replace(".py", ".disabled") - if os.path.exists(new): - os.unlink(new) - os.rename(path, new) - showInfo(p[1]) - - def rebuildPluginsMenu(self): - if getattr(self, "pluginActions", None) is None: - self.pluginActions = [] - for action in self.pluginActions: - self.mw.form.menuStartup.removeAction(action) - all = self.allPlugins() - all.sort() - for fname in all: - enabled = fname.endswith(".py") - p = re.sub("\.py(\.off)?", "", fname) - if p+".py" in self.registeredPlugins: - p = self.registeredPlugins[p+".py"]['name'] - a = QAction(p, self.mw) - a.setCheckable(True) - a.setChecked(enabled) - self.mw.connect(a, SIGNAL("triggered()"), - lambda fname=fname: self.togglePlugin(fname)) - self.mw.form.menuStartup.addAction(a) - self.pluginActions.append(a) - - def enabledPlugins(self): - return [p for p in os.listdir(self.pluginsFolder()) - if p.endswith(".py")] - - def disabledPlugins(self): - return [p for p in os.listdir(self.pluginsFolder()) - if p.endswith(".py.off")] - - def allPlugins(self): - return [p for p in os.listdir(self.pluginsFolder()) - if p.endswith(".py.off") or p.endswith(".py")] - - def onOpenPluginFolder(self, path=None): - if path is None: - path = self.pluginsFolder() - openFolder(path) - - def enablePlugin(self, p): - pd = self.pluginsFolder() - old = os.path.join(pd, p) - new = os.path.join(pd, p.replace(".off", "")) - try: - os.unlink(new) - except: - pass - os.rename(old, new) - - def disablePlugin(self, p): - pd = self.pluginsFolder() - old = os.path.join(pd, p) - new = os.path.join(pd, p.replace(".py", ".py.off")) - try: - os.unlink(new) - except: - pass - os.rename(old, new) - - def onEnableAllPlugins(self): - for p in self.disabledPlugins(): - self.enablePlugin(p) - self.rebuildPluginsMenu() - - def onDisableAllPlugins(self): - for p in self.enabledPlugins(): - self.disablePlugin(p) - self.rebuildPluginsMenu() - - def togglePlugin(self, plugin): - if plugin.endswith(".py"): - self.disablePlugin(plugin) - else: - self.enablePlugin(plugin) - self.rebuildPluginsMenu() - - def registerPlugin(self, name, updateId): + def registerAddon(self, name, updateId): + # not currently used return diff --git a/aqt/errors.py b/aqt/errors.py index 258ee520c..a54cce386 100644 --- a/aqt/errors.py +++ b/aqt/errors.py @@ -58,7 +58,7 @@ Please do not file a bug report with Anki.
""") self.mw.progress.clear() if "abortSchemaMod" in error: return - if "plugin" in error: + if "addon" in error: txt = pluginText else: txt = stdText diff --git a/aqt/profiles.py b/aqt/profiles.py index 1a53d6fed..c02406ebf 100644 --- a/aqt/profiles.py +++ b/aqt/profiles.py @@ -23,6 +23,7 @@ metaConf = dict( suppressUpdate=False, firstRun=True, defaultLang=None, + disabledAddons=[], ) profileConf = dict( @@ -33,7 +34,6 @@ profileConf = dict( numBackups=30, lastOptimize=intTime(), lang="en", - disabledAddons=[], # editing fullSearch=False,