def getRows(): finder = Finder(mw.col) #all notes cids = finder.findCards("") for cid in cids: card = mw.col.getCard(cid) deck = mw.col.decks.get(card.did) deckName = deck["name"] note = card.note() model = note._model modelName = model["name"] try: template = model["tmpls"][card.ord] except IndexError: print( f"""Card {cid} has ord {card.ord} and model {modelName}, which have only {len(model["tmpls"])} cards.""", file=sys.stderr) continue templateName = template["name"] try: yield (card.id, card.nid, deckName, templateName, card.mod, card.usn, card.type, card.queue, card.due, card.ivl, card.factor, card.reps, card.lapses, card.odue, card.odid) except: raise
def runBulkFill(mw, config, notifier, updaters, field, updatehow, notification): if mw.web.key == "deckBrowser": return showInfo(u"No deck selected 同志!") log.info("User triggered missing information fill for %s" % field) queryStr = "deck:current " for tag in config.getmodeltagslist(): queryStr += " or note:*" + tag + "* " notes = Finder(mw.col).findNotes(queryStr) for noteId in notes: note = mw.col.getNote(noteId) # Need a fact proxy because the updater works on dictionary-like objects factproxy = pinyin.factproxy.FactProxy(config.candidateFieldNamesByKey, note) if field not in factproxy: continue getattr(updaters[field], updatehow)(factproxy, factproxy[field]) # NB: very important to mark the fact as modified (see #105) because otherwise # the HTML etc won't be regenerated by Anki, so users may not e.g. get working # sounds that have just been filled in by the updater. note.flush() # For good measure, mark the deck as modified as well (see #105) mw.col.setMod() # DEBUG consider future feature to add missing measure words cards after doing so (not now) notifier.info(notification)
def bulk_fill_all(): prompt = ( '<div>This will update <i>all</i> non-audio fields in the current deck.</div>' '<div>Please back up your Anki collection first!</div>' '<div><b>Continue?</b></div>') if not askUser(prompt): return note_ids = Finder(mw.col).findNotes('deck:current') mw.progress.start(immediate=True, min=0, max=len(note_ids)) n_updated = 0 n_failed = 0 # FIXME exclude = config.get_fields(['sound', 'mandarinSound', 'cantoneseSound']) for i, nid in enumerate(note_ids): note = mw.col.getNote(nid) fields = [ f for f in mw.col.models.fieldNames(note.model()) if f not in exclude ] n_updated += update_fields(note, 'Hanzi', fields) msg = PROGRESS_TEMPLATE % { 'hanzi': get_hanzi(dict(note)), 'n_processed': i, 'n_updated': n_updated, 'n_failed': n_failed, } mw.progress.update(label=msg, value=i) note.flush() mw.progress.finish() showInfo('<b>Bulk filling complete</b><br>' '<b>Processed:</b> {}<br>'.format(len(note_ids)))
def bulk_fill_transcript(): prompt = PROMPT_TEMPLATE.format( field_names='<i>transcription</i> and <i>ruby</i>', extra_info='') field_groups = [ 'transcription', 'pinyin', 'pinyinTaiwan', 'cantonese', 'bopomofo', ] if not askUser(prompt): return d_has_fields = 0 d_added_pinyin = 0 d_updated = 0 note_ids = Finder(mw.col).findNotes('deck:current') mw.progress.start(immediate=True, min=0, max=len(note_ids)) for i, nid in enumerate(note_ids): note = mw.col.getNote(nid) copy = dict(note) if has_any_field(copy, field_groups) and has_field( config['fields']['hanzi'], copy): d_has_fields += 1 msg = ''' <b>Processing:</b> %(hanzi)s<br> <b>Filled pinyin:</b> %(pinyin)d notes<br> <b>Updated: </b>%(updated)d fields''' % { 'hanzi': get_hanzi(copy), 'pinyin': d_added_pinyin, 'updated': d_updated, } mw.progress.update(label=msg, value=i) hanzi = get_first(config['fields']['hanzi'], copy) results = fill_transcript(hanzi, copy) results += fill_bopomofo(hanzi, copy) if results > 0: d_added_pinyin += 1 fill_all_rubies(hanzi, copy) save_note(note, copy) mw.progress.finish() msg = ''' <b>Processing:</b> %(hanzi)s<br> <b>Filled pinyin:</b> %(pinyin)d notes<br> <b>Updated: </b>%(updated)d fields''' % { 'hanzi': get_hanzi(copy), 'pinyin': d_added_pinyin, 'updated': d_updated, } showInfo(msg)
def getRows(): finder = Finder(mw.col) #all notes nids = finder.findNotes("") models = mw.col.models.models for nid in nids: note = mw.col.getNote(nid) mid = note.mid model = note._model if model is None: print(f"Note {nid}'s model {mid}({type(mid)}) is not a model.") modelName = model["name"] try: yield (note.id, note.guid, note.mod, modelName, note.usn) except: raise
def bulk_fill_hanzi(): prompt = ''' <div>This will update the <i>Simplified</i> and <i>Traditional</i> fields in the current deck, if they exist and are empty.</div> <div>Please back-up your Anki deck first!</div> <div><b>Continue?</b></div> ''' if not askUser(prompt): return query_str = 'deck:current' d_scanned = 0 d_has_fields = 0 d_success = 0 notes = Finder(mw.col).findNotes(query_str) mw.progress.start(immediate=True, min=0, max=len(notes)) for noteId in notes: d_scanned += 1 note = mw.col.getNote(noteId) note_dict = dict(note) if (has_field(config['fields']['simplified'], note_dict) or has_field( config['fields']['traditional'], note_dict)) and has_field( config['fields']['hanzi'], note_dict): d_has_fields += 1 msg = ''' <b>Processing:</b> %(hanzi)s<br> <b>Updated:</b> %(filled)d''' % { 'hanzi': sanitize_hanzi(note_dict), 'filled': d_success, } mw.progress.update(label=msg, value=d_scanned) hanzi = get_first(config['fields']['hanzi'], note_dict) fill_simp(hanzi, note_dict) fill_trad(hanzi, note_dict) for f in config['fields']['traditional']: if f in note_dict and note_dict[f] != note[f]: note[f] = note_dict[f] d_success += 1 for f in config['fields']['simplified']: if f in note_dict and note_dict[f] != note[f]: note[f] = note_dict[f] d_success += 1 note.flush() msg = ''' <b>Update complete!</b> %(hanzi)s<br> <b>Updated:</b> %(filled)d notes''' % { 'hanzi': sanitize_hanzi(note_dict), 'filled': d_success, } mw.progress.finish() showInfo(msg)
def fill_simp_trad(collection, view_key): if view_key == "deckBrowser": return showInfo(u"First select one of your decks") if not (askUser( "<div>This will update the <i>Simplified</i> and <i>Traditional</i> fields in the current deck, if they exist and are empty.</div>\n\n<div>Please back-up your Anki deck first!</div>\n\n<div><b>Continue?</b></div>" )): return False query_str = "deck:current" d_scanned = 0 d_has_fields = 0 d_success = 0 d_failed = 0 notes = Finder(collection).findNotes(query_str) mw.progress.start(immediate=True, min=0, max=len(notes)) for noteId in notes: d_scanned += 1 note = collection.getNote(noteId) note_dict = dict(note) # edit_function routines require a dict if (has_field(Simplified_fields, note_dict) or has_field(Traditional_fields, note_dict)) and has_field( Hanzi_fields, note_dict): d_has_fields += 1 msg_string = "<b>Processing:</b> %(hanzi)s<br><b>Updated:</b> %(filled)d" % { "hanzi": cleanup(no_html(get_any(Hanzi_fields, note_dict))), "filled": d_success } mw.progress.update(label=msg_string, value=d_scanned) #Update simplified/traditional fields #If it's the same, leave empty, #so as to make this feature unobtrusive to simplified chinese users hanzi = get_any(Hanzi_fields, note_dict) update_Simplified_fields(hanzi, note_dict) update_Traditional_fields(hanzi, note_dict) # write back to note from dict and flush for f in Traditional_fields: if note_dict.has_key(f) and note_dict[ f] is not None and note_dict[f] <> note[f]: note[f] = note_dict[f] d_success += 1 for f in Simplified_fields: if note_dict.has_key(f) and note_dict[ f] is not None and note_dict[f] <> note[f]: note[f] = note_dict[f] d_success += 1 note.flush() msg_string = "<b>Update complete!</b> %(hanzi)s<br><b>Updated:</b> %(filled)d notes" % { "hanzi": cleanup(no_html(get_any(Hanzi_fields, note_dict))), "filled": d_success } mw.progress.finish() showInfo(msg_string)
def fill_silhouette(): if not (askUser( "<div>This will update the <i>Silhouette</i> fields in the " "current deck.</div>\n\n" "<div>Please back-up your Anki deck first!</div>\n\n" "<div><b>Continue?</b></div>")): return False query_str = "deck:current" d_scanned = 0 d_has_fields = 0 d_success = 0 notes = Finder(mw.col).findNotes(query_str) mw.progress.start(immediate=True, min=0, max=len(notes)) for noteId in notes: d_scanned += 1 note = mw.col.getNote(noteId) note_dict = dict(note) # edit_function routines require a dict if has_field(config.options["fields"]["silhouette"], note_dict): d_has_fields += 1 msg_string = ("<b>Processing:</b> {hangul:s}<br>" "<b>Updated:</b> {filled:d}").format( hangul=cleanup( no_html( get_any( config.options["fields"]["hangul"], note_dict))), filled=d_success, ) mw.progress.update(label=msg_string, value=d_scanned) hangul = get_any(config.options["fields"]["hangul"], note_dict) # Update Silhouette update_Silhouette_fields(hangul, note_dict) # write back to note from dict and flush for f in config.options["fields"]["silhouette"]: if f in note_dict and note_dict[f] != note[f]: note[f] = note_dict[f] d_success += 1 note.flush() msg_string = ("<b>Update complete!</b> {hangul:s}<br>" "<b>Updated:</b> {filled:d}").format( hangul=cleanup( no_html( get_any(config.options["fields"]["hangul"], note_dict))), filled=d_success, ) mw.progress.finish() showInfo(msg_string)
def fill_silhouette(collection, view_key): if view_key == "deckBrowser": return showInfo(u"First select one of your decks") if not (askUser( "<div>This will update the <i>Silhouette</i> fields in the current deck.</div>\n\n<div>Please back-up your Anki deck first!</div>\n\n<div><b>Continue?</b></div>" )): return False query_str = "deck:current" d_scanned = 0 d_has_fields = 0 d_success = 0 d_failed = 0 notes = Finder(collection).findNotes(query_str) mw.progress.start(immediate=True, min=0, max=len(notes)) for noteId in notes: d_scanned += 1 note = collection.getNote(noteId) note_dict = dict(note) # edit_function routines require a dict if has_field(Silhouette_fields, note_dict): d_has_fields += 1 msg_string = "<b>Processing:</b> %(hanzi)s<br><b>Updated:</b> %(filled)d" % { "hanzi": cleanup(no_html(get_any(Hanzi_fields, note_dict))), "filled": d_success } mw.progress.update(label=msg_string, value=d_scanned) hanzi = get_any(Hanzi_fields, note_dict) #Update Silhouette update_Silhouette_fields(hanzi, note_dict) # write back to note from dict and flush for f in Silhouette_fields: if note_dict.has_key(f) and note_dict[ f] is not None and note_dict[f] <> note[f]: note[f] = note_dict[f] d_success += 1 note.flush() msg_string = "<b>Update complete!</b> %(hanzi)s<br><b>Updated:</b> %(filled)d notes" % { "hanzi": cleanup(no_html(get_any(Hanzi_fields, note_dict))), "filled": d_success } mw.progress.finish() showInfo(msg_string)
def fill_silhouette(): prompt = ''' <div>This will update the <i>Silhouette</i> fields in the current deck.</div> <div>Please back-up your Anki deck first!</div> <div><b>Continue?</b></div> ''' if not askUser(prompt): return query_str = 'deck:current' d_scanned = 0 d_has_fields = 0 d_success = 0 notes = Finder(mw.col).findNotes(query_str) mw.progress.start(immediate=True, min=0, max=len(notes)) for noteId in notes: d_scanned += 1 note = mw.col.getNote(noteId) note_dict = dict(note) if has_field(config['fields']['silhouette'], note_dict): d_has_fields += 1 msg = ''' <b>Processing:</b> %(hanzi)s<br> <b>Updated:</b> %(filled)d''' % { 'hanzi': sanitize_hanzi(note_dict), 'filled': d_success } mw.progress.update(label=msg, value=d_scanned) hanzi = get_first(config['fields']['hanzi'], note_dict) update_Silhouette_fields(hanzi, note_dict) # write back to note from dict and flush for f in config['fields']['silhouette']: if f in note_dict and note_dict[f] != note[f]: note[f] = note_dict[f] d_success += 1 note.flush() msg = ''' <b>Update complete!</b> %(hanzi)s<br> <b>Updated:</b> %(filled)d notes''' % { 'hanzi': sanitize_hanzi(note_dict), 'filled': d_success } mw.progress.finish() showInfo(msg)
def fill_missing(): notes = Finder(mw.col).findNotes("deck:current") mw.progress.start(immediate=True, min=0, max=len(notes)) scanned = 0 for noteId in notes: scanned += 1 note = mw.col.getNote(noteId) note_dict = dict(note) if "Korean" in note_dict: korean = cleanup(note_dict["Korean"]) if "English" in note_dict and cleanup(note_dict["English"]) == "": mw.progress.update(label=f"[{korean}] Translating...", value=scanned) english = cleanup(note_dict["English"]) if korean != "" and english == "": translation = lookup(korean) note_dict["Korean"] = korean note_dict["English"] = translation if "Hanja" in note_dict and cleanup(note_dict["Hanja"]) == "": mw.progress.update( label=f"[{korean}] Looking up Hanja...", value=scanned ) found = hanja.lookup(korean) if found is not None: note_dict["Hanja"] = found["hanja"] if "Silhouette" in note_dict and cleanup(note_dict["Silhouette"]) == "": mw.progress.update( label=f"[{korean}] Processing silhouette...", value=scanned ) note_dict["Silhouette"] = silhouette(korean) if "Sound" in note_dict and cleanup(note_dict["Sound"]) == "": mw.progress.update( label=f"[{korean}] Looking up sound...", value=scanned ) note_dict["Sound"] = tts(korean) write_back( note, note_dict, ["Korean", "English", "Hanja", "Silhouette", "Sound"] ) print(note_dict) mw.progress.finish()
def bulk_fill_classifiers(): prompt = PROMPT_TEMPLATE.format(field_names='<i>classifier</i>', extra_info='') field_groups = ['classifier'] if not askUser(prompt): return n_targets = 0 d_success = 0 d_failed = 0 note_ids = Finder(mw.col).findNotes('deck:current') mw.progress.start(immediate=True, min=0, max=len(note_ids)) for i, nid in enumerate(note_ids): note = mw.col.getNote(nid) copy = dict(note) hanzi = get_hanzi(copy) if has_any_field(copy, field_groups) and hanzi: n_targets += 1 if all_fields_empty(copy, field_groups): if fill_classifier(hanzi, copy): d_success += 1 else: d_failed += 1 msg = PROGRESS_TEMPLATE % { 'hanzi': hanzi, 'has_fields': n_targets, 'filled': d_success, 'failed': d_failed, } mw.progress.update(label=msg, value=i) save_note(note, copy) mw.progress.finish() showInfo(END_TEMPLATE % { 'has_fields': n_targets, 'filled': d_success, 'failed': d_failed })
def get_resource(username): logging.debug("Getting resource.") collection_path = os.path.join(config["data_root"], username, "collection.anki2") col = collection_manager.get_collection(collection_path, None) real_col = col.wrapper._get_collection() data_by_deck = {} finder = Finder(real_col) for deck in real_col.decks.all(): data_by_deck[deck["name"]] = group_cards_for_deck(finder, deck) data_for_all = group_cards_for_deck(finder) finder = None real_col.close() data = {"all": data_for_all, "by_deck": data_by_deck} return data
def bulk_fill_hanzi(): prompt = PROMPT_TEMPLATE.format(field_names='<i>hanzi</i>', extra_info='') field_groups = ['traditional', 'simplified'] if not askUser(prompt): return d_has_fields = 0 d_success = 0 note_ids = Finder(mw.col).findNotes('deck:current') mw.progress.start(immediate=True, min=0, max=len(note_ids)) for i, nid in enumerate(note_ids): note = mw.col.getNote(nid) copy = dict(note) if has_any_field(copy, field_groups) and has_field( config['fields']['hanzi'], copy ): d_has_fields += 1 msg = ''' <b>Processing:</b> %(hanzi)s<br> <b>Updated:</b> %(filled)d''' % { 'hanzi': get_hanzi(copy), 'filled': d_success, } mw.progress.update(label=msg, value=i) hanzi = get_first(config['fields']['hanzi'], copy) fill_simp(hanzi, copy) fill_trad(hanzi, copy) fill_color(hanzi, copy) d_success = save_note(note, copy) msg = ''' <b>Update complete!</b> %(hanzi)s<br> <b>Updated:</b> %(filled)d notes''' % { 'hanzi': get_hanzi(copy), 'filled': d_success, } mw.progress.finish() showInfo(msg)
def bulk_fill_defs(): prompt = PROMPT_TEMPLATE.format( field_names='<i>definition</i> and <i>alternative</i>', extra_info='', ) progress_msg_template = ''' <b>Processing:</b> %(hanzi)s<br> <b>Chinese notes:</b> %(has_fields)d<br> <b>Translated:</b> %(filled)d<br> <b>Failed:</b> %(failed)d''' field_groups = ['meaning', 'english', 'german', 'french'] if not askUser(prompt): return n_targets = 0 d_success = 0 d_failed = 0 failed_hanzi = [] note_ids = Finder(mw.col).findNotes('deck:current') mw.progress.start(immediate=True, min=0, max=len(note_ids)) for i, nid in enumerate(note_ids): note = mw.col.getNote(nid) copy = dict(note) hanzi = get_hanzi(copy) if has_any_field(copy, field_groups) and hanzi: n_targets += 1 if all_fields_empty(copy, field_groups): result = fill_all_defs(hanzi, copy) if result: d_success += 1 else: d_failed += 1 if d_failed < 20: failed_hanzi += [hanzi] msg = progress_msg_template % { 'hanzi': hanzi, 'has_fields': n_targets, 'filled': d_success, 'failed': d_failed, } mw.progress.update(label=msg, value=i) save_note(note, copy) msg = ''' <b>Translation complete</b><br> <b>Chinese notes:</b> %(has_fields)d<br> <b>Translated:</b> %(filled)d<br> <b>Failed:</b> %(failed)d''' % { 'has_fields': n_targets, 'filled': d_success, 'failed': d_failed, } if d_failed > 0: msg += ( '<div>Translation failures may come either from connection issues ' "(if you're using an online translation service), or because some " 'words are not it the dictionary (for local dictionaries).</div>' '<div>The following notes failed: ' + ', '.join(failed_hanzi) + '</div>') mw.progress.finish() showInfo(msg)
def fill_translation(): if not (askUser( "<div>This will update the <i>Meaning</i> field in the current " "deck, if they exist and are empty.</div>" "<b>Learning tip:</b><div>Automatic dictionary lookup tends to " "produce very long text, often with multiple translations.</div>" "\n\n" "<div>For more effective memorization, it's highly " "recommended to trim them down to just a few words, only one " "meaning, and possibly add some mnemonics.</div>\n\n" "<div>Dictionary lookup is simply meant as a way to save you time " "when typing; please consider editing each definition by hand when" " you're done.</div>\n\n" "<div>Please back-up your Anki deck first!</div>\n\n" "<div><b>Continue?</b></div>")): return False query_str = "deck:current" d_scanned = 0 d_has_fields = 0 d_success = 0 d_failed = 0 failed_hangul = [] notes = Finder(mw.col).findNotes(query_str) mw.progress.start(immediate=True, min=0, max=len(notes)) for noteId in notes: d_scanned += 1 note = mw.col.getNote(noteId) note_dict = dict(note) # edit_function routines require a dict if has_field(config.options["fields"]["meaning"], note_dict) and has_field( config.options["fields"]["hangul"], note_dict): d_has_fields += 1 msg_string = ("<b>Processing:</b> {hangul:s}<br>" "<b>Korean notes:</b> {has_fields:d}<br>" "<b>Translated:</b> {filled:d}<br>" "<b>Failed:</b> {failed:d}").format( hangul=cleanup( no_html( get_any( config.options["fields"]["hangul"], note_dict))), has_fields=d_has_fields, filled=d_success, failed=d_failed, ) mw.progress.update(label=msg_string, value=d_scanned) hangul = get_any(config.options["fields"]["hangul"], note_dict) empty = len(get_any(config.options["fields"]["meaning"], note_dict)) if not (empty): result = update_Meaning_fields(hangul, note_dict) if result == 0: d_failed += 1 if d_failed < 20: failed_hangul += [ cleanup( no_html( get_any(config.options["fields"]["hangul"], note_dict))) ] else: d_success += 1 def write_back(fields): for f in fields: if f in note_dict and note_dict[f] != note[f]: note[f] = note_dict[f] return # write back to note from dict and flush write_back(config.options["fields"]["meaning"]) note.flush() msg_string = ("<b>Translation complete</b> <br>" "<b>Korean notes:</b> {has_fields:d}<br>" "<b>Translated:</b> {filled:d}<br>" "<b>Failed:</b> {failed:d}").format(has_fields=d_has_fields, filled=d_success, failed=d_failed) if d_failed > 0: msg_string += ("\n\n<div>Translation failures may come either from " "connection issues (if you're using an on-line " "translation service), or because some words are not in" " the dictionary (for local dictionaries).</div>") msg_string += "<div>The following notes failed: {}</div>".format( ", ".join(failed_hangul)) mw.progress.finish() showInfo(msg_string)
def _build_index(index_up_to_date): """ Builds the index. Result is stored in global var searchIndex. The index.type is either "Whoosh"/"SQLite FTS3"/"SQLite FTS4"/"SQLite FTS5" """ start = time.time() config = mw.addonManager.getConfig(__name__) try: useFTS = config['useFTS'] except KeyError: useFTS = False searchIndex = None corpus = get_corpus() #fts4 based sqlite reversed index if config["disableNonNativeSearching"] or useFTS: searchIndex = FTSIndex(corpus, config["disableNonNativeSearching"], index_up_to_date) end = time.time() initializationTime = round(end - start) #whoosh index else: searchIndex = WhooshSearchIndex(corpus, config["disableNonNativeSearching"], index_up_to_date) end = time.time() initializationTime = round(end - start) searchIndex.finder = Finder(mw.col) searchIndex.output.stopwords = searchIndex.stopWords searchIndex.output.remove_divs = config["removeDivsFromOutput"] searchIndex.output.gridView = config["gridView"] searchIndex.output.scale = config["noteScale"] searchIndex.output.fields_to_hide_in_results = config[ "fieldsToHideInResults"] searchIndex.selectedDecks = ["-1"] searchIndex.lastSearch = None searchIndex.lastResDict = None searchIndex.tagSearch = True searchIndex.tagSelect = False searchIndex.topToggled = True searchIndex.output.edited = {} searchIndex.initializationTime = initializationTime searchIndex.synonyms = loadSynonyms() searchIndex.tagSearch = config["searchOnTagEntry"] searchIndex.logging = config["logging"] searchIndex.searchbar_mode = "Add-on" try: limit = config['numberOfResults'] if limit <= 0: limit = 1 elif limit > 5000: limit = 5000 except KeyError: limit = 500 searchIndex.limit = limit try: showRetentionScores = config["showRetentionScores"] except KeyError: showRetentionScores = True searchIndex.output.showRetentionScores = showRetentionScores try: hideSidebar = config["hideSidebar"] except KeyError: hideSidebar = False searchIndex.output.hideSidebar = hideSidebar if searchIndex.logging: log("\n--------------------\nInitialized searchIndex:") log("""Type: %s\n# Stopwords: %s \n# Synonyms: %s \nLimit: %s \n""" % (searchIndex.type, len( searchIndex.stopWords), len(searchIndex.synonyms), limit)) editor = aqt.mw.app.activeWindow().editor if hasattr( aqt.mw.app.activeWindow(), "editor") else None if editor is not None and editor.addMode: searchIndex.output.editor = editor set_index(searchIndex) editor = editor if editor is not None else get_edit() showSearchResultArea(editor, initializationTime=initializationTime) printStartingInfo(editor)
def getNidsFromRelations(relations): finder = Finder(mw.col) nids = set(finder.findNotes(queryRelated(relations))) debug(f"from relations {relations} we get nids {nids}") return nids
def bulk_fill_sound(): prompt = ''' <div>This will update the <i>Sound</i> fields in the current deck, if they exist and are empty, using the selected speech engine.</div> <div>Please back-up your Anki deck first!</div> <div>(Please also note that there will be a 5 second delay between each sound request, to reduce burden on the server. This may therefore take a while.)</div> <div><b>Continue?</b></div> ''' if not askUser(prompt): return query_str = 'deck:current' d_scanned = 0 d_has_fields = 0 d_already_had_sound = 0 d_success = 0 d_failed = 0 note_ids = Finder(mw.col).findNotes(query_str) mw.progress.start(immediate=True, min=0, max=len(note_ids)) for nid in note_ids: d_scanned += 1 orig = mw.col.getNote(nid) copy = dict(orig) _hf_s = has_field(config['fields']['sound'], copy) _hf_sm = has_field(config['fields']['mandarinSound'], copy) _hf_sc = has_field(config['fields']['cantoneseSound'], copy) if (_hf_s or _hf_sm or _hf_sc) and has_field(config['fields']['hanzi'], copy): d_has_fields += 1 hanzi = get_first(config['fields']['hanzi'], copy) if (get_first(config['fields']['sound'], copy) or get_first(config['fields']['mandarinSound'], copy) or get_first(config['fields']['cantoneseSound'], copy)): d_already_had_sound += 1 else: msg = ''' <b>Processing:</b> %(hanzi)s<br> <b>Updated:</b> %(d_success)d notes<br> <b>Failed:</b> %(d_failed)d notes''' % { 'hanzi': sanitize_hanzi(copy), 'd_success': d_success, 'd_failed': d_failed, } mw.progress.update(label=msg, value=d_scanned) s, f = fill_sound(hanzi, copy) d_success += s d_failed += f save_note(orig, copy) sleep(5) mw.progress.finish() msg = ''' %(d_success)d new pronunciations downloaded %(d_failed)d downloads failed %(have)d/%(d_has_fields)d notes now have pronunciation''' % { 'd_success': d_success, 'd_failed': d_failed, 'have': d_already_had_sound + d_success, 'd_has_fields': d_has_fields, } if d_failed > 0: msg += ('TTS is taken from an online source. ' 'It may not always be fully responsive. ' 'Please check your network connexion, or retry later.') showInfo(msg)
def _build_index(index_up_to_date): """ Builds the index. Result is stored in global var index. The index.type is either "Whoosh"/"SQLite FTS3"/"SQLite FTS4"/"SQLite FTS5" """ start = time.time() config = mw.addonManager.getConfig(__name__) corpus = get_corpus() index = FTSIndex(corpus, index_up_to_date) end = time.time() initializationTime = round(end - start) index.finder = Finder(mw.col) index.ui.stopwords = index.stopWords index.ui.remove_divs = config["removeDivsFromOutput"] index.ui.gridView = config["gridView"] index.ui.scale = config["noteScale"] index.ui.fields_to_hide_in_results = config["fieldsToHideInResults"] index.selectedDecks = ["-1"] index.lastSearch = None index.lastResDict = None index.topToggled = True index.ui.edited = {} index.initializationTime = initializationTime index.synonyms = loadSynonyms() index.logging = config["logging"] index.searchbar_mode = "Add-on" try: limit = config['numberOfResults'] if limit <= 0: limit = 1 elif limit > 5000: limit = 5000 except KeyError: limit = 500 index.limit = limit try: showRetentionScores = config["showRetentionScores"] except KeyError: showRetentionScores = True index.ui.showRetentionScores = showRetentionScores try: hideSidebar = config["hideSidebar"] except KeyError: hideSidebar = False index.ui.hideSidebar = hideSidebar if index.logging: log("\n--------------------\nInitialized index:") log("""Type: %s\n# Stopwords: %s \n# Synonyms: %s \nLimit: %s \n""" % (index.type, len(index.stopWords), len(index.synonyms), limit)) editor = aqt.mw.app.activeWindow().editor if hasattr( aqt.mw.app.activeWindow(), "editor") else None if editor is not None and editor.addMode: index.ui.set_editor(editor) set_index(index) editor = editor if editor is not None else get_edit() setup_ui_after_index_built(editor, index) # showSearchResultArea(editor, initializationTime=initializationTime) fillDeckSelect(editor) printStartingInfo(editor)
def getReviewCards(): finder = Finder(mw.col) cids = finder.findCards("is:review") return cids
def fill_sounds(): prompt = """<div>This will update the <i>Sound</i> fields in the current deck, if they exist and are empty, using the selected speech engine.</div> <div>Please back-up your Anki deck first!</div> <div>(Please also note that there will be a 5 second delay between each sound request, to reduce burden on the server. This may therefore take a while.)</div> <div><b>Continue?</b></div>""" if not askUser(prompt): return False query_str = "deck:current" d_scanned = 0 d_has_fields = 0 d_already_had_sound = 0 d_success = 0 d_failed = 0 notes = Finder(mw.col).findNotes(query_str) mw.progress.start(immediate=True, min=0, max=len(notes)) for noteId in notes: d_scanned += 1 note = mw.col.getNote(noteId) note_dict = dict(note) # edit_function routines require a dict if has_field(config.options["fields"]["sound"], note_dict) and has_field( config.options["fields"]["hangul"], note_dict): d_has_fields += 1 hangul = get_any(config.options["fields"]["hangul"], note_dict) if get_any(config.options["fields"]["sound"], note_dict): d_already_had_sound += 1 else: msg_string = ( "<b>Processing:</b> {hangul:s}<br>" "<b>Updated:</b> {d_success:d} notes<br>" "<b>Failed:</b> {d_failed:d} notes").format( hangul=cleanup( no_html( get_any(config.options["fields"]["hangul"], note_dict))), d_success=d_success, d_failed=d_failed, ) mw.progress.update(label=msg_string, value=d_scanned) s, f = update_Sound_fields(hangul, note_dict) d_success += s d_failed += f # write back to note from dict and flush for f in config.options["fields"]["sound"]: if f in note_dict and note_dict[f] != note[f]: note[f] = note_dict[f] note.flush() sleep(5) mw.progress.finish() msg_string = """ {d_success:d} new pronunciations downloaded {d_failed:d} downloads failed {have:d}/{d_has_fields:d} notes now have pronunciation """.format( d_success=d_success, d_failed=d_failed, have=d_already_had_sound + d_success, d_has_fields=d_has_fields, ) if d_failed > 0: msg_string = msg_string + ("\n\nTTS is taken from an on-line source. " "It may not always be fully responsive. " "Please check your network connexion, " "or retry later.\n\nIf failures persist, " "please set Korean Support to debug mode " "and submit a bug report from the help " "menu.") showInfo(msg_string)
def fill_translation(collection, view_key): if view_key == "deckBrowser": return showInfo(u"First select one of your decks") if not (askUser( "<div>This will update the <i>Meaning</i>, <i>Mean Word</i>, and <i>Also Written</i> fields in the current deck, if they exist and are empty.</div><b>Learning tip:</b><div>Automatic dictionary lookup tends to produce very long text, often with multiple translations.</div>\n\n<div>For more effective memorization, it's highly recommended to trim them down to just a few words, only one meaning, and possibly add some mnemonics.</div>\n\n<div>Dictionary lookup is simply meant as a way to save you time when typing; please consider editing each definition by hand when you're done.</div>\n\n<div>Please back-up your Anki deck first!</div>\n\n<div><b>Continue?</b></div>" )): return False query_str = "deck:current" d_scanned = 0 d_has_fields = 0 d_success = 0 d_failed = 0 failed_hanzi = [] notes = Finder(collection).findNotes(query_str) mw.progress.start(immediate=True, min=0, max=len(notes)) for noteId in notes: d_scanned += 1 note = collection.getNote(noteId) note_dict = dict(note) # edit_function routines require a dict _hf_m = has_field(Meaning_fields, note_dict) _hf_e = has_field(English_fields, note_dict) _hf_g = has_field(German_fields, note_dict) _hf_f = has_field(French_fields, note_dict) if (_hf_m or _hf_e or _hf_g or _hf_f) and has_field( Hanzi_fields, note_dict): d_has_fields += 1 msg_string = "<b>Processing:</b> %(hanzi)s<br><b>Chinese notes:</b> %(has_fields)d<br><b>Translated:</b> %(filled)d<br><b>Failed:</b> %(failed)d" % { "hanzi": cleanup(no_html(get_any(Hanzi_fields, note_dict))), "has_fields": d_has_fields, "filled": d_success, "failed": d_failed } mw.progress.update(label=msg_string, value=d_scanned) hanzi = get_any(Hanzi_fields, note_dict) empty = len(get_any(Meaning_fields, note_dict)) empty += len(get_any(English_fields, note_dict)) empty += len(get_any(German_fields, note_dict)) empty += len(get_any(French_fields, note_dict)) if not (empty): result = 0 if _hf_m: result += update_Meaning_fields(hanzi, note_dict) if _hf_e: result += update_English_fields(hanzi, note_dict) if _hf_g: result += update_German_fields(hanzi, note_dict) if _hf_f: result += update_French_fields(hanzi, note_dict) if result == 0: d_failed += 1 if d_failed < 20: failed_hanzi += [ cleanup(no_html(get_any(Hanzi_fields, note_dict))) ] else: d_success += 1 def write_back(fields): for f in fields: if note_dict.has_key(f) and note_dict[ f] is not None and note_dict[f] <> note[f]: note[f] = note_dict[f] return # write back to note from dict and flush write_back(Meaning_fields) write_back(English_fields) write_back(German_fields) write_back(French_fields) write_back(Mean_Word_fields) write_back(Alternate_fields) note.flush() msg_string = "<b>Translation complete</b> <br><b>Chinese notes:</b> %(has_fields)d<br><b>Translated:</b> %(filled)d<br><b>Failed:</b> %(failed)d" % { "has_fields": d_has_fields, "filled": d_success, "failed": d_failed } if d_failed > 0: msg_string += "\n\n<div>Translation failures may come either from connection issues (if you're using an on-line translation service), or because some words are not it the dictionary (for local dictionaries).</div>" msg_string += "<div>The following notes failed: " + ", ".join( failed_hanzi) + "</div>" mw.progress.finish() showInfo(msg_string)
def fill_sounds(collection, view_key): if view_key == "deckBrowser": return showInfo(u"Please first select one of your decks.") if not (askUser( "<div>This will update the <i>Sound</i> fields in the current deck, if they exist and are empty, using the selected speech engine.</div>\n\n<div>Please back-up your Anki deck first!</div>\n\n<div><b>Continue?</b></div>" )): return False query_str = "deck:current" d_scanned = 0 d_has_fields = 0 d_already_had_sound = 0 d_success = 0 d_failed = 0 notes = Finder(collection).findNotes(query_str) mw.progress.start(immediate=True, min=0, max=len(notes)) for noteId in notes: d_scanned += 1 note = collection.getNote(noteId) note_dict = dict(note) # edit_function routines require a dict _hf_s = has_field(Sound_fields, note_dict) _hf_sm = has_field(Sound_Mandarin_fields, note_dict) _hf_sc = has_field(Sound_Cantonese_fields, note_dict) if (_hf_s or _hf_sm or _hf_sc) and has_field(Hanzi_fields, note_dict): d_has_fields += 1 hanzi = get_any(Hanzi_fields, note_dict) if get_any(Sound_fields, note_dict) or get_any( Sound_Mandarin_fields, note_dict) or get_any( Sound_Cantonese_fields, note_dict): d_already_had_sound += 1 else: msg_string = "<b>Processing:</b> %(hanzi)s<br><b>Updated:</b> %(d_success)d notes<br><b>Failed:</b> %(d_failed)d notes" % { "hanzi": cleanup(no_html(get_any(Hanzi_fields, note_dict))), "d_success": d_success, "d_failed": d_failed } mw.progress.update(label=msg_string, value=d_scanned) s, f = update_all_Sound_fields(hanzi, note_dict) d_success += s d_failed += f # write back to note from dict and flush for f in Sound_fields + Sound_Mandarin_fields + Sound_Cantonese_fields: if note_dict.has_key(f) and note_dict[ f] is not None and note_dict[f] <> note[f]: note[f] = note_dict[f] note.flush() mw.progress.finish() msg_string = ''' %(d_success)d new pronunciations downloaded %(d_failed)d downloads failed %(have)d/%(d_has_fields)d notes now have pronunciation ''' % { "d_success": d_success, "d_failed": d_failed, "have": d_already_had_sound + d_success, "d_has_fields": d_has_fields } if d_failed > 0: msg_string = msg_string + "\n\nTTS is taken from an on-line source. It may not always be fully responsive. Please check your network connexion, or retry later." showInfo(msg_string)
def test_parse(): f = Finder(None) assert f._tokenize("hello world") == ["hello", "world"] assert f._tokenize("hello world") == ["hello", "world"] assert f._tokenize("one -two") == ["one", "-", "two"] assert f._tokenize("one --two") == ["one", "-", "two"] assert f._tokenize("one - two") == ["one", "-", "two"] assert f._tokenize("one or -two") == ["one", "or", "-", "two"] assert f._tokenize("'hello \"world\"'") == ["hello \"world\""] assert f._tokenize('"hello world"') == ["hello world"] assert f._tokenize("one (two or ( three or four))") == [ "one", "(", "two", "or", "(", "three", "or", "four", ")", ")"] assert f._tokenize("embedded'string") == ["embedded'string"] assert f._tokenize("deck:'two words'") == ["deck:two words"]
def test_parse(): f = Finder(None) assert f._tokenize("hello world") == ["hello", "world"] assert f._tokenize("hello world") == ["hello", "world"] assert f._tokenize("one -two") == ["one", "not", "two"] assert f._tokenize("one --two") == ["one", "not", "two"] assert f._tokenize("one or -two") == ["one", "or", "not", "two"] assert f._tokenize("'hello \"world\"'") == ["hello \"world\""] assert f._tokenize('"hello world"') == ["hello world"] assert f._tokenize("one (two or ( three or four))") == [ "one", "(", "two", "or", "(", "three", "or", "four", ")", ")" ] assert f._tokenize("embedded'string") == ["embedded'string"] assert f._tokenize("deck:'two words'") == ["deck:two words"]
def bulk_fill_pinyin(): prompt = ''' <div>This will update the <i>Pinyin</i> (or <i>Transcription</i>), <i>Color</i> and <i>Ruby</i> fields in the current deck, if they exist.</div> <div><i>Pinyin</i> and <i>Transcription</i> will be filled if empty. Otherwise, their colorization and accentuation will be refreshed as needed.</div> <div>Please back-up your Anki deck first!</div> <div><b>Continue?</b></div> ''' if not askUser(prompt): return query_str = 'deck:current' d_scanned = 0 d_has_fields = 0 d_added_pinyin = 0 d_updated = 0 notes = Finder(mw.col).findNotes(query_str) mw.progress.start(immediate=True, min=0, max=len(notes)) for noteId in notes: d_scanned += 1 note = mw.col.getNote(noteId) note_dict = dict(note) _hf_t = has_field(config['fields']['transcription'], note_dict) _hf_py = has_field(config['fields']['pinyin'], note_dict) _hf_pytw = has_field(config['fields']['pinyinTaiwan'], note_dict) _hf_cant = has_field(config['fields']['cantonese'], note_dict) _hf_bpmf = has_field(config['fields']['bopomofo'], note_dict) if (_hf_t or _hf_py or _hf_pytw or _hf_cant or _hf_bpmf) and has_field( config['fields']['hanzi'], note_dict): d_has_fields += 1 msg = ''' <b>Processing:</b> %(hanzi)s<br> <b>Filled pinyin:</b> %(pinyin)d notes<br> <b>Updated: </b>%(updated)d fields''' % { 'hanzi': sanitize_hanzi(note_dict), 'pinyin': d_added_pinyin, 'updated': d_updated, } mw.progress.update(label=msg, value=d_scanned) hanzi = get_first(config['fields']['hanzi'], note_dict) results = 0 if _hf_t: results += fill_transcription(hanzi, note_dict) if _hf_py: results += bulk_fill_pinyin(hanzi, note_dict) if _hf_pytw: results += fill_taiwan_pinyin(hanzi, note_dict) if _hf_cant: results += fill_cantonese(hanzi, note_dict) if _hf_bpmf: results += fill_bopomofo(hanzi, note_dict) if results != 0: d_added_pinyin += 1 fill_color(hanzi, note_dict) fill_all_rubies(hanzi, note_dict) def write_back(fields): num_updated = 0 for f in fields: if f in note_dict and note_dict[f] != note[f]: note[f] = note_dict[f] num_updated += 1 return num_updated d_updated += write_back(config['fields']['transcription']) d_updated += write_back(config['fields']['pinyin']) d_updated += write_back(config['fields']['pinyinTaiwan']) d_updated += write_back(config['fields']['cantonese']) d_updated += write_back(config['fields']['bopomofo']) d_updated += write_back(config['fields']['color']) d_updated += write_back(config['fields']['colorPinyin']) d_updated += write_back(config['fields']['colorPinyinTaiwan']) d_updated += write_back(config['fields']['colorCantonese']) d_updated += write_back(config['fields']['colorBopomofo']) d_updated += write_back(config['fields']['ruby']) d_updated += write_back(config['fields']['rubyPinyin']) d_updated += write_back(config['fields']['rubyPinyinTaiwan']) d_updated += write_back(config['fields']['rubyCantonese']) d_updated += write_back(config['fields']['rubyBopomofo']) note.flush() mw.progress.finish() msg = ''' <b>Processing:</b> %(hanzi)s<br> <b>Filled pinyin:</b> %(pinyin)d notes<br> <b>Updated: </b>%(updated)d fields''' % { 'hanzi': sanitize_hanzi(note_dict), 'pinyin': d_added_pinyin, 'updated': d_updated, } showInfo(msg)
def bulk_fill_usage(): prompt = PROMPT_TEMPLATE.format(field_names='<i>usage</i>', extra_info='') progress_msg_template = ''' <b>Processing:</b> %(hanzi)s<br> <b>Chinese notes:</b> %(has_fields)d<br> <b>Cards with Sentences added:</b> %(filled)d<br> <b>Cards with no Sentences added:</b> %(not_filled)d<br> <b>Failed:</b> %(failed)d''' fields = config.get_fields(['usage']) if not askUser(prompt): return n_processed = 0 n_updated = 0 n_failed = 0 n_notfilled = 0 failed_hanzi = [] note_ids = Finder(mw.col).findNotes('deck:current') mw.progress.start(immediate=True, min=0, max=len(note_ids)) for i, note_id in enumerate(note_ids): note = mw.col.getNote(note_id) copy = dict(note) hanzi = get_hanzi(copy) if has_any_field(copy, fields) and hanzi: n_processed += 1 try: if all_fields_empty(copy, fields): result = fill_usage(hanzi, copy) if result: n_updated += 1 else: n_notfilled += 1 except: n_failed += 1 failed_hanzi.append(hanzi) msg = progress_msg_template % { 'hanzi': hanzi, 'has_fields': n_processed, 'filled': n_updated, 'not_filled': n_notfilled, 'failed': n_failed, } mw.progress.update(label=msg, value=i) save_note(note, copy) msg = ''' <b>Usage Additions Complete</b><br> <b>Chinese Notes:</b> %(has_fields)d<br> <b>Usage Fields Filled:</b> %(filled)d<br> <b>Usage Fields Not Filled:</b> %(not_filled)d<br> <b>Failed:</b> %(failed)d''' % { 'has_fields': n_processed, 'filled': n_updated, 'not_filled': n_notfilled, 'failed': n_failed, } if n_failed > 0: failed_msg = ( 'Usages may not be available in the database\'s data set. ' 'Custom data can be added to the english_usage column in the' 'chinese.db database.\n' 'The following notes failed: \n\n' + ', '.join(failed_hanzi)) showText(failed_msg, copyBtn=True) mw.progress.finish() showInfo(msg)
def fill_pinyin(collection, view_key): if view_key == "deckBrowser": return showInfo(u"Please first select one of your decks.") if not (askUser( "<div>This will update the <i>Pinyin</i> (or <i>Transcription</i>), <i>Color</i> and <i>Ruby</i> fields in the current deck, if they exist.</div>\n\n<div><i>Pinyin</i> and <i>Transcription</i> will be filled if empty. Otherwise, their colorization and accentuation will be refreshed as needed.</div>\n\n<div>Please back-up your Anki deck first!</div>\n\n<div><b>Continue?</b></div>" )): return False query_str = "deck:current" d_scanned = 0 d_has_fields = 0 d_failed = 0 d_added_pinyin = 0 d_updated = 0 notes = Finder(collection).findNotes(query_str) mw.progress.start(immediate=True, min=0, max=len(notes)) for noteId in notes: d_scanned += 1 note = collection.getNote(noteId) note_dict = dict(note) # edit_function routines require a dict _hf_t = has_field(Transcription_fields, note_dict) _hf_py = has_field(Pinyin_fields, note_dict) _hf_pytw = has_field(PinyinTW_fields, note_dict) _hf_cant = has_field(Cantonese_fields, note_dict) _hf_bpmf = has_field(Bopomofo_fields, note_dict) if (_hf_t or _hf_py or _hf_pytw or _hf_cant or _hf_bpmf) and has_field( Hanzi_fields, note_dict): d_has_fields += 1 msg_string = "<b>Processing:</b> %(hanzi)s<br><b>Filled pinyin:</b> %(pinyin)d notes<br><b>Updated: </b>%(updated)d fields" % { "hanzi": cleanup(no_html(get_any(Hanzi_fields, note_dict))), "pinyin": d_added_pinyin, "updated": d_updated } mw.progress.update(label=msg_string, value=d_scanned) hanzi = get_any(Hanzi_fields, note_dict) results = 0 if _hf_t: results += update_Transcription_fields(hanzi, note_dict) if _hf_py: results += update_Pinyin_fields(hanzi, note_dict) if _hf_pytw: results += update_PinyinTW_fields(hanzi, note_dict) if _hf_cant: results += update_Cantonese_fields(hanzi, note_dict) if _hf_bpmf: results += update_Bopomofo_fields(hanzi, note_dict) if results != 0: d_added_pinyin += 1 #Always overwrite, as in the default edit_behavior update_all_Color_fields(hanzi, note_dict) #Update ruby field update_all_Ruby_fields(hanzi, note_dict) def write_back(fields): num_updated = 0 for f in fields: if note_dict.has_key(f) and note_dict[ f] is not None and note_dict[f] <> note[f]: note[f] = note_dict[f] num_updated += 1 return num_updated # write back to note from dict and flush d_updated += write_back(Transcription_fields) d_updated += write_back(Pinyin_fields) d_updated += write_back(PinyinTW_fields) d_updated += write_back(Cantonese_fields) d_updated += write_back(Bopomofo_fields) d_updated += write_back(Color_fields) d_updated += write_back(ColorPY_fields) d_updated += write_back(ColorPYTW_fields) d_updated += write_back(ColorCANT_fields) d_updated += write_back(ColorBPMF_fields) d_updated += write_back(Ruby_fields) d_updated += write_back(RubyPY_fields) d_updated += write_back(RubyPYTW_fields) d_updated += write_back(RubyCANT_fields) d_updated += write_back(RubyBPMF_fields) note.flush() mw.progress.finish() msg_string = "<b>Processing:</b> %(hanzi)s<br><b>Filled pinyin:</b> %(pinyin)d notes<br><b>Updated: </b>%(updated)d fields" % { "hanzi": cleanup(no_html(get_any(Hanzi_fields, note_dict))), "pinyin": d_added_pinyin, "updated": d_updated } showInfo(msg_string)
def bulk_fill_sound(): prompt = PROMPT_TEMPLATE.format( field_names='<i>Sound</i>', extra_info=( '<div>There will be a 5 second delay between each sound request,' ' so this may take a while.</div>'), ) if not askUser(prompt): return d_has_fields = 0 d_already_had_sound = 0 d_success = 0 d_failed = 0 note_ids = Finder(mw.col).findNotes('deck:current') mw.progress.start(immediate=True, min=0, max=len(note_ids)) for i, nid in enumerate(note_ids): orig = mw.col.getNote(nid) copy = dict(orig) if has_any_field(copy, ['sound', 'mandarinSound', 'cantoneseSound']) and has_field( config['fields']['hanzi'], copy): d_has_fields += 1 hanzi = get_first(config['fields']['hanzi'], copy) if all_fields_empty(copy, ['sound', 'mandarinSound', 'cantoneseSound']): msg = ''' <b>Processing:</b> %(hanzi)s<br> <b>Updated:</b> %(d_success)d notes<br> <b>Failed:</b> %(d_failed)d notes''' % { 'hanzi': get_hanzi(copy), 'd_success': d_success, 'd_failed': d_failed, } mw.progress.update(label=msg, value=i) s, f = fill_sound(hanzi, copy) d_success += s d_failed += f save_note(orig, copy) sleep(5) else: d_already_had_sound += 1 mw.progress.finish() msg = ''' %(d_success)d new pronunciations downloaded %(d_failed)d downloads failed %(have)d/%(d_has_fields)d notes now have pronunciation''' % { 'd_success': d_success, 'd_failed': d_failed, 'have': d_already_had_sound + d_success, 'd_has_fields': d_has_fields, } if d_failed > 0: msg += ('TTS is taken from an online source. ' 'It may not always be fully responsive. ' 'Please check your network connexion, or retry later.') showInfo(msg)
def bulk_fill_defs(): prompt = ''' <div>This will update the <i>Meaning</i>, <i>Classifier</i>, and <i>Also Written</i> fields in the current deck, if they exist and are empty.</div> <div>Please back-up your Anki deck first!</div> <div><b>Continue?</b></div> ''' if not askUser(prompt): return query_str = 'deck:current' d_scanned = 0 d_has_fields = 0 d_success = 0 d_failed = 0 failed_hanzi = [] notes = Finder(mw.col).findNotes(query_str) mw.progress.start(immediate=True, min=0, max=len(notes)) for noteId in notes: d_scanned += 1 note = mw.col.getNote(noteId) note_dict = dict(note) _hf_m = has_field(config['fields']['meaning'], note_dict) _hf_e = has_field(config['fields']['english'], note_dict) _hf_g = has_field(config['fields']['german'], note_dict) _hf_f = has_field(config['fields']['french'], note_dict) if (_hf_m or _hf_e or _hf_g or _hf_f) and has_field( config['fields']['hanzi'], note_dict): d_has_fields += 1 msg = ''' <b>Processing:</b> %(hanzi)s<br> <b>Chinese notes:</b> %(has_fields)d<br> <b>Translated:</b> %(filled)d<br> <b>Failed:</b> %(failed)d''' % { 'hanzi': sanitize_hanzi(note_dict), 'has_fields': d_has_fields, 'filled': d_success, 'failed': d_failed, } mw.progress.update(label=msg, value=d_scanned) hanzi = get_first(config['fields']['hanzi'], note_dict) empty = len(get_first(config['fields']['meaning'], note_dict)) empty += len(get_first(config['fields']['english'], note_dict)) empty += len(get_first(config['fields']['german'], note_dict)) empty += len(get_first(config['fields']['french'], note_dict)) if not empty: result = fill_all_defs(hanzi, note_dict) if result: d_success += 1 else: d_failed += 1 if d_failed < 20: failed_hanzi += [sanitize_hanzi(note_dict)] def write_back(fields): for f in fields: if f in note_dict and note_dict[f] != note[f]: note[f] = note_dict[f] write_back(config['fields']['meaning']) write_back(config['fields']['english']) write_back(config['fields']['german']) write_back(config['fields']['french']) write_back(config['fields']['classifier']) write_back(config['fields']['alternative']) note.flush() msg = ''' <b>Translation complete</b><br> <b>Chinese notes:</b> %(has_fields)d<br> <b>Translated:</b> %(filled)d<br> <b>Failed:</b> %(failed)d''' % { 'has_fields': d_has_fields, 'filled': d_success, 'failed': d_failed, } if d_failed > 0: msg += ( '<div>Translation failures may come either from connection issues ' "(if you're using an online translation service), or because some " 'words are not it the dictionary (for local dictionaries).</div>' '<div>The following notes failed: ' + ', '.join(failed_hanzi) + '</div>') mw.progress.finish() showInfo(msg)