diff --git a/pylib/anki/decks.py b/pylib/anki/decks.py index 47696ad8a..c683eb8d5 100644 --- a/pylib/anki/decks.py +++ b/pylib/anki/decks.py @@ -92,6 +92,16 @@ defaultConf = { "usn": 0, } +# How to select list of decks + +# difference between WITHOUT_EMPTY_DEFAULT and +# WITHOUT_EMPTY_LEAF_DEFAULT is that the first contains default when +# it has a child. This is required for deck tree. + +WITHOUT_EMPTY_DEFAULT = 0 +ALL_DECKS = 1 +WITHOUT_EMPTY_LEAF_DEFAULT = 2 + class DeckManager: decks: Dict[str, Any] @@ -219,7 +229,7 @@ class DeckManager: self.select(int(list(self.decks.keys())[0])) self.save() - def allNames(self, dyn: bool = True, forceDefault: bool = True) -> List: + def allNames(self, dyn: bool = True, forceDefault: int = ALL_DECKS) -> List: "An unsorted list of all deck names." if dyn: return [x["name"] for x in self.all(forceDefault=forceDefault)] @@ -228,14 +238,10 @@ class DeckManager: x["name"] for x in self.all(forceDefault=forceDefault) if not x["dyn"] ] - def all(self, forceDefault: bool = True) -> List: + def all(self, forceDefault: int = ALL_DECKS) -> List: "A list of all decks." decks = list(self.decks.values()) - if ( - not forceDefault - and not self.col.db.scalar("select 1 from cards where did = 1 limit 1") - and len(decks) > 1 - ): + if not forceDefault and not self.shouldDefaultBeDisplayed(forceDefault): decks = [deck for deck in decks if deck["id"] != 1] return decks @@ -513,6 +519,35 @@ class DeckManager: self._recoverOrphans() self._checkDeckTree() + def shouldDeckBeDisplayed(self, deck, forceDefault: int = ALL_DECKS) -> bool: + """Whether the deck should appear in main window, browser side list, filter, deck selection... + + True, except for empty default deck without children""" + if deck["id"] != "1": + return True + return self.shouldDefaultBeDisplayed(forceDefault) + + def shouldDefaultBeDisplayed( + self, forceDefault: int = ALL_DECKS, defaultDeck=None + ) -> bool: + """Whether the default deck should appear in main window, browser side list, filter, deck selection... + + True, except for empty default deck (without children)""" + if forceDefault == ALL_DECKS: + return True + if self.col.db.scalar("select 1 from cards where did = 1 limit 1"): + return True + if len(self.decks) == 1: + return True + if forceDefault == WITHOUT_EMPTY_LEAF_DEFAULT: + if defaultDeck is None: + defaultDeck = self.get(1) + defaultName = defaultDeck["name"] + for name in self.allNames(): + if name.startswith(f"{defaultName}::"): + return True + return False + # Deck selection ############################################################# diff --git a/qt/aqt/studydeck.py b/qt/aqt/studydeck.py index 8a331f5e6..b0d56bcd9 100644 --- a/qt/aqt/studydeck.py +++ b/qt/aqt/studydeck.py @@ -3,6 +3,7 @@ # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import aqt +from anki.decks import WITHOUT_EMPTY_LEAF_DEFAULT from anki.lang import _ from aqt import gui_hooks from aqt.qt import * @@ -51,7 +52,11 @@ class StudyDeck(QDialog): if title: self.setWindowTitle(title) if not names: - names = sorted(self.mw.col.decks.allNames(dyn=dyn, forceDefault=False)) + names = sorted( + self.mw.col.decks.allNames( + dyn=dyn, forceDefault=WITHOUT_EMPTY_LEAF_DEFAULT + ) + ) self.nameFunc = None self.origNames = names else: