mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 14:32:22 -04:00
add public wrappers for remaining backend functions
This commit is contained in:
parent
c7f92f0737
commit
6c483bb577
12 changed files with 94 additions and 36 deletions
|
@ -20,6 +20,7 @@ from . import rsbridge
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from anki.lang import FormatTimeSpanContextValue, TRValue
|
from anki.lang import FormatTimeSpanContextValue, TRValue
|
||||||
|
|
||||||
|
# pylint: disable=c-extension-no-member
|
||||||
assert rsbridge.buildhash() == anki.buildinfo.buildhash
|
assert rsbridge.buildhash() == anki.buildinfo.buildhash
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,9 @@ LABEL_REQUIRED = 2
|
||||||
LABEL_REPEATED = 3
|
LABEL_REPEATED = 3
|
||||||
|
|
||||||
# messages we don't want to unroll in codegen
|
# messages we don't want to unroll in codegen
|
||||||
SKIP_UNROLL_INPUT = {"TranslateString"}
|
SKIP_UNROLL_INPUT = {"TranslateString", "SetPreferences"}
|
||||||
|
SKIP_UNROLL_OUTPUT = {"GetPreferences"}
|
||||||
|
|
||||||
SKIP_DECODE = {"Graphs", "GetGraphPreferences"}
|
SKIP_DECODE = {"Graphs", "GetGraphPreferences"}
|
||||||
|
|
||||||
|
|
||||||
|
@ -114,6 +116,7 @@ def render_method(method, idx):
|
||||||
if (
|
if (
|
||||||
len(method.output_type.fields) == 1
|
len(method.output_type.fields) == 1
|
||||||
and method.output_type.fields[0].type != TYPE_ENUM
|
and method.output_type.fields[0].type != TYPE_ENUM
|
||||||
|
and method.name not in SKIP_UNROLL_OUTPUT
|
||||||
):
|
):
|
||||||
# unwrap single return arg
|
# unwrap single return arg
|
||||||
f = method.output_type.fields[0]
|
f = method.output_type.fields[0]
|
||||||
|
|
|
@ -32,6 +32,7 @@ from anki.models import ModelManager
|
||||||
from anki.notes import Note
|
from anki.notes import Note
|
||||||
from anki.sched import Scheduler as V1Scheduler
|
from anki.sched import Scheduler as V1Scheduler
|
||||||
from anki.schedv2 import Scheduler as V2Scheduler
|
from anki.schedv2 import Scheduler as V2Scheduler
|
||||||
|
from anki.sync import SyncAuth, SyncOutput, SyncStatus
|
||||||
from anki.tags import TagManager
|
from anki.tags import TagManager
|
||||||
from anki.utils import (
|
from anki.utils import (
|
||||||
devMode,
|
devMode,
|
||||||
|
@ -53,6 +54,7 @@ EmptyCardsReport = _pb.EmptyCardsReport
|
||||||
NoteWithEmptyCards = _pb.NoteWithEmptyCards
|
NoteWithEmptyCards = _pb.NoteWithEmptyCards
|
||||||
GraphPreferences = _pb.GraphPreferences
|
GraphPreferences = _pb.GraphPreferences
|
||||||
BuiltinSortKind = _pb.SortOrder.Builtin.Kind # pylint: disable=no-member
|
BuiltinSortKind = _pb.SortOrder.Builtin.Kind # pylint: disable=no-member
|
||||||
|
Preferences = _pb.Preferences
|
||||||
|
|
||||||
# pylint: disable=no-member
|
# pylint: disable=no-member
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
@ -819,6 +821,44 @@ table.review-log {{ {revlog_style} }}
|
||||||
intTime(),
|
intTime(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
def set_wants_abort(self) -> None:
|
||||||
|
self.backend.set_wants_abort()
|
||||||
|
|
||||||
|
def i18n_resources(self) -> bytes:
|
||||||
|
return self.backend.i18n_resources()
|
||||||
|
|
||||||
|
def abort_media_sync(self) -> None:
|
||||||
|
self.backend.abort_media_sync()
|
||||||
|
|
||||||
|
def abort_sync(self) -> None:
|
||||||
|
self.backend.abort_sync()
|
||||||
|
|
||||||
|
def full_upload(self, auth: SyncAuth) -> None:
|
||||||
|
self.backend.full_upload(auth)
|
||||||
|
|
||||||
|
def full_download(self, auth: SyncAuth) -> None:
|
||||||
|
self.backend.full_download(auth)
|
||||||
|
|
||||||
|
def sync_login(self, username: str, password: str) -> SyncAuth:
|
||||||
|
return self.backend.sync_login(username=username, password=password)
|
||||||
|
|
||||||
|
def sync_collection(self, auth: SyncAuth) -> SyncOutput:
|
||||||
|
return self.backend.sync_collection(auth)
|
||||||
|
|
||||||
|
def sync_media(self, auth: SyncAuth) -> None:
|
||||||
|
self.backend.sync_media(auth)
|
||||||
|
|
||||||
|
def sync_status(self, auth: SyncAuth) -> SyncStatus:
|
||||||
|
return self.backend.sync_status(auth)
|
||||||
|
|
||||||
|
def get_preferences(self) -> Preferences:
|
||||||
|
return self.backend.get_preferences()
|
||||||
|
|
||||||
|
def set_preferences(self, prefs: Preferences):
|
||||||
|
self.backend.set_preferences(prefs)
|
||||||
|
|
||||||
|
|
||||||
class ProgressKind(enum.Enum):
|
class ProgressKind(enum.Enum):
|
||||||
NoProgress = 0
|
NoProgress = 0
|
||||||
|
|
|
@ -17,6 +17,8 @@ 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.sound import SoundOrVideoTag
|
||||||
|
from anki.template import av_tags_to_native
|
||||||
from anki.utils import intTime
|
from anki.utils import intTime
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,6 +100,24 @@ class MediaManager:
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def empty_trash(self) -> None:
|
||||||
|
self.col.backend.empty_trash()
|
||||||
|
|
||||||
|
def restore_trash(self) -> None:
|
||||||
|
self.col.backend.restore_trash()
|
||||||
|
|
||||||
|
def strip_av_tags(self, text: str) -> str:
|
||||||
|
return self.col.backend.strip_av_tags(text)
|
||||||
|
|
||||||
|
def _extract_filenames(self, text: str) -> List[str]:
|
||||||
|
"This only exists do support a legacy function; do not use."
|
||||||
|
out = self.col.backend.extract_av_tags(text=text, question_side=True)
|
||||||
|
return [
|
||||||
|
x.filename
|
||||||
|
for x in av_tags_to_native(out.av_tags)
|
||||||
|
if isinstance(x, SoundOrVideoTag)
|
||||||
|
]
|
||||||
|
|
||||||
# File manipulation
|
# File manipulation
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ class TagManager:
|
||||||
nids=nids, tags=tags, replacement=replacement, regex=regex
|
nids=nids, tags=tags, replacement=replacement, regex=regex
|
||||||
)
|
)
|
||||||
|
|
||||||
def rename_tag(self, old: str, new: str) -> int:
|
def rename(self, old: str, new: str) -> int:
|
||||||
"Rename provided tag, returning number of changed notes."
|
"Rename provided tag, returning number of changed notes."
|
||||||
nids = self.col.find_notes(anki.collection.SearchTerm(tag=old))
|
nids = self.col.find_notes(anki.collection.SearchTerm(tag=old))
|
||||||
if not nids:
|
if not nids:
|
||||||
|
@ -100,6 +100,9 @@ class TagManager:
|
||||||
escaped_name = re.sub(r"[*_\\]", r"\\\g<0>", old)
|
escaped_name = re.sub(r"[*_\\]", r"\\\g<0>", old)
|
||||||
return self.bulk_update(nids, escaped_name, new, False)
|
return self.bulk_update(nids, escaped_name, new, False)
|
||||||
|
|
||||||
|
def remove(self, tag: str) -> None:
|
||||||
|
self.col.backend.clear_tag(tag)
|
||||||
|
|
||||||
# legacy routines
|
# legacy routines
|
||||||
|
|
||||||
def bulkAdd(self, ids: List[int], tags: str, add: bool = True) -> None:
|
def bulkAdd(self, ids: List[int], tags: str, add: bool = True) -> None:
|
||||||
|
|
|
@ -10,8 +10,6 @@ from typing import List
|
||||||
|
|
||||||
import anki
|
import anki
|
||||||
import aqt
|
import aqt
|
||||||
from anki.sound import SoundOrVideoTag
|
|
||||||
from anki.template import av_tags_to_native
|
|
||||||
from aqt.theme import theme_manager
|
from aqt.theme import theme_manager
|
||||||
|
|
||||||
# Routines removed from pylib/
|
# Routines removed from pylib/
|
||||||
|
@ -25,21 +23,16 @@ def bodyClass(col, card) -> str:
|
||||||
|
|
||||||
def allSounds(text) -> List:
|
def allSounds(text) -> List:
|
||||||
print("allSounds() deprecated")
|
print("allSounds() deprecated")
|
||||||
out = aqt.mw.col.backend.extract_av_tags(text=text, question_side=True)
|
return aqt.mw.col.media._extract_filenames(text)
|
||||||
return [
|
|
||||||
x.filename
|
|
||||||
for x in av_tags_to_native(out.av_tags)
|
|
||||||
if isinstance(x, SoundOrVideoTag)
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def stripSounds(text) -> str:
|
def stripSounds(text) -> str:
|
||||||
print("stripSounds() deprecated")
|
print("stripSounds() deprecated")
|
||||||
return aqt.mw.col.backend.strip_av_tags(text)
|
return aqt.mw.col.media.strip_av_tags(text)
|
||||||
|
|
||||||
|
|
||||||
def fmtTimeSpan(time, pad=0, point=0, short=False, inTime=False, unit=99):
|
def fmtTimeSpan(time, pad=0, point=0, short=False, inTime=False, unit=99):
|
||||||
print("fmtTimeSpan() has become col.backend.format_time_span()")
|
print("fmtTimeSpan() has become col.format_timespan()")
|
||||||
return aqt.mw.col.format_timespan(time)
|
return aqt.mw.col.format_timespan(time)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ class MediaChecker:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if self.progress_dialog.wantCancel:
|
if self.progress_dialog.wantCancel:
|
||||||
self.mw.col.backend.set_wants_abort()
|
self.mw.col.set_wants_abort()
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
# dialog may not be active
|
# dialog may not be active
|
||||||
pass
|
pass
|
||||||
|
@ -188,7 +188,7 @@ class MediaChecker:
|
||||||
self._set_progress_enabled(True)
|
self._set_progress_enabled(True)
|
||||||
|
|
||||||
def empty_trash():
|
def empty_trash():
|
||||||
self.mw.col.backend.empty_trash()
|
self.mw.col.media.empty_trash()
|
||||||
|
|
||||||
def on_done(fut: Future):
|
def on_done(fut: Future):
|
||||||
self.mw.progress.finish()
|
self.mw.progress.finish()
|
||||||
|
@ -205,7 +205,7 @@ class MediaChecker:
|
||||||
self._set_progress_enabled(True)
|
self._set_progress_enabled(True)
|
||||||
|
|
||||||
def restore_trash():
|
def restore_trash():
|
||||||
self.mw.col.backend.restore_trash()
|
self.mw.col.media.restore_trash()
|
||||||
|
|
||||||
def on_done(fut: Future):
|
def on_done(fut: Future):
|
||||||
self.mw.progress.finish()
|
self.mw.progress.finish()
|
||||||
|
|
|
@ -274,7 +274,7 @@ post_handlers = {
|
||||||
"graphPreferences": graph_preferences,
|
"graphPreferences": graph_preferences,
|
||||||
"setGraphPreferences": set_graph_preferences,
|
"setGraphPreferences": set_graph_preferences,
|
||||||
# pylint: disable=unnecessary-lambda
|
# pylint: disable=unnecessary-lambda
|
||||||
"i18nResources": lambda: aqt.mw.col.backend.i18n_resources(),
|
"i18nResources": lambda: aqt.mw.col.i18n_resources(),
|
||||||
"congratsInfo": congrats_info,
|
"congratsInfo": congrats_info,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ class MediaSyncer:
|
||||||
gui_hooks.media_sync_did_start_or_stop(True)
|
gui_hooks.media_sync_did_start_or_stop(True)
|
||||||
|
|
||||||
def run() -> None:
|
def run() -> None:
|
||||||
self.mw.col.backend.sync_media(auth)
|
self.mw.col.sync_media(auth)
|
||||||
|
|
||||||
self.mw.taskman.run_in_background(run, self._on_finished)
|
self.mw.taskman.run_in_background(run, self._on_finished)
|
||||||
|
|
||||||
|
@ -107,8 +107,8 @@ class MediaSyncer:
|
||||||
if not self.is_syncing():
|
if not self.is_syncing():
|
||||||
return
|
return
|
||||||
self._log_and_notify(tr(TR.SYNC_MEDIA_ABORTING))
|
self._log_and_notify(tr(TR.SYNC_MEDIA_ABORTING))
|
||||||
self.mw.col.backend.set_wants_abort()
|
self.mw.col.set_wants_abort()
|
||||||
self.mw.col.backend.abort_media_sync()
|
self.mw.col.abort_media_sync()
|
||||||
|
|
||||||
def is_syncing(self) -> bool:
|
def is_syncing(self) -> bool:
|
||||||
return self._syncing
|
return self._syncing
|
||||||
|
|
|
@ -47,7 +47,7 @@ class Preferences(QDialog):
|
||||||
self.form.buttonBox.helpRequested, lambda: openHelp(HelpPage.PREFERENCES)
|
self.form.buttonBox.helpRequested, lambda: openHelp(HelpPage.PREFERENCES)
|
||||||
)
|
)
|
||||||
self.silentlyClose = True
|
self.silentlyClose = True
|
||||||
self.prefs = self.mw.col.backend.get_preferences()
|
self.prefs = self.mw.col.get_preferences()
|
||||||
self.setupLang()
|
self.setupLang()
|
||||||
self.setupCollection()
|
self.setupCollection()
|
||||||
self.setupNetwork()
|
self.setupNetwork()
|
||||||
|
@ -114,7 +114,7 @@ class Preferences(QDialog):
|
||||||
|
|
||||||
f.useCurrent.setCurrentIndex(int(not qc.get("addToCur", True)))
|
f.useCurrent.setCurrentIndex(int(not qc.get("addToCur", True)))
|
||||||
|
|
||||||
s = self.prefs
|
s = self.prefs.sched
|
||||||
f.lrnCutoff.setValue(int(s.learn_ahead_secs / 60.0))
|
f.lrnCutoff.setValue(int(s.learn_ahead_secs / 60.0))
|
||||||
f.timeLimit.setValue(int(s.time_limit_secs / 60.0))
|
f.timeLimit.setValue(int(s.time_limit_secs / 60.0))
|
||||||
f.showEstimates.setChecked(s.show_intervals_on_buttons)
|
f.showEstimates.setChecked(s.show_intervals_on_buttons)
|
||||||
|
@ -156,7 +156,7 @@ class Preferences(QDialog):
|
||||||
qc = d.conf
|
qc = d.conf
|
||||||
qc["addToCur"] = not f.useCurrent.currentIndex()
|
qc["addToCur"] = not f.useCurrent.currentIndex()
|
||||||
|
|
||||||
s = self.prefs
|
s = self.prefs.sched
|
||||||
s.show_remaining_due_counts = f.showProgress.isChecked()
|
s.show_remaining_due_counts = f.showProgress.isChecked()
|
||||||
s.show_intervals_on_buttons = f.showEstimates.isChecked()
|
s.show_intervals_on_buttons = f.showEstimates.isChecked()
|
||||||
s.new_review_mix = f.newSpread.currentIndex()
|
s.new_review_mix = f.newSpread.currentIndex()
|
||||||
|
@ -168,7 +168,7 @@ class Preferences(QDialog):
|
||||||
|
|
||||||
# if moving this, make sure scheduler change is moved to Rust or
|
# if moving this, make sure scheduler change is moved to Rust or
|
||||||
# happens afterwards
|
# happens afterwards
|
||||||
self.mw.col.backend.set_preferences(self.prefs)
|
self.mw.col.set_preferences(self.prefs)
|
||||||
|
|
||||||
self._updateSchedVer(f.newSched.isChecked())
|
self._updateSchedVer(f.newSched.isChecked())
|
||||||
d.setMod()
|
d.setMod()
|
||||||
|
|
|
@ -691,8 +691,8 @@ class SidebarTreeView(QTreeView):
|
||||||
old_name = item.full_name
|
old_name = item.full_name
|
||||||
|
|
||||||
def do_remove():
|
def do_remove():
|
||||||
self.mw.col.backend.clear_tag(old_name)
|
self.mw.col.tags.remove(old_name)
|
||||||
self.col.tags.rename_tag(old_name, "")
|
self.col.tags.rename(old_name, "")
|
||||||
|
|
||||||
def on_done(fut: Future):
|
def on_done(fut: Future):
|
||||||
self.mw.requireReset(reason=ResetReason.BrowserRemoveTags, context=self)
|
self.mw.requireReset(reason=ResetReason.BrowserRemoveTags, context=self)
|
||||||
|
@ -714,8 +714,8 @@ class SidebarTreeView(QTreeView):
|
||||||
return
|
return
|
||||||
|
|
||||||
def do_rename():
|
def do_rename():
|
||||||
self.mw.col.backend.clear_tag(old_name)
|
self.mw.col.tags.remove(old_name)
|
||||||
return self.col.tags.rename_tag(old_name, new_name)
|
return self.col.tags.rename(old_name, new_name)
|
||||||
|
|
||||||
def on_done(fut: Future):
|
def on_done(fut: Future):
|
||||||
self.mw.requireReset(reason=ResetReason.BrowserAddTags, context=self)
|
self.mw.requireReset(reason=ResetReason.BrowserAddTags, context=self)
|
||||||
|
|
|
@ -54,9 +54,7 @@ def get_sync_status(mw: aqt.main.AnkiQt, callback: Callable[[SyncStatus], None])
|
||||||
return
|
return
|
||||||
callback(out)
|
callback(out)
|
||||||
|
|
||||||
mw.taskman.run_in_background(
|
mw.taskman.run_in_background(lambda: mw.col.sync_status(auth), on_future_done)
|
||||||
lambda: mw.col.backend.sync_status(auth), on_future_done
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def handle_sync_error(mw: aqt.main.AnkiQt, err: Exception):
|
def handle_sync_error(mw: aqt.main.AnkiQt, err: Exception):
|
||||||
|
@ -82,7 +80,7 @@ def on_normal_sync_timer(mw: aqt.main.AnkiQt) -> None:
|
||||||
mw.progress.set_title(progress.val.stage)
|
mw.progress.set_title(progress.val.stage)
|
||||||
|
|
||||||
if mw.progress.want_cancel():
|
if mw.progress.want_cancel():
|
||||||
mw.col.backend.abort_sync()
|
mw.col.abort_sync()
|
||||||
|
|
||||||
|
|
||||||
def sync_collection(mw: aqt.main.AnkiQt, on_done: Callable[[], None]) -> None:
|
def sync_collection(mw: aqt.main.AnkiQt, on_done: Callable[[], None]) -> None:
|
||||||
|
@ -116,7 +114,7 @@ def sync_collection(mw: aqt.main.AnkiQt, on_done: Callable[[], None]) -> None:
|
||||||
|
|
||||||
mw.col.save(trx=False)
|
mw.col.save(trx=False)
|
||||||
mw.taskman.with_progress(
|
mw.taskman.with_progress(
|
||||||
lambda: mw.col.backend.sync_collection(auth),
|
lambda: mw.col.sync_collection(auth),
|
||||||
on_future_done,
|
on_future_done,
|
||||||
label=tr(TR.SYNC_CHECKING),
|
label=tr(TR.SYNC_CHECKING),
|
||||||
immediate=True,
|
immediate=True,
|
||||||
|
@ -167,7 +165,7 @@ def on_full_sync_timer(mw: aqt.main.AnkiQt) -> None:
|
||||||
)
|
)
|
||||||
|
|
||||||
if mw.progress.want_cancel():
|
if mw.progress.want_cancel():
|
||||||
mw.col.backend.abort_sync()
|
mw.col.abort_sync()
|
||||||
|
|
||||||
|
|
||||||
def full_download(mw: aqt.main.AnkiQt, on_done: Callable[[], None]) -> None:
|
def full_download(mw: aqt.main.AnkiQt, on_done: Callable[[], None]) -> None:
|
||||||
|
@ -192,7 +190,7 @@ def full_download(mw: aqt.main.AnkiQt, on_done: Callable[[], None]) -> None:
|
||||||
return on_done()
|
return on_done()
|
||||||
|
|
||||||
mw.taskman.with_progress(
|
mw.taskman.with_progress(
|
||||||
lambda: mw.col.backend.full_download(mw.pm.sync_auth()),
|
lambda: mw.col.full_download(mw.pm.sync_auth()),
|
||||||
on_future_done,
|
on_future_done,
|
||||||
label=tr(TR.SYNC_DOWNLOADING_FROM_ANKIWEB),
|
label=tr(TR.SYNC_DOWNLOADING_FROM_ANKIWEB),
|
||||||
)
|
)
|
||||||
|
@ -221,7 +219,7 @@ def full_upload(mw: aqt.main.AnkiQt, on_done: Callable[[], None]) -> None:
|
||||||
return on_done()
|
return on_done()
|
||||||
|
|
||||||
mw.taskman.with_progress(
|
mw.taskman.with_progress(
|
||||||
lambda: mw.col.backend.full_upload(mw.pm.sync_auth()),
|
lambda: mw.col.full_upload(mw.pm.sync_auth()),
|
||||||
on_future_done,
|
on_future_done,
|
||||||
label=tr(TR.SYNC_UPLOADING_TO_ANKIWEB),
|
label=tr(TR.SYNC_UPLOADING_TO_ANKIWEB),
|
||||||
)
|
)
|
||||||
|
@ -258,7 +256,7 @@ def sync_login(
|
||||||
on_success()
|
on_success()
|
||||||
|
|
||||||
mw.taskman.with_progress(
|
mw.taskman.with_progress(
|
||||||
lambda: mw.col.backend.sync_login(username=username, password=password),
|
lambda: mw.col.sync_login(username=username, password=password),
|
||||||
on_future_done,
|
on_future_done,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue