def postpone(): i = QInputDialog.getInteger(mw, _("Postpone"), _("Number of days to spread repetitions over:"), 2, 1) if i[1] and i[0] > 1: mw.deck.s.flush() q = mw.deck.s.all( "select id, interval, due from %s where reps > 0" % revCardOrder) size = len(q) / i[0] + 1 days = 0 count = -1 cards = [] now = time.time() for item in q: count += 1 if count == size: count = 0 days += 1 seconds = 86400 * days # determine the current delay delay = now - item.due cards.append({'id': item[0], 'interval': item[1] + days + (delay / 86400.0), 'due': now + seconds}) # apply changes mw.deck.s.execute(""" update cards set interval = :interval, due = :due, combinedDue = max(:due, spaceUntil), isDue = 0 where id = :id""", cards) # rebuild mw.reset()
def moveTags(): for fact in mw.deck.s.query(Fact).all(): old = fact.tags fact.tags = canonifyTags(fact.tags + "," + ",".join([c.tags for c in fact.cards])) fact.setModified() mw.deck.setModified() mw.reset()
def moveTags(): for fact in mw.deck.s.query(Fact).all(): old = fact.tags fact.tags = canonifyTags(fact.tags + "," + ",".join( [c.tags for c in fact.cards])) fact.setModified() mw.deck.setModified() mw.reset()
def doImport(): # add an iknow model if not [m for m in mw.deck.models if m.name == 'Smart.fm']: m = Model(u'Smart.fm') m.addFieldModel(FieldModel(u'Expression', False, False)) m.addFieldModel(FieldModel(u'Meaning', False, False)) m.addFieldModel(FieldModel(u'Reading', False, False)) m.addFieldModel(FieldModel(u'Audio', False, False)) m.addFieldModel(FieldModel(u'Image', False, False)) m.addCardModel(CardModel( u'Listening', u'Listen.%(Audio)s', u'%(Expression)s<br>%(Reading)s<br>%(Meaning)s<br>%(Image)s')) mw.deck.addModel(m) while 1: mw.reset() url = getOnlyText("Enter list URL:") if not url: return id = re.search("/lists/(\d+)", url).group(1) # get sentences f = urllib2.urlopen( "http://api.smart.fm/lists/%s/sentences.json" % id) d = simplejson.load(f) # add facts diag = QProgressDialog(_("Importing..."), "", 0, 0, mw) diag.setCancelButton(None) diag.setMaximum(len(d)) diag.setMinimumDuration(0) for i, sen in enumerate(d): diag.setValue(i) diag.setLabelText(sen['text']) mw.app.processEvents() f = mw.deck.newFact() f['Expression'] = sen['text'] f['Meaning'] = sen['translations'] and sen['translations'][0]['text'] or u"" try: f['Reading'] = sen['transliterations']['Hrkt'] or u"" # reading is sometimes missing if not f['Reading'] and kakasi: f['Reading'] = kakasi.toFurigana(f['Expression']) except KeyError: f['Reading'] = u"" if includeSounds and sen['sound']: (file, headers) = urllib.urlretrieve(sen['sound']) path = mw.deck.addMedia(file) f['Audio'] = u'[sound:%s]' % path else: f['Audio'] = u"" if includeImages and sen['image']: (file, headers) = urllib.urlretrieve(sen['image']) path = mw.deck.addMedia(file) f['Image'] = u'<img src="%s">' % path else: f['Image'] = u"" mw.deck.addFact(f) diag.cancel() mw.deck.save()
def addClicked(self): try: model = self.ensureKanjiModelExists() fact = mw.deck.newFact(model) #TODO pull data from UI field fact[u'Kanji'] = self.currentKanji fact[u'HeisigFrameID'] = u"heisig:%s" % self.currentKanjiFrame fact[u'Keyword'] = unicode(self.fld_keyword.text()) fact[u'Story'] = unicode(self.fld_story.toPlainText()) fact[u'PrimitiveMeanings'] = unicode( self.fld_primitives.toPlainText()) strokeDiagramPath = os.path.join(mw.pluginsFolder(), u'JPdictionaryFiles', u'sod-utf8', self.currentKanji + u'.png') if os.path.exists(strokeDiagramPath): ankiDiagramPath = mw.deck.addMedia(strokeDiagramPath) fact[u'Image_StrokeOrderDiagram'] = u'<img src="%s"/>' % ( ankiDiagramPath) else: fact[u'Image_StrokeOrderDiagram'] = u"" strokeAnimationPath = os.path.join(mw.pluginsFolder(), u'JPdictionaryFiles', u'soda-utf8', self.currentKanji + u'.gif') if os.path.exists(strokeAnimationPath): ankiAnimationPath = mw.deck.addMedia(strokeAnimationPath) fact[u'Image_StrokeOrderAnimation'] = u'<img src="%s" />' % ( ankiAnimationPath) else: fact[u'Image_StrokeOrderAnimation'] = u"" newfact = mw.deck.addFact(fact) thecard = None for card in newfact.cards: thecard = mw.deck.cardFromId(card.id) mw.deck.answerCard(thecard, 2) mw.deck.save() mw.reset() self.statusLabel.setText("Added card for kanji: %s" % self.currentKanji) self.reviewerWidget.addQuestionAnswerForReview( unicode(self.fld_keyword.text()), self.currentKanji) self.incrementKanji() except: logpath = os.path.join(mw.pluginsFolder(), "log-rtk-importer.txt") log = open(logpath, 'a') log.write(traceback.format_exc()) log.flush() log.close() QMessageBox.warning( mw, "Warning", "Your card may contain duplicate data. Please check that you have the correct keyword and that you haven't re-used the keyword or story before by accident. If you are sure there is no duplicate, then please contact the developer." )
def tagCurrentCard(tag): mw.deck.setUndoStart(_("Suspend")) mw.currentCard.fact.tags = addTags(tag, mw.currentCard.fact.tags) mw.currentCard.fact.setModified() for card in mw.currentCard.fact.cards: mw.deck.updatePriority(card) mw.deck.setModified() mw.lastScheduledTime = None mw.reset() mw.deck.setUndoEnd(_("Suspend"))
def markAndDelete(): undo = _("MarkDelete") mw.deck.setUndoStart(undo) mw.currentCard.fact.tags = canonifyTags(mw.currentCard.fact.tags + "," + "MarkDelete") mw.currentCard.fact.setModified() mw.deck.updateFactTags([mw.currentCard.fact.id]) mw.deck.deleteCard(mw.currentCard.id) mw.reset() mw.deck.setUndoEnd(undo)
def addClicked(self): try: model = self.ensureKanjiModelExists() fact = mw.deck.newFact(model) #TODO pull data from UI field fact[u'Kanji'] = self.currentKanji fact[u'HeisigFrameID'] = u"heisig:%s" % self.currentKanjiFrame fact[u'Keyword'] = unicode(self.fld_keyword.text()) fact[u'Story'] = unicode(self.fld_story.toPlainText()) fact[u'PrimitiveMeanings'] = unicode(self.fld_primitives.toPlainText()) strokeDiagramPath = os.path.join(mw.pluginsFolder(), u'JPdictionaryFiles', u'sod-utf8', self.currentKanji + u'.png') if os.path.exists(strokeDiagramPath): ankiDiagramPath = mw.deck.addMedia(strokeDiagramPath) fact[u'Image_StrokeOrderDiagram'] = u'<img src="%s"/>' % (ankiDiagramPath) else: fact[u'Image_StrokeOrderDiagram'] = u"" strokeAnimationPath = os.path.join(mw.pluginsFolder(), u'JPdictionaryFiles', u'soda-utf8', self.currentKanji + u'.gif') if os.path.exists(strokeAnimationPath): ankiAnimationPath = mw.deck.addMedia(strokeAnimationPath) fact[u'Image_StrokeOrderAnimation'] = u'<img src="%s" />' % (ankiAnimationPath) else: fact[u'Image_StrokeOrderAnimation'] = u"" newfact = mw.deck.addFact(fact) thecard = None for card in newfact.cards: thecard = mw.deck.cardFromId(card.id) mw.deck.answerCard(thecard, 2) mw.deck.save() mw.reset() self.statusLabel.setText("Added card for kanji: %s" % self.currentKanji) self.reviewerWidget.addQuestionAnswerForReview(unicode(self.fld_keyword.text()), self.currentKanji) self.incrementKanji() except: logpath = os.path.join(mw.pluginsFolder(), "log-rtk-importer.txt") log = open(logpath, 'a') log.write(traceback.format_exc()) log.flush() log.close() QMessageBox.warning(mw, "Warning","Your card may contain duplicate data. Please check that you have the correct keyword and that you haven't re-used the keyword or story before by accident. If you are sure there is no duplicate, then please contact the developer.")
def postpone(): i = QInputDialog.getInteger(mw, _("Postpone"), _("Number of days to spread repetitions over:"), 2, 1) if i[1] and i[0] > 1: mw.deck.s.flush() d = mw.deck q = d.s.all( d.cardLimit( "revActive", "revInactive", """ select c.id, interval, combinedDue from cards c where type = 1 and combinedDue < :lim order by priority desc, combinedDue """), lim=d.dueCutoff) size = len(q) / i[0] + 1 days = 0 count = -1 cards = [] now = time.time() for item in q: count += 1 if count == size: count = 0 days += 1 seconds = 86400 * days # determine the current delay delay = now - item.combinedDue cards.append({'id': item[0], 'interval': item[1] + days + (delay / 86400.0), 'due': now + seconds}) # apply changes d.s.execute(""" update cards set interval = :interval, combinedDue = :due, isDue = 0 where id = :id""", cards) # rebuild d.flushMod() mw.reset()
def runImport(modelManager, importSettings): progress = ProgressTracker(os.path.join(mw.pluginsFolder(), "iknow-smartfm-log.txt")) try: importSettings.saveToConfig() iknow = SmartFMAPI() iknowList = iknow.list(importSettings.listId) try: if iknowList.language and iknowList.language == "ja": modelManager.tagModelsAsJapanese() except: progress.logMsg("Error trying to tag models as Japanese") progress.logMsg(traceback.format_exc()) pass iknow.setCallback(progress.downloadCallback) items = iknow.listItems(importSettings.listId, (importSettings.importVocab or importSettings.includeItemMeaning), importSettings.importSentences) progress.preImportResetProgress(len(items)) totalImported = 0 totalDup = 0 totalFormattingErrors = 0 totalImportedByType = {"item" : 0, "sentence" : 0} for i, item in enumerate(items): if importSettings.maxItems > 0 and totalImported >= importSettings.maxItems: break if not importSettings.importSentences and item.type == "sentence": continue if not importSettings.importVocab and item.type == "item": continue if formatIknowItemPreImport(item, iknowList, importSettings, iknowList.isBilingual(), progress): progress.importCallback(i, item.expression) if importIknowItem(item, modelManager.sentenceModel, modelManager.vocabModel, importSettings, progress): totalImported += 1 totalImportedByType[item.type] = totalImportedByType[item.type] + 1 else: totalDup += 1 else: totalFormattingErrors += 1 progress.dialog.cancel() progress.close() mw.deck.save() resultStr = "Import complete. Imported %s items, %s sentences, and skipped %s duplicates." % (totalImportedByType["item"], totalImportedByType["sentence"], totalDup) if totalFormattingErrors > 0: resultStr += " %s items were skipped because there was no translation available on smart.fm." % totalFormattingErrors QMessageBox.information(mw, "Summary", resultStr) mw.reset(mw.mainWin) except AudioDownloadError: progress.logMsg(traceback.format_exc()) progress.dialog.cancel() progress.close() QMessageBox.warning(mw, "Warning", "Data for one item could not be retrieved even after several retries. This may be caused by a slower internet connection or smart.fm's (occasionally slow) servers. Please try your import again.") mw.reset(mw.mainWin) except AddMediaException: progress.logMsg(traceback.format_exc()) progress.dialog.cancel() progress.close() QMessageBox.warning(mw, "Warning", "Anki was unable to add an audio file to your deck. This may be caused by a problem with Anki, the smart.fm! plugin, or both. Please inform the plugin developer.") mw.reset(mw.mainWin) except SmartFMDownloadError: progress.logMsg(traceback.format_exc()) progress.dialog.cancel() progress.close() QMessageBox.warning(mw,"Warning","There was a problem retrieving data from Smart.fm. When you hit 'OK', a browser window will open to check that you can reach smart.fm.<br /><br />If this browser window shows an error, then please wait for smart.fm to be fixed, and try importing cards again. If there is no error in the browser window and you see some content relevant to your study list, please notify the plugin developer at http://github.com/ridisculous/anki-iknow-importer/issues") try: QDesktopServices.openUrl(QUrl(iknow.lastUrlFetched)) except: pass mw.reset(mw.mainWin) except: progress.logMsg(traceback.format_exc()) progress.dialog.cancel() progress.close() QMessageBox.warning(mw, "Warning", "There was an unknown error importing items. Please contact the plugin developer at http://github.com/ridisculous/anki-iknow-importer/issues<br /><br />Please be sure to include the file 'iknow-smartfm-log.txt' from your plugins directory with a description of what you tried to do before this error.") mw.reset(mw.mainWin)