mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 06:22:22 -04:00
Move tag collapse method to the backend
This commit is contained in:
parent
1be789f25f
commit
f7f509c70d
5 changed files with 45 additions and 36 deletions
|
@ -80,10 +80,9 @@ class TagManager:
|
||||||
res = self.col.db.list(query)
|
res = self.col.db.list(query)
|
||||||
return list(set(self.split(" ".join(res))))
|
return list(set(self.split(" ".join(res))))
|
||||||
|
|
||||||
def toggle_browser_collapse(self, name: str):
|
def set_collapsed(self, tag: str, collapsed: bool):
|
||||||
tag = self.col.backend.get_tag(name)
|
"Set browser collapse state for tag, registering the tag if missing."
|
||||||
tag.config.browser_collapsed = not tag.config.browser_collapsed
|
self.col.backend.set_tag_collapsed(name=tag, collapsed=collapsed)
|
||||||
self.col.backend.update_tag(tag)
|
|
||||||
|
|
||||||
# Bulk addition/removal from notes
|
# Bulk addition/removal from notes
|
||||||
#############################################################
|
#############################################################
|
||||||
|
|
|
@ -21,13 +21,7 @@ from anki.consts import *
|
||||||
from anki.lang import without_unicode_isolation
|
from anki.lang import without_unicode_isolation
|
||||||
from anki.models import NoteType
|
from anki.models import NoteType
|
||||||
from anki.notes import Note
|
from anki.notes import Note
|
||||||
from anki.rsbackend import (
|
from anki.rsbackend import ConcatSeparator, DeckTreeNode, InvalidInput, TagTreeNode
|
||||||
ConcatSeparator,
|
|
||||||
DeckTreeNode,
|
|
||||||
InvalidInput,
|
|
||||||
NotFoundError,
|
|
||||||
TagTreeNode,
|
|
||||||
)
|
|
||||||
from anki.stats import CardStats
|
from anki.stats import CardStats
|
||||||
from anki.utils import htmlToTextLine, ids2str, isMac, isWin
|
from anki.utils import htmlToTextLine, ids2str, isMac, isWin
|
||||||
from aqt import AnkiQt, gui_hooks
|
from aqt import AnkiQt, gui_hooks
|
||||||
|
@ -1152,18 +1146,10 @@ QTableView {{ gridline-color: {grid} }}
|
||||||
return lambda: self.setFilter("tag", full_name)
|
return lambda: self.setFilter("tag", full_name)
|
||||||
|
|
||||||
def toggle_expand():
|
def toggle_expand():
|
||||||
|
|
||||||
full_name = head + node.name # pylint: disable=cell-var-from-loop
|
full_name = head + node.name # pylint: disable=cell-var-from-loop
|
||||||
|
return lambda _: self.mw.col.tags.set_collapsed(
|
||||||
def toggle(_):
|
full_name, not node.collapsed
|
||||||
try:
|
)
|
||||||
self.mw.col.tags.toggle_browser_collapse(full_name)
|
|
||||||
except NotFoundError:
|
|
||||||
# tag is missing, register it first
|
|
||||||
self.mw.col.tags.register([full_name])
|
|
||||||
self.mw.col.tags.toggle_browser_collapse(full_name)
|
|
||||||
|
|
||||||
return toggle
|
|
||||||
|
|
||||||
item = SidebarItem(
|
item = SidebarItem(
|
||||||
node.name,
|
node.name,
|
||||||
|
|
|
@ -214,6 +214,7 @@ service BackendService {
|
||||||
rpc AllTags (Empty) returns (AllTagsOut);
|
rpc AllTags (Empty) returns (AllTagsOut);
|
||||||
rpc GetTag (String) returns (Tag);
|
rpc GetTag (String) returns (Tag);
|
||||||
rpc UpdateTag (Tag) returns (Bool);
|
rpc UpdateTag (Tag) returns (Bool);
|
||||||
|
rpc SetTagCollapsed (SetTagCollapsedIn) returns (Bool);
|
||||||
rpc ClearTag (String) returns (Bool);
|
rpc ClearTag (String) returns (Bool);
|
||||||
rpc TagTree (Empty) returns (TagTreeNode);
|
rpc TagTree (Empty) returns (TagTreeNode);
|
||||||
|
|
||||||
|
@ -796,6 +797,11 @@ message AllTagsOut {
|
||||||
repeated Tag tags = 1;
|
repeated Tag tags = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message SetTagCollapsedIn {
|
||||||
|
string name = 1;
|
||||||
|
bool collapsed = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message TagConfig {
|
message TagConfig {
|
||||||
bool browser_collapsed = 1;
|
bool browser_collapsed = 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::Tag,
|
||||||
template::RenderedNode,
|
template::RenderedNode,
|
||||||
text::{extract_av_tags, strip_av_tags, AVTag},
|
text::{extract_av_tags, strip_av_tags, AVTag},
|
||||||
timestamp::TimestampSecs,
|
timestamp::TimestampSecs,
|
||||||
|
@ -1316,6 +1317,24 @@ impl BackendService for Backend {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_tag_collapsed(&self, input: pb::SetTagCollapsedIn) -> BackendResult<pb::Bool> {
|
||||||
|
self.with_col(|col| {
|
||||||
|
let name = &input.name;
|
||||||
|
let tag: Result<Tag> = if let Some(tag) = col.storage.get_tag(name)? {
|
||||||
|
Ok(tag)
|
||||||
|
} else {
|
||||||
|
// tag is missing, register it
|
||||||
|
let t = Tag {
|
||||||
|
name: name.to_owned(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
Ok(col.register_tag(t)?.0)
|
||||||
|
};
|
||||||
|
tag?.config.browser_collapsed = input.collapsed;
|
||||||
|
Ok(pb::Bool { val: true })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn register_tags(&self, input: pb::RegisterTagsIn) -> BackendResult<pb::Bool> {
|
fn register_tags(&self, input: pb::RegisterTagsIn) -> BackendResult<pb::Bool> {
|
||||||
self.with_col(|col| {
|
self.with_col(|col| {
|
||||||
col.transact(None, |col| {
|
col.transact(None, |col| {
|
||||||
|
|
|
@ -232,11 +232,11 @@ impl Collection {
|
||||||
usn,
|
usn,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})?;
|
})?;
|
||||||
if t.0.is_empty() {
|
if t.0.name.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
added |= t.1;
|
added |= t.1;
|
||||||
seen.insert(UniCase::new(t.0));
|
seen.insert(UniCase::new(t.0.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
// exit early if no non-empty tags
|
// exit early if no non-empty tags
|
||||||
|
@ -247,28 +247,27 @@ impl Collection {
|
||||||
// return the sorted, canonified tags
|
// return the sorted, canonified tags
|
||||||
let mut tags = seen.into_iter().collect::<Vec<_>>();
|
let mut tags = seen.into_iter().collect::<Vec<_>>();
|
||||||
tags.sort_unstable();
|
tags.sort_unstable();
|
||||||
let tags: Vec<_> = tags
|
let tags: Vec<_> = tags.into_iter().map(|s| s.into_inner()).collect();
|
||||||
.into_iter()
|
|
||||||
.map(|s| s.into_inner().to_string())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Ok((tags, added))
|
Ok((tags, added))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn register_tag<'a>(&self, tag: Tag) -> Result<(Cow<'a, str>, bool)> {
|
pub(crate) fn register_tag(&self, tag: Tag) -> Result<(Tag, bool)> {
|
||||||
let native_name = human_tag_name_to_native(&tag.name);
|
let native_name = human_tag_name_to_native(&tag.name);
|
||||||
if native_name.is_empty() {
|
|
||||||
return Ok(("".into(), false));
|
|
||||||
}
|
|
||||||
if let Some(preferred) = self.storage.preferred_tag_case(&native_name)? {
|
|
||||||
Ok((native_tag_name_to_human(&preferred).into(), false))
|
|
||||||
} else {
|
|
||||||
let mut t = Tag {
|
let mut t = Tag {
|
||||||
name: native_name.clone(),
|
name: native_name.clone(),
|
||||||
..tag
|
..tag
|
||||||
};
|
};
|
||||||
|
if native_name.is_empty() {
|
||||||
|
return Ok((t, false));
|
||||||
|
}
|
||||||
|
if let Some(preferred) = self.storage.preferred_tag_case(&native_name)? {
|
||||||
|
t.name = native_tag_name_to_human(&preferred);
|
||||||
|
Ok((t, false))
|
||||||
|
} else {
|
||||||
self.storage.register_tag(&mut t)?;
|
self.storage.register_tag(&mut t)?;
|
||||||
Ok((native_tag_name_to_human(&native_name).into(), true))
|
t.name = native_tag_name_to_human(&t.name);
|
||||||
|
Ok((t, true))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue