Merge row contexts
This commit is contained in:
parent
8a131da9a2
commit
c6ebb9b441
@ -94,55 +94,9 @@ pub struct Font {
|
||||
pub size: u32,
|
||||
}
|
||||
|
||||
trait RowContext {
|
||||
fn get_cell_text(&mut self, column: Column) -> Result<String>;
|
||||
fn get_row_color(&self) -> Color;
|
||||
fn get_row_font(&self) -> Result<Font>;
|
||||
fn note(&self) -> &Note;
|
||||
fn notetype(&self) -> &Notetype;
|
||||
|
||||
fn get_cell(&mut self, column: Column) -> Result<Cell> {
|
||||
Ok(Cell {
|
||||
text: self.get_cell_text(column)?,
|
||||
is_rtl: self.get_is_rtl(column),
|
||||
})
|
||||
}
|
||||
|
||||
fn note_creation_str(&self) -> String {
|
||||
TimestampMillis(self.note().id.into())
|
||||
.as_secs()
|
||||
.date_string()
|
||||
}
|
||||
|
||||
fn note_field_str(&self) -> String {
|
||||
let index = self.notetype().config.sort_field_idx as usize;
|
||||
html_to_text_line(&self.note().fields()[index]).into()
|
||||
}
|
||||
|
||||
fn get_is_rtl(&self, column: Column) -> bool {
|
||||
match column {
|
||||
Column::NoteField => {
|
||||
let index = self.notetype().config.sort_field_idx as usize;
|
||||
self.notetype().fields[index].config.rtl
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn browser_row_for_id(&mut self, columns: &[Column]) -> Result<Row> {
|
||||
Ok(Row {
|
||||
cells: columns
|
||||
.iter()
|
||||
.map(|&column| self.get_cell(column))
|
||||
.collect::<Result<_>>()?,
|
||||
color: self.get_row_color(),
|
||||
font: self.get_row_font()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct CardRowContext {
|
||||
card: Card,
|
||||
struct RowContext {
|
||||
notes_mode: bool,
|
||||
cards: Vec<Card>,
|
||||
note: Note,
|
||||
notetype: Arc<Notetype>,
|
||||
deck: Arc<Deck>,
|
||||
@ -159,14 +113,6 @@ struct RenderContext {
|
||||
answer_nodes: Vec<RenderedNode>,
|
||||
}
|
||||
|
||||
struct NoteRowContext {
|
||||
note: Note,
|
||||
notetype: Arc<Notetype>,
|
||||
cards: Vec<Card>,
|
||||
tr: I18n,
|
||||
timing: SchedTimingToday,
|
||||
}
|
||||
|
||||
fn card_render_required(columns: &[Column]) -> bool {
|
||||
columns
|
||||
.iter()
|
||||
@ -218,18 +164,15 @@ impl Note {
|
||||
|
||||
impl Collection {
|
||||
pub fn browser_row_for_id(&mut self, id: i64) -> Result<Row> {
|
||||
if self.get_bool(BoolKey::BrowserTableShowNotesMode) {
|
||||
let columns = self
|
||||
.get_desktop_browser_note_columns()
|
||||
.ok_or_else(|| AnkiError::invalid_input("Note columns not set."))?;
|
||||
NoteRowContext::new(self, id)?.browser_row_for_id(&columns)
|
||||
let notes_mode = self.get_bool(BoolKey::BrowserTableShowNotesMode);
|
||||
let columns = if notes_mode {
|
||||
self.get_desktop_browser_note_columns()
|
||||
.ok_or_else(|| AnkiError::invalid_input("Note columns not set."))?
|
||||
} else {
|
||||
let columns = self
|
||||
.get_desktop_browser_card_columns()
|
||||
.ok_or_else(|| AnkiError::invalid_input("Card columns not set."))?;
|
||||
CardRowContext::new(self, id, card_render_required(&columns))?
|
||||
.browser_row_for_id(&columns)
|
||||
}
|
||||
self.get_desktop_browser_card_columns()
|
||||
.ok_or_else(|| AnkiError::invalid_input("Card columns not set."))?
|
||||
};
|
||||
RowContext::new(self, id, notes_mode, card_render_required(&columns))?.browser_row(&columns)
|
||||
}
|
||||
|
||||
fn get_note_maybe_with_fields(&self, id: NoteId, _with_fields: bool) -> Result<Note> {
|
||||
@ -275,20 +218,32 @@ impl RenderContext {
|
||||
}
|
||||
}
|
||||
|
||||
impl CardRowContext {
|
||||
fn new(col: &mut Collection, id: i64, with_card_render: bool) -> Result<Self> {
|
||||
let card = col
|
||||
impl RowContext {
|
||||
fn new(
|
||||
col: &mut Collection,
|
||||
id: i64,
|
||||
notes_mode: bool,
|
||||
with_card_render: bool,
|
||||
) -> Result<Self> {
|
||||
let cards;
|
||||
let note;
|
||||
if notes_mode {
|
||||
note = col.get_note_maybe_with_fields(NoteId(id), with_card_render)?;
|
||||
cards = col.storage.all_cards_of_note(note.id)?;
|
||||
} else {
|
||||
cards = vec![col
|
||||
.storage
|
||||
.get_card(CardId(id))?
|
||||
.ok_or(AnkiError::NotFound)?;
|
||||
let note = col.get_note_maybe_with_fields(card.note_id, with_card_render)?;
|
||||
.ok_or(AnkiError::NotFound)?];
|
||||
note = col.get_note_maybe_with_fields(cards[0].note_id, with_card_render)?;
|
||||
}
|
||||
let notetype = col
|
||||
.get_notetype(note.notetype_id)?
|
||||
.ok_or(AnkiError::NotFound)?;
|
||||
let deck = col.get_deck(card.deck_id)?.ok_or(AnkiError::NotFound)?;
|
||||
let original_deck = if card.original_deck_id.0 != 0 {
|
||||
let deck = col.get_deck(cards[0].deck_id)?.ok_or(AnkiError::NotFound)?;
|
||||
let original_deck = if cards[0].original_deck_id.0 != 0 {
|
||||
Some(
|
||||
col.get_deck(card.original_deck_id)?
|
||||
col.get_deck(cards[0].original_deck_id)?
|
||||
.ok_or(AnkiError::NotFound)?,
|
||||
)
|
||||
} else {
|
||||
@ -296,13 +251,14 @@ impl CardRowContext {
|
||||
};
|
||||
let timing = col.timing_today()?;
|
||||
let render_context = if with_card_render {
|
||||
Some(RenderContext::new(col, &card, ¬e, ¬etype)?)
|
||||
Some(RenderContext::new(col, &cards[0], ¬e, ¬etype)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(CardRowContext {
|
||||
card,
|
||||
Ok(RowContext {
|
||||
notes_mode,
|
||||
cards,
|
||||
note,
|
||||
notetype,
|
||||
deck,
|
||||
@ -313,8 +269,72 @@ impl CardRowContext {
|
||||
})
|
||||
}
|
||||
|
||||
fn browser_row(&mut self, columns: &[Column]) -> Result<Row> {
|
||||
Ok(Row {
|
||||
cells: columns
|
||||
.iter()
|
||||
.map(|&column| self.get_cell(column))
|
||||
.collect::<Result<_>>()?,
|
||||
color: self.get_row_color(),
|
||||
font: self.get_row_font()?,
|
||||
})
|
||||
}
|
||||
|
||||
fn get_cell(&mut self, column: Column) -> Result<Cell> {
|
||||
Ok(Cell {
|
||||
text: self.get_cell_text(column)?,
|
||||
is_rtl: self.get_is_rtl(column),
|
||||
})
|
||||
}
|
||||
|
||||
fn get_cell_text(&mut self, column: Column) -> Result<String> {
|
||||
Ok(match column {
|
||||
Column::Question => self.question_str(),
|
||||
Column::Answer => self.answer_str(),
|
||||
Column::CardDeck => self.deck_str(),
|
||||
Column::CardDue => self.card_due_str(),
|
||||
Column::CardEase => self.card_ease_str(),
|
||||
Column::CardInterval => self.card_interval_str(),
|
||||
Column::CardLapses => self.cards[0].lapses.to_string(),
|
||||
Column::CardMod => self.cards[0].mtime.date_string(),
|
||||
Column::CardReps => self.cards[0].reps.to_string(),
|
||||
Column::CardTemplate => self.template_str()?,
|
||||
Column::NoteCreation => self.note_creation_str(),
|
||||
Column::NoteField => self.note_field_str(),
|
||||
Column::NoteMod => self.note.mtime.date_string(),
|
||||
Column::NoteTags => self.note.tags.join(" "),
|
||||
Column::Notetype => self.notetype.name.to_owned(),
|
||||
Column::NoteCards => self.cards.len().to_string(),
|
||||
Column::NoteDue => self.note_due_str(),
|
||||
Column::NoteEase => self.note_ease_str(),
|
||||
Column::NoteInterval => self.note_interval_str(),
|
||||
Column::NoteLapses => self.cards.iter().map(|c| c.lapses).sum::<u32>().to_string(),
|
||||
Column::NoteReps => self.cards.iter().map(|c| c.reps).sum::<u32>().to_string(),
|
||||
Column::Custom => "".to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
fn note_creation_str(&self) -> String {
|
||||
TimestampMillis(self.note.id.into()).as_secs().date_string()
|
||||
}
|
||||
|
||||
fn note_field_str(&self) -> String {
|
||||
let index = self.notetype.config.sort_field_idx as usize;
|
||||
html_to_text_line(&self.note.fields()[index]).into()
|
||||
}
|
||||
|
||||
fn get_is_rtl(&self, column: Column) -> bool {
|
||||
match column {
|
||||
Column::NoteField => {
|
||||
let index = self.notetype.config.sort_field_idx as usize;
|
||||
self.notetype.fields[index].config.rtl
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn template(&self) -> Result<&CardTemplate> {
|
||||
self.notetype.get_template(self.card.template_idx)
|
||||
self.notetype.get_template(self.cards[0].template_idx)
|
||||
}
|
||||
|
||||
fn answer_str(&self) -> String {
|
||||
@ -343,16 +363,16 @@ impl CardRowContext {
|
||||
}
|
||||
|
||||
fn card_due_str(&mut self) -> String {
|
||||
let due = if self.card.is_filtered_deck() {
|
||||
let due = if self.cards[0].is_filtered_deck() {
|
||||
self.tr.browsing_filtered()
|
||||
} else if self.card.is_new_type_or_queue() {
|
||||
self.tr.statistics_due_for_new_card(self.card.due)
|
||||
} else if let Some(time) = self.card.due_time(&self.timing) {
|
||||
} else if self.cards[0].is_new_type_or_queue() {
|
||||
self.tr.statistics_due_for_new_card(self.cards[0].due)
|
||||
} else if let Some(time) = self.cards[0].due_time(&self.timing) {
|
||||
time.date_string().into()
|
||||
} else {
|
||||
return "".into();
|
||||
};
|
||||
if self.card.is_undue_queue() {
|
||||
if self.cards[0].is_undue_queue() {
|
||||
format!("({})", due)
|
||||
} else {
|
||||
due.into()
|
||||
@ -360,17 +380,17 @@ impl CardRowContext {
|
||||
}
|
||||
|
||||
fn card_ease_str(&self) -> String {
|
||||
match self.card.ctype {
|
||||
match self.cards[0].ctype {
|
||||
CardType::New => self.tr.browsing_new().into(),
|
||||
_ => format!("{}%", self.card.ease_factor / 10),
|
||||
_ => format!("{}%", self.cards[0].ease_factor / 10),
|
||||
}
|
||||
}
|
||||
|
||||
fn card_interval_str(&self) -> String {
|
||||
match self.card.ctype {
|
||||
match self.cards[0].ctype {
|
||||
CardType::New => self.tr.browsing_new().into(),
|
||||
CardType::Learn => self.tr.browsing_learning().into(),
|
||||
_ => time_span((self.card.interval * 86400) as f32, &self.tr, false),
|
||||
_ => time_span((self.cards[0].interval * 86400) as f32, &self.tr, false),
|
||||
}
|
||||
}
|
||||
|
||||
@ -387,88 +407,13 @@ impl CardRowContext {
|
||||
let name = &self.template()?.name;
|
||||
Ok(match self.notetype.config.kind() {
|
||||
NotetypeKind::Normal => name.to_owned(),
|
||||
NotetypeKind::Cloze => format!("{} {}", name, self.card.template_idx + 1),
|
||||
NotetypeKind::Cloze => format!("{} {}", name, self.cards[0].template_idx + 1),
|
||||
})
|
||||
}
|
||||
|
||||
fn question_str(&self) -> String {
|
||||
html_to_text_line(&self.render_context.as_ref().unwrap().question).to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl RowContext for CardRowContext {
|
||||
fn get_cell_text(&mut self, column: Column) -> Result<String> {
|
||||
Ok(match column {
|
||||
Column::Question => self.question_str(),
|
||||
Column::Answer => self.answer_str(),
|
||||
Column::CardDeck => self.deck_str(),
|
||||
Column::CardDue => self.card_due_str(),
|
||||
Column::CardEase => self.card_ease_str(),
|
||||
Column::CardInterval => self.card_interval_str(),
|
||||
Column::CardLapses => self.card.lapses.to_string(),
|
||||
Column::CardMod => self.card.mtime.date_string(),
|
||||
Column::CardReps => self.card.reps.to_string(),
|
||||
Column::CardTemplate => self.template_str()?,
|
||||
Column::NoteCreation => self.note_creation_str(),
|
||||
Column::NoteField => self.note_field_str(),
|
||||
Column::NoteMod => self.note.mtime.date_string(),
|
||||
Column::NoteTags => self.note.tags.join(" "),
|
||||
Column::Notetype => self.notetype.name.to_owned(),
|
||||
_ => "".to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
fn get_row_color(&self) -> Color {
|
||||
match self.card.flags {
|
||||
1 => Color::FlagRed,
|
||||
2 => Color::FlagOrange,
|
||||
3 => Color::FlagGreen,
|
||||
4 => Color::FlagBlue,
|
||||
_ => {
|
||||
if self.note.is_marked() {
|
||||
Color::Marked
|
||||
} else if self.card.queue == CardQueue::Suspended {
|
||||
Color::Suspended
|
||||
} else {
|
||||
Color::Default
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_row_font(&self) -> Result<Font> {
|
||||
Ok(Font {
|
||||
name: self.template()?.config.browser_font_name.to_owned(),
|
||||
size: self.template()?.config.browser_font_size,
|
||||
})
|
||||
}
|
||||
|
||||
fn note(&self) -> &Note {
|
||||
&self.note
|
||||
}
|
||||
|
||||
fn notetype(&self) -> &Notetype {
|
||||
&self.notetype
|
||||
}
|
||||
}
|
||||
|
||||
impl NoteRowContext {
|
||||
fn new(col: &mut Collection, id: i64) -> Result<Self> {
|
||||
let note = col.get_note_maybe_with_fields(NoteId(id), false)?;
|
||||
let notetype = col
|
||||
.get_notetype(note.notetype_id)?
|
||||
.ok_or(AnkiError::NotFound)?;
|
||||
let cards = col.storage.all_cards_of_note(note.id)?;
|
||||
let timing = col.timing_today()?;
|
||||
|
||||
Ok(NoteRowContext {
|
||||
note,
|
||||
notetype,
|
||||
cards,
|
||||
tr: col.tr.clone(),
|
||||
timing,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the average ease of the non-new cards or a hint if there aren't any.
|
||||
fn note_ease_str(&self) -> String {
|
||||
@ -516,46 +461,37 @@ impl NoteRowContext {
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RowContext for NoteRowContext {
|
||||
fn get_cell_text(&mut self, column: Column) -> Result<String> {
|
||||
Ok(match column {
|
||||
Column::NoteCards => self.cards.len().to_string(),
|
||||
Column::NoteCreation => self.note_creation_str(),
|
||||
Column::NoteDue => self.note_due_str(),
|
||||
Column::NoteEase => self.note_ease_str(),
|
||||
Column::NoteField => self.note_field_str(),
|
||||
Column::NoteInterval => self.note_interval_str(),
|
||||
Column::NoteLapses => self.cards.iter().map(|c| c.lapses).sum::<u32>().to_string(),
|
||||
Column::NoteMod => self.note.mtime.date_string(),
|
||||
Column::NoteReps => self.cards.iter().map(|c| c.reps).sum::<u32>().to_string(),
|
||||
Column::NoteTags => self.note.tags.join(" "),
|
||||
Column::Notetype => self.notetype.name.to_owned(),
|
||||
_ => "".to_string(),
|
||||
fn get_row_font(&self) -> Result<Font> {
|
||||
Ok(Font {
|
||||
name: self.template()?.config.browser_font_name.to_owned(),
|
||||
size: self.template()?.config.browser_font_size,
|
||||
})
|
||||
}
|
||||
|
||||
fn get_row_color(&self) -> Color {
|
||||
if self.notes_mode {
|
||||
if self.note.is_marked() {
|
||||
Color::Marked
|
||||
} else {
|
||||
Color::Default
|
||||
}
|
||||
}
|
||||
|
||||
fn get_row_font(&self) -> Result<Font> {
|
||||
Ok(Font {
|
||||
name: "".to_owned(),
|
||||
size: 0,
|
||||
})
|
||||
}
|
||||
|
||||
fn note(&self) -> &Note {
|
||||
&self.note
|
||||
}
|
||||
|
||||
fn notetype(&self) -> &Notetype {
|
||||
&self.notetype
|
||||
} else {
|
||||
match self.cards[0].flags {
|
||||
1 => Color::FlagRed,
|
||||
2 => Color::FlagOrange,
|
||||
3 => Color::FlagGreen,
|
||||
4 => Color::FlagBlue,
|
||||
_ => {
|
||||
if self.note.is_marked() {
|
||||
Color::Marked
|
||||
} else if self.cards[0].queue == CardQueue::Suspended {
|
||||
Color::Suspended
|
||||
} else {
|
||||
Color::Default
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user