From e071fb471bfde9b59a0e1d58bbcd7700769ee087 Mon Sep 17 00:00:00 2001 From: Gustaf-C <106698658+Gustaf-C@users.noreply.github.com> Date: Sun, 5 Nov 2023 10:23:14 +0800 Subject: [PATCH] Allow creation of empty filtered decks (#2788) * Add new button to UI * Add bool to allow creating empty filtered in back end * Implement logic into front end for passing on bool * Hide option on old decks * Show option again if any settings are changed * Revert "Show option again if any settings are changed" This reverts commit 094acd9c65936823fa206594da5c1f3e4eb09248. * Revert "Hide option on old decks" This reverts commit d20a9a240b4fd85d080e8cc52d94318416ca753f. * Update string * Update ftl/core/decks.ftl --------- Co-authored-by: Damien Elmes --- ftl/core/decks.ftl | 1 + proto/anki/decks.proto | 1 + qt/aqt/filtered_deck.py | 5 +++++ qt/aqt/forms/filtered_deck.ui | 7 +++++++ rslib/src/decks/service.rs | 2 ++ rslib/src/scheduler/filtered/custom_study.rs | 1 + rslib/src/scheduler/filtered/mod.rs | 5 ++++- 7 files changed, 21 insertions(+), 1 deletion(-) diff --git a/ftl/core/decks.ftl b/ftl/core/decks.ftl index b2ae2655e..a3777645d 100644 --- a/ftl/core/decks.ftl +++ b/ftl/core/decks.ftl @@ -2,6 +2,7 @@ decks-add-new-deck-ctrlandn = Add New Deck (Ctrl+N) decks-build = Build decks-cards-selected-by = cards selected by decks-create-deck = Create Deck +decks_create_even_if_empty = Create/update this deck even if empty decks-custom-steps-in-minutes = Custom steps (in minutes) decks-deck = Deck decks-decreasing-intervals = Decreasing intervals diff --git a/proto/anki/decks.proto b/proto/anki/decks.proto index 6ecd55ad8..aff2a9d21 100644 --- a/proto/anki/decks.proto +++ b/proto/anki/decks.proto @@ -212,4 +212,5 @@ message FilteredDeckForUpdate { int64 id = 1; string name = 2; Deck.Filtered config = 3; + bool allow_empty = 4; } diff --git a/qt/aqt/filtered_deck.py b/qt/aqt/filtered_deck.py index 489928743..af87b2e6d 100644 --- a/qt/aqt/filtered_deck.py +++ b/qt/aqt/filtered_deck.py @@ -79,6 +79,8 @@ class FilteredDeckConfigDialog(QDialog): self.form.order.addItems(order_labels) self.form.order_2.addItems(order_labels) + qconnect(self.form.allow_empty.stateChanged, self._on_allow_empty_toggled) + qconnect(self.form.resched.stateChanged, self._onReschedToggled) qconnect(self.form.search_button.clicked, self.on_search_button) @@ -233,6 +235,9 @@ class FilteredDeckConfigDialog(QDialog): def _onReschedToggled(self, _state: int) -> None: self.form.previewDelayWidget.setVisible(not self.form.resched.isChecked()) + def _on_allow_empty_toggled(self) -> None: + self.deck.allow_empty = self.form.allow_empty.isChecked() + def _update_deck(self) -> bool: """Update our stored deck with the details from the GUI. If false, abort adding.""" diff --git a/qt/aqt/forms/filtered_deck.ui b/qt/aqt/forms/filtered_deck.ui index 87277b4f5..40e7bb8d8 100644 --- a/qt/aqt/forms/filtered_deck.ui +++ b/qt/aqt/forms/filtered_deck.ui @@ -255,6 +255,13 @@ + + + + decks_create_even_if_empty + + + diff --git a/rslib/src/decks/service.rs b/rslib/src/decks/service.rs index f4b51b4e5..b5ef2a494 100644 --- a/rslib/src/decks/service.rs +++ b/rslib/src/decks/service.rs @@ -251,6 +251,7 @@ impl From for anki_proto::decks::FilteredDeckForUpdate { id: deck.id.into(), name: deck.human_name, config: Some(deck.config), + allow_empty: deck.allow_empty, } } } @@ -261,6 +262,7 @@ impl From for FilteredDeckForUpdate { id: deck.id.into(), human_name: deck.name, config: deck.config.unwrap_or_default(), + allow_empty: deck.allow_empty, } } } diff --git a/rslib/src/scheduler/filtered/custom_study.rs b/rslib/src/scheduler/filtered/custom_study.rs index 32a32950d..4b8c16700 100644 --- a/rslib/src/scheduler/filtered/custom_study.rs +++ b/rslib/src/scheduler/filtered/custom_study.rs @@ -184,6 +184,7 @@ impl Collection { id, human_name, config, + allow_empty: false, }; self.add_or_update_filtered_deck_inner(deck) diff --git a/rslib/src/scheduler/filtered/mod.rs b/rslib/src/scheduler/filtered/mod.rs index 5a158dff8..60083f6ac 100644 --- a/rslib/src/scheduler/filtered/mod.rs +++ b/rslib/src/scheduler/filtered/mod.rs @@ -21,6 +21,7 @@ pub struct FilteredDeckForUpdate { pub id: DeckId, pub human_name: String, pub config: FilteredDeck, + pub allow_empty: bool, } pub(crate) struct DeckFilterContext<'a> { @@ -144,6 +145,7 @@ impl Collection { mut update: FilteredDeckForUpdate, ) -> Result { let usn = self.usn()?; + let allow_empty = update.allow_empty; // check the searches are valid, and normalize them for term in &mut update.config.search_terms { @@ -167,7 +169,7 @@ impl Collection { let count = self.rebuild_filtered_deck_inner(&deck, usn)?; // if it failed to match any cards, we revert the changes - if count == 0 { + if count == 0 && !allow_empty { Err(FilteredDeckError::SearchReturnedNoCards.into()) } else { // update current deck and return id @@ -233,6 +235,7 @@ impl TryFrom for FilteredDeckForUpdate { id: value.id, human_name, config: filtered, + allow_empty: false, }), _ => invalid_input!("not filtered"), }