diff --git a/anki/deck.py b/anki/deck.py index 1bc5d0c74..279e64544 100644 --- a/anki/deck.py +++ b/anki/deck.py @@ -217,10 +217,10 @@ qconf=?, conf=?, data=?""", def findTemplates(self, fact, checkActive=True): "Return active, non-empty templates." ok = [] - for c, template in enumerate(fact.model.templates): + for template in fact.model.templates: if template['actv'] or not checkActive: # [cid, fid, mid, gid, ord, tags, flds, data] - data = [1, 1, fact.model.id, 1, c, + data = [1, 1, fact.model.id, 1, template['ord'], "", fact.joinedFields(), ""] now = self._renderQA(fact.model, "", data) data[6] = "\x1f".join([""]*len(fact._fields)) @@ -230,21 +230,19 @@ qconf=?, conf=?, data=?""", if not template['emptyAns']: if now['a'] == empty['a']: continue - # add ordinal - template['ord'] = c ok.append(template) return ok - def addCards(self, fact, tids): + def genCards(self, fact, templates): + "Generate cards for templates if cards not empty." + # templates should have .ord set ids = [] for template in self.findTemplates(fact, False): - if template.id not in tids: + if template not in templates: continue - if self.db.scalar(""" -select count(id) from cards -where fid = :fid and tid = :cmid""", - fid=fact.id, cmid=template.id) == 0: - # enough for 10 card models assuming 0.00001 timer precision + if not self.db.scalar( + "select 1 from cards where fid = ? and ord = ?", + fact.id, template.ord): card = anki.cards.Card( fact, template, fact.created+0.0001*template.ord) @@ -257,19 +255,6 @@ where fid = :fid and tid = :cmid""", self.setMod() return ids - def factIsInvalid(self, fact): - "True if existing fact is invalid. Returns the error." - try: - fact.assertValid() - fact.assertUnique(self.db) - except FactInvalidError, e: - return e - - def factUseCount(self, fid): - "Return number of cards referencing a given fact id." - return self.db.scalar("select count(id) from cards where fid = :id", - id=fid) - def _deleteFacts(self, ids): "Bulk delete facts by ID. Don't call this directly." if not ids: @@ -478,9 +463,9 @@ select id from cards where fid in (select id from facts where mid = ?)""", fields = splitFields(flds) model = mods[mid] if csum: - for c, f in enumerate(model.fields): - if f['uniq'] and fields[c]: - r.append((fid, mid, fieldChecksum(fields[c]))) + for f in model.fields: + if f['uniq'] and fields[f['ord']]: + r.append((fid, mid, fieldChecksum(fields[f['ord']]))) r2.append((stripHTML(fields[model.sortIdx()])[ :SORT_FIELD_LEN], fid)) if csum: diff --git a/anki/models.py b/anki/models.py index e50c08907..1d8f0e1c9 100644 --- a/anki/models.py +++ b/anki/models.py @@ -16,6 +16,7 @@ defaultConf = { defaultField = { 'name': "", + 'ord': None, 'rtl': False, 'req': False, 'uniq': False, @@ -28,6 +29,7 @@ defaultField = { defaultTemplate = { 'name': "", + 'ord': None, 'actv': True, 'qfmt': "", 'afmt': "", @@ -101,14 +103,14 @@ insert or replace into models values (?, ?, ?, ?, ?, ?, ?)""", return "" # fields css = "".join([self._fieldCSS( - ".fm%s.%s" % (hexifyID(self.id), hexifyID(c)), + ".fm%s.%s" % (hexifyID(self.id), hexifyID(f['ord'])), (f['font'], f['qsize'], f['qcol'], f['rtl'], f['pre'])) - for c, f in enumerate(self.fields)]) + for f in self.fields]) # templates css += "".join(["#cm%s-%s {text-align:%s;background:%s}\n" % ( - hexifyID(self.id), hexifyID(c), + hexifyID(self.id), hexifyID(t['ord']), ("center", "left", "right")[t['align']], t['bg']) - for c, t in enumerate(self.templates)]) + for t in self.templates]) return css def _rewriteFont(self, font): @@ -136,8 +138,8 @@ insert or replace into models values (?, ?, ?, ?, ?, ?, ?)""", ################################################## def fieldMap(self): - "Mapping of field name -> (ord, conf)." - return dict([(f['name'], (c, f)) for c, f in enumerate(self.fields)]) + "Mapping of field name -> (ord, field)." + return dict([(f['name'], (f['ord'], f)) for f in self.fields]) def sortIdx(self): return self.conf['sortf'] @@ -152,6 +154,7 @@ insert or replace into models values (?, ?, ?, ?, ?, ?, ?)""", def addField(self, field): self.fields.append(field) + self._updateFieldOrds() self.flush() def add(fields): fields.append("") @@ -161,7 +164,7 @@ insert or replace into models values (?, ?, ?, ?, ?, ?, ?)""", def delField(self, field): idx = self.fields.index(field) self.fields.remove(field) - self.flush() + self._updateFieldOrds() def delete(fields): del fields[idx] return fields @@ -169,6 +172,7 @@ insert or replace into models values (?, ?, ?, ?, ?, ?, ?)""", if idx == self.sortIdx(): # need to rebuild self.deck.updateFieldCache(self.fids(), csum=False) + # flushes self.renameField(field, None) def moveField(self, field, idx): @@ -177,6 +181,7 @@ insert or replace into models values (?, ?, ?, ?, ?, ?, ?)""", return self.fields.remove(field) self.fields.insert(idx, field) + self._updateFieldOrds() self.flush() def move(fields, oldidx=oldidx): val = fields[oldidx] @@ -200,6 +205,10 @@ insert or replace into models values (?, ?, ?, ?, ?, ?, ?)""", field['name'] = newName self.flush() + def _updateFieldOrds(self): + for c, f in enumerate(self.fields): + f['ord'] = c + def _transformFields(self, fn): self.deck.startProgress() self.deck.modSchema() @@ -219,6 +228,8 @@ insert or replace into models values (?, ?, ?, ?, ?, ?, ?)""", def addTemplate(self, template): self.deck.modSchema() self.templates.append(template) + self._updateTemplOrds() + self.flush() def delTemplate(self, template): self.deck.modSchema() @@ -232,8 +243,13 @@ select c.id from cards c, facts f where c.fid=f.id and mid = ? and ord = ?""", update cards set ord = ord - 1 where fid in (select id from facts where mid = ?) and ord > ?""", self.id, ord) self.templates.remove(template) + self._updateTemplOrds() self.flush() + def _updateTemplOrds(self): + for c, t in enumerate(self.templates): + t['ord'] = c + # Model changing ########################################################################## diff --git a/anki/storage.py b/anki/storage.py index f9bc17a9e..b3b55349f 100644 --- a/anki/storage.py +++ b/anki/storage.py @@ -454,11 +454,15 @@ questionAlign, lastFontColour, allowEmptyAnswer, typeAnswer from cardModels"""): db.execute("drop table cardModels") return mods -def _rewriteModelIds(deck): +def _fixupModels(deck): # rewrite model/template/field ids models = deck.models() deck.db.execute("delete from models") for c, m in enumerate(models.values()): + # update ordinals + m._updateFieldOrds() + m._updateTemplOrds() + # rewrite id old = m.id m.id = c+1 m.flush() @@ -467,8 +471,7 @@ def _rewriteModelIds(deck): def _postSchemaUpgrade(deck): "Handle the rest of the upgrade to 2.0." import anki.deck - # fix up model/template ids - _rewriteModelIds(deck) + _fixupModels(deck) # update uniq cache deck.updateFieldCache(deck.db.list("select id from facts")) # remove old views