mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 16:56:36 -04:00
drop the special config for top level decks
New/rev card mixing, collapse time and the timeboxing limit are now a collection property. I appreciate how it could be useful to have those settings per top-level deck in some cases, but having some settings inherited from the top level deck makes for a confusing UI.
This commit is contained in:
parent
8c9c3489e5
commit
451962d4a8
7 changed files with 18 additions and 89 deletions
|
@ -21,9 +21,12 @@ import anki.cards, anki.notes, anki.template, anki.cram, anki.find
|
||||||
defaultConf = {
|
defaultConf = {
|
||||||
# scheduling options
|
# scheduling options
|
||||||
'activeDecks': [1],
|
'activeDecks': [1],
|
||||||
'topDeck': 1,
|
|
||||||
'curDeck': 1,
|
'curDeck': 1,
|
||||||
|
'newSpread': NEW_CARDS_DISTRIBUTE,
|
||||||
|
'collapseTime': 1200,
|
||||||
|
'timeLim': 0,
|
||||||
# other config
|
# other config
|
||||||
|
'curModel': None,
|
||||||
'nextPos': 1,
|
'nextPos': 1,
|
||||||
'sortType': "noteFld",
|
'sortType': "noteFld",
|
||||||
'sortBackwards': False,
|
'sortBackwards': False,
|
||||||
|
|
|
@ -9,20 +9,7 @@ from anki.lang import _
|
||||||
|
|
||||||
# fixmes:
|
# fixmes:
|
||||||
# - make sure users can't set grad interval < 1
|
# - make sure users can't set grad interval < 1
|
||||||
# - make sure lists like new[delays] are not being shared by multiple decks
|
|
||||||
# - make sure all children have parents (create as necessary)
|
|
||||||
# - when renaming a deck, top level properties should be added or removed as
|
|
||||||
# appropriate
|
|
||||||
|
|
||||||
# notes:
|
|
||||||
# - it's difficult to enforce valid dids for models/notes/cards, as we
|
|
||||||
# may update the did locally only to have it overwritten by a more recent
|
|
||||||
# change from somewhere else. to avoid this, we allow invalid did
|
|
||||||
# references, and treat any invalid dids as the default deck.
|
|
||||||
# - deletions of deck config force a full sync
|
|
||||||
|
|
||||||
# these are a cache of the current day's reviews. they may be wrong after a
|
|
||||||
# sync merge if someone reviewed from two locations
|
|
||||||
defaultDeck = {
|
defaultDeck = {
|
||||||
'newToday': [0, 0], # currentDay, count
|
'newToday': [0, 0], # currentDay, count
|
||||||
'revToday': [0, 0],
|
'revToday': [0, 0],
|
||||||
|
@ -32,16 +19,6 @@ defaultDeck = {
|
||||||
'usn': 0,
|
'usn': 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
# configuration only available to top level decks
|
|
||||||
defaultTopConf = {
|
|
||||||
'newSpread': NEW_CARDS_DISTRIBUTE,
|
|
||||||
'collapseTime': 1200,
|
|
||||||
'repLim': 0,
|
|
||||||
'timeLim': 600,
|
|
||||||
'curModel': None,
|
|
||||||
}
|
|
||||||
|
|
||||||
# configuration available to all decks
|
|
||||||
defaultConf = {
|
defaultConf = {
|
||||||
'name': _("Default"),
|
'name': _("Default"),
|
||||||
'new': {
|
'new': {
|
||||||
|
@ -117,15 +94,10 @@ class DeckManager(object):
|
||||||
return int(id)
|
return int(id)
|
||||||
if not create:
|
if not create:
|
||||||
return None
|
return None
|
||||||
if "::" not in name:
|
g = copy.deepcopy(defaultDeck)
|
||||||
# if it's a top level deck, it gets the top level config
|
if "::" in name:
|
||||||
g = defaultTopConf.copy()
|
|
||||||
else:
|
|
||||||
# not top level; ensure all parents exist
|
# not top level; ensure all parents exist
|
||||||
g = {}
|
|
||||||
self._ensureParents(name)
|
self._ensureParents(name)
|
||||||
for (k,v) in defaultDeck.items():
|
|
||||||
g[k] = v
|
|
||||||
g['name'] = name
|
g['name'] = name
|
||||||
while 1:
|
while 1:
|
||||||
id = intTime(1000)
|
id = intTime(1000)
|
||||||
|
@ -192,13 +164,6 @@ class DeckManager(object):
|
||||||
grp['name'] = grp['name'].replace(g['name']+ "::",
|
grp['name'] = grp['name'].replace(g['name']+ "::",
|
||||||
newName + "::")
|
newName + "::")
|
||||||
self.save(grp)
|
self.save(grp)
|
||||||
# adjust top level conf
|
|
||||||
if "::" in newName and "::" not in g['name']:
|
|
||||||
for k in defaultTopConf.keys():
|
|
||||||
del g[k]
|
|
||||||
elif "::" not in newName and "::" in g['name']:
|
|
||||||
for k,v in defaultTopConf.items():
|
|
||||||
g[k] = v
|
|
||||||
# adjust name and save
|
# adjust name and save
|
||||||
g['name'] = newName
|
g['name'] = newName
|
||||||
self.save(g)
|
self.save(g)
|
||||||
|
@ -284,16 +249,6 @@ usn=?,mod=? where id in %s""" % ids2str(cids),
|
||||||
# Deck selection
|
# Deck selection
|
||||||
#############################################################
|
#############################################################
|
||||||
|
|
||||||
def top(self):
|
|
||||||
"The current top level deck as an object."
|
|
||||||
g = self.get(self.col.conf['topDeck'])
|
|
||||||
return g
|
|
||||||
|
|
||||||
def topIds(self):
|
|
||||||
"All dids from top level."
|
|
||||||
t = self.top()
|
|
||||||
return [t['id']] + [a[1] for a in self.children(t['id'])]
|
|
||||||
|
|
||||||
def active(self):
|
def active(self):
|
||||||
"The currrently active dids."
|
"The currrently active dids."
|
||||||
return self.col.conf['activeDecks']
|
return self.col.conf['activeDecks']
|
||||||
|
@ -307,9 +262,7 @@ usn=?,mod=? where id in %s""" % ids2str(cids),
|
||||||
|
|
||||||
def select(self, did):
|
def select(self, did):
|
||||||
"Select a new branch."
|
"Select a new branch."
|
||||||
# save the top level deck
|
|
||||||
name = self.decks[str(did)]['name']
|
name = self.decks[str(did)]['name']
|
||||||
self.col.conf['topDeck'] = self._topFor(name)
|
|
||||||
# current deck
|
# current deck
|
||||||
self.col.conf['curDeck'] = did
|
self.col.conf['curDeck'] = did
|
||||||
# and active decks (current + all children)
|
# and active decks (current + all children)
|
||||||
|
@ -332,11 +285,6 @@ usn=?,mod=? where id in %s""" % ids2str(cids),
|
||||||
path = self.get(did)['name'].split("::")
|
path = self.get(did)['name'].split("::")
|
||||||
return [self.get(x) for x in path[:-1]]
|
return [self.get(x) for x in path[:-1]]
|
||||||
|
|
||||||
def _topFor(self, name):
|
|
||||||
"The top level did for NAME."
|
|
||||||
path = name.split("::")
|
|
||||||
return self.id(path[0])
|
|
||||||
|
|
||||||
# Sync handling
|
# Sync handling
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
|
|
|
@ -87,17 +87,12 @@ class ModelManager(object):
|
||||||
|
|
||||||
def current(self):
|
def current(self):
|
||||||
"Get current model."
|
"Get current model."
|
||||||
try:
|
m = self.get(self.col.conf['curModel'])
|
||||||
m = self.get(self.col.decks.top()['curModel'])
|
return m or self.models.values()[0]
|
||||||
assert m
|
|
||||||
return m
|
|
||||||
except:
|
|
||||||
return self.models.values()[0]
|
|
||||||
|
|
||||||
def setCurrent(self, m):
|
def setCurrent(self, m):
|
||||||
t = self.col.decks.top()
|
self.col.conf['curModel'] = m['id']
|
||||||
t['curModel'] = m['id']
|
self.col.setMod()
|
||||||
self.col.decks.save(t)
|
|
||||||
|
|
||||||
def get(self, id):
|
def get(self, id):
|
||||||
"Get model with ID, or None."
|
"Get model with ID, or None."
|
||||||
|
|
|
@ -276,7 +276,7 @@ select id, due from cards where did = ? and queue = 0 limit ?""", did, lim)
|
||||||
return self.col.getCard(id)
|
return self.col.getCard(id)
|
||||||
|
|
||||||
def _updateNewCardRatio(self):
|
def _updateNewCardRatio(self):
|
||||||
if self.col.decks.top()['newSpread'] == NEW_CARDS_DISTRIBUTE:
|
if self.col.conf['newSpread'] == NEW_CARDS_DISTRIBUTE:
|
||||||
if self.newCount:
|
if self.newCount:
|
||||||
self.newCardModulus = (
|
self.newCardModulus = (
|
||||||
(self.newCount + self.revCount) / self.newCount)
|
(self.newCount + self.revCount) / self.newCount)
|
||||||
|
@ -290,9 +290,9 @@ select id, due from cards where did = ? and queue = 0 limit ?""", did, lim)
|
||||||
"True if it's time to display a new card when distributing."
|
"True if it's time to display a new card when distributing."
|
||||||
if not self.newCount:
|
if not self.newCount:
|
||||||
return False
|
return False
|
||||||
if self.col.decks.top()['newSpread'] == NEW_CARDS_LAST:
|
if self.col.conf['newSpread'] == NEW_CARDS_LAST:
|
||||||
return False
|
return False
|
||||||
elif self.col.decks.top()['newSpread'] == NEW_CARDS_FIRST:
|
elif self.col.conf['newSpread'] == NEW_CARDS_FIRST:
|
||||||
return True
|
return True
|
||||||
elif self.newCardModulus:
|
elif self.newCardModulus:
|
||||||
return self.reps and self.reps % self.newCardModulus == 0
|
return self.reps and self.reps % self.newCardModulus == 0
|
||||||
|
@ -352,7 +352,7 @@ limit %d""" % (self._deckLimit(), self.reportLimit), lim=self.dayCutoff)
|
||||||
if self._fillLrn():
|
if self._fillLrn():
|
||||||
cutoff = time.time()
|
cutoff = time.time()
|
||||||
if collapse:
|
if collapse:
|
||||||
cutoff += self.col.decks.top()['collapseTime']
|
cutoff += self.col.conf['collapseTime']
|
||||||
if self._lrnQueue[0][0] < cutoff:
|
if self._lrnQueue[0][0] < cutoff:
|
||||||
id = heappop(self._lrnQueue)[1]
|
id = heappop(self._lrnQueue)[1]
|
||||||
card = self.col.getCard(id)
|
card = self.col.getCard(id)
|
||||||
|
@ -467,7 +467,7 @@ where queue = 1 and type = 2
|
||||||
return self.col.db.scalar(
|
return self.col.db.scalar(
|
||||||
"select 1 from cards where did = ? and queue = 1 "
|
"select 1 from cards where did = ? and queue = 1 "
|
||||||
"and due < ? limit 1",
|
"and due < ? limit 1",
|
||||||
did, intTime() + self.col.decks.top()['collapseTime'])
|
did, intTime() + self.col.conf['collapseTime'])
|
||||||
|
|
||||||
# Reviews
|
# Reviews
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
|
@ -140,8 +140,6 @@ def _getColVars(db):
|
||||||
import anki.collection
|
import anki.collection
|
||||||
import anki.decks
|
import anki.decks
|
||||||
g = anki.decks.defaultDeck.copy()
|
g = anki.decks.defaultDeck.copy()
|
||||||
for k,v in anki.decks.defaultTopConf.items():
|
|
||||||
g[k] = v
|
|
||||||
g['id'] = 1
|
g['id'] = 1
|
||||||
g['name'] = _("Default")
|
g['name'] = _("Default")
|
||||||
g['conf'] = 1
|
g['conf'] = 1
|
||||||
|
|
|
@ -17,23 +17,19 @@ def test_basic():
|
||||||
# we start with the default deck selected
|
# we start with the default deck selected
|
||||||
assert deck.decks.selected() == 1
|
assert deck.decks.selected() == 1
|
||||||
assert deck.decks.active() == [1]
|
assert deck.decks.active() == [1]
|
||||||
assert deck.decks.top()['id'] == 1
|
|
||||||
# we can select a different deck
|
# we can select a different deck
|
||||||
deck.decks.select(parentId)
|
deck.decks.select(parentId)
|
||||||
assert deck.decks.selected() == parentId
|
assert deck.decks.selected() == parentId
|
||||||
assert deck.decks.active() == [parentId]
|
assert deck.decks.active() == [parentId]
|
||||||
assert deck.decks.top()['id'] == parentId
|
|
||||||
# let's create a child
|
# let's create a child
|
||||||
childId = deck.decks.id("new deck::child")
|
childId = deck.decks.id("new deck::child")
|
||||||
# it should have been added to the active list
|
# it should have been added to the active list
|
||||||
assert deck.decks.selected() == parentId
|
assert deck.decks.selected() == parentId
|
||||||
assert deck.decks.active() == [parentId, childId]
|
assert deck.decks.active() == [parentId, childId]
|
||||||
assert deck.decks.top()['id'] == parentId
|
|
||||||
# we can select the child individually too
|
# we can select the child individually too
|
||||||
deck.decks.select(childId)
|
deck.decks.select(childId)
|
||||||
assert deck.decks.selected() == childId
|
assert deck.decks.selected() == childId
|
||||||
assert deck.decks.active() == [childId]
|
assert deck.decks.active() == [childId]
|
||||||
assert deck.decks.top()['id'] == parentId
|
|
||||||
|
|
||||||
def test_remove():
|
def test_remove():
|
||||||
deck = getEmptyDeck()
|
deck = getEmptyDeck()
|
||||||
|
@ -83,14 +79,3 @@ def test_rename():
|
||||||
d.decks.rename(d.decks.get(id), "yo")
|
d.decks.rename(d.decks.get(id), "yo")
|
||||||
for n in "yo", "yo::two", "yo::two::three":
|
for n in "yo", "yo::two", "yo::two::three":
|
||||||
assert n in d.decks.allNames()
|
assert n in d.decks.allNames()
|
||||||
|
|
||||||
def test_topRename():
|
|
||||||
d = getEmptyDeck()
|
|
||||||
id = d.decks.id("hello::world")
|
|
||||||
# when moving to or from top level, properties should be updated
|
|
||||||
assert 'newSpread' in d.decks.get(d.decks.id("hello"))
|
|
||||||
assert 'newSpread' not in d.decks.get(d.decks.id("hello::world"))
|
|
||||||
d.decks.rename(d.decks.get(d.decks.id("hello")), "foo::bar")
|
|
||||||
assert 'newSpread' not in d.decks.get(d.decks.id("foo::bar"))
|
|
||||||
d.decks.rename(d.decks.get(d.decks.id("foo::bar")), "hello")
|
|
||||||
assert 'newSpread' in d.decks.get(d.decks.id("hello"))
|
|
||||||
|
|
|
@ -202,12 +202,12 @@ def test_decks():
|
||||||
@nose.with_setup(setup_modified)
|
@nose.with_setup(setup_modified)
|
||||||
def test_conf():
|
def test_conf():
|
||||||
test_sync()
|
test_sync()
|
||||||
assert deck2.conf['topDeck'] == 1
|
assert deck2.conf['curDeck'] == 1
|
||||||
deck1.conf['topDeck'] = 2
|
deck1.conf['curDeck'] = 2
|
||||||
deck1.setMod()
|
deck1.setMod()
|
||||||
deck1.save()
|
deck1.save()
|
||||||
assert client.sync() == "success"
|
assert client.sync() == "success"
|
||||||
assert deck2.conf['topDeck'] == 2
|
assert deck2.conf['curDeck'] == 2
|
||||||
|
|
||||||
@nose.with_setup(setup_modified)
|
@nose.with_setup(setup_modified)
|
||||||
def test_threeway():
|
def test_threeway():
|
||||||
|
|
Loading…
Reference in a new issue