mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
Equip Reviewer._showAnswer with hooks covering common add-on usages
This commit is contained in:
parent
d428b3b4c0
commit
68c5fd50f9
3 changed files with 100 additions and 0 deletions
|
@ -650,6 +650,30 @@ class _ReviewDidUndoHook:
|
|||
review_did_undo = _ReviewDidUndoHook()
|
||||
|
||||
|
||||
class _ReviewerDidAnswerCardHook:
|
||||
_hooks: List[Callable[["aqt.reviewer.Reviewer", Card, int], None]] = []
|
||||
|
||||
def append(self, cb: Callable[["aqt.reviewer.Reviewer", Card, int], None]) -> None:
|
||||
"""(reviewer: aqt.reviewer.Reviewer, card: Card, ease: int)"""
|
||||
self._hooks.append(cb)
|
||||
|
||||
def remove(self, cb: Callable[["aqt.reviewer.Reviewer", Card, int], None]) -> None:
|
||||
if cb in self._hooks:
|
||||
self._hooks.remove(cb)
|
||||
|
||||
def __call__(self, reviewer: aqt.reviewer.Reviewer, card: Card, ease: int) -> None:
|
||||
for hook in self._hooks:
|
||||
try:
|
||||
hook(reviewer, card, ease)
|
||||
except:
|
||||
# if the hook fails, remove it
|
||||
self._hooks.remove(hook)
|
||||
raise
|
||||
|
||||
|
||||
reviewer_did_answer_card = _ReviewerDidAnswerCardHook()
|
||||
|
||||
|
||||
class _ReviewerDidShowAnswerHook:
|
||||
_hooks: List[Callable[[Card], None]] = []
|
||||
|
||||
|
@ -702,6 +726,55 @@ class _ReviewerDidShowQuestionHook:
|
|||
reviewer_did_show_question = _ReviewerDidShowQuestionHook()
|
||||
|
||||
|
||||
class _ReviewerWillAnswerCardFilter:
|
||||
"""Used to modify the ease at which a card is rated or to bypass
|
||||
rating the card completely.
|
||||
|
||||
ease_tuple is a tuple consisting of a boolean expressing whether the reviewer
|
||||
should continue with rating the card, and an integer expressing the ease at
|
||||
which the card should be rated.
|
||||
|
||||
If your code just needs to be notified of the card rating event, you should use
|
||||
the reviewer_did_answer_card hook instead."""
|
||||
|
||||
_hooks: List[
|
||||
Callable[[Tuple[bool, int], "aqt.reviewer.Reviewer", Card], Tuple[bool, int]]
|
||||
] = []
|
||||
|
||||
def append(
|
||||
self,
|
||||
cb: Callable[
|
||||
[Tuple[bool, int], "aqt.reviewer.Reviewer", Card], Tuple[bool, int]
|
||||
],
|
||||
) -> None:
|
||||
"""(ease_tuple: Tuple[bool, int], reviewer: aqt.reviewer.Reviewer, card: Card)"""
|
||||
self._hooks.append(cb)
|
||||
|
||||
def remove(
|
||||
self,
|
||||
cb: Callable[
|
||||
[Tuple[bool, int], "aqt.reviewer.Reviewer", Card], Tuple[bool, int]
|
||||
],
|
||||
) -> None:
|
||||
if cb in self._hooks:
|
||||
self._hooks.remove(cb)
|
||||
|
||||
def __call__(
|
||||
self, ease_tuple: Tuple[bool, int], reviewer: aqt.reviewer.Reviewer, card: Card
|
||||
) -> Tuple[bool, int]:
|
||||
for filter in self._hooks:
|
||||
try:
|
||||
ease_tuple = filter(ease_tuple, reviewer, card)
|
||||
except:
|
||||
# if the hook fails, remove it
|
||||
self._hooks.remove(filter)
|
||||
raise
|
||||
return ease_tuple
|
||||
|
||||
|
||||
reviewer_will_answer_card = _ReviewerWillAnswerCardFilter()
|
||||
|
||||
|
||||
class _ReviewerWillEndHook:
|
||||
"""Called before Anki transitions from the review screen to another screen."""
|
||||
|
||||
|
|
|
@ -242,7 +242,13 @@ The front of this card is empty. Please run Tools>Empty Cards."""
|
|||
return
|
||||
if self.mw.col.sched.answerButtons(self.card) < ease:
|
||||
return
|
||||
proceed, ease = gui_hooks.reviewer_will_answer_card(
|
||||
(True, ease), self, self.card
|
||||
)
|
||||
if not proceed:
|
||||
return
|
||||
self.mw.col.sched.answerCard(self.card, ease)
|
||||
gui_hooks.reviewer_did_answer_card(self, self.card, ease)
|
||||
self._answeredIds.append(self.card.id)
|
||||
self.mw.autosave()
|
||||
self.nextCard()
|
||||
|
|
|
@ -31,6 +31,27 @@ hooks = [
|
|||
legacy_hook="showAnswer",
|
||||
legacy_no_args=True,
|
||||
),
|
||||
Hook(
|
||||
name="reviewer_will_answer_card",
|
||||
args=[
|
||||
"ease_tuple: Tuple[bool, int]",
|
||||
"reviewer: aqt.reviewer.Reviewer", "card: Card",
|
||||
],
|
||||
return_type="Tuple[bool, int]",
|
||||
doc="""Used to modify the ease at which a card is rated or to bypass
|
||||
rating the card completely.
|
||||
|
||||
ease_tuple is a tuple consisting of a boolean expressing whether the reviewer
|
||||
should continue with rating the card, and an integer expressing the ease at
|
||||
which the card should be rated.
|
||||
|
||||
If your code just needs to be notified of the card rating event, you should use
|
||||
the reviewer_did_answer_card hook instead.""",
|
||||
),
|
||||
Hook(
|
||||
name="reviewer_did_answer_card",
|
||||
args=["reviewer: aqt.reviewer.Reviewer", "card: Card", "ease: int"],
|
||||
),
|
||||
Hook(
|
||||
name="reviewer_will_show_context_menu",
|
||||
args=["reviewer: aqt.reviewer.Reviewer", "menu: QMenu"],
|
||||
|
|
Loading…
Reference in a new issue