mirror of
https://github.com/ankitects/anki.git
synced 2025-09-25 01:06:35 -04:00
implement addons
This commit is contained in:
parent
6148a28bfb
commit
08134c2462
3 changed files with 89 additions and 139 deletions
224
aqt/addons.py
224
aqt/addons.py
|
@ -10,155 +10,105 @@ from anki.hooks import runHook
|
||||||
class AddonManager(object):
|
class AddonManager(object):
|
||||||
|
|
||||||
def __init__(self, mw):
|
def __init__(self, mw):
|
||||||
print "addons"
|
|
||||||
return
|
|
||||||
self.mw = mw
|
self.mw = mw
|
||||||
f = self.mw.form; s = SIGNAL("triggered()")
|
f = self.mw.form; s = SIGNAL("triggered()")
|
||||||
self.mw.connect(f.actionOpenPluginFolder, s, self.onOpenPluginFolder)
|
self.mw.connect(f.actionOpenPluginFolder, s, self.onOpenAddonFolder)
|
||||||
self.mw.connect(f.actionEnableAllPlugins, s, self.onEnableAllPlugins)
|
self.mw.connect(f.actionEnableAllPlugins, s, self.onEnableAllAddons)
|
||||||
self.mw.connect(f.actionDisableAllPlugins, s, self.onDisableAllPlugins)
|
self.mw.connect(f.actionDisableAllPlugins, s, self.onDisableAllAddons)
|
||||||
if isWin:
|
if isWin:
|
||||||
self.clearPluginCache()
|
self.clearAddonCache()
|
||||||
self.disableObsoletePlugins()
|
sys.path.insert(0, self.addonsFolder())
|
||||||
plugdir = self.pluginsFolder()
|
self.loadAddons()
|
||||||
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):
|
def loadAddons(self):
|
||||||
dir = self.mw.config.confDir
|
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:
|
if isWin:
|
||||||
dir = dir.encode(sys.getfilesystemencoding())
|
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."
|
"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 curdir, dirs, files in os.walk(dir):
|
||||||
for f in files:
|
for f in files:
|
||||||
if not f.endswith(".pyc"):
|
if not f.endswith(".pyc"):
|
||||||
continue
|
continue
|
||||||
os.unlink(os.path.join(curdir, f))
|
os.unlink(os.path.join(curdir, f))
|
||||||
|
|
||||||
def disableObsoletePlugins(self):
|
def registerAddon(self, name, updateId):
|
||||||
dir = self.pluginsFolder()
|
# not currently used
|
||||||
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
|
return
|
||||||
|
|
|
@ -58,7 +58,7 @@ Please do not file a bug report with Anki.<br>""")
|
||||||
self.mw.progress.clear()
|
self.mw.progress.clear()
|
||||||
if "abortSchemaMod" in error:
|
if "abortSchemaMod" in error:
|
||||||
return
|
return
|
||||||
if "plugin" in error:
|
if "addon" in error:
|
||||||
txt = pluginText
|
txt = pluginText
|
||||||
else:
|
else:
|
||||||
txt = stdText
|
txt = stdText
|
||||||
|
|
|
@ -23,6 +23,7 @@ metaConf = dict(
|
||||||
suppressUpdate=False,
|
suppressUpdate=False,
|
||||||
firstRun=True,
|
firstRun=True,
|
||||||
defaultLang=None,
|
defaultLang=None,
|
||||||
|
disabledAddons=[],
|
||||||
)
|
)
|
||||||
|
|
||||||
profileConf = dict(
|
profileConf = dict(
|
||||||
|
@ -33,7 +34,6 @@ profileConf = dict(
|
||||||
numBackups=30,
|
numBackups=30,
|
||||||
lastOptimize=intTime(),
|
lastOptimize=intTime(),
|
||||||
lang="en",
|
lang="en",
|
||||||
disabledAddons=[],
|
|
||||||
|
|
||||||
# editing
|
# editing
|
||||||
fullSearch=False,
|
fullSearch=False,
|
||||||
|
|
Loading…
Reference in a new issue