mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 08:46:37 -04:00
Refactor code for clearing unused tags and saving collapse state
This commit is contained in:
parent
72e8f9d640
commit
9c1d7c522a
6 changed files with 43 additions and 84 deletions
|
@ -42,30 +42,14 @@ class TagManager:
|
||||||
def register(
|
def register(
|
||||||
self, tags: Collection[str], usn: Optional[int] = None, clear=False
|
self, tags: Collection[str], usn: Optional[int] = None, clear=False
|
||||||
) -> None:
|
) -> None:
|
||||||
if usn is None:
|
print("tags.register() is deprecated and no longer works")
|
||||||
preserve_usn = False
|
|
||||||
usn_ = 0
|
|
||||||
else:
|
|
||||||
usn_ = usn
|
|
||||||
preserve_usn = True
|
|
||||||
|
|
||||||
self.col.backend.register_tags(
|
|
||||||
tags=" ".join(tags), preserve_usn=preserve_usn, usn=usn_, clear_first=clear
|
|
||||||
)
|
|
||||||
|
|
||||||
def registerNotes(self, nids: Optional[List[int]] = None) -> None:
|
def registerNotes(self, nids: Optional[List[int]] = None) -> None:
|
||||||
"Add any missing tags from notes to the tags list."
|
"Clear unused tags and add any missing tags from notes to the tag list."
|
||||||
# when called without an argument, the old list is cleared first.
|
self.clear_unused_tags()
|
||||||
if nids:
|
|
||||||
lim = " where id in " + ids2str(nids)
|
def clear_unused_tags(self):
|
||||||
clear = False
|
self.col.backend.clear_unused_tags()
|
||||||
else:
|
|
||||||
lim = ""
|
|
||||||
clear = True
|
|
||||||
self.register(
|
|
||||||
self.col.backend.get_note_tags(nids),
|
|
||||||
clear=clear,
|
|
||||||
)
|
|
||||||
|
|
||||||
def byDeck(self, did, children=False) -> List[str]:
|
def byDeck(self, did, children=False) -> List[str]:
|
||||||
basequery = "select n.tags from cards c, notes n WHERE c.nid = n.id"
|
basequery = "select n.tags from cards c, notes n WHERE c.nid = n.id"
|
||||||
|
|
|
@ -165,7 +165,6 @@ service BackendService {
|
||||||
rpc RemoveNotes(RemoveNotesIn) returns (Empty);
|
rpc RemoveNotes(RemoveNotesIn) returns (Empty);
|
||||||
rpc AddNoteTags(AddNoteTagsIn) returns (UInt32);
|
rpc AddNoteTags(AddNoteTagsIn) returns (UInt32);
|
||||||
rpc UpdateNoteTags(UpdateNoteTagsIn) returns (UInt32);
|
rpc UpdateNoteTags(UpdateNoteTagsIn) returns (UInt32);
|
||||||
rpc GetNoteTags(GetNoteTagsIn) returns (GetNoteTagsOut);
|
|
||||||
rpc ClozeNumbersInNote(Note) returns (ClozeNumbersInNoteOut);
|
rpc ClozeNumbersInNote(Note) returns (ClozeNumbersInNoteOut);
|
||||||
rpc AfterNoteUpdates(AfterNoteUpdatesIn) returns (Empty);
|
rpc AfterNoteUpdates(AfterNoteUpdatesIn) returns (Empty);
|
||||||
rpc FieldNamesForNotes(FieldNamesForNotesIn) returns (FieldNamesForNotesOut);
|
rpc FieldNamesForNotes(FieldNamesForNotesIn) returns (FieldNamesForNotesOut);
|
||||||
|
@ -208,10 +207,10 @@ service BackendService {
|
||||||
|
|
||||||
// tags
|
// tags
|
||||||
|
|
||||||
rpc RegisterTags(RegisterTagsIn) returns (Bool);
|
rpc ClearUnusedTags(Empty) returns (Empty);
|
||||||
rpc AllTags(Empty) returns (AllTagsOut);
|
rpc AllTags(Empty) returns (AllTagsOut);
|
||||||
rpc SetTagCollapsed(SetTagCollapsedIn) returns (Bool);
|
rpc SetTagCollapsed(SetTagCollapsedIn) returns (Empty);
|
||||||
rpc ClearTag(String) returns (Bool);
|
rpc ClearTag(String) returns (Empty);
|
||||||
rpc TagTree(Empty) returns (TagTreeNode);
|
rpc TagTree(Empty) returns (TagTreeNode);
|
||||||
|
|
||||||
// config/preferences
|
// config/preferences
|
||||||
|
@ -811,13 +810,6 @@ message AddOrUpdateDeckConfigLegacyIn {
|
||||||
bool preserve_usn_and_mtime = 2;
|
bool preserve_usn_and_mtime = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message RegisterTagsIn {
|
|
||||||
string tags = 1;
|
|
||||||
bool preserve_usn = 2;
|
|
||||||
int32 usn = 3;
|
|
||||||
bool clear_first = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
message AllTagsOut {
|
message AllTagsOut {
|
||||||
repeated Tag tags = 1;
|
repeated Tag tags = 1;
|
||||||
}
|
}
|
||||||
|
@ -950,14 +942,6 @@ message UpdateNoteTagsIn {
|
||||||
bool regex = 4;
|
bool regex = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GetNoteTagsIn {
|
|
||||||
repeated int64 nids = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message GetNoteTagsOut {
|
|
||||||
repeated string tags = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message CheckDatabaseOut {
|
message CheckDatabaseOut {
|
||||||
repeated string problems = 1;
|
repeated string problems = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ use crate::{
|
||||||
get_remote_sync_meta, sync_abort, sync_login, FullSyncProgress, NormalSyncProgress,
|
get_remote_sync_meta, sync_abort, sync_login, FullSyncProgress, NormalSyncProgress,
|
||||||
SyncActionRequired, SyncAuth, SyncMeta, SyncOutput, SyncStage,
|
SyncActionRequired, SyncAuth, SyncMeta, SyncOutput, SyncStage,
|
||||||
},
|
},
|
||||||
|
tags::join_tags,
|
||||||
template::RenderedNode,
|
template::RenderedNode,
|
||||||
text::{escape_anki_wildcards, extract_av_tags, strip_av_tags, AVTag},
|
text::{escape_anki_wildcards, extract_av_tags, strip_av_tags, AVTag},
|
||||||
timestamp::TimestampSecs,
|
timestamp::TimestampSecs,
|
||||||
|
@ -974,14 +975,6 @@ impl BackendService for Backend {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_note_tags(&self, input: pb::GetNoteTagsIn) -> BackendResult<pb::GetNoteTagsOut> {
|
|
||||||
self.with_col(|col| {
|
|
||||||
Ok(pb::GetNoteTagsOut {
|
|
||||||
tags: col.storage.get_note_tags(to_nids(input.nids))?,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cloze_numbers_in_note(&self, note: pb::Note) -> BackendResult<pb::ClozeNumbersInNoteOut> {
|
fn cloze_numbers_in_note(&self, note: pb::Note) -> BackendResult<pb::ClozeNumbersInNoteOut> {
|
||||||
let mut set = HashSet::with_capacity(4);
|
let mut set = HashSet::with_capacity(4);
|
||||||
for field in ¬e.fields {
|
for field in ¬e.fields {
|
||||||
|
@ -1360,34 +1353,32 @@ impl BackendService for Backend {
|
||||||
Ok(pb::AllTagsOut { tags })
|
Ok(pb::AllTagsOut { tags })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_tag_collapsed(&self, input: pb::SetTagCollapsedIn) -> BackendResult<pb::Bool> {
|
fn set_tag_collapsed(&self, input: pb::SetTagCollapsedIn) -> BackendResult<pb::Empty> {
|
||||||
self.with_col(|col| {
|
self.with_col(|col| {
|
||||||
col.transact(None, |col| {
|
col.transact(None, |col| {
|
||||||
col.set_tag_collapsed(&input.name, input.collapsed)?;
|
col.set_tag_collapsed(&input.name, input.collapsed)?;
|
||||||
Ok(pb::Bool { val: true })
|
Ok(().into())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_tags(&self, input: pb::RegisterTagsIn) -> BackendResult<pb::Bool> {
|
fn clear_unused_tags(&self, _input: pb::Empty) -> BackendResult<pb::Empty> {
|
||||||
self.with_col(|col| {
|
self.with_col(|col| {
|
||||||
col.transact(None, |col| {
|
col.transact(None, |col| {
|
||||||
let usn = if input.preserve_usn {
|
let old_tags = col.storage.all_tags()?;
|
||||||
Usn(input.usn)
|
let note_tags = join_tags(&col.storage.get_note_tags()?);
|
||||||
} else {
|
col.register_tags(¬e_tags, col.usn()?, true)?;
|
||||||
col.usn()?
|
col.update_tags_collapse(old_tags)?;
|
||||||
};
|
Ok(().into())
|
||||||
col.register_tags(&input.tags, usn, input.clear_first)
|
|
||||||
.map(|val| pb::Bool { val })
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear_tag(&self, tag: pb::String) -> BackendResult<pb::Bool> {
|
fn clear_tag(&self, tag: pb::String) -> BackendResult<pb::Empty> {
|
||||||
self.with_col(|col| {
|
self.with_col(|col| {
|
||||||
col.transact(None, |col| {
|
col.transact(None, |col| {
|
||||||
col.storage.clear_tag(tag.val.as_str())?;
|
col.storage.clear_tag(tag.val.as_str())?;
|
||||||
Ok(pb::Bool { val: true })
|
Ok(().into())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -295,17 +295,8 @@ impl Collection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_tags = self.storage.all_tags_sorted()?;
|
// restore tags collapse state and re-register old tags that are parents of used ones
|
||||||
for old in old_tags.into_iter() {
|
self.update_tags_collapse(old_tags)?;
|
||||||
for new in new_tags.iter() {
|
|
||||||
if new.name == old.name {
|
|
||||||
self.storage.set_tag_collapsed(&new.name, new.collapsed)?;
|
|
||||||
break;
|
|
||||||
} else if new.name.starts_with(&old.name) {
|
|
||||||
self.set_tag_collapsed(&old.name, old.collapsed)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the collection is empty and the user has deleted all note types, ensure at least
|
// if the collection is empty and the user has deleted all note types, ensure at least
|
||||||
// one note type exists
|
// one note type exists
|
||||||
|
|
|
@ -158,17 +158,10 @@ impl super::SqliteStorage {
|
||||||
}
|
}
|
||||||
|
|
||||||
// get distinct note tags
|
// get distinct note tags
|
||||||
pub(crate) fn get_note_tags(&self, nids: Vec<NoteID>) -> Result<Vec<String>> {
|
pub(crate) fn get_note_tags(&self) -> Result<Vec<String>> {
|
||||||
if nids.is_empty() {
|
self.db
|
||||||
self.db
|
.prepare_cached("select distinct tags from notes")?
|
||||||
.prepare_cached("select distinct tags from notes")?
|
.query_and_then(NO_PARAMS, |r| Ok(r.get_raw(0).as_str()?.to_owned()))?
|
||||||
.query_and_then(NO_PARAMS, |r| Ok(r.get_raw(0).as_str()?.to_owned()))?
|
.collect()
|
||||||
.collect()
|
|
||||||
} else {
|
|
||||||
self.db
|
|
||||||
.prepare_cached("select distinct tags from notes where id in ?")?
|
|
||||||
.query_and_then(nids, |r| Ok(r.get_raw(0).as_str()?.to_owned()))?
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -272,6 +272,22 @@ impl Collection {
|
||||||
self.storage.set_tag_collapsed(name, collapsed)
|
self.storage.set_tag_collapsed(name, collapsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update collapse state of existing tags and register tags in old_tags that are parents of those tags
|
||||||
|
pub(crate) fn update_tags_collapse(&self, old_tags: Vec<Tag>) -> Result<()> {
|
||||||
|
let new_tags = self.storage.all_tags_sorted()?;
|
||||||
|
for old in old_tags.into_iter() {
|
||||||
|
for new in new_tags.iter() {
|
||||||
|
if new.name == old.name {
|
||||||
|
self.storage.set_tag_collapsed(&new.name, old.collapsed)?;
|
||||||
|
break;
|
||||||
|
} else if new.name.starts_with(&old.name) {
|
||||||
|
self.set_tag_collapsed(&old.name, old.collapsed)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn replace_tags_for_notes_inner<R: Replacer>(
|
fn replace_tags_for_notes_inner<R: Replacer>(
|
||||||
&mut self,
|
&mut self,
|
||||||
nids: &[NoteID],
|
nids: &[NoteID],
|
||||||
|
|
Loading…
Reference in a new issue