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 import weakref
from typing import TYPE_CHECKING, Any, List, Optional, Sequence, Tuple, Union from typing import TYPE_CHECKING, Any, List, Optional, Sequence, Tuple, Union
import anki.backend_pb2 as pb
import anki.find import anki.find
import anki.latex # sets up hook import anki.latex # sets up hook
import anki.template import anki.template
@ -32,16 +33,19 @@ from anki.rsbackend import (
Progress, Progress,
RustBackend, RustBackend,
from_json_bytes, from_json_bytes,
pb,
) )
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.tags import TagManager from anki.tags import TagManager
from anki.utils import devMode, ids2str, intTime from anki.utils import devMode, ids2str, intTime
ConfigBoolKey = pb.ConfigBool.Key # pylint: disable=no-member
if TYPE_CHECKING: if TYPE_CHECKING:
from anki.rsbackend import FormatTimeSpanContextValue, TRValue from anki.rsbackend import FormatTimeSpanContextValue, TRValue
ConfigBoolKeyValue = pb.ConfigBool.KeyValue # pylint: disable=no-member
class Collection: class Collection:
sched: Union[V1Scheduler, V2Scheduler] 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." "This is a debugging aid. Prefer .get_config() when you know the key you need."
return from_json_bytes(self.backend.get_all_config()) 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 # Stats
########################################################################## ##########################################################################

View file

@ -38,6 +38,9 @@ if TYPE_CHECKING:
assert anki._rsbridge.buildhash() == anki.buildinfo.buildhash 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 SchedTimingToday = pb.SchedTimingTodayOut
BuiltinSortKind = pb.BuiltinSearchOrder.BuiltinSortKind BuiltinSortKind = pb.BuiltinSearchOrder.BuiltinSortKind
BackendCard = pb.Card BackendCard = pb.Card

View file

@ -1,6 +1,7 @@
# coding: utf-8 # coding: utf-8
import pytest import pytest
from anki.collection import ConfigBoolKey
from anki.consts import * from anki.consts import *
from anki.rsbackend import BuiltinSortKind from anki.rsbackend import BuiltinSortKind
from tests.shared import getEmptyCol, isNearCutoff from tests.shared import getEmptyCol, isNearCutoff
@ -121,7 +122,7 @@ def test_findCards():
col.flush() col.flush()
assert col.findCards("", order=True)[-1] in latestCardIds assert col.findCards("", order=True)[-1] in latestCardIds
assert col.findCards("", order=True)[0] == firstCardId assert col.findCards("", order=True)[0] == firstCardId
col.conf["sortBackwards"] = True col.set_config_bool(ConfigBoolKey.BROWSER_SORT_BACKWARDS, True)
col.flush() col.flush()
assert col.findCards("", order=True)[0] in latestCardIds assert col.findCards("", order=True)[0] in latestCardIds
assert ( assert (

View file

@ -13,7 +13,7 @@ from typing import List, Optional, Sequence, Tuple, cast
import aqt import aqt
import aqt.forms import aqt.forms
from anki.cards import Card from anki.cards import Card
from anki.collection import Collection from anki.collection import Collection, ConfigBoolKey
from anki.consts import * from anki.consts import *
from anki.lang import without_unicode_isolation from anki.lang import without_unicode_isolation
from anki.models import NoteType from anki.models import NoteType
@ -827,13 +827,13 @@ QTableView {{ gridline-color: {grid} }}
# default to descending for non-text fields # default to descending for non-text fields
if type == "noteFld": if type == "noteFld":
ord = not ord ord = not ord
self.col.conf["sortBackwards"] = ord self.col.set_config_bool(ConfigBoolKey.BROWSER_SORT_BACKWARDS, ord)
self.col.setMod() self.col.setMod()
self.col.save() self.col.save()
self.search() self.search()
else: else:
if self.col.conf["sortBackwards"] != ord: if self.col.get_config_bool(ConfigBoolKey.BROWSER_SORT_BACKWARDS) != ord:
self.col.conf["sortBackwards"] = ord self.col.set_config_bool(ConfigBoolKey.BROWSER_SORT_BACKWARDS, ord)
self.col.setMod() self.col.setMod()
self.col.save() self.col.save()
self.model.reverse() self.model.reverse()
@ -846,7 +846,7 @@ QTableView {{ gridline-color: {grid} }}
hh.setSortIndicatorShown(False) hh.setSortIndicatorShown(False)
return return
idx = self.model.activeCols.index(type) idx = self.model.activeCols.index(type)
if self.col.conf["sortBackwards"]: if self.col.get_config_bool(ConfigBoolKey.BROWSER_SORT_BACKWARDS):
ord = Qt.DescendingOrder ord = Qt.DescendingOrder
else: else:
ord = Qt.AscendingOrder ord = Qt.AscendingOrder

View file

@ -7,6 +7,7 @@ import time
from typing import Any, Callable, Optional, Union from typing import Any, Callable, Optional, Union
from anki.cards import Card from anki.cards import Card
from anki.collection import ConfigBoolKey
from aqt import AnkiQt, gui_hooks from aqt import AnkiQt, gui_hooks
from aqt.qt import ( from aqt.qt import (
QAbstractItemView, QAbstractItemView,
@ -87,7 +88,9 @@ class Previewer(QDialog):
both_sides_button.setShortcut(QKeySequence("B")) both_sides_button.setShortcut(QKeySequence("B"))
both_sides_button.setToolTip(tr(TR.ACTIONS_SHORTCUT_KEY, val="B")) both_sides_button.setToolTip(tr(TR.ACTIONS_SHORTCUT_KEY, val="B"))
self.bbox.addButton(both_sides_button, QDialogButtonBox.ActionRole) 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) both_sides_button.setChecked(self._show_both_sides)
qconnect(both_sides_button.toggled, self._on_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): def _on_show_both_sides(self, toggle):
self._show_both_sides = 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() self.mw.col.setMod()
if self._state == "answer" and not toggle: if self._state == "answer" and not toggle:
self._state = "question" self._state = "question"

View file

@ -220,6 +220,8 @@ service BackendService {
rpc SetConfigJson(SetConfigJsonIn) returns (Empty); rpc SetConfigJson(SetConfigJsonIn) returns (Empty);
rpc RemoveConfig(String) returns (Empty); rpc RemoveConfig(String) returns (Empty);
rpc GetAllConfig(Empty) returns (Json); rpc GetAllConfig(Empty) returns (Json);
rpc GetConfigBool(ConfigBool) returns (Bool);
rpc SetConfigBool(SetConfigBoolIn) returns (Empty);
// preferences // preferences
@ -1186,3 +1188,16 @@ message SetDeckIn {
repeated int64 card_ids = 1; repeated int64 card_ids = 1;
int64 deck_id = 2; 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))) self.with_col(|col| col.transact(None, |col| col.set_preferences(input)))
.map(Into::into) .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 { impl Backend {

View file

@ -2,9 +2,10 @@
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use crate::{ use crate::{
collection::Collection, decks::DeckID, err::Result, notetype::NoteTypeID, backend_proto as pb, collection::Collection, decks::DeckID, err::Result, notetype::NoteTypeID,
timestamp::TimestampSecs, timestamp::TimestampSecs,
}; };
use pb::config_bool::Key as BoolKey;
use serde::{de::DeserializeOwned, Serialize}; use serde::{de::DeserializeOwned, Serialize};
use serde_aux::field_attributes::deserialize_bool_from_anything; use serde_aux::field_attributes::deserialize_bool_from_anything;
use serde_derive::Deserialize; use serde_derive::Deserialize;
@ -52,6 +53,7 @@ pub(crate) enum ConfigKey {
NewReviewMix, NewReviewMix,
NextNewCardPosition, NextNewCardPosition,
NormalizeNoteText, NormalizeNoteText,
PreviewBothSides,
Rollover, Rollover,
SchedulerVersion, SchedulerVersion,
ShowDayLearningCardsFirst, ShowDayLearningCardsFirst,
@ -83,6 +85,7 @@ impl From<ConfigKey> for &'static str {
ConfigKey::NewReviewMix => "newSpread", ConfigKey::NewReviewMix => "newSpread",
ConfigKey::NextNewCardPosition => "nextPos", ConfigKey::NextNewCardPosition => "nextPos",
ConfigKey::NormalizeNoteText => "normalize_note_text", ConfigKey::NormalizeNoteText => "normalize_note_text",
ConfigKey::PreviewBothSides => "previewBothSides",
ConfigKey::Rollover => "rollover", ConfigKey::Rollover => "rollover",
ConfigKey::SchedulerVersion => "schedVer", ConfigKey::SchedulerVersion => "schedVer",
ConfigKey::ShowDayLearningCardsFirst => "dayLearnFirst", 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 /// This is a workaround for old clients that used ints to represent boolean
/// values. For new config items, prefer using a bool directly. /// values. For new config items, prefer using a bool directly.
#[derive(Deserialize, Default)] #[derive(Deserialize, Default)]
@ -310,6 +322,18 @@ impl Collection {
pub(crate) fn set_last_unburied_day(&self, day: u32) -> Result<()> { pub(crate) fn set_last_unburied_day(&self, day: u32) -> Result<()> {
self.set_config(ConfigKey::LastUnburiedDay, &day) 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)] #[derive(Deserialize, PartialEq, Debug, Clone, Copy)]