mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 16:56:36 -04:00
move schema11 note type code into separate file
This commit is contained in:
parent
805a3a710e
commit
e2b978e7cb
8 changed files with 325 additions and 349 deletions
|
@ -94,12 +94,12 @@ pub(super) fn set_note(
|
||||||
note.usn = Usn(-1);
|
note.usn = Usn(-1);
|
||||||
let field1_nohtml = strip_html_preserving_image_filenames(¬e.fields()[0]);
|
let field1_nohtml = strip_html_preserving_image_filenames(¬e.fields()[0]);
|
||||||
let csum = field_checksum(field1_nohtml.as_ref());
|
let csum = field_checksum(field1_nohtml.as_ref());
|
||||||
let sort_field = if note_type.sort_field_idx == 0 {
|
let sort_field = if note_type.sortf == 0 {
|
||||||
field1_nohtml
|
field1_nohtml
|
||||||
} else {
|
} else {
|
||||||
strip_html_preserving_image_filenames(
|
strip_html_preserving_image_filenames(
|
||||||
note.fields()
|
note.fields()
|
||||||
.get(note_type.sort_field_idx as usize)
|
.get(note_type.sortf as usize)
|
||||||
.ok_or_else(|| AnkiError::DBError {
|
.ok_or_else(|| AnkiError::DBError {
|
||||||
info: "sort field out of range".to_string(),
|
info: "sort field out of range".to_string(),
|
||||||
kind: DBErrorKind::MissingEntity,
|
kind: DBErrorKind::MissingEntity,
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
// Copyright: Ankitects Pty Ltd and contributors
|
|
||||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
backend_proto::{NoteField as NoteFieldProto, NoteFieldConfig},
|
|
||||||
serde::deserialize_bool_from_anything,
|
|
||||||
};
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
|
||||||
use serde_json::Value;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub struct NoteFieldSchema11 {
|
|
||||||
pub(crate) name: String,
|
|
||||||
pub(crate) ord: u16,
|
|
||||||
#[serde(deserialize_with = "deserialize_bool_from_anything")]
|
|
||||||
pub(crate) sticky: bool,
|
|
||||||
#[serde(deserialize_with = "deserialize_bool_from_anything")]
|
|
||||||
pub(crate) rtl: bool,
|
|
||||||
pub(crate) font: String,
|
|
||||||
pub(crate) size: u16,
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub(crate) other: HashMap<String, Value>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for NoteFieldSchema11 {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
name: String::new(),
|
|
||||||
ord: 0,
|
|
||||||
sticky: false,
|
|
||||||
rtl: false,
|
|
||||||
font: "Arial".to_string(),
|
|
||||||
size: 20,
|
|
||||||
other: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<NoteFieldSchema11> for NoteFieldProto {
|
|
||||||
fn from(f: NoteFieldSchema11) -> Self {
|
|
||||||
NoteFieldProto {
|
|
||||||
ord: f.ord as u32,
|
|
||||||
name: f.name,
|
|
||||||
config: Some(NoteFieldConfig {
|
|
||||||
sticky: f.sticky,
|
|
||||||
rtl: f.rtl,
|
|
||||||
font_name: f.font,
|
|
||||||
font_size: f.size as u32,
|
|
||||||
other: serde_json::to_vec(&f.other).unwrap(),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<NoteFieldProto> for NoteFieldSchema11 {
|
|
||||||
fn from(p: NoteFieldProto) -> Self {
|
|
||||||
let conf = p.config.unwrap();
|
|
||||||
NoteFieldSchema11 {
|
|
||||||
name: p.name,
|
|
||||||
ord: p.ord as u16,
|
|
||||||
sticky: conf.sticky,
|
|
||||||
rtl: conf.rtl,
|
|
||||||
font: conf.font_name,
|
|
||||||
size: conf.font_size as u16,
|
|
||||||
other: serde_json::from_slice(&conf.other).unwrap(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +1,16 @@
|
||||||
// Copyright: Ankitects Pty Ltd and contributors
|
// Copyright: Ankitects Pty Ltd and contributors
|
||||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
mod field;
|
mod schema11;
|
||||||
mod template;
|
|
||||||
|
|
||||||
pub use field::NoteFieldSchema11;
|
pub use crate::backend_proto::{
|
||||||
pub use template::CardTemplateSchema11;
|
CardRequirement, CardTemplate, CardTemplateConfig, NoteField, NoteFieldConfig, NoteType,
|
||||||
|
NoteTypeConfig, NoteTypeKind,
|
||||||
use crate::{
|
|
||||||
backend_proto::{
|
|
||||||
CardRequirement as CardRequirementProto, NoteType as NoteTypeProto, NoteTypeConfig,
|
|
||||||
},
|
|
||||||
decks::DeckID,
|
|
||||||
define_newtype,
|
|
||||||
serde::{default_on_invalid, deserialize_number_from_string},
|
|
||||||
text::ensure_string_in_nfc,
|
|
||||||
timestamp::TimestampSecs,
|
|
||||||
types::Usn,
|
|
||||||
};
|
};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
pub use schema11::{CardTemplateSchema11, NoteFieldSchema11, NoteTypeSchema11};
|
||||||
use serde_json::Value;
|
|
||||||
use serde_repr::{Deserialize_repr, Serialize_repr};
|
use crate::{define_newtype, text::ensure_string_in_nfc};
|
||||||
use serde_tuple::Serialize_tuple;
|
use std::collections::HashSet;
|
||||||
use std::collections::{HashMap, HashSet};
|
|
||||||
use unicase::UniCase;
|
use unicase::UniCase;
|
||||||
|
|
||||||
define_newtype!(NoteTypeID, i64);
|
define_newtype!(NoteTypeID, i64);
|
||||||
|
@ -48,178 +36,23 @@ pub(crate) const DEFAULT_LATEX_HEADER: &str = r#"\documentclass[12pt]{article}
|
||||||
|
|
||||||
pub(crate) const DEFAULT_LATEX_FOOTER: &str = r#"\end{document}"#;
|
pub(crate) const DEFAULT_LATEX_FOOTER: &str = r#"\end{document}"#;
|
||||||
|
|
||||||
#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug, Clone)]
|
// other: vec![], // fixme: ensure empty map converted to empty bytes
|
||||||
#[repr(u8)]
|
|
||||||
pub enum NoteTypeKind {
|
|
||||||
Standard = 0,
|
|
||||||
Cloze = 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
impl NoteType {
|
||||||
#[serde(rename_all = "camelCase")]
|
pub fn new() -> Self {
|
||||||
pub struct NoteTypeSchema11 {
|
let mut nt = Self::default();
|
||||||
#[serde(deserialize_with = "deserialize_number_from_string")]
|
let mut conf = NoteTypeConfig::default();
|
||||||
pub(crate) id: NoteTypeID,
|
conf.css = DEFAULT_CSS.into();
|
||||||
pub(crate) name: String,
|
conf.latex_pre = DEFAULT_LATEX_HEADER.into();
|
||||||
#[serde(rename = "type")]
|
conf.latex_post = DEFAULT_LATEX_FOOTER.into();
|
||||||
pub(crate) kind: NoteTypeKind,
|
nt.config = Some(conf);
|
||||||
#[serde(rename = "mod")]
|
nt
|
||||||
pub(crate) mtime: TimestampSecs,
|
|
||||||
pub(crate) usn: Usn,
|
|
||||||
#[serde(rename = "sortf")]
|
|
||||||
pub(crate) sort_field_idx: u16,
|
|
||||||
#[serde(rename = "did", deserialize_with = "default_on_invalid")]
|
|
||||||
pub(crate) deck_id_for_adding: Option<DeckID>,
|
|
||||||
#[serde(rename = "tmpls")]
|
|
||||||
pub(crate) templates: Vec<CardTemplateSchema11>,
|
|
||||||
#[serde(rename = "flds")]
|
|
||||||
pub(crate) fields: Vec<NoteFieldSchema11>,
|
|
||||||
#[serde(deserialize_with = "default_on_invalid")]
|
|
||||||
pub(crate) css: String,
|
|
||||||
#[serde(default)]
|
|
||||||
pub(crate) latex_pre: String,
|
|
||||||
#[serde(default)]
|
|
||||||
pub(crate) latex_post: String,
|
|
||||||
#[serde(rename = "latexsvg", default)]
|
|
||||||
pub latex_svg: bool,
|
|
||||||
#[serde(default, deserialize_with = "default_on_invalid")]
|
|
||||||
pub(crate) req: CardRequirements,
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub(crate) other: HashMap<String, Value>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
pub(crate) struct CardRequirements(pub(crate) Vec<CardRequirement>);
|
|
||||||
|
|
||||||
impl Default for CardRequirements {
|
|
||||||
fn default() -> Self {
|
|
||||||
CardRequirements(vec![])
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize_tuple, Deserialize, Debug, Clone)]
|
pub fn id(&self) -> NoteTypeID {
|
||||||
pub(crate) struct CardRequirement {
|
NoteTypeID(self.id)
|
||||||
pub(crate) card_ord: u16,
|
|
||||||
pub(crate) kind: FieldRequirementKind,
|
|
||||||
pub(crate) field_ords: Vec<u16>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
#[serde(rename_all = "lowercase")]
|
|
||||||
pub enum FieldRequirementKind {
|
|
||||||
Any,
|
|
||||||
All,
|
|
||||||
None,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for NoteTypeSchema11 {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
id: NoteTypeID(0),
|
|
||||||
name: String::new(),
|
|
||||||
kind: NoteTypeKind::Standard,
|
|
||||||
mtime: TimestampSecs(0),
|
|
||||||
usn: Usn(0),
|
|
||||||
sort_field_idx: 0,
|
|
||||||
deck_id_for_adding: None,
|
|
||||||
fields: vec![],
|
|
||||||
templates: vec![],
|
|
||||||
css: DEFAULT_CSS.to_owned(),
|
|
||||||
latex_pre: DEFAULT_LATEX_HEADER.to_owned(),
|
|
||||||
latex_post: DEFAULT_LATEX_FOOTER.to_owned(),
|
|
||||||
req: Default::default(),
|
|
||||||
latex_svg: false,
|
|
||||||
other: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl NoteTypeSchema11 {
|
|
||||||
pub fn latex_uses_svg(&self) -> bool {
|
|
||||||
self.latex_svg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<NoteTypeSchema11> for NoteTypeProto {
|
|
||||||
fn from(nt: NoteTypeSchema11) -> Self {
|
|
||||||
NoteTypeProto {
|
|
||||||
id: nt.id.0,
|
|
||||||
name: nt.name,
|
|
||||||
mtime_secs: nt.mtime.0 as u32,
|
|
||||||
usn: nt.usn.0,
|
|
||||||
config: Some(NoteTypeConfig {
|
|
||||||
kind: nt.kind as i32,
|
|
||||||
sort_field_idx: nt.sort_field_idx as u32,
|
|
||||||
css: nt.css,
|
|
||||||
target_deck_id: nt.deck_id_for_adding.unwrap_or(DeckID(0)).0,
|
|
||||||
latex_pre: nt.latex_pre,
|
|
||||||
latex_post: nt.latex_post,
|
|
||||||
latex_svg: nt.latex_svg,
|
|
||||||
reqs: nt.req.0.into_iter().map(Into::into).collect(),
|
|
||||||
other: serde_json::to_vec(&nt.other).unwrap(),
|
|
||||||
}),
|
|
||||||
fields: nt.fields.into_iter().map(Into::into).collect(),
|
|
||||||
templates: nt.templates.into_iter().map(Into::into).collect(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<NoteTypeProto> for NoteTypeSchema11 {
|
|
||||||
fn from(p: NoteTypeProto) -> Self {
|
|
||||||
let c = p.config.unwrap();
|
|
||||||
NoteTypeSchema11 {
|
|
||||||
id: NoteTypeID(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),
|
|
||||||
sort_field_idx: c.sort_field_idx as u16,
|
|
||||||
deck_id_for_adding: if c.target_deck_id == 0 {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(DeckID(c.target_deck_id))
|
|
||||||
},
|
|
||||||
templates: p.templates.into_iter().map(Into::into).collect(),
|
|
||||||
fields: p.fields.into_iter().map(Into::into).collect(),
|
|
||||||
css: c.css,
|
|
||||||
latex_pre: c.latex_pre,
|
|
||||||
latex_post: c.latex_post,
|
|
||||||
latex_svg: c.latex_svg,
|
|
||||||
req: CardRequirements(c.reqs.into_iter().map(Into::into).collect()),
|
|
||||||
other: serde_json::from_slice(&c.other).unwrap_or_default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<CardRequirement> for CardRequirementProto {
|
|
||||||
fn from(r: CardRequirement) -> Self {
|
|
||||||
CardRequirementProto {
|
|
||||||
card_ord: r.card_ord as u32,
|
|
||||||
kind: r.kind as u32,
|
|
||||||
field_ords: r.field_ords.into_iter().map(|n| n as u32).collect(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<CardRequirementProto> for CardRequirement {
|
|
||||||
fn from(p: CardRequirementProto) -> Self {
|
|
||||||
CardRequirement {
|
|
||||||
card_ord: p.card_ord as u16,
|
|
||||||
kind: match p.kind {
|
|
||||||
0 => FieldRequirementKind::Any,
|
|
||||||
1 => FieldRequirementKind::All,
|
|
||||||
_ => FieldRequirementKind::None,
|
|
||||||
},
|
|
||||||
field_ords: p.field_ords.into_iter().map(|n| n as u16).collect(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NoteTypeProto {
|
|
||||||
pub(crate) fn ensure_names_unique(&mut self) {
|
pub(crate) fn ensure_names_unique(&mut self) {
|
||||||
let mut names = HashSet::new();
|
let mut names = HashSet::new();
|
||||||
for t in &mut self.templates {
|
for t in &mut self.templates {
|
||||||
|
|
288
rslib/src/notetype/schema11.rs
Normal file
288
rslib/src/notetype/schema11.rs
Normal file
|
@ -0,0 +1,288 @@
|
||||||
|
// Copyright: Ankitects Pty Ltd and contributors
|
||||||
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
use crate::{
|
||||||
|
decks::DeckID,
|
||||||
|
notetype::{
|
||||||
|
CardRequirement, CardTemplate, CardTemplateConfig, NoteField, NoteFieldConfig, NoteType,
|
||||||
|
NoteTypeConfig,
|
||||||
|
},
|
||||||
|
serde::{default_on_invalid, deserialize_bool_from_anything, deserialize_number_from_string},
|
||||||
|
timestamp::TimestampSecs,
|
||||||
|
types::Usn,
|
||||||
|
};
|
||||||
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
use serde_json::Value;
|
||||||
|
use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||||
|
use serde_tuple::Serialize_tuple;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use super::NoteTypeID;
|
||||||
|
|
||||||
|
#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug, Clone)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum NoteTypeKind {
|
||||||
|
Standard = 0,
|
||||||
|
Cloze = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct NoteTypeSchema11 {
|
||||||
|
#[serde(deserialize_with = "deserialize_number_from_string")]
|
||||||
|
pub(crate) id: NoteTypeID,
|
||||||
|
pub(crate) name: String,
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub(crate) kind: NoteTypeKind,
|
||||||
|
#[serde(rename = "mod")]
|
||||||
|
pub(crate) mtime: TimestampSecs,
|
||||||
|
pub(crate) usn: Usn,
|
||||||
|
pub(crate) sortf: u16,
|
||||||
|
#[serde(deserialize_with = "default_on_invalid")]
|
||||||
|
pub(crate) did: Option<DeckID>,
|
||||||
|
pub(crate) tmpls: Vec<CardTemplateSchema11>,
|
||||||
|
pub(crate) flds: Vec<NoteFieldSchema11>,
|
||||||
|
#[serde(deserialize_with = "default_on_invalid")]
|
||||||
|
pub(crate) css: String,
|
||||||
|
#[serde(default)]
|
||||||
|
pub(crate) latex_pre: String,
|
||||||
|
#[serde(default)]
|
||||||
|
pub(crate) latex_post: String,
|
||||||
|
#[serde(default)]
|
||||||
|
pub latexsvg: bool,
|
||||||
|
#[serde(default, deserialize_with = "default_on_invalid")]
|
||||||
|
pub(crate) req: CardRequirementsSchema11,
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub(crate) other: HashMap<String, Value>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub(crate) struct CardRequirementsSchema11(pub(crate) Vec<CardRequirementSchema11>);
|
||||||
|
|
||||||
|
impl Default for CardRequirementsSchema11 {
|
||||||
|
fn default() -> Self {
|
||||||
|
CardRequirementsSchema11(vec![])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize_tuple, Deserialize, Debug, Clone)]
|
||||||
|
pub(crate) struct CardRequirementSchema11 {
|
||||||
|
pub(crate) card_ord: u16,
|
||||||
|
pub(crate) kind: FieldRequirementKindSchema11,
|
||||||
|
pub(crate) field_ords: Vec<u16>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum FieldRequirementKindSchema11 {
|
||||||
|
Any,
|
||||||
|
All,
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NoteTypeSchema11 {
|
||||||
|
pub fn latex_uses_svg(&self) -> bool {
|
||||||
|
self.latexsvg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<NoteTypeSchema11> for NoteType {
|
||||||
|
fn from(nt: NoteTypeSchema11) -> Self {
|
||||||
|
NoteType {
|
||||||
|
id: nt.id.0,
|
||||||
|
name: nt.name,
|
||||||
|
mtime_secs: nt.mtime.0 as u32,
|
||||||
|
usn: nt.usn.0,
|
||||||
|
config: Some(NoteTypeConfig {
|
||||||
|
kind: nt.kind as i32,
|
||||||
|
sort_field_idx: nt.sortf as u32,
|
||||||
|
css: nt.css,
|
||||||
|
target_deck_id: nt.did.unwrap_or(DeckID(0)).0,
|
||||||
|
latex_pre: nt.latex_pre,
|
||||||
|
latex_post: nt.latex_post,
|
||||||
|
latex_svg: nt.latexsvg,
|
||||||
|
reqs: nt.req.0.into_iter().map(Into::into).collect(),
|
||||||
|
other: serde_json::to_vec(&nt.other).unwrap(),
|
||||||
|
}),
|
||||||
|
fields: nt.flds.into_iter().map(Into::into).collect(),
|
||||||
|
templates: nt.tmpls.into_iter().map(Into::into).collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<NoteType> for NoteTypeSchema11 {
|
||||||
|
fn from(p: NoteType) -> Self {
|
||||||
|
let c = p.config.unwrap();
|
||||||
|
NoteTypeSchema11 {
|
||||||
|
id: NoteTypeID(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),
|
||||||
|
sortf: c.sort_field_idx as u16,
|
||||||
|
did: if c.target_deck_id == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(DeckID(c.target_deck_id))
|
||||||
|
},
|
||||||
|
tmpls: p.templates.into_iter().map(Into::into).collect(),
|
||||||
|
flds: p.fields.into_iter().map(Into::into).collect(),
|
||||||
|
css: c.css,
|
||||||
|
latex_pre: c.latex_pre,
|
||||||
|
latex_post: c.latex_post,
|
||||||
|
latexsvg: c.latex_svg,
|
||||||
|
req: CardRequirementsSchema11(c.reqs.into_iter().map(Into::into).collect()),
|
||||||
|
other: serde_json::from_slice(&c.other).unwrap_or_default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CardRequirementSchema11> for CardRequirement {
|
||||||
|
fn from(r: CardRequirementSchema11) -> Self {
|
||||||
|
CardRequirement {
|
||||||
|
card_ord: r.card_ord as u32,
|
||||||
|
kind: r.kind as u32,
|
||||||
|
field_ords: r.field_ords.into_iter().map(|n| n as u32).collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CardRequirement> for CardRequirementSchema11 {
|
||||||
|
fn from(p: CardRequirement) -> Self {
|
||||||
|
CardRequirementSchema11 {
|
||||||
|
card_ord: p.card_ord as u16,
|
||||||
|
kind: match p.kind {
|
||||||
|
0 => FieldRequirementKindSchema11::Any,
|
||||||
|
1 => FieldRequirementKindSchema11::All,
|
||||||
|
_ => FieldRequirementKindSchema11::None,
|
||||||
|
},
|
||||||
|
field_ords: p.field_ords.into_iter().map(|n| n as u16).collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct NoteFieldSchema11 {
|
||||||
|
pub(crate) name: String,
|
||||||
|
pub(crate) ord: u16,
|
||||||
|
#[serde(deserialize_with = "deserialize_bool_from_anything")]
|
||||||
|
pub(crate) sticky: bool,
|
||||||
|
#[serde(deserialize_with = "deserialize_bool_from_anything")]
|
||||||
|
pub(crate) rtl: bool,
|
||||||
|
pub(crate) font: String,
|
||||||
|
pub(crate) size: u16,
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub(crate) other: HashMap<String, Value>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for NoteFieldSchema11 {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
name: String::new(),
|
||||||
|
ord: 0,
|
||||||
|
sticky: false,
|
||||||
|
rtl: false,
|
||||||
|
font: "Arial".to_string(),
|
||||||
|
size: 20,
|
||||||
|
other: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<NoteFieldSchema11> for NoteField {
|
||||||
|
fn from(f: NoteFieldSchema11) -> Self {
|
||||||
|
NoteField {
|
||||||
|
ord: f.ord as u32,
|
||||||
|
name: f.name,
|
||||||
|
config: Some(NoteFieldConfig {
|
||||||
|
sticky: f.sticky,
|
||||||
|
rtl: f.rtl,
|
||||||
|
font_name: f.font,
|
||||||
|
font_size: f.size as u32,
|
||||||
|
other: serde_json::to_vec(&f.other).unwrap(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<NoteField> for NoteFieldSchema11 {
|
||||||
|
fn from(p: NoteField) -> Self {
|
||||||
|
let conf = p.config.unwrap();
|
||||||
|
NoteFieldSchema11 {
|
||||||
|
name: p.name,
|
||||||
|
ord: p.ord as u16,
|
||||||
|
sticky: conf.sticky,
|
||||||
|
rtl: conf.rtl,
|
||||||
|
font: conf.font_name,
|
||||||
|
size: conf.font_size as u16,
|
||||||
|
other: serde_json::from_slice(&conf.other).unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
|
||||||
|
pub struct CardTemplateSchema11 {
|
||||||
|
pub(crate) name: String,
|
||||||
|
pub(crate) ord: u16,
|
||||||
|
pub(crate) qfmt: String,
|
||||||
|
#[serde(default)]
|
||||||
|
pub(crate) afmt: String,
|
||||||
|
#[serde(default)]
|
||||||
|
pub(crate) bqfmt: String,
|
||||||
|
#[serde(default)]
|
||||||
|
pub(crate) bafmt: String,
|
||||||
|
#[serde(deserialize_with = "default_on_invalid")]
|
||||||
|
pub(crate) did: Option<DeckID>,
|
||||||
|
#[serde(default, deserialize_with = "default_on_invalid")]
|
||||||
|
pub(crate) bfont: String,
|
||||||
|
#[serde(default, deserialize_with = "default_on_invalid")]
|
||||||
|
pub(crate) bsize: u8,
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub(crate) other: HashMap<String, Value>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CardTemplateSchema11> for CardTemplate {
|
||||||
|
fn from(t: CardTemplateSchema11) -> Self {
|
||||||
|
CardTemplate {
|
||||||
|
ord: t.ord as u32,
|
||||||
|
name: t.name,
|
||||||
|
mtime_secs: 0,
|
||||||
|
usn: 0,
|
||||||
|
config: Some(CardTemplateConfig {
|
||||||
|
q_format: t.qfmt,
|
||||||
|
a_format: t.afmt,
|
||||||
|
q_format_browser: t.bqfmt,
|
||||||
|
a_format_browser: t.bafmt,
|
||||||
|
target_deck_id: t.did.unwrap_or(DeckID(0)).0,
|
||||||
|
browser_font_name: t.bfont,
|
||||||
|
browser_font_size: t.bsize as u32,
|
||||||
|
other: serde_json::to_vec(&t.other).unwrap(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CardTemplate> for CardTemplateSchema11 {
|
||||||
|
fn from(p: CardTemplate) -> Self {
|
||||||
|
let conf = p.config.unwrap();
|
||||||
|
CardTemplateSchema11 {
|
||||||
|
name: p.name,
|
||||||
|
ord: p.ord as u16,
|
||||||
|
qfmt: conf.q_format,
|
||||||
|
afmt: conf.a_format,
|
||||||
|
bqfmt: conf.q_format_browser,
|
||||||
|
bafmt: conf.a_format_browser,
|
||||||
|
did: if conf.target_deck_id > 0 {
|
||||||
|
Some(DeckID(conf.target_deck_id))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
bfont: conf.browser_font_name,
|
||||||
|
bsize: conf.browser_font_size as u8,
|
||||||
|
other: serde_json::from_slice(&conf.other).unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,75 +0,0 @@
|
||||||
// Copyright: Ankitects Pty Ltd and contributors
|
|
||||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
backend_proto::{CardTemplate as CardTemplateProto, CardTemplateConfig},
|
|
||||||
decks::DeckID,
|
|
||||||
serde::default_on_invalid,
|
|
||||||
};
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
|
||||||
use serde_json::Value;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
|
|
||||||
pub struct CardTemplateSchema11 {
|
|
||||||
pub(crate) name: String,
|
|
||||||
pub(crate) ord: u16,
|
|
||||||
pub(crate) qfmt: String,
|
|
||||||
#[serde(default)]
|
|
||||||
pub(crate) afmt: String,
|
|
||||||
#[serde(default)]
|
|
||||||
pub(crate) bqfmt: String,
|
|
||||||
#[serde(default)]
|
|
||||||
pub(crate) bafmt: String,
|
|
||||||
#[serde(rename = "did", deserialize_with = "default_on_invalid")]
|
|
||||||
pub(crate) override_did: Option<DeckID>,
|
|
||||||
#[serde(default, deserialize_with = "default_on_invalid")]
|
|
||||||
pub(crate) bfont: String,
|
|
||||||
#[serde(default, deserialize_with = "default_on_invalid")]
|
|
||||||
pub(crate) bsize: u8,
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub(crate) other: HashMap<String, Value>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<CardTemplateSchema11> for CardTemplateProto {
|
|
||||||
fn from(t: CardTemplateSchema11) -> Self {
|
|
||||||
CardTemplateProto {
|
|
||||||
ord: t.ord as u32,
|
|
||||||
name: t.name,
|
|
||||||
mtime_secs: 0,
|
|
||||||
usn: 0,
|
|
||||||
config: Some(CardTemplateConfig {
|
|
||||||
q_format: t.qfmt,
|
|
||||||
a_format: t.afmt,
|
|
||||||
q_format_browser: t.bqfmt,
|
|
||||||
a_format_browser: t.bafmt,
|
|
||||||
target_deck_id: t.override_did.unwrap_or(DeckID(0)).0,
|
|
||||||
browser_font_name: t.bfont,
|
|
||||||
browser_font_size: t.bsize as u32,
|
|
||||||
other: serde_json::to_vec(&t.other).unwrap(),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<CardTemplateProto> for CardTemplateSchema11 {
|
|
||||||
fn from(p: CardTemplateProto) -> Self {
|
|
||||||
let conf = p.config.unwrap();
|
|
||||||
CardTemplateSchema11 {
|
|
||||||
name: p.name,
|
|
||||||
ord: p.ord as u16,
|
|
||||||
qfmt: conf.q_format,
|
|
||||||
afmt: conf.a_format,
|
|
||||||
bqfmt: conf.q_format_browser,
|
|
||||||
bafmt: conf.a_format_browser,
|
|
||||||
override_did: if conf.target_deck_id > 0 {
|
|
||||||
Some(DeckID(conf.target_deck_id))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
},
|
|
||||||
bfont: conf.browser_font_name,
|
|
||||||
bsize: conf.browser_font_size as u8,
|
|
||||||
other: serde_json::from_slice(&conf.other).unwrap(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -128,7 +128,7 @@ fn prepare_sort(req: &mut Collection, kind: &SortKind) -> Result<()> {
|
||||||
.prepare("insert into sort_order (k1,k2,v) values (?,?,?)")?;
|
.prepare("insert into sort_order (k1,k2,v) values (?,?,?)")?;
|
||||||
|
|
||||||
for (ntid, nt) in req.storage.get_all_notetypes_as_schema11()? {
|
for (ntid, nt) in req.storage.get_all_notetypes_as_schema11()? {
|
||||||
for tmpl in nt.templates {
|
for tmpl in nt.tmpls {
|
||||||
stmt.execute(params![ntid, tmpl.ord, tmpl.name])?;
|
stmt.execute(params![ntid, tmpl.ord, tmpl.name])?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,7 +270,7 @@ impl SqlWriter<'_> {
|
||||||
let note_types = self.col.storage.get_all_notetypes_as_schema11()?;
|
let note_types = self.col.storage.get_all_notetypes_as_schema11()?;
|
||||||
let mut id_ords = vec![];
|
let mut id_ords = vec![];
|
||||||
for nt in note_types.values() {
|
for nt in note_types.values() {
|
||||||
for tmpl in &nt.templates {
|
for tmpl in &nt.tmpls {
|
||||||
if matches_wildcard(&tmpl.name, name) {
|
if matches_wildcard(&tmpl.name, name) {
|
||||||
id_ords.push((nt.id, tmpl.ord));
|
id_ords.push((nt.id, tmpl.ord));
|
||||||
}
|
}
|
||||||
|
@ -315,7 +315,7 @@ impl SqlWriter<'_> {
|
||||||
|
|
||||||
let mut field_map = vec![];
|
let mut field_map = vec![];
|
||||||
for nt in note_types.values() {
|
for nt in note_types.values() {
|
||||||
for field in &nt.fields {
|
for field in &nt.flds {
|
||||||
if matches_wildcard(&field.name, field_name) {
|
if matches_wildcard(&field.name, field_name) {
|
||||||
field_map.push((nt.id, field.ord));
|
field_map.push((nt.id, field.ord));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
use super::SqliteStorage;
|
use super::SqliteStorage;
|
||||||
use crate::{
|
use crate::{
|
||||||
backend_proto::{
|
backend_proto::{
|
||||||
CardTemplate as CardTemplateProto, CardTemplateConfig, NoteField as NoteFieldProto,
|
CardTemplate, CardTemplateConfig, NoteField, NoteFieldConfig, NoteType, NoteTypeConfig,
|
||||||
NoteFieldConfig, NoteType as NoteTypeProto, NoteTypeConfig,
|
|
||||||
},
|
},
|
||||||
err::{AnkiError, DBErrorKind, Result},
|
err::{AnkiError, DBErrorKind, Result},
|
||||||
notetype::{NoteTypeID, NoteTypeSchema11},
|
notetype::{NoteTypeID, NoteTypeSchema11},
|
||||||
|
@ -16,12 +15,12 @@ use std::collections::{HashMap, HashSet};
|
||||||
use unicase::UniCase;
|
use unicase::UniCase;
|
||||||
|
|
||||||
impl SqliteStorage {
|
impl SqliteStorage {
|
||||||
fn get_notetype_core(&self, ntid: NoteTypeID) -> Result<Option<NoteTypeProto>> {
|
fn get_notetype_core(&self, ntid: NoteTypeID) -> Result<Option<NoteType>> {
|
||||||
self.db
|
self.db
|
||||||
.prepare_cached(include_str!("get_notetype.sql"))?
|
.prepare_cached(include_str!("get_notetype.sql"))?
|
||||||
.query_and_then(&[ntid], |row| {
|
.query_and_then(&[ntid], |row| {
|
||||||
let config = NoteTypeConfig::decode(row.get_raw(3).as_blob()?)?;
|
let config = NoteTypeConfig::decode(row.get_raw(3).as_blob()?)?;
|
||||||
Ok(NoteTypeProto {
|
Ok(NoteType {
|
||||||
id: ntid.0,
|
id: ntid.0,
|
||||||
name: row.get(0)?,
|
name: row.get(0)?,
|
||||||
mtime_secs: row.get(1)?,
|
mtime_secs: row.get(1)?,
|
||||||
|
@ -35,12 +34,12 @@ impl SqliteStorage {
|
||||||
.transpose()
|
.transpose()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_notetype_fields(&self, ntid: NoteTypeID) -> Result<Vec<NoteFieldProto>> {
|
fn get_notetype_fields(&self, ntid: NoteTypeID) -> Result<Vec<NoteField>> {
|
||||||
self.db
|
self.db
|
||||||
.prepare_cached(include_str!("get_fields.sql"))?
|
.prepare_cached(include_str!("get_fields.sql"))?
|
||||||
.query_and_then(&[ntid], |row| {
|
.query_and_then(&[ntid], |row| {
|
||||||
let config = NoteFieldConfig::decode(row.get_raw(2).as_blob()?)?;
|
let config = NoteFieldConfig::decode(row.get_raw(2).as_blob()?)?;
|
||||||
Ok(NoteFieldProto {
|
Ok(NoteField {
|
||||||
ord: row.get(0)?,
|
ord: row.get(0)?,
|
||||||
name: row.get(1)?,
|
name: row.get(1)?,
|
||||||
config: Some(config),
|
config: Some(config),
|
||||||
|
@ -49,12 +48,12 @@ impl SqliteStorage {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_notetype_templates(&self, ntid: NoteTypeID) -> Result<Vec<CardTemplateProto>> {
|
fn get_notetype_templates(&self, ntid: NoteTypeID) -> Result<Vec<CardTemplate>> {
|
||||||
self.db
|
self.db
|
||||||
.prepare_cached(include_str!("get_templates.sql"))?
|
.prepare_cached(include_str!("get_templates.sql"))?
|
||||||
.query_and_then(&[ntid], |row| {
|
.query_and_then(&[ntid], |row| {
|
||||||
let config = CardTemplateConfig::decode(row.get_raw(4).as_blob()?)?;
|
let config = CardTemplateConfig::decode(row.get_raw(4).as_blob()?)?;
|
||||||
Ok(CardTemplateProto {
|
Ok(CardTemplate {
|
||||||
ord: row.get(0)?,
|
ord: row.get(0)?,
|
||||||
name: row.get(1)?,
|
name: row.get(1)?,
|
||||||
mtime_secs: row.get(2)?,
|
mtime_secs: row.get(2)?,
|
||||||
|
@ -65,7 +64,7 @@ impl SqliteStorage {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_full_notetype(&self, ntid: NoteTypeID) -> Result<Option<NoteTypeProto>> {
|
fn get_full_notetype(&self, ntid: NoteTypeID) -> Result<Option<NoteType>> {
|
||||||
match self.get_notetype_core(ntid)? {
|
match self.get_notetype_core(ntid)? {
|
||||||
Some(mut nt) => {
|
Some(mut nt) => {
|
||||||
nt.fields = self.get_notetype_fields(ntid)?;
|
nt.fields = self.get_notetype_fields(ntid)?;
|
||||||
|
@ -94,7 +93,7 @@ impl SqliteStorage {
|
||||||
Ok(nts)
|
Ok(nts)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_notetype_fields(&self, ntid: NoteTypeID, fields: &[NoteFieldProto]) -> Result<()> {
|
fn update_notetype_fields(&self, ntid: NoteTypeID, fields: &[NoteField]) -> Result<()> {
|
||||||
self.db
|
self.db
|
||||||
.prepare_cached("delete from fields where ntid=?")?
|
.prepare_cached("delete from fields where ntid=?")?
|
||||||
.execute(&[ntid])?;
|
.execute(&[ntid])?;
|
||||||
|
@ -111,7 +110,7 @@ impl SqliteStorage {
|
||||||
fn update_notetype_templates(
|
fn update_notetype_templates(
|
||||||
&self,
|
&self,
|
||||||
ntid: NoteTypeID,
|
ntid: NoteTypeID,
|
||||||
templates: &[CardTemplateProto],
|
templates: &[CardTemplate],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.db
|
self.db
|
||||||
.prepare_cached("delete from templates where ntid=?")?
|
.prepare_cached("delete from templates where ntid=?")?
|
||||||
|
@ -139,7 +138,7 @@ impl SqliteStorage {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_notetype_meta(&self, nt: &NoteTypeProto) -> Result<()> {
|
fn update_notetype_meta(&self, nt: &NoteType) -> Result<()> {
|
||||||
assert!(nt.id != 0);
|
assert!(nt.id != 0);
|
||||||
let mut stmt = self
|
let mut stmt = self
|
||||||
.db
|
.db
|
||||||
|
@ -157,7 +156,7 @@ impl SqliteStorage {
|
||||||
let nts = self.get_schema11_notetypes()?;
|
let nts = self.get_schema11_notetypes()?;
|
||||||
let mut names = HashSet::new();
|
let mut names = HashSet::new();
|
||||||
for (ntid, nt) in nts {
|
for (ntid, nt) in nts {
|
||||||
let mut nt = NoteTypeProto::from(nt);
|
let mut nt = NoteType::from(nt);
|
||||||
nt.normalize_names();
|
nt.normalize_names();
|
||||||
nt.ensure_names_unique();
|
nt.ensure_names_unique();
|
||||||
loop {
|
loop {
|
||||||
|
|
Loading…
Reference in a new issue