use perform_op() for deck creation
This commit is contained in:
parent
0123a382ec
commit
01161c8ed2
@ -17,6 +17,7 @@ Preferences = _pb.Preferences
|
||||
UndoStatus = _pb.UndoStatus
|
||||
OpChanges = _pb.OpChanges
|
||||
OpChangesWithCount = _pb.OpChangesWithCount
|
||||
OpChangesWithID = _pb.OpChangesWithID
|
||||
DefaultsForAdding = _pb.DeckAndNotetype
|
||||
|
||||
import copy
|
||||
|
@ -11,7 +11,7 @@ from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple, Union
|
||||
|
||||
import anki # pylint: disable=unused-import
|
||||
import anki._backend.backend_pb2 as _pb
|
||||
from anki.collection import OpChanges, OpChangesWithCount
|
||||
from anki.collection import OpChanges, OpChangesWithCount, OpChangesWithID
|
||||
from anki.consts import *
|
||||
from anki.errors import NotFoundError
|
||||
from anki.utils import from_json_bytes, ids2str, intTime, legacy_func, to_json_bytes
|
||||
@ -112,6 +112,20 @@ class DeckManager:
|
||||
# Deck save/load
|
||||
#############################################################
|
||||
|
||||
def add_normal_deck_with_name(self, name: str) -> OpChangesWithID:
|
||||
"If deck exists, return existing id."
|
||||
if id := self.col.decks.id_for_name(name):
|
||||
return OpChangesWithID(id=id)
|
||||
else:
|
||||
deck = self.col.decks.new_deck_legacy(filtered=False)
|
||||
deck["name"] = name
|
||||
return self.add_deck_legacy(deck)
|
||||
|
||||
def add_deck_legacy(self, deck: Deck) -> OpChangesWithID:
|
||||
"Add a deck created with new_deck_legacy(). Must have id of 0."
|
||||
assert deck["id"] == 0
|
||||
return self.col._backend.add_deck_legacy(to_json_bytes(deck))
|
||||
|
||||
def id(
|
||||
self,
|
||||
name: str,
|
||||
@ -127,9 +141,8 @@ class DeckManager:
|
||||
|
||||
deck = self.new_deck_legacy(bool(type))
|
||||
deck["name"] = name
|
||||
self.update(deck, preserve_usn=False)
|
||||
|
||||
return deck["id"]
|
||||
out = self.add_deck_legacy(deck)
|
||||
return out.id
|
||||
|
||||
@legacy_func(sub="remove")
|
||||
def rem(self, did: int, cardsToo: bool = True, childrenToo: bool = True) -> None:
|
||||
|
@ -8,7 +8,8 @@ from typing import Callable, Sequence
|
||||
from anki.decks import DeckID
|
||||
from anki.lang import TR
|
||||
from aqt import AnkiQt, QWidget
|
||||
from aqt.utils import tooltip, tr
|
||||
from aqt.main import PerformOpOptionalSuccessCallback
|
||||
from aqt.utils import getOnlyText, tooltip, tr
|
||||
|
||||
|
||||
def remove_decks(
|
||||
@ -46,3 +47,25 @@ def rename_deck(
|
||||
mw.perform_op(
|
||||
lambda: mw.col.decks.rename(deck_id, new_name), after_hooks=after_rename
|
||||
)
|
||||
|
||||
|
||||
def add_deck_dialog(
|
||||
*,
|
||||
mw: AnkiQt,
|
||||
parent: QWidget,
|
||||
default_text: str = "",
|
||||
success: PerformOpOptionalSuccessCallback = None,
|
||||
) -> None:
|
||||
if name := getOnlyText(
|
||||
tr(TR.DECKS_NEW_DECK_NAME), default=default_text, parent=parent
|
||||
).strip():
|
||||
add_deck(mw=mw, name=name, success=success)
|
||||
|
||||
|
||||
def add_deck(
|
||||
*, mw: AnkiQt, name: str, success: PerformOpOptionalSuccessCallback = None
|
||||
) -> None:
|
||||
mw.perform_op(
|
||||
lambda: mw.col.decks.add_normal_deck_with_name(name),
|
||||
success=success,
|
||||
)
|
||||
|
@ -10,23 +10,13 @@ from typing import Any
|
||||
import aqt
|
||||
from anki.collection import OpChanges
|
||||
from anki.decks import DeckTreeNode
|
||||
from anki.errors import DeckIsFilteredError
|
||||
from anki.utils import intTime
|
||||
from aqt import AnkiQt, gui_hooks
|
||||
from aqt.deck_ops import remove_decks, rename_deck, reparent_decks
|
||||
from aqt.deck_ops import add_deck_dialog, remove_decks, rename_deck, reparent_decks
|
||||
from aqt.qt import *
|
||||
from aqt.sound import av_player
|
||||
from aqt.toolbar import BottomBar
|
||||
from aqt.utils import (
|
||||
TR,
|
||||
askUser,
|
||||
getOnlyText,
|
||||
openLink,
|
||||
shortcut,
|
||||
showInfo,
|
||||
showWarning,
|
||||
tr,
|
||||
)
|
||||
from aqt.utils import TR, askUser, getOnlyText, openLink, shortcut, showInfo, tr
|
||||
|
||||
|
||||
class DeckBrowserBottomBar:
|
||||
@ -331,15 +321,7 @@ class DeckBrowser:
|
||||
openLink(f"{aqt.appShared}decks/")
|
||||
|
||||
def _on_create(self) -> None:
|
||||
deck = getOnlyText(tr(TR.DECKS_NAME_FOR_DECK))
|
||||
if deck:
|
||||
try:
|
||||
self.mw.col.decks.id(deck)
|
||||
except DeckIsFilteredError as err:
|
||||
showWarning(str(err))
|
||||
return
|
||||
gui_hooks.sidebar_should_refresh_decks()
|
||||
self.refresh()
|
||||
add_deck_dialog(mw=self.mw, parent=self.mw)
|
||||
|
||||
######################################################################
|
||||
|
||||
|
@ -47,6 +47,7 @@ from anki.collection import (
|
||||
Config,
|
||||
OpChanges,
|
||||
OpChangesWithCount,
|
||||
OpChangesWithID,
|
||||
ReviewUndo,
|
||||
UndoResult,
|
||||
UndoStatus,
|
||||
@ -102,7 +103,8 @@ class HasChangesProperty(Protocol):
|
||||
# doesn't actually work for protobuf objects, so new protobuf objects will
|
||||
# either need to be added here, or cast at call time
|
||||
ResultWithChanges = TypeVar(
|
||||
"ResultWithChanges", bound=Union[OpChanges, OpChangesWithCount, HasChangesProperty]
|
||||
"ResultWithChanges",
|
||||
bound=Union[OpChanges, OpChangesWithCount, OpChangesWithID, HasChangesProperty],
|
||||
)
|
||||
|
||||
PerformOpOptionalSuccessCallback = Optional[Callable[[ResultWithChanges], Any]]
|
||||
|
@ -4,21 +4,20 @@
|
||||
from typing import List, Optional
|
||||
|
||||
import aqt
|
||||
from anki.errors import DeckIsFilteredError
|
||||
from anki.collection import OpChangesWithID
|
||||
from aqt import gui_hooks
|
||||
from aqt.deck_ops import add_deck_dialog
|
||||
from aqt.qt import *
|
||||
from aqt.utils import (
|
||||
TR,
|
||||
HelpPage,
|
||||
HelpPageArgument,
|
||||
disable_help_button,
|
||||
getOnlyText,
|
||||
openHelp,
|
||||
restoreGeom,
|
||||
saveGeom,
|
||||
shortcut,
|
||||
showInfo,
|
||||
showWarning,
|
||||
tr,
|
||||
)
|
||||
|
||||
@ -166,19 +165,14 @@ class StudyDeck(QDialog):
|
||||
default = self.form.filter.text()
|
||||
else:
|
||||
default = self.names[self.form.list.currentRow()]
|
||||
n = getOnlyText(tr(TR.DECKS_NEW_DECK_NAME), default=default)
|
||||
n = n.strip()
|
||||
if n:
|
||||
try:
|
||||
did = self.mw.col.decks.id(n)
|
||||
except DeckIsFilteredError as err:
|
||||
showWarning(str(err))
|
||||
return
|
||||
# deck name may not be the same as user input. ex: ", ::
|
||||
self.name = self.mw.col.decks.name(did)
|
||||
|
||||
def success(out: OpChangesWithID) -> None:
|
||||
deck = self.mw.col.decks.get(out.id)
|
||||
self.name = deck["name"]
|
||||
|
||||
# make sure we clean up reset hook when manually exiting
|
||||
gui_hooks.state_did_reset.remove(self.onReset)
|
||||
if self.mw.state == "deckBrowser":
|
||||
self.mw.deckBrowser.refresh()
|
||||
gui_hooks.sidebar_should_refresh_decks()
|
||||
|
||||
QDialog.accept(self)
|
||||
|
||||
add_deck_dialog(mw=self.mw, parent=self, default_text=default, success=success)
|
||||
|
@ -50,6 +50,11 @@ message OpChangesWithCount {
|
||||
OpChanges changes = 2;
|
||||
}
|
||||
|
||||
message OpChangesWithID {
|
||||
int64 id = 1;
|
||||
OpChanges changes = 2;
|
||||
}
|
||||
|
||||
// IDs used in RPC calls
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
@ -131,6 +136,7 @@ service SchedulingService {
|
||||
}
|
||||
|
||||
service DecksService {
|
||||
rpc AddDeckLegacy(Json) returns (OpChangesWithID);
|
||||
rpc AddOrUpdateDeckLegacy(AddOrUpdateDeckLegacyIn) returns (DeckID);
|
||||
rpc DeckTree(DeckTreeIn) returns (DeckTreeNode);
|
||||
rpc DeckTreeLegacy(Empty) returns (Json);
|
||||
@ -459,7 +465,7 @@ message CardRequirement {
|
||||
message Deck {
|
||||
int64 id = 1;
|
||||
string name = 2;
|
||||
uint32 mtime_secs = 3;
|
||||
int64 mtime_secs = 3;
|
||||
int32 usn = 4;
|
||||
DeckCommon common = 5;
|
||||
oneof kind {
|
||||
|
@ -10,6 +10,15 @@ use crate::{
|
||||
pub(super) use pb::decks_service::Service as DecksService;
|
||||
|
||||
impl DecksService for Backend {
|
||||
fn add_deck_legacy(&self, input: pb::Json) -> Result<pb::OpChangesWithId> {
|
||||
let schema11: DeckSchema11 = serde_json::from_slice(&input.json)?;
|
||||
let mut deck: Deck = schema11.into();
|
||||
self.with_col(|col| {
|
||||
let output = col.add_deck(&mut deck)?;
|
||||
Ok(output.map(|_| deck.id.0).into())
|
||||
})
|
||||
}
|
||||
|
||||
fn add_or_update_deck_legacy(&self, input: pb::AddOrUpdateDeckLegacyIn) -> Result<pb::DeckId> {
|
||||
self.with_col(|col| {
|
||||
let schema11: DeckSchema11 = serde_json::from_slice(&input.deck)?;
|
||||
@ -148,3 +157,40 @@ impl From<DeckID> for pb::DeckId {
|
||||
pb::DeckId { did: did.0 }
|
||||
}
|
||||
}
|
||||
|
||||
// before we can switch to returning protobuf, we need to make sure we're converting the
|
||||
// deck separators
|
||||
|
||||
// fn new_deck(&self, input: pb::Bool) -> Result<pb::Deck> {
|
||||
// let deck = if input.val {
|
||||
// Deck::new_filtered()
|
||||
// } else {
|
||||
// Deck::new_normal()
|
||||
// };
|
||||
// Ok(deck.into())
|
||||
// }
|
||||
|
||||
// impl From<pb::Deck> for Deck {
|
||||
// fn from(deck: pb::Deck) -> Self {
|
||||
// Self {
|
||||
// id: deck.id.into(),
|
||||
// name: deck.name,
|
||||
// mtime_secs: deck.mtime_secs.into(),
|
||||
// usn: deck.usn.into(),
|
||||
// common: deck.common.unwrap_or_default(),
|
||||
// kind: deck
|
||||
// .kind
|
||||
// .map(Into::into)
|
||||
// .unwrap_or_else(|| DeckKind::Normal(NormalDeck::default())),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl From<pb::deck::Kind> for DeckKind {
|
||||
// fn from(kind: pb::deck::Kind) -> Self {
|
||||
// match kind {
|
||||
// pb::deck::Kind::Normal(normal) => DeckKind::Normal(normal),
|
||||
// pb::deck::Kind::Filtered(filtered) => DeckKind::Filtered(filtered),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
@ -80,12 +80,3 @@ impl From<Vec<String>> for pb::StringList {
|
||||
pb::StringList { vals }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OpOutput<usize>> for pb::OpChangesWithCount {
|
||||
fn from(out: OpOutput<usize>) -> Self {
|
||||
pb::OpChangesWithCount {
|
||||
count: out.output as u32,
|
||||
changes: Some(out.changes.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,3 +44,21 @@ impl From<OpOutput<()>> for pb::OpChanges {
|
||||
o.changes.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OpOutput<usize>> for pb::OpChangesWithCount {
|
||||
fn from(out: OpOutput<usize>) -> Self {
|
||||
pb::OpChangesWithCount {
|
||||
count: out.output as u32,
|
||||
changes: Some(out.changes.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OpOutput<i64>> for pb::OpChangesWithId {
|
||||
fn from(out: OpOutput<i64>) -> Self {
|
||||
pb::OpChangesWithId {
|
||||
id: out.output,
|
||||
changes: Some(out.changes.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ impl From<Deck> for DeckProto {
|
||||
DeckProto {
|
||||
id: d.id.0,
|
||||
name: d.name,
|
||||
mtime_secs: d.mtime_secs.0 as u32,
|
||||
mtime_secs: d.mtime_secs.0,
|
||||
usn: d.usn.0,
|
||||
common: Some(d.common),
|
||||
kind: Some(d.kind.into()),
|
||||
|
@ -86,3 +86,15 @@ pub struct OpOutput<T> {
|
||||
pub output: T,
|
||||
pub changes: OpChanges,
|
||||
}
|
||||
|
||||
impl<T> OpOutput<T> {
|
||||
pub(crate) fn map<F, N>(self, func: F) -> OpOutput<N>
|
||||
where
|
||||
F: FnOnce(T) -> N,
|
||||
{
|
||||
OpOutput {
|
||||
output: func(self.output),
|
||||
changes: self.changes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user