Example #1
0
 def __init__(self):
     AnkiQt.moveToState = wrap(AnkiQt.moveToState, AnkiQt_moveToState(self), "before")
     Deck.answerCard = wrap(Deck.answerCard, Deck_answerCard(self), "after")
     self.config = config.Config(mw.config)
     self.api = AnnikkiClient(self, self.config)
     self.setup_ui()
     self.cards_answered = []
Example #2
0
    def __init__(self):

        # Setup
        self.db = DBConnect()
        self.__treasureChest = TreasureChest(self.db)
        self.__options = Options(self.db)
        self.__eventManager = EventManager(self, self.__options, self.__treasureChest)
        self.__stats = Stats(self.db, self.__eventManager)
        world = World(self.db, self.__options.getOption('activeCountry'))
        self.__buildingAuthority = BuildingAuthority(self, world)
        self.__ranks = Ranks(self.db, self.__eventManager, world)
        self.__ranks.updateRank(self.__treasureChest.getTotalGold(), self.__buildingAuthority.getActiveCountry().getCompletedObjectsPercentage(), True)
        self.__layout = None    # Setup as a property as we must be able to clear it
        self.__view = None  # Keep's track of current view. Useful if we want to update a view, but we're not sure which one
        self.deckSelected = False

        # Setup window
        QDialog.__init__(self, mw, Qt.WindowTitleHint)
        self.setWindowTitle(getPluginName())
        self.resize(300, 800)
        self.command("MainView||main")

        # Wrap Anki methods
        Reviewer._answerCard = wrap(self.answerCard, Reviewer._answerCard)
        _Collection.undo = wrap(_Collection.undo, self.undo)
        DeckManager.select = wrap(DeckManager.select, self.refreshSettings)

        # Add AnkiEmperor to the Anki menu
        action = QAction(getPluginName(), mw)
        mw.connect(action, SIGNAL("triggered()"), self.show)
        mw.form.menuTools.addAction(action)
Example #3
0
    def setupFunctions(self, imageResizer):
        """Replace functions in anki
        """
        # setup button
        Editor.setupButtons = wrap(Editor.setupButtons, ImageResizerButton, 'after')
        Editor.imageResizer = imageResizer

        EditorWebView._processMime = wrap(EditorWebView._processMime, _processMime_around, 'around')
def profileLoaded():
    # add menu entry
    mw.addonManager.rebuildAddonsMenu = wrap(mw.addonManager.rebuildAddonsMenu,
                                             siblingMenu)
    mw.addonManager.rebuildAddonsMenu()

    # add scheduler
    anki.sched.Scheduler._adjRevIvl = wrap(anki.sched.Scheduler._adjRevIvl,
                                           siblingIvl, "around")
Example #5
0
def anknotes_onload():
    # write_file_contents('%s: anknotes_onload' % __name__, 'load')
    if in_anki():
        addHook("profileLoaded", anknotes_profile_loaded)
        if ANKNOTES.HOOKS.DB:
            DB.scalar = anknotes_scalar # wrap(DB.scalar, anknotes_scalar, "before")
            DB.execute = wrap(DB.execute, anknotes_execute, "before")
        if ANKNOTES.HOOKS.SEARCH:
            addHook("search", anknotes_search_hook)
            Finder._query = wrap(Finder._query, anknotes_finder_query_wrap, "around")
            Finder.findCards = wrap(Finder.findCards, anknotes_finder_findCards_wrap, "around")
            browser.Browser._systemTagTree = wrap(browser.Browser._systemTagTree, anknotes_browser_tagtree_wrap, "around")
        # write_file_contents('%s: anknotes_onload: anknotes_setup_menu' % __name__, 'load')
        menu.anknotes_setup_menu()
        Preferences.setupOptions = wrap(Preferences.setupOptions, settings.setup_evernote)
 def setupHanziGraph(self, graphwindow):
     log.info("Beginning setup of Hanzi graph on the graph window")
     
     # Don't add a graph if the deck doesn't have a Mandarin tag. This might be too conservative (the user
     # could add a Mandarin tag and then refresh) but in general it's going to work well to hide it from the
     # user on their non-Mandarin decks.
     if len(self.suitableModelIds()) == 0:
         return
     
     # NB: we used to preload the Hanzi data at this point, but that makes the ``refresh'' button not work,
     # because we have no means of clearing the preloaded data, so now it lives on the class. We also used to
     # avoid adding the graph if the current deck was not 
     
     # Append our own graph at the end
     from ankiqt.ui.graphs import AdjustableFigure
     extragraph = AdjustableFigure(graphwindow.parent, 'hanzi', lambda days: self.calculateHanziData(graphwindow, days), graphwindow.range)
     extragraph.addWidget(QtGui.QLabel("<h1>Unique Hanzi (Cumulative, By HSK Level)</h1>"))
     graphwindow.vbox.addWidget(extragraph)
     graphwindow.widgets.append(extragraph)
     
     # Add our graph to the name map - this is necessary to avoid exceptions when using show/hide
     graphwindow.nameMap['hanzi'] = "Unique Hanzi (Cumulative, By HSK Level)"
     
     # To allow refreshing to work properly, we have to intercept the call to updateFigure() made by Ankis onRefresh code
     extragraph.updateFigure = wrap(extragraph.updateFigure, self.invalidateHanziData, "before")
Example #7
0
def initPlugin():
	main.AnkiQt.showAnswerButton = wrap(main.AnkiQt.showAnswerButton, afterShowAnswerButton, "after")
	main.AnkiQt.keyPressEvent = wrap(main.AnkiQt.keyPressEvent, aroundKeyPressEvent, "around")
	view.View.drawAnswer = wrap(view.View.drawAnswer, aroundDrawAnswer, "around")
	menu = QAction(mw)
	menu.setText("Add Password")
	mw.connect(menu, SIGNAL("triggered()"), addPassword)
	menu2 = QAction(mw)
	menu2.setText("Set GPG User Name")
	mw.connect(menu2, SIGNAL("triggered()"), setGPGName)
	mw.mainWin.menuTools.addSeparator()
	mw.mainWin.menuTools.addAction(menu)
	mw.mainWin.menuTools.addAction(menu2)
	config.load()
	if not config.loaded:
		setGPGName()
Example #8
0
 def install(self):
     from anki.hooks import wrap
     import ankiqt.ui.facteditor
     
     log.info("Installing color shortcut keys hook")
     ankiqt.ui.facteditor.FactEditor.setupFields = wrap(ankiqt.ui.facteditor.FactEditor.setupFields, self.setupShortcuts, "after")
     self.setupShortcuts(self.mw.editor)
def profileLoaded():
    """Support for Advanced Previewer"""
    try:
        from advanced_previewer.previewer import Previewer
    except ImportError:
        return
    Previewer.linkHandler = wrap(
        Previewer.linkHandler, linkHandler, "around")
    addHook("previewerMungeQA", linkInserter)
Example #10
0
def profileLoaded():
    '''Initialize Kanji Info'''

    # load the kanji_info.txt
    init_kanji_info()

    # add menu entry
    mw.addonManager.rebuildAddonsMenu = wrap(mw.addonManager.rebuildAddonsMenu,
                                             kanji_info_Menu)
    mw.addonManager.rebuildAddonsMenu()
Example #11
0
    def __init__(cls, name, bases, attributes):
        super().__init__(name, bases, attributes)

        # singleton
        cls.instance = None
        old_creator = cls.__new__
        cls.__new__ = singleton_creator(old_creator)

        # additions and replacements
        cls.additions = {}
        cls.replacements = {}

        target = attributes.get('target', None)

        def callback_maker(wrapper):
            def raw_new(*args, **kwargs):
                return wrapper(cls.instance, *args, **kwargs)
            return raw_new

        for key, attr in attributes.items():

            if key == 'init':
                key = '__init__'
            if hasattr(attr, 'wraps'):

                if not target:
                    raise Exception(f'Asked to wrap "{key}" but target of {name} not defined')

                original = getattr(target, key)

                if type(original) is MethodType:
                    original = original.__func__

                new = wrap(original, callback_maker(attr), attr.position)

                # for classes, just add the new function, it will be bound later,
                # but instances need some more work: we need to bind!
                if not isclass(target):
                    new = MethodType(new, target)

                cls.replacements[key] = new

            if hasattr(attr, 'appends_in_night_mode'):
                if not target:
                    raise Exception(f'Asked to replace "{key}" but target of {name} not defined')
                cls.additions[key] = attr
            if hasattr(attr, 'replaces_in_night_mode'):
                if not target:
                    raise Exception(f'Asked to replace "{key}" but target of {name} not defined')
                cls.replacements[key] = attr

            # TODO: invoke and cache css?
            if hasattr(attr, 'is_css'):
                pass
 def install(self):
     log.info("Installing Hanzi graph hook")
     
     # NB: must lazy-load ankiqt.ui.graphs because importing it will fail if the user doesn't
     # have python-matplotlib installed on Linux.
     try:
         from ankiqt.ui.graphs import GraphWindow
         GraphWindow.setupGraphs = wrap(GraphWindow.setupGraphs, self.setupHanziGraph, "after")
     except ImportError, e:
         self.notifier.exception("There was a problem setting up the Hanzi Graph! If you are using Linux, " +
                                 "you may need to install the package providing matplotlib to Python. On Ubuntu " +
                                 "you can do that by running 'sudo apt-get install python-matplotlib' in the Terminal.")
Example #13
0
def main():
    # Query system colours.
    p = QPalette()
    textcolour = p.color(QPalette.Text)
    basecolour = p.color(QPalette.Base)

    # Inject background colour into the browser.
    def tree_colour_hook(self):
        p = self.form.tree.palette()
        p.setColor(QPalette.Base, basecolour)
        self.form.tree.setPalette(p)
    browser.Browser.setupTree = wrap(browser.Browser.setupTree, tree_colour_hook)

    # Change suspend and mark colours.
    coloursuspended = QColor()
    coloursuspended.setNamedColor(browser.COLOUR_SUSPENDED)
    colourmarked = QColor()
    colourmarked.setNamedColor(browser.COLOUR_MARKED)
    lightness_blacklist = [textcolour.lightness()]
    hue_blacklist = [basecolour.hue(), textcolour.hue()]
    lightness_preference = max(basecolour.lightness(), 40)
    for colour in [coloursuspended, colourmarked]:
        (h, s, l, a) = colour.getHsl()
        new_lightness = get_new_lightness(lightness_blacklist, lightness_preference)
        # print("Considering {0} with preference {2} choose lightness {1}\n".format(
        #     lightness_blacklist, new_lightness, lightness_preference))
        new_hue = get_new_hue(hue_blacklist, h)
        # print("Considering {0} with preference {2} choose hue {1}\n".format(
        #     hue_blacklist, new_hue, h))
        hue_blacklist.append(new_hue)
        colour.setHsl(new_hue, s, new_lightness, a)
    browser.COLOUR_SUSPENDED = coloursuspended.name()
    browser.COLOUR_MARKED = colourmarked.name()

    # Inject colouring into the web view.
    editor._html = re.sub(
        "(\\.fname\s*\\{)",
        "\\1 color: {0};".format(textcolour.name()),
        editor._html)
    # Fix the default text colour for type answer edit elements.
    reviewer.Reviewer._css = re.sub(
        "(#typeans\s*\\{)",
        "\\1 color: {0};".format(textcolour.name()),
        reviewer.Reviewer._css)
Example #14
0
    def initialize(self, mw):
        log.info("Pinyin Toolkit is initializing")
        
        # Build basic objects we use to interface with Anki
        thenotifier = notifier.AnkiNotifier()
        themediamanager = mediamanager.AnkiMediaManager(mw)
        
        # Open up the database
        if not self.tryCreateAndLoadDatabase(mw, thenotifier):
            # Eeek! Database building failed, so we better turn off the toolkit
            log.error("Database construction failed: disabling the Toolkit")
            return

        # Build the updaters
        updaters = {
            'expression' : pinyin.updater.FieldUpdaterFromExpression(thenotifier, themediamanager),
            'reading'    : pinyin.updater.FieldUpdaterFromReading(),
            'meaning'    : pinyin.updater.FieldUpdaterFromMeaning(),
            'audio'      : pinyin.updater.FieldUpdaterFromAudio(thenotifier, themediamanager)
          }
        
        # Finally, build the hooks.  Make sure you store a reference to these, because otherwise they
        # get garbage collected, causing garbage collection of the actions they contain
        self.hooks = [hookbuilder(mw, thenotifier, themediamanager, updaters) for hookbuilder in hookbuilders]
        for hook in self.hooks:
            hook.install()

        # add hooks and menu items
        # use wrap() instead of addHook to ensure menu already created 
        def ptkRebuildAddonsMenu(self):
            ptkMenu = None
            for menu in self._menus:
                if menu.title() == "Pinyin Toolkit":
                    ptkMenu = menu
                    break

            ptkMenu.addSeparator()
            config = getconfig()
            hooks.buildHooks(ptkMenu, mw, config, thenotifier, themediamanager,
                               updaters)

        aqt.addons.AddonManager.rebuildAddonsMenu = wrap(aqt.addons.AddonManager.rebuildAddonsMenu, ptkRebuildAddonsMenu) 
Example #15
0
def monster():
    mw.col.sched.answerCard = wrap( mw.col.sched.answerCard, monsterAnswerCard )

    newCount, lrnCount, revCount = mw.col.sched.counts()
    totalCount = (newCount + lrnCount + revCount)
    howManyToDo = totalCount / 2
    if howManyToDo < N:
        howManyToDo = N
    if totalCount < N:
        howManyToDo = totalCount

    mw.monstersToDo = howManyToDo
    mw.monstersDone = 0
    # XXX If howManyToDo is > than the number of pngs, this is bad
    mw.monsters = [ loadMonster(png) for png in os.listdir(MonstersPath)]
    shuffle(mw.monsters)

    if mw.monstersToDo > 0:
        displayMonsters(False)
        mw.moveToState("review")
Example #16
0
    # is that the model names are not set up correctly in the
    # model_buttons list of dictionaries above.
    cdeck = chooser.deck.decks.current()
    cdeck['mid'] = m['id']
    chooser.deck.decks.save(cdeck)
    runHook("currentModelChanged")
    chooser.mw.reset()


def isClozeNote(note):
    for name, val in note.items():
        if re.search(r'\{\{c(\d+)::', val):
            return True
    return False


def newAddCards(self, _old):
    note = self.editor.note
    if note.model()['name'] in basic_note_type and isClozeNote(note):
        oldModelName = note.model()['name']
        change_model_to(self.modelChooser, cloze_note_type)
        _old(self)
        change_model_to(self.modelChooser, oldModelName)
        tooltip(_("Automatic switch from Basic to Cloze"))

    else:
        return _old(self)


AddCards.addCards = wrap(AddCards.addCards, newAddCards, "around")
Example #17
0
    each other, the class describes this fact.

    When t and g can't be converted to numbers, the ValueError of that
    conversion is not caught.
    """
    try:
        target_value = int(t)
        given_value = int(g)
    except ValueError:
        # No try here. Catch that case higher up.
        target_value = float(t)
        given_value = float(g)
    # One of the two conversions worked: we have two valid numbers, two
    # ints or two floats. We don’t really care which.
    if target_value == given_value:
        return exact_class
    # Now we know that they are not the same, so either red or yellow.
    try:
        factor = 1.0 * given_value / target_value
    except ZeroDivisionError:
        return fail_class
    if factor < 1.0 / pass_factor or factor > pass_factor:
        return fail_class
    return pass_class


Reviewer.correct = wrap(Reviewer.correct, correct_scalar, "around")

old_css = Card.css
Card.css = scalar_card_css
        if reviewer.state == "question":
            reviewer._showQuestion()
        elif reviewer.state == "answer":
            reviewer._showAnswer()

    # Catch ctrl key presses from bottom.web.
    elif url == "EFDRC!ctrldown":
        reviewer.web.eval("EFDRC.ctrldown()")
    elif url == "EFDRC!ctrlup":
        reviewer.web.eval("EFDRC.ctrlup()")

    elif url == "EFDRC!paste":
        # From aqt.editor.Editor._onPaste, doPaste.
        mime = mw.app.clipboard().mimeData(mode=QClipboard.Clipboard)
        html, internal = editorwv._processMime(mime)
        html = editorwv.editor._pastePreFilter(html, internal)
        reviewer.web.eval("pasteHTML(%s, %s);" %
                          (json.dumps(html), json.dumps(internal)))

    elif url.startswith("EFDRC!debug#"):
        fld = url.replace("EFDRC!debug#", "")
        showText(fld)
    else:
        return _old(reviewer, url)


Reviewer._bottomHTML = wrap(Reviewer._bottomHTML, myRevBottomHTML, "around")
Reviewer.revHtml = wrap(Reviewer.revHtml, myRevHtml, "around")
Reviewer._linkHandler = wrap(Reviewer._linkHandler, myLinkHandler, "around")
addHook("fmod_edit", edit)
Example #19
0
from aqt.utils import tooltip

from .config import gc, pycmd_string
from .helpers import check_string_for_existing_file
from .linked__link_handler import process_urlcmd
from .open_in_external import open_external


def myLinkHandler(self, url, _old):
    if process_urlcmd(url):
        return
    else:
        return _old(self, url)


Reviewer._linkHandler = wrap(Reviewer._linkHandler, myLinkHandler, "around")
Previewer._on_bridge_cmd = wrap(Previewer._on_bridge_cmd, myLinkHandler,
                                "around")
Editor.onBridgeCmd = wrap(Editor.onBridgeCmd, myLinkHandler, "around")


def contexthelper(menu, selectedtext):
    if not gc("inline_prefix"):
        return
    if not gc("inline_prefix") in selectedtext:
        return
    file, page = check_string_for_existing_file(selectedtext)
    # print(f"file_add_to_context: {file}, {page}")
    if file:
        a = menu.addAction("Try to open externally")
        a.triggered.connect(lambda _, f=file, p=page: open_external(f, p))
Example #20
0
def setup():
    Editor.onBridgeCmd = wrap(Editor.onBridgeCmd, onBridgeCmd, "around")

    addHook("browser.setupMenus", setup_menus)
    addHook("setupEditorButtons", setup_editor_buttons)
Example #21
0
def initializeScheduler():
    for scheduler in SCHEDULERS:
        scheduler._burySiblings = wrap(scheduler._burySiblings, myBurySiblings,
                                       "around")
    self.arToggleLabel = QtGui.QLabel("Strip Arabic\n Diacritics")
    
    # Initial checked state is what we had saved previously
    self.arToggleButton.setCheckState(mw.col.conf.get(CONF_KEY_CHECKED, 0))

    # Save state on toggle
    mw.connect(self.arToggleButton, SIGNAL("stateChanged(int)"), onChecked)
    
    # Add our items to the right of the search box. We do this by moving
    # every widget out of the gridlayout and into a new list. We simply
    # add our stuff in the new list in the right place before moving them
    # back to gridlayout.
    n_items = self.gridLayout.count()
    items= []
    for i in range(0, n_items):
        item = self.gridLayout.itemAt(i).widget()
        items.append(item)
        if item == self.searchEdit:
            items.append(self.arToggleButton)
            items.append(self.arToggleLabel)
    
    for i, item in enumerate(items):
        self.gridLayout.addWidget(item, 0, i, 1, 1)
        
    
def onChecked(state):
    """Save the checked state in Anki's configuration."""
    mw.col.conf[CONF_KEY_CHECKED] = state

Ui_Dialog.setupUi= wrap(Ui_Dialog.setupUi, mySetupUi)
DataModel.search = mySearch
Example #23
0
from anki.hooks import wrap, addHook
from aqt import mw
from aqt.reviewer import Reviewer

def newShortcutKeys(self, _old):
    return _old(self) + [
        ("j", lambda: self._answerCard(1)),
        ("k", lambda: self._answerCard(2)),
        ("l", lambda: self._answerCard(3)),
        (";", lambda: self._answerCard(4)),
        ("x", lambda: self.onSuspendCard()),
    ]

def newAnswerCard(self, ease, _old):
    if self.state == "question":
        self._showAnswer()
    else: 
        _old(self, min(self.mw.col.sched.answerButtons(self.card), ease))

def refocusInterface():
    mw.web.setFocus()

        
Reviewer._shortcutKeys = wrap(Reviewer._shortcutKeys, newShortcutKeys, "around")
Reviewer._answerCard = wrap(Reviewer._answerCard, newAnswerCard, "around")


addHook("showQuestion", refocusInterface)
addHook("showAnswer", refocusInterface)
Example #24
0
    # "good" as an answer for cards studied ahead).
    #
    # As the scheduled due date draws closer these intervals will start to
    # diverge, ever coming closer to the intervals you would see if you
    # were to review the card when it's actually due

    ivl2 = int(max(elapsed * 1.2, card.ivl, 1))  # hard (default fct = 1.2)
    ivl3 = int(max(elapsed * fct, ivl2, 1))  # good
    ivl4 = int(max(elapsed * fct * conf['ease4'], ivl3, 1))  # easy

    print("--------------------------------")
    print("card.ivl", card.ivl)
    print("elapsed", elapsed)
    print("delta to due", card.due - self.today)
    print("fct", fct)
    print("ivl2", ivl2)
    print("ivl3", ivl3)
    print("ivl4", ivl4)

    if ease == 2:
        interval = ivl2
    elif ease == 3:
        interval = ivl3
    elif ease == 4:
        interval = ivl4
    # interval capped?
    return min(interval, conf['maxIvl'])


Scheduler._nextRevIvl = wrap(Scheduler._nextRevIvl, nextRevIvl, "around")
''' This addon hooks TextImporter (CSV files) to automatically import media files within the same directory. '''

__version__ = '1.0.0'

import os
import re

from aqt import mw
from anki.hooks import wrap
from anki.importing import TextImporter
from anki.media import MediaManager

def importNotes(self, notes):

	mediamanager = MediaManager(mw.col, None)
	directory = os.path.dirname(self.file)
	files = os.listdir(directory)

	regexes = [re.compile(regex) for regex in mediamanager.regexps]

	for note in notes:
		for field in note.fields:
			for regex in regexes:
				for finding in regex.findall(field):
					mediafile = finding[-1]
					if mediafile in files:
						mediamanager.addFile(directory + '/' + mediafile)

TextImporter.importNotes = wrap(TextImporter.importNotes, importNotes)
Example #26
0
def on_ipa_language_select(editor, lang):
    try:
        alias = LANGUAGES_MAP[lang]
    except KeyError as e:
        print(e)
        showInfo("mist")
        editor.ipa_lang_alias = ""
        return False
    set_default_lang(mw, lang)
    editor.ipa_lang_alias = alias


def init_ipa(editor, *args, **kwargs):
    # Get the last selected language (or the default language if the user
    # has never chosen any)
    previous_lang = get_default_lang(mw)
    editor.ipa_lang_alias = LANGUAGES_MAP.get(previous_lang, "")


def onBridgeCmd(ed, cmd, _old):
    if not cmd.startswith("shLang"):
        return _old(ed, cmd)
    (type, lang) = cmd.split(":")
    on_ipa_language_select(ed, lang)


addHook("setupEditorButtons", on_setup_buttons)
Editor.onBridgeCmd = wrap(Editor.onBridgeCmd, onBridgeCmd, "around")
Editor.__init__ = wrap(Editor.__init__, init_ipa)
Example #27
0
    [ actionFunc(did) for did in dynDeckIds ]
    mw.progress.finish()
    tooltip("Updated {0} filtered decks.".format(count))

    mw.reset()


def _handleFilteredDeckButtons(self, url):
    if url in ["rebuildDyn", "emptyDyn"]:
        _updateFilteredDecks(url)


def _addButtons(self):
    # There's no clean way to add a button, so hack it in. :(
    newHtml = ""
    newButtons = [
        [_("Rebuild All"), "rebuildDyn"],
        [_("Empty All"),   "emptyDyn"],
    ]

    for newButton in newButtons:
        newHtml += "<button title='{0}' onclick='py.link(\"{1}\");'>{0}</button>".format(*newButton)

    html = self.bottom.web.page().mainFrame().toHtml()
    buttons = re.findall('<button.+</button>', html)
    self.bottom.draw(''.join(buttons) + newHtml)  


DeckBrowser._drawButtons = wrap(DeckBrowser._drawButtons, _addButtons, "after")
DeckBrowser._linkHandler = wrap(DeckBrowser._linkHandler, _handleFilteredDeckButtons, "after")
    clayout.forms[-1]['pform'].frontWeb.setLinkHandler(simple_link_handler)
    clayout.forms[-1]['pform'].backWeb.setLinkHandler(simple_link_handler)


def add_preview_link_handler(browser):
    u"""Make sure we play the files from the preview window."""
    browser._previewWeb.setLinkHandler(simple_link_handler)


def reduce_format_qa(self, text):
    u"""Remove elements with a given class before displaying."""
    soup = BeautifulSoup(text)
    for hide in soup.findAll(True, {'class': re.compile(
            '\\b' + hide_class_name + '\\b')}):
        hide.extract()
    return original_format_qa(self, unicode(soup))


original_review_link_handler = Reviewer._linkHandler
Reviewer._linkHandler = review_link_handler_wrapper

original_format_qa = DataModel.formatQA
DataModel.formatQA = reduce_format_qa

old_css = Card.css
Card.css = svg_css

addHook("mungeQA", play_button_filter)
Browser._openPreview = wrap(Browser._openPreview, add_preview_link_handler)
CardLayout.addTab = wrap(CardLayout.addTab, add_clayout_link_handler)
    TODO: there seems to be no clean way to add a button. I've resorted to
    copying the body of Overview._renderBottom and adding the link here.
    Hopefully we can find a better way to do this in the future.
    """
    links = [
        ["O", "opts", _("Options")],
    ]
    if self.mw.col.decks.current()['dyn']:
        links.append(["R", "refresh", _("Rebuild")])
        links.append(["E", "empty", _("Empty")])
    else:
        links.append(["C", "studymore", _("Custom Study")])
        #links.append(["F", "cram", _("Filter/Cram")])
    if self.mw.col.sched.haveBuried():
        links.append(["U", "unbury", _("Unbury")])
    links.append(["L", "resetLimits", _("Reset Limit Increases")])
    buf = ""
    for b in links:
        if b[0]:
            b[0] = _("Shortcut key: %s") % shortcut(b[0])
        buf += """
<button title="%s" onclick='pycmd("%s")'>%s</button>""" % tuple(b)
    self.bottom.draw(buf)
    self.bottom.web.onBridgeCmd = self._linkHandler


Overview._renderBottom = wrap(Overview._renderBottom, _renderBottom, "after")
Overview._linkHandler = wrap(Overview._linkHandler, _handleResetLimitsButton,
                             "after")
Example #30
0
def init():
    EditorWebView.dropEvent = wrap(EditorWebView.dropEvent, drop_event,
                                   'around')
    EditorWebView.onPaste = custom_decorate(EditorWebView.onPaste, paste_event)
Example #31
0
        clipboard = QApplication.clipboard()
        # Get the code from the clipboard
        code = clipboard.text()
    
    langAlias = self.codeHighlightLangAlias
    
    # Select the lexer for the correct language
    my_lexer = get_lexer_by_name(langAlias, stripall=True)
    # Tell pygments that we will be generating HTML without CSS.
    # HTML without CSS may take more space, but it's self contained.
    
    my_formatter = HtmlFormatter(linenos=linenos, noclasses=True, font_size=16)

    if linenos:
        pretty_code = "".join([("", "<center>")[center],
                               highlight(code, my_lexer, my_formatter),
                               ("<br>", "</center><br>")[center]])
    # TODO: understand why this is neccessary
    else:
        pretty_code = "".join([("", "<center>")[center] + "<table><tbody><tr><td>",
                               highlight(code, my_lexer, my_formatter),
                               "</td></tr></tbody></table>" + ("<br>", "</center><br>")[center]])

    # These two lines insert a piece of HTML in the current cursor position
    self.web.eval("document.execCommand('inserthtml', false, %s);"
                  % json.dumps(pretty_code))

editor.Editor.onCodeHighlightLangSelect = onCodeHighlightLangSelect
editor.Editor.highlight_code = highlight_code
editor.Editor.__init__ = hooks.wrap(editor.Editor.__init__, init_highlighter)

def setupUi(self, Dialog):
    """Add an option for Stainless Ease at Lapse section on Deckconf dialog."""
    try:
        self.stainlessEase = QtWidgets.QCheckBox(self.tab_2)
    except NameError:
        self.stainlessEase = QtGui.QCheckBox(self.tab_2)
    self.stainlessEase.setText(_("Stainless Ease"))
    self.gridLayout_2.addWidget(self.stainlessEase, 7, 0, 1, 3)


def load_conf(self):
    """Get the option for Stainless Ease."""
    self.conf = self.mw.col.decks.confForDid(self.deck['id'])
    c = self.conf
    f = self.form
    f.stainlessEase.setChecked(c.get("stainlessEase", False))


def save_conf(self):
    """Save the option for Stainless Ease."""
    self.conf['stainlessEase'] = self.form.stainlessEase.isChecked()


addHook("leech", reduce_ease)
Scheduler._rescheduleLapse = wrap(Scheduler._rescheduleLapse, preserve_ease, 'around')
dconf.Ui_Dialog.setupUi = wrap(dconf.Ui_Dialog.setupUi, setupUi)
DeckConf.loadConf = wrap(DeckConf.loadConf, load_conf)
DeckConf.saveConf = wrap(DeckConf.saveConf, save_conf, 'before')
    _old = kwargs.pop("_old")
    if "parent" in kwargs:
        parent = kwargs["parent"]
    elif len(args) > 4:
        parent = args[4]  # Position of 'parent' parameter.
    else:
        parent = None

    if parent == "EFDRCsemiedit":
        # Don't show progress window when pasting images while in review.
        myprogress = True
        mw.app.setOverrideCursor(QCursor(Qt.WaitCursor))
        return
    else:
        myprogress = False
        return _old(*args, **kwargs)


def myfinish(self, _old):
    global myprogress
    if myprogress:
        myprogress = False
        self.app.restoreOverrideCursor()
        return
    else:
        return _old(self)


ProgressManager.start = wrap(ProgressManager.start, mystart, "around")
ProgressManager.finish = wrap(ProgressManager.finish, myfinish, "around")
Example #34
0
    for i in transcriptions:
        ui_actions["transcription_"+i]=add_action(i, sm, set_option_constructor("transcription", i), True)
    sm=m.addMenu(_("Set speech language"))
    for i in speech_options:
        ui_actions["speech_"+i]=add_action(i, sm, set_option_constructor("speech", i), True)
    add_action(_("Fill missing sounds"), m, fill_sounds_logic)
    add_action(_("Editor Behavior"), m, edit_logic)
    sm=m.addMenu(_("Help"))
    ### REMINDER : the website addresses are also available in config.py, in some startup tips. Don't forget to update both.
    add_action(_("Setup instructions"), sm, lambda : goto_page("https://github.com/ttempe/chinese-support-addon/wiki/Setup-Instructions"))
    add_action(_("Usage instructions"), sm, lambda : goto_page("https://github.com/ttempe/chinese-support-addon/wiki"))
    add_action(_("Support forum"), sm, lambda : goto_page("https://groups.google.com/forum/#!msg/anki-addons/YZmzNpmEuaY/OKbqbfGaMA0J"))
    add_action(_("Report a bug"), sm, lambda : goto_page("https://github.com/ttempe/chinese-support-addon/issues"))
    add_action(_("About..."), m, lambda : showInfo(u"Chinese support plugin v. " + __init__.__version__ + u"<br>Copyright © 2012 Thomas TEMP&Eacute; and many others.<br><br>Please see source code for additional info."))
    add_action(_("Please rate me on Ankiweb!"), m, lambda : goto_page("https://ankiweb.net/shared/addons/"))
    update_dict_action_checkboxes()



aqt.addons.AddonManager.rebuildAddonsMenu = wrap(aqt.addons.AddonManager.rebuildAddonsMenu, myRebuildAddonsMenu)

display_next_tip()
display_new_version_message()
#Check for new version of this plug-in when closing Anki
aqt.main.AnkiQt.onClose = wrap(aqt.main.AnkiQt.onClose, check_for_next_version)

#Uncomment to force display of next version info (debug)
#latest_version="123"
#latest_comment = __init__.release_info
#chinese_support_config.set_option("next_version_message", 'A new version of <b>Chinese Support Add-on</b> is available.<br>&nbsp;<br>You can download it now through <tt>Tools->Add-ons->Browse and install</tt><br>&nbsp;<br>Add-on code: %s<br>&nbsp;<br><b>Version %s:</div><div>%s</div>' %( __init__.ankiweb_number, latest_version, latest_comment))
Example #35
0
from PyQt4.QtCore import SIGNAL
from PyQt4.QtGui import QKeySequence, QShortcut

from anki.hooks import wrap
from aqt import mw
from aqt.reviewer import Reviewer

__version__ = "1.2.1"

mw.other_deck = QShortcut(QKeySequence("Ctrl+w"), mw)
mw.other_browse = QShortcut(QKeySequence("Ctrl+f"), mw)


def replay_6(self, evt):
    """
    Use “6” and “i” to replay audio.

    Use the “6” key to replay audio, useful for reviewing with the
    right hand on the numeric key pad, and the “i” key, useful when
    reviewing with the left hand on a Dvorak keyboard.
    """
    key = unicode(evt.text())
    if key == "6" or key == 'i':
        self.replayAudio()


Reviewer._keyHandler = wrap(Reviewer._keyHandler, replay_6)
mw.connect(mw.other_deck, SIGNAL("activated()"),
           lambda: mw.moveToState("deckBrowser"))
mw.connect(mw.other_browse, SIGNAL("activated()"), lambda: mw.onBrowse())
        l = lambda s=self, nn=button_item["note_name"]: change_model_to(s, nn)
        try:
            s = QShortcut(
                QKeySequence(_(button_item["shortcut"])), self.widget)
        except KeyError:
            pass
        else:
            s.connect(s, SIGNAL("activated()"), l)
        try:
            b.setFixedWidth(button_item["button_width"])
        except KeyError:
            b.setFixedWidth(default_button_width)
        bhbl.addWidget(b)
        self.connect(b, SIGNAL("clicked()"), l)
    self.addLayout(bhbl)


def change_model_to(self, model_name):
    #mostly just a copy and paste from the bottom of onModelChange()
    m = self.deck.models.byName(model_name)
    self.deck.conf['curModel'] = m['id']
    cdeck = self.deck.decks.current()
    cdeck['mid'] = m['id']
    self.deck.decks.save(cdeck)
    runHook("currentModelChanged")
    self.mw.reset()

ModelChooser.setupModels = wrap(
    ModelChooser.setupModels, setup_model_buttons, "after")
ModelChooser.changeModelTo = change_model_to
Example #37
0

def setBrowserEditor(browser, c, p):
    if mw.miaDictionary and mw.miaDictionary.isVisible():
        if browser.editor.note:
            mw.miaDictionary.dict.setCurrentEditor(browser.editor, 'Browser')
        else:
            mw.miaDictionary.dict.closeEditor()


def checkCurrentEditor(self):
    if mw.miaDictionary and mw.miaDictionary.isVisible():
        mw.miaDictionary.dict.checkEditorClose(self.editor)


Browser._onRowChanged = wrap(Browser._onRowChanged, setBrowserEditor)

AddCards._reject = wrap(AddCards._reject, checkCurrentEditor)
EditCurrent._saveAndClose = wrap(EditCurrent._saveAndClose, checkCurrentEditor)
Browser._closeWindow = wrap(Browser._closeWindow, checkCurrentEditor)


def addEditActivated(self, event=False):
    if mw.miaDictionary and mw.miaDictionary.isVisible():
        mw.miaDictionary.dict.setCurrentEditor(self.editor,
                                               getTarget(type(self).__name__))


bodyClick = '''document.addEventListener("click", function (ev) {
        pycmd("bodyClick")
    }, false);'''
    nids = mw.col.findNotes("*")
    for nid in nids:
        note = mw.col.getNote(nid)
        if not check_model(note.model()):
            continue
        generate_enhanced_cloze(note)
        note.flush()


def setup_menu(self):
    browser = self
    menu = browser.form.menuEdit
    menu.addSeparator()
    a = menu.addAction('Update Enhanced Clozes')
    a.setShortcut(QKeySequence(UPDATE_ENHANCED_CLOZE_SHORTCUT))
    a.triggered.connect(
        lambda _, b=browser: update_all_enhanced_clozes_in_browser(b))


def on_save_now(self, callback=None):
    update_all_enhanced_cloze(self)


AddCards.addCards = wrap(AddCards.addCards, on_add_cards, "around")

EditCurrent.onSave = wrap(EditCurrent.onSave, on_edit_current_save, "around")

Editor.saveNow = wrap(Editor.saveNow, on_save_now, "before")

addHook("browser.setupMenus", setup_menu)
Example #39
0
    links.append(
        toolbar.create_link("morph",
                            _(name),
                            on_morph_link_clicked,
                            tip=_(details),
                            id="morph"))


try:
    from aqt import gui_hooks
    gui_hooks.top_toolbar_did_init_links.append(on_top_toolbar_did_init_links)
except:
    # Support for legacy Anki before 2.1.22
    def my_centerLinks(self, _old):
        name, details = getStatsLink()
        links = [
            ["decks", _("Decks"),
             _("Shortcut key: %s") % "D"],
            ["add", _("Add"), _("Shortcut key: %s") % "A"],
            ["browse", _("Browse"),
             _("Shortcut key: %s") % "B"],
            ["stats", _("Stats"),
             _("Shortcut key: %s") % "T"],
            ["sync", _("Sync"), _("Shortcut key: %s") % "Y"],
            ["morph", _(name), _(details)],
        ]
        return self._linkHTML(links)

    toolbar.Toolbar._centerLinks = wrap(toolbar.Toolbar._centerLinks,
                                        my_centerLinks, 'around')
Example #40
0
def onProfileLoaded():
    """Monkey-patch Reviewer delayed in order to counteract bad practices
    in other add-ons that overwrite revHtml and _linkHandler in their
    entirety"""
    Reviewer.revHtml = wrap(Reviewer.revHtml, onRevHtml, "around")
    Reviewer._linkHandler = wrap(Reviewer._linkHandler, linkHandler, "around")
Example #41
0
    self.form.fieldsArea.setMinimumSize(50, 1)
    self.form.widget.setMinimumSize(50, 1)
    self.extremestate = 0  # for toggling views
    self.advbrowse_uniqueNote_state_original = mw.col.get_config(
        "advbrowse_uniqueNote", False)

    val = gc("splitter_bigger", False)
    if val:
        #test for old config style that just had True and False
        if bool(val):
            val = 20
        self.form.splitter.setHandleWidth(val)


if pointVersion() < 45:
    Browser.setupTable = wrap(Browser.setupTable, mysetupTable, "before")
else:
    Browser.setup_table = wrap(Browser.setup_table, mysetupTable, "before")


def my_toggle_notes_only(self, arg):
    if pointVersion() < 45:
        self.model.beginReset()
        mw.col.set_config("advbrowse_uniqueNote", arg)
        self.onSearchActivated()
        self.model.endReset()
    else:
        self.on_table_state_changed(False)


def get_splitter_dimension(self):
Example #42
0
def customize_addcards():
    AddCards.setupButtons = wrap(AddCards.setupButtons, add_query_button,
                                 "before")
iconsDir = os.path.join(mw.pm.addonFolder(), 'ffvocdeckbuilder', 'icons')

def enableVocabularyBuilderView(self):
    return

def onSetupEditorButtons(self):
    """Add an a button to the editor to activate the vocabulary deck building
    mode.
    """
    # 'text' must be non empty otherwise the function tries to find an icon
    # into the anki path
    editorButton = self._addButton(
        "ffvocdeckbuilder",
        lambda self=self: enableVocabularyBuilderView(self),
        tip=u"Build language deck...", text=" ",
        check=True)
    editorButton.setIcon(QIcon(os.path.join(iconsDir, 'dictionary.png')))
    # Remove the empty text to center align the icon
    editorButton.setText("")

def enableDeckBuilderButton(self, val=True):
    """Disable the editor button when the note type is not 'FF basic vocabulary'
    """
    if val and (self.note.model()['name'] != "FF basic vocabulary"):
        self._buttons["ffvocdeckbuilder"].setEnabled(False)

hooks.addHook("setupEditorButtons", onSetupEditorButtons)

editor.Editor.enableButtons = hooks.wrap(
    editor.Editor.enableButtons, enableDeckBuilderButton)
Example #44
0
    # randomized card from lrnDayQueue, revQueue and newQueue (if the relevant setting is set)
    totalCount = newCardCount + self.revCount + self.lrnDayCount
    if totalCount > 0:
        rand = random.randint(1, totalCount)
        if rand <= newCardCount:
            card = self._getNewCard()
        elif rand <= newCardCount + self.revCount:
            card = self._getRevCard()
        else:
            card = self._getLrnDayCard()

        if card:
            return card

    # new cards left?
    card = self._getNewCard()
    if card:
        return card

    # collapse or finish
    return self._getLrnCard(collapse=True)


Scheduler._resetLrnCount = wrap(Scheduler._resetLrnCount, resetLrnCount,
                                'around')
Scheduler._fillLrnDay = wrap(Scheduler._fillLrnDay, fillLrnDay, 'around')
Scheduler._getLrnDayCard = wrap(Scheduler._getLrnDayCard, getLrnDayCard,
                                'around')
Scheduler._getCard = wrap(Scheduler._getCard, getCard, 'around')
def linkHandler(self, url, _old):
    if not url.startswith("open"):
        return _old(self, url)
    (cmd, arg) = url.split(":", 1)
    openFileHandler(arg)


def linkInserter(html):
    return re.sub(regex_link, replacement, html)


def onMungeQA(self, buf, _old):
    buf = _old(self, buf)
    return linkInserter(buf)


def profileLoaded():
    """Support for Advanced Previewer"""
    try:
        from advanced_previewer.previewer import Previewer
    except ImportError:
        return
    Previewer.linkHandler = wrap(
        Previewer.linkHandler, linkHandler, "around")
    addHook("previewerMungeQA", linkInserter)


Reviewer._linkHandler = wrap(Reviewer._linkHandler, linkHandler, "around")
Reviewer._mungeQA = wrap(Reviewer._mungeQA, onMungeQA, "around")
addHook("profileLoaded", profileLoaded)
Example #46
0
                "<center>",
                highlight(code, my_lexer, my_formatter), "</center><br>"
            ])
        else:
            pretty_code = "".join(
                [highlight(code, my_lexer, my_formatter), "<br>"])

    pretty_code = process_html(pretty_code)

    # These two lines insert a piece of HTML in the current cursor position
    ed.web.eval("document.execCommand('inserthtml', false, %s);" %
                json.dumps(pretty_code))


def process_html(html):
    """Modify highlighter output to address some Anki idiosyncracies"""
    # 1.) "Escape" curly bracket sequences reserved to Anki's card template
    # system by placing an invisible html tag inbetween
    for pattern, replacement in ((r"{{", r"{<!---->{"), (r"}}", r"}<!---->}"),
                                 (r"::", r":<!---->:")):
        html = re.sub(pattern, replacement, html)
    return html


# Hooks and monkey-patches

addHook("setupEditorButtons", onSetupButtons)
Editor.onBridgeCmd = wrap(Editor.onBridgeCmd, onBridgeCmd, "around")

Editor.__init__ = wrap(Editor.__init__, init_highlighter)
Example #47
0
def add_preview_link_handler(browser):
    """Make sure we play the files from the preview window."""
    browser._previewWeb.setLinkHandler(simple_link_handler)


def reduce_format_qa(self, text):
    """Remove elements with a given class before displaying."""
    soup = BeautifulSoup(text, 'html.parser')
    for hide in soup.findAll(True, {'class': re.compile(
            '\\b' + hide_class_name + '\\b')}):
        hide.extract()
    return original_format_qa(self, unicode(soup))


original_review_link_handler = Reviewer._linkHandler
Reviewer._linkHandler = review_link_handler_wrapper

# TODO: hide stuff from the browser again
#original_format_qa = DataModel.formatQA
#DataModel.formatQA = reduce_format_qa

old_css = Card.css
Card.css = svg_css

addHook("mungeQA", play_button_filter)
Browser._openPreview = wrap(Browser._openPreview, add_preview_link_handler)

# TODO: fix this
#CardLayout.addTab = wrap(CardLayout.addTab, add_clayout_link_handler)

def linkHandler(self, url, _old):
    if not url.startswith("open"):
        return _old(self, url)
    (cmd, arg) = url.split(":", 1)
    openFileHandler(arg)


def linkInserter(html):
    return re.sub(regex_link, replacement, html)


def onMungeQA(self, buf, _old):
    buf = _old(self, buf)
    return linkInserter(buf)


def profileLoaded():
    """Support for Advanced Previewer"""
    try:
        from advanced_previewer.previewer import Previewer
    except ImportError:
        return
    Previewer.linkHandler = wrap(Previewer.linkHandler, linkHandler, "around")
    addHook("previewerMungeQA", linkInserter)


Reviewer._linkHandler = wrap(Reviewer._linkHandler, linkHandler, "around")
Reviewer._mungeQA = wrap(Reviewer._mungeQA, onMungeQA, "around")
addHook("profileLoaded", profileLoaded)
    # Mostly just a copy and paste from the bottom of onModelChange()
    m = chooser.deck.models.byName(model_name)
    chooser.deck.conf['curModel'] = m['id']
    # When you get a “TypeError: 'NoneType' object has no attribute
    # '__getitem__'” directing you here, the most likely explanation
    # is that the model names are not set up correctly in the
    # model_buttons list of dictionaries above.
    cdeck = chooser.deck.decks.current()
    cdeck['mid'] = m['id']
    chooser.deck.decks.save(cdeck)
    runHook("currentModelChanged")
    chooser.mw.reset()


def change_deck_to(chooser, deck_name):
    """Change to deck with name deck_name"""
    # Well, that is easy.
    chooser.deck.setText(deck_name)


ModelChooser.setupModels = wrap(
    ModelChooser.setupModels,
    lambda mc: setup_buttons(mc, model_buttons, "note type", change_model_to),
    "after")
ModelChooser.change_model_to = change_model_to
DeckChooser.setupDecks = wrap(
    DeckChooser.setupDecks,
    lambda dc: setup_buttons(dc, deck_buttons, "deck", change_deck_to),
    "after")
DeckChooser.change_deck_to = change_deck_to
Example #50
0
        ah.log.info("your profile is %s" % (ah.settings.profile))
    if ah.settings.profile not in ah.config:
        ah.config[ah.settings.profile] = {}
        if ah.user_settings["keep_log"]:
            ah.log.info("adding %s to config dict" % ah.settings.profile)

    check_unsynced_score()


#################
### Wrap Code ###
#################

addHook("profileLoaded", grab_profile)
addHook("unloadProfile", save_stats)
Reviewer.nextCard = wrap(Reviewer.nextCard, hrpg_realtime, "before")

# Insert progress bar into bottom review stats
#       along with database scoring and realtime habitica routines
orig_remaining = Reviewer._remaining


def my_remaining(x):
    if ah.user_settings["keep_log"]:
        ah.log.debug("Begin function")
    ret = orig_remaining(x)
    if ah.user_settings[
            "show_progress_bar"] and not ah.settings.hrpg_progbar == "":
        ret += " : %s" % (ah.settings.hrpg_progbar)
    if ah.settings.initialized and ah.user_settings["show_mini_stats"]:
        mini_stats = ah.habitica.compact_habitica_stats()
from aqt import mw
from aqt.reviewer import Reviewer
from anki.hooks import wrap
from aqt.utils import tooltip

def keyHandler(self, evt, _old):
    key = unicode(evt.text())
    if key == "$":
        self.onForget()
    else:
        return _old(self, evt)

Reviewer._keyHandler = wrap(Reviewer._keyHandler, keyHandler, "around")

def onForget(self):
    self.mw.checkpoint(_("Forget"))
    self.mw.col.sched.forgetCards(
        [c.id for c in self.card.note().cards()])
    tooltip(_("Note rescheduled as new"))
    self.mw.reset()

Reviewer.onForget = onForget
    window = QDialog(mw)
    window.setWindowTitle(title_text)
    window.setWindowIcon(
        QIcon(join(addon_path, 'user_files/images') + "/icon.png"))
    header = QLabel()
    header.setAlignment(Qt.AlignCenter)
    header.setText(
        "<div style='font-size: {}px; font-family: {};'> {} </div>".format(
            headerText_fontSize, headerText_fontStyle, header_text))
    image = QLabel()
    image.setAlignment(Qt.AlignCenter)
    image.setText(
        "<img src='{}' style='max-height: 450px; max-width: 450px;'>".format(
            image_folder + image_name))
    button = QPushButton(button_text)
    button.clicked.connect(lambda: window.hide())
    layout = QVBoxLayout()
    if show_header:
        layout.addWidget(header)
    if show_image:
        layout.addWidget(image)
    layout.addWidget(button)
    window.setLayout(layout)
    if not show_image and not show_header:
        return
    else:
        window.exec()


Reviewer._showAnswer = wrap(Reviewer._showAnswer, myPopUp, 'after')
Example #53
0
    if (self.name == "due" or 
        self.name == "reps" or 
        self.name == "times" or 
        self.name == "added" or 
        self.name == "answered" or 
        self.name == "cum" or
        self.name == "kanji"):
    
        #Get the plot we're gonna modify (calling add_subplot() with the params of an existing subplot returns it)
        theSubplot = self.figureCanvas.fig.add_subplot(111)

        #Get a list of the plot's tickmarks
        defaultTickMarks = theSubplot.get_xticks()
        newTickMarks = []

        #Use each of these ticks to create a set of string labels based on date offsets from today
        nowDate = datetime.datetime.now()
        for thisTickMark in defaultTickMarks:
            delta   = datetime.timedelta(days=thisTickMark)
            newdate = nowDate + delta
            newTickMarks.append( str(int(thisTickMark)) + "\n" + str(newdate.month) + "/" + str(newdate.day) + "/" + str(newdate.year)[2:] )
    
        #And set the plot's labels!
        theSubplot.set_xticklabels(newTickMarks)


#Setup our hooks
if not __name__ == "__main__":
    AdjustableFigure.updateFigure = wrap(AdjustableFigure.updateFigure, hook_overrideLabels, "after")
    AdjustableFigure.addFigure = wrap(AdjustableFigure.addFigure, hook_overrideLabels, "after")
Example #54
0
from aqt import mw
from aqt.reviewer import Reviewer
from anki.hooks import wrap

def keyHandler(self, evt, _old):
    key = unicode(evt.text())
    if key == "z":
        try:# throws an error on undo -> do -> undo pattern,  otherwise works fine
            mw.onUndo()
        except:
            pass
    elif key in ["j", "k", "l", ";",]:
        isq = self.state == "question"
        if isq:
            self._showAnswerHack()
        if key == "j":
            self._answerCard(1)
        elif key == "k":
            self._answerCard(2)
        elif key == "l":
            self._answerCard(3)
        elif key == ";":
            self._answerCard(4)
        else:
            return _old(self, evt)
    else:
        return _old(self, evt)

Reviewer._keyHandler = wrap(Reviewer._keyHandler, keyHandler, "around")

    params = urllib.urlencode({"timestamp": data["date"],
                               "value": data["value"],
                               "comment": data["comment"],
                               "auth_token": token})

    conn = httplib.HTTPSConnection(base)
    conn.request("POST", api, params, headers)
    response = conn.getresponse()
    if not response.status == 200:
        raise Exception("transmission failed:", response.status, response.reason, response.read())
    conn.close()

def beeminderUpdate(obj, _old=None):
    ret = _old(obj)
    col = mw.col or mw.syncer.thread.col
    if col is not None:
        checkCollection(col)

    return ret

# convert time to timestamp because python sucks
def timestamp(time):
    epoch = datetime.datetime.utcfromtimestamp(0)
    delta = time - epoch
    timestamp = "%d" % delta.total_seconds()
    return timestamp

# run update whenever we sync a deck
anki.sync.Syncer.sync = wrap(anki.sync.Syncer.sync, beeminderUpdate, "around")
Example #56
0
def extscmhash(self, m, _old):
    "Return a hash of parts of the schema, to check model compatibility."
    _old(self, m)

    s = m['css']
    for f in m['flds']:
        s += f['name']
    for t in m['tmpls']:
        s += t['name']
        for fmt in ('qfmt', 'afmt'):
            s += t[fmt]
    return checksum(s)


ModelManager.scmhash = wrap(ModelManager.scmhash, extscmhash, "around")

# Stuff used during development
##########################################################################


def debug():
    card = mw.col.sched.getCard()
    #showText(str(card.nid), title="anki-extended-scmhash debug output")

    note = card.note()
    #showText(str(note.model), title="anki-extended-scmhash debug output")

    model = note.model()

    # debugtext = str(model['tmpls'][0]['name'])
Example #57
0
def reduce_format_qa(self, text):
    u"""Remove elements with a given class before displaying."""
    soup = BeautifulSoup(text)
    for hide in soup.findAll(True, {'class': re.compile(
            '\\b' + hide_class_name + '\\b')}):
        hide.extract()
    return original_format_qa(self, unicode(soup))


def copy_arrow():
    u"""Copy the image file to the collection."""
    if not os.path.exists(os.path.join(
            mw.col.media.dir(), collection_arrow_name)):
        shutil.copy(
            os.path.join(mw.pm.addonFolder(), 'color_icons',
                         original_arrow_name),
            collection_arrow_name)


original_review_link_handler = Reviewer._linkHandler
Reviewer._linkHandler = review_link_handler_wrapper

original_format_qa = DataModel.formatQA
DataModel.formatQA = reduce_format_qa

addHook("mungeQA", play_button_filter)
Browser._openPreview = wrap(Browser._openPreview, add_preview_link_handler)
CardLayout.addTab = wrap(CardLayout.addTab, add_clayout_link_handler)
addHook("profileLoaded", copy_arrow)
Example #58
0
        AgainColor = getUserOption("AgainColor")
        HardColor = getUserOption("HardColor")
        GoodColor = getUserOption("GoodColor")
        EasyColor = getUserOption("EasyColor")                        

    #set font size options
    if getUserOption("button font size") == "S":
        FONTSIZE = ""
    elif getUserOption("button font size") == "M":
        FONTSIZE = "font-size: 16px;"
    elif getUserOption("button font size") == "L":
        FONTSIZE = "font-size: 20px;"

    # show tooltip in according color
    if len(cB) > 0 :
        # display the tooltip in an according color
        if (cB[0][1]=="Again" or "Again" in cB[0][1]):
            utils.tooltipWithColour(("<div style='color:#3a3a3a;%s'>Again</div>" % (FONTSIZE)), AgainColor, x=x1, y=y, xref=xref, period=time, width=width, height=height)
        elif (cB[0][1]=="Hard" or "Hard" in cB[0][1]):
            utils.tooltipWithColour(("<div style='color:#3a3a3a;%s'>Hard</div>" % (FONTSIZE)), HardColor, x=x2, y=y, xref=xref, period=time, width=width, height=height)
        elif (cB[0][1]=="Good" or "Good" in cB[0][1]):
            utils.tooltipWithColour(("<div style='color:#3a3a3a;%s'>Good</div>" % (FONTSIZE)), GoodColor, x=x3, y=y, xref=xref, period=time, width=width, height=height)
        elif (cB[0][1]=="Easy" or "Easy" in cB[0][1]):
            utils.tooltipWithColour(("<div style='color:#3a3a3a;%s'>Easy</div>" % (FONTSIZE)), EasyColor, x=x4, y=y, xref=xref, period=time, width=width, height=height)
        else:
            # default behavior for unforeseen cases
            tooltip(cB[0][1])

if getUserOption("confirmation", True):
    Reviewer._answerCard  = wrap(Reviewer._answerCard, answerCard_before, "before")
    Reviewer.CustomAnswerCard = answerCard_before
Example #59
0
        #ah.habitica.scorecount_on_sync()
        #scorecount now sent in a background thread after scoring
        if ah.settings.score_on_sync:
            score_backlog(True)
    ah.log.debug("End function")


#################
### Wrap Code ###
#################

addHook("profileLoaded", grab_profile)
#addHook("sync", ahsync)
addHook("unloadProfile", save_stats)
#AnkiQt.closeEvent = wrap(AnkiQt.closeEvent, save_stats, "before")
Reviewer.nextCard = wrap(Reviewer.nextCard, hrpg_realtime, "before")

#Insert progress bar into bottom review stats
#       along with database scoring and realtime habitica routines
orig_remaining = Reviewer._remaining
def my_remaining(x):
    ah.log.debug("Begin function")
    ret = orig_remaining(x)
    #if compare_score_to_db():
    #hrpg_progbar = make_habit_progbar()
    #hrpg_realtime()
    if not ah.settings.hrpg_progbar == "":
        ret += " : %s" % (ah.settings.hrpg_progbar)
    if ah.settings.initialized and ah.settings.show_mini_stats:
        mini_stats = ah.habitica.compact_habitica_stats()
        if mini_stats: ret += " : %s" % (mini_stats)
Example #60
0
# Copyright 2016-2020 Matthew Hayes

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from progress_stats.graphs import progressGraphs

import anki.stats
from anki.hooks import wrap


anki.stats.CollectionStats.easeGraph = \
    wrap(anki.stats.CollectionStats.easeGraph, progressGraphs, pos="")