unihan = ChineseGenerator() def onFocusLost(fact, field): if field.name not in srcFields: return if findTag(cantoneseTag, fact.model.tags): type = "cantonese" elif findTag(mandarinTag, fact.model.tags): type = "mandarin" else: return idx = srcFields.index(field.name) dstField = dstFields[idx] try: if fact[dstField] and fact[dstField] != "<br />": return except: return fact[dstField] = unihan.toReading(type, field.value) addHook('fact.focusLost', onFocusLost) from ankiqt import mw mw.registerPlugin("Basic Chinese Support", 171)
from anki.hooks import addHook from ankiqt import mw def morphInit(): import morph.util import morph.manager import morph.exportMorphemes import morph.viewMorphemes import morph.massTagger import morph.setMatch import morph.auto mw.registerPlugin('Morph Man', 17201108172228) addHook('init', morphInit)
from ankiqt import ui from anki.hooks import addHook from ankiqt.ui import utils from ankiqt import mw from anki.facts import Fact from anki.utils import tidyHTML from PyQt4.QtCore import * from PyQt4.QtGui import * from PyQt4.QtWebKit import QWebPage import os import libxml2, urllib2, tempfile from urlparse import urljoin mw.registerPlugin("Incremental Reading", 22) # prepare urllib2 opener opener = urllib2.build_opener() opener.addheaders = [('User-agent', 'Mozilla/5.0')] __originalContextMenuEvent = None __originalFlush = None def onInit(): """ Plugin initialization: - replace context menu - replace flush method - add tools menu entry
newField.value = unicode(ifact.gloss.word) if newField.name == "Reading": newField.value = unicode(ifact.gloss.reading) if newField.name == "Meaning": newField.value = unicode(ifact.gloss.meaning) if newField.name == "From": newField.value = u'' for osnt in ifact.origSentences: newField.value = newField.value +\ unicode(osnt) +\ u'<br>' + ' -- ' + '<br>' outputDeck.addFact(f) outputDeck.save() def onJVocab(): mw.mainWin.jv = NewDeckDiag(mw) mw.mainWin.jv.show() def init(): mw.mainWin.jVocab = QAction('jVocab', mw) mw.connect(mw.mainWin.jVocab, SIGNAL('triggered()'), onJVocab) mw.mainWin.toolBar.addAction(mw.mainWin.jVocab) mw.registerPlugin("jVocab", 0.1) addHook('init', init)
if newField.name == "Expression": newField.value = unicode(ifact.gloss.word) if newField.name == "Reading": newField.value = unicode(ifact.gloss.reading) if newField.name == "Meaning": newField.value = unicode(ifact.gloss.meaning) if newField.name == "From": newField.value = u'' for osnt in ifact.origSentences: newField.value = newField.value +\ unicode(osnt) +\ u'<br>' + ' -- ' + '<br>' outputDeck.addFact(f) outputDeck.save() def onJVocab(): mw.mainWin.jv = NewDeckDiag(mw) mw.mainWin.jv.show() def init(): mw.mainWin.jVocab = QAction('jVocab', mw) mw.connect(mw.mainWin.jVocab, SIGNAL('triggered()'), onJVocab) mw.mainWin.toolBar.addAction(mw.mainWin.jVocab) mw.registerPlugin("jVocab", 0.1) addHook('init', init)
# -*- coding: utf-8 -*- #!/usr/bin/env python # # original author: Tymon Warecki # changes: Roland, [email protected] # License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html from ankiqt import mw def init(): import Japanese_audio.download mw.registerPlugin(u"Japanese audio download", 1) from anki.hooks import addHook addHook("init", init)
# Damien Elmes <*****@*****.**> # License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html # this plugin resizes images that are wider then the window to 100% of the # window width # version 1: initial release # version 1.1: added plugin registration (3/21/09) # version 1.2: changed from hooking on clearWindow to setBackground for # compatibility with Anki 1.1+ (1/22/11) from ankiqt.ui import view as v from anki.hooks import wrap from ankiqt import mw mw.registerPlugin("Resize Images", 10) def newClearWindow(self): self.write(''' <script type="text/javascript"> //<![CDATA[ var maxWidth = window.innerWidth-40; window.onload = function(){ var elements = document.getElementsByTagName("img"); for(i=0;i<elements.length;i++){ if(elements[i].width > maxWidth){ elements[i].style.width = "100%"; } } } //]]>
for item in q: count += 1 if count == size: count = 0 days += 1 seconds = 86400 * days # determine the current delay delay = now - item.combinedDue cards.append({'id': item[0], 'interval': item[1] + days + (delay / 86400.0), 'due': now + seconds}) # apply changes d.s.execute(""" update cards set interval = :interval, combinedDue = :due, isDue = 0 where id = :id""", cards) # rebuild d.flushMod() mw.reset() def init(): q = QAction(mw) q.setText("Postpone") mw.mainWin.menuTools.addAction(q) mw.connect(q, SIGNAL("triggered()"), postpone) mw.addHook("init", init) mw.registerPlugin("Postpone Reviews", 6)
evt.accept() return oldEventHandler(evt) def configureLogging(debug): global logger if not debug: class LoggerStub: def debug(self, s): pass logger = LoggerStub() return import logging logger = logging.getLogger(__name__) logger.addHandler(logging.FileHandler(LOG_FILENAME, delay=True)) logger.setLevel(logging.DEBUG) configureLogging(debug) # Would be much better if we could use a hook to modify this, and slightly # better if it was at least a list rather than a tuple: #anki.importing.Importers.append( [u"TypedTextImporter (*.txt)", TypedTextImporter] ) anki.importing.Importers = [ e for e in anki.importing.Importers ] anki.importing.Importers.insert( 0, [u"TypedTextImporter (*.txt)", TypedTextImporter] ) oldEventHandler = mw.keyPressEvent mw.keyPressEvent = newKeyPressEvent mw.registerPlugin("TypedTextImporter", 0) # vim: softtabstop=8 shiftwidth=8 expandtab
sock = urllib2.urlopen("http://ankiweb.net/file/search?t=1&c=1") data = sock.read() try: data = gzip.GzipFile(fileobj=cStringIO.StringIO(data)).read() except: # the server is sending gzipped data, but a transparent # proxy or antivirus software may be decompressing it # before we get it pass return simplejson.loads(unicode(data)) def check_for_updates(): registered = [] current = {} for val in mw.registeredPlugins.values(): registered.append(unicode(val['name'])) plugin_data = get_data() for plugin in plugin_data: if unicode(plugin[2]) in registered: current[plugin[2]] = plugin[9] raise Exception, '%s %s' % (registered, current) from ankiqt import mw mw.registerPlugin("Check Updates", 976) from anki.hooks import addHook addHook('init', check_for_updates)
searchword = field.value.lower().strip() try: if fact['Chinese Definition'] == "": # Generate if empty fact['Chinese Definition'] = findMandarinDef(searchword) except KeyError: pass try: if fact['English Definition'] == "": fact['English Definition'] = findEnglishDef(searchword) except KeyError: pass try: if fact['English Pronunciation'] == "": fact['English Pronunciation'] = findEnglishPro(searchword) except KeyError: pass addHook('fact.focusLost', onFocusLost) # Setup menu entries menu1 = QAction(mw) menu1.setText("Don't Fetch English Pronunciation Audio") mw.connect(menu1, SIGNAL("triggered()"),fetchAudioToggle) mw.mainWin.menuTools.addSeparator() mw.mainWin.menuTools.addAction(menu1) mw.registerPlugin("English Helper for Chinese", 0.08)
if not debug: class LoggerStub: def debug(self, s): pass logger = LoggerStub() return import logging logger = logging.getLogger(__name__) logger.addHandler(logging.FileHandler(LOG_FILENAME, delay=True)) logger.setLevel(logging.DEBUG) configureLogging(debug) # Would be much better if we could use a hook to modify this, and slightly # better if it was at least a list rather than a tuple: #anki.importing.Importers.append( [u"TypedTextImporter (*.txt)", TypedTextImporter] ) anki.importing.Importers = [e for e in anki.importing.Importers] anki.importing.Importers.insert( 0, [u"TypedTextImporter (*.txt)", TypedTextImporter]) oldEventHandler = mw.keyPressEvent mw.keyPressEvent = newKeyPressEvent mw.registerPlugin("TypedTextImporter", 0) # vim: softtabstop=8 shiftwidth=8 expandtab
# -*- coding: utf-8 -*- # Copyright: Arne Brasseur <*****@*****.**> # License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html """ Support for the Anki-logbook website Annikki.org. """ from ankiqt import mw from anki.hooks import addHook def annikki_init(): import annikki global ANNIKKI_INSTANCE ANNIKKI_INSTANCE = annikki.AnnikkiPlugin() mw.registerPlugin("Annikki", None) addHook("init", annikki_init)
def onFocusLost(fact, field): modelTag = "Esperanto" if not findTag(modelTag, fact.model.tags): return tmp = re.sub("cx", u"ĉ", field.value) tmp = re.sub("gx", u"ĝ", tmp) tmp = re.sub("hx", u"ĥ", tmp) tmp = re.sub("jx", u"ĵ", tmp) tmp = re.sub("sx", u"ŝ", tmp) tmp = re.sub("ux", u"ŭ", tmp) tmp = re.sub("Cx", u"Ĉ", tmp) tmp = re.sub("Gx", u"Ĝ", tmp) tmp = re.sub("Hx", u"Ĥ", tmp) tmp = re.sub("Jx", u"Ĵ", tmp) tmp = re.sub("Sx", u"Ŝ", tmp) tmp = re.sub("Ux", u"Ŭ", tmp) field.value = tmp fact[field.name] = tmp anki.stdmodels.models['Esperanto'] = EsperantoModel addHook('fact.focusLost', onFocusLost) mw.registerPlugin("Esperanto Support", 10)
for item in q: count += 1 if count == size: count = 0 days += 1 seconds = 86400 * days # determine the current delay delay = now - item.due cards.append({'id': item[0], 'interval': item[1] + days + (delay / 86400.0), 'due': now + seconds}) # apply changes mw.deck.s.execute(""" update cards set interval = :interval, due = :due, combinedDue = max(:due, spaceUntil), isDue = 0 where id = :id""", cards) # rebuild mw.reset() def init(): q = QAction(mw) q.setText("Postpone") mw.mainWin.menuTools.addAction(q) mw.connect(q, SIGNAL("triggered()"), postpone) mw.addHook("init", init) mw.registerPlugin("Postpone Reviews", 6)
NoWIfySyncThread = NoWifiSync(mw) def init_NoWifiSync(): """Initialises the Anki GUI to present an option to invoke the plugin.""" from PyQt4 import QtGui, QtCore # creates menu entry mw.mainWin.actionNDSync = QtGui.QAction('NDSync', mw) mw.mainWin.actionNDSync.setStatusTip('Sync with Anki.nds without wifi') mw.mainWin.actionNDSync.setEnabled(not not mw.deck) mw.connect(mw.mainWin.actionNDSync, QtCore.SIGNAL('triggered()'), NoWIfySyncThread.start) # adds the plugin icons in the Anki Toolbar mw.mainWin.toolBar.addAction(mw.mainWin.actionNDSync) # to enable or disable Jstats whenever a deck is opened/closed mw.deckRelatedMenuItems = mw.deckRelatedMenuItems + ("NDSync",) if __name__ == "__main__": print "Don't run me : I'm an Anki plugin." else: # adds NoWifiSync to the list of plugin to process in Anki mw.addHook('init', init_NoWifiSync) mw.registerPlugin("Button to Sync with Anki.nds without wifi", 668)
# -*- coding: utf-8 -*- # Copyright: Damien Elmes <*****@*****.**> # License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html # this plugin allows you to redefine the keys used to answer cards. it defines # 'x' as a failed answer and 'y' as a correct answer. # version 1: initial release from ankiqt import mw def newEventHandler(evt): if mw.state == "showAnswer": key = unicode(evt.text()) if key == "x": evt.accept() return mw.cardAnswered(1) if key == "y": evt.accept() return mw.cardAnswered(4) return oldEventHandler(evt) oldEventHandler = mw.keyPressEvent mw.keyPressEvent = newEventHandler mw.registerPlugin("Change Keys", 7)
from anki.hooks import addHook from ankiqt import mw def morphInit(): import morph.util import morph.manager import morph.exportMorphemes import morph.viewMorphemes import morph.massTagger import morph.setMatch import morph.auto mw.registerPlugin("Morph Man", 17201108172228) addHook("init", morphInit)
# -*- coding: utf-8 -*- # Copyright: Damien Elmes <*****@*****.**> # License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html # # This plugin lets you change the graph colours. # from ankiqt import mw from anki import graphs as g mw.registerPlugin("Graph Colours", 11) # These are the standard graph colours. Uncomment the lines you want to # customize the colours. # # g.dueYoungC = "#ffb380" # g.dueMatureC = "#ff5555" # g.dueCumulC = "#ff8080" # # g.reviewNewC = "#80b3ff" # g.reviewYoungC = "#5555ff" # g.reviewMatureC = "#0f5aff" # g.reviewTimeC = "#0fcaff" # # g.easesNewC = "#80b3ff" # g.easesYoungC = "#5555ff" # g.easesMatureC = "#0f5aff" # # g.addedC = "#b3ff80" # g.firstC = "#b380ff" # g.intervC = "#80e5ff"
from anki.hooks import addHook from ankiqt import mw def setup(): import learnX.interface.main mw.registerPlugin( 'LearnX', 17201108172229 ) addHook('init', setup)
def resetTimer(): notify('resetting timer') global pressReplyButtonTimer pressReplyButtonTimer.cancel() pressReplyButtonTimer = Timer(secondsUntilReply, pressReplyButton) pressReplyButtonTimer.start() def stopTimer(): notify('stopping timer') global pressReplyButtonTimer pressReplyButtonTimer.cancel() def onPreMoveToState(self, state): notify('move to state') if state in ["showAnswer"]: resetTimer() elif state in ["editCurrentFact", "studyScreen"]: stopTimer() addHook('showQuestion', stopTimer) addHook('deckFinished', stopTimer) addHook('deckClosed', stopTimer) addHook('quit', stopTimer) AnkiQt.moveToState = wrap(AnkiQt.moveToState, onPreMoveToState, pos="before") # register plugin mw.registerPlugin('pluginName', 2012030802)
def gloss(expr): if type(expr) != unicode: expr = unicode(expr) print 'glossing:', expr x = fetchGloss(expr) u = unicode(x, 'utf-8', errors='ignore') ls = re.findall('<li>(.*?)</li>', u) return u'<br>\n'.join(ls) from PyQt4.QtCore import * from PyQt4.QtGui import * from anki.hooks import addHook from anki.facts import Fact from ankiqt import mw mw.registerPlugin('jmrGloss', 2011012917) #### Update facts with gloss def glossFact(f): if f['Gloss']: return f['Gloss'] = gloss(f['Expression']) def setupMenu(ed): a = QAction('Regenerate Glosses', ed) ed.connect(a, SIGNAL('triggered()'), lambda e=ed: onRegenGlosses(e)) ed.dialog.menuActions.addSeparator() ed.dialog.menuActions.addAction(a)
from anki.hooks import addHook from ankiqt import mw def morphInit(): import morph.util import morph.manager import morph.exportMorphemes import morph.viewMorphemes import morph.massTagger import morph.setMatch import morph.auto mw.registerPlugin( 'Morph Man', 17201108172228 ) addHook( 'init', morphInit )
from ankiqt import mw from ankiqt.ui.main import AnkiQt from anki.hooks import wrap from anki import sound import os from threading import Timer d = { 6.0:'SuperMarioBrothers-OutOfTime.mp3' , 10.0:'GameshowBellDing3.mp3' } basePath = mw.pluginsFolder() + os.sep + 'timerSounds' ts = [] # :: FilePath -> Audio () def play( sPath ): path = basePath + os.sep + sPath path = path.replace( os.sep, os.sep*2 ) # fix for windows print 'playing:', path sound.play( path ) # :: AnkiQt -> Response -> m () def onPreCardAnswered( self, r ): print 'resetting timers' global ts [ t.cancel() for t in ts ] ts = [ Timer( dur, play, args=[path] ) for dur,path in d.items() ] [ t.start() for t in ts ] AnkiQt.cardAnswered = wrap(AnkiQt.cardAnswered, onPreCardAnswered, pos="before") mw.registerPlugin( 'jmrTimer', 2011012918 )
NoWIfySyncThread = NoWifiSync(mw) def init_NoWifiSync(): """Initialises the Anki GUI to present an option to invoke the plugin.""" from PyQt4 import QtGui, QtCore # creates menu entry mw.mainWin.actionNDSync = QtGui.QAction('NDSync', mw) mw.mainWin.actionNDSync.setStatusTip('Sync with Anki.nds without wifi') mw.mainWin.actionNDSync.setEnabled(not not mw.deck) mw.connect(mw.mainWin.actionNDSync, QtCore.SIGNAL('triggered()'), NoWIfySyncThread.start) # adds the plugin icons in the Anki Toolbar mw.mainWin.toolBar.addAction(mw.mainWin.actionNDSync) # to enable or disable Jstats whenever a deck is opened/closed mw.deckRelatedMenuItems = mw.deckRelatedMenuItems + ("NDSync", ) if __name__ == "__main__": print "Don't run me : I'm an Anki plugin." else: # adds NoWifiSync to the list of plugin to process in Anki mw.addHook('init', init_NoWifiSync) mw.registerPlugin("Button to Sync with Anki.nds without wifi", 668)
# adds the plugin icons in the Anki Toolbar mw.mainWin.toolBar.addAction(mw.mainWin.actionJxMenu) mw.mainWin.toolBar.addAction(mw.mainWin.actionJxGraphs) # to enable or disable Jstats whenever a deck is opened/closed mw.deckRelatedMenuItems = mw.deckRelatedMenuItems + ("JxMenu","JxGraphs",) # Adding features through hooks ! mw.addHook('drawAnswer', append_JxPlugin) # additional info in answer cards mw.addHook('deckClosed', JxWindow.hide) # hides the main Jxplugin window when the current deck is closed # adds JxPlugin to the list of plugin to process in Anki mw.addHook('init', init_JxPlugin) mw.registerPlugin("Japanese Extended Support", 666) # let's overload the loadDeck function as there isn't any hook oldLoadDeck = mw.loadDeck def newLoadDeck(deckPath, sync=True, interactive=True, uprecent=True,media=None): code = oldLoadDeck(deckPath, sync, interactive, uprecent,media) if code and mw.deck: from database import build_JxDeck build_JxDeck() return code mw.loadDeck = newLoadDeck # The main JxPlugin Windows # funny, you cannot import stuff after these statements from controls import JxWindow from controls import JxPreview
epwingLookup(mw.currentCard.fact['Meaning']) def lookupS(): mw.initLookup() mw.lookup.selection(epwingLookup) # remove the standard lookup links ml = mw.mainWin.menu_Lookup for i in ("expr", "mean", "as", "es", "esk"): ml.removeAction(getattr(mw.mainWin, "actionLookup_" + i)) # add custom links q = QAction(mw) q.setText("..question") q.setShortcut(_("Ctrl+1")) ml.addAction(q) mw.connect(q, SIGNAL("triggered()"), lookupQ) a = QAction(mw) a.setText("..answer") a.setShortcut(_("Ctrl+2")) ml.addAction(a) mw.connect(a, SIGNAL("triggered()"), lookupA) s = QAction(mw) s.setText("..selection") s.setShortcut(_("Ctrl+3")) ml.addAction(s) mw.connect(s, SIGNAL("triggered()"), lookupS) mw.registerPlugin("Custom Dictionary Lookup", 5)
if mw.trayIcon.ti.isVisible(): mw.trayIcon.hideAll(); event.ignore(); def myTrayActivated(reason): if reason != QtGui.QSystemTrayIcon.Context: if mw.trayIcon.anki_visible: mw.trayIcon.hideAll() else: mw.trayIcon.showAll() if __name__ == "__main__": print "Don't run me. I'm a plugin." else: mw.registerPlugin("Minimize to Tray", 1) if not mw.config['showTrayIcon']: ans = ui.utils.askUser("Minimize to tray plugin needs tray icon option " "enabled.\nWould you like to enable it?") if ans: mw.config['showTrayIcon'] = True mw.config.save() mw.setupTray() if mw.config['showTrayIcon']: mw.quit = quit mw.closeEvent = myCloseEvent mw.trayIcon.activated = myTrayActivated mw.addHook('init', init_hook) print 'Minimize to tray plugin loaded' else:
# -*- coding: utf-8 -*- # Copyright: Phan Quoc Huy # License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html def init(): import vietnamese.model import vietnamese.offline import vietnamese.online from ankiqt import mw mw.registerPlugin("JpEnVi Support", 173) from anki.hooks import addHook addHook('init', init)
global replace replace = False global pressAnswerButtonTimer pressAnswerButtonTimer.cancel() pressAnswerButtonTimer = Timer(secondsUntilAnswer, pressAnswerButton) pressAnswerButtonTimer.start() def stopTimer(): notify("stopping timer") global pressAnswerButtonTimer pressAnswerButtonTimer.cancel() def onPreMoveToState(self, state): notify("move to state") if state in ["showAnswer", "editCurrentFact", "studyScreen"]: stopTimer() addHook("showQuestion", resetTimer) addHook("deckFinished", stopTimer) addHook("deckClosed", stopTimer) addHook("quit", stopTimer) AnkiQt.moveToState = wrap(AnkiQt.moveToState, onPreMoveToState, pos="before") # register plugin mw.registerPlugin("autoAnswer", 2011100501)
# -*- coding: utf-8 -*- # Copyright: Damien Elmes <*****@*****.**> # License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html # # This plugin keeps Anki on top of other windows. from ankiqt import mw from PyQt4.QtCore import * from PyQt4.QtGui import * mw.setWindowFlags(Qt.WindowStaysOnTopHint) mw.show() mw.registerPlugin("Always On Top", 9)
l = struct.pack("I", len(srs)) c.sendall(l) c.sendall(srs) c.close() mw.loadDeck(mw.deck.path, sync=False) def ScoreCard(id, ease, reps): card = mw.deck.cardFromId(id) # not equal means it was reviewed on anki at some point so ditch the change if card.reps == reps: mw.deck.answerCard(card, ease) mw.registerPlugin("Syncing with Anki.nds", 667) print 'DsSync Plugin loaded' mythread=DSSyncThread(mw) # should ovrload opening of deck/closing of deck and make it run/stop there mythread.start()# for the time being, it runs and never stops...
def markAndDelete(): undo = _("MarkDelete") mw.deck.setUndoStart(undo) mw.currentCard.fact.tags = canonifyTags(mw.currentCard.fact.tags + "," + "MarkDelete") mw.currentCard.fact.setModified() mw.deck.updateFactTags([mw.currentCard.fact.id]) mw.deck.deleteCard(mw.currentCard.id) mw.reset() mw.deck.setUndoEnd(undo) act = QAction(mw) act.setText("Mark and &Delete") icon = QIcon() icon.addPixmap(QPixmap(":/icons/editdelete.png")) act.setIcon(icon) mw.connect(act, SIGNAL("triggered()"), markAndDelete) old = mw.mainWin.actionDelete act.setEnabled(old.isEnabled()) mw.mainWin.menuEdit.removeAction(mw.mainWin.actionDelete) mw.mainWin.menuEdit.addAction(act) # make sure it's enabled/disabled mw.mainWin.actionDelete = act mw.registerPlugin("Mark and Delete", 8)
# -*- coding: utf-8 -*- # Copyright: Damien Elmes <*****@*****.**> # License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html def init(): import japanese.model import japanese.furigana import japanese.reading import japanese.lookup import japanese.stats import japanese.bulkreading from ankiqt import mw mw.registerPlugin("Japanese Support", 172) from anki.hooks import addHook addHook('init', init)
# -*- coding: utf-8 -*- # Copyright: Damien Elmes <*****@*****.**> # License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html # Add an icon to the toolbar. Adds a separator and 'suspend card' by default. # version 1: initial release from PyQt4.QtCore import * from PyQt4.QtGui import * from ankiqt import mw def init(): mw.mainWin.toolBar.addSeparator() mw.mainWin.toolBar.addAction(mw.mainWin.actionSuspendCard) mw.addHook("init", init) mw.registerPlugin("Add to Toolbar", 13)
# reading is sometimes missing if not f['Reading'] and kakasi: f['Reading'] = kakasi.toFurigana(f['Expression']) except KeyError: f['Reading'] = u"" if includeSounds and sen['sound']: (file, headers) = urllib.urlretrieve(sen['sound']) path = mw.deck.addMedia(file) f['Audio'] = u'[sound:%s]' % path else: f['Audio'] = u"" if includeImages and sen['image']: (file, headers) = urllib.urlretrieve(sen['image']) path = mw.deck.addMedia(file) f['Image'] = u'<img src="%s">' % path else: f['Image'] = u"" mw.deck.addFact(f) diag.cancel() mw.deck.save() act = QAction(mw) act.setText("Smart.fm Import") mw.connect(act, SIGNAL("triggered()"), doImport) mw.mainWin.menuTools.addSeparator() mw.mainWin.menuTools.addAction(act) mw.registerPlugin("Smart.fm Sentence Importer", 1)
return self.unihan.reading(val) except: return u"" unihan = ChineseGenerator() def onFocusLost(fact, field): if field.name not in srcFields: return if findTag(cantoneseTag, fact.model.tags): type = "cantonese" elif findTag(mandarinTag, fact.model.tags): type = "mandarin" else: return idx = srcFields.index(field.name) dstField = dstFields[idx] try: if fact[dstField]: return except: return fact[dstField] = unihan.toReading(type, field.value) addHook('fact.focusLost', onFocusLost) from ankiqt import mw mw.registerPlugin("Basic Chinese Support", 171)
prioritySubMenu.addAction(prioLow) prioritySubMenu.addAction(prioNormal) # The core workings of the plugin. # Since Anki doesn't provide access to the HasTag() function, I essentially have to just delete and recreate the tags for each instance. def priorityVeryHigh(editor): editor.deleteTags(tags=PRIORITYVERYHIGH, label=False) editor.deleteTags(tags=PRIORITYHIGH, label=False) editor.deleteTags(tags=PRIORITYLOW, label=False) editor.addTags(tags=PRIORITYVERYHIGH, label=False,) def priorityHigh(editor): editor.deleteTags(tags=PRIORITYVERYHIGH, label=False) editor.deleteTags(tags=PRIORITYHIGH, label=False) editor.deleteTags(tags=PRIORITYLOW, label=False) editor.addTags(tags=PRIORITYHIGH, label=False,) def priorityLow(editor): editor.deleteTags(tags=PRIORITYVERYHIGH, label=False) editor.deleteTags(tags=PRIORITYHIGH, label=False) editor.deleteTags(tags=PRIORITYLOW, label=False) editor.addTags(tags=PRIORITYLOW, label=False,) def priorityNormal(editor): editor.deleteTags(tags=PRIORITYVERYHIGH, label=False) editor.deleteTags(tags=PRIORITYHIGH, label=False) editor.deleteTags(tags=PRIORITYLOW, label=False) addHook("editor.setupMenus", setupMenu) mw.registerPlugin("Priority Switcher", 19)
from PyQt4.QtCore import * from PyQt4.QtGui import * from ankiqt import mw from anki.hooks import addHook from anki.cards import Card def setupMenu(editor): resetl = QAction("Reset Leeches zomg", editor) resetl.setEnabled(True) resetl.setText("Reset Leech") editor.connect(resetl, SIGNAL("triggered()"), lambda e=editor: resetLeech(e)) editor.dialog.menuActions.addSeparator() editor.dialog.menuActions.addAction(resetl) def resetLeech(editor): # Reps(known as "Reviews" inside of Anki) is set # to 1 instead of 0 because of a generic # database error. editor.currentCard.reps = 1 editor.deleteTags(tags="Leech", label=False) editor.onSuspend(sus=False) addHook("editor.setupMenus", setupMenu) mw.registerPlugin("Reset Leech", 18)
def newRedisplay(self): """If we are showing the hint, display the answer. We will filter away the ANSWER_FIELDS with a hook.""" # This mirrors View.redisplay's "showAnswer" state. if self.state == "showHint": self.setBackground() if not self.main.currentCard.cardModel.questionInAnswer: self.drawQuestion(nosound=True) if self.drawRule: self.write("<hr>") self.drawAnswer() self.flush() def filterHint(a, currentCard): """If we are showing the hint, filter out the ANSWER_FIELDS""" if mw.state == "showHint": fieldIDs = ["fm" + hexifyID(field.id) for field in currentCard.fact.model.fieldModels if field.name in ANSWER_FIELDS] for fid in fieldIDs: p = re.compile('<span class="%s">' % fid) a = p.sub('<span class="%s" style="visibility:hidden">' % fid, a, re.IGNORECASE) return a addHook("drawAnswer", filterHint) AnkiQt.keyPressEvent = wrap(AnkiQt.keyPressEvent, newKeyPressEvent, "around") View.redisplay = wrap(View.redisplay, newRedisplay, "after") mw.registerPlugin("Hint-peeking", 10)
evt.accept() return mw.onUndo() if (key) and (key >= "1") and (key <= "7"): press = int(key) evt.accept() if mw.state == "showQuestion": # if we are on the question jump to the answer return mw.mainWin.showAnswerButton.click() defaultpress=mw.defaultEaseButton() if (press == 3): # Redefine 3 as whatever the default key is press = defaultpress if (press == 4) and (defaultpress==2): # lower by one if reccomendation is "hard" and you chose "easy" press = 3 if (press == 6): # reset the original 3 as 6 press = 3 if (press == 7): # reset the original 4 as 7 press = 4 if mw.state == "showAnswer": # push an answer button return mw.cardAnswered(press) return oldEventHandler(evt) oldEventHandler = mw.keyPressEvent mw.keyPressEvent = newEventHandler mw.registerPlugin("Faster-Keys", 7)
from ankiqt import mw import anki.deck # make random review order instead order cards by when they were first answered def revOrder( self ): return ( 'priority desc, interval desc', 'priority desc, interval', 'priority desc, combinedDue', 'priority desc, firstAnswered', )[ self.revCardOrder ] anki.deck.Deck.revOrder = revOrder mw.registerPlugin( 'First answered rev order', 2012062517 )
searchword = field.value.lower().strip() try: if fact['Chinese Definition'] == "": # Generate if empty fact['Chinese Definition'] = findMandarinDef(searchword) except KeyError: pass try: if fact['English Definition'] == "": fact['English Definition'] = findEnglishDef(searchword) except KeyError: pass try: if fact['English Pronunciation'] == "": fact['English Pronunciation'] = findEnglishPro(searchword) except KeyError: pass addHook('fact.focusLost', onFocusLost) # Setup menu entries menu1 = QAction(mw) menu1.setText("Don't Fetch English Pronunciation Audio") mw.connect(menu1, SIGNAL("triggered()"),fetchAudioToggle) mw.mainWin.menuTools.addSeparator() mw.mainWin.menuTools.addAction(menu1) mw.registerPlugin("English Helper for Chinese zh-tw", 0.10)
event.ignore() def myTrayActivated(reason): if reason != QtGui.QSystemTrayIcon.Context: if mw.trayIcon.anki_visible: mw.trayIcon.hideAll() else: mw.trayIcon.showAll() if __name__ == "__main__": print "Don't run me. I'm a plugin." else: mw.registerPlugin("Minimize to Tray", 1) if not mw.config['showTrayIcon']: ans = ui.utils.askUser( "Minimize to tray plugin needs tray icon option " "enabled.\nWould you like to enable it?") if ans: mw.config['showTrayIcon'] = True mw.config.save() mw.setupTray() if mw.config['showTrayIcon']: mw.quit = quit mw.closeEvent = myCloseEvent mw.trayIcon.activated = myTrayActivated mw.addHook('init', init_hook) print 'Minimize to tray plugin loaded'