add getter/setter for boolean config values

This commit is contained in:
Damien Elmes 2021-01-29 21:03:19 +10:00
parent a9be60c8b4
commit 5ff7944a26
8 changed files with 80 additions and 10 deletions

View file

@ -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
##########################################################################

View file

@ -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

View file

@ -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 (

View file

@ -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

View file

@ -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"

View file

@ -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;
}

View file

@ -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 {

View file

@ -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)]