use native struct for NoteType

This commit is contained in:
Damien Elmes 2020-04-14 08:47:48 +10:00
parent d6646a6db5
commit 8cfb1fad44
9 changed files with 84 additions and 58 deletions

View File

@ -319,7 +319,10 @@ impl Backend {
OValue::SetAllDecks(pb::Empty {})
}
Value::AllStockNotetypes(_) => OValue::AllStockNotetypes(pb::AllStockNotetypesOut {
notetypes: all_stock_notetypes(&self.i18n),
notetypes: all_stock_notetypes(&self.i18n)
.into_iter()
.map(Into::into)
.collect(),
}),
})
}

View File

@ -401,12 +401,16 @@ where
&self.mgr.media_folder,
)? {
// note was modified, needs saving
set_note(&self.ctx.storage.db, note, nt.sort_field_idx())?;
set_note(
&self.ctx.storage.db,
note,
nt.config.sort_field_idx as usize,
)?;
collection_modified = true;
}
// extract latex
extract_latex_refs(note, &mut referenced_files, nt.latex_uses_svg());
extract_latex_refs(note, &mut referenced_files, nt.config.latex_svg);
Ok(())
})?;

View File

@ -6,7 +6,7 @@ mod stock;
pub use crate::backend_proto::{
card_requirement::CardRequirementKind, CardRequirement, CardTemplate, CardTemplateConfig,
NoteField, NoteFieldConfig, NoteType, NoteTypeConfig, NoteTypeKind,
NoteField, NoteFieldConfig, NoteType as NoteTypeProto, NoteTypeConfig, NoteTypeKind,
};
pub use schema11::{CardTemplateSchema11, NoteFieldSchema11, NoteTypeSchema11};
pub use stock::all_stock_notetypes;
@ -15,6 +15,8 @@ use crate::{
define_newtype,
template::{without_legacy_template_directives, FieldRequirements, ParsedTemplate},
text::ensure_string_in_nfc,
timestamp::TimestampSecs,
types::Usn,
};
use std::collections::{HashMap, HashSet};
use unicase::UniCase;
@ -42,29 +44,35 @@ pub(crate) const DEFAULT_LATEX_HEADER: &str = r#"\documentclass[12pt]{article}
pub(crate) const DEFAULT_LATEX_FOOTER: &str = r#"\end{document}"#;
impl NoteType {
pub fn new() -> Self {
let mut nt = Self::default();
pub struct NoteType {
pub id: NoteTypeID,
pub name: String,
pub mtime_secs: TimestampSecs,
pub usn: Usn,
pub fields: Vec<NoteField>,
pub templates: Vec<CardTemplate>,
pub config: NoteTypeConfig,
}
impl Default for NoteType {
fn default() -> Self {
let mut conf = NoteTypeConfig::default();
conf.css = DEFAULT_CSS.into();
conf.latex_pre = DEFAULT_LATEX_HEADER.into();
conf.latex_post = DEFAULT_LATEX_FOOTER.into();
nt.config = Some(conf);
nt
}
pub fn id(&self) -> NoteTypeID {
NoteTypeID(self.id)
}
pub fn sort_field_idx(&self) -> usize {
self.config.as_ref().unwrap().sort_field_idx as usize
}
pub fn latex_uses_svg(&self) -> bool {
self.config.as_ref().unwrap().latex_svg
NoteType {
id: NoteTypeID(0),
name: "".into(),
mtime_secs: TimestampSecs(0),
usn: Usn(0),
fields: vec![],
templates: vec![],
config: conf,
}
}
}
impl NoteType {
pub(crate) fn ensure_names_unique(&mut self) {
let mut names = HashSet::new();
for t in &mut self.templates {
@ -134,7 +142,7 @@ impl NoteType {
}
})
.collect();
self.config.as_mut().unwrap().reqs = reqs;
self.config.reqs = reqs;
}
pub(crate) fn normalize_names(&mut self) {
@ -180,3 +188,17 @@ impl NoteType {
self.update_requirements();
}
}
impl From<NoteType> for NoteTypeProto {
fn from(nt: NoteType) -> Self {
NoteTypeProto {
id: nt.id.0,
name: nt.name,
mtime_secs: nt.mtime_secs.0 as u32,
usn: nt.usn.0,
config: Some(nt.config),
fields: nt.fields,
templates: nt.templates,
}
}
}

View File

@ -88,11 +88,11 @@ impl NoteTypeSchema11 {
impl From<NoteTypeSchema11> for NoteType {
fn from(nt: NoteTypeSchema11) -> Self {
NoteType {
id: nt.id.0,
id: nt.id,
name: nt.name,
mtime_secs: nt.mtime.0 as u32,
usn: nt.usn.0,
config: Some(NoteTypeConfig {
mtime_secs: nt.mtime,
usn: nt.usn,
config: NoteTypeConfig {
kind: nt.kind as i32,
sort_field_idx: nt.sortf as u32,
css: nt.css,
@ -102,7 +102,7 @@ impl From<NoteTypeSchema11> for NoteType {
latex_svg: nt.latexsvg,
reqs: nt.req.0.into_iter().map(Into::into).collect(),
other: other_to_bytes(&nt.other),
}),
},
fields: nt.flds.into_iter().map(Into::into).collect(),
templates: nt.tmpls.into_iter().map(Into::into).collect(),
}
@ -134,17 +134,17 @@ fn bytes_to_other(bytes: &[u8]) -> HashMap<String, Value> {
impl From<NoteType> for NoteTypeSchema11 {
fn from(p: NoteType) -> Self {
let c = p.config.unwrap();
let c = p.config;
NoteTypeSchema11 {
id: NoteTypeID(p.id),
id: p.id,
name: p.name,
kind: if c.kind == 1 {
NoteTypeKind::Cloze
} else {
NoteTypeKind::Standard
},
mtime: TimestampSecs(p.mtime_secs as i64),
usn: Usn(p.usn),
mtime: p.mtime_secs,
usn: p.usn,
sortf: c.sort_field_idx as u16,
did: if c.target_deck_id == 0 {
None

View File

@ -16,7 +16,7 @@ impl SqliteStorage {
if idx == StockNoteType::Basic as usize {
self.set_config_value(
ConfigKey::CurrentNoteTypeID.into(),
&nt.id(),
&nt.id,
self.usn(false)?,
TimestampSecs::now(),
)?;
@ -43,7 +43,7 @@ fn fieldref<S: AsRef<str>>(name: S) -> String {
}
pub(crate) fn basic(i18n: &I18n) -> NoteType {
let mut nt = NoteType::new();
let mut nt = NoteType::default();
nt.name = i18n.tr(TR::NotetypesBasicName).into();
let front = i18n.tr(TR::NotetypesFrontField);
let back = i18n.tr(TR::NotetypesBackField);
@ -108,15 +108,14 @@ pub(crate) fn basic_optional_reverse(i18n: &I18n) -> NoteType {
}
pub(crate) fn cloze(i18n: &I18n) -> NoteType {
let mut nt = NoteType::new();
let mut nt = NoteType::default();
nt.name = i18n.tr(TR::NotetypesClozeName).into();
let text = i18n.tr(TR::NotetypesTextField);
nt.add_field(text.as_ref());
let fmt = format!("{{{{cloze:{}}}}}", text);
nt.add_template(nt.name.clone(), fmt.clone(), fmt);
let mut config = nt.config.as_mut().unwrap();
config.kind = NoteTypeKind::Cloze as i32;
config.css += "
nt.config.kind = NoteTypeKind::Cloze as i32;
nt.config.css += "
.cloze {
font-weight: bold;
color: blue;

View File

@ -301,10 +301,10 @@ impl SqlWriter<'_> {
let mut field_map = vec![];
for nt in note_types.values() {
let fields = self.col.storage.get_notetype_fields(nt.id())?;
let fields = self.col.storage.get_notetype_fields(nt.id)?;
for field in &fields {
if matches_wildcard(&field.name, field_name) {
field_map.push((nt.id(), field.ord));
field_map.push((nt.id, field.ord));
}
}
}

View File

@ -3,11 +3,9 @@
use super::SqliteStorage;
use crate::{
backend_proto::{
CardTemplate, CardTemplateConfig, NoteField, NoteFieldConfig, NoteType, NoteTypeConfig,
},
backend_proto::{CardTemplate, CardTemplateConfig, NoteField, NoteFieldConfig, NoteTypeConfig},
err::{AnkiError, DBErrorKind, Result},
notetype::{NoteTypeID, NoteTypeSchema11},
notetype::{NoteType, NoteTypeID, NoteTypeSchema11},
timestamp::TimestampMillis,
};
use prost::Message;
@ -22,7 +20,7 @@ fn row_to_notetype_core(row: &Row) -> Result<NoteType> {
name: row.get(1)?,
mtime_secs: row.get(2)?,
usn: row.get(3)?,
config: Some(config),
config,
fields: vec![],
templates: vec![],
})
@ -41,7 +39,7 @@ impl SqliteStorage {
self.db
.prepare_cached(include_str!("get_notetype.sql"))?
.query_and_then(NO_PARAMS, row_to_notetype_core)?
.map(|ntres| ntres.map(|nt| (nt.id(), nt)))
.map(|ntres| ntres.map(|nt| (nt.id, nt)))
.collect()
}
@ -86,7 +84,8 @@ impl SqliteStorage {
}
}
fn get_all_notetype_meta(&self) -> Result<Vec<(NoteTypeID, String)>> {
#[allow(dead_code)]
fn get_all_notetype_names(&self) -> Result<Vec<(NoteTypeID, String)>> {
self.db
.prepare_cached(include_str!("get_notetype_names.sql"))?
.query_and_then(NO_PARAMS, |row| Ok((row.get(0)?, row.get(1)?)))?
@ -97,7 +96,7 @@ impl SqliteStorage {
&self,
) -> Result<HashMap<NoteTypeID, NoteTypeSchema11>> {
let mut nts = HashMap::new();
for (ntid, _name) in self.get_all_notetype_meta()? {
for (ntid, _name) in self.get_all_notetype_core()? {
let full = self.get_full_notetype(ntid)?.unwrap();
nts.insert(ntid, full.into());
}
@ -149,24 +148,24 @@ impl SqliteStorage {
Ok(())
}
fn update_notetype_meta(&self, nt: &NoteType) -> Result<()> {
assert!(nt.id != 0);
fn update_notetype_config(&self, nt: &NoteType) -> Result<()> {
assert!(nt.id.0 != 0);
let mut stmt = self
.db
.prepare_cached(include_str!("update_notetype_meta.sql"))?;
.prepare_cached(include_str!("update_notetype_core.sql"))?;
let mut config_bytes = vec![];
nt.config.as_ref().unwrap().encode(&mut config_bytes)?;
nt.config.encode(&mut config_bytes)?;
stmt.execute(params![nt.id, nt.name, nt.mtime_secs, nt.usn, config_bytes])?;
Ok(())
}
pub(crate) fn add_new_notetype(&self, nt: &mut NoteType) -> Result<()> {
assert!(nt.id == 0);
assert!(nt.id.0 == 0);
let mut stmt = self.db.prepare_cached(include_str!("add_notetype.sql"))?;
let mut config_bytes = vec![];
nt.config.as_ref().unwrap().encode(&mut config_bytes)?;
nt.config.encode(&mut config_bytes)?;
stmt.execute(params![
TimestampMillis::now(),
nt.name,
@ -174,10 +173,10 @@ impl SqliteStorage {
nt.usn,
config_bytes
])?;
nt.id = self.db.last_insert_rowid();
nt.id.0 = self.db.last_insert_rowid();
self.update_notetype_fields(nt.id(), &nt.fields)?;
self.update_notetype_templates(nt.id(), &nt.templates)?;
self.update_notetype_fields(nt.id, &nt.fields)?;
self.update_notetype_templates(nt.id, &nt.templates)?;
Ok(())
}
@ -199,7 +198,7 @@ impl SqliteStorage {
}
nt.name.push('_');
}
self.update_notetype_meta(&nt)?;
self.update_notetype_config(&nt)?;
self.update_notetype_fields(ntid, &nt.fields)?;
self.update_notetype_templates(ntid, &nt.templates)?;
}

View File

@ -21,7 +21,6 @@ fn unicase_compare(s1: &str, s2: &str) -> Ordering {
}
// fixme: rollback savepoint when tags not changed
// fixme: switch away from proto for top level struct
// currently public for dbproxy
#[derive(Debug)]