mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
fetch stock notetypes from backend
This commit is contained in:
parent
f650e5557f
commit
2ac33500eb
6 changed files with 59 additions and 123 deletions
|
@ -71,7 +71,7 @@ message BackendInput {
|
|||
AddOrUpdateNotetypeIn add_or_update_notetype = 57;
|
||||
Empty get_all_decks = 58;
|
||||
Empty check_database = 59;
|
||||
Empty all_stock_notetypes = 60;
|
||||
StockNoteType get_stock_notetype_legacy = 60;
|
||||
int64 get_notetype_legacy = 61;
|
||||
Empty get_notetype_names = 62;
|
||||
Empty get_notetype_names_and_counts = 63;
|
||||
|
@ -114,7 +114,6 @@ message BackendOutput {
|
|||
string studied_today = 32;
|
||||
string congrats_learn_msg = 33;
|
||||
Empty abort_media_sync = 46;
|
||||
AllStockNotetypesOut all_stock_notetypes = 60;
|
||||
ClozeNumbersInNoteOut cloze_numbers_in_note = 87;
|
||||
|
||||
// fallible commands
|
||||
|
@ -177,6 +176,7 @@ message BackendOutput {
|
|||
Preferences get_preferences = 84;
|
||||
Empty set_preferences = 85;
|
||||
RenderCardOut render_existing_card = 86;
|
||||
bytes get_stock_notetype_legacy = 60;
|
||||
|
||||
BackendError error = 2047;
|
||||
}
|
||||
|
@ -587,10 +587,6 @@ enum StockNoteType {
|
|||
StockNoteTypeCloze = 4;
|
||||
}
|
||||
|
||||
message AllStockNotetypesOut {
|
||||
repeated NoteType notetypes = 1;
|
||||
}
|
||||
|
||||
message NoteTypeNames {
|
||||
repeated NoteTypeNameID entries = 1;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ BackendNote = pb.Note
|
|||
TagUsnTuple = pb.TagUsnTuple
|
||||
NoteType = pb.NoteType
|
||||
DeckTreeNode = pb.DeckTreeNode
|
||||
StockNoteType = pb.StockNoteType
|
||||
|
||||
try:
|
||||
import orjson
|
||||
|
@ -602,12 +603,11 @@ class RustBackend:
|
|||
).get_all_decks
|
||||
return orjson.loads(jstr)
|
||||
|
||||
def all_stock_notetypes(self) -> List[NoteType]:
|
||||
return list(
|
||||
self._run_command(
|
||||
pb.BackendInput(all_stock_notetypes=pb.Empty())
|
||||
).all_stock_notetypes.notetypes
|
||||
)
|
||||
def get_stock_notetype_legacy(self, kind: StockNoteType) -> Dict[str, Any]:
|
||||
bytes = self._run_command(
|
||||
pb.BackendInput(get_stock_notetype_legacy=kind)
|
||||
).get_stock_notetype_legacy
|
||||
return orjson.loads(bytes)
|
||||
|
||||
def get_notetype_names_and_ids(self) -> List[pb.NoteTypeNameID]:
|
||||
return list(
|
||||
|
|
|
@ -1,125 +1,62 @@
|
|||
# Copyright: Ankitects Pty Ltd and contributors
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
from typing import Any, Callable, List, Optional, Tuple, Union
|
||||
from typing import Callable, List, Tuple
|
||||
|
||||
from anki.collection import _Collection
|
||||
from anki.consts import MODEL_CLOZE
|
||||
from anki.lang import _
|
||||
from anki.models import NoteType
|
||||
from anki.rsbackend import StockNoteType
|
||||
|
||||
models: List[Tuple[Union[Callable[[], str], str], Callable[[Any], NoteType]]] = []
|
||||
|
||||
# Basic
|
||||
##########################################################################
|
||||
# add-on authors can add ("note type name", function_like_addBasicModel)
|
||||
# to this list to have it shown in the add/clone note type screen
|
||||
models: List[Tuple] = []
|
||||
|
||||
|
||||
def _newBasicModel(col: _Collection, name: Optional[str] = None) -> NoteType:
|
||||
mm = col.models
|
||||
m = mm.new(name or _("Basic"))
|
||||
fm = mm.newField(_("Front"))
|
||||
mm.addField(m, fm)
|
||||
fm = mm.newField(_("Back"))
|
||||
mm.addField(m, fm)
|
||||
t = mm.newTemplate(_("Card 1"))
|
||||
t["qfmt"] = "{{" + _("Front") + "}}"
|
||||
t["afmt"] = "{{FrontSide}}\n\n<hr id=answer>\n\n" + "{{" + _("Back") + "}}"
|
||||
mm.addTemplate(m, t)
|
||||
def add_stock_notetype(col: _Collection, kind: StockNoteType) -> NoteType:
|
||||
m = col.backend.get_stock_notetype_legacy(kind)
|
||||
col.models.add(m)
|
||||
return m
|
||||
|
||||
|
||||
def addBasicModel(col: _Collection) -> NoteType:
|
||||
m = _newBasicModel(col)
|
||||
col.models.add(m)
|
||||
return m
|
||||
|
||||
|
||||
models.append((lambda: _("Basic"), addBasicModel))
|
||||
|
||||
# Basic w/ typing
|
||||
##########################################################################
|
||||
return add_stock_notetype(col, StockNoteType.StockNoteTypeBasic)
|
||||
|
||||
|
||||
def addBasicTypingModel(col: _Collection) -> NoteType:
|
||||
mm = col.models
|
||||
m = _newBasicModel(col, _("Basic (type in the answer)"))
|
||||
t = m["tmpls"][0]
|
||||
t["qfmt"] = "{{" + _("Front") + "}}\n\n{{type:" + _("Back") + "}}"
|
||||
t["afmt"] = "{{" + _("Front") + "}}\n\n<hr id=answer>\n\n{{type:" + _("Back") + "}}"
|
||||
mm.add(m)
|
||||
return m
|
||||
|
||||
|
||||
models.append((lambda: _("Basic (type in the answer)"), addBasicTypingModel))
|
||||
|
||||
# Forward & Reverse
|
||||
##########################################################################
|
||||
|
||||
|
||||
def _newForwardReverse(col: _Collection, name: Optional[str] = None) -> NoteType:
|
||||
mm = col.models
|
||||
m = _newBasicModel(col, name or _("Basic (and reversed card)"))
|
||||
t = mm.newTemplate(_("Card 2"))
|
||||
t["qfmt"] = "{{" + _("Back") + "}}"
|
||||
t["afmt"] = "{{FrontSide}}\n\n<hr id=answer>\n\n" + "{{" + _("Front") + "}}"
|
||||
mm.addTemplate(m, t)
|
||||
return m
|
||||
return add_stock_notetype(col, StockNoteType.StockNoteTypeBasicTyping)
|
||||
|
||||
|
||||
def addForwardReverse(col: _Collection) -> NoteType:
|
||||
m = _newForwardReverse(col)
|
||||
col.models.add(m)
|
||||
return m
|
||||
|
||||
|
||||
models.append((lambda: _("Basic (and reversed card)"), addForwardReverse))
|
||||
|
||||
# Forward & Optional Reverse
|
||||
##########################################################################
|
||||
return add_stock_notetype(col, StockNoteType.StockNoteTypeBasicAndReversed)
|
||||
|
||||
|
||||
def addForwardOptionalReverse(col: _Collection) -> NoteType:
|
||||
mm = col.models
|
||||
m = _newForwardReverse(col, _("Basic (optional reversed card)"))
|
||||
av = _("Add Reverse")
|
||||
fm = mm.newField(av)
|
||||
mm.addField(m, fm)
|
||||
t = m["tmpls"][1]
|
||||
t["qfmt"] = "{{#%s}}%s{{/%s}}" % (av, t["qfmt"], av)
|
||||
mm.add(m)
|
||||
return m
|
||||
|
||||
|
||||
models.append((lambda: _("Basic (optional reversed card)"), addForwardOptionalReverse))
|
||||
|
||||
# Cloze
|
||||
##########################################################################
|
||||
return add_stock_notetype(col, StockNoteType.StockNoteTypeBasicOptionalReversed)
|
||||
|
||||
|
||||
def addClozeModel(col: _Collection) -> NoteType:
|
||||
mm = col.models
|
||||
m = mm.new(_("Cloze"))
|
||||
m["type"] = MODEL_CLOZE
|
||||
txt = _("Text")
|
||||
fm = mm.newField(txt)
|
||||
mm.addField(m, fm)
|
||||
t = mm.newTemplate(_("Cloze"))
|
||||
fmt = "{{cloze:%s}}" % txt
|
||||
m[
|
||||
"css"
|
||||
] += """
|
||||
.cloze {
|
||||
font-weight: bold;
|
||||
color: blue;
|
||||
}
|
||||
.nightMode .cloze {
|
||||
color: lightblue;
|
||||
}"""
|
||||
t["qfmt"] = fmt
|
||||
t["afmt"] = fmt
|
||||
mm.addTemplate(m, t)
|
||||
mm.add(m)
|
||||
return m
|
||||
return add_stock_notetype(col, StockNoteType.StockNoteTypeCloze)
|
||||
|
||||
|
||||
models.append((lambda: _("Cloze"), addClozeModel))
|
||||
def get_stock_notetypes(
|
||||
col: _Collection,
|
||||
) -> List[Tuple[str, Callable[[_Collection], NoteType]]]:
|
||||
out: List[Tuple[str, Callable[[_Collection], NoteType]]] = []
|
||||
# add standard
|
||||
for (kind, func) in [
|
||||
(StockNoteType.StockNoteTypeBasic, addBasicModel),
|
||||
(StockNoteType.StockNoteTypeBasicTyping, addBasicTypingModel),
|
||||
(StockNoteType.StockNoteTypeBasicAndReversed, addForwardReverse),
|
||||
(StockNoteType.StockNoteTypeBasicOptionalReversed, addForwardOptionalReverse),
|
||||
(StockNoteType.StockNoteTypeCloze, addClozeModel),
|
||||
]:
|
||||
m = col.backend.get_stock_notetype_legacy(kind)
|
||||
out.append((m["name"], func))
|
||||
# add extras from add-ons
|
||||
for (name_or_func, func) in models:
|
||||
if not isinstance(name_or_func, str):
|
||||
name = name_or_func()
|
||||
else:
|
||||
name = name_or_func
|
||||
out.append((name, func))
|
||||
return out
|
||||
|
|
|
@ -7,7 +7,7 @@ from anki import Collection as aopen
|
|||
from anki.dbproxy import emulate_named_args
|
||||
from anki.lang import without_unicode_isolation
|
||||
from anki.rsbackend import TR
|
||||
from anki.stdmodels import addBasicModel, models
|
||||
from anki.stdmodels import addBasicModel, get_stock_notetypes
|
||||
from anki.utils import isWin
|
||||
from tests.shared import assertException, getEmptyCol
|
||||
|
||||
|
@ -119,10 +119,10 @@ def test_addDelTags():
|
|||
|
||||
def test_timestamps():
|
||||
deck = getEmptyCol()
|
||||
assert len(deck.models.all_names_and_ids()) == len(models)
|
||||
assert len(deck.models.all_names_and_ids()) == len(get_stock_notetypes(deck))
|
||||
for i in range(100):
|
||||
addBasicModel(deck)
|
||||
assert len(deck.models.all_names_and_ids()) == 100 + len(models)
|
||||
assert len(deck.models.all_names_and_ids()) == 100 + len(get_stock_notetypes(deck))
|
||||
|
||||
|
||||
def test_furigana():
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# Copyright: Ankitects Pty Ltd and contributors
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
import collections
|
||||
from operator import itemgetter
|
||||
from typing import List, Optional
|
||||
|
||||
|
@ -196,9 +195,7 @@ class AddModel(QDialog):
|
|||
self.dialog.setupUi(self)
|
||||
# standard models
|
||||
self.models = []
|
||||
for (name, func) in stdmodels.models:
|
||||
if isinstance(name, collections.Callable): # type: ignore
|
||||
name = name() # type: ignore
|
||||
for (name, func) in stdmodels.get_stock_notetypes(self.col):
|
||||
item = QListWidgetItem(_("Add: %s") % name)
|
||||
self.dialog.models.addItem(item)
|
||||
self.models.append((True, func))
|
||||
|
|
|
@ -308,12 +308,9 @@ impl Backend {
|
|||
OValue::GetChangedNotetypes(self.get_changed_notetypes()?)
|
||||
}
|
||||
Value::GetAllDecks(_) => OValue::GetAllDecks(self.get_all_decks()?),
|
||||
Value::AllStockNotetypes(_) => OValue::AllStockNotetypes(pb::AllStockNotetypesOut {
|
||||
notetypes: all_stock_notetypes(&self.i18n)
|
||||
.into_iter()
|
||||
.map(Into::into)
|
||||
.collect(),
|
||||
}),
|
||||
Value::GetStockNotetypeLegacy(kind) => {
|
||||
OValue::GetStockNotetypeLegacy(self.get_stock_notetype_legacy(kind)?)
|
||||
}
|
||||
Value::GetNotetypeLegacy(id) => {
|
||||
OValue::GetNotetypeLegacy(self.get_notetype_legacy(id)?)
|
||||
}
|
||||
|
@ -1151,6 +1148,15 @@ impl Backend {
|
|||
numbers: set.into_iter().map(|n| n as u32).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_stock_notetype_legacy(&self, kind: i32) -> Result<Vec<u8>> {
|
||||
// fixme: use individual functions instead of full vec
|
||||
let mut all = all_stock_notetypes(&self.i18n);
|
||||
let idx = (kind as usize).min(all.len() - 1);
|
||||
let nt = all.swap_remove(idx);
|
||||
let schema11: NoteTypeSchema11 = nt.into();
|
||||
serde_json::to_vec(&schema11).map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
fn to_nids(ids: Vec<i64>) -> Vec<NoteID> {
|
||||
|
|
Loading…
Reference in a new issue