Unify state columns
* Remove duplicate backend columns * Remove duplicate column routines * Move columns on frontend from state to model * Generate available columns from Colum enum * Add second column label for notes mode
This commit is contained in:
parent
dd56dc6650
commit
c74078ea9e
@ -697,11 +697,8 @@ class Collection:
|
||||
# Browser Table
|
||||
##########################################################################
|
||||
|
||||
def all_browser_card_columns(self) -> Sequence[BrowserColumns.Column]:
|
||||
return self._backend.all_browser_card_columns()
|
||||
|
||||
def all_browser_note_columns(self) -> Sequence[BrowserColumns.Column]:
|
||||
return self._backend.all_browser_note_columns()
|
||||
def all_browser_columns(self) -> Sequence[BrowserColumns.Column]:
|
||||
return self._backend.all_browser_columns()
|
||||
|
||||
def browser_row_for_id(
|
||||
self, id_: int
|
||||
|
@ -347,8 +347,8 @@ class Table:
|
||||
def _on_header_context(self, pos: QPoint) -> None:
|
||||
gpos = self._view.mapToGlobal(pos)
|
||||
m = QMenu()
|
||||
for key, column in self._state.columns.items():
|
||||
a = m.addAction(column.label)
|
||||
for key, column in self._model.columns.items():
|
||||
a = m.addAction(self._state.column_label(column))
|
||||
a.setCheckable(True)
|
||||
a.setChecked(self._model.active_column_index(key) is not None)
|
||||
qconnect(
|
||||
@ -522,7 +522,6 @@ class Table:
|
||||
|
||||
|
||||
class ItemState(ABC):
|
||||
_columns: Dict[str, Column]
|
||||
_active_columns: List[str]
|
||||
_sort_column: str
|
||||
_sort_backwards: bool
|
||||
@ -544,26 +543,16 @@ class ItemState(ABC):
|
||||
def card_ids_from_note_ids(self, items: Sequence[ItemId]) -> Sequence[CardId]:
|
||||
return self.col.db.list(f"select id from cards where nid in {ids2str(items)}")
|
||||
|
||||
def column_at(self, index: int) -> Column:
|
||||
"""Returns the column object corresponding to the active column at index or the default
|
||||
column object if no data is associated with the active column.
|
||||
"""
|
||||
def column_key_at(self, index: int) -> str:
|
||||
return self._active_columns[index]
|
||||
|
||||
key = self._active_columns[index]
|
||||
try:
|
||||
return self._columns[key]
|
||||
except KeyError:
|
||||
self._columns[key] = addon_column_fillin(key)
|
||||
return self._columns[key]
|
||||
def column_label(self, column: Column) -> str:
|
||||
return column.notes_label if self.is_notes_mode() else column.label
|
||||
|
||||
# Columns and sorting
|
||||
|
||||
# abstractproperty is deprecated but used due to mypy limitations
|
||||
# (https://github.com/python/mypy/issues/1362)
|
||||
@abstractproperty
|
||||
def columns(self) -> Dict[str, Column]:
|
||||
"""Return all for the state available columns."""
|
||||
|
||||
@abstractproperty
|
||||
def active_columns(self) -> List[str]:
|
||||
"""Return the saved or default columns for the state."""
|
||||
@ -630,17 +619,12 @@ class ItemState(ABC):
|
||||
class CardState(ItemState):
|
||||
def __init__(self, col: Collection) -> None:
|
||||
super().__init__(col)
|
||||
self._columns = dict(((c.key, c) for c in self.col.all_browser_card_columns()))
|
||||
self._active_columns = self.col.load_browser_card_columns()
|
||||
self._sort_column = self.col.get_config("sortType")
|
||||
self._sort_backwards = self.col.get_config_bool(
|
||||
Config.Bool.BROWSER_SORT_BACKWARDS
|
||||
)
|
||||
|
||||
@property
|
||||
def columns(self) -> Dict[str, Column]:
|
||||
return self._columns
|
||||
|
||||
@property
|
||||
def active_columns(self) -> List[str]:
|
||||
return self._active_columns
|
||||
@ -698,17 +682,12 @@ class CardState(ItemState):
|
||||
class NoteState(ItemState):
|
||||
def __init__(self, col: Collection) -> None:
|
||||
super().__init__(col)
|
||||
self._columns = dict(((c.key, c) for c in self.col.all_browser_note_columns()))
|
||||
self._active_columns = self.col.load_browser_note_columns()
|
||||
self._sort_column = self.col.get_config("noteSortType")
|
||||
self._sort_backwards = self.col.get_config_bool(
|
||||
Config.Bool.BROWSER_NOTE_SORT_BACKWARDS
|
||||
)
|
||||
|
||||
@property
|
||||
def columns(self) -> Dict[str, Column]:
|
||||
return self._columns
|
||||
|
||||
@property
|
||||
def active_columns(self) -> List[str]:
|
||||
return self._active_columns
|
||||
@ -832,6 +811,9 @@ class DataModel(QAbstractTableModel):
|
||||
def __init__(self, col: Collection, state: ItemState) -> None:
|
||||
QAbstractTableModel.__init__(self)
|
||||
self.col: Collection = col
|
||||
self.columns: Dict[str, Column] = dict(
|
||||
((c.key, c) for c in self.col.all_browser_columns())
|
||||
)
|
||||
self._state: ItemState = state
|
||||
self._items: Sequence[ItemId] = []
|
||||
self._rows: Dict[int, CellRow] = {}
|
||||
@ -1002,10 +984,18 @@ class DataModel(QAbstractTableModel):
|
||||
# Columns
|
||||
|
||||
def column_at(self, index: QModelIndex) -> Column:
|
||||
return self._state.column_at(index.column())
|
||||
return self.column_at_section(index.column())
|
||||
|
||||
def column_at_section(self, section: int) -> Column:
|
||||
return self._state.column_at(section)
|
||||
"""Returns the column object corresponding to the active column at index or the default
|
||||
column object if no data is associated with the active column.
|
||||
"""
|
||||
key = self._state.column_key_at(section)
|
||||
try:
|
||||
return self.columns[key]
|
||||
except KeyError:
|
||||
self.columns[key] = addon_column_fillin(key)
|
||||
return self.columns[key]
|
||||
|
||||
def active_column_index(self, column: str) -> Optional[int]:
|
||||
return (
|
||||
@ -1056,7 +1046,7 @@ class DataModel(QAbstractTableModel):
|
||||
self, section: int, orientation: Qt.Orientation, role: int = 0
|
||||
) -> Optional[str]:
|
||||
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
|
||||
return self.column_at_section(section).label
|
||||
return self._state.column_label(self.column_at_section(section))
|
||||
return None
|
||||
|
||||
def flags(self, index: QModelIndex) -> Qt.ItemFlags:
|
||||
@ -1094,6 +1084,7 @@ def addon_column_fillin(key: str) -> Column:
|
||||
return Column(
|
||||
key=key,
|
||||
label=tr.browsing_addon(),
|
||||
notes_label=tr.browsing_addon(),
|
||||
sorting=Columns.SORTING_NONE,
|
||||
uses_cell_font=False,
|
||||
alignment=Columns.ALIGNMENT_CENTER,
|
||||
|
@ -248,8 +248,7 @@ service SearchService {
|
||||
rpc JoinSearchNodes(JoinSearchNodesIn) returns (String);
|
||||
rpc ReplaceSearchNode(ReplaceSearchNodeIn) returns (String);
|
||||
rpc FindAndReplace(FindAndReplaceIn) returns (OpChangesWithCount);
|
||||
rpc AllBrowserCardColumns(Empty) returns (BrowserColumns);
|
||||
rpc AllBrowserNoteColumns(Empty) returns (BrowserColumns);
|
||||
rpc AllBrowserColumns(Empty) returns (BrowserColumns);
|
||||
rpc BrowserRowForId(Int64) returns (BrowserRow);
|
||||
rpc SetDesktopBrowserCardColumns(StringList) returns (Empty);
|
||||
rpc SetDesktopBrowserNoteColumns(StringList) returns (Empty);
|
||||
@ -1067,7 +1066,8 @@ message BrowserColumns {
|
||||
message Column {
|
||||
string key = 1;
|
||||
string label = 2;
|
||||
Sorting sorting = 3;
|
||||
string notes_label = 3;
|
||||
Sorting sorting = 4;
|
||||
bool uses_cell_font = 5;
|
||||
Alignment alignment = 6;
|
||||
}
|
||||
|
@ -3,54 +3,16 @@
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::{backend_proto as pb, browser_table, collection::Collection, i18n::I18n};
|
||||
|
||||
const CARD_COLUMNS: [browser_table::Column; 15] = [
|
||||
browser_table::Column::Question,
|
||||
browser_table::Column::Answer,
|
||||
browser_table::Column::Deck,
|
||||
browser_table::Column::Due,
|
||||
browser_table::Column::Ease,
|
||||
browser_table::Column::Lapses,
|
||||
browser_table::Column::Interval,
|
||||
browser_table::Column::CardMod,
|
||||
browser_table::Column::Reps,
|
||||
browser_table::Column::Cards,
|
||||
browser_table::Column::NoteCreation,
|
||||
browser_table::Column::SortField,
|
||||
browser_table::Column::NoteMod,
|
||||
browser_table::Column::Tags,
|
||||
browser_table::Column::Notetype,
|
||||
];
|
||||
|
||||
const NOTE_COLUMNS: [browser_table::Column; 13] = [
|
||||
browser_table::Column::Deck,
|
||||
browser_table::Column::CardMod,
|
||||
browser_table::Column::NoteCards,
|
||||
browser_table::Column::NoteCreation,
|
||||
browser_table::Column::NoteDue,
|
||||
browser_table::Column::NoteEase,
|
||||
browser_table::Column::SortField,
|
||||
browser_table::Column::NoteInterval,
|
||||
browser_table::Column::NoteLapses,
|
||||
browser_table::Column::NoteMod,
|
||||
browser_table::Column::NoteReps,
|
||||
browser_table::Column::Tags,
|
||||
browser_table::Column::Notetype,
|
||||
];
|
||||
|
||||
impl Collection {
|
||||
pub(crate) fn all_browser_card_columns(&self) -> pb::BrowserColumns {
|
||||
self.to_pb_columns(&CARD_COLUMNS)
|
||||
}
|
||||
|
||||
pub(crate) fn all_browser_note_columns(&self) -> pb::BrowserColumns {
|
||||
self.to_pb_columns(&NOTE_COLUMNS)
|
||||
}
|
||||
|
||||
fn to_pb_columns(&self, columns: &[browser_table::Column]) -> pb::BrowserColumns {
|
||||
let mut columns: Vec<pb::browser_columns::Column> =
|
||||
columns.iter().map(|c| c.to_pb_column(&self.tr)).collect();
|
||||
pub(crate) fn all_browser_columns(&self) -> pb::BrowserColumns {
|
||||
let mut columns: Vec<pb::browser_columns::Column> = browser_table::Column::iter()
|
||||
.filter(|&c| c != browser_table::Column::Custom)
|
||||
.map(|c| c.to_pb_column(&self.tr))
|
||||
.collect();
|
||||
columns.sort_by(|c1, c2| c1.label.cmp(&c2.label));
|
||||
pb::BrowserColumns { columns }
|
||||
}
|
||||
@ -61,6 +23,7 @@ impl browser_table::Column {
|
||||
pb::browser_columns::Column {
|
||||
key: self.to_string(),
|
||||
label: self.localized_label(i18n),
|
||||
notes_label: self.localized_notes_label(i18n),
|
||||
sorting: self.sorting() as i32,
|
||||
uses_cell_font: self.uses_cell_font(),
|
||||
alignment: self.alignment() as i32,
|
||||
@ -94,28 +57,34 @@ impl browser_table::Column {
|
||||
|
||||
fn localized_label(self, i18n: &I18n) -> String {
|
||||
match self {
|
||||
Self::Custom => i18n.browsing_addon(),
|
||||
Self::Question => i18n.browsing_question(),
|
||||
Self::Answer => i18n.browsing_answer(),
|
||||
Self::CardMod => i18n.search_card_modified(),
|
||||
Self::Cards => i18n.browsing_card(),
|
||||
Self::Deck => i18n.decks_deck(),
|
||||
Self::Due => i18n.statistics_due_date(),
|
||||
Self::Custom => i18n.browsing_addon(),
|
||||
Self::Ease => i18n.browsing_ease(),
|
||||
Self::Interval => i18n.browsing_interval(),
|
||||
Self::Lapses => i18n.scheduling_lapses(),
|
||||
Self::CardMod => i18n.search_card_modified(),
|
||||
Self::Reps => i18n.scheduling_reviews(),
|
||||
Self::Cards => i18n.browsing_card(),
|
||||
Self::NoteCards => i18n.editing_cards(),
|
||||
Self::NoteCreation => i18n.browsing_created(),
|
||||
Self::NoteDue => i18n.statistics_due_date(),
|
||||
Self::NoteEase => i18n.browsing_average_ease(),
|
||||
Self::SortField => i18n.browsing_sort_field(),
|
||||
Self::NoteInterval => i18n.browsing_average_interval(),
|
||||
Self::NoteMod => i18n.search_note_modified(),
|
||||
Self::NoteLapses => i18n.scheduling_lapses(),
|
||||
Self::NoteReps => i18n.scheduling_reviews(),
|
||||
Self::Tags => i18n.editing_tags(),
|
||||
Self::Notetype => i18n.browsing_note(),
|
||||
Self::Question => i18n.browsing_question(),
|
||||
Self::Reps => i18n.scheduling_reviews(),
|
||||
Self::SortField => i18n.browsing_sort_field(),
|
||||
Self::Tags => i18n.editing_tags(),
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
||||
fn localized_notes_label(self, i18n: &I18n) -> String {
|
||||
match self {
|
||||
Self::CardMod => i18n.search_card_modified(),
|
||||
Self::Cards => i18n.editing_cards(),
|
||||
Self::Ease => i18n.browsing_average_ease(),
|
||||
Self::Interval => i18n.browsing_average_interval(),
|
||||
Self::Reps => i18n.scheduling_reviews(),
|
||||
_ => return self.localized_label(i18n),
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
@ -89,12 +89,8 @@ impl SearchService for Backend {
|
||||
})
|
||||
}
|
||||
|
||||
fn all_browser_card_columns(&self, _input: pb::Empty) -> Result<pb::BrowserColumns> {
|
||||
self.with_col(|col| Ok(col.all_browser_card_columns()))
|
||||
}
|
||||
|
||||
fn all_browser_note_columns(&self, _input: pb::Empty) -> Result<pb::BrowserColumns> {
|
||||
self.with_col(|col| Ok(col.all_browser_note_columns()))
|
||||
fn all_browser_columns(&self, _input: pb::Empty) -> Result<pb::BrowserColumns> {
|
||||
self.with_col(|col| Ok(col.all_browser_columns()))
|
||||
}
|
||||
|
||||
fn browser_row_for_id(&self, input: pb::Int64) -> Result<pb::BrowserRow> {
|
||||
|
@ -5,7 +5,7 @@ use std::sync::Arc;
|
||||
|
||||
use itertools::Itertools;
|
||||
use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||
use strum::{Display, EnumString};
|
||||
use strum::{Display, EnumIter, EnumString};
|
||||
|
||||
use crate::error::{AnkiError, Result};
|
||||
use crate::i18n::I18n;
|
||||
@ -22,14 +22,18 @@ use crate::{
|
||||
timestamp::{TimestampMillis, TimestampSecs},
|
||||
};
|
||||
|
||||
#[derive(Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy, Display, EnumString)]
|
||||
#[derive(
|
||||
Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy, Display, EnumString, EnumIter,
|
||||
)]
|
||||
#[strum(serialize_all = "camelCase")]
|
||||
#[repr(u8)]
|
||||
pub enum Column {
|
||||
#[strum(serialize = "")]
|
||||
Custom,
|
||||
Question,
|
||||
Answer,
|
||||
CardMod,
|
||||
#[strum(serialize = "template")]
|
||||
Cards,
|
||||
Deck,
|
||||
#[strum(serialize = "cardDue")]
|
||||
Due,
|
||||
@ -39,26 +43,17 @@ pub enum Column {
|
||||
Lapses,
|
||||
#[strum(serialize = "cardIvl")]
|
||||
Interval,
|
||||
CardMod,
|
||||
#[strum(serialize = "cardReps")]
|
||||
Reps,
|
||||
#[strum(serialize = "template")]
|
||||
Cards,
|
||||
NoteCards,
|
||||
#[strum(serialize = "noteCrt")]
|
||||
NoteCreation,
|
||||
NoteDue,
|
||||
NoteEase,
|
||||
#[strum(serialize = "noteFld")]
|
||||
SortField,
|
||||
#[strum(serialize = "noteIvl")]
|
||||
NoteInterval,
|
||||
NoteLapses,
|
||||
NoteMod,
|
||||
NoteReps,
|
||||
Tags,
|
||||
#[strum(serialize = "note")]
|
||||
Notetype,
|
||||
Question,
|
||||
#[strum(serialize = "cardReps")]
|
||||
Reps,
|
||||
#[strum(serialize = "noteFld")]
|
||||
SortField,
|
||||
Tags,
|
||||
}
|
||||
|
||||
impl Default for Column {
|
||||
@ -295,17 +290,13 @@ impl RowContext {
|
||||
Column::Question => self.question_str(),
|
||||
Column::Answer => self.answer_str(),
|
||||
Column::Deck => self.deck_str(),
|
||||
Column::Due | Column::NoteDue => self.due_str(),
|
||||
Column::Ease | Column::NoteEase => self.ease_str(),
|
||||
Column::Interval | Column::NoteInterval => self.interval_str(),
|
||||
Column::Lapses | Column::NoteLapses => {
|
||||
self.cards.iter().map(|c| c.lapses).sum::<u32>().to_string()
|
||||
}
|
||||
Column::Due => self.due_str(),
|
||||
Column::Ease => self.ease_str(),
|
||||
Column::Interval => self.interval_str(),
|
||||
Column::Lapses => self.cards.iter().map(|c| c.lapses).sum::<u32>().to_string(),
|
||||
Column::CardMod => self.card_mod_str(),
|
||||
Column::Reps | Column::NoteReps => {
|
||||
self.cards.iter().map(|c| c.reps).sum::<u32>().to_string()
|
||||
}
|
||||
Column::Cards | Column::NoteCards => self.cards_str()?,
|
||||
Column::Reps => self.cards.iter().map(|c| c.reps).sum::<u32>().to_string(),
|
||||
Column::Cards => self.cards_str()?,
|
||||
Column::NoteCreation => self.note_creation_str(),
|
||||
Column::SortField => self.note_field_str(),
|
||||
Column::NoteMod => self.note.mtime.date_string(),
|
||||
|
Loading…
Reference in New Issue
Block a user