Python源码示例:anki.hooks.wrap()

示例1
def initializeLinks():
    Overview._linkHandler = wrap(Overview._linkHandler, heatmapLinkHandler, "around")
    DeckBrowser._linkHandler = wrap(
        DeckBrowser._linkHandler, heatmapLinkHandler, "around"
    )
    DeckStats._linkHandler = heatmapLinkHandler

    try:
        from aqt.gui_hooks import browser_will_search

        browser_will_search.append(on_browser_will_search)
    except (ImportError, ModuleNotFoundError):
        from anki.find import Finder

        Finder.findRevlogEntries = findRevlogEntries
        Finder.__init__ = wrap(Finder.__init__, addFinders, "after") 
示例2
def _setupAddonMenus20(self):
        from anki.hooks import wrap
        from aqt.addons import AddonManager
        from ..gui.dialog_configeditor import ConfigEditor
        
        from ..consts import ADDON
        from ..platform import PATH_ADDONS
        
        def onEdit(mgr, file_path, _old):
            entry_point = os.path.join(
                PATH_ADDONS, ADDON.NAME + ".py")
            if not file_path == entry_point:
                return _old(mgr, file_path)
            if self.conf_action:
                self.conf_action()
            elif "local" in self._config:
                ConfigEditor(self, self.mw)
            else:
                return _old(mgr, file_path)
        
        AddonManager.onEdit = wrap(AddonManager.onEdit, onEdit, "around")

    # Local storage
    ###################################################################### 
示例3
def _ensureSaveBeforeConfigGUILoaded(self) -> None:
        """ugly workaround, drop as soon as possible"""

        if checkVersion(ANKI.VERSION, "2.1.17"):
            self._mw.addonManager.setConfigAction(
                self._namespace, self._saveBeforeConfigLoaded
            )
            return

        from anki.hooks import wrap
        from aqt.addons import AddonsDialog

        def wrappedOnConfig(addonsDialog: AddonsDialog, *args, **kwargs):
            """Save before config editor is invoked"""
            addon = addonsDialog.onlyOneSelected()
            if not addon or addon != self._namespace:
                return
            self.save()

        AddonsDialog.onConfig = wrap(AddonsDialog.onConfig, wrappedOnConfig, "before") 
示例4
def _setupAddonMenus20(self):
        from anki.hooks import wrap
        from aqt.addons import AddonManager
        from ..gui.dialog_configeditor import ConfigEditor
        
        from ..consts import ADDON
        from ..platform import DIRECTORY_ADDONS
        
        def onEdit(mgr, file_path, _old):
            entry_point = os.path.join(
                DIRECTORY_ADDONS, ADDON.NAME + ".py")
            if not file_path == entry_point:
                return _old(mgr, file_path)
            if self.conf_action:
                self.conf_action()
            elif "local" in self._config:
                ConfigEditor(self, self.mw)
            else:
                return _old(mgr, file_path)
        
        AddonManager.onEdit = wrap(AddonManager.onEdit, onEdit, "around")

    # Local storage
    ###################################################################### 
示例5
def onInsertCloze(self, _old):
    """Handles cloze-wraps when the add-on model is active"""
    if not checkModel(self.note.model(), fields=False, notify=False):
        return _old(self)
    # find the highest existing cloze
    highest = 0
    for name, val in self.note.items():
        m = re.findall("\[\[oc(\d+)::", val)
        if m:
            highest = max(highest, sorted([int(x) for x in m])[-1])
    # reuse last?
    if not self.mw.app.keyboardModifiers() & Qt.AltModifier:
        highest += 1
    # must start at 1
    highest = max(1, highest)
    self.web.eval("wrap('[[oc%d::', ']]');" % highest) 
示例6
def initializeEditor():
    # Editor widget
    Editor.onCloze = wrap(Editor.onCloze, onInsertCloze, "around")
    Editor.onOlClozeButton = onOlClozeButton
    Editor.onOlOptionsButton = onOlOptionsButton
    Editor.onInsertMultipleClozes = onInsertMultipleClozes
    Editor.onRemoveClozes = onRemoveClozes
    if ANKI20:
        addHook("setupEditorButtons", onSetupEditorButtons20)
    else:
        addHook("setupEditorButtons", onSetupEditorButtons21)

    # AddCard / EditCurrent windows
    AddCards.addNote = wrap(AddCards.addNote, onAddNote, "around")
    if ANKI20:
        AddCards.addCards = wrap(AddCards.addCards, onAddCards, "around")
        EditCurrent.onSave = wrap(EditCurrent.onSave, onEditCurrent, "around")
    else:
        # always use the methods that are fired on editor save:
        AddCards._addCards = wrap(AddCards._addCards, onAddCards, "around")
        EditCurrent._saveAndClose = wrap(EditCurrent._saveAndClose,
                                         onEditCurrent, "around") 
示例7
def load():
    ruby.install()
    chinese.install()
    addHook('profileLoaded', load_menu)
    addHook('profileLoaded', add_models)
    addHook('loadNote', append_tone_styling)
    addHook('unloadProfile', config.save)
    addHook('unloadProfile', dictionary.conn.close)
    addHook('unloadProfile', unload_menu)
    CollectionStats.todayStats = wrap(
        CollectionStats.todayStats, todayStats, 'around'
    )
    EditManager() 
示例8
def patch_config():
    from aqt.clayout import CardLayout

    from .config import add_maobi_button

    CardLayout.setupButtons = wrap(CardLayout.setupButtons, add_maobi_button) 
示例9
def initializeViews():
    try:
        from aqt.gui_hooks import (
            deck_browser_will_render_content,
            overview_will_render_content,
        )

        deck_browser_will_render_content.append(on_deckbrowser_will_render_content)
        overview_will_render_content.append(on_overview_will_render_content)
    except (ImportError, ModuleNotFoundError):
        Overview._body = ov_body
        Overview._renderPage = overviewRenderPage
        DeckBrowser._renderStats = wrap(
            DeckBrowser._renderStats, deckbrowserRenderStats, "around"
        )

    # TODO: Submit Anki PR to add hook to CollectionStats.report
    CollectionStats.dueGraph = wrap(
        CollectionStats.dueGraph, collectionStatsDueGraph, "around"
    )
    DeckStats.__init__ = wrap(DeckStats.__init__, deckStatsInit21, "after")
    DeckStats.reject = wrap(DeckStats.reject, deckStatsReject)

    # Initially set up hotkey:
    # TODO: Migrate to config.json storage, so that profile hook is not required
    try:
        from aqt.gui_hooks import profile_did_open

        profile_did_open.append(initializeHotkey)
    except (ImportError, ModuleNotFoundError):
        addHook("profileLoaded", initializeHotkey)

    # Update hotkey on config save:
    addHook("config_saved_heatmap", initializeHotkey) 
示例10
def customize_addcards():
    AddCards.setupButtons = wrap(
        AddCards.setupButtons, add_query_button, "before") 
示例11
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) 
示例12
def onProfileLoaded():
    """
    Apply modifications to Browser and Previewer
    Needs to be run after all other add-ons have been loaded
    """
    Browser.onTagMove = onTagMove
    Browser.switchToSidebarItem = switchToSidebarItem
    Browser.setFilter = wrap(Browser.setFilter, onSetFilter, "around")
    Previewer.setupHotkeys = wrap(Previewer.setupHotkeys, onSetupHotkeys, "after") 
示例13
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")

# --- Hooks: --- 
示例14
def pasteWithoutLinebreaks(self):
    """Remove linebreaks from clipboard and paste"""
    mime = self.web.mungeClip(mode=QClipboard.Clipboard)
    html = mime.html()
    text = mime.text()

    if not(text or html):
        return
    
    if html:
        content = re.sub(re_lb_open, " ", html)
        content = re.sub(re_lb_close, "", content)
    else:
        if PRESERVE_PARAGRAPHS:
            # remove EOL hyphens:
            content = re.sub(r"-\n(?!\n)", "", text) 
            # skip ends of sentences:
            content = re.sub(r"(?<!\.|\!|\:)\n(?!\n)", " ", content)
            # strip extraneous linebreaks while rejoining with <br> tags
            content = "<br />".join(i.strip() for i in content.split("\n"))
        else:
            content = content.replace("\n", " ")

    self.web.eval("""
        var pasteHTML = function(html) {
            setFormat("inserthtml", html);
        };
        var filterHTML = function(html) {
            // wrap it in <top> as we aren't allowed to change top level elements
            var top = $.parseHTML("<ankitop>" + html + "</ankitop>")[0];
            filterNode(top);
            var outHtml = top.innerHTML;
            // get rid of nbsp
            outHtml = outHtml.replace(/&nbsp;/ig, " ");
            return outHtml;
        };
        pasteHTML(%s);
        """ % json.dumps(content))

    if TOOLTIP:
        tooltip("Pasting without linebreaks", period=500) 
示例15
def initializeReviewer():
    if ANKI20:
        Reviewer._keyHandler = wrap(
            Reviewer._keyHandler, newKeyHandler20, "before")
    else:
        Reviewer._shortcutKeys = wrap(Reviewer._shortcutKeys, onShortcutKeys21,
                                      "around") 
示例16
def initializeScheduler():
    for scheduler in SCHEDULERS:
        scheduler._burySiblings = wrap(
            scheduler._burySiblings, myBurySiblings, "around") 
示例17
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 
示例18
def init_addon():
    """ Executed once on Anki startup. """
    global origEditorContextMenuEvt

    gui_hooks.webview_did_receive_js_message.append(expanded_on_bridge_cmd)
    
    #todo: Find out if there is a better moment to start index creation
    state.db_file_existed = create_db_file_if_not_exists()

    gui_hooks.profile_did_open.append(build_index)
    gui_hooks.profile_did_open.append(insert_scripts)
    gui_hooks.profile_did_open.append(lambda : recalculate_priority_queue(True))

    if conf_or_def("searchOnTagEntry", True):
        TagEdit.keyPressEvent = wrap(TagEdit.keyPressEvent, tag_edit_keypress, "around")

    setup_tagedit_timer()

    # add new notes to search index when adding
    gui_hooks.add_cards_did_add_note.append(add_note_to_index)

    # update notes in index when changed through the "Edit" button
    EditDialog.saveAndClose = wrap(EditDialog.saveAndClose, editor_save_with_index_update, "around")

    # register add-on's shortcuts 
    gui_hooks.editor_did_init_shortcuts.append(register_shortcuts) 
    # reset state after the add/edit dialog is opened
    gui_hooks.editor_did_init_shortcuts.append(reset_state) 

    # activate nighmode if Anki's nightmode is active
    gui_hooks.editor_did_init_shortcuts.append(activate_nightmode) 

    # add-on internal hooks
    setup_hooks()

    # add shortcuts
    aqt.editor._html += """
    <script>
            document.addEventListener("keydown", function (e) {globalKeydown(e); }, false);
    </script>"""
    
    #this inserts all the javascript functions in scripts.js into the editor webview
    aqt.editor._html += getScriptPlatformSpecific()

    #when a note is loaded (i.e. the add cards dialog is opened), we have to insert our html for the search ui
    gui_hooks.editor_did_load_note.append(on_load_note) 
示例19
def customize_addcards():
    """
    add button to addcards window
    """

    def add_query_button(self):
        '''
        add a button in add card window
        '''
        bb = self.form.buttonBox
        ar = QDialogButtonBox.ActionRole
        # button
        fastwqBtn = QPushButton(_("QUERY") + u" " + downArrow())
        fastwqBtn.setShortcut(QKeySequence(my_shortcut))
        fastwqBtn.setToolTip(_(u"Shortcut: %s") % shortcut(my_shortcut))
        bb.addButton(fastwqBtn, ar)

        # signal
        def onQuery(e):
            if isinstance(e, QMouseEvent):
                if e.buttons() & Qt.LeftButton:
                    menu = QMenu(self)
                    menu.addAction(
                        _("ALL_FIELDS"),
                        lambda: query_from_editor_fields(self.editor),
                        QKeySequence(my_shortcut))
                    # default options
                    mid = self.editor.note.model()['id']
                    conf = config.get_maps(mid)
                    conf = {
                        'list': [conf],
                        'def': 0
                    } if isinstance(conf, list) else conf
                    maps_list = conf['list']
                    if len(maps_list) > 1:
                        menu.addSeparator()
                        for i, maps in enumerate(maps_list):
                            menu.addAction(
                                _OK_ICON if i == conf['def'] else _NULL_ICON,
                                _('CONFIG_INDEX') % (i + 1) if isinstance(
                                    maps, list) else maps['name'],
                                lambda mid=mid, i=i: set_options_def(mid, i))
                        menu.addSeparator()
                    # end default options
                    menu.addAction(_("OPTIONS"), lambda: show_options(self, self.editor.note.model()['id']))
                    menu.exec_(
                        fastwqBtn.mapToGlobal(QPoint(0, fastwqBtn.height())))
            else:
                query_from_editor_fields(self.editor)

        fastwqBtn.mousePressEvent = onQuery
        fastwqBtn.clicked.connect(onQuery)

    AddCards.setupButtons = wrap(AddCards.setupButtons, add_query_button,
                                 "after") 
示例20
def customize_addcards():
    """
    add button to addcards window
    """
    def add_query_button(self):
        '''
        add a button in add card window
        '''
        bb = self.form.buttonBox
        ar = QDialogButtonBox.ActionRole
        # button
        fastwqBtn = QPushButton(_("QUERY") + u" " + downArrow())
        fastwqBtn.setShortcut(QKeySequence(my_shortcut))
        fastwqBtn.setToolTip(
            _(u"Shortcut: %s") % shortcut(my_shortcut)
        )
        bb.addButton(fastwqBtn, ar)
        # signal
        def onQuery(e):
            if isinstance(e, QMouseEvent):
                if e.buttons() & Qt.LeftButton:
                    menu = QMenu(self)
                    menu.addAction(_("ALL_FIELDS"), lambda: query_from_editor_fields(self.editor), QKeySequence(my_shortcut))
                    # default options
                    mid = self.editor.note.model()['id']
                    conf = config.get_maps(mid)
                    conf = {'list': [conf], 'def': 0} if isinstance(conf, list) else conf
                    maps_list = conf['list']
                    if len(maps_list) > 1:
                        menu.addSeparator()
                        for i, maps in enumerate(maps_list):
                            menu.addAction(
                                _OK_ICON if i==conf['def'] else _NULL_ICON,
                                _('CONFIG_INDEX') % (i+1) if isinstance(maps, list) else maps['name'],
                                lambda mid=mid, i=i: set_options_def(mid, i)
                            )
                        menu.addSeparator()
                    # end default options
                    menu.addAction(_("OPTIONS"), lambda: show_options(self, self.editor.note.model()['id']))
                    menu.exec_(fastwqBtn.mapToGlobal(QPoint(0, fastwqBtn.height())))
            else:
                query_from_editor_fields(self.editor)

        fastwqBtn.mousePressEvent = onQuery
        fastwqBtn.clicked.connect(onQuery)
    
    AddCards.setupButtons = wrap(
        AddCards.setupButtons, 
        add_query_button, 
        "after"
    )