mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
164 lines
5.5 KiB
Python
164 lines
5.5 KiB
Python
# Copyright: Damien Elmes <anki@ichi2.net>
|
|
# -*- coding: utf-8 -*-
|
|
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|
|
|
import sys, os, re, traceback
|
|
from aqt.qt import *
|
|
from aqt.utils import showInfo, showWarning, openFolder, isWin
|
|
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)
|
|
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"))
|
|
|
|
def pluginsFolder(self):
|
|
dir = self.mw.config.confDir
|
|
if isWin:
|
|
dir = dir.encode(sys.getfilesystemencoding())
|
|
return os.path.join(dir, "addons")
|
|
|
|
def clearPluginCache(self):
|
|
"Clear .pyc files which may cause crashes if Python version updated."
|
|
dir = self.pluginsFolder()
|
|
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):
|
|
return
|