def on_done(future: Future): mw.progress.finish() try: future.result() except UnicodeDecodeError: showUnicodeWarning() return except Exception as e: msg = tr(TR.IMPORTING_FAILED_DEBUG_INFO) + "\n" err = repr(str(e)) if "1-character string" in err: msg += err elif "invalidTempFolder" in err: msg += mw.errorHandler.tempFolderMsg() else: msg += traceback.format_exc() showText(msg) return else: txt = _("Importing complete.") + "\n" if importer.log: txt += "\n".join(importer.log) # fixme: the main window gets minimized when this dialog is closed showText(txt) mw.reset() return
def getOrCreateDeck(deckName): deck_id = mw.col.decks.id(deckName) deck = mw.col.decks.get(deck_id) mw.col.decks.save(deck) mw.col.reset() mw.reset() return deck
def search_word(browser, type=0): # if type == 0: # showInfo('科林辞典') # else: # showInfo('人人词典') notes = [mw.col.getNote(note_id) for note_id in browser.selectedNotes()] total = len(notes) n = 0 for note in notes: result = '' if type == 0: result = searchWord_kelin(note['Front']) else: result = searchWord_renren(note['Front']) if result == '': # showInfo('查询失败,可以尝试使用别的词典') n += 1 else: # showInfo('查询成功'+note['Back']) note['Back'] = result note.flush() mw.reset() msg = '查询单词' + str(total) + '个,其中' + str(total - n) + '个成功,' + str(n) + '个失败' showInfo(msg)
def regeneratePronunciations(nids): mw.checkpoint("Bulk-add Pronunciations") mw.progress.start() for nid in nids: note = mw.col.getNote(nid) if "japanese" not in note.model()['name'].lower(): continue src, srcIdx, dst, dstIdx = get_src_dst_fields(note) if src is None or dst is None: continue if note[dst] and not regenerate_readings: # already contains data, skip continue srcTxt = mw.col.media.strip(note[src]) if not srcTxt.strip(): continue prons = getPronunciations(srcTxt) note[dst] = " *** ".join(prons) note.flush() mw.progress.finish() mw.reset()
def import_apkg_model(path, delete=False): #If delete==True, our sole purpose is to import the note types and flashcard templates, not the data. imp = AnkiPackageImporter(mw.col, path) imp.run() mw.col.models.flush() mw.reset( True) # refresh the screen so that the newly imported deck is visible if delete: # Delete ALL cards/notes in the LIFT deck. Ignore errors try: # deck = mw.col.decks.byName(TARGET_DECK) #hmm, this returns a Python dict(); how to get the deck object? # assert deck.cardCount() > 0 # assert deck.noteCount() > 0 ids = mw.col.findCards("deck:{}".format(TARGET_DECK)) mw.col.remCards(ids, True) # assert deck.cardCount() == 0 # assert deck.noteCount() == 0 except: return "Failed to delete cards and notes after importing the APKG file." mw.col.models.flush() mw.reset(True) return ""
def toggleSameDaySpacing(): global nospacing nospacing ^= True mw.col.conf['268644742_intraday_spacing'] ^= True mw.col.setMod() showInfo(msg_ger if German else msg_en) mw.reset()
def _onAddNotesButton(self, choice, close, svg): """Get occlusion settings in and pass them to the note generator (add)""" dialog = self.imgoccedit r1 = self.getUserInputs(dialog) if r1 is False: return False (fields, tags) = r1 did = dialog.deckChooser.selectedId() noteGenerator = genByKey(choice) gen = noteGenerator(self.ed, svg, self.image_path, self.opref, tags, fields, did) r = gen.generateNotes() if r is False: return False if self.origin == "addcards" and self.ed.note: # Update Editor with modified tags and sources field self.ed.tags.setText(" ".join(tags)) self.ed.saveTags() for i in self.ioflds_prsv: if i in self.ed.note: self.ed.note[i] = fields[i] self.ed.loadNote() deck = mw.col.decks.nameOrNone(did) self.ed.parentWindow.deckChooser.deck.setText(deck) if close: dialog.close() mw.reset()
def import_from_json(): path = getFile(mw, "Org file to import", cb=None, dir=expanduser("~")) if not path: return with open(path, 'r') as f: content = f.read().decode('utf-8') entries = json.loads(content) import itertools get_deck = lambda e: e['deck'] entries = sorted(entries, key=get_deck) mw.checkpoint(_("Import")) logs = [] for deck_name, entries in itertools.groupby(entries, get_deck): # FIXME: If required we could group by model name also! importer = JsonImporter(mw.col, path, MODEL_NAME, deck_name) importer.initMapping() importer.run(list(entries)) if importer.log: logs.append('\n'.join(importer.log)) txt = _("Importing complete.") + "\n" txt += '\n'.join(logs) showText(txt) mw.reset()
def onDeckBrowserResetCards(did): if mw.col.decks.isDyn(did): tooltip("Can't reset scheduling for filtered/custom decks.") deck_name = mw.col.decks.name(did) cids = mw.col.decks.cids(did, children=True) if not cids: tooltip("Deck contains no cards.") return r = askUser("This will reset <b>ALL</b> scheduling information and " "progress in the deck '{}' and all of its subdecks ({} cards)." "<br><br>Are you sure you want to proceed?".format( deck_name, len(cids)), defaultno=True, title="Reset Card Scheduling") if not r: return mw.checkpoint("Reset selected deck") mw.progress.start() resetSelectedCardScheduling(cids) mw.progress.finish() mw.reset() tooltip("{} card(s) reset.".format(len(cids)), parent=mw)
def run(): # Stats updated = 0 numcards = mw.col.cardCount() # Get the RevTK file fname = QFileDialog.getOpenFileName(None, 'Open file', '', 'CSV (*.csv)') # Open try: f = open(fname, 'r') except: print 'Could not open file %s' % fname return # Process reader = csv.reader(f, delimiter=',', quotechar='"') for line in reader: if processCard(*line): updated += 1 # Close f.close() # Finished showInfo('Updated %d/%d cards.' % (updated, numcards)) mw.reset()
def process_one_feed(**kw): # get deck and model deck = mw.col.decks.get(mw.col.decks.id(kw['Deck'])) model = mw.col.models.byName(kw['Note type']) # assign model to deck mw.col.decks.select(deck['id']) mw.col.decks.get(deck)['mid'] = model['id'] mw.col.decks.save(deck) # assign deck to model mw.col.models.setCurrent(model) mw.col.models.current()['did'] = deck['id'] mw.col.models.save(model) # retrieve rss data, errmsg = getFeed(kw['Url']) if errmsg: return errmsg #parse xml doc = BeautifulSoup(data, "html.parser") if not doc.find('item') is None: items = doc.findAll('item') feed = "rss" elif not doc.find('entry') is None: items = doc.findAll('entry') feed = "atom" else: return # iterate notes dups = 0 adds = 0 tofill = fields_to_fill_for_nonempty_front_template(model["id"]) for item in items: note, increasedups = process_one_item(item, kw, feed, tofill) if increasedups: dups += 1 if not note: continue mw.col.addNote(note) if not tofill: # now one note of the note type exists tofill = fields_to_fill_for_nonempty_front_template(model["id"]) adds += 1 mw.col.reset() mw.reset() # show result msg = ngettext("%d note added", "%d notes added", adds) % adds msg += "\n" if dups > 0: msg += _("<ignored>") + "\n" msg += _("duplicate") + ": " msg += ngettext("%d note", "%d notes", dups) % dups msg += "\n" return msg
def addKanjiSplits_bulk(nids): try: mw.checkpoint("Add Kanji Splits") mw.progress.start() # For each seleccted card for nid in nids: note = mw.col.getNote(nid) # do the note and handle the results if False == doNote(note): continue # Add the data to the dst field if True == doNote(note): note.flush() except KeyError: mw.hDialog = hDialog = QMessageBox() hDialog.setText( "Please make sure that these fields exist: 'Kanji Removed 1' ~ 'Kanji Removed 6', and 'Kanji Removed All'" ) hDialog.exec_() finally: mw.progress.finish() mw.reset()
def addKDStories(nids): readStories() fields = [] anote=mw.col.getNote(nids[0]) #get the fields of the first note for (i, f) in anote.items(): fields.append(i) #get input/output fields from user expField = addinfofuncts.getKeyFromList("Select field to read from", "Read relevant kanji/expression from:", fields) if (expField is None): return compoundMeaning = addinfofuncts.getKeyFromList("Select field to write to", "Write compound information to:", fields) if (compoundMeaning is None): return Mnemonic = addinfofuncts.getKeyFromList("Select field to write to", "Write Mnemonic to:", fields) if (Mnemonic is None): return EngMeaning = addinfofuncts.getKeyFromList("Select field to write to", "Write English meanings to:", fields) if (EngMeaning is None): return mw.checkpoint("Add KD Stories") mw.progress.start() #For each seleccted card for nid in nids: note = mw.col.getNote(nid) srcTxt = mw.col.media.strip(note[expField]) if not srcTxt.strip(): continue #Add the data to the dst field kanjizz = extractKanji(note[expField]) if kanjiIndex.get(kanjizz): if kanjiIndex[kanjizz]['compound']: note[compoundMeaning] = kanjiIndex[kanjizz]['compound'].decode('utf8') else: note[compoundMeaning] = "" if kanjiIndex[kanjizz]['eng2meaning']: note[Mnemonic] = kanjiIndex[kanjizz]['eng2meaning'].decode('utf8') else: note[Mnemonic] = "" if kanjiIndex[kanjizz]['engmeaning']: note[EngMeaning] = kanjiIndex[kanjizz]['engmeaning'].decode('utf8') else: note[EngMeaning] = "" note.flush() mw.progress.finish() mw.reset()
def createDeck(self, result): # create new deck and custom model name = result['title'] terms = result['terms'] deck = mw.col.decks.get(mw.col.decks.id(name)) model = addCustomModel(name, mw.col) # assign custom model to new deck mw.col.decks.select(deck["id"]) mw.col.decks.get(deck)["mid"] = model["id"] mw.col.decks.save(deck) # assign new deck to custom model mw.col.models.setCurrent(model) mw.col.models.current()["did"] = deck["id"] mw.col.models.save(model) txt = u""" <div><img src="{0}" /></div> """ for term in terms: note = mw.col.newNote() note["Front"] = term["term"] note["Back"] = term["definition"].replace('\n', '<br>') if not term["image"] is None: #stop the previous thread first file_name = self.fileDownloader(term["image"]["url"]) note["Back"] += txt.format(file_name) mw.app.processEvents() mw.col.addNote(note) mw.col.reset() mw.reset()
def add_nids_to_all(): """ Add note id to all empty fields with the right names. Iterate over all notes and add the nid """ if not askUser(_(u"Add note id to all 'Note ID' fields?")): return # Maybe there is a way to just select the notes which have a nid # field. But this should work and efficency isn't too much of an # issue. nids = mw.col.db.list("select id from notes") # Iterate over the cards for nid in progress(nids, _(u"Adding note ids."), _(u"Stop that!")): n = mw.col.getNote(nid) # Go over the fields ... for name in mw.col.models.fieldNames(n.model()): # ... and the target field names .. for f in id_fields: # ... and compare the two if f == name.lower(): # Check if target is empty if not n[name]: n[name] = str(nid) n.flush() mw.reset()
def execute(self, action): mw.checkpoint(action) for cmd in self: try: self._parse(cmd, course=self.course, datasource=self.datasource) except Exception as x: msg = 'Undoing {0} due to error "{1}"'.format(action, x) if hasattr(x, 'cmd'): msg = msg + '\n\nWas processing command:\n{0}'.format( x.cmd) msg = msg + ''' ------------------------------------------------------------------ Please include the information below if reporting an error ------------------------------------------------------------------ {0}'''.format(traceback.format_exc()) showWarning(msg, title=self.course.name) mw.onUndo() return False if self._warnings: showWarning('\n'.join(self._warnings)) # refresh main view so changes are visible mw.reset() return True
def regeneratePronunciations(nids): mw.checkpoint("Bulk-add Pronunciations") mw.progress.start() for nid in nids: note = mw.col.getNote(nid) #if "japanese" not in note.model()['name'].lower(): # continue src, srcIdx, dst, dstIdx, snd, sndIdx, color, colorIdx = get_src_dst_fields( note) if not src or dst is None: continue if note[dst] and not config["regenerate_prons"]: # already contains data, skip continue srcTxt = mw.col.media.strip(note[src]) if not srcTxt.strip(): continue color_src = mw.col.media.strip(note[color]) if color else '' note[src], note[dst], new_color_field, audio = multi_lookup( srcTxt, getPronunciations, colorTxt=color_src) if snd and audio: note[snd] = add_audio(audio) if color: note[color] = new_color_field note.flush() mw.progress.finish() mw.reset()
def add_nids_to_all(): """Add note id to all empty fields with the right names. Iterate over all notes and add the nid minus 1’300’000’000’000. The subtraction is done mostly for aesthetical reasons. """ if not askUser( _("Add note id to all “{fn}” fields?".format( fn=config["NoteIdFieldName"]))): return # Maybe there is a way to just select the notes which have a nid # field. But this should work and efficency isn't too much of an # issue. nids = mw.col.db.list("select id from notes") # Iterate over the cards for nid in progress(nids, _("Adding note ids."), _("Stop that!")): n = mw.col.getNote(nid) # Go over the fields ... for name in mw.col.models.fieldNames(n.model()): # ... and the target field names .. if name == config["NoteIdFieldName"]: # Check if target is empty if not n[name]: n[name] = str(nid - int(15e11)) n.flush() mw.reset()
def importDeckFromCSV(self, filename, name): #file = r"C:\Users\aarun\OneDrive\Documents\Anki\addons\import.txt" # select deck did = mw.col.decks.id(name) #model = self.addNewModel() mw.col.decks.select(did) # set note type for deck model = mw.col.models.byName("Basic") deck = mw.col.decks.get(did) deck['mid'] = model['id'] mw.col.decks.save(deck) # Assign new deck to model mw.col.models.setCurrent(model) model['did'] = did mw.col.models.save(model) # import into the collection ti = TextImporter(mw.col, filename) ti.initMapping() ti.run() mw.col.reset() mw.reset()
def r(): #debug(f"Call function defined thanks to ({map})") card = mw.reviewer.card note = card.note() if 'bury' in map and map[ 'bury']: #old config. May eventually be removed. map['action'] = 'bury note' del map['bury'] updateConfig() action = map.get('action', "") checkSuffix = { "bury card": " and Bury Card", "bury note": " and Bury Note", "suspend card": " and Suspend Card", }.get(action, "") mw.checkpoint("Add Tags" + checkSuffix) addTags(note, map['tags']) if action == "bury card": mw.col.sched.buryCards([card.id]) elif action == "bury note": mw.col.sched.buryNote(note.id) elif action == "suspend card": mw.col.sched.suspendCards([card.id]) if action: mw.reset() tooltipSuffix = { "bury card": " and buried card", "bury note": " and buried note", "suspend card": " and suspended card", }.get(action, "") tooltip(f'Added tag(s) "%s"{tooltipSuffix}' % map['tags'])
def showConfDialog(): global wkconf d = QDialog() form = forms.configuration.Ui_Dialog() form.setupUi(d) form.key.setText(wkconf['key']) button = d.findChild(QRadioButton,wkconf['deck_separation']) if button: button.setChecked(True) button = d.findChild(QRadioButton,wkconf['card_direction']) if button: button.setChecked(True) button = d.findChild(QCheckBox,'includeTangorinLink') button.setChecked(wkconf.get('include_tangorin_link', False)) button = d.findChild(QPushButton,'updateWaniKaniDecks') button.clicked.connect(updateWaniKaniDeck) d.setWindowModality(Qt.WindowModal) if d.exec_(): wkconf['key'] = form.key.text() wkconf['deck_separation'] = form.deckSeparation.checkedButton().objectName() wkconf['card_direction'] = form.cardDirection.checkedButton().objectName() wkconf['include_tangorin_link'] = form.includeTangorinLink.isChecked() writeConf(); mw.app.processEvents() mw.reset() mw.deckBrowser.show()
def regenerateKeywords(nids): mw.checkpoint("Bulk-add RTK Keywords") mw.progress.start() for nid in nids: note = mw.col.getNote(nid) src = None for fld in srcFields: if fld in note: src = fld break if not src: # no src field continue dst = None for fld in dstFields: if fld in note: dst = fld break if not dst: # no dst field continue if note[dst] and not OVERRIDE: # already contains data, skip continue srcTxt = mw.col.media.strip(note[src]) if not srcTxt.strip(): continue try: note[dst] = getKeywordsFast(srcTxt) except Exception as e: raise note.flush() mw.progress.finish() mw.reset()
def onClearFormatting(browser): """ Clears the formatting for every selected note. Also creates a restore point, allowing a single undo operation. Parameters ---------- browser : Browser the anki browser from which the function is called """ mw.checkpoint("Bulk-Clear Formatting") mw.progress.start() for nid in browser.selectedNotes(): note = mw.col.getNote(nid) def clearField(field): result = stripFormatting(field) # if result != field: # sys.stderr.write("Changed: \"" + field # + "\" ==> \"" + result + "\"") return result note.fields = map(clearField, note.fields) note.flush() mw.progress.finish() mw.reset()
def _onTreeDeckAdd(self, item=None): parent = item.fullname + "::" if item and item.type == 'deck' else '' subdeck = getOnlyText(_("Name for deck/subdeck:")) if subdeck: mw.col.decks.id(parent + subdeck) self._saveDecks() mw.reset(True)
def importFromFolder(): mw.importDialog = QFileDialog() mw.importDialog.setFileMode(QFileDialog.Directory) if mw.importDialog.exec_(): fileNames = mw.importDialog.selectedFiles() if len(fileNames) > 0: rootDir = fileNames[0] baseName = os.path.basename(rootDir) prefixLen = len(rootDir) - len(baseName) for root, subDirs, files in os.walk(rootDir): for f in files: if f.endswith(".apkg"): # Get name for deck deckName = "::".join(root[prefixLen:].split( os.sep)) + "::" + f[0:len(f) - 5] did = mw.col.decks.id(deckName) mw.col.decks.save(mw.col.decks.get(did)) importer = CustomImporter(mw.col, os.path.join(root, f)) importer.deckPrefix = deckName importer.run() mw.reset()
def addDelay(cids): (delay, delayResp) = getDelayWithResponse() if delay is None: if delayResp: showWarning("Please enter an integral number of days") return mw.checkpoint("Adding delay") mw.progress.start() ivlDelay = max( 0, round(delay * (getIntervalCoefficient() if delay > 0 else getIntervalForNegativeCoefficient()))) for cid in cids: card = mw.col.getCard(cid) if card.type != 2: continue card.ivl += ivlDelay if card.odid: # Also update cards in filtered decks card.odue += delay else: card.due += delay card.flush() mw.progress.finish() mw.col.reset() mw.reset() tooltip(_("""Delay added."""))
def bulkAddJDefs(nids): mw.checkpoint("Add JDefs") mw.progress.start() #For each seleccted card for nid in nids: note = mw.col.getNote(nid) #Check if we should do it #First check to see if the fields exist #If field check fails then cancel (does any field not exist and are all of them full? if not definitionField in note or \ not dictionaryForm in note or \ (note[definitionField] and \ note[dictionaryForm]): continue #do the note if True == doNote(note, 1): note.flush() #save mw.progress.finish() mw.reset()
def regeneratePronunciations(nids): mw.checkpoint("Bulk-add Pronunciations") mw.progress.start() for nid in nids: note = mw.col.getNote(nid) # Check if this is a supported note type. If it is not, skip. # If no note type has been specified, we always continue the lookup proces. if config["noteTypes"] and not any(nt.lower() in note.model()['name'].lower() for nt in config["noteTypes"]): continue src, srcIdx, dst, dstIdx = get_src_dst_fields(note) if src is None or dst is None: continue if note[dst] and not config["regenerateReadings"]: # already contains data, skip continue srcTxt = mw.col.media.strip(note[src]) if not srcTxt.strip(): continue note[dst] = getFormattedPronunciations(srcTxt) note.flush() mw.progress.finish() mw.reset()
def maybeCreateTemplate(): if not config["local"]["dictionaryEnabled"]: return mid = mw.col.models.byName(config["local"]["dictionaryNoteTypeName"]) if not mid: addModel() mw.reset()
def rename(old_name, new_name): SEPARATOR = get_config()["separator"] tags = mw.col.tags.all() rename_dict = {old_name: new_name} # {old : new} for tag in tags: parts = tag.split(SEPARATOR) for i in range(len(parts)): if old_name == SEPARATOR.join(parts[:i]): retained_stub = SEPARATOR.join(parts[i:len(parts)]) rename_dict[tag] = SEPARATOR.join([new_name, retained_stub]) mw.checkpoint("Rename Tag") mw.progress.start() nids = mw.col.db.list('select id from notes') for id in nids: note = mw.col.getNote(id) for k, v, in rename_dict.items(): if note.hasTag(k): note.delTag(k) note.addTag(v) note.flush() mw.reset() mw.progress.finish()
def bulkAdd(browser): nids=browser.selectedNotes() mw.checkpoint("Bulk-add Tatoeba") mw.progress.start() #connect to database #connection = sqlite3.connect(databasePath) global cursor #cursor = connection.cursor() #For each seleccted card for nid in nids: note = mw.col.getNote(nid) #Check if we should do it #First check to see if the fields exist #If field check fails then cancel (does any field not exist and are all of them full? ##skip, deal with it in doNote #do the note if True == doNote(note): note.flush() #save cursor.close() mw.progress.finish() mw.reset()
def _onTreeDeckDelete(self, item): self.browser._lastSearchTxt = "" sel = mw.col.decks.byName(item.fullname) mw.deckBrowser._delete(sel['id']) mw.col.decks.save() mw.col.decks.flush() mw.reset(True)
def compare(self, remoteWordList): localWordList = cardManager.getDeckWordList( deckName=self.ui.deckComboBox.currentText(), ) local = set(localWordList) remote = set(remoteWordList) needToAddWords = remote - local needToDeleteWords = local - remote needToDeleteIds = cardManager.getNoteByWord( words=needToDeleteWords, deckName=self.ui.deckComboBox.currentText()) if needToDeleteWords and askUser( f'远程单词({len(needToDeleteWords)}个):\n{", ".join(list(needToDeleteWords)[:3])}...已经删除,\n是否删除Anki相应卡片?', title='Dict2Anki', parent=self): self.log(f'准备删除:\n{list(needToDeleteWords)}') self.log(f'卡片 Ids:\n{needToDeleteIds}') mw.col.remNotes(needToDeleteIds) mw.col.reset() mw.reset() self.log(f'删除成功。') if needToAddWords: self.log(f'准备查询:{list(needToAddWords)}') else: self.log("没有需要查询的单词。") return needToAddWords
def regeneratePronunciations(nids): mw.checkpoint("Bulk-add Pronunciations") mw.progress.start() for nid in nids: note = mw.col.getNote(nid) if "japanese" not in note.model()["name"].lower(): continue src, srcIdx, dst, dstIdx = get_src_dst_fields(note) if src is None or dst is None: continue if note[dst] and not regenerate_readings: # already contains data, skip continue srcTxt = mw.col.media.strip(note[src]) if not srcTxt.strip(): continue prons = getPronunciations(srcTxt) note[dst] = " *** ".join(prons) note.flush() mw.progress.finish() mw.reset()
def createDeck(self, name, terms): """create new Anki deck from downloaded data""" #create new deck and custom model deck = mw.col.decks.get(mw.col.decks.id(name)) model = addCustomModel(name, mw.col) #assign custom model to new deck mw.col.decks.select(deck["id"]) mw.col.decks.get(deck)["mid"] = model["id"] mw.col.decks.save(deck) #assign new deck to custom model mw.col.models.setCurrent(model) mw.col.models.current()["did"] = deck["id"] mw.col.models.save(model) # f=open('terms.txt','wb') txt=u""" <div><img src="{0}" /></div> """ for term in terms: note = mw.col.newNote() note[_("Front")] = term["term"] note[_("Back")] = term["definition"] if not term["image"] is None: #stop the previous thread first self.fileDownloader(term["image"]["url"]) note[_("Back")]+=txt.format(term["image"]["url"].split('/')[-1]) mw.app.processEvents() mw.col.addNote(note) # f.close() mw.col.reset() mw.reset()
def _onTreeDeckRenameLeaf(self, item): mw.checkpoint(_("Rename Deck")) from aqt.utils import showWarning from anki.errors import DeckRenameError self.browser._lastSearchTxt = "" sel = mw.col.decks.byName(item.fullname) try: path, leaf = item.fullname.rsplit('::', 1) newName = path + '::' + getOnlyText(_("New deck name:"), default=leaf) except ValueError: newName = getOnlyText(_("New deck name:"), default=item.fullname) newName = newName.replace('"', "") if not newName or newName == item.fullname: return newName = unicodedata.normalize("NFC", newName) deck = mw.col.decks.get(sel["id"]) try: mw.col.decks.rename(deck, newName) except DeckRenameError as e: return showWarning(e.description) self._swapHighlight(item.type, item.fullname, newName) self._saveDecks() # self.highlight('deck',newName) mw.show() mw.reset(True)
def bulkAdd(browser): nids = browser.selectedNotes() mw.checkpoint("Bulk-add Tatoeba") mw.progress.start() #connect to database #connection = sqlite3.connect(databasePath) global cursor #cursor = connection.cursor() #For each seleccted card for nid in nids: note = mw.col.getNote(nid) #Check if we should do it #First check to see if the fields exist #If field check fails then cancel (does any field not exist and are all of them full? ##skip, deal with it in doNote #do the note if True == doNote(note): note.flush() #save cursor.close() mw.progress.finish() mw.reset()
def regeneratePronunciations(nids): mw.checkpoint("Bulk-add Pronunciations") mw.progress.start() for nid in nids: note = mw.col.getNote(nid) # Check if this is a supported note type. If it is not, skip. # If no note type has been specified, we always continue the lookup proces. if config["noteTypes"] and not any( nt.lower() in note.model()['name'].lower() for nt in config["noteTypes"]): continue src, srcIdx, dst, dstIdx = get_src_dst_fields(note) if src is None or dst is None: continue if note[dst] and not config["regenerateReadings"]: # already contains data, skip continue srcTxt = mw.col.media.strip(note[src]) if not srcTxt.strip(): continue note[dst] = getFormattedPronunciations(srcTxt) note.flush() mw.progress.finish() mw.reset()
def paste_to_my_field(editor): u'''Paste clipboard text to field specified by constant FIELD_NAMES ''' note = editor.note # enumerate all fieldNames of the current note for _, field_name in enumerate(mw.col.models.fieldNames(note.model())): if field_name in FIELD_NAMES: note[field_name] = pyperclip.paste() mw.reset()
def clear_all_editor_fields(editor): u'''Remove text from fields in editor. ''' note = editor.note # enumerate all fieldNames of the current note for c, field_name in enumerate(mw.col.models.fieldNames(note.model())): note[field_name] = '' note.flush() # never forget to flush mw.reset() # refresh gui
def onBulkadd(browser): nids = browser.selectedNotes() for nid in nids: note = mw.col.getNote(nid) onFocusLost(False, note, None) note.flush() mw.progress.finish() mw.reset()
def processTransactions(self, transactions): # transactions is an array transactions.sort(cmp=compare) for t in transactions: if t["query"] in self.CARD_QUERIES: self.CARD_QUERIES[t["query"]](self, t["data"]) else: pass # uh oh, unsupported query mw.reset()
def reset_and_redraw(same_card_shown=False): """Rebuild the scheduler and redraw the card.""" answer_state = mw.reviewer.state == "answer" mw.reset() if answer_state and same_card_shown: try: mw.reviewer._showAnswerHack() except: pass
def changeFont(): f = QFontInfo(QFont(FONT)) ws = QWebSettings.globalSettings() mw.fontHeight = f.pixelSize() mw.fontFamily = f.family() mw.fontHeightDelta = max(0, mw.fontHeight - 13) ws.setFontFamily(QWebSettings.StandardFont, mw.fontFamily) ws.setFontSize(QWebSettings.DefaultFontSize, mw.fontHeight) mw.reset()
def onResetTimes(browser): # Make sure user selected something. if not browser.form.tableView.selectionModel().hasSelection(): showWarning("Please select at least one card to reset creation date.", parent=browser) return # Preprocess cards, collecting note IDs. (card_cnt, nids) = identifyNotes(browser.selectedCards()) # debug #showInfo(("Processed %s cards leading to %s notes") % (card_cnt, len(nids))) # Prompt for date. todaystr = time.strftime('%Y/%m/%d', time.localtime()) (s, ret) = getText("Enter a date as YYYY/MM/DD to set as the creation time, or 'today' for current date (%s):" % todaystr, parent=browser) if (not s) or (not ret): return # Generate a random MM:HH:SS. This will help prevent the same timestamp from # being used if this addon is executed multiple times with the same date. random_time = ("%s:%s:%s") % (random.randint(0, 23), random.randint(0, 59), random.randint(0, 59)) # Don't want random? Uncomment the following line and specify any time you # want in the format HH:MM:SS where HH is 00-24: #random_time = "15:01:01" if s == 'today': desttime = time.mktime(time.strptime(("%s %s") % (todaystr, random_time), '%Y/%m/%d %H:%M:%S')) else: try: desttime = time.mktime(time.strptime(("%s %s") % (s, random_time), '%Y/%m/%d %H:%M:%S')) except ValueError: showWarning("Sorry, I didn't understand that date. Please enter 'today' or a date in YYYY/MM/DD format", parent=browser) return # This mimics anki/utils.py timestampID function (which calls intTime for # seconds since epoch and multiplies those seconds by 1000). desttime = desttime * 1000 # debug # showInfo(("desttime %s") % desttime) # Force a full sync if collection isn't already marked for one. This is # apparently because we are changing the key column of the table. # (Per Damien on 2013/01/07: http://groups.google.com/group/anki-users/msg/3c8910e10f6fd0ac?hl=en ) mw.col.modSchema(check=True) # Do it. resetCreationTimes(nids, desttime) # Done. mw.reset() tooltip(ngettext("Creation time reset for %d note.", "Creation time reset for %d notes.", len(nids)) % len(nids))
def changeModel(name): deck = mw.col #m = deck.models.byName(u'Básico') m = deck.models.byName(name) deck.conf['curModel'] = m['id'] cdeck = deck.decks.current() cdeck['mid'] = m['id'] deck.decks.save(cdeck) runHook("currentModelChanged") mw.reset()
def processDeckTransactions(self, transactions): # transactions is an array # need to sort transactions by timestamp/grouping here transactions.sort(cmp=compare) for t in transactions: if t["query"] in self.DECK_QUERIES: self.DECK_QUERIES[t["query"]](self, t) else: pass # uh oh, unsupported query mw.reset()
def addHeisigNumbers(nids): #get version to use version = getHeisigVersion() if version == False: return fields = [] anote=mw.col.getNote(nids[0]) #get the fields of the first note for (i, f) in anote.items(): fields.append(i) #get input/output fields from user expField = getKeyFromList("Select field to read from", "Read relevant kanji/expression from:", fields) if (expField is None): return heisigNumDstField = getKeyFromList("Select field to write to", "Write Heisig numbers to:", fields) if (heisigNumDstField is None): return mw.checkpoint("Add Heisig Numbers") mw.progress.start() readRTK() #For each seleccted card for nid in nids: note = mw.col.getNote(nid) src = None if expField in note: src = expField if not src: # no src field then next card continue dst = None if heisigNumDstField in note: dst = heisigNumDstField if not dst: # no dst field then skip card continue srcTxt = mw.col.media.strip(note[src]) if not srcTxt.strip(): continue #Add the data to the dst field num = joinseparator.join(lookupKanjiInfo(srcTxt, 'heisig'+version)) if num!=0: note[dst] = str(num) #sys.stderr.write("Results:" + note[dst]) note.flush() mw.progress.finish() mw.reset()
def mergeDupes(res): if not res: return mw.checkpoint(_("Merge Duplicates")) def update(ncc, nc): #if not mw.col.decks.current()['dyn']: # curdid = mw.col.decks.current()['id'] #else: curdid = nc.did mw.col.db.execute("update cards set did=?, mod=?, usn=?, type=?, queue=?, due=?, ivl=?, factor=?, reps=?, lapses=?, left=?, odue=0, odid=0 where id = ?", curdid, intTime(), mw.col.usn(), nc.type, nc.queue, nc.due, nc.ivl, nc.factor, nc.reps, nc.lapses, nc.left, ncc.id) for s, nidlist in res: note_copy = mw.col.newNote() for i, nid in enumerate(nidlist): n = mw.col.getNote(nid) note_copy.tags += n.tags # Because apparently it's nontrivial to retrive cards by ord# so force all cards to exist before we copy the scheduling for (name, value) in n.items(): if not n[name]: n[name] = "BLANK" n.flush() # Add note to database now to force anki to generate cards, then copy an initial state for the new cards if (i == 0): note_copy.fields = n.fields mw.col.addNote(note_copy) for ncc, nc in zip(note_copy.cards(), n.cards()): update(ncc, nc) for (name, value) in note_copy.items(): if value == "BLANK": note_copy[name] = "" if n[name] != "BLANK": if not value or value == "BLANK": note_copy[name] = n[name] continue arr = value.split(" / ") if (n[name] not in arr): note_copy[name] = value + " / " + n[name] for ncc, nc in zip(note_copy.cards(), n.cards()): if nc.ivl > ncc.ivl or nc.queue > ncc.queue: update(ncc, nc) note_copy.flush() mw.col.remNotes(nidlist) mw.col.tags.bulkRem([note_copy.id], _("duplicate")) mw.progress.finish() mw.col.reset() mw.reset() tooltip(_("Notes merged."))
def make_cards(self, terms): title = self.DECK_FIELD.text() img_side = self.I_BUTTON.checkedButton().text() tags = re.split(' |, ', self.TAGS_FIELD.text()) model_name = 'HTML 2 ANKI' #log.info(terms) # MAKE DECK deck = mw.col.decks.get(mw.col.decks.id(title)) # MAKE MODEL IF IT DOESN'T EXIST if self.THEME.isChecked(): if not mw.col.models.byName('Basic (HTML 2 ANKI DARK)') is None: model = mw.col.models.byName('Basic (HTML 2 ANKI DARK)') else: model = dark_theme(model_name, mw.col) else: if not mw.col.models.byName('Basic (HTML 2 ANKI)') is None: model = mw.col.models.byName('Basic (HTML 2 ANKI)') else: model = basic_theme(model_name, mw.col) # ASSIGN MODEL TO DECK mw.col.decks.select(deck['id']) mw.col.decks.get(deck)['mid'] = model['id'] mw.col.decks.save(deck) # ASSIGN DECK TO MODEL mw.col.models.setCurrent(model) mw.col.models.current()['did'] = deck['id'] mw.col.models.save(model) # ITERATE CARDS for term in terms: card = mw.col.newNote() if not term['question'] is None: card['Front'] = u''.join(unicode(i) for i in term['question']) if not term['answer'] is None: card['Back'] = u''.join(unicode(i) for i in term['answer']) if not term['image'] is None: card[img_side] += u'<img src="%s">' % term['image'] mw.app.processEvents() card['http'] = u''.join(unicode(i) for i in term['url']) card.tags = filter(None, tags) mw.col.addNote(card) mw.col.reset() mw.reset() return terms
def run(self, apiKey): """Import all available cards.""" mw.checkpoint("Import from SRS Collector") self._apiKey = apiKey data = self._downloadCardData() self._checkMeta(data["meta"]["anki_addon"]) if "card_models" in data: self._ensureCardModels(data["card_models"]) self._importCardsWithTempDir(data["cards"]) mw.col.autosave() mw.reset()
def add_tag(q, t): # adds tag to note self = get_plugin() setup() note = get_note(q) if not note: raise "Najpierw otaguj siebie, zanim zaczniesz tagować to co nie istnieje..." note.tags.append(t) note.flush() mw.reset()
def doOnCardSelection( b, preF, perF, postF ): st = preF( b ) if not st: return cids = b.selectedCards() for i,cid in enumerate( cids ): card = mw.col.getCard( cid ) st = perF( st, card ) st = postF( st ) if not st or st.get( '__reset', True ): mw.reset()
def promptNewInterval(self, card): dayString = getText("Number of days until next review: ") try: days = int(dayString[0]) except ValueError: return if days > 0: mw.col.sched.reschedCards( [card.id], days, days ) tooltip('Rescheduled for review in ' + str(days) + ' days' ) mw.reset()
def repositionCards(nids): mw.checkpoint("Reposition cards") mw.progress.start() for nid in nids: note = mw.col.getNote(nid) (c,e) = clozeFields(note) # does it contain data? if not c or not e: continue _repositionCards(note, c, e) mw.progress.finish() mw.reset()