ask user to confirm which deck they want when opening options in reviewer

Also fixes https://forums.ankiweb.net/t/anki-2-1-45-alpha/10061/57
This commit is contained in:
Damien Elmes 2021-05-27 13:11:20 +10:00
parent 903eefc5c9
commit f26c7ed99e
7 changed files with 84 additions and 26 deletions

View file

@ -213,3 +213,7 @@ deck-config-reviews-too-low =
deck-config-learning-step-above-graduating-interval = The graduating interval should be at least as long as your final learning step. deck-config-learning-step-above-graduating-interval = The graduating interval should be at least as long as your final learning step.
deck-config-good-above-easy = The easy interval should be at least as long as the graduating interval. deck-config-good-above-easy = The easy interval should be at least as long as the graduating interval.
deck-config-relearning-steps-above-minimum-interval = The minimum lapse interval should be at least as long as your final relearning step. deck-config-relearning-steps-above-minimum-interval = The minimum lapse interval should be at least as long as your final relearning step.
## Selecting a deck
deck-config-which-deck = Which deck would you like?

View file

@ -12,6 +12,7 @@ from anki.collection import OpChanges
from anki.decks import Deck, DeckCollapseScope, DeckId, DeckTreeNode from anki.decks import Deck, DeckCollapseScope, DeckId, DeckTreeNode
from anki.utils import intTime from anki.utils import intTime
from aqt import AnkiQt, gui_hooks from aqt import AnkiQt, gui_hooks
from aqt.deckoptions import display_options_for_deck_id
from aqt.operations import QueryOp from aqt.operations import QueryOp
from aqt.operations.deck import ( from aqt.operations.deck import (
add_deck_dialog, add_deck_dialog,
@ -295,10 +296,7 @@ class DeckBrowser:
).run_in_background() ).run_in_background()
def _options(self, did: DeckId) -> None: def _options(self, did: DeckId) -> None:
# select the deck first, because the dyn deck conf assumes the deck display_options_for_deck_id(did)
# we're editing is the current one
self.mw.col.decks.select(did)
self.mw.onDeckConf()
def _collapse(self, did: DeckId) -> None: def _collapse(self, did: DeckId) -> None:
node = self.mw.col.decks.find_deck_in_tree(self._dueTree, did) node = self.mw.col.decks.find_deck_in_tree(self._dueTree, did)

View file

@ -1,5 +1,8 @@
# Copyright: Ankitects Pty Ltd and contributors # Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from __future__ import annotations
from operator import itemgetter from operator import itemgetter
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional

View file

@ -3,11 +3,23 @@
from __future__ import annotations from __future__ import annotations
from typing import List, Optional
import aqt import aqt
import aqt.deckconf
from anki.cards import Card
from anki.decks import Deck, DeckId
from anki.lang import without_unicode_isolation from anki.lang import without_unicode_isolation
from aqt import gui_hooks from aqt import gui_hooks
from aqt.qt import * from aqt.qt import *
from aqt.utils import addCloseShortcut, disable_help_button, restoreGeom, saveGeom, tr from aqt.utils import (
KeyboardModifiersPressed,
addCloseShortcut,
disable_help_button,
restoreGeom,
saveGeom,
tr,
)
from aqt.webview import AnkiWebView from aqt.webview import AnkiWebView
@ -17,9 +29,10 @@ class DeckOptionsDialog(QDialog):
TITLE = "deckOptions" TITLE = "deckOptions"
silentlyClose = True silentlyClose = True
def __init__(self, mw: aqt.main.AnkiQt) -> None: def __init__(self, mw: aqt.main.AnkiQt, deck: Deck) -> None:
QDialog.__init__(self, mw, Qt.Window) QDialog.__init__(self, mw, Qt.Window)
self.mw = mw self.mw = mw
self._deck = deck
self._setup_ui() self._setup_ui()
self.show() self.show()
@ -39,13 +52,12 @@ class DeckOptionsDialog(QDialog):
layout.addWidget(self.web) layout.addWidget(self.web)
self.setLayout(layout) self.setLayout(layout)
deck = self.mw.col.decks.get_current()
self.web.eval( self.web.eval(
f"""const $deckOptions = anki.deckOptions( f"""const $deckOptions = anki.deckOptions(
document.getElementById('main'), {deck.id});""" document.getElementById('main'), {self._deck.id});"""
) )
self.setWindowTitle( self.setWindowTitle(
without_unicode_isolation(tr.actions_options_for(val=deck.name)) without_unicode_isolation(tr.actions_options_for(val=self._deck.name))
) )
gui_hooks.deck_options_did_load(self) gui_hooks.deck_options_did_load(self)
@ -53,3 +65,51 @@ class DeckOptionsDialog(QDialog):
self.web = None self.web = None
saveGeom(self, self.TITLE) saveGeom(self, self.TITLE)
QDialog.reject(self) QDialog.reject(self)
def confirm_deck_then_display_options(active_card: Optional[Card] = None) -> None:
decks = [aqt.mw.col.decks.get_current()]
if card := active_card:
if card.odid and card.odid != decks[0].id:
decks.append(aqt.mw.col.get_deck(card.odid))
if not any(d.id == card.did for d in decks):
decks.append(aqt.mw.col.get_deck(card.odid))
if len(decks) == 1:
display_options_for_deck(decks[0])
else:
decks.sort(key=lambda x: x.WhichOneof("kind") == "filtered")
_deck_prompt_dialog(decks)
def _deck_prompt_dialog(decks: List[Deck]) -> None:
diag = QDialog(aqt.mw.app.activeWindow())
diag.setWindowTitle("Anki")
box = QVBoxLayout()
box.addWidget(QLabel(tr.deck_config_which_deck()))
for deck in decks:
button = QPushButton(deck.name)
qconnect(button.clicked, lambda _, deck=deck: display_options_for_deck(deck))
qconnect(button.clicked, diag.close)
box.addWidget(button)
button = QPushButton(tr.actions_cancel())
qconnect(button.clicked, diag.close)
box.addWidget(button)
diag.setLayout(box)
diag.exec_()
def display_options_for_deck_id(deck_id: DeckId) -> None:
display_options_for_deck(aqt.mw.col.get_deck(deck_id))
def display_options_for_deck(deck: Deck) -> None:
if deck.WhichOneof("kind") == "normal":
if KeyboardModifiersPressed().shift or aqt.mw.col.schedVer() == 1:
deck_legacy = aqt.mw.col.decks.get(DeckId(deck.id))
aqt.deckconf.DeckConf(aqt.mw, deck_legacy)
else:
DeckOptionsDialog(aqt.mw, deck)
else:
aqt.dialogs.open("FilteredDeckConfigDialog", aqt.mw, deck_id=deck.id)

View file

@ -48,7 +48,6 @@ from anki.utils import devMode, ids2str, intTime, isMac, isWin, splitFields
from aqt import gui_hooks from aqt import gui_hooks
from aqt.addons import DownloadLogEntry, check_and_prompt_for_updates, show_log_to_user from aqt.addons import DownloadLogEntry, check_and_prompt_for_updates, show_log_to_user
from aqt.dbcheck import check_db from aqt.dbcheck import check_db
from aqt.deckoptions import DeckOptionsDialog
from aqt.emptycards import show_empty_cards from aqt.emptycards import show_empty_cards
from aqt.legacy import install_pylib_legacy from aqt.legacy import install_pylib_legacy
from aqt.mediacheck import check_media_db from aqt.mediacheck import check_media_db
@ -1120,19 +1119,6 @@ title="%s" %s>%s</button>""" % (
def onEditCurrent(self) -> None: def onEditCurrent(self) -> None:
aqt.dialogs.open("EditCurrent", self) aqt.dialogs.open("EditCurrent", self)
def onDeckConf(self, deck: Optional[DeckDict] = None) -> None:
import aqt.deckconf
if not deck:
deck = self.col.decks.current()
if deck["dyn"]:
aqt.dialogs.open("FilteredDeckConfigDialog", self, deck_id=deck["id"])
else:
if KeyboardModifiersPressed().shift or self.col.schedVer() == 1:
aqt.deckconf.DeckConf(self, deck)
else:
DeckOptionsDialog(self)
def onOverview(self) -> None: def onOverview(self) -> None:
self.col.reset() self.col.reset()
self.moveToState("overview") self.moveToState("overview")
@ -1164,6 +1150,11 @@ title="%s" %s>%s</button>""" % (
def onDocumentation(self) -> None: def onDocumentation(self) -> None:
openHelp(HelpPage.INDEX) openHelp(HelpPage.INDEX)
# legacy
def onDeckConf(self, deck: Optional[DeckDict] = None) -> None:
pass
# Importing & exporting # Importing & exporting
########################################################################## ##########################################################################

View file

@ -10,6 +10,7 @@ from anki.collection import OpChanges
from anki.scheduler import UnburyDeck from anki.scheduler import UnburyDeck
from aqt import gui_hooks from aqt import gui_hooks
from aqt.deckdescription import DeckDescriptionDialog from aqt.deckdescription import DeckDescriptionDialog
from aqt.deckoptions import display_options_for_deck
from aqt.operations.scheduling import ( from aqt.operations.scheduling import (
empty_filtered_deck, empty_filtered_deck,
rebuild_filtered_deck, rebuild_filtered_deck,
@ -93,7 +94,7 @@ class Overview:
elif url == "anki": elif url == "anki":
print("anki menu") print("anki menu")
elif url == "opts": elif url == "opts":
self.mw.onDeckConf() display_options_for_deck(self.mw.col.decks.get_current())
elif url == "cram": elif url == "cram":
aqt.dialogs.open("FilteredDeckConfigDialog", self.mw) aqt.dialogs.open("FilteredDeckConfigDialog", self.mw)
elif url == "refresh": elif url == "refresh":
@ -116,7 +117,7 @@ class Overview:
def _shortcutKeys(self) -> List[Tuple[str, Callable]]: def _shortcutKeys(self) -> List[Tuple[str, Callable]]:
return [ return [
("o", self.mw.onDeckConf), ("o", lambda: display_options_for_deck(self.mw.col.decks.get_current())),
("r", self.rebuild_current_filtered_deck), ("r", self.rebuild_current_filtered_deck),
("e", self.empty_current_filtered_deck), ("e", self.empty_current_filtered_deck),
("c", self.onCustomStudyKey), ("c", self.onCustomStudyKey),

View file

@ -23,6 +23,7 @@ from anki.scheduler.v3 import Scheduler as V3Scheduler
from anki.tags import MARKED_TAG from anki.tags import MARKED_TAG
from anki.utils import stripHTML from anki.utils import stripHTML
from aqt import AnkiQt, gui_hooks from aqt import AnkiQt, gui_hooks
from aqt.deckoptions import confirm_deck_then_display_options
from aqt.flags import load_flags from aqt.flags import load_flags
from aqt.operations.card import set_card_flag from aqt.operations.card import set_card_flag
from aqt.operations.note import remove_notes from aqt.operations.note import remove_notes
@ -953,7 +954,7 @@ time = %(time)d;
qconnect(a.triggered, func) qconnect(a.triggered, func)
def onOptions(self) -> None: def onOptions(self) -> None:
self.mw.onDeckConf(self.mw.col.decks.get(self.card.current_deck_id())) confirm_deck_then_display_options(self.card)
def set_flag_on_current_card(self, desired_flag: int) -> None: def set_flag_on_current_card(self, desired_flag: int) -> None:
def redraw_flag(out: OpChangesWithCount) -> None: def redraw_flag(out: OpChangesWithCount) -> None: