mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 16:56:36 -04:00
add some more hooks; stringify fully qualified types
To avoid circular imports, types that contain a '.' are automatically converted to strings.
This commit is contained in:
parent
2921037c7b
commit
2fa662f7ae
7 changed files with 210 additions and 19 deletions
|
@ -355,13 +355,17 @@ prepare_searches_hook = PrepareSearchesHook()
|
|||
|
||||
|
||||
class RemoveNotesHook:
|
||||
_hooks: List[Callable[[anki.storage._Collection, List[int]], None]] = []
|
||||
_hooks: List[Callable[["anki.storage._Collection", List[int]], None]] = []
|
||||
|
||||
def append(self, cb: Callable[[anki.storage._Collection, List[int]], None]) -> None:
|
||||
def append(
|
||||
self, cb: Callable[["anki.storage._Collection", List[int]], None]
|
||||
) -> None:
|
||||
"""(col: anki.storage._Collection, ids: List[int])"""
|
||||
self._hooks.append(cb)
|
||||
|
||||
def remove(self, cb: Callable[[anki.storage._Collection, List[int]], None]) -> None:
|
||||
def remove(
|
||||
self, cb: Callable[["anki.storage._Collection", List[int]], None]
|
||||
) -> None:
|
||||
self._hooks.remove(cb)
|
||||
|
||||
def __call__(self, col: anki.storage._Collection, ids: List[int]) -> None:
|
||||
|
@ -388,7 +392,7 @@ class RenderedCardTemplateFilter:
|
|||
Dict[str, str],
|
||||
Dict[str, Any],
|
||||
QAData,
|
||||
anki.storage._Collection,
|
||||
"anki.storage._Collection",
|
||||
],
|
||||
str,
|
||||
]
|
||||
|
@ -403,7 +407,7 @@ class RenderedCardTemplateFilter:
|
|||
Dict[str, str],
|
||||
Dict[str, Any],
|
||||
QAData,
|
||||
anki.storage._Collection,
|
||||
"anki.storage._Collection",
|
||||
],
|
||||
str,
|
||||
],
|
||||
|
@ -420,7 +424,7 @@ class RenderedCardTemplateFilter:
|
|||
Dict[str, str],
|
||||
Dict[str, Any],
|
||||
QAData,
|
||||
anki.storage._Collection,
|
||||
"anki.storage._Collection",
|
||||
],
|
||||
str,
|
||||
],
|
||||
|
|
|
@ -32,7 +32,9 @@ class Hook:
|
|||
types = []
|
||||
for arg in self.args or []:
|
||||
(name, type) = arg.split(":")
|
||||
types.append(type.strip())
|
||||
if "." in type:
|
||||
type = '"' + type.strip() + '"'
|
||||
types.append(type)
|
||||
types_str = ", ".join(types)
|
||||
return f"Callable[[{types_str}], {self.return_type or 'None'}]"
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ import anki
|
|||
import aqt.forms
|
||||
from anki.collection import _Collection
|
||||
from anki.consts import *
|
||||
from anki.hooks import addHook, remHook, runFilter, runHook
|
||||
from anki.hooks import addHook, remHook
|
||||
from anki.lang import _, ngettext
|
||||
from anki.utils import (
|
||||
bodyClass,
|
||||
|
@ -26,7 +26,7 @@ from anki.utils import (
|
|||
isMac,
|
||||
isWin,
|
||||
)
|
||||
from aqt import AnkiQt
|
||||
from aqt import AnkiQt, gui_hooks
|
||||
from aqt.qt import *
|
||||
from aqt.sound import allSounds, clearAudioQueue, play
|
||||
from aqt.utils import (
|
||||
|
@ -639,7 +639,7 @@ class Browser(QMainWindow):
|
|||
self.pgDownCut = QShortcut(QKeySequence("Shift+End"), self)
|
||||
self.pgDownCut.activated.connect(self.onLastCard)
|
||||
# add-on hook
|
||||
runHook("browser.setupMenus", self)
|
||||
gui_hooks.browser_setup_menus_hook(self)
|
||||
self.mw.maybeHideAccelerators(self)
|
||||
|
||||
# context menu
|
||||
|
@ -653,8 +653,7 @@ class Browser(QMainWindow):
|
|||
m.addSeparator()
|
||||
for act in self.form.menu_Notes.actions():
|
||||
m.addAction(act)
|
||||
runHook("browser.onContextMenu", self, m)
|
||||
|
||||
gui_hooks.browser_context_menu_hook(self, m)
|
||||
qtMenuShortcutWorkaround(m)
|
||||
m.exec_(QCursor.pos())
|
||||
|
||||
|
@ -845,7 +844,7 @@ class Browser(QMainWindow):
|
|||
self.editor.card = self.card
|
||||
self.singleCard = True
|
||||
self._updateFlagsMenu()
|
||||
runHook("browser.rowChanged", self)
|
||||
gui_hooks.browser_row_changed_hook(self)
|
||||
self._renderPreview(True)
|
||||
|
||||
def refreshCurrentCard(self, note):
|
||||
|
@ -1717,8 +1716,8 @@ where id in %s"""
|
|||
play(audio)
|
||||
|
||||
txt = mungeQA(self.col, txt)
|
||||
txt = runFilter(
|
||||
"prepareQA", txt, c, "preview" + self._previewState.capitalize()
|
||||
gui_hooks.card_text_filter(
|
||||
txt, c, "preview" + self._previewState.capitalize()
|
||||
)
|
||||
self._lastPreviewState = self._previewStateAndMod()
|
||||
self._updatePreviewButtons()
|
||||
|
|
|
@ -9,8 +9,10 @@ from __future__ import annotations
|
|||
|
||||
from typing import Any, Callable, Dict, List # pylint: disable=unused-import
|
||||
|
||||
import aqt
|
||||
from anki.cards import Card
|
||||
from anki.hooks import runFilter, runHook # pylint: disable=unused-import
|
||||
from aqt.qt import QMenu
|
||||
|
||||
# New hook/filter handling
|
||||
##############################################################################
|
||||
|
@ -20,6 +22,132 @@ from anki.hooks import runFilter, runHook # pylint: disable=unused-import
|
|||
# @@AUTOGEN@@
|
||||
|
||||
|
||||
class BrowserContextMenuHook:
|
||||
_hooks: List[Callable[["aqt.browser.Browser", QMenu], None]] = []
|
||||
|
||||
def append(self, cb: Callable[["aqt.browser.Browser", QMenu], None]) -> None:
|
||||
"""(browser: aqt.browser.Browser, menu: QMenu)"""
|
||||
self._hooks.append(cb)
|
||||
|
||||
def remove(self, cb: Callable[["aqt.browser.Browser", QMenu], None]) -> None:
|
||||
self._hooks.remove(cb)
|
||||
|
||||
def __call__(self, browser: aqt.browser.Browser, menu: QMenu) -> None:
|
||||
for hook in self._hooks:
|
||||
try:
|
||||
hook(browser, menu)
|
||||
except:
|
||||
# if the hook fails, remove it
|
||||
self._hooks.remove(hook)
|
||||
raise
|
||||
# legacy support
|
||||
runHook("browser.onContextMenu", browser, menu)
|
||||
|
||||
|
||||
browser_context_menu_hook = BrowserContextMenuHook()
|
||||
|
||||
|
||||
class BrowserRowChangedHook:
|
||||
_hooks: List[Callable[["aqt.browser.Browser"], None]] = []
|
||||
|
||||
def append(self, cb: Callable[["aqt.browser.Browser"], None]) -> None:
|
||||
"""(browser: aqt.browser.Browser)"""
|
||||
self._hooks.append(cb)
|
||||
|
||||
def remove(self, cb: Callable[["aqt.browser.Browser"], None]) -> None:
|
||||
self._hooks.remove(cb)
|
||||
|
||||
def __call__(self, browser: aqt.browser.Browser) -> None:
|
||||
for hook in self._hooks:
|
||||
try:
|
||||
hook(browser)
|
||||
except:
|
||||
# if the hook fails, remove it
|
||||
self._hooks.remove(hook)
|
||||
raise
|
||||
# legacy support
|
||||
runHook("browser.rowChanged", browser)
|
||||
|
||||
|
||||
browser_row_changed_hook = BrowserRowChangedHook()
|
||||
|
||||
|
||||
class BrowserSetupMenusHook:
|
||||
_hooks: List[Callable[["aqt.browser.Browser"], None]] = []
|
||||
|
||||
def append(self, cb: Callable[["aqt.browser.Browser"], None]) -> None:
|
||||
"""(browser: aqt.browser.Browser)"""
|
||||
self._hooks.append(cb)
|
||||
|
||||
def remove(self, cb: Callable[["aqt.browser.Browser"], None]) -> None:
|
||||
self._hooks.remove(cb)
|
||||
|
||||
def __call__(self, browser: aqt.browser.Browser) -> None:
|
||||
for hook in self._hooks:
|
||||
try:
|
||||
hook(browser)
|
||||
except:
|
||||
# if the hook fails, remove it
|
||||
self._hooks.remove(hook)
|
||||
raise
|
||||
# legacy support
|
||||
runHook("browser.setupMenus", browser)
|
||||
|
||||
|
||||
browser_setup_menus_hook = BrowserSetupMenusHook()
|
||||
|
||||
|
||||
class CardTextFilter:
|
||||
_hooks: List[Callable[[str, Card, str], str]] = []
|
||||
|
||||
def append(self, cb: Callable[[str, Card, str], str]) -> None:
|
||||
"""(text: str, card: Card, kind: str)"""
|
||||
self._hooks.append(cb)
|
||||
|
||||
def remove(self, cb: Callable[[str, Card, str], str]) -> None:
|
||||
self._hooks.remove(cb)
|
||||
|
||||
def __call__(self, text: str, card: Card, kind: str) -> str:
|
||||
for filter in self._hooks:
|
||||
try:
|
||||
text = filter(text, card, kind)
|
||||
except:
|
||||
# if the hook fails, remove it
|
||||
self._hooks.remove(filter)
|
||||
raise
|
||||
# legacy support
|
||||
runFilter("prepareQA", text, card, kind)
|
||||
return text
|
||||
|
||||
|
||||
card_text_filter = CardTextFilter()
|
||||
|
||||
|
||||
class CurrentNoteTypeChangedHook:
|
||||
_hooks: List[Callable[[Dict[str, Any]], None]] = []
|
||||
|
||||
def append(self, cb: Callable[[Dict[str, Any]], None]) -> None:
|
||||
"""(notetype: Dict[str, Any])"""
|
||||
self._hooks.append(cb)
|
||||
|
||||
def remove(self, cb: Callable[[Dict[str, Any]], None]) -> None:
|
||||
self._hooks.remove(cb)
|
||||
|
||||
def __call__(self, notetype: Dict[str, Any]) -> None:
|
||||
for hook in self._hooks:
|
||||
try:
|
||||
hook(notetype)
|
||||
except:
|
||||
# if the hook fails, remove it
|
||||
self._hooks.remove(hook)
|
||||
raise
|
||||
# legacy support
|
||||
runHook("currentModelChanged")
|
||||
|
||||
|
||||
current_note_type_changed_hook = CurrentNoteTypeChangedHook()
|
||||
|
||||
|
||||
class MpvIdleHook:
|
||||
_hooks: List[Callable[[], None]] = []
|
||||
|
||||
|
@ -116,4 +244,29 @@ class ReviewerShowingQuestionHook:
|
|||
|
||||
|
||||
reviewer_showing_question_hook = ReviewerShowingQuestionHook()
|
||||
|
||||
|
||||
class WebviewContextMenuHook:
|
||||
_hooks: List[Callable[["aqt.webview.AnkiWebView", QMenu], None]] = []
|
||||
|
||||
def append(self, cb: Callable[["aqt.webview.AnkiWebView", QMenu], None]) -> None:
|
||||
"""(webview: aqt.webview.AnkiWebView, menu: QMenu)"""
|
||||
self._hooks.append(cb)
|
||||
|
||||
def remove(self, cb: Callable[["aqt.webview.AnkiWebView", QMenu], None]) -> None:
|
||||
self._hooks.remove(cb)
|
||||
|
||||
def __call__(self, webview: aqt.webview.AnkiWebView, menu: QMenu) -> None:
|
||||
for hook in self._hooks:
|
||||
try:
|
||||
hook(webview, menu)
|
||||
except:
|
||||
# if the hook fails, remove it
|
||||
self._hooks.remove(hook)
|
||||
raise
|
||||
# legacy support
|
||||
runHook("AnkiWebView.contextMenuEvent", webview, menu)
|
||||
|
||||
|
||||
webview_context_menu_hook = WebviewContextMenuHook()
|
||||
# @@AUTOGEN@@
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
# Copyright: Ankitects Pty Ltd and contributors
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
from anki.hooks import addHook, remHook, runHook
|
||||
from anki.hooks import addHook, remHook
|
||||
from anki.lang import _
|
||||
from aqt import gui_hooks
|
||||
from aqt.qt import *
|
||||
from aqt.utils import shortcut
|
||||
|
||||
|
@ -86,7 +87,7 @@ class ModelChooser(QHBoxLayout):
|
|||
cdeck = self.deck.decks.current()
|
||||
cdeck["mid"] = m["id"]
|
||||
self.deck.decks.save(cdeck)
|
||||
runHook("currentModelChanged")
|
||||
gui_hooks.current_note_type_changed_hook(current)
|
||||
self.mw.reset()
|
||||
|
||||
def updateModels(self):
|
||||
|
|
|
@ -5,9 +5,9 @@ import json
|
|||
import math
|
||||
import sys
|
||||
|
||||
from anki.hooks import runHook
|
||||
from anki.lang import _
|
||||
from anki.utils import isLin, isMac, isWin
|
||||
from aqt import gui_hooks
|
||||
from aqt.qt import *
|
||||
from aqt.utils import openLink
|
||||
|
||||
|
@ -182,7 +182,7 @@ class AnkiWebView(QWebEngineView): # type: ignore
|
|||
m = QMenu(self)
|
||||
a = m.addAction(_("Copy"))
|
||||
a.triggered.connect(self.onCopy)
|
||||
runHook("AnkiWebView.contextMenuEvent", self, m)
|
||||
gui_hooks.webview_context_menu_hook(self, m)
|
||||
m.popup(QCursor.pos())
|
||||
|
||||
def dropEvent(self, evt):
|
||||
|
|
|
@ -27,6 +27,38 @@ hooks = [
|
|||
legacy_hook="showAnswer",
|
||||
legacy_no_args=True,
|
||||
),
|
||||
Hook(
|
||||
name="current_note_type_changed",
|
||||
args=["notetype: Dict[str, Any]"],
|
||||
legacy_hook="currentModelChanged",
|
||||
legacy_no_args=True,
|
||||
),
|
||||
Hook(
|
||||
name="browser_setup_menus",
|
||||
args=["browser: aqt.browser.Browser"],
|
||||
legacy_hook="browser.setupMenus",
|
||||
),
|
||||
Hook(
|
||||
name="browser_context_menu",
|
||||
args=["browser: aqt.browser.Browser", "menu: QMenu"],
|
||||
legacy_hook="browser.onContextMenu",
|
||||
),
|
||||
Hook(
|
||||
name="browser_row_changed",
|
||||
args=["browser: aqt.browser.Browser"],
|
||||
legacy_hook="browser.rowChanged",
|
||||
),
|
||||
Hook(
|
||||
name="card_text",
|
||||
args=["text: str", "card: Card", "kind: str"],
|
||||
return_type="str",
|
||||
legacy_hook="prepareQA",
|
||||
),
|
||||
Hook(
|
||||
name="webview_context_menu",
|
||||
args=["webview: aqt.webview.AnkiWebView", "menu: QMenu"],
|
||||
legacy_hook="AnkiWebView.contextMenuEvent",
|
||||
),
|
||||
]
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
Loading…
Reference in a new issue