mirror of
https://github.com/ankitects/anki.git
synced 2025-09-22 16:02:23 -04:00
move group code into a registry like models
This commit is contained in:
parent
d3a3edb707
commit
78600e8ed6
7 changed files with 89 additions and 65 deletions
58
anki/deck.py
58
anki/deck.py
|
@ -11,12 +11,12 @@ from anki.hooks import runHook, runFilter
|
||||||
from anki.sched import Scheduler
|
from anki.sched import Scheduler
|
||||||
from anki.models import ModelRegistry
|
from anki.models import ModelRegistry
|
||||||
from anki.media import MediaRegistry
|
from anki.media import MediaRegistry
|
||||||
|
from anki.groups import GroupRegistry
|
||||||
from anki.consts import *
|
from anki.consts import *
|
||||||
from anki.errors import AnkiError
|
from anki.errors import AnkiError
|
||||||
|
|
||||||
import anki.latex # sets up hook
|
import anki.latex # sets up hook
|
||||||
import anki.cards, anki.facts, anki.template, anki.cram, \
|
import anki.cards, anki.facts, anki.template, anki.cram, anki.find
|
||||||
anki.groups, anki.find
|
|
||||||
|
|
||||||
# Settings related to queue building. These may be loaded without the rest of
|
# Settings related to queue building. These may be loaded without the rest of
|
||||||
# the config to check due counts faster on mobile clients.
|
# the config to check due counts faster on mobile clients.
|
||||||
|
@ -54,6 +54,7 @@ class _Deck(object):
|
||||||
self.clearUndo()
|
self.clearUndo()
|
||||||
self.media = MediaRegistry(self)
|
self.media = MediaRegistry(self)
|
||||||
self.models = ModelRegistry(self)
|
self.models = ModelRegistry(self)
|
||||||
|
self.groups = GroupRegistry(self)
|
||||||
self.load()
|
self.load()
|
||||||
if not self.crt:
|
if not self.crt:
|
||||||
d = datetime.datetime.today()
|
d = datetime.datetime.today()
|
||||||
|
@ -88,15 +89,14 @@ class _Deck(object):
|
||||||
self.qconf,
|
self.qconf,
|
||||||
self.conf,
|
self.conf,
|
||||||
models,
|
models,
|
||||||
self.groups,
|
groups,
|
||||||
self.gconf) = self.db.first("""
|
gconf) = self.db.first("""
|
||||||
select crt, mod, scm, dty, syncName, lastSync,
|
select crt, mod, scm, dty, syncName, lastSync,
|
||||||
qconf, conf, models, groups, gconf from deck""")
|
qconf, conf, models, groups, gconf from deck""")
|
||||||
self.qconf = simplejson.loads(self.qconf)
|
self.qconf = simplejson.loads(self.qconf)
|
||||||
self.conf = simplejson.loads(self.conf)
|
self.conf = simplejson.loads(self.conf)
|
||||||
self.groups = simplejson.loads(self.groups)
|
|
||||||
self.gconf = simplejson.loads(self.gconf)
|
|
||||||
self.models.load(models)
|
self.models.load(models)
|
||||||
|
self.groups.load(groups, gconf)
|
||||||
|
|
||||||
def flush(self, mod=None):
|
def flush(self, mod=None):
|
||||||
"Flush state to DB, updating mod time."
|
"Flush state to DB, updating mod time."
|
||||||
|
@ -104,14 +104,13 @@ qconf, conf, models, groups, gconf from deck""")
|
||||||
self.db.execute(
|
self.db.execute(
|
||||||
"""update deck set
|
"""update deck set
|
||||||
crt=?, mod=?, scm=?, dty=?, syncName=?, lastSync=?,
|
crt=?, mod=?, scm=?, dty=?, syncName=?, lastSync=?,
|
||||||
qconf=?, conf=?, groups=?, gconf=?""",
|
qconf=?, conf=?""",
|
||||||
self.crt, self.mod, self.scm, self.dty,
|
self.crt, self.mod, self.scm, self.dty,
|
||||||
self.syncName, self.lastSync,
|
self.syncName, self.lastSync,
|
||||||
simplejson.dumps(self.qconf),
|
simplejson.dumps(self.qconf),
|
||||||
simplejson.dumps(self.conf),
|
simplejson.dumps(self.conf))
|
||||||
simplejson.dumps(self.groups),
|
|
||||||
simplejson.dumps(self.gconf))
|
|
||||||
self.models.flush()
|
self.models.flush()
|
||||||
|
self.groups.flush()
|
||||||
|
|
||||||
def save(self, name=None, mod=None):
|
def save(self, name=None, mod=None):
|
||||||
"Flush, commit DB, and take out another write lock."
|
"Flush, commit DB, and take out another write lock."
|
||||||
|
@ -420,7 +419,7 @@ select id from facts where id in %s and id not in (select fid from cards)""" %
|
||||||
fields[name] = ""
|
fields[name] = ""
|
||||||
fields['Tags'] = data[5]
|
fields['Tags'] = data[5]
|
||||||
fields['Model'] = model['name']
|
fields['Model'] = model['name']
|
||||||
fields['Group'] = self.groupName(data[3])
|
fields['Group'] = self.groups.name(data[3])
|
||||||
template = model['tmpls'][data[4]]
|
template = model['tmpls'][data[4]]
|
||||||
fields['Template'] = template['name']
|
fields['Template'] = template['name']
|
||||||
# render q & a
|
# render q & a
|
||||||
|
@ -504,43 +503,6 @@ update facts set tags = :t, mod = :n where id = :id""", [fix(row) for row in res
|
||||||
def delTags(self, ids, tags):
|
def delTags(self, ids, tags):
|
||||||
self.addTags(ids, tags, False)
|
self.addTags(ids, tags, False)
|
||||||
|
|
||||||
# Groups
|
|
||||||
##########################################################################
|
|
||||||
# the id keys are strings because that's the way they're stored in json,
|
|
||||||
# but the anki code passes around integers
|
|
||||||
|
|
||||||
def groupID(self, name, create=True):
|
|
||||||
"Add a group with NAME. Reuse group if already exists. Return id."
|
|
||||||
for id, g in self.groups.items():
|
|
||||||
if g['name'].lower() == name.lower():
|
|
||||||
return int(id)
|
|
||||||
if not create:
|
|
||||||
return None
|
|
||||||
g = dict(name=name, conf=1, mod=intTime())
|
|
||||||
while 1:
|
|
||||||
id = intTime(1000)
|
|
||||||
if str(id) in self.groups:
|
|
||||||
continue
|
|
||||||
self.groups[str(id)] = g
|
|
||||||
return id
|
|
||||||
|
|
||||||
def groupName(self, gid):
|
|
||||||
return self.groups[str(gid)]['name']
|
|
||||||
|
|
||||||
def groupConf(self, gid):
|
|
||||||
return self.gconf[str(self.groups[str(gid)]['conf'])]
|
|
||||||
|
|
||||||
def delGroup(self, gid):
|
|
||||||
self.modSchema()
|
|
||||||
self.db.execute("update cards set gid = 1 where gid = ?", gid)
|
|
||||||
self.db.execute("update facts set gid = 1 where gid = ?", gid)
|
|
||||||
self.db.execute("delete from groups where id = ?", gid)
|
|
||||||
print "fixme: loop through models and update stale gid references"
|
|
||||||
|
|
||||||
def setGroup(self, cids, gid):
|
|
||||||
self.db.execute(
|
|
||||||
"update cards set gid = ? where id in "+ids2str(cids), gid)
|
|
||||||
|
|
||||||
# Tag-based selective study
|
# Tag-based selective study
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
|
|
|
@ -192,8 +192,8 @@ order by %s""" % (lim, sort)
|
||||||
|
|
||||||
def _findGroup(self, val, isNeg):
|
def _findGroup(self, val, isNeg):
|
||||||
extra = "!" if isNeg else ""
|
extra = "!" if isNeg else ""
|
||||||
id = self.deck.groupID(val, create=False) or 0
|
id = self.deck.groups.id(val, create=False) or 0
|
||||||
self.lims['card'].append("c.gid %s= %d" % (extra, id))
|
self.lims['card'].append("c.gid %s= %s" % (extra, id))
|
||||||
|
|
||||||
def _findTemplate(self, val, isNeg):
|
def _findTemplate(self, val, isNeg):
|
||||||
lims = []
|
lims = []
|
||||||
|
|
|
@ -39,3 +39,65 @@ defaultData = {
|
||||||
'activeTags': None,
|
'activeTags': None,
|
||||||
'inactiveTags': None,
|
'inactiveTags': None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class GroupRegistry(object):
|
||||||
|
|
||||||
|
# Registry save/load
|
||||||
|
#############################################################
|
||||||
|
|
||||||
|
def __init__(self, deck):
|
||||||
|
self.deck = deck
|
||||||
|
|
||||||
|
def load(self, groups, gconf):
|
||||||
|
self.groups = simplejson.loads(groups)
|
||||||
|
self.gconf = simplejson.loads(gconf)
|
||||||
|
self.changed = False
|
||||||
|
|
||||||
|
def save(self, g):
|
||||||
|
g['mod'] = intTime()
|
||||||
|
self.changed = True
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
if self.changed:
|
||||||
|
self.deck.db.execute("update deck set groups=?, gconf=?",
|
||||||
|
simplejson.dumps(self.groups),
|
||||||
|
simplejson.dumps(self.gconf))
|
||||||
|
|
||||||
|
# Group save/load
|
||||||
|
#############################################################
|
||||||
|
|
||||||
|
def id(self, name, create=True):
|
||||||
|
"Add a group with NAME. Reuse group if already exists. Return id as int."
|
||||||
|
for id, g in self.groups.items():
|
||||||
|
if g['name'].lower() == name.lower():
|
||||||
|
return int(id)
|
||||||
|
if not create:
|
||||||
|
return None
|
||||||
|
g = dict(name=name, conf=1, mod=intTime())
|
||||||
|
while 1:
|
||||||
|
id = str(intTime(1000))
|
||||||
|
if id in self.groups:
|
||||||
|
continue
|
||||||
|
self.groups[id] = g
|
||||||
|
self.save(g)
|
||||||
|
return int(id)
|
||||||
|
|
||||||
|
def del_(self, gid):
|
||||||
|
self.deck.modSchema()
|
||||||
|
self.deck.db.execute("update cards set gid = 1 where gid = ?", gid)
|
||||||
|
self.deck.db.execute("update facts set gid = 1 where gid = ?", gid)
|
||||||
|
self.deck.db.execute("delete from groups where id = ?", gid)
|
||||||
|
print "fixme: loop through models and update stale gid references"
|
||||||
|
|
||||||
|
# Utils
|
||||||
|
#############################################################
|
||||||
|
|
||||||
|
def name(self, gid):
|
||||||
|
return self.groups[str(gid)]['name']
|
||||||
|
|
||||||
|
def conf(self, gid):
|
||||||
|
return self.gconf[str(self.groups[str(gid)]['conf'])]
|
||||||
|
|
||||||
|
def setGroup(self, cids, gid):
|
||||||
|
self.db.execute(
|
||||||
|
"update cards set gid = ? where id in "+ids2str(cids), gid)
|
||||||
|
|
|
@ -154,7 +154,7 @@ from cards group by gid""", self.today):
|
||||||
for (gid, grp) in self._orderedGroups()]
|
for (gid, grp) in self._orderedGroups()]
|
||||||
|
|
||||||
def _orderedGroups(self):
|
def _orderedGroups(self):
|
||||||
grps = self.deck.groups.items()
|
grps = self.deck.groups.groups.items()
|
||||||
def key(grp):
|
def key(grp):
|
||||||
return grp[1]['name']
|
return grp[1]['name']
|
||||||
grps.sort(key=key)
|
grps.sort(key=key)
|
||||||
|
@ -595,7 +595,7 @@ queue = 2 %s and due <= :lim order by %s limit %d""" % (
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def _cardConf(self, card):
|
def _cardConf(self, card):
|
||||||
return self.deck.groupConf(card.gid)
|
return self.deck.groups.conf(card.gid)
|
||||||
|
|
||||||
def _groupLimit(self):
|
def _groupLimit(self):
|
||||||
l = self.deck.qconf['groups']
|
l = self.deck.qconf['groups']
|
||||||
|
|
|
@ -49,8 +49,8 @@ class CardStats(object):
|
||||||
self.addLine(_("Position"), c.due)
|
self.addLine(_("Position"), c.due)
|
||||||
self.addLine(_("Model"), c.model()['name'])
|
self.addLine(_("Model"), c.model()['name'])
|
||||||
self.addLine(_("Template"), c.template()['name'])
|
self.addLine(_("Template"), c.template()['name'])
|
||||||
self.addLine(_("Current Group"), self.deck.groupName(c.gid))
|
self.addLine(_("Current Group"), self.deck.groups.name(c.gid))
|
||||||
self.addLine(_("Initial Group"), self.deck.groupName(c.fact().gid))
|
self.addLine(_("Home Group"), self.deck.groups.name(c.fact().gid))
|
||||||
self.txt += "</table>"
|
self.txt += "</table>"
|
||||||
return self.txt
|
return self.txt
|
||||||
|
|
||||||
|
|
|
@ -133,15 +133,15 @@ def test_upgrade():
|
||||||
def test_groups():
|
def test_groups():
|
||||||
deck = getEmptyDeck()
|
deck = getEmptyDeck()
|
||||||
# we start with a standard group
|
# we start with a standard group
|
||||||
assert len(deck.groups) == 1
|
assert len(deck.groups.groups) == 1
|
||||||
# it should have an id of 1
|
# it should have an id of 1
|
||||||
assert deck.groups['1']
|
assert deck.groups.name(1)
|
||||||
# create a new group
|
# create a new group
|
||||||
ts = deck.groupID("new group")
|
g = deck.groups.id("new group")
|
||||||
assert ts
|
assert g
|
||||||
assert len(deck.groups) == 2
|
assert len(deck.groups.groups) == 2
|
||||||
# should get the same id
|
# should get the same id
|
||||||
assert deck.groupID("new group") == ts
|
assert deck.groups.id("new group") == g
|
||||||
# by default, everything should be shown
|
# by default, everything should be shown
|
||||||
assert not deck.qconf['groups']
|
assert not deck.qconf['groups']
|
||||||
|
|
||||||
|
|
|
@ -581,7 +581,7 @@ def test_ordcycle():
|
||||||
def test_counts():
|
def test_counts():
|
||||||
d = getEmptyDeck()
|
d = getEmptyDeck()
|
||||||
# add a second group
|
# add a second group
|
||||||
assert d.groupID("new group")
|
assert d.groups.id("new group")
|
||||||
# for each card type
|
# for each card type
|
||||||
for type in range(3):
|
for type in range(3):
|
||||||
# and each of the groups
|
# and each of the groups
|
||||||
|
@ -680,7 +680,7 @@ def test_groupCounts():
|
||||||
# and one that's a child
|
# and one that's a child
|
||||||
f = d.newFact()
|
f = d.newFact()
|
||||||
f['Front'] = u"two"
|
f['Front'] = u"two"
|
||||||
default1 = f.gid = d.groupID("Default::1")
|
default1 = f.gid = d.groups.id("Default::1")
|
||||||
d.addFact(f)
|
d.addFact(f)
|
||||||
# make it a review card
|
# make it a review card
|
||||||
c = f.cards()[0]
|
c = f.cards()[0]
|
||||||
|
@ -690,16 +690,16 @@ def test_groupCounts():
|
||||||
# add one more with a new group
|
# add one more with a new group
|
||||||
f = d.newFact()
|
f = d.newFact()
|
||||||
f['Front'] = u"two"
|
f['Front'] = u"two"
|
||||||
foobar = f.gid = d.groupID("foo::bar")
|
foobar = f.gid = d.groups.id("foo::bar")
|
||||||
d.addFact(f)
|
d.addFact(f)
|
||||||
# and one that's a sibling
|
# and one that's a sibling
|
||||||
f = d.newFact()
|
f = d.newFact()
|
||||||
f['Front'] = u"three"
|
f['Front'] = u"three"
|
||||||
foobaz = f.gid = d.groupID("foo::baz")
|
foobaz = f.gid = d.groups.id("foo::baz")
|
||||||
d.addFact(f)
|
d.addFact(f)
|
||||||
d.reset()
|
d.reset()
|
||||||
assert d.sched.counts() == (3, 0, 1)
|
assert d.sched.counts() == (3, 0, 1)
|
||||||
assert len(d.groups) == 4
|
assert len(d.groups.groups) == 4
|
||||||
cnts = d.sched.groupCounts()
|
cnts = d.sched.groupCounts()
|
||||||
assert cnts[0] == ["Default", 1, 1, 0, 1]
|
assert cnts[0] == ["Default", 1, 1, 0, 1]
|
||||||
assert cnts[1] == ["Default::1", default1, 1, 1, 0]
|
assert cnts[1] == ["Default::1", default1, 1, 1, 0]
|
||||||
|
|
Loading…
Reference in a new issue