mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
remove deck protobuf from frontend
Like the previous change, avoid exposing the protobuf as a public API for now. It requires more thought, and is probably better done with either extra helper accessors like decks.name(), or via a native class.
This commit is contained in:
parent
bb323615dd
commit
29c4869aef
10 changed files with 57 additions and 59 deletions
|
@ -39,7 +39,7 @@ from anki.cards import Card, CardId
|
|||
from anki.config import Config, ConfigManager
|
||||
from anki.consts import *
|
||||
from anki.dbproxy import DBProxy
|
||||
from anki.decks import Deck, DeckId, DeckManager
|
||||
from anki.decks import DeckId, DeckManager
|
||||
from anki.errors import AbortSchemaModification, DBError
|
||||
from anki.lang import FormatTimeSpan
|
||||
from anki.media import MediaManager, media_paths_from_col_path
|
||||
|
@ -335,14 +335,6 @@ class Collection:
|
|||
note=note._to_backend_note(), skip_undo_entry=False
|
||||
)
|
||||
|
||||
def get_deck(self, id: DeckId) -> Deck:
|
||||
"Get a new-style deck object."
|
||||
return self._backend.get_deck(id)
|
||||
|
||||
def update_deck(self, deck: Deck) -> OpChanges:
|
||||
"Save updates to an existing deck."
|
||||
return self._backend.update_deck(deck)
|
||||
|
||||
getCard = get_card
|
||||
getNote = get_note
|
||||
|
||||
|
|
|
@ -33,9 +33,6 @@ defaultDynamicDeck = 1
|
|||
DeckDict = Dict[str, Any]
|
||||
DeckConfigDict = Dict[str, Any]
|
||||
|
||||
# currently only supports read-only access
|
||||
Deck = _pb.Deck
|
||||
|
||||
DeckId = NewType("DeckId", int)
|
||||
DeckConfigId = NewType("DeckConfigId", int)
|
||||
|
||||
|
@ -290,6 +287,9 @@ class DeckManager:
|
|||
deck=to_json_bytes(g), preserve_usn_and_mtime=preserve_usn
|
||||
)
|
||||
|
||||
def update_dict(self, deck: DeckDict) -> OpChanges:
|
||||
return self.col._backend.update_deck_legacy(json=to_json_bytes(deck))
|
||||
|
||||
def rename(self, deck: Union[DeckDict, DeckId], new_name: str) -> OpChanges:
|
||||
"Rename deck prefix to NAME if not exists. Updates children."
|
||||
if isinstance(deck, int):
|
||||
|
@ -455,15 +455,12 @@ class DeckManager:
|
|||
# Deck selection
|
||||
#############################################################
|
||||
|
||||
def get_current(self) -> Deck:
|
||||
return self.col._backend.get_current_deck()
|
||||
|
||||
def set_current(self, deck: DeckId) -> OpChanges:
|
||||
return self.col._backend.set_current_deck(deck)
|
||||
|
||||
def get_current_id(self) -> DeckId:
|
||||
"The currently selected deck ID."
|
||||
return DeckId(self.get_current().id)
|
||||
return DeckId(self.col._backend.get_current_deck().id)
|
||||
|
||||
# legacy
|
||||
|
||||
|
@ -528,7 +525,7 @@ class DeckManager:
|
|||
)
|
||||
|
||||
def deck_and_child_ids(self, deck_id: DeckId) -> List[DeckId]:
|
||||
parent_name = self.col.get_deck(deck_id).name
|
||||
parent_name = self.name(deck_id)
|
||||
out = [deck_id]
|
||||
out.extend(self.child_ids(parent_name))
|
||||
return out
|
||||
|
|
|
@ -13,7 +13,7 @@ from anki.collection import (
|
|||
SearchJoiner,
|
||||
SearchNode,
|
||||
)
|
||||
from anki.decks import Deck, DeckCollapseScope, DeckId, DeckTreeNode
|
||||
from anki.decks import DeckCollapseScope, DeckId, DeckTreeNode
|
||||
from anki.models import NotetypeId
|
||||
from anki.notes import Note
|
||||
from anki.tags import TagTreeNode
|
||||
|
@ -902,8 +902,8 @@ class SidebarTreeView(QTreeView):
|
|||
full_name = item.name_prefix + new_name
|
||||
deck_id = DeckId(item.id)
|
||||
|
||||
def after_fetch(deck: Deck) -> None:
|
||||
if full_name == deck.name:
|
||||
def after_fetch(name: str) -> None:
|
||||
if full_name == name:
|
||||
return
|
||||
|
||||
rename_deck(
|
||||
|
@ -914,7 +914,7 @@ class SidebarTreeView(QTreeView):
|
|||
|
||||
QueryOp(
|
||||
parent=self.browser,
|
||||
op=lambda col: col.get_deck(deck_id),
|
||||
op=lambda col: col.decks.name(deck_id),
|
||||
success=after_fetch,
|
||||
).run_in_background()
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ from typing import Any, Optional
|
|||
|
||||
import aqt
|
||||
from anki.collection import OpChanges
|
||||
from anki.decks import Deck, DeckCollapseScope, DeckId, DeckTreeNode
|
||||
from anki.decks import DeckCollapseScope, DeckId, DeckTreeNode
|
||||
from aqt import AnkiQt, gui_hooks
|
||||
from aqt.deckoptions import display_options_for_deck_id
|
||||
from aqt.operations import QueryOp
|
||||
|
@ -278,9 +278,9 @@ class DeckBrowser:
|
|||
self.mw.onExport(did=did)
|
||||
|
||||
def _rename(self, did: DeckId) -> None:
|
||||
def prompt(deck: Deck) -> None:
|
||||
new_name = getOnlyText(tr.decks_new_deck_name(), default=deck.name)
|
||||
if not new_name or new_name == deck.name:
|
||||
def prompt(name: str) -> None:
|
||||
new_name = getOnlyText(tr.decks_new_deck_name(), default=name)
|
||||
if not new_name or new_name == name:
|
||||
return
|
||||
else:
|
||||
rename_deck(
|
||||
|
@ -288,7 +288,7 @@ class DeckBrowser:
|
|||
).run_in_background()
|
||||
|
||||
QueryOp(
|
||||
parent=self.mw, op=lambda col: col.get_deck(did), success=prompt
|
||||
parent=self.mw, op=lambda col: col.decks.name(did), success=prompt
|
||||
).run_in_background()
|
||||
|
||||
def _options(self, did: DeckId) -> None:
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import aqt
|
||||
from anki.decks import Deck
|
||||
from anki.decks import DeckDict
|
||||
from aqt.operations import QueryOp
|
||||
from aqt.operations.deck import update_deck
|
||||
from aqt.operations.deck import update_deck_dict
|
||||
from aqt.qt import *
|
||||
from aqt.utils import addCloseShortcut, disable_help_button, restoreGeom, saveGeom, tr
|
||||
|
||||
|
@ -21,16 +21,16 @@ class DeckDescriptionDialog(QDialog):
|
|||
self.mw = mw
|
||||
|
||||
# set on success
|
||||
self.deck: Deck
|
||||
self.deck: DeckDict
|
||||
|
||||
QueryOp(
|
||||
parent=self.mw,
|
||||
op=lambda col: col.decks.get_current(),
|
||||
op=lambda col: col.decks.current(),
|
||||
success=self._setup_and_show,
|
||||
).run_in_background()
|
||||
|
||||
def _setup_and_show(self, deck: Deck) -> None:
|
||||
if deck.WhichOneof("kind") != "normal":
|
||||
def _setup_and_show(self, deck: DeckDict) -> None:
|
||||
if deck["dyn"]:
|
||||
return
|
||||
|
||||
self.deck = deck
|
||||
|
@ -53,11 +53,11 @@ class DeckDescriptionDialog(QDialog):
|
|||
|
||||
self.enable_markdown = QCheckBox(tr.deck_config_description_markdown())
|
||||
self.enable_markdown.setToolTip(tr.deck_config_description_markdown_hint())
|
||||
self.enable_markdown.setChecked(self.deck.normal.markdown_description)
|
||||
self.enable_markdown.setChecked(self.deck.get("md", False))
|
||||
box.addWidget(self.enable_markdown)
|
||||
|
||||
self.description = QPlainTextEdit()
|
||||
self.description.setPlainText(self.deck.normal.description)
|
||||
self.description.setPlainText(self.deck.get("desc", ""))
|
||||
box.addWidget(self.description)
|
||||
|
||||
button_box = QDialogButtonBox()
|
||||
|
@ -69,10 +69,10 @@ class DeckDescriptionDialog(QDialog):
|
|||
self.show()
|
||||
|
||||
def save_and_accept(self) -> None:
|
||||
self.deck.normal.description = self.description.toPlainText()
|
||||
self.deck.normal.markdown_description = self.enable_markdown.isChecked()
|
||||
self.deck["desc"] = self.description.toPlainText()
|
||||
self.deck["md"] = self.enable_markdown.isChecked()
|
||||
|
||||
update_deck(parent=self, deck=self.deck).success(
|
||||
update_deck_dict(parent=self, deck=self.deck).success(
|
||||
lambda _: self.accept()
|
||||
).run_in_background()
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ from typing import List, Optional
|
|||
import aqt
|
||||
import aqt.deckconf
|
||||
from anki.cards import Card
|
||||
from anki.decks import Deck, DeckId
|
||||
from anki.decks import DeckDict, DeckId
|
||||
from anki.lang import without_unicode_isolation
|
||||
from aqt import gui_hooks
|
||||
from aqt.qt import *
|
||||
|
@ -29,7 +29,7 @@ class DeckOptionsDialog(QDialog):
|
|||
TITLE = "deckOptions"
|
||||
silentlyClose = True
|
||||
|
||||
def __init__(self, mw: aqt.main.AnkiQt, deck: Deck) -> None:
|
||||
def __init__(self, mw: aqt.main.AnkiQt, deck: DeckDict) -> None:
|
||||
QDialog.__init__(self, mw, Qt.Window)
|
||||
self.mw = mw
|
||||
self._deck = deck
|
||||
|
@ -54,10 +54,10 @@ class DeckOptionsDialog(QDialog):
|
|||
|
||||
self.web.eval(
|
||||
f"""const $deckOptions = anki.deckOptions(
|
||||
document.getElementById('main'), {self._deck.id});"""
|
||||
document.getElementById('main'), {self._deck["id"]});"""
|
||||
)
|
||||
self.setWindowTitle(
|
||||
without_unicode_isolation(tr.actions_options_for(val=self._deck.name))
|
||||
without_unicode_isolation(tr.actions_options_for(val=self._deck["name"]))
|
||||
)
|
||||
gui_hooks.deck_options_did_load(self)
|
||||
|
||||
|
@ -68,28 +68,28 @@ class DeckOptionsDialog(QDialog):
|
|||
|
||||
|
||||
def confirm_deck_then_display_options(active_card: Optional[Card] = None) -> None:
|
||||
decks = [aqt.mw.col.decks.get_current()]
|
||||
decks = [aqt.mw.col.decks.current()]
|
||||
if card := active_card:
|
||||
if card.odid and card.odid != decks[0].id:
|
||||
decks.append(aqt.mw.col.get_deck(card.odid))
|
||||
if card.odid and card.odid != decks[0]["id"]:
|
||||
decks.append(aqt.mw.col.decks.get(card.odid))
|
||||
|
||||
if not any(d.id == card.did for d in decks):
|
||||
decks.append(aqt.mw.col.get_deck(card.odid))
|
||||
if not any(d["id"] == card.did for d in decks):
|
||||
decks.append(aqt.mw.col.decks.get(card.odid))
|
||||
|
||||
if len(decks) == 1:
|
||||
display_options_for_deck(decks[0])
|
||||
else:
|
||||
decks.sort(key=lambda x: x.WhichOneof("kind") == "filtered")
|
||||
decks.sort(key=lambda x: x["dyn"])
|
||||
_deck_prompt_dialog(decks)
|
||||
|
||||
|
||||
def _deck_prompt_dialog(decks: List[Deck]) -> None:
|
||||
def _deck_prompt_dialog(decks: List[DeckDict]) -> None:
|
||||
diag = QDialog(aqt.mw.app.activeWindow())
|
||||
diag.setWindowTitle("Anki")
|
||||
box = QVBoxLayout()
|
||||
box.addWidget(QLabel(tr.deck_config_which_deck()))
|
||||
for deck in decks:
|
||||
button = QPushButton(deck.name)
|
||||
button = QPushButton(deck["name"])
|
||||
qconnect(button.clicked, lambda _, deck=deck: display_options_for_deck(deck))
|
||||
qconnect(button.clicked, diag.close)
|
||||
box.addWidget(button)
|
||||
|
@ -101,15 +101,15 @@ def _deck_prompt_dialog(decks: List[Deck]) -> None:
|
|||
|
||||
|
||||
def display_options_for_deck_id(deck_id: DeckId) -> None:
|
||||
display_options_for_deck(aqt.mw.col.get_deck(deck_id))
|
||||
display_options_for_deck(aqt.mw.col.decks.get(deck_id))
|
||||
|
||||
|
||||
def display_options_for_deck(deck: Deck) -> None:
|
||||
if deck.WhichOneof("kind") == "normal":
|
||||
def display_options_for_deck(deck: DeckDict) -> None:
|
||||
if not deck["dyn"]:
|
||||
if KeyboardModifiersPressed().shift or aqt.mw.col.schedVer() == 1:
|
||||
deck_legacy = aqt.mw.col.decks.get(DeckId(deck.id))
|
||||
deck_legacy = aqt.mw.col.decks.get(DeckId(deck["id"]))
|
||||
aqt.deckconf.DeckConf(aqt.mw, deck_legacy)
|
||||
else:
|
||||
DeckOptionsDialog(aqt.mw, deck)
|
||||
else:
|
||||
aqt.dialogs.open("FilteredDeckConfigDialog", aqt.mw, deck_id=deck.id)
|
||||
aqt.dialogs.open("FilteredDeckConfigDialog", aqt.mw, deck_id=deck["id"])
|
||||
|
|
|
@ -6,7 +6,7 @@ from __future__ import annotations
|
|||
from typing import Optional, Sequence
|
||||
|
||||
from anki.collection import OpChanges, OpChangesWithCount, OpChangesWithId
|
||||
from anki.decks import Deck, DeckCollapseScope, DeckId, UpdateDeckConfigs
|
||||
from anki.decks import DeckCollapseScope, DeckDict, DeckId, UpdateDeckConfigs
|
||||
from aqt import QWidget
|
||||
from aqt.operations import CollectionOp
|
||||
from aqt.utils import getOnlyText, tooltip, tr
|
||||
|
@ -88,5 +88,5 @@ def update_deck_configs(
|
|||
return CollectionOp(parent, lambda col: col.decks.update_deck_configs(input))
|
||||
|
||||
|
||||
def update_deck(*, parent: QWidget, deck: Deck) -> CollectionOp[OpChanges]:
|
||||
return CollectionOp(parent, lambda col: col.update_deck(deck))
|
||||
def update_deck_dict(*, parent: QWidget, deck: DeckDict) -> CollectionOp[OpChanges]:
|
||||
return CollectionOp(parent, lambda col: col.decks.update_dict(deck))
|
||||
|
|
|
@ -94,7 +94,7 @@ class Overview:
|
|||
elif url == "anki":
|
||||
print("anki menu")
|
||||
elif url == "opts":
|
||||
display_options_for_deck(self.mw.col.decks.get_current())
|
||||
display_options_for_deck(self.mw.col.decks.current())
|
||||
elif url == "cram":
|
||||
aqt.dialogs.open("FilteredDeckConfigDialog", self.mw)
|
||||
elif url == "refresh":
|
||||
|
@ -117,7 +117,7 @@ class Overview:
|
|||
|
||||
def _shortcutKeys(self) -> List[Tuple[str, Callable]]:
|
||||
return [
|
||||
("o", lambda: display_options_for_deck(self.mw.col.decks.get_current())),
|
||||
("o", lambda: display_options_for_deck(self.mw.col.decks.current())),
|
||||
("r", self.rebuild_current_filtered_deck),
|
||||
("e", self.empty_current_filtered_deck),
|
||||
("c", self.onCustomStudyKey),
|
||||
|
|
|
@ -144,6 +144,7 @@ service DecksService {
|
|||
rpc GetDeckIdByName(String) returns (DeckId);
|
||||
rpc GetDeck(DeckId) returns (Deck);
|
||||
rpc UpdateDeck(Deck) returns (OpChanges);
|
||||
rpc UpdateDeckLegacy(Json) returns (OpChanges);
|
||||
rpc SetDeckCollapsed(SetDeckCollapsedIn) returns (OpChanges);
|
||||
rpc GetDeckLegacy(DeckId) returns (Json);
|
||||
rpc GetDeckNames(GetDeckNamesIn) returns (DeckNames);
|
||||
|
|
|
@ -97,6 +97,14 @@ impl DecksService for Backend {
|
|||
})
|
||||
}
|
||||
|
||||
fn update_deck_legacy(&self, input: pb::Json) -> Result<pb::OpChanges> {
|
||||
self.with_col(|col| {
|
||||
let deck: DeckSchema11 = serde_json::from_slice(&input.json)?;
|
||||
let mut deck = deck.into();
|
||||
col.update_deck(&mut deck).map(Into::into)
|
||||
})
|
||||
}
|
||||
|
||||
fn get_deck_legacy(&self, input: pb::DeckId) -> Result<pb::Json> {
|
||||
self.with_col(|col| {
|
||||
let deck: DeckSchema11 = col
|
||||
|
|
Loading…
Reference in a new issue