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:
RumovZ 2021-04-08 23:48:24 +02:00
parent dd56dc6650
commit c74078ea9e
6 changed files with 74 additions and 130 deletions

View File

@ -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

View File

@ -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,

View File

@ -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;
}

View File

@ -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()
}

View File

@ -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> {

View File

@ -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(),