def id(self, name, create=True, type=None): "Add a deck with NAME. Reuse deck if already exists. Return id as int." if type is None: type = defaultDeck name = name.replace('"', '') name = unicodedata.normalize("NFC", name) for id, g in list(self.decks.items()): if unicodedata.normalize("NFC", g['name'].lower()) == name.lower(): return int(id) if not create: return None g = copy.deepcopy(type) if "::" in name: # not top level; ensure all parents exist name = self._ensureParents(name) g['name'] = name while 1: id = intTime(1000) if str(id) not in self.decks: break g['id'] = id self.decks[str(id)] = g self.save(g) self.maybeAddToActive() runHook("newDeck") return int(id)
def save(self, m=None, templates=False): "Mark M modified if provided, and schedule registry flush." if m and m['id']: m['mod'] = intTime() m['usn'] = self.col.usn() self._updateRequired(m) if templates: self._syncTemplates(m) self.changed = True runHook("newModel")
def _remNotes(self, ids): "Bulk delete notes by ID. Don't call this directly." if not ids: return strids = ids2str(ids) # we need to log these independently of cards, as one side may have # more card templates runHook("remNotes", self, ids) self._logRem(ids, REM_NOTE) self.db.execute("delete from notes where id in %s" % strids)
def register(self, tags, usn=None): "Given a list of tags, add any missing ones to tag registry." found = False for t in tags: if t not in self.tags: found = True self.tags[t] = self.col.usn() if usn is None else usn self.changed = True if found: runHook("newTag")
def exporters(): def id(obj): return ("%s (*%s)" % (obj.key, obj.ext), obj) exps = [ id(AnkiCollectionPackageExporter), id(AnkiPackageExporter), id(TextNoteExporter), id(TextCardExporter), ] runHook("exportersList", exps) return exps
def flushSched(self): self.mod = intTime() self.usn = self.col.usn() # bug checks if self.queue == 2 and self.odue and not self.col.decks.isDyn( self.did): runHook("odueInvalid") assert self.due < 4294967296 self.col.db.execute( """update cards set mod=?, usn=?, type=?, queue=?, due=?, ivl=?, factor=?, reps=?, lapses=?, left=?, odue=?, odid=?, did=? where id = ?""", self.mod, self.usn, self.type, self.queue, self.due, self.ivl, self.factor, self.reps, self.lapses, self.left, self.odue, self.odid, self.did, self.id) self.col.log(self)
def _exportMedia(self, z, files, fdir): media = {} for c, file in enumerate(files): cStr = str(c) mpath = os.path.join(fdir, file) if os.path.isdir(mpath): continue if os.path.exists(mpath): if re.search(r'\.svg$', file, re.IGNORECASE): z.write(mpath, cStr, zipfile.ZIP_DEFLATED) else: z.write(mpath, cStr, zipfile.ZIP_STORED) media[cStr] = unicodedata.normalize("NFC", file) runHook("exportedMediaFiles", c) return media
def flush(self): self.mod = intTime() self.usn = self.col.usn() # bug check if self.queue == 2 and self.odue and not self.col.decks.isDyn( self.did): runHook("odueInvalid") assert self.due < 4294967296 self.col.db.execute( """ insert or replace into cards values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""", self.id, self.nid, self.did, self.ord, self.mod, self.usn, self.type, self.queue, self.due, self.ivl, self.factor, self.reps, self.lapses, self.left, self.odue, self.odid, self.flags, self.data) self.col.log(self)
def _checkLeech(self, card, conf): "Leech handler. True if card was a leech." lf = conf['leechFails'] if not lf: return # if over threshold or every half threshold reps after that if (card.lapses >= lf and (card.lapses - lf) % (max(lf // 2, 1)) == 0): # add a leech tag f = card.note() f.addTag("leech") f.flush() # handle a = conf['leechAction'] if a == 0: # if it has an old due, remove it from cram/relearning if card.odue: card.due = card.odue if card.odid: card.did = card.odid card.odue = card.odid = 0 card.queue = -1 # notify UI runHook("leech", card) return True
def on_idle(self): runHook("mpvIdleHook")
def queueFile(self, file): runHook("mpvWillPlay", file) path = os.path.join(os.getcwd(), file) self.command("loadfile", path, "append-play")