implement addons

This commit is contained in:
Damien Elmes 2011-12-08 04:38:47 +09:00
parent 6148a28bfb
commit 08134c2462
3 changed files with 89 additions and 139 deletions

View file

@ -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

View file

@ -58,7 +58,7 @@ Please do not file a bug report with Anki.<br>""")
self.mw.progress.clear()
if "abortSchemaMod" in error:
return
if "plugin" in error:
if "addon" in error:
txt = pluginText
else:
txt = stdText

View file

@ -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,