add more hooks, tweak wording for consistency

This commit is contained in:
Damien Elmes 2020-01-15 12:16:54 +10:00
parent f021d616dd
commit 84c17e1f02
7 changed files with 774 additions and 60 deletions

View file

@ -639,7 +639,7 @@ class Browser(QMainWindow):
self.pgDownCut = QShortcut(QKeySequence("Shift+End"), self) self.pgDownCut = QShortcut(QKeySequence("Shift+End"), self)
self.pgDownCut.activated.connect(self.onLastCard) self.pgDownCut.activated.connect(self.onLastCard)
# add-on hook # add-on hook
gui_hooks.browser_setup_menus_hook(self) gui_hooks.browser_menus_did_setup_hook(self)
self.mw.maybeHideAccelerators(self) self.mw.maybeHideAccelerators(self)
# context menu # context menu
@ -653,7 +653,7 @@ class Browser(QMainWindow):
m.addSeparator() m.addSeparator()
for act in self.form.menu_Notes.actions(): for act in self.form.menu_Notes.actions():
m.addAction(act) m.addAction(act)
gui_hooks.browser_context_menu_hook(self, m) gui_hooks.browser_context_menu_will_show_hook(self, m)
qtMenuShortcutWorkaround(m) qtMenuShortcutWorkaround(m)
m.exec_(QCursor.pos()) m.exec_(QCursor.pos())
@ -844,7 +844,7 @@ class Browser(QMainWindow):
self.editor.card = self.card self.editor.card = self.card
self.singleCard = True self.singleCard = True
self._updateFlagsMenu() self._updateFlagsMenu()
gui_hooks.browser_row_changed_hook(self) gui_hooks.browser_row_did_change_hook(self)
self._renderPreview(True) self._renderPreview(True)
def refreshCurrentCard(self, note): def refreshCurrentCard(self, note):

View file

@ -8,9 +8,9 @@ import re
import aqt import aqt
from anki.consts import * from anki.consts import *
from anki.hooks import runFilter
from anki.lang import _, ngettext from anki.lang import _, ngettext
from anki.utils import bodyClass, isMac, isWin, joinFields from anki.utils import bodyClass, isMac, isWin, joinFields
from aqt import gui_hooks
from aqt.qt import * from aqt.qt import *
from aqt.sound import clearAudioQueue, playFromText from aqt.sound import clearAudioQueue, playFromText
from aqt.utils import ( from aqt.utils import (
@ -335,10 +335,10 @@ Please create a new card type first."""
bodyclass = bodyClass(self.mw.col, c) bodyclass = bodyClass(self.mw.col, c)
q = ti(mungeQA(self.mw.col, c.q(reload=True))) q = ti(mungeQA(self.mw.col, c.q(reload=True)))
q = runFilter("prepareQA", q, c, "clayoutQuestion") q = gui_hooks.card_text_filter(q, c, "clayoutQuestion")
a = ti(mungeQA(self.mw.col, c.a()), type="a") a = ti(mungeQA(self.mw.col, c.a()), type="a")
a = runFilter("prepareQA", a, c, "clayoutAnswer") a = gui_hooks.card_text_filter(a, c, "clayoutAnswer")
# use _showAnswer to avoid the longer delay # use _showAnswer to avoid the longer delay
self.pform.frontWeb.eval("_showAnswer(%s,'%s');" % (json.dumps(q), bodyclass)) self.pform.frontWeb.eval("_showAnswer(%s,'%s');" % (json.dumps(q), bodyclass))

View file

@ -7,12 +7,13 @@ See pylib/anki/hooks.py
from __future__ import annotations from __future__ import annotations
from typing import Any, Callable, Dict, List # pylint: disable=unused-import from typing import Any, Callable, Dict, List, Tuple
import anki
import aqt import aqt
from anki.cards import Card from anki.cards import Card
from anki.hooks import runFilter, runHook # pylint: disable=unused-import from anki.hooks import runFilter, runHook
from aqt.qt import QMenu from aqt.qt import QMenu, QShortcut
# New hook/filter handling # New hook/filter handling
############################################################################## ##############################################################################
@ -22,7 +23,57 @@ from aqt.qt import QMenu
# @@AUTOGEN@@ # @@AUTOGEN@@
class _BrowserContextMenuHook: class _AddCardsHistoryMenuWillShowHook:
_hooks: List[Callable[["aqt.addcards.AddCards", QMenu], None]] = []
def append(self, cb: Callable[["aqt.addcards.AddCards", QMenu], None]) -> None:
"""(addcards: aqt.addcards.AddCards, menu: QMenu)"""
self._hooks.append(cb)
def remove(self, cb: Callable[["aqt.addcards.AddCards", QMenu], None]) -> None:
self._hooks.remove(cb)
def __call__(self, addcards: aqt.addcards.AddCards, menu: QMenu) -> None:
for hook in self._hooks:
try:
hook(addcards, menu)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("AddCards.onHistory", addcards, menu)
add_cards_history_menu_will_show_hook = _AddCardsHistoryMenuWillShowHook()
class _AddCardsNoteDidAddHook:
_hooks: List[Callable[["anki.notes.Note"], None]] = []
def append(self, cb: Callable[["anki.notes.Note"], None]) -> None:
"""(note: anki.notes.Note)"""
self._hooks.append(cb)
def remove(self, cb: Callable[["anki.notes.Note"], None]) -> None:
self._hooks.remove(cb)
def __call__(self, note: anki.notes.Note) -> None:
for hook in self._hooks:
try:
hook(note)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("AddCards.noteAdded", note)
add_cards_note_did_add_hook = _AddCardsNoteDidAddHook()
class _BrowserContextMenuWillShowHook:
_hooks: List[Callable[["aqt.browser.Browser", QMenu], None]] = [] _hooks: List[Callable[["aqt.browser.Browser", QMenu], None]] = []
def append(self, cb: Callable[["aqt.browser.Browser", QMenu], None]) -> None: def append(self, cb: Callable[["aqt.browser.Browser", QMenu], None]) -> None:
@ -44,35 +95,10 @@ class _BrowserContextMenuHook:
runHook("browser.onContextMenu", browser, menu) runHook("browser.onContextMenu", browser, menu)
browser_context_menu_hook = _BrowserContextMenuHook() browser_context_menu_will_show_hook = _BrowserContextMenuWillShowHook()
class _BrowserRowChangedHook: class _BrowserMenusDidSetupHook:
_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]] = [] _hooks: List[Callable[["aqt.browser.Browser"], None]] = []
def append(self, cb: Callable[["aqt.browser.Browser"], None]) -> None: def append(self, cb: Callable[["aqt.browser.Browser"], None]) -> None:
@ -94,7 +120,32 @@ class _BrowserSetupMenusHook:
runHook("browser.setupMenus", browser) runHook("browser.setupMenus", browser)
browser_setup_menus_hook = _BrowserSetupMenusHook() browser_menus_did_setup_hook = _BrowserMenusDidSetupHook()
class _BrowserRowDidChangeHook:
_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_did_change_hook = _BrowserRowDidChangeHook()
class _CardTextFilter: class _CardTextFilter:
@ -123,7 +174,32 @@ class _CardTextFilter:
card_text_filter = _CardTextFilter() card_text_filter = _CardTextFilter()
class _CurrentNoteTypeChangedHook: class _CollectionDidLoadHook:
_hooks: List[Callable[["anki.storage._Collection"], None]] = []
def append(self, cb: Callable[["anki.storage._Collection"], None]) -> None:
"""(col: anki.storage._Collection)"""
self._hooks.append(cb)
def remove(self, cb: Callable[["anki.storage._Collection"], None]) -> None:
self._hooks.remove(cb)
def __call__(self, col: anki.storage._Collection) -> None:
for hook in self._hooks:
try:
hook(col)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("colLoading", col)
collection_did_load_hook = _CollectionDidLoadHook()
class _CurrentNoteTypeDidChangeHook:
_hooks: List[Callable[[Dict[str, Any]], None]] = [] _hooks: List[Callable[[Dict[str, Any]], None]] = []
def append(self, cb: Callable[[Dict[str, Any]], None]) -> None: def append(self, cb: Callable[[Dict[str, Any]], None]) -> None:
@ -145,7 +221,259 @@ class _CurrentNoteTypeChangedHook:
runHook("currentModelChanged") runHook("currentModelChanged")
current_note_type_changed_hook = _CurrentNoteTypeChangedHook() current_note_type_did_change_hook = _CurrentNoteTypeDidChangeHook()
class _DeckBrowserOptionsMenuWillShowHook:
_hooks: List[Callable[[QMenu, int], None]] = []
def append(self, cb: Callable[[QMenu, int], None]) -> None:
"""(menu: QMenu, deck_id: int)"""
self._hooks.append(cb)
def remove(self, cb: Callable[[QMenu, int], None]) -> None:
self._hooks.remove(cb)
def __call__(self, menu: QMenu, deck_id: int) -> None:
for hook in self._hooks:
try:
hook(menu, deck_id)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("showDeckOptions", menu, deck_id)
deck_browser_options_menu_will_show_hook = _DeckBrowserOptionsMenuWillShowHook()
class _EditorButtonsDidSetupHook:
_hooks: List[Callable[[List, "aqt.editor.Editor"], None]] = []
def append(self, cb: Callable[[List, "aqt.editor.Editor"], None]) -> None:
"""(buttons: List, editor: aqt.editor.Editor)"""
self._hooks.append(cb)
def remove(self, cb: Callable[[List, "aqt.editor.Editor"], None]) -> None:
self._hooks.remove(cb)
def __call__(self, buttons: List, editor: aqt.editor.Editor) -> None:
for hook in self._hooks:
try:
hook(buttons, editor)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
editor_buttons_did_setup_hook = _EditorButtonsDidSetupHook()
class _EditorContextMenuWillShowHook:
_hooks: List[Callable[["aqt.editor.EditorWebView", QMenu], None]] = []
def append(self, cb: Callable[["aqt.editor.EditorWebView", QMenu], None]) -> None:
"""(editor_webview: aqt.editor.EditorWebView, menu: QMenu)"""
self._hooks.append(cb)
def remove(self, cb: Callable[["aqt.editor.EditorWebView", QMenu], None]) -> None:
self._hooks.remove(cb)
def __call__(self, editor_webview: aqt.editor.EditorWebView, menu: QMenu) -> None:
for hook in self._hooks:
try:
hook(editor_webview, menu)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("EditorWebView.contextMenuEvent", editor_webview, menu)
editor_context_menu_will_show_hook = _EditorContextMenuWillShowHook()
class _EditorFieldDidGainFocusHook:
_hooks: List[Callable[["anki.notes.Note", int], None]] = []
def append(self, cb: Callable[["anki.notes.Note", int], None]) -> None:
"""(note: anki.notes.Note, current_field_idx: int)"""
self._hooks.append(cb)
def remove(self, cb: Callable[["anki.notes.Note", int], None]) -> None:
self._hooks.remove(cb)
def __call__(self, note: anki.notes.Note, current_field_idx: int) -> None:
for hook in self._hooks:
try:
hook(note, current_field_idx)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("editFocusGained", note, current_field_idx)
editor_field_did_gain_focus_hook = _EditorFieldDidGainFocusHook()
class _EditorFieldDidLoseFocusFilter:
_hooks: List[Callable[[bool, "anki.notes.Note", int], bool]] = []
def append(self, cb: Callable[[bool, "anki.notes.Note", int], bool]) -> None:
"""(changed: bool, note: anki.notes.Note, current_field_idx: int)"""
self._hooks.append(cb)
def remove(self, cb: Callable[[bool, "anki.notes.Note", int], bool]) -> None:
self._hooks.remove(cb)
def __call__(
self, changed: bool, note: anki.notes.Note, current_field_idx: int
) -> bool:
for filter in self._hooks:
try:
changed = filter(changed, note, current_field_idx)
except:
# if the hook fails, remove it
self._hooks.remove(filter)
raise
# legacy support
runFilter("editFocusLost", changed, note, current_field_idx)
return changed
editor_field_did_lose_focus_filter = _EditorFieldDidLoseFocusFilter()
class _EditorFontForFieldFilter:
_hooks: List[Callable[[str], str]] = []
def append(self, cb: Callable[[str], str]) -> None:
"""(font: str)"""
self._hooks.append(cb)
def remove(self, cb: Callable[[str], str]) -> None:
self._hooks.remove(cb)
def __call__(self, font: str) -> str:
for filter in self._hooks:
try:
font = filter(font)
except:
# if the hook fails, remove it
self._hooks.remove(filter)
raise
# legacy support
runFilter("mungeEditingFontName", font)
return font
editor_font_for_field_filter = _EditorFontForFieldFilter()
class _EditorNoteDidUpdateHook:
_hooks: List[Callable[["aqt.editor.Editor"], None]] = []
def append(self, cb: Callable[["aqt.editor.Editor"], None]) -> None:
"""(editor: aqt.editor.Editor)"""
self._hooks.append(cb)
def remove(self, cb: Callable[["aqt.editor.Editor"], None]) -> None:
self._hooks.remove(cb)
def __call__(self, editor: aqt.editor.Editor) -> None:
for hook in self._hooks:
try:
hook(editor)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("loadNote", editor)
editor_note_did_update_hook = _EditorNoteDidUpdateHook()
class _EditorShortcutsDidSetupHook:
_hooks: List[Callable[[List[Tuple], "aqt.editor.Editor"], None]] = []
def append(self, cb: Callable[[List[Tuple], "aqt.editor.Editor"], None]) -> None:
"""(shortcuts: List[Tuple], editor: aqt.editor.Editor)"""
self._hooks.append(cb)
def remove(self, cb: Callable[[List[Tuple], "aqt.editor.Editor"], None]) -> None:
self._hooks.remove(cb)
def __call__(self, shortcuts: List[Tuple], editor: aqt.editor.Editor) -> None:
for hook in self._hooks:
try:
hook(shortcuts, editor)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("setupEditorShortcuts", shortcuts, editor)
editor_shortcuts_did_setup_hook = _EditorShortcutsDidSetupHook()
class _EditorTagsDidUpdateHook:
_hooks: List[Callable[["anki.notes.Note"], None]] = []
def append(self, cb: Callable[["anki.notes.Note"], None]) -> None:
"""(note: anki.notes.Note)"""
self._hooks.append(cb)
def remove(self, cb: Callable[["anki.notes.Note"], None]) -> None:
self._hooks.remove(cb)
def __call__(self, note: anki.notes.Note) -> None:
for hook in self._hooks:
try:
hook(note)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("tagsUpdated", note)
editor_tags_did_update_hook = _EditorTagsDidUpdateHook()
class _EditorTypingTimerDidFireHook:
_hooks: List[Callable[["anki.notes.Note"], None]] = []
def append(self, cb: Callable[["anki.notes.Note"], None]) -> None:
"""(note: anki.notes.Note)"""
self._hooks.append(cb)
def remove(self, cb: Callable[["anki.notes.Note"], None]) -> None:
self._hooks.remove(cb)
def __call__(self, note: anki.notes.Note) -> None:
for hook in self._hooks:
try:
hook(note)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("editTimer", note)
editor_typing_timer_did_fire_hook = _EditorTypingTimerDidFireHook()
class _MpvIdleHook: class _MpvIdleHook:
@ -196,7 +524,82 @@ class _MpvWillPlayHook:
mpv_will_play_hook = _MpvWillPlayHook() mpv_will_play_hook = _MpvWillPlayHook()
class _ReviewerShowingAnswerHook: class _ProfileDidOpenHook:
_hooks: List[Callable[[], None]] = []
def append(self, cb: Callable[[], None]) -> None:
"""()"""
self._hooks.append(cb)
def remove(self, cb: Callable[[], None]) -> None:
self._hooks.remove(cb)
def __call__(self) -> None:
for hook in self._hooks:
try:
hook()
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("profileLoaded")
profile_did_open_hook = _ProfileDidOpenHook()
class _ProfileWillCloseHook:
_hooks: List[Callable[[], None]] = []
def append(self, cb: Callable[[], None]) -> None:
"""()"""
self._hooks.append(cb)
def remove(self, cb: Callable[[], None]) -> None:
self._hooks.remove(cb)
def __call__(self) -> None:
for hook in self._hooks:
try:
hook()
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("unloadProfile")
profile_will_close_hook = _ProfileWillCloseHook()
class _ReviewDidUndoHook:
_hooks: List[Callable[[int], None]] = []
def append(self, cb: Callable[[int], None]) -> None:
"""(card_id: int)"""
self._hooks.append(cb)
def remove(self, cb: Callable[[int], None]) -> None:
self._hooks.remove(cb)
def __call__(self, card_id: int) -> None:
for hook in self._hooks:
try:
hook(card_id)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("revertedCard", card_id)
review_did_undo_hook = _ReviewDidUndoHook()
class _ReviewerAnswerDidShowHook:
_hooks: List[Callable[[Card], None]] = [] _hooks: List[Callable[[Card], None]] = []
def append(self, cb: Callable[[Card], None]) -> None: def append(self, cb: Callable[[Card], None]) -> None:
@ -218,10 +621,35 @@ class _ReviewerShowingAnswerHook:
runHook("showAnswer") runHook("showAnswer")
reviewer_showing_answer_hook = _ReviewerShowingAnswerHook() reviewer_answer_did_show_hook = _ReviewerAnswerDidShowHook()
class _ReviewerShowingQuestionHook: class _ReviewerContextMenuWillShowHook:
_hooks: List[Callable[["aqt.reviewer.Reviewer", QMenu], None]] = []
def append(self, cb: Callable[["aqt.reviewer.Reviewer", QMenu], None]) -> None:
"""(reviewer: aqt.reviewer.Reviewer, menu: QMenu)"""
self._hooks.append(cb)
def remove(self, cb: Callable[["aqt.reviewer.Reviewer", QMenu], None]) -> None:
self._hooks.remove(cb)
def __call__(self, reviewer: aqt.reviewer.Reviewer, menu: QMenu) -> None:
for hook in self._hooks:
try:
hook(reviewer, menu)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("Reviewer.contextMenuEvent", reviewer, menu)
reviewer_context_menu_will_show_hook = _ReviewerContextMenuWillShowHook()
class _ReviewerQuestionDidShowHook:
_hooks: List[Callable[[Card], None]] = [] _hooks: List[Callable[[Card], None]] = []
def append(self, cb: Callable[[Card], None]) -> None: def append(self, cb: Callable[[Card], None]) -> None:
@ -243,10 +671,186 @@ class _ReviewerShowingQuestionHook:
runHook("showQuestion") runHook("showQuestion")
reviewer_showing_question_hook = _ReviewerShowingQuestionHook() reviewer_question_did_show_hook = _ReviewerQuestionDidShowHook()
class _WebviewContextMenuHook: class _SetupStyleFilter:
_hooks: List[Callable[[str], str]] = []
def append(self, cb: Callable[[str], str]) -> None:
"""(style: str)"""
self._hooks.append(cb)
def remove(self, cb: Callable[[str], str]) -> None:
self._hooks.remove(cb)
def __call__(self, style: str) -> str:
for filter in self._hooks:
try:
style = filter(style)
except:
# if the hook fails, remove it
self._hooks.remove(filter)
raise
# legacy support
runFilter("setupStyle", style)
return style
setup_style_filter = _SetupStyleFilter()
class _StateDidChangeHook:
_hooks: List[Callable[[str, str], None]] = []
def append(self, cb: Callable[[str, str], None]) -> None:
"""(new_state: str, old_state: str)"""
self._hooks.append(cb)
def remove(self, cb: Callable[[str, str], None]) -> None:
self._hooks.remove(cb)
def __call__(self, new_state: str, old_state: str) -> None:
for hook in self._hooks:
try:
hook(new_state, old_state)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("afterStateChange", new_state, old_state)
state_did_change_hook = _StateDidChangeHook()
class _StateDidResetHook:
"""Called when the interface needs to be redisplayed after non-trivial changes have been made."""
_hooks: List[Callable[[], None]] = []
def append(self, cb: Callable[[], None]) -> None:
"""()"""
self._hooks.append(cb)
def remove(self, cb: Callable[[], None]) -> None:
self._hooks.remove(cb)
def __call__(self) -> None:
for hook in self._hooks:
try:
hook()
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("reset")
state_did_reset_hook = _StateDidResetHook()
class _StateDidRevertHook:
_hooks: List[Callable[[str], None]] = []
def append(self, cb: Callable[[str], None]) -> None:
"""(action: str)"""
self._hooks.append(cb)
def remove(self, cb: Callable[[str], None]) -> None:
self._hooks.remove(cb)
def __call__(self, action: str) -> None:
for hook in self._hooks:
try:
hook(action)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("revertedState", action)
state_did_revert_hook = _StateDidRevertHook()
class _StateShortcutsWillChangeHook:
_hooks: List[Callable[[str, List[QShortcut]], None]] = []
def append(self, cb: Callable[[str, List[QShortcut]], None]) -> None:
"""(state: str, shortcuts: List[QShortcut])"""
self._hooks.append(cb)
def remove(self, cb: Callable[[str, List[QShortcut]], None]) -> None:
self._hooks.remove(cb)
def __call__(self, state: str, shortcuts: List[QShortcut]) -> None:
for hook in self._hooks:
try:
hook(state, shortcuts)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
state_shortcuts_will_change_hook = _StateShortcutsWillChangeHook()
class _StateWillChangeHook:
_hooks: List[Callable[[str, str], None]] = []
def append(self, cb: Callable[[str, str], None]) -> None:
"""(new_state: str, old_state: str)"""
self._hooks.append(cb)
def remove(self, cb: Callable[[str, str], None]) -> None:
self._hooks.remove(cb)
def __call__(self, new_state: str, old_state: str) -> None:
for hook in self._hooks:
try:
hook(new_state, old_state)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("beforeStateChange", new_state, old_state)
state_will_change_hook = _StateWillChangeHook()
class _UndoStateDidChangeHook:
_hooks: List[Callable[[bool], None]] = []
def append(self, cb: Callable[[bool], None]) -> None:
"""(can_undo: bool)"""
self._hooks.append(cb)
def remove(self, cb: Callable[[bool], None]) -> None:
self._hooks.remove(cb)
def __call__(self, can_undo: bool) -> None:
for hook in self._hooks:
try:
hook(can_undo)
except:
# if the hook fails, remove it
self._hooks.remove(hook)
raise
# legacy support
runHook("undoState", can_undo)
undo_state_did_change_hook = _UndoStateDidChangeHook()
class _WebviewContextMenuWillShowHook:
_hooks: List[Callable[["aqt.webview.AnkiWebView", QMenu], None]] = [] _hooks: List[Callable[["aqt.webview.AnkiWebView", QMenu], None]] = []
def append(self, cb: Callable[["aqt.webview.AnkiWebView", QMenu], None]) -> None: def append(self, cb: Callable[["aqt.webview.AnkiWebView", QMenu], None]) -> None:
@ -268,5 +872,5 @@ class _WebviewContextMenuHook:
runHook("AnkiWebView.contextMenuEvent", webview, menu) runHook("AnkiWebView.contextMenuEvent", webview, menu)
webview_context_menu_hook = _WebviewContextMenuHook() webview_context_menu_will_show_hook = _WebviewContextMenuWillShowHook()
# @@AUTOGEN@@ # @@AUTOGEN@@

View file

@ -87,7 +87,7 @@ class ModelChooser(QHBoxLayout):
cdeck = self.deck.decks.current() cdeck = self.deck.decks.current()
cdeck["mid"] = m["id"] cdeck["mid"] = m["id"]
self.deck.decks.save(cdeck) self.deck.decks.save(cdeck)
gui_hooks.current_note_type_changed_hook(current) gui_hooks.current_note_type_did_change_hook(current)
self.mw.reset() self.mw.reset()
def updateModels(self): def updateModels(self):

View file

@ -13,7 +13,7 @@ from typing import List
import aqt import aqt
from anki import hooks from anki import hooks
from anki.cards import Card from anki.cards import Card
from anki.hooks import runFilter, runHook from anki.hooks import runHook
from anki.lang import _, ngettext from anki.lang import _, ngettext
from anki.utils import bodyClass, stripHTML from anki.utils import bodyClass, stripHTML
from aqt import AnkiQt, gui_hooks from aqt import AnkiQt, gui_hooks
@ -188,7 +188,7 @@ The front of this card is empty. Please run Tools>Empty Cards."""
playFromText(q) playFromText(q)
# render & update bottom # render & update bottom
q = self._mungeQA(q) q = self._mungeQA(q)
q = runFilter("prepareQA", q, c, "reviewQuestion") q = gui_hooks.card_text_filter(q, c, "reviewQuestion")
bodyclass = bodyClass(self.mw.col, c) bodyclass = bodyClass(self.mw.col, c)
@ -200,7 +200,7 @@ The front of this card is empty. Please run Tools>Empty Cards."""
if self.typeCorrect: if self.typeCorrect:
self.mw.web.setFocus() self.mw.web.setFocus()
# user hook # user hook
gui_hooks.reviewer_showing_question_hook(c) gui_hooks.reviewer_question_did_show_hook(c)
def autoplay(self, card): def autoplay(self, card):
return self.mw.col.decks.confForDid(card.odid or card.did)["autoplay"] return self.mw.col.decks.confForDid(card.odid or card.did)["autoplay"]
@ -230,12 +230,12 @@ The front of this card is empty. Please run Tools>Empty Cards."""
if self.autoplay(c): if self.autoplay(c):
playFromText(a) playFromText(a)
a = self._mungeQA(a) a = self._mungeQA(a)
a = runFilter("prepareQA", a, c, "reviewAnswer") a = gui_hooks.card_text_filter(a, c, "reviewAnswer")
# render and update bottom # render and update bottom
self.web.eval("_showAnswer(%s);" % json.dumps(a)) self.web.eval("_showAnswer(%s);" % json.dumps(a))
self._showEaseButtons() self._showEaseButtons()
# user hook # user hook
gui_hooks.reviewer_showing_answer_hook(c) gui_hooks.reviewer_answer_did_show_hook(c)
# Answering a card # Answering a card
############################################################ ############################################################
@ -695,6 +695,7 @@ time = %(time)d;
m = QMenu(self.mw) m = QMenu(self.mw)
self._addMenuItems(m, opts) self._addMenuItems(m, opts)
gui_hooks.reviewer_context_menu_will_show_hook(self, m)
runHook("Reviewer.contextMenuEvent", self, m) runHook("Reviewer.contextMenuEvent", self, m)
qtMenuShortcutWorkaround(m) qtMenuShortcutWorkaround(m)
m.exec_(QCursor.pos()) m.exec_(QCursor.pos())

View file

@ -182,7 +182,7 @@ class AnkiWebView(QWebEngineView): # type: ignore
m = QMenu(self) m = QMenu(self)
a = m.addAction(_("Copy")) a = m.addAction(_("Copy"))
a.triggered.connect(self.onCopy) a.triggered.connect(self.onCopy)
gui_hooks.webview_context_menu_hook(self, m) gui_hooks.webview_context_menu_will_show_hook(self, m)
m.popup(QCursor.pos()) m.popup(QCursor.pos())
def dropEvent(self, evt): def dropEvent(self, evt):

View file

@ -20,35 +20,35 @@ hooks = [
Hook(name="mpv_idle"), Hook(name="mpv_idle"),
Hook(name="mpv_will_play", args=["file: str"], legacy_hook="mpvWillPlay"), Hook(name="mpv_will_play", args=["file: str"], legacy_hook="mpvWillPlay"),
Hook( Hook(
name="reviewer_showing_question", name="reviewer_question_did_show",
args=["card: Card"], args=["card: Card"],
legacy_hook="showQuestion", legacy_hook="showQuestion",
legacy_no_args=True, legacy_no_args=True,
), ),
Hook( Hook(
name="reviewer_showing_answer", name="reviewer_answer_did_show",
args=["card: Card"], args=["card: Card"],
legacy_hook="showAnswer", legacy_hook="showAnswer",
legacy_no_args=True, legacy_no_args=True,
), ),
Hook( Hook(
name="current_note_type_changed", name="current_note_type_did_change",
args=["notetype: Dict[str, Any]"], args=["notetype: Dict[str, Any]"],
legacy_hook="currentModelChanged", legacy_hook="currentModelChanged",
legacy_no_args=True, legacy_no_args=True,
), ),
Hook( Hook(
name="browser_setup_menus", name="browser_menus_did_setup",
args=["browser: aqt.browser.Browser"], args=["browser: aqt.browser.Browser"],
legacy_hook="browser.setupMenus", legacy_hook="browser.setupMenus",
), ),
Hook( Hook(
name="browser_context_menu", name="browser_context_menu_will_show",
args=["browser: aqt.browser.Browser", "menu: QMenu"], args=["browser: aqt.browser.Browser", "menu: QMenu"],
legacy_hook="browser.onContextMenu", legacy_hook="browser.onContextMenu",
), ),
Hook( Hook(
name="browser_row_changed", name="browser_row_did_change",
args=["browser: aqt.browser.Browser"], args=["browser: aqt.browser.Browser"],
legacy_hook="browser.rowChanged", legacy_hook="browser.rowChanged",
), ),
@ -59,10 +59,119 @@ hooks = [
legacy_hook="prepareQA", legacy_hook="prepareQA",
), ),
Hook( Hook(
name="webview_context_menu", name="webview_context_menu_will_show",
args=["webview: aqt.webview.AnkiWebView", "menu: QMenu"], args=["webview: aqt.webview.AnkiWebView", "menu: QMenu"],
legacy_hook="AnkiWebView.contextMenuEvent", legacy_hook="AnkiWebView.contextMenuEvent",
), ),
Hook(
name="reviewer_context_menu_will_show",
args=["reviewer: aqt.reviewer.Reviewer", "menu: QMenu"],
legacy_hook="Reviewer.contextMenuEvent",
),
Hook(name="profile_did_open", legacy_hook="profileLoaded"),
Hook(name="profile_will_close", legacy_hook="unloadProfile"),
Hook(
name="state_will_change",
args=["new_state: str", "old_state: str"],
legacy_hook="beforeStateChange",
),
Hook(
name="state_did_change",
args=["new_state: str", "old_state: str"],
legacy_hook="afterStateChange",
),
# different sig to original
Hook(
name="state_shortcuts_will_change",
args=["state: str", "shortcuts: List[QShortcut]"],
),
Hook(
name="collection_did_load",
args=["col: anki.storage._Collection"],
legacy_hook="colLoading",
),
Hook(name="state_did_revert", args=["action: str"], legacy_hook="revertedState"),
Hook(
name="state_did_reset",
legacy_hook="reset",
doc="Called when the interface needs to be redisplayed after non-trivial changes have been made.",
),
Hook(
name="undo_state_did_change", args=["can_undo: bool"], legacy_hook="undoState"
),
Hook(name="review_did_undo", args=["card_id: int"], legacy_hook="revertedCard"),
Hook(
name="setup_style",
args=["style: str"],
return_type="str",
legacy_hook="setupStyle",
),
Hook(
name="add_cards_history_menu_will_show",
args=["addcards: aqt.addcards.AddCards", "menu: QMenu"],
legacy_hook="AddCards.onHistory",
),
Hook(
name="add_cards_note_did_add",
args=["note: anki.notes.Note"],
legacy_hook="AddCards.noteAdded",
),
Hook(
name="deck_browser_options_menu_will_show",
args=["menu: QMenu", "deck_id: int"],
legacy_hook="showDeckOptions",
),
# no return like setupEditorButtons
Hook(
name="editor_buttons_did_setup",
args=["buttons: List", "editor: aqt.editor.Editor"],
),
Hook(
name="editor_shortcuts_did_setup",
args=["shortcuts: List[Tuple]", "editor: aqt.editor.Editor"],
legacy_hook="setupEditorShortcuts",
),
Hook(
name="editor_context_menu_will_show",
args=["editor_webview: aqt.editor.EditorWebView", "menu: QMenu"],
legacy_hook="EditorWebView.contextMenuEvent",
),
Hook(
name="editor_typing_timer_did_fire",
args=["note: anki.notes.Note"],
legacy_hook="editTimer",
),
Hook(
name="editor_field_did_gain_focus",
args=["note: anki.notes.Note", "current_field_idx: int"],
legacy_hook="editFocusGained",
),
Hook(
name="editor_field_did_lose_focus",
args=["changed: bool", "note: anki.notes.Note", "current_field_idx: int"],
return_type="bool",
legacy_hook="editFocusLost",
),
Hook(
name="editor_note_did_update",
args=["editor: aqt.editor.Editor"],
legacy_hook="loadNote",
),
Hook(
name="editor_tags_did_update",
args=["note: anki.notes.Note"],
legacy_hook="tagsUpdated",
),
Hook(
name="editor_font_for_field",
args=["font: str"],
return_type="str",
legacy_hook="mungeEditingFontName",
),
#
# aqt/reviewer.py
# 66: runHook("reviewCleanup")
#
] ]
if __name__ == "__main__": if __name__ == "__main__":