Merge row contexts
This commit is contained in:
parent
8a131da9a2
commit
c6ebb9b441
@ -94,55 +94,9 @@ pub struct Font {
|
|||||||
pub size: u32,
|
pub size: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
trait RowContext {
|
struct RowContext {
|
||||||
fn get_cell_text(&mut self, column: Column) -> Result<String>;
|
notes_mode: bool,
|
||||||
fn get_row_color(&self) -> Color;
|
cards: Vec<Card>,
|
||||||
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,
|
|
||||||
note: Note,
|
note: Note,
|
||||||
notetype: Arc<Notetype>,
|
notetype: Arc<Notetype>,
|
||||||
deck: Arc<Deck>,
|
deck: Arc<Deck>,
|
||||||
@ -159,14 +113,6 @@ struct RenderContext {
|
|||||||
answer_nodes: Vec<RenderedNode>,
|
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 {
|
fn card_render_required(columns: &[Column]) -> bool {
|
||||||
columns
|
columns
|
||||||
.iter()
|
.iter()
|
||||||
@ -218,18 +164,15 @@ impl Note {
|
|||||||
|
|
||||||
impl Collection {
|
impl Collection {
|
||||||
pub fn browser_row_for_id(&mut self, id: i64) -> Result<Row> {
|
pub fn browser_row_for_id(&mut self, id: i64) -> Result<Row> {
|
||||||
if self.get_bool(BoolKey::BrowserTableShowNotesMode) {
|
let notes_mode = self.get_bool(BoolKey::BrowserTableShowNotesMode);
|
||||||
let columns = self
|
let columns = if notes_mode {
|
||||||
.get_desktop_browser_note_columns()
|
self.get_desktop_browser_note_columns()
|
||||||
.ok_or_else(|| AnkiError::invalid_input("Note columns not set."))?;
|
.ok_or_else(|| AnkiError::invalid_input("Note columns not set."))?
|
||||||
NoteRowContext::new(self, id)?.browser_row_for_id(&columns)
|
|
||||||
} else {
|
} else {
|
||||||
let columns = self
|
self.get_desktop_browser_card_columns()
|
||||||
.get_desktop_browser_card_columns()
|
.ok_or_else(|| AnkiError::invalid_input("Card columns not set."))?
|
||||||
.ok_or_else(|| AnkiError::invalid_input("Card columns not set."))?;
|
};
|
||||||
CardRowContext::new(self, id, card_render_required(&columns))?
|
RowContext::new(self, id, notes_mode, card_render_required(&columns))?.browser_row(&columns)
|
||||||
.browser_row_for_id(&columns)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_note_maybe_with_fields(&self, id: NoteId, _with_fields: bool) -> Result<Note> {
|
fn get_note_maybe_with_fields(&self, id: NoteId, _with_fields: bool) -> Result<Note> {
|
||||||
@ -275,20 +218,32 @@ impl RenderContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CardRowContext {
|
impl RowContext {
|
||||||
fn new(col: &mut Collection, id: i64, with_card_render: bool) -> Result<Self> {
|
fn new(
|
||||||
let card = col
|
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
|
.storage
|
||||||
.get_card(CardId(id))?
|
.get_card(CardId(id))?
|
||||||
.ok_or(AnkiError::NotFound)?;
|
.ok_or(AnkiError::NotFound)?];
|
||||||
let note = col.get_note_maybe_with_fields(card.note_id, with_card_render)?;
|
note = col.get_note_maybe_with_fields(cards[0].note_id, with_card_render)?;
|
||||||
|
}
|
||||||
let notetype = col
|
let notetype = col
|
||||||
.get_notetype(note.notetype_id)?
|
.get_notetype(note.notetype_id)?
|
||||||
.ok_or(AnkiError::NotFound)?;
|
.ok_or(AnkiError::NotFound)?;
|
||||||
let deck = col.get_deck(card.deck_id)?.ok_or(AnkiError::NotFound)?;
|
let deck = col.get_deck(cards[0].deck_id)?.ok_or(AnkiError::NotFound)?;
|
||||||
let original_deck = if card.original_deck_id.0 != 0 {
|
let original_deck = if cards[0].original_deck_id.0 != 0 {
|
||||||
Some(
|
Some(
|
||||||
col.get_deck(card.original_deck_id)?
|
col.get_deck(cards[0].original_deck_id)?
|
||||||
.ok_or(AnkiError::NotFound)?,
|
.ok_or(AnkiError::NotFound)?,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@ -296,13 +251,14 @@ impl CardRowContext {
|
|||||||
};
|
};
|
||||||
let timing = col.timing_today()?;
|
let timing = col.timing_today()?;
|
||||||
let render_context = if with_card_render {
|
let render_context = if with_card_render {
|
||||||
Some(RenderContext::new(col, &card, ¬e, ¬etype)?)
|
Some(RenderContext::new(col, &cards[0], ¬e, ¬etype)?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(CardRowContext {
|
Ok(RowContext {
|
||||||
card,
|
notes_mode,
|
||||||
|
cards,
|
||||||
note,
|
note,
|
||||||
notetype,
|
notetype,
|
||||||
deck,
|
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> {
|
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 {
|
fn answer_str(&self) -> String {
|
||||||
@ -343,16 +363,16 @@ impl CardRowContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn card_due_str(&mut self) -> String {
|
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()
|
self.tr.browsing_filtered()
|
||||||
} else if self.card.is_new_type_or_queue() {
|
} else if self.cards[0].is_new_type_or_queue() {
|
||||||
self.tr.statistics_due_for_new_card(self.card.due)
|
self.tr.statistics_due_for_new_card(self.cards[0].due)
|
||||||
} else if let Some(time) = self.card.due_time(&self.timing) {
|
} else if let Some(time) = self.cards[0].due_time(&self.timing) {
|
||||||
time.date_string().into()
|
time.date_string().into()
|
||||||
} else {
|
} else {
|
||||||
return "".into();
|
return "".into();
|
||||||
};
|
};
|
||||||
if self.card.is_undue_queue() {
|
if self.cards[0].is_undue_queue() {
|
||||||
format!("({})", due)
|
format!("({})", due)
|
||||||
} else {
|
} else {
|
||||||
due.into()
|
due.into()
|
||||||
@ -360,17 +380,17 @@ impl CardRowContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn card_ease_str(&self) -> String {
|
fn card_ease_str(&self) -> String {
|
||||||
match self.card.ctype {
|
match self.cards[0].ctype {
|
||||||
CardType::New => self.tr.browsing_new().into(),
|
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 {
|
fn card_interval_str(&self) -> String {
|
||||||
match self.card.ctype {
|
match self.cards[0].ctype {
|
||||||
CardType::New => self.tr.browsing_new().into(),
|
CardType::New => self.tr.browsing_new().into(),
|
||||||
CardType::Learn => self.tr.browsing_learning().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;
|
let name = &self.template()?.name;
|
||||||
Ok(match self.notetype.config.kind() {
|
Ok(match self.notetype.config.kind() {
|
||||||
NotetypeKind::Normal => name.to_owned(),
|
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 {
|
fn question_str(&self) -> String {
|
||||||
html_to_text_line(&self.render_context.as_ref().unwrap().question).to_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.
|
/// Returns the average ease of the non-new cards or a hint if there aren't any.
|
||||||
fn note_ease_str(&self) -> String {
|
fn note_ease_str(&self) -> String {
|
||||||
@ -516,46 +461,37 @@ impl NoteRowContext {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl RowContext for NoteRowContext {
|
fn get_row_font(&self) -> Result<Font> {
|
||||||
fn get_cell_text(&mut self, column: Column) -> Result<String> {
|
Ok(Font {
|
||||||
Ok(match column {
|
name: self.template()?.config.browser_font_name.to_owned(),
|
||||||
Column::NoteCards => self.cards.len().to_string(),
|
size: self.template()?.config.browser_font_size,
|
||||||
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_color(&self) -> Color {
|
fn get_row_color(&self) -> Color {
|
||||||
|
if self.notes_mode {
|
||||||
if self.note.is_marked() {
|
if self.note.is_marked() {
|
||||||
Color::Marked
|
Color::Marked
|
||||||
} else {
|
} else {
|
||||||
Color::Default
|
Color::Default
|
||||||
}
|
}
|
||||||
|
} 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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user