Skip card generation if fronts remain unchanged (#1949)

Closes #1945
This commit is contained in:
RumovZ 2022-07-06 11:26:14 +02:00 committed by GitHub
parent fbbd3e678c
commit 2bbd1fca2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 33 deletions

View File

@ -695,7 +695,7 @@ impl Collection {
original.config.sort_field_idx,
normalize,
)?;
self.update_cards_for_changed_templates(notetype, original.templates.len())?;
self.update_cards_for_changed_templates(notetype, &original.templates)?;
self.update_notetype_undoable(notetype, original)?;
} else {
// adding with existing id for old undo code, bypass undo

View File

@ -5,7 +5,7 @@
use std::collections::HashMap;
use super::{CardGenContext, Notetype};
use super::{CardGenContext, CardTemplate, Notetype};
use crate::{
prelude::*,
search::{JoinSearches, SortMode, TemplateKind},
@ -52,6 +52,10 @@ impl TemplateOrdChanges {
changes
}
fn is_empty(&self) -> bool {
*self == Self::default()
}
}
impl Collection {
@ -130,47 +134,67 @@ impl Collection {
pub(crate) fn update_cards_for_changed_templates(
&mut self,
nt: &Notetype,
previous_template_count: usize,
old_templates: &[CardTemplate],
) -> Result<()> {
let ords: Vec<_> = nt.templates.iter().map(|f| f.ord).collect();
let usn = self.usn()?;
if ords_changed(&ords, previous_template_count) {
let ords: Vec<_> = nt.templates.iter().map(|f| f.ord).collect();
let changes = TemplateOrdChanges::new(ords, old_templates.len() as u32);
if !changes.is_empty() {
self.set_schema_modified()?;
let changes = TemplateOrdChanges::new(ords, previous_template_count as u32);
// remove any cards where the template was deleted
if !changes.removed.is_empty() {
let ords =
SearchBuilder::any(changes.removed.into_iter().map(TemplateKind::Ordinal));
self.search_cards_into_table(nt.id.and(ords), SortMode::NoOrder)?;
for card in self.storage.all_searched_cards()? {
self.remove_card_and_add_grave_undoable(card, usn)?;
}
self.storage.clear_searched_cards_table()?;
}
// update ordinals for cards with a repositioned template
if !changes.moved.is_empty() {
let ords =
SearchBuilder::any(changes.moved.keys().cloned().map(TemplateKind::Ordinal));
self.search_cards_into_table(nt.id.and(ords), SortMode::NoOrder)?;
for mut card in self.storage.all_searched_cards()? {
let original = card.clone();
card.template_idx = *changes.moved.get(&card.template_idx).unwrap();
self.update_card_inner(&mut card, original, usn)?;
}
self.storage.clear_searched_cards_table()?;
}
}
let last_deck = self.get_last_deck_added_to_for_notetype(nt.id);
let ctx = CardGenContext::new(nt, last_deck, usn);
self.generate_cards_for_notetype(&ctx)?;
// remove any cards where the template was deleted
if !changes.removed.is_empty() {
let ords =
SearchBuilder::any(changes.removed.iter().cloned().map(TemplateKind::Ordinal));
self.search_cards_into_table(nt.id.and(ords), SortMode::NoOrder)?;
for card in self.storage.all_searched_cards()? {
self.remove_card_and_add_grave_undoable(card, usn)?;
}
self.storage.clear_searched_cards_table()?;
}
// update ordinals for cards with a repositioned template
if !changes.moved.is_empty() {
let ords = SearchBuilder::any(changes.moved.keys().cloned().map(TemplateKind::Ordinal));
self.search_cards_into_table(nt.id.and(ords), SortMode::NoOrder)?;
for mut card in self.storage.all_searched_cards()? {
let original = card.clone();
card.template_idx = *changes.moved.get(&card.template_idx).unwrap();
self.update_card_inner(&mut card, original, usn)?;
}
self.storage.clear_searched_cards_table()?;
}
if should_generate_cards(&changes, nt, old_templates) {
let last_deck = self.get_last_deck_added_to_for_notetype(nt.id);
let ctx = CardGenContext::new(nt, last_deck, usn);
self.generate_cards_for_notetype(&ctx)?;
}
Ok(())
}
}
fn should_generate_cards(
changes: &TemplateOrdChanges,
nt: &Notetype,
old_templates: &[CardTemplate],
) -> bool {
// must regenerate if any front side has changed, but also in the (unlikely)
// case that a template has been replaced by one with an identical front
!(changes.added.is_empty() && nt.template_fronts_are_identical(old_templates))
}
impl Notetype {
fn template_fronts_are_identical(&self, other_templates: &[CardTemplate]) -> bool {
self.templates
.iter()
.map(|t| &t.config.q_format)
.eq(other_templates.iter().map(|t| &t.config.q_format))
}
}
#[cfg(test)]
mod test {
use super::{ords_changed, TemplateOrdChanges};