From e92b0f8d63242f32477a52f087cdb263811f5b24 Mon Sep 17 00:00:00 2001 From: Thomas B Date: Tue, 18 Aug 2020 10:37:45 -0400 Subject: [PATCH] Bugfix proposed filter post-testing Mirrored filter more closely on _ReviewerWillAnswerCardFilter, including taking and returning the value to be modified. --- qt/aqt/gui_hooks.py | 105 +++++++++++++++++++++++---------------- qt/aqt/reviewer.py | 21 ++++---- qt/tools/genhooks_gui.py | 16 ++++-- 3 files changed, 82 insertions(+), 60 deletions(-) diff --git a/qt/aqt/gui_hooks.py b/qt/aqt/gui_hooks.py index b66efa6ea..a2eabf8b0 100644 --- a/qt/aqt/gui_hooks.py +++ b/qt/aqt/gui_hooks.py @@ -2081,50 +2081,6 @@ reviewer_did_show_question = _ReviewerDidShowQuestionHook() class _ReviewerWillInitAnswerButtonsFilter: """Used to modify the answer buttons shown for a card. - """ - - _hooks: List[ - Callable["aqt.reviewer.Reviewer", Card], Tuple[Tuple[int, str]]] - ] = [] - - def append( - self, - cb: Callable[ - "aqt.reviewer.Reviewer", Card], Tuple[Tuple[int, str]]] - ], - ) -> None: - """(reviewer: aqt.reviewer.Reviewer, card: Card)""" - self._hooks.append(cb) - - def remove( - self, - cb: Callable[ - "aqt.reviewer.Reviewer", Card], Tuple[Tuple[int, str]]] - ], - ) -> None: - if cb in self._hooks: - self._hooks.remove(cb) - - def count(self) -> int: - return len(self._hooks) - - def __call__( - self, reviewer: aqt.reviewer.Reviewer, card: Card - ) -> Tuple[Tuple[int, str]]: - buttons_tuple = None - for filter in self._hooks: - try: - buttons_tuple = filter(reviewer, card) - except: - # if the hook fails, remove it - self._hooks.remove(filter) - raise - return buttons_tuple - - -reviewer_will_init_answer_buttons = _ReviewerWillInitAnswerButtonsFilter() - - class _ReviewerWillAnswerCardFilter: """Used to modify the ease at which a card is rated or to bypass rating the card completely. @@ -2208,6 +2164,67 @@ class _ReviewerWillEndHook: reviewer_will_end = _ReviewerWillEndHook() +class _ReviewerWillInitAnswerButtonsFilter: + """Used to modify list of answer buttons + + buttons_tuple is a tuple of buttons, with each button represented by a tuple + containing an int for the button's number and a string for the button's label. + + Return a tuple of the form ((1, "Label1"), (2, "Label2"), ...) + + Note: import _ from anki.lang to support automatic translation, using, e.g., + ((1, _("Label1")), ...) + """ + + _hooks: List[ + Callable[ + ["Optional[Tuple[Tuple[int, str], ...]]", "aqt.reviewer.Reviewer", Card], + Tuple[Tuple[int, str], ...], + ] + ] = [] + + def append( + self, + cb: Callable[ + ["Optional[Tuple[Tuple[int, str], ...]]", "aqt.reviewer.Reviewer", Card], + Tuple[Tuple[int, str], ...], + ], + ) -> None: + """(buttons_tuple: Optional[Tuple[Tuple[int, str], ...]], reviewer: aqt.reviewer.Reviewer, card: Card)""" + self._hooks.append(cb) + + def remove( + self, + cb: Callable[ + ["Optional[Tuple[Tuple[int, str], ...]]", "aqt.reviewer.Reviewer", Card], + Tuple[Tuple[int, str], ...], + ], + ) -> None: + if cb in self._hooks: + self._hooks.remove(cb) + + def count(self) -> int: + return len(self._hooks) + + def __call__( + self, + buttons_tuple: Optional[Tuple[Tuple[int, str], ...]], + reviewer: aqt.reviewer.Reviewer, + card: Card, + ) -> Tuple[Tuple[int, str], ...]: + for filter in self._hooks: + try: + buttons_tuple = filter(buttons_tuple, reviewer, card) + except: + # if the hook fails, remove it + self._hooks.remove(filter) + raise + return buttons_tuple + + +reviewer_will_init_answer_buttons = _ReviewerWillInitAnswerButtonsFilter() + + class _ReviewerWillPlayAnswerSoundsHook: """Called before showing the answer/back side. diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index f39feb97d..d30436de8 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -621,19 +621,16 @@ time = %(time)d; else: return 2 - def _answerButtonList(self) -> Sequence[Tuple[int, str]]: - buttons_tuple = gui_hooks.reviewer_will_init_answer_buttons(self, self.card) - if buttons_tuple is not None: - return buttons_tuple + def _answerButtonList(self) -> Sequence[Tuple[int, str], ...]: + button_count = self.mw.col.sched.answerButtons(self.card) + if button_count == 2: + buttons_tuple = ((1, _("Again")), (2, _("Good")),) + elif button_count == 3: + buttons_tuple = ((1, _("Again")), (2, _("Good")), (3, _("Easy"))) else: - l = ((1, _("Again")),) - cnt = self.mw.col.sched.answerButtons(self.card) - if cnt == 2: - return l + ((2, _("Good")),) - elif cnt == 3: - return l + ((2, _("Good")), (3, _("Easy"))) - else: - return l + ((2, _("Hard")), (3, _("Good")), (4, _("Easy"))) + buttons_tuple = ((1, _("Again")), (2, _("Hard")), (3, _("Good")), (4, _("Easy"))) + buttons_tuple = gui_hooks.reviewer_will_init_answer_buttons(buttons_tuple, self, self.card) + return buttons_tuple def _answerButtons(self) -> str: default = self._defaultEase() diff --git a/qt/tools/genhooks_gui.py b/qt/tools/genhooks_gui.py index 118e783bf..bf84ce664 100644 --- a/qt/tools/genhooks_gui.py +++ b/qt/tools/genhooks_gui.py @@ -60,13 +60,21 @@ hooks = [ ), Hook( name="reviewer_will_init_answer_buttons", - args=["reviewer: aqt.reviewer.Reviewer", "card: Card"], + args=[ + "buttons_tuple: Optional[Tuple[Tuple[int, str], ...]]", + "reviewer: aqt.reviewer.Reviewer", + "card: Card", + ], + return_type="Tuple[Tuple[int, str], ...]", doc="""Used to modify list of answer buttons - Return a tuple of the form ((1, "Label1"), (2, "Label2")) + buttons_tuple is a tuple of buttons, with each button represented by a tuple + containing an int for the button's number and a string for the button's label. - import _ from anki.lang to support translation, as - ((1, _("Label1)), ...) + Return a tuple of the form ((1, "Label1"), (2, "Label2"), ...) + + Note: import _ from anki.lang to support automatic translation, using, e.g., + ((1, _("Label1")), ...) """, ), Hook(