mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
add getter/setter for boolean config values
This commit is contained in:
parent
a9be60c8b4
commit
5ff7944a26
8 changed files with 80 additions and 10 deletions
|
@ -12,6 +12,7 @@ import traceback
|
|||
import weakref
|
||||
from typing import TYPE_CHECKING, Any, List, Optional, Sequence, Tuple, Union
|
||||
|
||||
import anki.backend_pb2 as pb
|
||||
import anki.find
|
||||
import anki.latex # sets up hook
|
||||
import anki.template
|
||||
|
@ -32,16 +33,19 @@ from anki.rsbackend import (
|
|||
Progress,
|
||||
RustBackend,
|
||||
from_json_bytes,
|
||||
pb,
|
||||
)
|
||||
from anki.sched import Scheduler as V1Scheduler
|
||||
from anki.schedv2 import Scheduler as V2Scheduler
|
||||
from anki.tags import TagManager
|
||||
from anki.utils import devMode, ids2str, intTime
|
||||
|
||||
ConfigBoolKey = pb.ConfigBool.Key # pylint: disable=no-member
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from anki.rsbackend import FormatTimeSpanContextValue, TRValue
|
||||
|
||||
ConfigBoolKeyValue = pb.ConfigBool.KeyValue # pylint: disable=no-member
|
||||
|
||||
|
||||
class Collection:
|
||||
sched: Union[V1Scheduler, V2Scheduler]
|
||||
|
@ -496,6 +500,13 @@ class Collection:
|
|||
"This is a debugging aid. Prefer .get_config() when you know the key you need."
|
||||
return from_json_bytes(self.backend.get_all_config())
|
||||
|
||||
def get_config_bool(self, key: ConfigBoolKeyValue) -> bool:
|
||||
return self.backend.get_config_bool(key)
|
||||
|
||||
def set_config_bool(self, key: ConfigBoolKeyValue, value: bool) -> None:
|
||||
self.setMod()
|
||||
self.backend.set_config_bool(key=key, value=value)
|
||||
|
||||
# Stats
|
||||
##########################################################################
|
||||
|
||||
|
|
|
@ -38,6 +38,9 @@ if TYPE_CHECKING:
|
|||
|
||||
assert anki._rsbridge.buildhash() == anki.buildinfo.buildhash
|
||||
|
||||
# FIXME: rather than adding new items here, items intended to be consumed
|
||||
# by external libraries (eg aqt) should be exported in the module that
|
||||
# refers to them, eg collection.py
|
||||
SchedTimingToday = pb.SchedTimingTodayOut
|
||||
BuiltinSortKind = pb.BuiltinSearchOrder.BuiltinSortKind
|
||||
BackendCard = pb.Card
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# coding: utf-8
|
||||
import pytest
|
||||
|
||||
from anki.collection import ConfigBoolKey
|
||||
from anki.consts import *
|
||||
from anki.rsbackend import BuiltinSortKind
|
||||
from tests.shared import getEmptyCol, isNearCutoff
|
||||
|
@ -121,7 +122,7 @@ def test_findCards():
|
|||
col.flush()
|
||||
assert col.findCards("", order=True)[-1] in latestCardIds
|
||||
assert col.findCards("", order=True)[0] == firstCardId
|
||||
col.conf["sortBackwards"] = True
|
||||
col.set_config_bool(ConfigBoolKey.BROWSER_SORT_BACKWARDS, True)
|
||||
col.flush()
|
||||
assert col.findCards("", order=True)[0] in latestCardIds
|
||||
assert (
|
||||
|
|
|
@ -13,7 +13,7 @@ from typing import List, Optional, Sequence, Tuple, cast
|
|||
import aqt
|
||||
import aqt.forms
|
||||
from anki.cards import Card
|
||||
from anki.collection import Collection
|
||||
from anki.collection import Collection, ConfigBoolKey
|
||||
from anki.consts import *
|
||||
from anki.lang import without_unicode_isolation
|
||||
from anki.models import NoteType
|
||||
|
@ -827,13 +827,13 @@ QTableView {{ gridline-color: {grid} }}
|
|||
# default to descending for non-text fields
|
||||
if type == "noteFld":
|
||||
ord = not ord
|
||||
self.col.conf["sortBackwards"] = ord
|
||||
self.col.set_config_bool(ConfigBoolKey.BROWSER_SORT_BACKWARDS, ord)
|
||||
self.col.setMod()
|
||||
self.col.save()
|
||||
self.search()
|
||||
else:
|
||||
if self.col.conf["sortBackwards"] != ord:
|
||||
self.col.conf["sortBackwards"] = ord
|
||||
if self.col.get_config_bool(ConfigBoolKey.BROWSER_SORT_BACKWARDS) != ord:
|
||||
self.col.set_config_bool(ConfigBoolKey.BROWSER_SORT_BACKWARDS, ord)
|
||||
self.col.setMod()
|
||||
self.col.save()
|
||||
self.model.reverse()
|
||||
|
@ -846,7 +846,7 @@ QTableView {{ gridline-color: {grid} }}
|
|||
hh.setSortIndicatorShown(False)
|
||||
return
|
||||
idx = self.model.activeCols.index(type)
|
||||
if self.col.conf["sortBackwards"]:
|
||||
if self.col.get_config_bool(ConfigBoolKey.BROWSER_SORT_BACKWARDS):
|
||||
ord = Qt.DescendingOrder
|
||||
else:
|
||||
ord = Qt.AscendingOrder
|
||||
|
|
|
@ -7,6 +7,7 @@ import time
|
|||
from typing import Any, Callable, Optional, Union
|
||||
|
||||
from anki.cards import Card
|
||||
from anki.collection import ConfigBoolKey
|
||||
from aqt import AnkiQt, gui_hooks
|
||||
from aqt.qt import (
|
||||
QAbstractItemView,
|
||||
|
@ -87,7 +88,9 @@ class Previewer(QDialog):
|
|||
both_sides_button.setShortcut(QKeySequence("B"))
|
||||
both_sides_button.setToolTip(tr(TR.ACTIONS_SHORTCUT_KEY, val="B"))
|
||||
self.bbox.addButton(both_sides_button, QDialogButtonBox.ActionRole)
|
||||
self._show_both_sides = self.mw.col.conf.get("previewBothSides", False)
|
||||
self._show_both_sides = self.mw.col.get_config_bool(
|
||||
ConfigBoolKey.PREVIEW_BOTH_SIDES
|
||||
)
|
||||
both_sides_button.setChecked(self._show_both_sides)
|
||||
qconnect(both_sides_button.toggled, self._on_show_both_sides)
|
||||
|
||||
|
@ -213,7 +216,7 @@ class Previewer(QDialog):
|
|||
|
||||
def _on_show_both_sides(self, toggle):
|
||||
self._show_both_sides = toggle
|
||||
self.mw.col.conf["previewBothSides"] = toggle
|
||||
self.mw.col.set_config_bool(ConfigBoolKey.PREVIEW_BOTH_SIDES, toggle)
|
||||
self.mw.col.setMod()
|
||||
if self._state == "answer" and not toggle:
|
||||
self._state = "question"
|
||||
|
|
|
@ -220,6 +220,8 @@ service BackendService {
|
|||
rpc SetConfigJson(SetConfigJsonIn) returns (Empty);
|
||||
rpc RemoveConfig(String) returns (Empty);
|
||||
rpc GetAllConfig(Empty) returns (Json);
|
||||
rpc GetConfigBool(ConfigBool) returns (Bool);
|
||||
rpc SetConfigBool(SetConfigBoolIn) returns (Empty);
|
||||
|
||||
// preferences
|
||||
|
||||
|
@ -1186,3 +1188,16 @@ message SetDeckIn {
|
|||
repeated int64 card_ids = 1;
|
||||
int64 deck_id = 2;
|
||||
}
|
||||
|
||||
message ConfigBool {
|
||||
enum Key {
|
||||
BROWSER_SORT_BACKWARDS = 0;
|
||||
PREVIEW_BOTH_SIDES = 1;
|
||||
}
|
||||
Key key = 1;
|
||||
}
|
||||
|
||||
message SetConfigBoolIn {
|
||||
ConfigBool.Key key = 1;
|
||||
bool value = 2;
|
||||
}
|
||||
|
|
|
@ -1429,6 +1429,19 @@ impl BackendService for Backend {
|
|||
self.with_col(|col| col.transact(None, |col| col.set_preferences(input)))
|
||||
.map(Into::into)
|
||||
}
|
||||
|
||||
fn get_config_bool(&self, input: pb::ConfigBool) -> BackendResult<pb::Bool> {
|
||||
self.with_col(|col| {
|
||||
Ok(pb::Bool {
|
||||
val: col.get_bool(input),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn set_config_bool(&self, input: pb::SetConfigBoolIn) -> BackendResult<pb::Empty> {
|
||||
self.with_col(|col| col.transact(None, |col| col.set_bool(input)))
|
||||
.map(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
impl Backend {
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
use crate::{
|
||||
collection::Collection, decks::DeckID, err::Result, notetype::NoteTypeID,
|
||||
backend_proto as pb, collection::Collection, decks::DeckID, err::Result, notetype::NoteTypeID,
|
||||
timestamp::TimestampSecs,
|
||||
};
|
||||
use pb::config_bool::Key as BoolKey;
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use serde_aux::field_attributes::deserialize_bool_from_anything;
|
||||
use serde_derive::Deserialize;
|
||||
|
@ -52,6 +53,7 @@ pub(crate) enum ConfigKey {
|
|||
NewReviewMix,
|
||||
NextNewCardPosition,
|
||||
NormalizeNoteText,
|
||||
PreviewBothSides,
|
||||
Rollover,
|
||||
SchedulerVersion,
|
||||
ShowDayLearningCardsFirst,
|
||||
|
@ -83,6 +85,7 @@ impl From<ConfigKey> for &'static str {
|
|||
ConfigKey::NewReviewMix => "newSpread",
|
||||
ConfigKey::NextNewCardPosition => "nextPos",
|
||||
ConfigKey::NormalizeNoteText => "normalize_note_text",
|
||||
ConfigKey::PreviewBothSides => "previewBothSides",
|
||||
ConfigKey::Rollover => "rollover",
|
||||
ConfigKey::SchedulerVersion => "schedVer",
|
||||
ConfigKey::ShowDayLearningCardsFirst => "dayLearnFirst",
|
||||
|
@ -92,6 +95,15 @@ impl From<ConfigKey> for &'static str {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<BoolKey> for ConfigKey {
|
||||
fn from(key: BoolKey) -> Self {
|
||||
match key {
|
||||
BoolKey::BrowserSortBackwards => ConfigKey::BrowserSortReverse,
|
||||
BoolKey::PreviewBothSides => ConfigKey::PreviewBothSides,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This is a workaround for old clients that used ints to represent boolean
|
||||
/// values. For new config items, prefer using a bool directly.
|
||||
#[derive(Deserialize, Default)]
|
||||
|
@ -310,6 +322,18 @@ impl Collection {
|
|||
pub(crate) fn set_last_unburied_day(&self, day: u32) -> Result<()> {
|
||||
self.set_config(ConfigKey::LastUnburiedDay, &day)
|
||||
}
|
||||
|
||||
#[allow(clippy::match_single_binding)]
|
||||
pub(crate) fn get_bool(&self, config: pb::ConfigBool) -> bool {
|
||||
match config.key() {
|
||||
// all options default to false at the moment
|
||||
other => self.get_config_default(ConfigKey::from(other)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn set_bool(&self, input: pb::SetConfigBoolIn) -> Result<()> {
|
||||
self.set_config(ConfigKey::from(input.key()), &input.value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, PartialEq, Debug, Clone, Copy)]
|
||||
|
|
Loading…
Reference in a new issue