switch NoteType to Notetype
When used as a variable, we were typically calling it a 'notetype', not a 'note type'.
This commit is contained in:
parent
716b474314
commit
cfac40febc
@ -42,7 +42,7 @@ from anki.decks import DeckId, DeckManager
|
|||||||
from anki.errors import AnkiError, DBError
|
from anki.errors import AnkiError, DBError
|
||||||
from anki.lang import FormatTimeSpan
|
from anki.lang import FormatTimeSpan
|
||||||
from anki.media import MediaManager, media_paths_from_col_path
|
from anki.media import MediaManager, media_paths_from_col_path
|
||||||
from anki.models import ModelManager, NotetypeDict, NoteTypeId
|
from anki.models import ModelManager, NotetypeDict, NotetypeId
|
||||||
from anki.notes import Note, NoteId
|
from anki.notes import Note, NoteId
|
||||||
from anki.scheduler.v1 import Scheduler as V1Scheduler
|
from anki.scheduler.v1 import Scheduler as V1Scheduler
|
||||||
from anki.scheduler.v2 import Scheduler as V2Scheduler
|
from anki.scheduler.v2 import Scheduler as V2Scheduler
|
||||||
@ -404,7 +404,7 @@ class Collection:
|
|||||||
home_deck_of_current_review_card=home_deck,
|
home_deck_of_current_review_card=home_deck,
|
||||||
)
|
)
|
||||||
|
|
||||||
def default_deck_for_notetype(self, notetype_id: NoteTypeId) -> Optional[DeckId]:
|
def default_deck_for_notetype(self, notetype_id: NotetypeId) -> Optional[DeckId]:
|
||||||
"""If 'change deck depending on notetype' is enabled in the preferences,
|
"""If 'change deck depending on notetype' is enabled in the preferences,
|
||||||
return the last deck used with the provided notetype, if any.."""
|
return the last deck used with the provided notetype, if any.."""
|
||||||
if self.get_config_bool(Config.Bool.ADDING_DEFAULTS_TO_CURRENT_DECK):
|
if self.get_config_bool(Config.Bool.ADDING_DEFAULTS_TO_CURRENT_DECK):
|
||||||
@ -576,7 +576,7 @@ class Collection:
|
|||||||
dupes = []
|
dupes = []
|
||||||
fields: Dict[int, int] = {}
|
fields: Dict[int, int] = {}
|
||||||
|
|
||||||
def ordForMid(mid: NoteTypeId) -> int:
|
def ordForMid(mid: NotetypeId) -> int:
|
||||||
if mid not in fields:
|
if mid not in fields:
|
||||||
model = self.models.get(mid)
|
model = self.models.get(mid)
|
||||||
for c, f in enumerate(model["flds"]):
|
for c, f in enumerate(model["flds"]):
|
||||||
|
@ -10,7 +10,7 @@ from anki.collection import Collection
|
|||||||
from anki.consts import *
|
from anki.consts import *
|
||||||
from anki.decks import DeckId, DeckManager
|
from anki.decks import DeckId, DeckManager
|
||||||
from anki.importing.base import Importer
|
from anki.importing.base import Importer
|
||||||
from anki.models import NoteTypeId
|
from anki.models import NotetypeId
|
||||||
from anki.notes import NoteId
|
from anki.notes import NoteId
|
||||||
from anki.utils import intTime, joinFields, splitFields, stripHTMLMedia
|
from anki.utils import intTime, joinFields, splitFields, stripHTMLMedia
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ class Anki2Importer(Importer):
|
|||||||
|
|
||||||
def _importNotes(self) -> None:
|
def _importNotes(self) -> None:
|
||||||
# build guid -> (id,mod,mid) hash & map of existing note ids
|
# build guid -> (id,mod,mid) hash & map of existing note ids
|
||||||
self._notes: Dict[str, Tuple[NoteId, int, NoteTypeId]] = {}
|
self._notes: Dict[str, Tuple[NoteId, int, NotetypeId]] = {}
|
||||||
existing = {}
|
existing = {}
|
||||||
for id, guid, mod, mid in self.dst.db.execute(
|
for id, guid, mod, mid in self.dst.db.execute(
|
||||||
"select id, guid, mod, mid from notes"
|
"select id, guid, mod, mid from notes"
|
||||||
@ -212,9 +212,9 @@ class Anki2Importer(Importer):
|
|||||||
|
|
||||||
def _prepareModels(self) -> None:
|
def _prepareModels(self) -> None:
|
||||||
"Prepare index of schema hashes."
|
"Prepare index of schema hashes."
|
||||||
self._modelMap: Dict[NoteTypeId, NoteTypeId] = {}
|
self._modelMap: Dict[NotetypeId, NotetypeId] = {}
|
||||||
|
|
||||||
def _mid(self, srcMid: NoteTypeId) -> Any:
|
def _mid(self, srcMid: NotetypeId) -> Any:
|
||||||
"Return local id for remote MID."
|
"Return local id for remote MID."
|
||||||
# already processed this mid?
|
# already processed this mid?
|
||||||
if srcMid in self._modelMap:
|
if srcMid in self._modelMap:
|
||||||
@ -243,7 +243,7 @@ class Anki2Importer(Importer):
|
|||||||
self.dst.models.update(model)
|
self.dst.models.update(model)
|
||||||
break
|
break
|
||||||
# as they don't match, try next id
|
# as they don't match, try next id
|
||||||
mid = NoteTypeId(mid + 1)
|
mid = NotetypeId(mid + 1)
|
||||||
# save map and return new mid
|
# save map and return new mid
|
||||||
self._modelMap[srcMid] = mid
|
self._modelMap[srcMid] = mid
|
||||||
return mid
|
return mid
|
||||||
@ -427,7 +427,7 @@ insert or ignore into revlog values (?,?,?,?,?,?,?,?,?)""",
|
|||||||
# the user likely used subdirectories
|
# the user likely used subdirectories
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _mungeMedia(self, mid: NoteTypeId, fieldsStr: str) -> str:
|
def _mungeMedia(self, mid: NotetypeId, fieldsStr: str) -> str:
|
||||||
fields = splitFields(fieldsStr)
|
fields = splitFields(fieldsStr)
|
||||||
|
|
||||||
def repl(match):
|
def repl(match):
|
||||||
|
@ -9,7 +9,7 @@ from anki.collection import Collection
|
|||||||
from anki.config import Config
|
from anki.config import Config
|
||||||
from anki.consts import NEW_CARDS_RANDOM, STARTING_FACTOR
|
from anki.consts import NEW_CARDS_RANDOM, STARTING_FACTOR
|
||||||
from anki.importing.base import Importer
|
from anki.importing.base import Importer
|
||||||
from anki.models import NoteTypeId
|
from anki.models import NotetypeId
|
||||||
from anki.notes import NoteId
|
from anki.notes import NoteId
|
||||||
from anki.utils import (
|
from anki.utils import (
|
||||||
fieldChecksum,
|
fieldChecksum,
|
||||||
@ -230,7 +230,7 @@ class NoteImporter(Importer):
|
|||||||
|
|
||||||
def newData(
|
def newData(
|
||||||
self, n: ForeignNote
|
self, n: ForeignNote
|
||||||
) -> Tuple[NoteId, str, NoteTypeId, int, int, str, str, str, int, int, str]:
|
) -> Tuple[NoteId, str, NotetypeId, int, int, str, str, str, int, int, str]:
|
||||||
id = self._nextID
|
id = self._nextID
|
||||||
self._nextID = NoteId(self._nextID + 1)
|
self._nextID = NoteId(self._nextID + 1)
|
||||||
self._ids.append(id)
|
self._ids.append(id)
|
||||||
@ -255,7 +255,7 @@ class NoteImporter(Importer):
|
|||||||
def addNew(
|
def addNew(
|
||||||
self,
|
self,
|
||||||
rows: List[
|
rows: List[
|
||||||
Tuple[NoteId, str, NoteTypeId, int, int, str, str, str, int, int, str]
|
Tuple[NoteId, str, NotetypeId, int, int, str, str, str, int, int, str]
|
||||||
],
|
],
|
||||||
) -> None:
|
) -> None:
|
||||||
self.col.db.executemany(
|
self.col.db.executemany(
|
||||||
|
@ -17,7 +17,7 @@ import anki
|
|||||||
import anki._backend.backend_pb2 as _pb
|
import anki._backend.backend_pb2 as _pb
|
||||||
from anki.consts import *
|
from anki.consts import *
|
||||||
from anki.latex import render_latex, render_latex_returning_errors
|
from anki.latex import render_latex, render_latex_returning_errors
|
||||||
from anki.models import NoteTypeId
|
from anki.models import NotetypeId
|
||||||
from anki.sound import SoundOrVideoTag
|
from anki.sound import SoundOrVideoTag
|
||||||
from anki.template import av_tags_to_native
|
from anki.template import av_tags_to_native
|
||||||
from anki.utils import intTime
|
from anki.utils import intTime
|
||||||
@ -160,7 +160,7 @@ class MediaManager:
|
|||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def filesInStr(
|
def filesInStr(
|
||||||
self, mid: NoteTypeId, string: str, includeRemote: bool = False
|
self, mid: NotetypeId, string: str, includeRemote: bool = False
|
||||||
) -> List[str]:
|
) -> List[str]:
|
||||||
l = []
|
l = []
|
||||||
model = self.col.models.get(mid)
|
model = self.col.models.get(mid)
|
||||||
|
@ -27,15 +27,15 @@ from anki.utils import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
# public exports
|
# public exports
|
||||||
NoteTypeNameId = _pb.NoteTypeNameId
|
NotetypeNameId = _pb.NotetypeNameId
|
||||||
NoteTypeNameIdUseCount = _pb.NoteTypeNameIdUseCount
|
NotetypeNameIdUseCount = _pb.NotetypeNameIdUseCount
|
||||||
|
|
||||||
|
|
||||||
# types
|
# types
|
||||||
NotetypeDict = Dict[str, Any]
|
NotetypeDict = Dict[str, Any]
|
||||||
FieldDict = Dict[str, Any]
|
FieldDict = Dict[str, Any]
|
||||||
TemplateDict = Dict[str, Union[str, int, None]]
|
TemplateDict = Dict[str, Union[str, int, None]]
|
||||||
NoteTypeId = NewType("NoteTypeId", int)
|
NotetypeId = NewType("NotetypeId", int)
|
||||||
|
|
||||||
|
|
||||||
class ModelsDictProxy:
|
class ModelsDictProxy:
|
||||||
@ -48,7 +48,7 @@ class ModelsDictProxy:
|
|||||||
|
|
||||||
def __getitem__(self, item: Any) -> Any:
|
def __getitem__(self, item: Any) -> Any:
|
||||||
self._warn()
|
self._warn()
|
||||||
return self._col.models.get(NoteTypeId(int(item)))
|
return self._col.models.get(NotetypeId(int(item)))
|
||||||
|
|
||||||
def __setitem__(self, key: str, val: Any) -> None:
|
def __setitem__(self, key: str, val: Any) -> None:
|
||||||
self._warn()
|
self._warn()
|
||||||
@ -115,16 +115,16 @@ class ModelManager:
|
|||||||
# need to cache responses from the backend. Please do not
|
# need to cache responses from the backend. Please do not
|
||||||
# access the cache directly!
|
# access the cache directly!
|
||||||
|
|
||||||
_cache: Dict[NoteTypeId, NotetypeDict] = {}
|
_cache: Dict[NotetypeId, NotetypeDict] = {}
|
||||||
|
|
||||||
def _update_cache(self, nt: NotetypeDict) -> None:
|
def _update_cache(self, nt: NotetypeDict) -> None:
|
||||||
self._cache[nt["id"]] = nt
|
self._cache[nt["id"]] = nt
|
||||||
|
|
||||||
def _remove_from_cache(self, ntid: NoteTypeId) -> None:
|
def _remove_from_cache(self, ntid: NotetypeId) -> None:
|
||||||
if ntid in self._cache:
|
if ntid in self._cache:
|
||||||
del self._cache[ntid]
|
del self._cache[ntid]
|
||||||
|
|
||||||
def _get_cached(self, ntid: NoteTypeId) -> Optional[NotetypeDict]:
|
def _get_cached(self, ntid: NotetypeId) -> Optional[NotetypeDict]:
|
||||||
return self._cache.get(ntid)
|
return self._cache.get(ntid)
|
||||||
|
|
||||||
def _clear_cache(self) -> None:
|
def _clear_cache(self) -> None:
|
||||||
@ -133,10 +133,10 @@ class ModelManager:
|
|||||||
# Listing note types
|
# Listing note types
|
||||||
#############################################################
|
#############################################################
|
||||||
|
|
||||||
def all_names_and_ids(self) -> Sequence[NoteTypeNameId]:
|
def all_names_and_ids(self) -> Sequence[NotetypeNameId]:
|
||||||
return self.col._backend.get_notetype_names()
|
return self.col._backend.get_notetype_names()
|
||||||
|
|
||||||
def all_use_counts(self) -> Sequence[NoteTypeNameIdUseCount]:
|
def all_use_counts(self) -> Sequence[NotetypeNameIdUseCount]:
|
||||||
return self.col._backend.get_notetype_names_and_counts()
|
return self.col._backend.get_notetype_names_and_counts()
|
||||||
|
|
||||||
# legacy
|
# legacy
|
||||||
@ -144,11 +144,11 @@ class ModelManager:
|
|||||||
def allNames(self) -> List[str]:
|
def allNames(self) -> List[str]:
|
||||||
return [n.name for n in self.all_names_and_ids()]
|
return [n.name for n in self.all_names_and_ids()]
|
||||||
|
|
||||||
def ids(self) -> List[NoteTypeId]:
|
def ids(self) -> List[NotetypeId]:
|
||||||
return [NoteTypeId(n.id) for n in self.all_names_and_ids()]
|
return [NotetypeId(n.id) for n in self.all_names_and_ids()]
|
||||||
|
|
||||||
# only used by importing code
|
# only used by importing code
|
||||||
def have(self, id: NoteTypeId) -> bool:
|
def have(self, id: NotetypeId) -> bool:
|
||||||
if isinstance(id, str):
|
if isinstance(id, str):
|
||||||
id = int(id)
|
id = int(id)
|
||||||
return any(True for e in self.all_names_and_ids() if e.id == id)
|
return any(True for e in self.all_names_and_ids() if e.id == id)
|
||||||
@ -163,7 +163,7 @@ class ModelManager:
|
|||||||
m = self.get(self.col.conf["curModel"])
|
m = self.get(self.col.conf["curModel"])
|
||||||
if m:
|
if m:
|
||||||
return m
|
return m
|
||||||
return self.get(NoteTypeId(self.all_names_and_ids()[0].id))
|
return self.get(NotetypeId(self.all_names_and_ids()[0].id))
|
||||||
|
|
||||||
def setCurrent(self, m: NotetypeDict) -> None:
|
def setCurrent(self, m: NotetypeDict) -> None:
|
||||||
self.col.conf["curModel"] = m["id"]
|
self.col.conf["curModel"] = m["id"]
|
||||||
@ -171,13 +171,13 @@ class ModelManager:
|
|||||||
# Retrieving and creating models
|
# Retrieving and creating models
|
||||||
#############################################################
|
#############################################################
|
||||||
|
|
||||||
def id_for_name(self, name: str) -> Optional[NoteTypeId]:
|
def id_for_name(self, name: str) -> Optional[NotetypeId]:
|
||||||
try:
|
try:
|
||||||
return NoteTypeId(self.col._backend.get_notetype_id_by_name(name))
|
return NotetypeId(self.col._backend.get_notetype_id_by_name(name))
|
||||||
except NotFoundError:
|
except NotFoundError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get(self, id: NoteTypeId) -> Optional[NotetypeDict]:
|
def get(self, id: NotetypeId) -> Optional[NotetypeDict]:
|
||||||
"Get model with ID, or None."
|
"Get model with ID, or None."
|
||||||
# deal with various legacy input types
|
# deal with various legacy input types
|
||||||
if id is None:
|
if id is None:
|
||||||
@ -196,7 +196,7 @@ class ModelManager:
|
|||||||
|
|
||||||
def all(self) -> List[NotetypeDict]:
|
def all(self) -> List[NotetypeDict]:
|
||||||
"Get all models."
|
"Get all models."
|
||||||
return [self.get(NoteTypeId(nt.id)) for nt in self.all_names_and_ids()]
|
return [self.get(NotetypeId(nt.id)) for nt in self.all_names_and_ids()]
|
||||||
|
|
||||||
def byName(self, name: str) -> Optional[NotetypeDict]:
|
def byName(self, name: str) -> Optional[NotetypeDict]:
|
||||||
"Get model with NAME."
|
"Get model with NAME."
|
||||||
@ -223,10 +223,10 @@ class ModelManager:
|
|||||||
|
|
||||||
def remove_all_notetypes(self) -> None:
|
def remove_all_notetypes(self) -> None:
|
||||||
for nt in self.all_names_and_ids():
|
for nt in self.all_names_and_ids():
|
||||||
self._remove_from_cache(NoteTypeId(nt.id))
|
self._remove_from_cache(NotetypeId(nt.id))
|
||||||
self.col._backend.remove_notetype(nt.id)
|
self.col._backend.remove_notetype(nt.id)
|
||||||
|
|
||||||
def remove(self, id: NoteTypeId) -> None:
|
def remove(self, id: NotetypeId) -> None:
|
||||||
"Modifies schema."
|
"Modifies schema."
|
||||||
self._remove_from_cache(id)
|
self._remove_from_cache(id)
|
||||||
self.col._backend.remove_notetype(id)
|
self.col._backend.remove_notetype(id)
|
||||||
@ -258,7 +258,7 @@ class ModelManager:
|
|||||||
# Tools
|
# Tools
|
||||||
##################################################
|
##################################################
|
||||||
|
|
||||||
def nids(self, ntid: NoteTypeId) -> List[anki.notes.NoteId]:
|
def nids(self, ntid: NotetypeId) -> List[anki.notes.NoteId]:
|
||||||
"Note ids for M."
|
"Note ids for M."
|
||||||
if isinstance(ntid, dict):
|
if isinstance(ntid, dict):
|
||||||
# legacy callers passed in note type
|
# legacy callers passed in note type
|
||||||
@ -406,7 +406,7 @@ class ModelManager:
|
|||||||
self.reposition_template(m, template, idx)
|
self.reposition_template(m, template, idx)
|
||||||
self.save(m)
|
self.save(m)
|
||||||
|
|
||||||
def template_use_count(self, ntid: NoteTypeId, ord: int) -> int:
|
def template_use_count(self, ntid: NotetypeId, ord: int) -> int:
|
||||||
return self.col.db.scalar(
|
return self.col.db.scalar(
|
||||||
"""
|
"""
|
||||||
select count() from cards, notes where cards.nid = notes.id
|
select count() from cards, notes where cards.nid = notes.id
|
||||||
|
@ -11,7 +11,7 @@ import anki # pylint: disable=unused-import
|
|||||||
import anki._backend.backend_pb2 as _pb
|
import anki._backend.backend_pb2 as _pb
|
||||||
from anki import hooks
|
from anki import hooks
|
||||||
from anki.consts import MODEL_STD
|
from anki.consts import MODEL_STD
|
||||||
from anki.models import NotetypeDict, NoteTypeId, TemplateDict
|
from anki.models import NotetypeDict, NotetypeId, TemplateDict
|
||||||
from anki.utils import joinFields
|
from anki.utils import joinFields
|
||||||
|
|
||||||
DuplicateOrEmptyResult = _pb.NoteIsDuplicateOrEmptyOut.State
|
DuplicateOrEmptyResult = _pb.NoteIsDuplicateOrEmptyOut.State
|
||||||
@ -25,7 +25,7 @@ class Note:
|
|||||||
flags = 0
|
flags = 0
|
||||||
data = ""
|
data = ""
|
||||||
id: NoteId
|
id: NoteId
|
||||||
mid: NoteTypeId
|
mid: NotetypeId
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -53,7 +53,7 @@ class Note:
|
|||||||
def _load_from_backend_note(self, n: _pb.Note) -> None:
|
def _load_from_backend_note(self, n: _pb.Note) -> None:
|
||||||
self.id = NoteId(n.id)
|
self.id = NoteId(n.id)
|
||||||
self.guid = n.guid
|
self.guid = n.guid
|
||||||
self.mid = NoteTypeId(n.notetype_id)
|
self.mid = NotetypeId(n.notetype_id)
|
||||||
self.mod = n.mtime_secs
|
self.mod = n.mtime_secs
|
||||||
self.usn = n.usn
|
self.usn = n.usn
|
||||||
self.tags = list(n.tags)
|
self.tags = list(n.tags)
|
||||||
|
@ -10,7 +10,7 @@ import anki._backend.backend_pb2 as _pb
|
|||||||
from anki.utils import from_json_bytes
|
from anki.utils import from_json_bytes
|
||||||
|
|
||||||
# pylint: disable=no-member
|
# pylint: disable=no-member
|
||||||
StockNotetypeKind = _pb.StockNoteType.Kind
|
StockNotetypeKind = _pb.StockNotetype.Kind
|
||||||
|
|
||||||
# add-on authors can add ("note type name", function_like_addBasicModel)
|
# 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
|
# to this list to have it shown in the add/clone note type screen
|
||||||
|
@ -9,12 +9,12 @@ import aqt.forms
|
|||||||
from anki.collection import OpChanges, SearchNode
|
from anki.collection import OpChanges, SearchNode
|
||||||
from anki.consts import MODEL_CLOZE
|
from anki.consts import MODEL_CLOZE
|
||||||
from anki.decks import DeckId
|
from anki.decks import DeckId
|
||||||
from anki.models import NoteTypeId
|
from anki.models import NotetypeId
|
||||||
from anki.notes import DuplicateOrEmptyResult, Note, NoteId
|
from anki.notes import DuplicateOrEmptyResult, Note, NoteId
|
||||||
from anki.utils import htmlToTextLine, isMac
|
from anki.utils import htmlToTextLine, isMac
|
||||||
from aqt import AnkiQt, gui_hooks
|
from aqt import AnkiQt, gui_hooks
|
||||||
from aqt.note_ops import add_note
|
from aqt.note_ops import add_note
|
||||||
from aqt.notetypechooser import NoteTypeChooser
|
from aqt.notetypechooser import NotetypeChooser
|
||||||
from aqt.qt import *
|
from aqt.qt import *
|
||||||
from aqt.sound import av_player
|
from aqt.sound import av_player
|
||||||
from aqt.utils import (
|
from aqt.utils import (
|
||||||
@ -62,10 +62,10 @@ class AddCards(QDialog):
|
|||||||
defaults = self.mw.col.defaults_for_adding(
|
defaults = self.mw.col.defaults_for_adding(
|
||||||
current_review_card=self.mw.reviewer.card
|
current_review_card=self.mw.reviewer.card
|
||||||
)
|
)
|
||||||
self.notetype_chooser = NoteTypeChooser(
|
self.notetype_chooser = NotetypeChooser(
|
||||||
mw=self.mw,
|
mw=self.mw,
|
||||||
widget=self.form.modelArea,
|
widget=self.form.modelArea,
|
||||||
starting_notetype_id=NoteTypeId(defaults.notetype_id),
|
starting_notetype_id=NotetypeId(defaults.notetype_id),
|
||||||
on_button_activated=self.show_notetype_selector,
|
on_button_activated=self.show_notetype_selector,
|
||||||
on_notetype_changed=self.on_notetype_change,
|
on_notetype_changed=self.on_notetype_change,
|
||||||
)
|
)
|
||||||
@ -110,7 +110,7 @@ class AddCards(QDialog):
|
|||||||
def show_notetype_selector(self) -> None:
|
def show_notetype_selector(self) -> None:
|
||||||
self.editor.call_after_note_saved(self.notetype_chooser.choose_notetype)
|
self.editor.call_after_note_saved(self.notetype_chooser.choose_notetype)
|
||||||
|
|
||||||
def on_notetype_change(self, notetype_id: NoteTypeId) -> None:
|
def on_notetype_change(self, notetype_id: NotetypeId) -> None:
|
||||||
# need to adjust current deck?
|
# need to adjust current deck?
|
||||||
if deck_id := self.mw.col.default_deck_for_notetype(notetype_id):
|
if deck_id := self.mw.col.default_deck_for_notetype(notetype_id):
|
||||||
self.deck_chooser.selected_deck_id = deck_id
|
self.deck_chooser.selected_deck_id = deck_id
|
||||||
|
@ -8,7 +8,7 @@ from aqt.utils import HelpPage, shortcut, tr
|
|||||||
|
|
||||||
|
|
||||||
class ModelChooser(QHBoxLayout):
|
class ModelChooser(QHBoxLayout):
|
||||||
"New code should prefer NoteTypeChooser."
|
"New code should prefer NotetypeChooser."
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
@ -8,7 +8,7 @@ from typing import List, Optional, Sequence
|
|||||||
import aqt.clayout
|
import aqt.clayout
|
||||||
from anki import Collection, stdmodels
|
from anki import Collection, stdmodels
|
||||||
from anki.lang import without_unicode_isolation
|
from anki.lang import without_unicode_isolation
|
||||||
from anki.models import NotetypeDict, NoteTypeId, NoteTypeNameIdUseCount
|
from anki.models import NotetypeDict, NotetypeId, NotetypeNameIdUseCount
|
||||||
from anki.notes import Note
|
from anki.notes import Note
|
||||||
from aqt import AnkiQt, gui_hooks
|
from aqt import AnkiQt, gui_hooks
|
||||||
from aqt.qt import *
|
from aqt.qt import *
|
||||||
@ -32,7 +32,7 @@ class Models(QDialog):
|
|||||||
mw: AnkiQt,
|
mw: AnkiQt,
|
||||||
parent: Optional[QWidget] = None,
|
parent: Optional[QWidget] = None,
|
||||||
fromMain: bool = False,
|
fromMain: bool = False,
|
||||||
selected_notetype_id: Optional[NoteTypeId] = None,
|
selected_notetype_id: Optional[NotetypeId] = None,
|
||||||
):
|
):
|
||||||
self.mw = mw
|
self.mw = mw
|
||||||
parent = parent or mw
|
parent = parent or mw
|
||||||
@ -49,7 +49,7 @@ class Models(QDialog):
|
|||||||
self.form.buttonBox.helpRequested,
|
self.form.buttonBox.helpRequested,
|
||||||
lambda: openHelp(HelpPage.ADDING_A_NOTE_TYPE),
|
lambda: openHelp(HelpPage.ADDING_A_NOTE_TYPE),
|
||||||
)
|
)
|
||||||
self.models: List[NoteTypeNameIdUseCount] = []
|
self.models: List[NotetypeNameIdUseCount] = []
|
||||||
self.setupModels()
|
self.setupModels()
|
||||||
restoreGeom(self, "models")
|
restoreGeom(self, "models")
|
||||||
self.exec_()
|
self.exec_()
|
||||||
@ -109,7 +109,7 @@ class Models(QDialog):
|
|||||||
self.saveAndRefresh(nt)
|
self.saveAndRefresh(nt)
|
||||||
|
|
||||||
def saveAndRefresh(self, nt: NotetypeDict) -> None:
|
def saveAndRefresh(self, nt: NotetypeDict) -> None:
|
||||||
def save() -> Sequence[NoteTypeNameIdUseCount]:
|
def save() -> Sequence[NotetypeNameIdUseCount]:
|
||||||
self.mm.save(nt)
|
self.mm.save(nt)
|
||||||
return self.col.models.all_use_counts()
|
return self.col.models.all_use_counts()
|
||||||
|
|
||||||
@ -118,7 +118,7 @@ class Models(QDialog):
|
|||||||
|
|
||||||
self.mw.taskman.with_progress(save, on_done, self)
|
self.mw.taskman.with_progress(save, on_done, self)
|
||||||
|
|
||||||
def updateModelsList(self, notetypes: List[NoteTypeNameIdUseCount]) -> None:
|
def updateModelsList(self, notetypes: List[NotetypeNameIdUseCount]) -> None:
|
||||||
row = self.form.modelsList.currentRow()
|
row = self.form.modelsList.currentRow()
|
||||||
if row == -1:
|
if row == -1:
|
||||||
row = 0
|
row = 0
|
||||||
@ -133,7 +133,7 @@ class Models(QDialog):
|
|||||||
|
|
||||||
def current_notetype(self) -> NotetypeDict:
|
def current_notetype(self) -> NotetypeDict:
|
||||||
row = self.form.modelsList.currentRow()
|
row = self.form.modelsList.currentRow()
|
||||||
return self.mm.get(NoteTypeId(self.models[row].id))
|
return self.mm.get(NotetypeId(self.models[row].id))
|
||||||
|
|
||||||
def onAdd(self) -> None:
|
def onAdd(self) -> None:
|
||||||
m = AddModel(self.mw, self).get()
|
m = AddModel(self.mw, self).get()
|
||||||
@ -159,7 +159,7 @@ class Models(QDialog):
|
|||||||
|
|
||||||
nt = self.current_notetype()
|
nt = self.current_notetype()
|
||||||
|
|
||||||
def save() -> Sequence[NoteTypeNameIdUseCount]:
|
def save() -> Sequence[NotetypeNameIdUseCount]:
|
||||||
self.mm.rem(nt)
|
self.mm.rem(nt)
|
||||||
return self.col.models.all_use_counts()
|
return self.col.models.all_use_counts()
|
||||||
|
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
# 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
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from anki.models import NoteTypeId
|
from anki.models import NotetypeId
|
||||||
from aqt import AnkiQt, gui_hooks
|
from aqt import AnkiQt, gui_hooks
|
||||||
from aqt.qt import *
|
from aqt.qt import *
|
||||||
from aqt.utils import HelpPage, shortcut, tr
|
from aqt.utils import HelpPage, shortcut, tr
|
||||||
|
|
||||||
|
|
||||||
class NoteTypeChooser(QHBoxLayout):
|
class NotetypeChooser(QHBoxLayout):
|
||||||
"""
|
"""
|
||||||
Unlike the older modelchooser, this does not modify the "current model",
|
Unlike the older modelchooser, this does not modify the "current model",
|
||||||
so changes made here do not affect other parts of the UI. To read the
|
so changes made here do not affect other parts of the UI. To read the
|
||||||
@ -23,16 +23,16 @@ class NoteTypeChooser(QHBoxLayout):
|
|||||||
deleted.
|
deleted.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_selected_notetype_id: NoteTypeId
|
_selected_notetype_id: NotetypeId
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
mw: AnkiQt,
|
mw: AnkiQt,
|
||||||
widget: QWidget,
|
widget: QWidget,
|
||||||
starting_notetype_id: NoteTypeId,
|
starting_notetype_id: NotetypeId,
|
||||||
on_button_activated: Optional[Callable[[], None]] = None,
|
on_button_activated: Optional[Callable[[], None]] = None,
|
||||||
on_notetype_changed: Optional[Callable[[NoteTypeId], None]] = None,
|
on_notetype_changed: Optional[Callable[[NotetypeId], None]] = None,
|
||||||
show_prefix_label: bool = True,
|
show_prefix_label: bool = True,
|
||||||
) -> None:
|
) -> None:
|
||||||
QHBoxLayout.__init__(self)
|
QHBoxLayout.__init__(self)
|
||||||
@ -44,7 +44,7 @@ class NoteTypeChooser(QHBoxLayout):
|
|||||||
self.on_button_activated = self.choose_notetype
|
self.on_button_activated = self.choose_notetype
|
||||||
self._setup_ui(show_label=show_prefix_label)
|
self._setup_ui(show_label=show_prefix_label)
|
||||||
gui_hooks.state_did_reset.append(self.reset_state)
|
gui_hooks.state_did_reset.append(self.reset_state)
|
||||||
self._selected_notetype_id = NoteTypeId(0)
|
self._selected_notetype_id = NotetypeId(0)
|
||||||
# triggers UI update; avoid firing changed hook on startup
|
# triggers UI update; avoid firing changed hook on startup
|
||||||
self.on_notetype_changed = None
|
self.on_notetype_changed = None
|
||||||
self.selected_notetype_id = starting_notetype_id
|
self.selected_notetype_id = starting_notetype_id
|
||||||
@ -121,7 +121,7 @@ class NoteTypeChooser(QHBoxLayout):
|
|||||||
self.selected_notetype_id = id
|
self.selected_notetype_id = id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def selected_notetype_id(self) -> NoteTypeId:
|
def selected_notetype_id(self) -> NotetypeId:
|
||||||
# theoretically this should not be necessary, as we're listening to
|
# theoretically this should not be necessary, as we're listening to
|
||||||
# resets
|
# resets
|
||||||
self._ensure_selected_notetype_valid()
|
self._ensure_selected_notetype_valid()
|
||||||
@ -129,7 +129,7 @@ class NoteTypeChooser(QHBoxLayout):
|
|||||||
return self._selected_notetype_id
|
return self._selected_notetype_id
|
||||||
|
|
||||||
@selected_notetype_id.setter
|
@selected_notetype_id.setter
|
||||||
def selected_notetype_id(self, id: NoteTypeId) -> None:
|
def selected_notetype_id(self, id: NotetypeId) -> None:
|
||||||
if id != self._selected_notetype_id:
|
if id != self._selected_notetype_id:
|
||||||
self._selected_notetype_id = id
|
self._selected_notetype_id = id
|
||||||
self._ensure_selected_notetype_valid()
|
self._ensure_selected_notetype_valid()
|
||||||
@ -142,7 +142,7 @@ class NoteTypeChooser(QHBoxLayout):
|
|||||||
|
|
||||||
def _ensure_selected_notetype_valid(self) -> None:
|
def _ensure_selected_notetype_valid(self) -> None:
|
||||||
if not self.mw.col.models.get(self._selected_notetype_id):
|
if not self.mw.col.models.get(self._selected_notetype_id):
|
||||||
self.selected_notetype_id = NoteTypeId(
|
self.selected_notetype_id = NotetypeId(
|
||||||
self.mw.col.models.all_names_and_ids()[0].id
|
self.mw.col.models.all_names_and_ids()[0].id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ from typing import Dict, Iterable, List, Optional, Tuple, cast
|
|||||||
import aqt
|
import aqt
|
||||||
from anki.collection import Config, OpChanges, SearchJoiner, SearchNode
|
from anki.collection import Config, OpChanges, SearchJoiner, SearchNode
|
||||||
from anki.decks import DeckId, DeckTreeNode
|
from anki.decks import DeckId, DeckTreeNode
|
||||||
from anki.models import NoteTypeId
|
from anki.models import NotetypeId
|
||||||
from anki.notes import Note
|
from anki.notes import Note
|
||||||
from anki.tags import TagTreeNode
|
from anki.tags import TagTreeNode
|
||||||
from anki.types import assert_exhaustive
|
from anki.types import assert_exhaustive
|
||||||
@ -1284,11 +1284,11 @@ class SidebarTreeView(QTreeView):
|
|||||||
self.mw,
|
self.mw,
|
||||||
parent=self.browser,
|
parent=self.browser,
|
||||||
fromMain=True,
|
fromMain=True,
|
||||||
selected_notetype_id=NoteTypeId(item.id),
|
selected_notetype_id=NotetypeId(item.id),
|
||||||
)
|
)
|
||||||
|
|
||||||
def manage_template(self, item: SidebarItem) -> None:
|
def manage_template(self, item: SidebarItem) -> None:
|
||||||
note = Note(self.col, self.col.models.get(NoteTypeId(item._parent_item.id)))
|
note = Note(self.col, self.col.models.get(NotetypeId(item._parent_item.id)))
|
||||||
CardLayout(self.mw, note, ord=item.id, parent=self, fill_empty=True)
|
CardLayout(self.mw, note, ord=item.id, parent=self, fill_empty=True)
|
||||||
|
|
||||||
# Helpers
|
# Helpers
|
||||||
|
@ -58,7 +58,7 @@ message OpChangesWithId {
|
|||||||
// IDs used in RPC calls
|
// IDs used in RPC calls
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
|
||||||
message NoteTypeId {
|
message NotetypeId {
|
||||||
int64 ntid = 1;
|
int64 ntid = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ enum ServiceIndex {
|
|||||||
SERVICE_INDEX_DECKS = 1;
|
SERVICE_INDEX_DECKS = 1;
|
||||||
SERVICE_INDEX_NOTES = 2;
|
SERVICE_INDEX_NOTES = 2;
|
||||||
SERVICE_INDEX_SYNC = 3;
|
SERVICE_INDEX_SYNC = 3;
|
||||||
SERVICE_INDEX_NOTE_TYPES = 4;
|
SERVICE_INDEX_NOTETYPES = 4;
|
||||||
SERVICE_INDEX_CONFIG = 5;
|
SERVICE_INDEX_CONFIG = 5;
|
||||||
SERVICE_INDEX_CARD_RENDERING = 6;
|
SERVICE_INDEX_CARD_RENDERING = 6;
|
||||||
SERVICE_INDEX_DECK_CONFIG = 7;
|
SERVICE_INDEX_DECK_CONFIG = 7;
|
||||||
@ -153,10 +153,10 @@ service DecksService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
service NotesService {
|
service NotesService {
|
||||||
rpc NewNote(NoteTypeId) returns (Note);
|
rpc NewNote(NotetypeId) returns (Note);
|
||||||
rpc AddNote(AddNoteIn) returns (AddNoteOut);
|
rpc AddNote(AddNoteIn) returns (AddNoteOut);
|
||||||
rpc DefaultsForAdding(DefaultsForAddingIn) returns (DeckAndNotetype);
|
rpc DefaultsForAdding(DefaultsForAddingIn) returns (DeckAndNotetype);
|
||||||
rpc DefaultDeckForNotetype(NoteTypeId) returns (DeckId);
|
rpc DefaultDeckForNotetype(NotetypeId) returns (DeckId);
|
||||||
rpc UpdateNote(UpdateNoteIn) returns (OpChanges);
|
rpc UpdateNote(UpdateNoteIn) returns (OpChanges);
|
||||||
rpc GetNote(NoteId) returns (Note);
|
rpc GetNote(NoteId) returns (Note);
|
||||||
rpc RemoveNotes(RemoveNotesIn) returns (OpChanges);
|
rpc RemoveNotes(RemoveNotesIn) returns (OpChanges);
|
||||||
@ -193,14 +193,14 @@ service ConfigService {
|
|||||||
rpc SetPreferences(Preferences) returns (OpChanges);
|
rpc SetPreferences(Preferences) returns (OpChanges);
|
||||||
}
|
}
|
||||||
|
|
||||||
service NoteTypesService {
|
service NotetypesService {
|
||||||
rpc AddOrUpdateNotetype(AddOrUpdateNotetypeIn) returns (NoteTypeId);
|
rpc AddOrUpdateNotetype(AddOrUpdateNotetypeIn) returns (NotetypeId);
|
||||||
rpc GetStockNotetypeLegacy(StockNoteType) returns (Json);
|
rpc GetStockNotetypeLegacy(StockNotetype) returns (Json);
|
||||||
rpc GetNotetypeLegacy(NoteTypeId) returns (Json);
|
rpc GetNotetypeLegacy(NotetypeId) returns (Json);
|
||||||
rpc GetNotetypeNames(Empty) returns (NoteTypeNames);
|
rpc GetNotetypeNames(Empty) returns (NotetypeNames);
|
||||||
rpc GetNotetypeNamesAndCounts(Empty) returns (NoteTypeUseCounts);
|
rpc GetNotetypeNamesAndCounts(Empty) returns (NotetypeUseCounts);
|
||||||
rpc GetNotetypeIdByName(String) returns (NoteTypeId);
|
rpc GetNotetypeIdByName(String) returns (NotetypeId);
|
||||||
rpc RemoveNotetype(NoteTypeId) returns (Empty);
|
rpc RemoveNotetype(NotetypeId) returns (Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
service CardRenderingService {
|
service CardRenderingService {
|
||||||
@ -434,7 +434,7 @@ message CardTemplateConfig {
|
|||||||
bytes other = 255;
|
bytes other = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
message NoteTypeConfig {
|
message NotetypeConfig {
|
||||||
enum Kind {
|
enum Kind {
|
||||||
KIND_NORMAL = 0;
|
KIND_NORMAL = 0;
|
||||||
KIND_CLOZE = 1;
|
KIND_CLOZE = 1;
|
||||||
@ -477,12 +477,12 @@ message Deck {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message NoteType {
|
message Notetype {
|
||||||
int64 id = 1;
|
int64 id = 1;
|
||||||
string name = 2;
|
string name = 2;
|
||||||
uint32 mtime_secs = 3;
|
uint32 mtime_secs = 3;
|
||||||
sint32 usn = 4;
|
sint32 usn = 4;
|
||||||
NoteTypeConfig config = 7;
|
NotetypeConfig config = 7;
|
||||||
repeated NoteField fields = 8;
|
repeated NoteField fields = 8;
|
||||||
repeated CardTemplate templates = 9;
|
repeated CardTemplate templates = 9;
|
||||||
}
|
}
|
||||||
@ -811,7 +811,7 @@ message SortOrder {
|
|||||||
NOTE_MOD = 1;
|
NOTE_MOD = 1;
|
||||||
NOTE_FIELD = 2;
|
NOTE_FIELD = 2;
|
||||||
NOTE_TAGS = 3;
|
NOTE_TAGS = 3;
|
||||||
NOTE_TYPE = 4;
|
NOTETYPE = 4;
|
||||||
CARD_MOD = 5;
|
CARD_MOD = 5;
|
||||||
CARD_REPS = 6;
|
CARD_REPS = 6;
|
||||||
CARD_DUE = 7;
|
CARD_DUE = 7;
|
||||||
@ -957,7 +957,7 @@ message SetConfigJsonIn {
|
|||||||
bytes value_json = 2;
|
bytes value_json = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message StockNoteType {
|
message StockNotetype {
|
||||||
enum Kind {
|
enum Kind {
|
||||||
BASIC = 0;
|
BASIC = 0;
|
||||||
BASIC_AND_REVERSED = 1;
|
BASIC_AND_REVERSED = 1;
|
||||||
@ -969,20 +969,20 @@ message StockNoteType {
|
|||||||
Kind kind = 1;
|
Kind kind = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message NoteTypeNames {
|
message NotetypeNames {
|
||||||
repeated NoteTypeNameId entries = 1;
|
repeated NotetypeNameId entries = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message NoteTypeUseCounts {
|
message NotetypeUseCounts {
|
||||||
repeated NoteTypeNameIdUseCount entries = 1;
|
repeated NotetypeNameIdUseCount entries = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message NoteTypeNameId {
|
message NotetypeNameId {
|
||||||
int64 id = 1;
|
int64 id = 1;
|
||||||
string name = 2;
|
string name = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message NoteTypeNameIdUseCount {
|
message NotetypeNameIdUseCount {
|
||||||
int64 id = 1;
|
int64 id = 1;
|
||||||
string name = 2;
|
string name = 2;
|
||||||
uint32 use_count = 3;
|
uint32 use_count = 3;
|
||||||
|
@ -7,7 +7,7 @@ use crate::prelude::*;
|
|||||||
|
|
||||||
pub struct DeckAndNotetype {
|
pub struct DeckAndNotetype {
|
||||||
pub deck_id: DeckId,
|
pub deck_id: DeckId,
|
||||||
pub notetype_id: NoteTypeId,
|
pub notetype_id: NotetypeId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Collection {
|
impl Collection {
|
||||||
@ -68,7 +68,7 @@ impl Collection {
|
|||||||
self.get_deck(DeckId(1))?.ok_or(AnkiError::NotFound)
|
self.get_deck(DeckId(1))?.ok_or(AnkiError::NotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_current_notetype_for_adding(&mut self) -> Result<Arc<NoteType>> {
|
fn get_current_notetype_for_adding(&mut self) -> Result<Arc<Notetype>> {
|
||||||
// try global 'current' notetype
|
// try global 'current' notetype
|
||||||
if let Some(ntid) = self.get_current_notetype_id() {
|
if let Some(ntid) = self.get_current_notetype_id() {
|
||||||
if let Some(nt) = self.get_notetype(ntid)? {
|
if let Some(nt) = self.get_notetype(ntid)? {
|
||||||
@ -83,7 +83,7 @@ impl Collection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_notetype_for_deck(&mut self, deck: DeckId) -> Result<Arc<NoteType>> {
|
fn default_notetype_for_deck(&mut self, deck: DeckId) -> Result<Arc<Notetype>> {
|
||||||
// try last notetype used by deck
|
// try last notetype used by deck
|
||||||
if let Some(ntid) = self.get_last_notetype_for_deck(deck) {
|
if let Some(ntid) = self.get_last_notetype_for_deck(deck) {
|
||||||
if let Some(nt) = self.get_notetype(ntid)? {
|
if let Some(nt) = self.get_notetype(ntid)? {
|
||||||
@ -99,7 +99,7 @@ impl Collection {
|
|||||||
/// This is optional due to the inconsistent handling, where changes in notetype
|
/// This is optional due to the inconsistent handling, where changes in notetype
|
||||||
/// may need to update the current deck, but not vice versa. If a previous deck is
|
/// may need to update the current deck, but not vice versa. If a previous deck is
|
||||||
/// not set, we want to keep the current selection, instead of resetting it.
|
/// not set, we want to keep the current selection, instead of resetting it.
|
||||||
pub(crate) fn default_deck_for_notetype(&mut self, ntid: NoteTypeId) -> Result<Option<DeckId>> {
|
pub(crate) fn default_deck_for_notetype(&mut self, ntid: NotetypeId) -> Result<Option<DeckId>> {
|
||||||
if let Some(last_deck_id) = self.get_last_deck_added_to_for_notetype(ntid) {
|
if let Some(last_deck_id) = self.get_last_deck_added_to_for_notetype(ntid) {
|
||||||
if let Some(deck) = self.get_deck(last_deck_id)? {
|
if let Some(deck) = self.get_deck(last_deck_id)? {
|
||||||
if !deck.is_filtered() {
|
if !deck.is_filtered() {
|
||||||
|
@ -63,9 +63,9 @@ impl From<pb::NoteId> for NoteId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<pb::NoteTypeId> for NoteTypeId {
|
impl From<pb::NotetypeId> for NotetypeId {
|
||||||
fn from(ntid: pb::NoteTypeId) -> Self {
|
fn from(ntid: pb::NotetypeId) -> Self {
|
||||||
NoteTypeId(ntid.ntid)
|
NotetypeId(ntid.ntid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ use self::{
|
|||||||
i18n::I18nService,
|
i18n::I18nService,
|
||||||
media::MediaService,
|
media::MediaService,
|
||||||
notes::NotesService,
|
notes::NotesService,
|
||||||
notetypes::NoteTypesService,
|
notetypes::NotetypesService,
|
||||||
progress::ProgressState,
|
progress::ProgressState,
|
||||||
scheduler::SchedulingService,
|
scheduler::SchedulingService,
|
||||||
search::SearchService,
|
search::SearchService,
|
||||||
@ -121,7 +121,7 @@ impl Backend {
|
|||||||
pb::ServiceIndex::Scheduling => SchedulingService::run_method(self, method, input),
|
pb::ServiceIndex::Scheduling => SchedulingService::run_method(self, method, input),
|
||||||
pb::ServiceIndex::Decks => DecksService::run_method(self, method, input),
|
pb::ServiceIndex::Decks => DecksService::run_method(self, method, input),
|
||||||
pb::ServiceIndex::Notes => NotesService::run_method(self, method, input),
|
pb::ServiceIndex::Notes => NotesService::run_method(self, method, input),
|
||||||
pb::ServiceIndex::NoteTypes => NoteTypesService::run_method(self, method, input),
|
pb::ServiceIndex::Notetypes => NotetypesService::run_method(self, method, input),
|
||||||
pb::ServiceIndex::Config => ConfigService::run_method(self, method, input),
|
pb::ServiceIndex::Config => ConfigService::run_method(self, method, input),
|
||||||
pb::ServiceIndex::Sync => SyncService::run_method(self, method, input),
|
pb::ServiceIndex::Sync => SyncService::run_method(self, method, input),
|
||||||
pb::ServiceIndex::Tags => TagsService::run_method(self, method, input),
|
pb::ServiceIndex::Tags => TagsService::run_method(self, method, input),
|
||||||
|
@ -12,7 +12,7 @@ use crate::{
|
|||||||
pub(super) use pb::notes_service::Service as NotesService;
|
pub(super) use pb::notes_service::Service as NotesService;
|
||||||
|
|
||||||
impl NotesService for Backend {
|
impl NotesService for Backend {
|
||||||
fn new_note(&self, input: pb::NoteTypeId) -> Result<pb::Note> {
|
fn new_note(&self, input: pb::NotetypeId) -> Result<pb::Note> {
|
||||||
self.with_col(|col| {
|
self.with_col(|col| {
|
||||||
let nt = col.get_notetype(input.into())?.ok_or(AnkiError::NotFound)?;
|
let nt = col.get_notetype(input.into())?.ok_or(AnkiError::NotFound)?;
|
||||||
Ok(nt.new_note().into())
|
Ok(nt.new_note().into())
|
||||||
@ -37,7 +37,7 @@ impl NotesService for Backend {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_deck_for_notetype(&self, input: pb::NoteTypeId) -> Result<pb::DeckId> {
|
fn default_deck_for_notetype(&self, input: pb::NotetypeId) -> Result<pb::DeckId> {
|
||||||
self.with_col(|col| {
|
self.with_col(|col| {
|
||||||
Ok(col
|
Ok(col
|
||||||
.default_deck_for_notetype(input.into())?
|
.default_deck_for_notetype(input.into())?
|
||||||
|
@ -4,39 +4,39 @@
|
|||||||
use super::Backend;
|
use super::Backend;
|
||||||
use crate::{
|
use crate::{
|
||||||
backend_proto as pb,
|
backend_proto as pb,
|
||||||
notetype::{all_stock_notetypes, NoteType, NoteTypeSchema11},
|
notetype::{all_stock_notetypes, Notetype, NotetypeSchema11},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
pub(super) use pb::notetypes_service::Service as NoteTypesService;
|
pub(super) use pb::notetypes_service::Service as NotetypesService;
|
||||||
|
|
||||||
impl NoteTypesService for Backend {
|
impl NotetypesService for Backend {
|
||||||
fn add_or_update_notetype(&self, input: pb::AddOrUpdateNotetypeIn) -> Result<pb::NoteTypeId> {
|
fn add_or_update_notetype(&self, input: pb::AddOrUpdateNotetypeIn) -> Result<pb::NotetypeId> {
|
||||||
self.with_col(|col| {
|
self.with_col(|col| {
|
||||||
let legacy: NoteTypeSchema11 = serde_json::from_slice(&input.json)?;
|
let legacy: NotetypeSchema11 = serde_json::from_slice(&input.json)?;
|
||||||
let mut nt: NoteType = legacy.into();
|
let mut nt: Notetype = legacy.into();
|
||||||
if nt.id.0 == 0 {
|
if nt.id.0 == 0 {
|
||||||
col.add_notetype(&mut nt)?;
|
col.add_notetype(&mut nt)?;
|
||||||
} else {
|
} else {
|
||||||
col.update_notetype(&mut nt, input.preserve_usn_and_mtime)?;
|
col.update_notetype(&mut nt, input.preserve_usn_and_mtime)?;
|
||||||
}
|
}
|
||||||
Ok(pb::NoteTypeId { ntid: nt.id.0 })
|
Ok(pb::NotetypeId { ntid: nt.id.0 })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_stock_notetype_legacy(&self, input: pb::StockNoteType) -> Result<pb::Json> {
|
fn get_stock_notetype_legacy(&self, input: pb::StockNotetype) -> Result<pb::Json> {
|
||||||
// fixme: use individual functions instead of full vec
|
// fixme: use individual functions instead of full vec
|
||||||
let mut all = all_stock_notetypes(&self.tr);
|
let mut all = all_stock_notetypes(&self.tr);
|
||||||
let idx = (input.kind as usize).min(all.len() - 1);
|
let idx = (input.kind as usize).min(all.len() - 1);
|
||||||
let nt = all.swap_remove(idx);
|
let nt = all.swap_remove(idx);
|
||||||
let schema11: NoteTypeSchema11 = nt.into();
|
let schema11: NotetypeSchema11 = nt.into();
|
||||||
serde_json::to_vec(&schema11)
|
serde_json::to_vec(&schema11)
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_notetype_legacy(&self, input: pb::NoteTypeId) -> Result<pb::Json> {
|
fn get_notetype_legacy(&self, input: pb::NotetypeId) -> Result<pb::Json> {
|
||||||
self.with_col(|col| {
|
self.with_col(|col| {
|
||||||
let schema11: NoteTypeSchema11 = col
|
let schema11: NotetypeSchema11 = col
|
||||||
.storage
|
.storage
|
||||||
.get_notetype(input.into())?
|
.get_notetype(input.into())?
|
||||||
.ok_or(AnkiError::NotFound)?
|
.ok_or(AnkiError::NotFound)?
|
||||||
@ -45,44 +45,44 @@ impl NoteTypesService for Backend {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_notetype_names(&self, _input: pb::Empty) -> Result<pb::NoteTypeNames> {
|
fn get_notetype_names(&self, _input: pb::Empty) -> Result<pb::NotetypeNames> {
|
||||||
self.with_col(|col| {
|
self.with_col(|col| {
|
||||||
let entries: Vec<_> = col
|
let entries: Vec<_> = col
|
||||||
.storage
|
.storage
|
||||||
.get_all_notetype_names()?
|
.get_all_notetype_names()?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(id, name)| pb::NoteTypeNameId { id: id.0, name })
|
.map(|(id, name)| pb::NotetypeNameId { id: id.0, name })
|
||||||
.collect();
|
.collect();
|
||||||
Ok(pb::NoteTypeNames { entries })
|
Ok(pb::NotetypeNames { entries })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_notetype_names_and_counts(&self, _input: pb::Empty) -> Result<pb::NoteTypeUseCounts> {
|
fn get_notetype_names_and_counts(&self, _input: pb::Empty) -> Result<pb::NotetypeUseCounts> {
|
||||||
self.with_col(|col| {
|
self.with_col(|col| {
|
||||||
let entries: Vec<_> = col
|
let entries: Vec<_> = col
|
||||||
.storage
|
.storage
|
||||||
.get_notetype_use_counts()?
|
.get_notetype_use_counts()?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(id, name, use_count)| pb::NoteTypeNameIdUseCount {
|
.map(|(id, name, use_count)| pb::NotetypeNameIdUseCount {
|
||||||
id: id.0,
|
id: id.0,
|
||||||
name,
|
name,
|
||||||
use_count,
|
use_count,
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
Ok(pb::NoteTypeUseCounts { entries })
|
Ok(pb::NotetypeUseCounts { entries })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_notetype_id_by_name(&self, input: pb::String) -> Result<pb::NoteTypeId> {
|
fn get_notetype_id_by_name(&self, input: pb::String) -> Result<pb::NotetypeId> {
|
||||||
self.with_col(|col| {
|
self.with_col(|col| {
|
||||||
col.storage
|
col.storage
|
||||||
.get_notetype_id(&input.val)
|
.get_notetype_id(&input.val)
|
||||||
.and_then(|nt| nt.ok_or(AnkiError::NotFound))
|
.and_then(|nt| nt.ok_or(AnkiError::NotFound))
|
||||||
.map(|ntid| pb::NoteTypeId { ntid: ntid.0 })
|
.map(|ntid| pb::NotetypeId { ntid: ntid.0 })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_notetype(&self, input: pb::NoteTypeId) -> Result<pb::Empty> {
|
fn remove_notetype(&self, input: pb::NotetypeId) -> Result<pb::Empty> {
|
||||||
self.with_col(|col| col.remove_notetype(input.into()))
|
self.with_col(|col| col.remove_notetype(input.into()))
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ impl From<SortKindProto> for SortKind {
|
|||||||
SortKindProto::NoteMod => SortKind::NoteMod,
|
SortKindProto::NoteMod => SortKind::NoteMod,
|
||||||
SortKindProto::NoteField => SortKind::NoteField,
|
SortKindProto::NoteField => SortKind::NoteField,
|
||||||
SortKindProto::NoteTags => SortKind::NoteTags,
|
SortKindProto::NoteTags => SortKind::NoteTags,
|
||||||
SortKindProto::NoteType => SortKind::NoteType,
|
SortKindProto::Notetype => SortKind::Notetype,
|
||||||
SortKindProto::CardMod => SortKind::CardMod,
|
SortKindProto::CardMod => SortKind::CardMod,
|
||||||
SortKindProto::CardReps => SortKind::CardReps,
|
SortKindProto::CardReps => SortKind::CardReps,
|
||||||
SortKindProto::CardDue => SortKind::CardDue,
|
SortKindProto::CardDue => SortKind::CardDue,
|
||||||
|
@ -29,14 +29,14 @@ impl TryFrom<pb::SearchNode> for Node {
|
|||||||
} else {
|
} else {
|
||||||
escape_anki_wildcards(&s)
|
escape_anki_wildcards(&s)
|
||||||
})),
|
})),
|
||||||
Filter::Note(s) => Node::Search(SearchNode::NoteType(escape_anki_wildcards(&s))),
|
Filter::Note(s) => Node::Search(SearchNode::Notetype(escape_anki_wildcards(&s))),
|
||||||
Filter::Template(u) => {
|
Filter::Template(u) => {
|
||||||
Node::Search(SearchNode::CardTemplate(TemplateKind::Ordinal(u as u16)))
|
Node::Search(SearchNode::CardTemplate(TemplateKind::Ordinal(u as u16)))
|
||||||
}
|
}
|
||||||
Filter::Nid(nid) => Node::Search(SearchNode::NoteIds(nid.to_string())),
|
Filter::Nid(nid) => Node::Search(SearchNode::NoteIds(nid.to_string())),
|
||||||
Filter::Nids(nids) => Node::Search(SearchNode::NoteIds(nids.into_id_string())),
|
Filter::Nids(nids) => Node::Search(SearchNode::NoteIds(nids.into_id_string())),
|
||||||
Filter::Dupe(dupe) => Node::Search(SearchNode::Duplicates {
|
Filter::Dupe(dupe) => Node::Search(SearchNode::Duplicates {
|
||||||
note_type_id: dupe.notetype_id.into(),
|
notetype_id: dupe.notetype_id.into(),
|
||||||
text: dupe.first_field,
|
text: dupe.first_field,
|
||||||
}),
|
}),
|
||||||
Filter::FieldName(s) => Node::Search(SearchNode::SingleField {
|
Filter::FieldName(s) => Node::Search(SearchNode::SingleField {
|
||||||
|
@ -12,7 +12,7 @@ use crate::{
|
|||||||
collection::Collection,
|
collection::Collection,
|
||||||
decks::{Deck, DeckId},
|
decks::{Deck, DeckId},
|
||||||
notes::Note,
|
notes::Note,
|
||||||
notetype::{CardTemplate, NoteType, NoteTypeKind},
|
notetype::{CardTemplate, Notetype, NotetypeKind},
|
||||||
scheduler::{timespan::time_span, timing::SchedTimingToday},
|
scheduler::{timespan::time_span, timing::SchedTimingToday},
|
||||||
template::RenderedNode,
|
template::RenderedNode,
|
||||||
text::{extract_av_tags, html_to_text_line},
|
text::{extract_av_tags, html_to_text_line},
|
||||||
@ -55,7 +55,7 @@ struct RowContext<'a> {
|
|||||||
col: &'a Collection,
|
col: &'a Collection,
|
||||||
card: Card,
|
card: Card,
|
||||||
note: Note,
|
note: Note,
|
||||||
notetype: Arc<NoteType>,
|
notetype: Arc<Notetype>,
|
||||||
deck: Option<Deck>,
|
deck: Option<Deck>,
|
||||||
original_deck: Option<Option<Deck>>,
|
original_deck: Option<Option<Deck>>,
|
||||||
tr: &'a I18n,
|
tr: &'a I18n,
|
||||||
@ -94,7 +94,7 @@ impl Collection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RenderContext {
|
impl RenderContext {
|
||||||
fn new(col: &mut Collection, card: &Card, note: &Note, notetype: &NoteType) -> Result<Self> {
|
fn new(col: &mut Collection, card: &Card, note: &Note, notetype: &Notetype) -> Result<Self> {
|
||||||
let render = col.render_card(
|
let render = col.render_card(
|
||||||
note,
|
note,
|
||||||
card,
|
card,
|
||||||
@ -296,8 +296,8 @@ impl<'a> RowContext<'a> {
|
|||||||
fn template_str(&self) -> Result<String> {
|
fn template_str(&self) -> Result<String> {
|
||||||
let name = &self.template()?.name;
|
let name = &self.template()?.name;
|
||||||
Ok(match self.notetype.config.kind() {
|
Ok(match self.notetype.config.kind() {
|
||||||
NoteTypeKind::Normal => name.to_owned(),
|
NotetypeKind::Normal => name.to_owned(),
|
||||||
NoteTypeKind::Cloze => format!("{} {}", name, self.card.template_idx + 1),
|
NotetypeKind::Cloze => format!("{} {}", name, self.card.template_idx + 1),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ use crate::log::Logger;
|
|||||||
use crate::types::Usn;
|
use crate::types::Usn;
|
||||||
use crate::{
|
use crate::{
|
||||||
decks::{Deck, DeckId},
|
decks::{Deck, DeckId},
|
||||||
notetype::{NoteType, NoteTypeId},
|
notetype::{Notetype, NotetypeId},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
storage::SqliteStorage,
|
storage::SqliteStorage,
|
||||||
undo::UndoManager,
|
undo::UndoManager,
|
||||||
@ -62,7 +62,7 @@ pub fn open_test_collection_with_server(server: bool) -> Collection {
|
|||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct CollectionState {
|
pub struct CollectionState {
|
||||||
pub(crate) undo: UndoManager,
|
pub(crate) undo: UndoManager,
|
||||||
pub(crate) notetype_cache: HashMap<NoteTypeId, Arc<NoteType>>,
|
pub(crate) notetype_cache: HashMap<NotetypeId, Arc<Notetype>>,
|
||||||
pub(crate) deck_cache: HashMap<DeckId, Arc<Deck>>,
|
pub(crate) deck_cache: HashMap<DeckId, Arc<Deck>>,
|
||||||
pub(crate) card_queues: Option<CardQueues>,
|
pub(crate) card_queues: Option<CardQueues>,
|
||||||
/// True if legacy Python code has executed SQL that has modified the
|
/// True if legacy Python code has executed SQL that has modified the
|
||||||
|
@ -29,7 +29,7 @@ impl Collection {
|
|||||||
self.remove_config_prefix(&build_aux_deck_key(ntid, ""))
|
self.remove_config_prefix(&build_aux_deck_key(ntid, ""))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_last_notetype_for_deck(&self, id: DeckId) -> Option<NoteTypeId> {
|
pub(crate) fn get_last_notetype_for_deck(&self, id: DeckId) -> Option<NotetypeId> {
|
||||||
let key = DeckConfigKey::LastNotetype.for_deck(id);
|
let key = DeckConfigKey::LastNotetype.for_deck(id);
|
||||||
self.get_config_optional(key.as_str())
|
self.get_config_optional(key.as_str())
|
||||||
}
|
}
|
||||||
@ -37,7 +37,7 @@ impl Collection {
|
|||||||
pub(crate) fn set_last_notetype_for_deck(
|
pub(crate) fn set_last_notetype_for_deck(
|
||||||
&mut self,
|
&mut self,
|
||||||
did: DeckId,
|
did: DeckId,
|
||||||
ntid: NoteTypeId,
|
ntid: NotetypeId,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let key = DeckConfigKey::LastNotetype.for_deck(did);
|
let key = DeckConfigKey::LastNotetype.for_deck(did);
|
||||||
self.set_config(key.as_str(), &ntid)
|
self.set_config(key.as_str(), &ntid)
|
||||||
|
@ -51,7 +51,7 @@ pub(crate) enum ConfigKey {
|
|||||||
#[strum(to_string = "curDeck")]
|
#[strum(to_string = "curDeck")]
|
||||||
CurrentDeckId,
|
CurrentDeckId,
|
||||||
#[strum(to_string = "curModel")]
|
#[strum(to_string = "curModel")]
|
||||||
CurrentNoteTypeId,
|
CurrentNotetypeId,
|
||||||
#[strum(to_string = "lastUnburied")]
|
#[strum(to_string = "lastUnburied")]
|
||||||
LastUnburiedDay,
|
LastUnburiedDay,
|
||||||
#[strum(to_string = "collapseTime")]
|
#[strum(to_string = "collapseTime")]
|
||||||
@ -257,7 +257,7 @@ pub enum SortKind {
|
|||||||
#[serde(rename = "noteFld")]
|
#[serde(rename = "noteFld")]
|
||||||
NoteField,
|
NoteField,
|
||||||
#[serde(rename = "note")]
|
#[serde(rename = "note")]
|
||||||
NoteType,
|
Notetype,
|
||||||
NoteTags,
|
NoteTags,
|
||||||
CardMod,
|
CardMod,
|
||||||
CardReps,
|
CardReps,
|
||||||
|
@ -11,42 +11,42 @@ use strum::IntoStaticStr;
|
|||||||
/// write/sync.
|
/// write/sync.
|
||||||
#[derive(Debug, Clone, Copy, IntoStaticStr)]
|
#[derive(Debug, Clone, Copy, IntoStaticStr)]
|
||||||
#[strum(serialize_all = "camelCase")]
|
#[strum(serialize_all = "camelCase")]
|
||||||
enum NoteTypeConfigKey {
|
enum NotetypeConfigKey {
|
||||||
#[strum(to_string = "lastDeck")]
|
#[strum(to_string = "lastDeck")]
|
||||||
LastDeckAddedTo,
|
LastDeckAddedTo,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NoteTypeConfigKey {
|
impl NotetypeConfigKey {
|
||||||
fn for_notetype(self, ntid: NoteTypeId) -> String {
|
fn for_notetype(self, ntid: NotetypeId) -> String {
|
||||||
build_aux_notetype_key(ntid, <&'static str>::from(self))
|
build_aux_notetype_key(ntid, <&'static str>::from(self))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Collection {
|
impl Collection {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) fn get_current_notetype_id(&self) -> Option<NoteTypeId> {
|
pub(crate) fn get_current_notetype_id(&self) -> Option<NotetypeId> {
|
||||||
self.get_config_optional(ConfigKey::CurrentNoteTypeId)
|
self.get_config_optional(ConfigKey::CurrentNotetypeId)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_current_notetype_id(&mut self, ntid: NoteTypeId) -> Result<()> {
|
pub(crate) fn set_current_notetype_id(&mut self, ntid: NotetypeId) -> Result<()> {
|
||||||
self.set_config(ConfigKey::CurrentNoteTypeId, &ntid)
|
self.set_config(ConfigKey::CurrentNotetypeId, &ntid)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn clear_aux_config_for_notetype(&self, ntid: NoteTypeId) -> Result<()> {
|
pub(crate) fn clear_aux_config_for_notetype(&self, ntid: NotetypeId) -> Result<()> {
|
||||||
self.remove_config_prefix(&build_aux_notetype_key(ntid, ""))
|
self.remove_config_prefix(&build_aux_notetype_key(ntid, ""))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_last_deck_added_to_for_notetype(&self, id: NoteTypeId) -> Option<DeckId> {
|
pub(crate) fn get_last_deck_added_to_for_notetype(&self, id: NotetypeId) -> Option<DeckId> {
|
||||||
let key = NoteTypeConfigKey::LastDeckAddedTo.for_notetype(id);
|
let key = NotetypeConfigKey::LastDeckAddedTo.for_notetype(id);
|
||||||
self.get_config_optional(key.as_str())
|
self.get_config_optional(key.as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_last_deck_for_notetype(&mut self, id: NoteTypeId, did: DeckId) -> Result<()> {
|
pub(crate) fn set_last_deck_for_notetype(&mut self, id: NotetypeId, did: DeckId) -> Result<()> {
|
||||||
let key = NoteTypeConfigKey::LastDeckAddedTo.for_notetype(id);
|
let key = NotetypeConfigKey::LastDeckAddedTo.for_notetype(id);
|
||||||
self.set_config(key.as_str(), &did)
|
self.set_config(key.as_str(), &did)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_aux_notetype_key(ntid: NoteTypeId, key: &str) -> String {
|
fn build_aux_notetype_key(ntid: NotetypeId, key: &str) -> String {
|
||||||
format!("_nt_{ntid}_{key}", ntid = ntid, key = key)
|
format!("_nt_{ntid}_{key}", ntid = ntid, key = key)
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@ use crate::{
|
|||||||
err::{AnkiError, DbErrorKind, Result},
|
err::{AnkiError, DbErrorKind, Result},
|
||||||
i18n::I18n,
|
i18n::I18n,
|
||||||
notetype::{
|
notetype::{
|
||||||
all_stock_notetypes, AlreadyGeneratedCardInfo, CardGenContext, NoteType, NoteTypeId,
|
all_stock_notetypes, AlreadyGeneratedCardInfo, CardGenContext, Notetype, NotetypeId,
|
||||||
NoteTypeKind,
|
NotetypeKind,
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
timestamp::{TimestampMillis, TimestampSecs},
|
timestamp::{TimestampMillis, TimestampSecs},
|
||||||
@ -322,10 +322,10 @@ impl Collection {
|
|||||||
|
|
||||||
fn remove_cards_without_template(
|
fn remove_cards_without_template(
|
||||||
&mut self,
|
&mut self,
|
||||||
nt: &NoteType,
|
nt: &Notetype,
|
||||||
cards: &[AlreadyGeneratedCardInfo],
|
cards: &[AlreadyGeneratedCardInfo],
|
||||||
) -> Result<usize> {
|
) -> Result<usize> {
|
||||||
if nt.config.kind() == NoteTypeKind::Cloze {
|
if nt.config.kind() == NotetypeKind::Cloze {
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
}
|
}
|
||||||
let mut removed = 0;
|
let mut removed = 0;
|
||||||
@ -343,8 +343,8 @@ impl Collection {
|
|||||||
&mut self,
|
&mut self,
|
||||||
stamp: TimestampMillis,
|
stamp: TimestampMillis,
|
||||||
field_count: usize,
|
field_count: usize,
|
||||||
previous_id: NoteTypeId,
|
previous_id: NotetypeId,
|
||||||
) -> Result<Arc<NoteType>> {
|
) -> Result<Arc<Notetype>> {
|
||||||
debug!(self.log, "create recovery notetype");
|
debug!(self.log, "create recovery notetype");
|
||||||
let extra_cards_required = self
|
let extra_cards_required = self
|
||||||
.storage
|
.storage
|
||||||
|
@ -349,7 +349,7 @@ where
|
|||||||
renamed: &HashMap<String, String>,
|
renamed: &HashMap<String, String>,
|
||||||
) -> Result<HashSet<String>> {
|
) -> Result<HashSet<String>> {
|
||||||
let mut referenced_files = HashSet::new();
|
let mut referenced_files = HashSet::new();
|
||||||
let note_types = self.ctx.get_all_notetypes()?;
|
let notetypes = self.ctx.get_all_notetypes()?;
|
||||||
let mut collection_modified = false;
|
let mut collection_modified = false;
|
||||||
|
|
||||||
let nids = self.ctx.search_notes("")?;
|
let nids = self.ctx.search_notes("")?;
|
||||||
@ -360,7 +360,7 @@ where
|
|||||||
self.fire_progress_cb()?;
|
self.fire_progress_cb()?;
|
||||||
}
|
}
|
||||||
let mut note = self.ctx.storage.get_note(nid)?.unwrap();
|
let mut note = self.ctx.storage.get_note(nid)?.unwrap();
|
||||||
let nt = note_types
|
let nt = notetypes
|
||||||
.get(¬e.notetype_id)
|
.get(¬e.notetype_id)
|
||||||
.ok_or_else(|| AnkiError::DbError {
|
.ok_or_else(|| AnkiError::DbError {
|
||||||
info: "missing note type".to_string(),
|
info: "missing note type".to_string(),
|
||||||
|
@ -8,7 +8,7 @@ use crate::{
|
|||||||
decks::DeckId,
|
decks::DeckId,
|
||||||
define_newtype,
|
define_newtype,
|
||||||
err::{AnkiError, Result},
|
err::{AnkiError, Result},
|
||||||
notetype::{CardGenContext, NoteField, NoteType, NoteTypeId},
|
notetype::{CardGenContext, NoteField, Notetype, NotetypeId},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
template::field_is_empty,
|
template::field_is_empty,
|
||||||
text::{ensure_string_in_nfc, normalize_to_nfc, strip_html_preserving_media_filenames},
|
text::{ensure_string_in_nfc, normalize_to_nfc, strip_html_preserving_media_filenames},
|
||||||
@ -39,7 +39,7 @@ pub(crate) struct TransformNoteOutput {
|
|||||||
pub struct Note {
|
pub struct Note {
|
||||||
pub id: NoteId,
|
pub id: NoteId,
|
||||||
pub guid: String,
|
pub guid: String,
|
||||||
pub notetype_id: NoteTypeId,
|
pub notetype_id: NotetypeId,
|
||||||
pub mtime: TimestampSecs,
|
pub mtime: TimestampSecs,
|
||||||
pub usn: Usn,
|
pub usn: Usn,
|
||||||
pub tags: Vec<String>,
|
pub tags: Vec<String>,
|
||||||
@ -66,7 +66,7 @@ impl NoteTags {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Note {
|
impl Note {
|
||||||
pub(crate) fn new(notetype: &NoteType) -> Self {
|
pub(crate) fn new(notetype: &Notetype) -> Self {
|
||||||
Note {
|
Note {
|
||||||
id: NoteId(0),
|
id: NoteId(0),
|
||||||
guid: guid(),
|
guid: guid(),
|
||||||
@ -84,7 +84,7 @@ impl Note {
|
|||||||
pub(crate) fn new_from_storage(
|
pub(crate) fn new_from_storage(
|
||||||
id: NoteId,
|
id: NoteId,
|
||||||
guid: String,
|
guid: String,
|
||||||
notetype_id: NoteTypeId,
|
notetype_id: NotetypeId,
|
||||||
mtime: TimestampSecs,
|
mtime: TimestampSecs,
|
||||||
usn: Usn,
|
usn: Usn,
|
||||||
tags: Vec<String>,
|
tags: Vec<String>,
|
||||||
@ -134,7 +134,7 @@ impl Note {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Prepare note for saving to the database. Does not mark it as modified.
|
/// Prepare note for saving to the database. Does not mark it as modified.
|
||||||
pub fn prepare_for_update(&mut self, nt: &NoteType, normalize_text: bool) -> Result<()> {
|
pub fn prepare_for_update(&mut self, nt: &Notetype, normalize_text: bool) -> Result<()> {
|
||||||
assert!(nt.id == self.notetype_id);
|
assert!(nt.id == self.notetype_id);
|
||||||
let notetype_field_count = nt.fields.len().max(1);
|
let notetype_field_count = nt.fields.len().max(1);
|
||||||
if notetype_field_count != self.fields.len() {
|
if notetype_field_count != self.fields.len() {
|
||||||
@ -210,7 +210,7 @@ impl Note {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Pad or merge fields to match note type.
|
/// Pad or merge fields to match note type.
|
||||||
pub(crate) fn fix_field_count(&mut self, nt: &NoteType) {
|
pub(crate) fn fix_field_count(&mut self, nt: &Notetype) {
|
||||||
while self.fields.len() < nt.fields.len() {
|
while self.fields.len() < nt.fields.len() {
|
||||||
self.fields.push("".into())
|
self.fields.push("".into())
|
||||||
}
|
}
|
||||||
@ -243,7 +243,7 @@ impl From<pb::Note> for Note {
|
|||||||
Note {
|
Note {
|
||||||
id: NoteId(n.id),
|
id: NoteId(n.id),
|
||||||
guid: n.guid,
|
guid: n.guid,
|
||||||
notetype_id: NoteTypeId(n.notetype_id),
|
notetype_id: NotetypeId(n.notetype_id),
|
||||||
mtime: TimestampSecs(n.mtime_secs as i64),
|
mtime: TimestampSecs(n.mtime_secs as i64),
|
||||||
usn: Usn(n.usn),
|
usn: Usn(n.usn),
|
||||||
tags: n.tags,
|
tags: n.tags,
|
||||||
@ -388,7 +388,7 @@ impl Collection {
|
|||||||
&mut self,
|
&mut self,
|
||||||
note: &mut Note,
|
note: &mut Note,
|
||||||
original: &Note,
|
original: &Note,
|
||||||
nt: &NoteType,
|
nt: &Notetype,
|
||||||
usn: Usn,
|
usn: Usn,
|
||||||
mark_note_modified: bool,
|
mark_note_modified: bool,
|
||||||
normalize_text: bool,
|
normalize_text: bool,
|
||||||
@ -444,7 +444,7 @@ impl Collection {
|
|||||||
mut transformer: F,
|
mut transformer: F,
|
||||||
) -> Result<usize>
|
) -> Result<usize>
|
||||||
where
|
where
|
||||||
F: FnMut(&mut Note, &NoteType) -> Result<TransformNoteOutput>,
|
F: FnMut(&mut Note, &Notetype) -> Result<TransformNoteOutput>,
|
||||||
{
|
{
|
||||||
let nids_by_notetype = self.storage.note_ids_by_notetype(nids)?;
|
let nids_by_notetype = self.storage.note_ids_by_notetype(nids)?;
|
||||||
let norm = self.get_bool(BoolKey::NormalizeNoteText);
|
let norm = self.get_bool(BoolKey::NormalizeNoteText);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// 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
|
||||||
|
|
||||||
use super::NoteType;
|
use super::Notetype;
|
||||||
use crate::{
|
use crate::{
|
||||||
card::{Card, CardId},
|
card::{Card, CardId},
|
||||||
cloze::add_cloze_numbers_in_string,
|
cloze::add_cloze_numbers_in_string,
|
||||||
@ -10,7 +10,7 @@ use crate::{
|
|||||||
decks::DeckId,
|
decks::DeckId,
|
||||||
err::{AnkiError, Result},
|
err::{AnkiError, Result},
|
||||||
notes::{Note, NoteId},
|
notes::{Note, NoteId},
|
||||||
notetype::NoteTypeKind,
|
notetype::NotetypeKind,
|
||||||
template::ParsedTemplate,
|
template::ParsedTemplate,
|
||||||
types::Usn,
|
types::Usn,
|
||||||
};
|
};
|
||||||
@ -46,7 +46,7 @@ pub(crate) struct SingleCardGenContext {
|
|||||||
/// and where they should be placed.
|
/// and where they should be placed.
|
||||||
pub(crate) struct CardGenContext<'a> {
|
pub(crate) struct CardGenContext<'a> {
|
||||||
pub usn: Usn,
|
pub usn: Usn,
|
||||||
pub notetype: &'a NoteType,
|
pub notetype: &'a Notetype,
|
||||||
cards: Vec<SingleCardGenContext>,
|
cards: Vec<SingleCardGenContext>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ pub(crate) struct CardGenCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CardGenContext<'_> {
|
impl CardGenContext<'_> {
|
||||||
pub(crate) fn new(nt: &NoteType, usn: Usn) -> CardGenContext<'_> {
|
pub(crate) fn new(nt: &Notetype, usn: Usn) -> CardGenContext<'_> {
|
||||||
CardGenContext {
|
CardGenContext {
|
||||||
usn,
|
usn,
|
||||||
notetype: &nt,
|
notetype: &nt,
|
||||||
@ -97,8 +97,8 @@ impl CardGenContext<'_> {
|
|||||||
) -> Vec<CardToGenerate> {
|
) -> Vec<CardToGenerate> {
|
||||||
let extracted = extract_data_from_existing_cards(existing);
|
let extracted = extract_data_from_existing_cards(existing);
|
||||||
let cards = match self.notetype.config.kind() {
|
let cards = match self.notetype.config.kind() {
|
||||||
NoteTypeKind::Normal => self.new_cards_required_normal(note, &extracted),
|
NotetypeKind::Normal => self.new_cards_required_normal(note, &extracted),
|
||||||
NoteTypeKind::Cloze => self.new_cards_required_cloze(note, &extracted),
|
NotetypeKind::Cloze => self.new_cards_required_cloze(note, &extracted),
|
||||||
};
|
};
|
||||||
if extracted.existing_ords.is_empty() && cards.is_empty() && ensure_not_empty {
|
if extracted.existing_ords.is_empty() && cards.is_empty() && ensure_not_empty {
|
||||||
// if there are no existing cards and no cards will be generated,
|
// if there are no existing cards and no cards will be generated,
|
||||||
@ -260,7 +260,7 @@ impl Collection {
|
|||||||
let by_note = group_generated_cards_by_note(existing_cards);
|
let by_note = group_generated_cards_by_note(existing_cards);
|
||||||
let mut cache = CardGenCache::default();
|
let mut cache = CardGenCache::default();
|
||||||
for (nid, existing_cards) in by_note {
|
for (nid, existing_cards) in by_note {
|
||||||
if ctx.notetype.config.kind() == NoteTypeKind::Normal
|
if ctx.notetype.config.kind() == NotetypeKind::Normal
|
||||||
&& existing_cards.len() == ctx.notetype.templates.len()
|
&& existing_cards.len() == ctx.notetype.templates.len()
|
||||||
{
|
{
|
||||||
// in a normal note type, if card count matches template count, we don't need
|
// in a normal note type, if card count matches template count, we don't need
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// 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
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
cardgen::group_generated_cards_by_note, CardGenContext, NoteType, NoteTypeId, NoteTypeKind,
|
cardgen::group_generated_cards_by_note, CardGenContext, Notetype, NotetypeId, NotetypeKind,
|
||||||
};
|
};
|
||||||
use crate::{card::CardId, collection::Collection, err::Result, notes::NoteId};
|
use crate::{card::CardId, collection::Collection, err::Result, notes::NoteId};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
@ -16,7 +16,7 @@ pub struct EmptyCardsForNote {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Collection {
|
impl Collection {
|
||||||
fn empty_cards_for_notetype(&self, nt: &NoteType) -> Result<Vec<EmptyCardsForNote>> {
|
fn empty_cards_for_notetype(&self, nt: &Notetype) -> Result<Vec<EmptyCardsForNote>> {
|
||||||
let ctx = CardGenContext::new(nt, self.usn()?);
|
let ctx = CardGenContext::new(nt, self.usn()?);
|
||||||
let existing_cards = self.storage.existing_cards_for_notetype(nt.id)?;
|
let existing_cards = self.storage.existing_cards_for_notetype(nt.id)?;
|
||||||
let by_note = group_generated_cards_by_note(existing_cards);
|
let by_note = group_generated_cards_by_note(existing_cards);
|
||||||
@ -49,7 +49,7 @@ impl Collection {
|
|||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn empty_cards(&mut self) -> Result<Vec<(NoteTypeId, Vec<EmptyCardsForNote>)>> {
|
pub fn empty_cards(&mut self) -> Result<Vec<(NotetypeId, Vec<EmptyCardsForNote>)>> {
|
||||||
self.storage
|
self.storage
|
||||||
.get_all_notetype_names()?
|
.get_all_notetype_names()?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -63,7 +63,7 @@ impl Collection {
|
|||||||
/// Create a report on empty cards. Mutates the provided data to sort ordinals.
|
/// Create a report on empty cards. Mutates the provided data to sort ordinals.
|
||||||
pub fn empty_cards_report(
|
pub fn empty_cards_report(
|
||||||
&mut self,
|
&mut self,
|
||||||
empty: &mut [(NoteTypeId, Vec<EmptyCardsForNote>)],
|
empty: &mut [(NotetypeId, Vec<EmptyCardsForNote>)],
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let nts = self.get_all_notetypes()?;
|
let nts = self.get_all_notetypes()?;
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
@ -81,7 +81,7 @@ impl Collection {
|
|||||||
note.empty.sort_unstable();
|
note.empty.sort_unstable();
|
||||||
let templates = match nt.config.kind() {
|
let templates = match nt.config.kind() {
|
||||||
// "Front, Back"
|
// "Front, Back"
|
||||||
NoteTypeKind::Normal => note
|
NotetypeKind::Normal => note
|
||||||
.empty
|
.empty
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(ord, _)| {
|
.map(|(ord, _)| {
|
||||||
@ -93,7 +93,7 @@ impl Collection {
|
|||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", "),
|
.join(", "),
|
||||||
// "Cloze 1, 3"
|
// "Cloze 1, 3"
|
||||||
NoteTypeKind::Cloze => format!(
|
NotetypeKind::Cloze => format!(
|
||||||
"{} {}",
|
"{} {}",
|
||||||
self.tr.notetypes_cloze_name(),
|
self.tr.notetypes_cloze_name(),
|
||||||
note.empty
|
note.empty
|
||||||
|
@ -11,14 +11,14 @@ mod stock;
|
|||||||
mod templates;
|
mod templates;
|
||||||
|
|
||||||
pub use crate::backend_proto::{
|
pub use crate::backend_proto::{
|
||||||
card_requirement::Kind as CardRequirementKind, note_type_config::Kind as NoteTypeKind,
|
card_requirement::Kind as CardRequirementKind, notetype_config::Kind as NotetypeKind,
|
||||||
CardRequirement, CardTemplateConfig, NoteFieldConfig, NoteType as NoteTypeProto,
|
CardRequirement, CardTemplateConfig, NoteFieldConfig, Notetype as NotetypeProto,
|
||||||
NoteTypeConfig,
|
NotetypeConfig,
|
||||||
};
|
};
|
||||||
pub(crate) use cardgen::{AlreadyGeneratedCardInfo, CardGenContext};
|
pub(crate) use cardgen::{AlreadyGeneratedCardInfo, CardGenContext};
|
||||||
pub use fields::NoteField;
|
pub use fields::NoteField;
|
||||||
pub(crate) use render::RenderCardOutput;
|
pub(crate) use render::RenderCardOutput;
|
||||||
pub use schema11::{CardTemplateSchema11, NoteFieldSchema11, NoteTypeSchema11};
|
pub use schema11::{CardTemplateSchema11, NoteFieldSchema11, NotetypeSchema11};
|
||||||
pub use stock::all_stock_notetypes;
|
pub use stock::all_stock_notetypes;
|
||||||
pub use templates::CardTemplate;
|
pub use templates::CardTemplate;
|
||||||
|
|
||||||
@ -40,33 +40,33 @@ use std::{
|
|||||||
};
|
};
|
||||||
use unicase::UniCase;
|
use unicase::UniCase;
|
||||||
|
|
||||||
define_newtype!(NoteTypeId, i64);
|
define_newtype!(NotetypeId, i64);
|
||||||
|
|
||||||
pub(crate) const DEFAULT_CSS: &str = include_str!("styling.css");
|
pub(crate) const DEFAULT_CSS: &str = include_str!("styling.css");
|
||||||
pub(crate) const DEFAULT_LATEX_HEADER: &str = include_str!("header.tex");
|
pub(crate) const DEFAULT_LATEX_HEADER: &str = include_str!("header.tex");
|
||||||
pub(crate) const DEFAULT_LATEX_FOOTER: &str = r"\end{document}";
|
pub(crate) const DEFAULT_LATEX_FOOTER: &str = r"\end{document}";
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct NoteType {
|
pub struct Notetype {
|
||||||
pub id: NoteTypeId,
|
pub id: NotetypeId,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub mtime_secs: TimestampSecs,
|
pub mtime_secs: TimestampSecs,
|
||||||
pub usn: Usn,
|
pub usn: Usn,
|
||||||
pub fields: Vec<NoteField>,
|
pub fields: Vec<NoteField>,
|
||||||
pub templates: Vec<CardTemplate>,
|
pub templates: Vec<CardTemplate>,
|
||||||
pub config: NoteTypeConfig,
|
pub config: NotetypeConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for NoteType {
|
impl Default for Notetype {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
NoteType {
|
Notetype {
|
||||||
id: NoteTypeId(0),
|
id: NotetypeId(0),
|
||||||
name: "".into(),
|
name: "".into(),
|
||||||
mtime_secs: TimestampSecs(0),
|
mtime_secs: TimestampSecs(0),
|
||||||
usn: Usn(0),
|
usn: Usn(0),
|
||||||
fields: vec![],
|
fields: vec![],
|
||||||
templates: vec![],
|
templates: vec![],
|
||||||
config: NoteTypeConfig {
|
config: NotetypeConfig {
|
||||||
css: DEFAULT_CSS.into(),
|
css: DEFAULT_CSS.into(),
|
||||||
latex_pre: DEFAULT_LATEX_HEADER.into(),
|
latex_pre: DEFAULT_LATEX_HEADER.into(),
|
||||||
latex_post: DEFAULT_LATEX_FOOTER.into(),
|
latex_post: DEFAULT_LATEX_FOOTER.into(),
|
||||||
@ -76,7 +76,7 @@ impl Default for NoteType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NoteType {
|
impl Notetype {
|
||||||
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 {
|
||||||
@ -105,7 +105,7 @@ impl NoteType {
|
|||||||
/// Return the template for the given card ordinal. Cloze notetypes
|
/// Return the template for the given card ordinal. Cloze notetypes
|
||||||
/// always return the first and only template.
|
/// always return the first and only template.
|
||||||
pub fn get_template(&self, card_ord: u16) -> Result<&CardTemplate> {
|
pub fn get_template(&self, card_ord: u16) -> Result<&CardTemplate> {
|
||||||
let template = if self.config.kind() == NoteTypeKind::Cloze {
|
let template = if self.config.kind() == NotetypeKind::Cloze {
|
||||||
self.templates.get(0)
|
self.templates.get(0)
|
||||||
} else {
|
} else {
|
||||||
self.templates.get(card_ord as usize)
|
self.templates.get(card_ord as usize)
|
||||||
@ -218,7 +218,7 @@ impl NoteType {
|
|||||||
self.prepare_for_update(None)
|
self.prepare_for_update(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn prepare_for_update(&mut self, existing: Option<&NoteType>) -> Result<()> {
|
pub(crate) fn prepare_for_update(&mut self, existing: Option<&Notetype>) -> Result<()> {
|
||||||
if self.fields.is_empty() {
|
if self.fields.is_empty() {
|
||||||
return Err(AnkiError::invalid_input("1 field required"));
|
return Err(AnkiError::invalid_input("1 field required"));
|
||||||
}
|
}
|
||||||
@ -266,7 +266,7 @@ impl NoteType {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renamed_and_removed_fields(&self, current: &NoteType) -> HashMap<String, Option<String>> {
|
fn renamed_and_removed_fields(&self, current: &Notetype) -> HashMap<String, Option<String>> {
|
||||||
let mut remaining_ords = HashSet::new();
|
let mut remaining_ords = HashSet::new();
|
||||||
// gather renames
|
// gather renames
|
||||||
let mut map: HashMap<String, Option<String>> = self
|
let mut map: HashMap<String, Option<String>> = self
|
||||||
@ -355,13 +355,13 @@ impl NoteType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_cloze(&self) -> bool {
|
pub(crate) fn is_cloze(&self) -> bool {
|
||||||
matches!(self.config.kind(), NoteTypeKind::Cloze)
|
matches!(self.config.kind(), NotetypeKind::Cloze)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<NoteType> for NoteTypeProto {
|
impl From<Notetype> for NotetypeProto {
|
||||||
fn from(nt: NoteType) -> Self {
|
fn from(nt: Notetype) -> Self {
|
||||||
NoteTypeProto {
|
NotetypeProto {
|
||||||
id: nt.id.0,
|
id: nt.id.0,
|
||||||
name: nt.name,
|
name: nt.name,
|
||||||
mtime_secs: nt.mtime_secs.0 as u32,
|
mtime_secs: nt.mtime_secs.0 as u32,
|
||||||
@ -375,7 +375,7 @@ impl From<NoteType> for NoteTypeProto {
|
|||||||
|
|
||||||
impl Collection {
|
impl Collection {
|
||||||
/// Add a new notetype, and allocate it an ID.
|
/// Add a new notetype, and allocate it an ID.
|
||||||
pub fn add_notetype(&mut self, nt: &mut NoteType) -> Result<()> {
|
pub fn add_notetype(&mut self, nt: &mut Notetype) -> Result<()> {
|
||||||
self.transact_no_undo(|col| {
|
self.transact_no_undo(|col| {
|
||||||
let usn = col.usn()?;
|
let usn = col.usn()?;
|
||||||
nt.set_modified(usn);
|
nt.set_modified(usn);
|
||||||
@ -383,7 +383,7 @@ impl Collection {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_notetype_inner(&mut self, nt: &mut NoteType, usn: Usn) -> Result<()> {
|
pub(crate) fn add_notetype_inner(&mut self, nt: &mut Notetype, usn: Usn) -> Result<()> {
|
||||||
nt.prepare_for_adding()?;
|
nt.prepare_for_adding()?;
|
||||||
self.ensure_notetype_name_unique(nt, usn)?;
|
self.ensure_notetype_name_unique(nt, usn)?;
|
||||||
self.storage.add_new_notetype(nt)
|
self.storage.add_new_notetype(nt)
|
||||||
@ -391,7 +391,7 @@ impl Collection {
|
|||||||
|
|
||||||
pub(crate) fn ensure_notetype_name_unique(
|
pub(crate) fn ensure_notetype_name_unique(
|
||||||
&self,
|
&self,
|
||||||
notetype: &mut NoteType,
|
notetype: &mut Notetype,
|
||||||
usn: Usn,
|
usn: Usn,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
loop {
|
loop {
|
||||||
@ -411,7 +411,7 @@ impl Collection {
|
|||||||
|
|
||||||
/// Saves changes to a note type. This will force a full sync if templates
|
/// Saves changes to a note type. This will force a full sync if templates
|
||||||
/// or fields have been added/removed/reordered.
|
/// or fields have been added/removed/reordered.
|
||||||
pub fn update_notetype(&mut self, nt: &mut NoteType, preserve_usn: bool) -> Result<()> {
|
pub fn update_notetype(&mut self, nt: &mut Notetype, preserve_usn: bool) -> Result<()> {
|
||||||
let existing = self.get_notetype(nt.id)?;
|
let existing = self.get_notetype(nt.id)?;
|
||||||
let norm = self.get_bool(BoolKey::NormalizeNoteText);
|
let norm = self.get_bool(BoolKey::NormalizeNoteText);
|
||||||
nt.prepare_for_update(existing.as_ref().map(AsRef::as_ref))?;
|
nt.prepare_for_update(existing.as_ref().map(AsRef::as_ref))?;
|
||||||
@ -447,7 +447,7 @@ impl Collection {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_notetype_by_name(&mut self, name: &str) -> Result<Option<Arc<NoteType>>> {
|
pub fn get_notetype_by_name(&mut self, name: &str) -> Result<Option<Arc<Notetype>>> {
|
||||||
if let Some(ntid) = self.storage.get_notetype_id(name)? {
|
if let Some(ntid) = self.storage.get_notetype_id(name)? {
|
||||||
self.get_notetype(ntid)
|
self.get_notetype(ntid)
|
||||||
} else {
|
} else {
|
||||||
@ -455,7 +455,7 @@ impl Collection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_notetype(&mut self, ntid: NoteTypeId) -> Result<Option<Arc<NoteType>>> {
|
pub fn get_notetype(&mut self, ntid: NotetypeId) -> Result<Option<Arc<Notetype>>> {
|
||||||
if let Some(nt) = self.state.notetype_cache.get(&ntid) {
|
if let Some(nt) = self.state.notetype_cache.get(&ntid) {
|
||||||
return Ok(Some(nt.clone()));
|
return Ok(Some(nt.clone()));
|
||||||
}
|
}
|
||||||
@ -468,7 +468,7 @@ impl Collection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_all_notetypes(&mut self) -> Result<HashMap<NoteTypeId, Arc<NoteType>>> {
|
pub fn get_all_notetypes(&mut self) -> Result<HashMap<NotetypeId, Arc<Notetype>>> {
|
||||||
self.storage
|
self.storage
|
||||||
.get_all_notetype_names()?
|
.get_all_notetype_names()?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -481,7 +481,7 @@ impl Collection {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_notetype(&mut self, ntid: NoteTypeId) -> Result<()> {
|
pub fn remove_notetype(&mut self, ntid: NotetypeId) -> Result<()> {
|
||||||
// fixme: currently the storage layer is taking care of removing the notes and cards,
|
// fixme: currently the storage layer is taking care of removing the notes and cards,
|
||||||
// but we need to do it in this layer in the future for undo handling
|
// but we need to do it in this layer in the future for undo handling
|
||||||
self.transact_no_undo(|col| {
|
self.transact_no_undo(|col| {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// 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
|
||||||
|
|
||||||
use super::{CardTemplate, NoteType, NoteTypeKind};
|
use super::{CardTemplate, Notetype, NotetypeKind};
|
||||||
use crate::{
|
use crate::{
|
||||||
card::{Card, CardId},
|
card::{Card, CardId},
|
||||||
collection::Collection,
|
collection::Collection,
|
||||||
@ -32,8 +32,8 @@ impl Collection {
|
|||||||
.get_notetype(note.notetype_id)?
|
.get_notetype(note.notetype_id)?
|
||||||
.ok_or_else(|| AnkiError::invalid_input("no such notetype"))?;
|
.ok_or_else(|| AnkiError::invalid_input("no such notetype"))?;
|
||||||
let template = match nt.config.kind() {
|
let template = match nt.config.kind() {
|
||||||
NoteTypeKind::Normal => nt.templates.get(card.template_idx as usize),
|
NotetypeKind::Normal => nt.templates.get(card.template_idx as usize),
|
||||||
NoteTypeKind::Cloze => nt.templates.get(0),
|
NotetypeKind::Cloze => nt.templates.get(0),
|
||||||
}
|
}
|
||||||
.ok_or_else(|| AnkiError::invalid_input("missing template"))?;
|
.ok_or_else(|| AnkiError::invalid_input("missing template"))?;
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ impl Collection {
|
|||||||
&mut self,
|
&mut self,
|
||||||
note: &Note,
|
note: &Note,
|
||||||
card: &Card,
|
card: &Card,
|
||||||
nt: &NoteType,
|
nt: &Notetype,
|
||||||
template: &CardTemplate,
|
template: &CardTemplate,
|
||||||
browser: bool,
|
browser: bool,
|
||||||
) -> Result<RenderCardOutput> {
|
) -> Result<RenderCardOutput> {
|
||||||
@ -127,7 +127,7 @@ impl Collection {
|
|||||||
map: &mut HashMap<&str, Cow<str>>,
|
map: &mut HashMap<&str, Cow<str>>,
|
||||||
note: &Note,
|
note: &Note,
|
||||||
card: &Card,
|
card: &Card,
|
||||||
nt: &NoteType,
|
nt: &Notetype,
|
||||||
template: &CardTemplate,
|
template: &CardTemplate,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let tags = note.tags.join(" ");
|
let tags = note.tags.join(" ");
|
||||||
@ -165,7 +165,7 @@ fn flag_name(n: u8) -> &'static str {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill_empty_fields(note: &mut Note, qfmt: &str, nt: &NoteType, tr: &I18n) {
|
fn fill_empty_fields(note: &mut Note, qfmt: &str, nt: &Notetype, tr: &I18n) {
|
||||||
if let Ok(tmpl) = ParsedTemplate::from_text(qfmt) {
|
if let Ok(tmpl) = ParsedTemplate::from_text(qfmt) {
|
||||||
let cloze_fields = tmpl.cloze_fields();
|
let cloze_fields = tmpl.cloze_fields();
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
decks::DeckId,
|
decks::DeckId,
|
||||||
notetype::{
|
notetype::{
|
||||||
CardRequirement, CardTemplate, CardTemplateConfig, NoteField, NoteFieldConfig, NoteType,
|
CardRequirement, CardTemplate, CardTemplateConfig, NoteField, NoteFieldConfig, Notetype,
|
||||||
NoteTypeConfig,
|
NotetypeConfig,
|
||||||
},
|
},
|
||||||
serde::{default_on_invalid, deserialize_bool_from_anything, deserialize_number_from_string},
|
serde::{default_on_invalid, deserialize_bool_from_anything, deserialize_number_from_string},
|
||||||
timestamp::TimestampSecs,
|
timestamp::TimestampSecs,
|
||||||
@ -17,23 +17,23 @@ use serde_repr::{Deserialize_repr, Serialize_repr};
|
|||||||
use serde_tuple::Serialize_tuple;
|
use serde_tuple::Serialize_tuple;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use super::{CardRequirementKind, NoteTypeId};
|
use super::{CardRequirementKind, NotetypeId};
|
||||||
|
|
||||||
#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug, Clone)]
|
#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug, Clone)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum NoteTypeKind {
|
pub enum NotetypeKind {
|
||||||
Standard = 0,
|
Standard = 0,
|
||||||
Cloze = 1,
|
Cloze = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct NoteTypeSchema11 {
|
pub struct NotetypeSchema11 {
|
||||||
#[serde(deserialize_with = "deserialize_number_from_string")]
|
#[serde(deserialize_with = "deserialize_number_from_string")]
|
||||||
pub(crate) id: NoteTypeId,
|
pub(crate) id: NotetypeId,
|
||||||
pub(crate) name: String,
|
pub(crate) name: String,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub(crate) kind: NoteTypeKind,
|
pub(crate) kind: NotetypeKind,
|
||||||
#[serde(rename = "mod")]
|
#[serde(rename = "mod")]
|
||||||
pub(crate) mtime: TimestampSecs,
|
pub(crate) mtime: TimestampSecs,
|
||||||
pub(crate) usn: Usn,
|
pub(crate) usn: Usn,
|
||||||
@ -80,20 +80,20 @@ pub enum FieldRequirementKindSchema11 {
|
|||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NoteTypeSchema11 {
|
impl NotetypeSchema11 {
|
||||||
pub fn latex_uses_svg(&self) -> bool {
|
pub fn latex_uses_svg(&self) -> bool {
|
||||||
self.latexsvg
|
self.latexsvg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<NoteTypeSchema11> for NoteType {
|
impl From<NotetypeSchema11> for Notetype {
|
||||||
fn from(nt: NoteTypeSchema11) -> Self {
|
fn from(nt: NotetypeSchema11) -> Self {
|
||||||
NoteType {
|
Notetype {
|
||||||
id: nt.id,
|
id: nt.id,
|
||||||
name: nt.name,
|
name: nt.name,
|
||||||
mtime_secs: nt.mtime,
|
mtime_secs: nt.mtime,
|
||||||
usn: nt.usn,
|
usn: nt.usn,
|
||||||
config: NoteTypeConfig {
|
config: NotetypeConfig {
|
||||||
kind: nt.kind as i32,
|
kind: nt.kind as i32,
|
||||||
sort_field_idx: nt.sortf as u32,
|
sort_field_idx: nt.sortf as u32,
|
||||||
css: nt.css,
|
css: nt.css,
|
||||||
@ -133,16 +133,16 @@ fn bytes_to_other(bytes: &[u8]) -> HashMap<String, Value> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<NoteType> for NoteTypeSchema11 {
|
impl From<Notetype> for NotetypeSchema11 {
|
||||||
fn from(p: NoteType) -> Self {
|
fn from(p: Notetype) -> Self {
|
||||||
let c = p.config;
|
let c = p.config;
|
||||||
NoteTypeSchema11 {
|
NotetypeSchema11 {
|
||||||
id: p.id,
|
id: p.id,
|
||||||
name: p.name,
|
name: p.name,
|
||||||
kind: if c.kind == 1 {
|
kind: if c.kind == 1 {
|
||||||
NoteTypeKind::Cloze
|
NotetypeKind::Cloze
|
||||||
} else {
|
} else {
|
||||||
NoteTypeKind::Standard
|
NotetypeKind::Standard
|
||||||
},
|
},
|
||||||
mtime: p.mtime_secs,
|
mtime: p.mtime_secs,
|
||||||
usn: p.usn,
|
usn: p.usn,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// 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
|
||||||
|
|
||||||
use super::{CardGenContext, NoteType};
|
use super::{CardGenContext, Notetype};
|
||||||
use crate::{collection::Collection, err::Result};
|
use crate::{collection::Collection, err::Result};
|
||||||
|
|
||||||
/// True if any ordinals added, removed or reordered.
|
/// True if any ordinals added, removed or reordered.
|
||||||
@ -52,7 +52,7 @@ impl Collection {
|
|||||||
/// Caller must create transaction.
|
/// Caller must create transaction.
|
||||||
pub(crate) fn update_notes_for_changed_fields(
|
pub(crate) fn update_notes_for_changed_fields(
|
||||||
&mut self,
|
&mut self,
|
||||||
nt: &NoteType,
|
nt: &Notetype,
|
||||||
previous_field_count: usize,
|
previous_field_count: usize,
|
||||||
previous_sort_idx: u32,
|
previous_sort_idx: u32,
|
||||||
normalize_text: bool,
|
normalize_text: bool,
|
||||||
@ -106,7 +106,7 @@ impl Collection {
|
|||||||
/// Caller must create transaction.
|
/// Caller must create transaction.
|
||||||
pub(crate) fn update_cards_for_changed_templates(
|
pub(crate) fn update_cards_for_changed_templates(
|
||||||
&mut self,
|
&mut self,
|
||||||
nt: &NoteType,
|
nt: &Notetype,
|
||||||
previous_template_count: usize,
|
previous_template_count: usize,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ords: Vec<_> = nt.templates.iter().map(|f| f.ord).collect();
|
let ords: Vec<_> = nt.templates.iter().map(|f| f.ord).collect();
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
// 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
|
||||||
|
|
||||||
use super::NoteTypeKind;
|
use super::NotetypeKind;
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{ConfigEntry, ConfigKey},
|
config::{ConfigEntry, ConfigKey},
|
||||||
err::Result,
|
err::Result,
|
||||||
i18n::I18n,
|
i18n::I18n,
|
||||||
notetype::NoteType,
|
notetype::Notetype,
|
||||||
storage::SqliteStorage,
|
storage::SqliteStorage,
|
||||||
timestamp::TimestampSecs,
|
timestamp::TimestampSecs,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::backend_proto::stock_note_type::Kind;
|
use crate::backend_proto::stock_notetype::Kind;
|
||||||
|
|
||||||
impl SqliteStorage {
|
impl SqliteStorage {
|
||||||
pub(crate) fn add_stock_notetypes(&self, tr: &I18n) -> Result<()> {
|
pub(crate) fn add_stock_notetypes(&self, tr: &I18n) -> Result<()> {
|
||||||
@ -19,7 +19,7 @@ impl SqliteStorage {
|
|||||||
self.add_new_notetype(&mut nt)?;
|
self.add_new_notetype(&mut nt)?;
|
||||||
if idx == Kind::Basic as usize {
|
if idx == Kind::Basic as usize {
|
||||||
self.set_config_entry(&ConfigEntry::boxed(
|
self.set_config_entry(&ConfigEntry::boxed(
|
||||||
ConfigKey::CurrentNoteTypeId.into(),
|
ConfigKey::CurrentNotetypeId.into(),
|
||||||
serde_json::to_vec(&nt.id)?,
|
serde_json::to_vec(&nt.id)?,
|
||||||
self.usn(false)?,
|
self.usn(false)?,
|
||||||
TimestampSecs::now(),
|
TimestampSecs::now(),
|
||||||
@ -30,8 +30,8 @@ impl SqliteStorage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if changing this, make sure to update StockNoteType enum
|
// if changing this, make sure to update StockNotetype enum
|
||||||
pub fn all_stock_notetypes(tr: &I18n) -> Vec<NoteType> {
|
pub fn all_stock_notetypes(tr: &I18n) -> Vec<Notetype> {
|
||||||
vec![
|
vec![
|
||||||
basic(tr),
|
basic(tr),
|
||||||
basic_forward_reverse(tr),
|
basic_forward_reverse(tr),
|
||||||
@ -46,8 +46,8 @@ fn fieldref<S: AsRef<str>>(name: S) -> String {
|
|||||||
format!("{{{{{}}}}}", name.as_ref())
|
format!("{{{{{}}}}}", name.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn basic(tr: &I18n) -> NoteType {
|
pub(crate) fn basic(tr: &I18n) -> Notetype {
|
||||||
let mut nt = NoteType {
|
let mut nt = Notetype {
|
||||||
name: tr.notetypes_basic_name().into(),
|
name: tr.notetypes_basic_name().into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@ -68,7 +68,7 @@ pub(crate) fn basic(tr: &I18n) -> NoteType {
|
|||||||
nt
|
nt
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn basic_typing(tr: &I18n) -> NoteType {
|
pub(crate) fn basic_typing(tr: &I18n) -> Notetype {
|
||||||
let mut nt = basic(tr);
|
let mut nt = basic(tr);
|
||||||
nt.name = tr.notetypes_basic_type_answer_name().into();
|
nt.name = tr.notetypes_basic_type_answer_name().into();
|
||||||
let front = tr.notetypes_front_field();
|
let front = tr.notetypes_front_field();
|
||||||
@ -84,7 +84,7 @@ pub(crate) fn basic_typing(tr: &I18n) -> NoteType {
|
|||||||
nt
|
nt
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn basic_forward_reverse(tr: &I18n) -> NoteType {
|
pub(crate) fn basic_forward_reverse(tr: &I18n) -> Notetype {
|
||||||
let mut nt = basic(tr);
|
let mut nt = basic(tr);
|
||||||
nt.name = tr.notetypes_basic_reversed_name().into();
|
nt.name = tr.notetypes_basic_reversed_name().into();
|
||||||
let front = tr.notetypes_front_field();
|
let front = tr.notetypes_front_field();
|
||||||
@ -102,7 +102,7 @@ pub(crate) fn basic_forward_reverse(tr: &I18n) -> NoteType {
|
|||||||
nt
|
nt
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn basic_optional_reverse(tr: &I18n) -> NoteType {
|
pub(crate) fn basic_optional_reverse(tr: &I18n) -> Notetype {
|
||||||
let mut nt = basic_forward_reverse(tr);
|
let mut nt = basic_forward_reverse(tr);
|
||||||
nt.name = tr.notetypes_basic_optional_reversed_name().into();
|
nt.name = tr.notetypes_basic_optional_reversed_name().into();
|
||||||
let addrev = tr.notetypes_add_reverse_field();
|
let addrev = tr.notetypes_add_reverse_field();
|
||||||
@ -113,8 +113,8 @@ pub(crate) fn basic_optional_reverse(tr: &I18n) -> NoteType {
|
|||||||
nt
|
nt
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn cloze(tr: &I18n) -> NoteType {
|
pub(crate) fn cloze(tr: &I18n) -> Notetype {
|
||||||
let mut nt = NoteType {
|
let mut nt = Notetype {
|
||||||
name: tr.notetypes_cloze_name().into(),
|
name: tr.notetypes_cloze_name().into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@ -125,7 +125,7 @@ pub(crate) fn cloze(tr: &I18n) -> NoteType {
|
|||||||
let qfmt = format!("{{{{cloze:{}}}}}", text);
|
let qfmt = format!("{{{{cloze:{}}}}}", text);
|
||||||
let afmt = format!("{}<br>\n{{{{{}}}}}", qfmt, back_extra);
|
let afmt = format!("{}<br>\n{{{{{}}}}}", qfmt, back_extra);
|
||||||
nt.add_template(nt.name.clone(), qfmt, afmt);
|
nt.add_template(nt.name.clone(), qfmt, afmt);
|
||||||
nt.config.kind = NoteTypeKind::Cloze as i32;
|
nt.config.kind = NotetypeKind::Cloze as i32;
|
||||||
nt.config.css += "
|
nt.config.css += "
|
||||||
.cloze {
|
.cloze {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
@ -10,7 +10,7 @@ pub use crate::{
|
|||||||
err::{AnkiError, Result},
|
err::{AnkiError, Result},
|
||||||
i18n::I18n,
|
i18n::I18n,
|
||||||
notes::{Note, NoteId},
|
notes::{Note, NoteId},
|
||||||
notetype::{NoteType, NoteTypeId},
|
notetype::{Notetype, NotetypeId},
|
||||||
ops::{Op, OpChanges, OpOutput},
|
ops::{Op, OpChanges, OpOutput},
|
||||||
revlog::RevlogId,
|
revlog::RevlogId,
|
||||||
timestamp::{TimestampMillis, TimestampSecs},
|
timestamp::{TimestampMillis, TimestampSecs},
|
||||||
|
@ -45,7 +45,7 @@ impl SortKind {
|
|||||||
SortKind::NoteCreation
|
SortKind::NoteCreation
|
||||||
| SortKind::NoteMod
|
| SortKind::NoteMod
|
||||||
| SortKind::NoteField
|
| SortKind::NoteField
|
||||||
| SortKind::NoteType
|
| SortKind::Notetype
|
||||||
| SortKind::NoteTags
|
| SortKind::NoteTags
|
||||||
| SortKind::CardTemplate => RequiredTable::CardsAndNotes,
|
| SortKind::CardTemplate => RequiredTable::CardsAndNotes,
|
||||||
SortKind::CardMod
|
SortKind::CardMod
|
||||||
@ -152,7 +152,7 @@ fn write_order(sql: &mut String, kind: SortKind, reverse: bool) {
|
|||||||
SortKind::CardInterval => "c.ivl asc",
|
SortKind::CardInterval => "c.ivl asc",
|
||||||
SortKind::NoteTags => "n.tags asc",
|
SortKind::NoteTags => "n.tags asc",
|
||||||
SortKind::CardDeck => "(select pos from sort_order where did = c.did) asc",
|
SortKind::CardDeck => "(select pos from sort_order where did = c.did) asc",
|
||||||
SortKind::NoteType => "(select pos from sort_order where ntid = n.mid) asc",
|
SortKind::Notetype => "(select pos from sort_order where ntid = n.mid) asc",
|
||||||
SortKind::CardTemplate => concat!(
|
SortKind::CardTemplate => concat!(
|
||||||
"coalesce((select pos from sort_order where ntid = n.mid and ord = c.ord),",
|
"coalesce((select pos from sort_order where ntid = n.mid and ord = c.ord),",
|
||||||
// need to fall back on ord 0 for cloze cards
|
// need to fall back on ord 0 for cloze cards
|
||||||
@ -176,7 +176,7 @@ fn write_order(sql: &mut String, kind: SortKind, reverse: bool) {
|
|||||||
|
|
||||||
fn needs_aux_sort_table(kind: SortKind) -> bool {
|
fn needs_aux_sort_table(kind: SortKind) -> bool {
|
||||||
use SortKind::*;
|
use SortKind::*;
|
||||||
matches!(kind, CardDeck | NoteType | CardTemplate)
|
matches!(kind, CardDeck | Notetype | CardTemplate)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_sort(col: &mut Collection, kind: SortKind) -> Result<()> {
|
fn prepare_sort(col: &mut Collection, kind: SortKind) -> Result<()> {
|
||||||
@ -187,7 +187,7 @@ fn prepare_sort(col: &mut Collection, kind: SortKind) -> Result<()> {
|
|||||||
use SortKind::*;
|
use SortKind::*;
|
||||||
let sql = match kind {
|
let sql = match kind {
|
||||||
CardDeck => include_str!("deck_order.sql"),
|
CardDeck => include_str!("deck_order.sql"),
|
||||||
NoteType => include_str!("notetype_order.sql"),
|
Notetype => include_str!("notetype_order.sql"),
|
||||||
CardTemplate => include_str!("template_order.sql"),
|
CardTemplate => include_str!("template_order.sql"),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
decks::DeckId,
|
decks::DeckId,
|
||||||
err::{ParseError, Result, SearchErrorKind as FailKind},
|
err::{ParseError, Result, SearchErrorKind as FailKind},
|
||||||
notetype::NoteTypeId,
|
notetype::NotetypeId,
|
||||||
};
|
};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use nom::{
|
use nom::{
|
||||||
@ -73,15 +73,15 @@ pub enum SearchNode {
|
|||||||
CardTemplate(TemplateKind),
|
CardTemplate(TemplateKind),
|
||||||
Deck(String),
|
Deck(String),
|
||||||
DeckId(DeckId),
|
DeckId(DeckId),
|
||||||
NoteTypeId(NoteTypeId),
|
NotetypeId(NotetypeId),
|
||||||
NoteType(String),
|
Notetype(String),
|
||||||
Rated {
|
Rated {
|
||||||
days: u32,
|
days: u32,
|
||||||
ease: RatingKind,
|
ease: RatingKind,
|
||||||
},
|
},
|
||||||
Tag(String),
|
Tag(String),
|
||||||
Duplicates {
|
Duplicates {
|
||||||
note_type_id: NoteTypeId,
|
notetype_id: NotetypeId,
|
||||||
text: String,
|
text: String,
|
||||||
},
|
},
|
||||||
State(StateKind),
|
State(StateKind),
|
||||||
@ -325,7 +325,7 @@ fn search_node_for_text_with_argument<'a>(
|
|||||||
) -> ParseResult<'a, SearchNode> {
|
) -> ParseResult<'a, SearchNode> {
|
||||||
Ok(match key.to_ascii_lowercase().as_str() {
|
Ok(match key.to_ascii_lowercase().as_str() {
|
||||||
"deck" => SearchNode::Deck(unescape(val)?),
|
"deck" => SearchNode::Deck(unescape(val)?),
|
||||||
"note" => SearchNode::NoteType(unescape(val)?),
|
"note" => SearchNode::Notetype(unescape(val)?),
|
||||||
"tag" => SearchNode::Tag(unescape(val)?),
|
"tag" => SearchNode::Tag(unescape(val)?),
|
||||||
"card" => parse_template(val)?,
|
"card" => parse_template(val)?,
|
||||||
"flag" => parse_flag(val)?,
|
"flag" => parse_flag(val)?,
|
||||||
@ -557,7 +557,7 @@ fn parse_did(s: &str) -> ParseResult<SearchNode> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_mid(s: &str) -> ParseResult<SearchNode> {
|
fn parse_mid(s: &str) -> ParseResult<SearchNode> {
|
||||||
parse_i64(s, "mid:").map(|n| SearchNode::NoteTypeId(n.into()))
|
parse_i64(s, "mid:").map(|n| SearchNode::NotetypeId(n.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ensure a list of ids contains only numbers and commas, returning unchanged if true
|
/// ensure a list of ids contains only numbers and commas, returning unchanged if true
|
||||||
@ -586,7 +586,7 @@ fn parse_dupe(s: &str) -> ParseResult<SearchNode> {
|
|||||||
let ntid = parse_i64(it.next().unwrap(), s)?;
|
let ntid = parse_i64(it.next().unwrap(), s)?;
|
||||||
if let Some(text) = it.next() {
|
if let Some(text) = it.next() {
|
||||||
Ok(SearchNode::Duplicates {
|
Ok(SearchNode::Duplicates {
|
||||||
note_type_id: ntid.into(),
|
notetype_id: ntid.into(),
|
||||||
text: unescape_quotes_and_backslashes(text),
|
text: unescape_quotes_and_backslashes(text),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -829,7 +829,7 @@ mod test {
|
|||||||
vec![Search(Deck("default one".into()))]
|
vec![Search(Deck("default one".into()))]
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(parse("note:basic")?, vec![Search(NoteType("basic".into()))]);
|
assert_eq!(parse("note:basic")?, vec![Search(Notetype("basic".into()))]);
|
||||||
assert_eq!(parse("tag:hard")?, vec![Search(Tag("hard".into()))]);
|
assert_eq!(parse("tag:hard")?, vec![Search(Tag("hard".into()))]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse("nid:1237123712,2,3")?,
|
parse("nid:1237123712,2,3")?,
|
||||||
|
@ -8,7 +8,7 @@ use crate::{
|
|||||||
decks::human_deck_name_to_native,
|
decks::human_deck_name_to_native,
|
||||||
err::Result,
|
err::Result,
|
||||||
notes::field_checksum,
|
notes::field_checksum,
|
||||||
notetype::NoteTypeId,
|
notetype::NotetypeId,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
storage::ids_to_string,
|
storage::ids_to_string,
|
||||||
text::{
|
text::{
|
||||||
@ -123,8 +123,8 @@ impl SqlWriter<'_> {
|
|||||||
SearchNode::SingleField { field, text, is_re } => {
|
SearchNode::SingleField { field, text, is_re } => {
|
||||||
self.write_single_field(&norm(field), &self.norm_note(text), *is_re)?
|
self.write_single_field(&norm(field), &self.norm_note(text), *is_re)?
|
||||||
}
|
}
|
||||||
SearchNode::Duplicates { note_type_id, text } => {
|
SearchNode::Duplicates { notetype_id, text } => {
|
||||||
self.write_dupe(*note_type_id, &self.norm_note(text))?
|
self.write_dupe(*notetype_id, &self.norm_note(text))?
|
||||||
}
|
}
|
||||||
SearchNode::Regex(re) => self.write_regex(&self.norm_note(re)),
|
SearchNode::Regex(re) => self.write_regex(&self.norm_note(re)),
|
||||||
SearchNode::NoCombining(text) => self.write_no_combining(&self.norm_note(text)),
|
SearchNode::NoCombining(text) => self.write_no_combining(&self.norm_note(text)),
|
||||||
@ -140,13 +140,13 @@ impl SqlWriter<'_> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
SearchNode::Deck(deck) => self.write_deck(&norm(deck))?,
|
SearchNode::Deck(deck) => self.write_deck(&norm(deck))?,
|
||||||
SearchNode::NoteTypeId(ntid) => {
|
SearchNode::NotetypeId(ntid) => {
|
||||||
write!(self.sql, "n.mid = {}", ntid).unwrap();
|
write!(self.sql, "n.mid = {}", ntid).unwrap();
|
||||||
}
|
}
|
||||||
SearchNode::DeckId(did) => {
|
SearchNode::DeckId(did) => {
|
||||||
write!(self.sql, "c.did = {}", did).unwrap();
|
write!(self.sql, "c.did = {}", did).unwrap();
|
||||||
}
|
}
|
||||||
SearchNode::NoteType(notetype) => self.write_note_type(&norm(notetype)),
|
SearchNode::Notetype(notetype) => self.write_notetype(&norm(notetype)),
|
||||||
SearchNode::Rated { days, ease } => self.write_rated(">", -i64::from(*days), ease)?,
|
SearchNode::Rated { days, ease } => self.write_rated(">", -i64::from(*days), ease)?,
|
||||||
|
|
||||||
SearchNode::Tag(tag) => self.write_tag(&norm(tag)),
|
SearchNode::Tag(tag) => self.write_tag(&norm(tag)),
|
||||||
@ -393,7 +393,7 @@ impl SqlWriter<'_> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_note_type(&mut self, nt_name: &str) {
|
fn write_notetype(&mut self, nt_name: &str) {
|
||||||
if is_glob(nt_name) {
|
if is_glob(nt_name) {
|
||||||
let re = format!("(?i){}", to_re(nt_name));
|
let re = format!("(?i){}", to_re(nt_name));
|
||||||
self.sql
|
self.sql
|
||||||
@ -407,10 +407,10 @@ impl SqlWriter<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn write_single_field(&mut self, field_name: &str, val: &str, is_re: bool) -> Result<()> {
|
fn write_single_field(&mut self, field_name: &str, val: &str, is_re: bool) -> Result<()> {
|
||||||
let note_types = self.col.get_all_notetypes()?;
|
let notetypes = self.col.get_all_notetypes()?;
|
||||||
|
|
||||||
let mut field_map = vec![];
|
let mut field_map = vec![];
|
||||||
for nt in note_types.values() {
|
for nt in notetypes.values() {
|
||||||
for field in &nt.fields {
|
for field in &nt.fields {
|
||||||
if matches_glob(&field.name, field_name) {
|
if matches_glob(&field.name, field_name) {
|
||||||
field_map.push((nt.id, field.ord));
|
field_map.push((nt.id, field.ord));
|
||||||
@ -457,7 +457,7 @@ impl SqlWriter<'_> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_dupe(&mut self, ntid: NoteTypeId, text: &str) -> Result<()> {
|
fn write_dupe(&mut self, ntid: NotetypeId, text: &str) -> Result<()> {
|
||||||
let text_nohtml = strip_html_preserving_media_filenames(text);
|
let text_nohtml = strip_html_preserving_media_filenames(text);
|
||||||
let csum = field_checksum(text_nohtml.as_ref());
|
let csum = field_checksum(text_nohtml.as_ref());
|
||||||
|
|
||||||
@ -564,8 +564,8 @@ impl SearchNode {
|
|||||||
SearchNode::Regex(_) => RequiredTable::Notes,
|
SearchNode::Regex(_) => RequiredTable::Notes,
|
||||||
SearchNode::NoCombining(_) => RequiredTable::Notes,
|
SearchNode::NoCombining(_) => RequiredTable::Notes,
|
||||||
SearchNode::WordBoundary(_) => RequiredTable::Notes,
|
SearchNode::WordBoundary(_) => RequiredTable::Notes,
|
||||||
SearchNode::NoteTypeId(_) => RequiredTable::Notes,
|
SearchNode::NotetypeId(_) => RequiredTable::Notes,
|
||||||
SearchNode::NoteType(_) => RequiredTable::Notes,
|
SearchNode::Notetype(_) => RequiredTable::Notes,
|
||||||
SearchNode::EditedInDays(_) => RequiredTable::Notes,
|
SearchNode::EditedInDays(_) => RequiredTable::Notes,
|
||||||
|
|
||||||
SearchNode::NoteIds(_) => RequiredTable::CardsOrNotes,
|
SearchNode::NoteIds(_) => RequiredTable::CardsOrNotes,
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
decks::DeckId as DeckIdType,
|
decks::DeckId as DeckIdType,
|
||||||
notetype::NoteTypeId as NoteTypeIdType,
|
notetype::NotetypeId as NotetypeIdType,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
search::parser::{parse, Node, PropertyKind, RatingKind, SearchNode, StateKind, TemplateKind},
|
search::parser::{parse, Node, PropertyKind, RatingKind, SearchNode, StateKind, TemplateKind},
|
||||||
text::escape_anki_wildcards,
|
text::escape_anki_wildcards,
|
||||||
@ -86,11 +86,11 @@ fn write_search_node(node: &SearchNode) -> String {
|
|||||||
CardTemplate(t) => write_template(t),
|
CardTemplate(t) => write_template(t),
|
||||||
Deck(s) => quote(&format!("deck:{}", s)),
|
Deck(s) => quote(&format!("deck:{}", s)),
|
||||||
DeckId(DeckIdType(i)) => format!("\"did:{}\"", i),
|
DeckId(DeckIdType(i)) => format!("\"did:{}\"", i),
|
||||||
NoteTypeId(NoteTypeIdType(i)) => format!("\"mid:{}\"", i),
|
NotetypeId(NotetypeIdType(i)) => format!("\"mid:{}\"", i),
|
||||||
NoteType(s) => quote(&format!("note:{}", s)),
|
Notetype(s) => quote(&format!("note:{}", s)),
|
||||||
Rated { days, ease } => write_rated(days, ease),
|
Rated { days, ease } => write_rated(days, ease),
|
||||||
Tag(s) => quote(&format!("tag:{}", s)),
|
Tag(s) => quote(&format!("tag:{}", s)),
|
||||||
Duplicates { note_type_id, text } => write_dupe(note_type_id, text),
|
Duplicates { notetype_id, text } => write_dupe(notetype_id, text),
|
||||||
State(k) => write_state(k),
|
State(k) => write_state(k),
|
||||||
Flag(u) => format!("\"flag:{}\"", u),
|
Flag(u) => format!("\"flag:{}\"", u),
|
||||||
NoteIds(s) => format!("\"nid:{}\"", s),
|
NoteIds(s) => format!("\"nid:{}\"", s),
|
||||||
@ -135,9 +135,9 @@ fn write_rated(days: &u32, ease: &RatingKind) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Escape double quotes and backslashes: \"
|
/// Escape double quotes and backslashes: \"
|
||||||
fn write_dupe(note_type_id: &NoteTypeId, text: &str) -> String {
|
fn write_dupe(notetype_id: &NotetypeId, text: &str) -> String {
|
||||||
let esc = text.replace(r"\", r"\\").replace('"', r#"\""#);
|
let esc = text.replace(r"\", r"\\").replace('"', r#"\""#);
|
||||||
format!("\"dupe:{},{}\"", note_type_id, esc)
|
format!("\"dupe:{},{}\"", notetype_id, esc)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_state(kind: &StateKind) -> String {
|
fn write_state(kind: &StateKind) -> String {
|
||||||
|
@ -23,7 +23,7 @@ struct CardStats {
|
|||||||
average_secs: f32,
|
average_secs: f32,
|
||||||
total_secs: f32,
|
total_secs: f32,
|
||||||
card_type: String,
|
card_type: String,
|
||||||
note_type: String,
|
notetype: String,
|
||||||
deck: String,
|
deck: String,
|
||||||
nid: NoteId,
|
nid: NoteId,
|
||||||
cid: CardId,
|
cid: CardId,
|
||||||
@ -118,7 +118,7 @@ impl Collection {
|
|||||||
average_secs,
|
average_secs,
|
||||||
total_secs,
|
total_secs,
|
||||||
card_type: nt.get_template(card.template_idx)?.name.clone(),
|
card_type: nt.get_template(card.template_idx)?.name.clone(),
|
||||||
note_type: nt.name.clone(),
|
notetype: nt.name.clone(),
|
||||||
deck: deck.human_name(),
|
deck: deck.human_name(),
|
||||||
nid: card.note_id,
|
nid: card.note_id,
|
||||||
cid: card.id,
|
cid: card.id,
|
||||||
@ -172,7 +172,7 @@ impl Collection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
stats.push((tr.card_stats_card_template().into(), cs.card_type));
|
stats.push((tr.card_stats_card_template().into(), cs.card_type));
|
||||||
stats.push((tr.card_stats_note_type().into(), cs.note_type));
|
stats.push((tr.card_stats_note_type().into(), cs.notetype));
|
||||||
stats.push((tr.card_stats_deck_name().into(), cs.deck));
|
stats.push((tr.card_stats_deck_name().into(), cs.deck));
|
||||||
stats.push((tr.card_stats_card_id().into(), cs.cid.0.to_string()));
|
stats.push((tr.card_stats_card_id().into(), cs.cid.0.to_string()));
|
||||||
stats.push((tr.card_stats_note_id().into(), cs.nid.0.to_string()));
|
stats.push((tr.card_stats_note_id().into(), cs.nid.0.to_string()));
|
||||||
|
@ -6,7 +6,7 @@ use std::collections::HashSet;
|
|||||||
use crate::{
|
use crate::{
|
||||||
err::Result,
|
err::Result,
|
||||||
notes::{Note, NoteId, NoteTags},
|
notes::{Note, NoteId, NoteTags},
|
||||||
notetype::NoteTypeId,
|
notetype::NotetypeId,
|
||||||
tags::{join_tags, split_tags},
|
tags::{join_tags, split_tags},
|
||||||
timestamp::TimestampMillis,
|
timestamp::TimestampMillis,
|
||||||
};
|
};
|
||||||
@ -137,7 +137,7 @@ impl super::SqliteStorage {
|
|||||||
/// match.
|
/// match.
|
||||||
pub(crate) fn note_fields_by_checksum(
|
pub(crate) fn note_fields_by_checksum(
|
||||||
&self,
|
&self,
|
||||||
ntid: NoteTypeId,
|
ntid: NotetypeId,
|
||||||
csum: u32,
|
csum: u32,
|
||||||
) -> Result<Vec<(NoteId, String)>> {
|
) -> Result<Vec<(NoteId, String)>> {
|
||||||
self.db
|
self.db
|
||||||
|
@ -7,9 +7,9 @@ use crate::{
|
|||||||
notes::NoteId,
|
notes::NoteId,
|
||||||
notetype::{
|
notetype::{
|
||||||
AlreadyGeneratedCardInfo, CardTemplate, CardTemplateConfig, NoteField, NoteFieldConfig,
|
AlreadyGeneratedCardInfo, CardTemplate, CardTemplateConfig, NoteField, NoteFieldConfig,
|
||||||
NoteTypeConfig,
|
NotetypeConfig,
|
||||||
},
|
},
|
||||||
notetype::{NoteType, NoteTypeId, NoteTypeSchema11},
|
notetype::{Notetype, NotetypeId, NotetypeSchema11},
|
||||||
timestamp::TimestampMillis,
|
timestamp::TimestampMillis,
|
||||||
};
|
};
|
||||||
use prost::Message;
|
use prost::Message;
|
||||||
@ -17,9 +17,9 @@ use rusqlite::{params, OptionalExtension, Row, NO_PARAMS};
|
|||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use unicase::UniCase;
|
use unicase::UniCase;
|
||||||
|
|
||||||
fn row_to_notetype_core(row: &Row) -> Result<NoteType> {
|
fn row_to_notetype_core(row: &Row) -> Result<Notetype> {
|
||||||
let config = NoteTypeConfig::decode(row.get_raw(4).as_blob()?)?;
|
let config = NotetypeConfig::decode(row.get_raw(4).as_blob()?)?;
|
||||||
Ok(NoteType {
|
Ok(Notetype {
|
||||||
id: row.get(0)?,
|
id: row.get(0)?,
|
||||||
name: row.get(1)?,
|
name: row.get(1)?,
|
||||||
mtime_secs: row.get(2)?,
|
mtime_secs: row.get(2)?,
|
||||||
@ -41,7 +41,7 @@ fn row_to_existing_card(row: &Row) -> Result<AlreadyGeneratedCardInfo> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SqliteStorage {
|
impl SqliteStorage {
|
||||||
pub(crate) fn get_notetype(&self, ntid: NoteTypeId) -> Result<Option<NoteType>> {
|
pub(crate) fn get_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)?;
|
||||||
@ -52,7 +52,7 @@ impl SqliteStorage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_notetype_core(&self, ntid: NoteTypeId) -> Result<Option<NoteType>> {
|
fn get_notetype_core(&self, ntid: NotetypeId) -> Result<Option<Notetype>> {
|
||||||
self.db
|
self.db
|
||||||
.prepare_cached(concat!(include_str!("get_notetype.sql"), " where id = ?"))?
|
.prepare_cached(concat!(include_str!("get_notetype.sql"), " where id = ?"))?
|
||||||
.query_and_then(&[ntid], row_to_notetype_core)?
|
.query_and_then(&[ntid], row_to_notetype_core)?
|
||||||
@ -60,7 +60,7 @@ impl SqliteStorage {
|
|||||||
.transpose()
|
.transpose()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_notetype_fields(&self, ntid: NoteTypeId) -> Result<Vec<NoteField>> {
|
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| {
|
||||||
@ -74,7 +74,7 @@ impl SqliteStorage {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_notetype_templates(&self, ntid: NoteTypeId) -> Result<Vec<CardTemplate>> {
|
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| {
|
||||||
@ -90,7 +90,7 @@ impl SqliteStorage {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_notetype_id(&self, name: &str) -> Result<Option<NoteTypeId>> {
|
pub(crate) fn get_notetype_id(&self, name: &str) -> Result<Option<NotetypeId>> {
|
||||||
self.db
|
self.db
|
||||||
.prepare_cached("select id from notetypes where name = ?")?
|
.prepare_cached("select id from notetypes where name = ?")?
|
||||||
.query_row(params![name], |row| row.get(0))
|
.query_row(params![name], |row| row.get(0))
|
||||||
@ -98,7 +98,7 @@ impl SqliteStorage {
|
|||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_all_notetype_names(&self) -> Result<Vec<(NoteTypeId, String)>> {
|
pub fn get_all_notetype_names(&self) -> Result<Vec<(NotetypeId, String)>> {
|
||||||
self.db
|
self.db
|
||||||
.prepare_cached(include_str!("get_notetype_names.sql"))?
|
.prepare_cached(include_str!("get_notetype_names.sql"))?
|
||||||
.query_and_then(NO_PARAMS, |row| Ok((row.get(0)?, row.get(1)?)))?
|
.query_and_then(NO_PARAMS, |row| Ok((row.get(0)?, row.get(1)?)))?
|
||||||
@ -106,7 +106,7 @@ impl SqliteStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns list of (id, name, use_count)
|
/// Returns list of (id, name, use_count)
|
||||||
pub fn get_notetype_use_counts(&self) -> Result<Vec<(NoteTypeId, String, u32)>> {
|
pub fn get_notetype_use_counts(&self) -> Result<Vec<(NotetypeId, String, u32)>> {
|
||||||
self.db
|
self.db
|
||||||
.prepare_cached(include_str!("get_use_counts.sql"))?
|
.prepare_cached(include_str!("get_use_counts.sql"))?
|
||||||
.query_and_then(NO_PARAMS, |row| Ok((row.get(0)?, row.get(1)?, row.get(2)?)))?
|
.query_and_then(NO_PARAMS, |row| Ok((row.get(0)?, row.get(1)?, row.get(2)?)))?
|
||||||
@ -115,7 +115,7 @@ impl SqliteStorage {
|
|||||||
|
|
||||||
pub(crate) fn update_notetype_fields(
|
pub(crate) fn update_notetype_fields(
|
||||||
&self,
|
&self,
|
||||||
ntid: NoteTypeId,
|
ntid: NotetypeId,
|
||||||
fields: &[NoteField],
|
fields: &[NoteField],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.db
|
self.db
|
||||||
@ -147,7 +147,7 @@ impl SqliteStorage {
|
|||||||
pub(crate) fn note_ids_by_notetype(
|
pub(crate) fn note_ids_by_notetype(
|
||||||
&self,
|
&self,
|
||||||
nids: &[NoteId],
|
nids: &[NoteId],
|
||||||
) -> Result<Vec<(NoteTypeId, NoteId)>> {
|
) -> Result<Vec<(NotetypeId, NoteId)>> {
|
||||||
let mut sql = String::from("select mid, id from notes where id in ");
|
let mut sql = String::from("select mid, id from notes where id in ");
|
||||||
ids_to_string(&mut sql, nids);
|
ids_to_string(&mut sql, nids);
|
||||||
sql += " order by mid, id";
|
sql += " order by mid, id";
|
||||||
@ -157,7 +157,7 @@ impl SqliteStorage {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn all_note_ids_by_notetype(&self) -> Result<Vec<(NoteTypeId, NoteId)>> {
|
pub(crate) fn all_note_ids_by_notetype(&self) -> Result<Vec<(NotetypeId, NoteId)>> {
|
||||||
let sql = String::from("select mid, id from notes order by mid, id");
|
let sql = String::from("select mid, id from notes order by mid, id");
|
||||||
self.db
|
self.db
|
||||||
.prepare(&sql)?
|
.prepare(&sql)?
|
||||||
@ -167,7 +167,7 @@ impl SqliteStorage {
|
|||||||
|
|
||||||
pub(crate) fn update_notetype_templates(
|
pub(crate) fn update_notetype_templates(
|
||||||
&self,
|
&self,
|
||||||
ntid: NoteTypeId,
|
ntid: NotetypeId,
|
||||||
templates: &[CardTemplate],
|
templates: &[CardTemplate],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.db
|
self.db
|
||||||
@ -192,7 +192,7 @@ impl SqliteStorage {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn update_notetype_config(&self, nt: &NoteType) -> Result<()> {
|
pub(crate) fn update_notetype_config(&self, nt: &Notetype) -> Result<()> {
|
||||||
assert!(nt.id.0 != 0);
|
assert!(nt.id.0 != 0);
|
||||||
let mut stmt = self
|
let mut stmt = self
|
||||||
.db
|
.db
|
||||||
@ -204,7 +204,7 @@ impl SqliteStorage {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_new_notetype(&self, nt: &mut NoteType) -> Result<()> {
|
pub(crate) fn add_new_notetype(&self, nt: &mut Notetype) -> Result<()> {
|
||||||
assert!(nt.id.0 == 0);
|
assert!(nt.id.0 == 0);
|
||||||
|
|
||||||
let mut stmt = self.db.prepare_cached(include_str!("add_notetype.sql"))?;
|
let mut stmt = self.db.prepare_cached(include_str!("add_notetype.sql"))?;
|
||||||
@ -226,7 +226,7 @@ impl SqliteStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Used for syncing.
|
/// Used for syncing.
|
||||||
pub(crate) fn add_or_update_notetype(&self, nt: &NoteType) -> Result<()> {
|
pub(crate) fn add_or_update_notetype(&self, nt: &Notetype) -> Result<()> {
|
||||||
let mut stmt = self.db.prepare_cached(include_str!("add_or_update.sql"))?;
|
let mut stmt = self.db.prepare_cached(include_str!("add_or_update.sql"))?;
|
||||||
let mut config_bytes = vec![];
|
let mut config_bytes = vec![];
|
||||||
nt.config.encode(&mut config_bytes)?;
|
nt.config.encode(&mut config_bytes)?;
|
||||||
@ -240,7 +240,7 @@ impl SqliteStorage {
|
|||||||
|
|
||||||
pub(crate) fn remove_cards_for_deleted_templates(
|
pub(crate) fn remove_cards_for_deleted_templates(
|
||||||
&self,
|
&self,
|
||||||
ntid: NoteTypeId,
|
ntid: NotetypeId,
|
||||||
ords: &[u32],
|
ords: &[u32],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut stmt = self
|
let mut stmt = self
|
||||||
@ -252,7 +252,7 @@ impl SqliteStorage {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn remove_notetype(&self, ntid: NoteTypeId) -> Result<()> {
|
pub(crate) fn remove_notetype(&self, ntid: NotetypeId) -> Result<()> {
|
||||||
self.db
|
self.db
|
||||||
.prepare_cached("delete from cards where nid in (select id from notes where mid=?)")?
|
.prepare_cached("delete from cards where nid in (select id from notes where mid=?)")?
|
||||||
.execute(&[ntid])?;
|
.execute(&[ntid])?;
|
||||||
@ -274,7 +274,7 @@ impl SqliteStorage {
|
|||||||
|
|
||||||
pub(crate) fn move_cards_for_repositioned_templates(
|
pub(crate) fn move_cards_for_repositioned_templates(
|
||||||
&self,
|
&self,
|
||||||
ntid: NoteTypeId,
|
ntid: NotetypeId,
|
||||||
changes: &[(u32, u32)],
|
changes: &[(u32, u32)],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let case_clauses: Vec<_> = changes
|
let case_clauses: Vec<_> = changes
|
||||||
@ -297,7 +297,7 @@ and ord in ",
|
|||||||
|
|
||||||
pub(crate) fn existing_cards_for_notetype(
|
pub(crate) fn existing_cards_for_notetype(
|
||||||
&self,
|
&self,
|
||||||
ntid: NoteTypeId,
|
ntid: NotetypeId,
|
||||||
) -> Result<Vec<AlreadyGeneratedCardInfo>> {
|
) -> Result<Vec<AlreadyGeneratedCardInfo>> {
|
||||||
self.db
|
self.db
|
||||||
.prepare_cached(concat!(
|
.prepare_cached(concat!(
|
||||||
@ -328,7 +328,7 @@ and ord in ",
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn highest_card_ordinal_for_notetype(&self, ntid: NoteTypeId) -> Result<u16> {
|
pub(crate) fn highest_card_ordinal_for_notetype(&self, ntid: NotetypeId) -> Result<u16> {
|
||||||
self.db
|
self.db
|
||||||
.prepare(include_str!("highest_card_ord.sql"))?
|
.prepare(include_str!("highest_card_ord.sql"))?
|
||||||
.query_row(&[ntid], |row| row.get(0))
|
.query_row(&[ntid], |row| row.get(0))
|
||||||
@ -339,7 +339,7 @@ and ord in ",
|
|||||||
|
|
||||||
pub(crate) fn get_all_notetypes_as_schema11(
|
pub(crate) fn get_all_notetypes_as_schema11(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<HashMap<NoteTypeId, NoteTypeSchema11>> {
|
) -> Result<HashMap<NotetypeId, NotetypeSchema11>> {
|
||||||
let mut nts = HashMap::new();
|
let mut nts = HashMap::new();
|
||||||
for (ntid, _name) in self.get_all_notetype_names()? {
|
for (ntid, _name) in self.get_all_notetype_names()? {
|
||||||
let full = self.get_notetype(ntid)?.unwrap();
|
let full = self.get_notetype(ntid)?.unwrap();
|
||||||
@ -352,7 +352,7 @@ and ord in ",
|
|||||||
let nts = self.get_schema11_notetypes()?;
|
let nts = self.get_schema11_notetypes()?;
|
||||||
let mut names = HashSet::new();
|
let mut names = HashSet::new();
|
||||||
for (mut ntid, nt) in nts {
|
for (mut ntid, nt) in nts {
|
||||||
let mut nt = NoteType::from(nt);
|
let mut nt = Notetype::from(nt);
|
||||||
// note types with id 0 found in the wild; assign a random ID
|
// note types with id 0 found in the wild; assign a random ID
|
||||||
if ntid.0 == 0 {
|
if ntid.0 == 0 {
|
||||||
ntid.0 = rand::random::<u32>().max(1) as i64;
|
ntid.0 = rand::random::<u32>().max(1) as i64;
|
||||||
@ -381,13 +381,13 @@ and ord in ",
|
|||||||
self.set_schema11_notetypes(nts)
|
self.set_schema11_notetypes(nts)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_schema11_notetypes(&self) -> Result<HashMap<NoteTypeId, NoteTypeSchema11>> {
|
fn get_schema11_notetypes(&self) -> Result<HashMap<NotetypeId, NotetypeSchema11>> {
|
||||||
let mut stmt = self.db.prepare("select models from col")?;
|
let mut stmt = self.db.prepare("select models from col")?;
|
||||||
let note_types = stmt
|
let notetypes = stmt
|
||||||
.query_and_then(
|
.query_and_then(
|
||||||
NO_PARAMS,
|
NO_PARAMS,
|
||||||
|row| -> Result<HashMap<NoteTypeId, NoteTypeSchema11>> {
|
|row| -> Result<HashMap<NotetypeId, NotetypeSchema11>> {
|
||||||
let v: HashMap<NoteTypeId, NoteTypeSchema11> =
|
let v: HashMap<NotetypeId, NotetypeSchema11> =
|
||||||
serde_json::from_str(row.get_raw(0).as_str()?)?;
|
serde_json::from_str(row.get_raw(0).as_str()?)?;
|
||||||
Ok(v)
|
Ok(v)
|
||||||
},
|
},
|
||||||
@ -397,12 +397,12 @@ and ord in ",
|
|||||||
info: "col table empty".to_string(),
|
info: "col table empty".to_string(),
|
||||||
kind: DbErrorKind::MissingEntity,
|
kind: DbErrorKind::MissingEntity,
|
||||||
})??;
|
})??;
|
||||||
Ok(note_types)
|
Ok(notetypes)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_schema11_notetypes(
|
pub(crate) fn set_schema11_notetypes(
|
||||||
&self,
|
&self,
|
||||||
notetypes: HashMap<NoteTypeId, NoteTypeSchema11>,
|
notetypes: HashMap<NotetypeId, NotetypeSchema11>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let json = serde_json::to_string(¬etypes)?;
|
let json = serde_json::to_string(¬etypes)?;
|
||||||
self.db.execute("update col set models = ?", &[json])?;
|
self.db.execute("update col set models = ?", &[json])?;
|
||||||
|
@ -12,7 +12,7 @@ use crate::{
|
|||||||
decks::DeckSchema11,
|
decks::DeckSchema11,
|
||||||
err::SyncErrorKind,
|
err::SyncErrorKind,
|
||||||
notes::Note,
|
notes::Note,
|
||||||
notetype::{NoteType, NoteTypeSchema11},
|
notetype::{Notetype, NotetypeSchema11},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
revlog::RevlogEntry,
|
revlog::RevlogEntry,
|
||||||
serde::{default_on_invalid, deserialize_int_from_number},
|
serde::{default_on_invalid, deserialize_int_from_number},
|
||||||
@ -89,7 +89,7 @@ pub struct DecksAndConfig {
|
|||||||
#[derive(Serialize, Deserialize, Debug, Default)]
|
#[derive(Serialize, Deserialize, Debug, Default)]
|
||||||
pub struct UnchunkedChanges {
|
pub struct UnchunkedChanges {
|
||||||
#[serde(rename = "models")]
|
#[serde(rename = "models")]
|
||||||
notetypes: Vec<NoteTypeSchema11>,
|
notetypes: Vec<NotetypeSchema11>,
|
||||||
#[serde(rename = "decks")]
|
#[serde(rename = "decks")]
|
||||||
decks_and_config: DecksAndConfig,
|
decks_and_config: DecksAndConfig,
|
||||||
tags: Vec<String>,
|
tags: Vec<String>,
|
||||||
@ -124,7 +124,7 @@ pub struct NoteEntry {
|
|||||||
pub id: NoteId,
|
pub id: NoteId,
|
||||||
pub guid: String,
|
pub guid: String,
|
||||||
#[serde(rename = "mid")]
|
#[serde(rename = "mid")]
|
||||||
pub ntid: NoteTypeId,
|
pub ntid: NotetypeId,
|
||||||
#[serde(rename = "mod")]
|
#[serde(rename = "mod")]
|
||||||
pub mtime: TimestampSecs,
|
pub mtime: TimestampSecs,
|
||||||
pub usn: Usn,
|
pub usn: Usn,
|
||||||
@ -750,7 +750,7 @@ impl Collection {
|
|||||||
&mut self,
|
&mut self,
|
||||||
pending_usn: Usn,
|
pending_usn: Usn,
|
||||||
new_usn: Option<Usn>,
|
new_usn: Option<Usn>,
|
||||||
) -> Result<Vec<NoteTypeSchema11>> {
|
) -> Result<Vec<NotetypeSchema11>> {
|
||||||
let ids = self
|
let ids = self
|
||||||
.storage
|
.storage
|
||||||
.objects_pending_sync("notetypes", pending_usn)?;
|
.objects_pending_sync("notetypes", pending_usn)?;
|
||||||
@ -760,7 +760,7 @@ impl Collection {
|
|||||||
ids.into_iter()
|
ids.into_iter()
|
||||||
.map(|id| {
|
.map(|id| {
|
||||||
self.storage.get_notetype(id).map(|opt| {
|
self.storage.get_notetype(id).map(|opt| {
|
||||||
let mut nt: NoteTypeSchema11 = opt.unwrap().into();
|
let mut nt: NotetypeSchema11 = opt.unwrap().into();
|
||||||
nt.usn = new_usn.unwrap_or(nt.usn);
|
nt.usn = new_usn.unwrap_or(nt.usn);
|
||||||
nt
|
nt
|
||||||
})
|
})
|
||||||
@ -844,9 +844,9 @@ impl Collection {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn merge_notetypes(&mut self, notetypes: Vec<NoteTypeSchema11>, latest_usn: Usn) -> Result<()> {
|
fn merge_notetypes(&mut self, notetypes: Vec<NotetypeSchema11>, latest_usn: Usn) -> Result<()> {
|
||||||
for nt in notetypes {
|
for nt in notetypes {
|
||||||
let mut nt: NoteType = nt.into();
|
let mut nt: Notetype = nt.into();
|
||||||
let proceed = if let Some(existing_nt) = self.storage.get_notetype(nt.id)? {
|
let proceed = if let Some(existing_nt) = self.storage.get_notetype(nt.id)? {
|
||||||
if existing_nt.mtime_secs <= nt.mtime_secs {
|
if existing_nt.mtime_secs <= nt.mtime_secs {
|
||||||
if (existing_nt.fields.len() != nt.fields.len())
|
if (existing_nt.fields.len() != nt.fields.len())
|
||||||
|
Loading…
Reference in New Issue
Block a user