def test_and_dehashilate():
    if not test_names():
        showInfo('No hashes found in cards. Have a nice day.')
        return
    if not askUser('Go ahead?\nThis cannot be undone!\nUse at your own risk!\n'
                   'Backup your collection before continuing!'):
        return
    if not askUser('Click on "No".\n'
                   'Clicking on "Yes" will probably mess up your collection.\n'
                   'You will have to fix it yourself!',
                   defaultno=True):
        return
    dehashilate()
Exemple #2
0
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()
Exemple #3
0
    def addNote(self, note):
        note.model()["did"] = self.deckChooser.selectedId()
        ret = note.dupeOrEmpty()
        if ret == 1:
            showWarning(_("The first field is empty."), help="AddItems#AddError")
            return
        if "{{cloze:" in note.model()["tmpls"][0]["qfmt"]:
            if not self.mw.col.models._availClozeOrds(note.model(), note.joinedFields(), False):
                if not askUser(
                    _("You have a cloze deletion note type " "but have not made any cloze deletions. Proceed?")
                ):
                    return
        cards = self.mw.col.addNote(note)
        if not cards:
            showWarning(
                _(
                    """\
The input you have provided would make an empty \
question on all cards."""
                ),
                help="AddItems",
            )
            return
        self.addHistory(note)
        self.mw.requireReset()
        return note
def onFieldToTags(self, _):
    """Main function"""
    nids = self.selectedNotes()
    count = len(nids)
    if not nids:
        tooltip("Please select some cards.")
        return
    fields = sorted(find.fieldNames(self.col, downcase=False))
    if not fields:
        tooltip("No fields found."
            "Something might be wrong with your collection")
        return
    
    field = getField(self, fields)

    if not field:
        return

    q = ("Are you sure you want to convert the <b>'{}'</b> field "
        "to tags in <b>{}</b> selected notes?".format(field, count))
    ret = askUser(q, parent=self, title="Please confirm your choice")
    if not ret:
        return

    self.mw.checkpoint("Find and Replace")
    self.mw.progress.start()
    self.model.beginReset()

    edited = self.fieldToTags(nids, field)
    
    self.model.endReset()
    self.mw.progress.finish()
    tooltip("{} out of {} notes updated.".format(edited, count))
Exemple #5
0
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()
Exemple #6
0
 def accept(self):
     self.exporter.includeSched = (
         self.frm.includeSched.isChecked())
     self.exporter.includeMedia = (
         self.frm.includeMedia.isChecked())
     self.exporter.includeTags = (
         self.frm.includeTags.isChecked())
     if not self.frm.deck.currentIndex():
         self.exporter.did = None
     else:
         name = self.decks[self.frm.deck.currentIndex()]
         self.exporter.did = self.col.decks.id(name)
     if (self.isApkg and self.exporter.includeSched and not
         self.exporter.did):
         verbatim = True
         # it's a verbatim apkg export, so place on desktop instead of
         # choosing file
         file = os.path.join(QDesktopServices.storageLocation(
             QDesktopServices.DesktopLocation), "collection.apkg")
         if os.path.exists(file):
             if not askUser(
                 _("%s already exists on your desktop. Overwrite it?")%
                 "collection.apkg"):
                 return
     else:
         verbatim = False
         # Get deck name and remove invalid filename characters
         deck_name = self.decks[self.frm.deck.currentIndex()]
         deck_name = re.sub('[\\\\/?<>:*|"^]', '_', deck_name)
         filename = os.path.join(aqt.mw.pm.base,
                                 u'{0}{1}'.format(deck_name, self.exporter.ext))
         while 1:
             file = getSaveFile(self, _("Export"), "export",
                                self.exporter.key, self.exporter.ext,
                                fname=filename)
             if not file:
                 return
             if checkInvalidFilename(os.path.basename(file), dirsep=False):
                 continue
             break
     self.hide()
     if file:
         self.mw.progress.start(immediate=True)
         try:
             f = open(file, "wb")
             f.close()
         except (OSError, IOError), e:
             showWarning(_("Couldn't save file: %s") % unicode(e))
         else:
             os.unlink(file)
             self.exporter.exportInto(file)
             if verbatim:
                 msg = _("A file called collection.apkg was saved on your desktop.")
                 period = 5000
             else:
                 period = 3000
                 msg = ngettext("%d card exported.", "%d cards exported.", \
                             self.exporter.count) % self.exporter.count
             tooltip(msg, period=period)
         finally:
Exemple #7
0
    def onRemoveTab(self, idx):
        if not askUser(_("Remove template and all its cards?")):
            return
        if not self.mm.remTemplate(self.model, self.cards[idx].template()):
            return showWarning(_("""\
Removing this card would cause one or more notes to be deleted. \
Please create a new card first."""))
        self.redraw()
Exemple #8
0
def display_next_tip():
    (tip, link) = chinese_support_config.get_next_tip()
    if tip:
        if link:
            if askUser(tip):
                openLink(link)
        else:
            showInfo(tip)
Exemple #9
0
    def _updateSchedVer(self, wantNew):
        haveNew = self.mw.col.schedVer() == 2

        # nothing to do?
        if haveNew == wantNew:
            return

        if haveNew and not wantNew:
            if not askUser(_("This will reset any cards in learning, clear filtered decks, and change the scheduler version. Proceed?")):
                return
            self.mw.col.changeSchedulerVer(1)
            return

        if not askUser(_("The experimental scheduler could cause incorrect scheduling. Please ensure you have read the documentation first. Proceed?")):
            return

        self.mw.col.changeSchedulerVer(2)
Exemple #10
0
 def setChildren(self):
     if not askUser(_("Set all decks below %s to this option group?") % self.deck["name"]):
         return
     for did in self.childDids:
         deck = self.mw.col.decks.get(did)
         deck["conf"] = self.deck["conf"]
         self.mw.col.decks.save(deck)
     tooltip(ngettext("%d deck updated.", "%d decks updated.", len(self.childDids)) % len(self.childDids))
Exemple #11
0
 def setChildren(self):
     if not askUser(
         _("Set all decks below %s to this option group?") %
         self.deck['name']):
         return
     for did in self.childDids:
         deck = self.mw.col.decks.get(did)
         deck['conf'] = self.deck['conf']
         self.mw.col.decks.save(deck)
     tooltip(_("%d decks updated.") % len(self.childDids))
Exemple #12
0
    def onRemoveTab(self, idx):
        if len(self.model['tmpls']) < 2:
            return showInfo(_("At least one card is required."))
        if not askUser(_("Remove all cards of this type?")):
            return
        if not self.mm.remTemplate(self.model, self.cards[idx].template()):
            return showWarning(_("""\
Removing this card type would cause one or more notes to be deleted. \
Please create a new card type first."""))
        self.redraw()
Exemple #13
0
    def onFullSync(self):
        if not askUser(_("""\
If you proceed, you will need to choose between a full download or full \
upload, overwriting any changes either here or on AnkiWeb. Proceed?""")):
            return
        self.hideSchemaMsg = True
        self.col.modSchema()
        self.col.setMod()
        self.hideSchemaMsg = False
        self.onSync()
Exemple #14
0
 def deleteUnused(self, unused, diag):
     if not askUser(
         _("Delete unused media? This operation can not be undone.")):
         return
     mdir = self.col.media.dir()
     for f in unused:
         path = os.path.join(mdir, f)
         os.unlink(path)
     tooltip(_("Deleted."))
     diag.close()
Exemple #15
0
 def deleteUnused(self, unused, diag):
     if not askUser(
         _("Delete unused media?")):
         return
     mdir = self.col.media.dir()
     for f in unused:
         path = os.path.join(mdir, f)
         send2trash(path)
     tooltip(_("Deleted."))
     diag.close()
Exemple #16
0
 def onDelete(self):
     selected = self.selectedAddons()
     if not selected:
         return
     if not askUser(_("Delete the %(num)d selected add-ons?") %
                            dict(num=len(selected))):
         return
     for dir in selected:
         self.mgr.deleteAddon(dir)
     self.redrawAddons()
Exemple #17
0
    def accept(self):
        if not self.saveConf():
            return
        if not self.mw.col.sched.rebuildDyn():
            if askUser(_("""\
The provided search did not match any cards. Would you like to revise \
it?""")):
                return
        self.mw.reset()
        QDialog.accept(self)
Exemple #18
0
    def onOpenBackup(self):
        if not askUser(_("""\
Replace your collection with an earlier backup?"""),
                       msgfunc=QMessageBox.warning,
                       defaultno=True):
            return
        def doOpen(path):
            self._openBackup(path)
        getFile(self.profileDiag, _("Revert to backup"),
                cb=doOpen, filter="*.colpkg", dir=self.pm.backupFolder())
Exemple #19
0
    def _delete(self, did):
        if str(did) == '1':
            return showWarning(_("The default deck can't be deleted."))
        self.mw.checkpoint(_("Delete Deck"))
        deck = self.mw.col.decks.get(did)
        if deck['dyn'] or askUser(_("""\
Are you sure you wish to delete all of the cards in %s?""")%deck['name']):
            self.mw.progress.start(immediate=True)
            self.mw.col.decks.rem(did, True)
            self.mw.progress.finish()
            self.show()
def on_fix_button():
    if not askUser(question, defaultno=True):
        return
    media_dir = mw.col.media.dir()
    files = get_image_occlusion_files(media_dir)
    fixed = fix_files(files)
    showInfo("Done. {}/{} files needed fixing."
        "<br><br>Please consider upgrading to "
        "<a href='https://ankiweb.net/shared/info/1111933094'>"
        "Image Occlusion Enhanced</a> to avoid issues like these "
        "in the future".format(fixed, len(files)))
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] <> 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)
Exemple #22
0
 def deleteTemplate(self):
     if len (self.model.templates) < 2:
         ui.utils.showWarning(
             _("Please add a new template first."),
             parent=self)
         return
     if not askUser(
         _("Delete this template and all cards that use it?")):
         return
     self.model.delTemplate(self.template)
     self.updateTemplates()
Exemple #23
0
 def onDelete(self):
     if len(self.model["flds"]) < 3:
         return showWarning(_("Notes require at least two fields."))
     if not askUser(_("Delete field?")):
         return
     f = self.model["flds"][self.form.fieldList.currentRow()]
     self.mw.progress.start()
     self.mm.remField(self.model, f)
     self.mw.progress.finish()
     self.fillFields()
     self.form.fieldList.setCurrentRow(0)
	def getFile(self, pathName):
		if os.path.exists(pathName):
			ok = askUser(_("The file \n%s \nalready exists. Overwrite it?") % pathName)
			if not ok:
				return None
		try:
			file = open(pathName, "w")
		except:
			file = None
			showWarning(_("Could not open the file \n%s. \n") % pathName)
		return file
Exemple #25
0
    def onRemProfile(self):
        profs = self.pm.profiles()
        if len(profs) < 2:
            return showWarning(_("There must be at least one profile."))
        # sure?
        if not askUser(_("""\
All cards, notes, and media for this profile will be deleted. \
Are you sure?"""), msgfunc=QMessageBox.warning, defaultno=True):
            return
        self.pm.remove(self.pm.name)
        self.refreshProfilesList()
def copy_all():
    # Find the models that have the right name and fields; faster than
    # checking every note
    if not askUser("Fill with kanji diagrams references?"):
        return
    models = [m for m in mw.col.models.all() if model_is_correct_type(m)]
    # Find the notes in those models and give them kanji
    for model in models:
        for nid in mw.col.models.nids(model):
            add_kanji(mw.col.getNote(nid))
    tooltip("Done copying colorized kanji diagrams!")
Exemple #27
0
 def onDelete(self):
     if len(self.models) < 2:
         showInfo(_("Please add another model first."),
                  parent=self)
         return
     if not askUser(
         _("Delete this model and all its cards?"),
         parent=self):
         return
     self.deck.delModel(self.model.id)
     self.model = None
     self.updateModelsList()
Exemple #28
0
    def onSchemaMod(self, arg):
        # if triggered in sync, make sure we don't use the gui
        if not self.inMainThread():
            return True
        # if from the full sync menu, ignore
        if self.hideSchemaMsg:
            return True
        return askUser(_("""\
The requested change will require a full upload of the database when \
you next synchronize your collection. If you have reviews or other changes \
waiting on another device that haven't been synchronized here yet, they \
will be lost. Continue?"""))
Exemple #29
0
 def onDelete(self):
     if len(self.models) < 2:
         showInfo(_("Please add another note type first."),
                  parent=self)
         return
     if not askUser(
         _("Delete this note type and all its cards?"),
         parent=self):
         return
     self.mm.rem(self.model)
     self.model = None
     self.updateModelsList()
def regenerate_all():
    # Find the models that have the right name and fields; faster than
    # checking every note
    if not askUser("Do you want to regenerate all kanji diagrams? "
                   'This may take some time and will overwrite the '
                   'destination Diagram fields.'):
        return
    models = [m for m in mw.col.models.all() if modelIsCorrectType(m)]
    # Find the notes in those models and give them kanji
    for model in models:
        for nid in mw.col.models.nids(model):
            addKanji(mw.col.getNote(nid))
    showInfo("Done regenerating colorized kanji diagrams!")
def reset_threshold():
    if askUser("Really reset threshold?"):
        mw.pm.profile["reset_ease_mod__last_run"] = 0
        tooltip("""Reset to zero.""")
Exemple #32
0
 def reject(self) -> None:
     if self.change_tracker.changed():
         if not askUser("Discard changes?"):
             return
     self.cleanup()
     return QDialog.reject(self)
Exemple #33
0
 def reject(self) -> None:
     if self.change_tracker.changed():
         if not askUser(tr(TR.CARD_TEMPLATES_DISCARD_CHANGES)):
             return
     self.cleanup()
     return QDialog.reject(self)
Exemple #34
0
def sync_duolingo():
    model = get_duolingo_model(mw)

    if not model:
        showWarning("Could not find or create Duolingo Sync note type.")
        return

    note_ids = mw.col.findNotes("tag:duolingo_sync")
    notes = mw.col.db.list("select flds from notes where id in {}".format(
        ids2str(note_ids)))
    gids_to_notes = {splitFields(note)[0]: note for note in notes}
    try:
        username, password = duolingo_dialog(mw)
    except TypeError:
        return

    if username and password:
        try:
            mw.progress.start(immediate=True, label="Logging in...")

            login_thread = DuolingoThread(target=Duolingo,
                                          args=(username, password))
            login_thread.start()
            while login_thread.is_alive():
                time.sleep(0.02)
                mw.progress.update()
            lingo = login_thread.join()

            vocabulary_thread = DuolingoThread(target=lingo.get_vocabulary)
            vocabulary_thread.start()
            mw.progress.update(label="Retrieving vocabulary...")
            while vocabulary_thread.is_alive():
                time.sleep(0.02)
                mw.progress.update()
            vocabulary_response = vocabulary_thread.join()

        except LoginFailedException:
            showWarning("""
                <p>Logging in to Duolingo failed. Please check your Duolingo credentials.</p>
                
                <p>Having trouble logging in? You must use your <i>Duolingo</i> username and password.
                You <i>can't</i> use your Google or Facebook credentials, even if that's what you use to
                sign in to Duolingo.</p>
                
                <p>You can find your Duolingo username at
                <a href="https://www.duolingo.com/settings">https://www.duolingo.com/settings</a> and you
                can create or set your Duolingo password at
                <a href="https://www.duolingo.com/settings/password">https://www.duolingo.com/settings/password</a>.</p>
                """)
            return
        except requests.exceptions.ConnectionError:
            showWarning(
                "Could not connect to Duolingo. Please check your internet connection."
            )
            return
        finally:
            mw.progress.finish()

        language_string = vocabulary_response["language_string"]
        vocabs = vocabulary_response["vocab_overview"]

        did = mw.col.decks.id("Default")
        mw.col.decks.select(did)

        deck = mw.col.decks.get(did)
        deck["mid"] = model["id"]
        mw.col.decks.save(deck)

        words_to_add = [
            vocab for vocab in vocabs if vocab["id"] not in gids_to_notes
        ]

        if not words_to_add:
            showInfo(
                "Successfully logged in to Duolingo, but no new words found in {} language."
                .format(language_string))
        elif askUser("Add {} notes from {} language?".format(
                len(words_to_add), language_string)):

            word_chunks = [
                words_to_add[x:x + 50] for x in range(0, len(words_to_add), 50)
            ]

            mw.progress.start(
                immediate=True,
                label="Importing from Duolingo...",
                max=len(words_to_add),
            )
            notes_added = 0
            for word_chunk in word_chunks:
                translations = lingo.get_translations(
                    [vocab["word_string"] for vocab in word_chunk])

                for vocab in word_chunk:

                    n = mw.col.newNote()

                    # Update the underlying dictionary to accept more arguments for more customisable cards
                    n._fmap = defaultdict(str, n._fmap)

                    n["Gid"] = vocab["id"]
                    n["Gender"] = vocab["gender"] if vocab["gender"] else ""
                    n["Source"] = "; ".join(translations[vocab["word_string"]])
                    n["Target"] = vocab["word_string"]
                    n["Pronunciation"] = vocab["normalized_string"].strip()
                    n["Target Language"] = language_string
                    n.addTag(language_string)
                    n.addTag("duolingo_sync")

                    if vocab["pos"]:
                        n.addTag(vocab["pos"])

                    if vocab["skill"]:
                        n.addTag(vocab["skill"].replace(" ", "-"))

                    mw.col.addNote(n)
                    notes_added += 1

                    mw.progress.update(value=notes_added)

            showInfo("{} notes added".format(notes_added))
            mw.moveToState("deckBrowser")

            mw.progress.finish()
Exemple #35
0
    def onSchemaMod(self, arg):
        return askUser(_("""\
The requested change will require a full upload of the database when \
you next synchronize your collection. If you have reviews or other changes \
waiting on another device that haven't been synchronized here yet, they \
will be lost. Continue?"""))
Exemple #36
0
 def canClose(self):
     has_data = self.form.pteText.toPlainText() or self.form.pteNotes.toPlainText()
     if (not has_data or askUser(_("Close and lose current input?"))):
         return True
     return False
Exemple #37
0
    def reject(self):
        if self.change_tracker.changed():
            if not askUser("Discard changes?"):
                return

        QDialog.reject(self)
def _forExistingCards(prompt, funcForExistingCards):
    if not askUser(_(prompt)):
        return
    cloze = mw.col.models.byName("Cloze")
    nids = mw.col.models.nids(cloze)
    funcForExistingCards(nids)
Exemple #39
0
 def _onTreeFavDelete(self, item):
     for idx in self.selectedIndexes():
         itm = idx.internalPointer()
         if mw.col.conf['savedFilters'].get(itm.favname) and \
         askUser(_("Remove %s from your saved searches?") % itm.favname):
             del mw.col.conf['savedFilters'][itm.favname]
Exemple #40
0
    def on_import(self):
        dict_nm = ''
        if self.builder:
            try:
                mdx_dict = readmdict.MDX(self.mdx, only_header=True)
                self.builder._encoding = mdx_dict._encoding
            except MemoryError:
                showInfo(_trans("MDX MEMORY ERROR"),
                         self,
                         type="warning",
                         title=_trans("ANKINDLE"))
                return
            except TypeError:
                showInfo(_trans("MDX TYPE ERROR"),
                         self,
                         type="warning",
                         title=_trans("ANKINDLE"))
                return
            dict_nm = os.path.splitext(os.path.basename(mdx_dict._fname))[0]

        else:
            ret = askUser(_trans("ALERT FOR MISSING MDX"),
                          self,
                          defaultno=False,
                          title=_trans("ANKINDLE"))
            if not ret:
                return

        total_new = 0
        total_dup = 0
        for i, _ in enumerate(self.yield_one_word()):
            (id, word, stem, lang, added_tm, usage, title, authors,
             category) = _
            # region save new cards
            try:
                note = notes.Note(mw.col,
                                  mw.col.models.models[str(self.model['id'])])
            except KeyError:
                continue
            note.model()['did'] = self.deck['id']

            def update_note(_note):

                qry_word = stem if stem else word if word else ''
                _usage = self.adapt_to_anki(
                    usage.replace(word, u"<b>%s</b>" % word)) if usage else ''

                try:
                    _id_in_field = re.sub("[^0-9a-zA-Z]", "",
                                          qry_word + usage).strip().upper()
                except TypeError:
                    return False

                _note.fields[_note._fieldOrd(
                    'id')] = _id_in_field if _id_in_field else ''
                _note.fields[_note._fieldOrd('word')] = word if word else ''
                _note.fields[_note._fieldOrd('stem')] = stem if stem else ''
                _note.fields[_note._fieldOrd('lang')] = lang if lang else ''
                _note.fields[_note._fieldOrd(
                    'creation_tm')] = added_tm if added_tm else ''
                _note.fields[_note._fieldOrd(
                    'usage')] = _usage if _usage else ''
                _note.fields[_note._fieldOrd('title')] = title if title else ''
                _note.fields[_note._fieldOrd(
                    'authors')] = authors if authors else ''
                _note.fields[_note._fieldOrd('mdx_dict')] = self.get_html(
                    qry_word)

                try:
                    _note.fields[_note._fieldOrd('mdx_name')] = dict_nm
                except KeyError:
                    pass
                return True

            if update_note(note):
                if note.dupeOrEmpty() != 2:
                    mw.col.addNote(note)
                    total_new += 1
                else:
                    total_dup += 1
                mw.col.autosave()
                # endregion

        # copy css files
        if self.mdx:
            mdx_dict_dir = os.path.split(self.mdx)[0]
            include_mdx_extras = ['.CSS', '.JS']
            for root, dirs, files in os.walk(mdx_dict_dir):
                for _mfile in [
                        css for css in files if os.path.splitext(css)
                    [1].strip().upper() in include_mdx_extras
                ]:
                    _nfile = _mfile
                    if _mfile in self.missed_css:
                        _nfile = "_" + _mfile
                    shutil.copy(os.path.join(root, _mfile), _nfile)

        mw.moveToState("deckBrowser")
        showText(
            _trans("CREATED AND DUPLICATES") % (total_new, total_dup), self)
Exemple #41
0
def 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 += 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(hanzi, note_dict)

            if results != 0:
                d_added_pinyin += 1

            update_all_Color_fields(hanzi, note_dict)
            update_all_Ruby_fields(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)
Exemple #42
0
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'''

    fields = config.get_fields(['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, fields) and hanzi:
            n_targets += 1

            if all_fields_empty(copy, fields):
                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)
Exemple #43
0
 def javaScriptConfirm(self, frame: Any, text: str) -> bool:
     return askUser(text)
Exemple #44
0
 def onRem(self, path):
     if not askUser(_("Delete %s?") % os.path.basename(path)):
         return
     os.unlink(path)
     self.rebuildAddonsMenu()
     showInfo(_("Deleted. Please restart Anki."))
Exemple #45
0
 def _onTreeFavDelete(self, item):
     act = mw.col.conf['savedFilters'].get(item.favname)
     if not act: return
     if askUser(_("Remove %s from your saved searches?") % item.favname):
         del mw.col.conf['savedFilters'][item.favname]
Exemple #46
0
 def reject(self) -> None:
     if self.change_tracker.changed():
         if not askUser(tr.card_templates_discard_changes()):
             return
     self.cleanup()
     return QDialog.reject(self)
Exemple #47
0
 def afterSave():
     ok = (self.editor.fieldsAreBlank() or
             askUser(_("Close and lose current input?")))
     if ok:
         onOk()
Exemple #48
0
 def afterSave():
     ok = self.editor.fieldsAreBlank(self.previousNote) or askUser(
         _("Close and lose current input?"), defaultno=True)
     if ok:
         onOk()
Exemple #49
0
 def canClose(self):
     if (self.forceClose or self.editor.fieldsAreBlank()
             or askUser(_("Close and lose current input?"))):
         return True
     return False
Exemple #50
0
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["fields"]["sound"], note_dict) and has_field(
                config["fields"]["hangul"], note_dict):
            d_has_fields += 1

            hangul = get_any(config["fields"]["hangul"], note_dict)

            if get_any(config["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["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["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)
Exemple #51
0
 def afterSave() -> None:
     ok = self.editor.fieldsAreBlank(self._last_added_note) or askUser(
         tr.adding_close_and_lose_current_input(), defaultno=True)
     if ok:
         onOk()
Exemple #52
0
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] <> 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)
Exemple #53
0
 def afterSave() -> None:
     ok = self.editor.fieldsAreBlank(self.previousNote) or askUser(
         tr(TR.ADDING_CLOSE_AND_LOSE_CURRENT_INPUT), defaultno=True)
     if ok:
         onOk()
Exemple #54
0
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["fields"]["meaning"], note_dict) and has_field(
                config["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["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["fields"]["hangul"], note_dict)
            empty = len(get_any(config["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["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["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)
Exemple #55
0
    def accept(self):
        """
        If user accept the settings (commit the settings)
        """
        # validate directory
        if not os.path.exists(self.dirPath):
            showInfo("Directory not found.\n"
                     "The resource you're looking for might have been removed, "
                     "had its name changed, or is temporary unavailable. \n"
                     "Please select another directory.")
            self.browse_dir()
            return
        # validate provenance
        try:
            # Test if a string is filename-ok by creating a file
            with open(self.prov, 'w'):
                pass
            os.remove(self.prov)
        except (FileNotFoundError, OSError):
            _prov = 'Unknown'
            if askUser("""
Provenance will be used to rename files, so it cannot be empty or contain any of the following characters:\n
/\\:*?"<>|\n
If you choose 'Yes', you'll return to edit the provenance.\n
If you choose 'No', provenance will be '%s'.
""" % _prov):
                self.form.provInput.setFocus()
                self.form.provInput.selectAll()
                return
            else:
                self.prov = _prov
        # validate deck
        if not self.deckName:
            self.deckName = mw.col.decks.current()['name']
        # validate model
        if not self.modelName:
            self.modelName = mw.col.models.current()['name']
        # get field map
        self.fieldMap = {}
        for row in range(len(mw.col.models.byName(self.modelName)['flds'])):
            # QLabel with field name
            field = self.form.fieldMapGrid.itemAtPosition(row, 0).widget().text()
            # QComboBox with index from the FILLING_OPTIONS list
            option_idx = self.form.fieldMapGrid.itemAtPosition(row, 1).widget().currentIndex()
            self.fieldMap[field] = option_idx

        # logging
        logging.info("Final dirPath   =     " + self.dirPath)
        logging.info("Final prov      =     " + self.prov)
        logging.info("Final deckName  =     " + self.deckName)
        logging.info("Final modelName =     " + self.modelName)
        logging.info('fieldMap = \n' + json.dumps(self.fieldMap, indent=4))
        logging.info("Final tags =          " + self.tagsTxt)

        # save user settings
        settings_dict = {
            self.DIR_PATH_KEY: self.dirPath,
            self.PROV_KEY: self.prov,
            self.DECK_NAME_KEY: self.deckName,
            self.MODEL_NAME_KEY: self.modelName,
            self.FIELD_MAP_KEY: self.fieldMap,
            self.TAGS_TXT_KEY: self.tagsTxt
        }
        with open(self.SETTINGS_JSON_PATH, 'w') as f:
            f.write(json.dumps(settings_dict, indent=4))

        QDialog.accept(self)
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)
Exemple #57
0
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] <> 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)
Exemple #58
0
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>'),
    )

    fields = config.get_fields(['sound', 'mandarinSound', 'cantoneseSound'])

    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, fields) and has_any_field(
                config['fields']['hanzi'], copy):
            d_has_fields += 1
            hanzi = get_first(config['fields']['hanzi'], copy)

            if all_fields_empty(copy, fields):
                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 connection, or retry later.')
    showInfo(msg)
Exemple #59
0
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] <> 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 accept(self):
     self.exporter.includeSched = (self.frm.includeSched.isChecked())
     self.exporter.includeMedia = (self.frm.includeMedia.isChecked())
     self.exporter.includeTags = (self.frm.includeTags.isChecked())
     if not self.frm.deck.currentIndex():
         self.exporter.did = None
     else:
         name = self.decks[self.frm.deck.currentIndex()]
         self.exporter.did = self.col.decks.id(name)
     if (self.isApkg and self.exporter.includeSched
             and not self.exporter.did):
         verbatim = True
         # it's a verbatim apkg export, so place on desktop instead of
         # choosing file; use homedir if no desktop
         usingHomedir = False
         file = os.path.join(
             QStandardPaths.writableLocation(
                 QStandardPaths.DesktopLocation), "collection.apkg")
         if not os.path.exists(os.path.dirname(file)):
             usingHomedir = True
             file = os.path.join(
                 QStandardPaths.writableLocation(
                     QStandardPaths.HomeLocation), "collection.apkg")
         if os.path.exists(file):
             if usingHomedir:
                 question = _(
                     "%s already exists in your home directory. Overwrite it?"
                 )
             else:
                 question = _(
                     "%s already exists on your desktop. Overwrite it?")
             if not askUser(question % "collection.apkg"):
                 return
     else:
         verbatim = False
         # Get deck name and remove invalid filename characters
         deck_name = self.decks[self.frm.deck.currentIndex()]
         deck_name = re.sub('[\\\\/?<>:*|"^]', '_', deck_name)
         filename = os.path.join(
             aqt.mw.pm.base, '{0}{1}'.format(deck_name, self.exporter.ext))
         while 1:
             file = getSaveFile(self,
                                _("Export"),
                                "export",
                                self.exporter.key,
                                self.exporter.ext,
                                fname=filename)
             if not file:
                 return
             if checkInvalidFilename(os.path.basename(file), dirsep=False):
                 continue
             break
     self.hide()
     if file:
         self.mw.progress.start(immediate=True)
         try:
             f = open(file, "wb")
             f.close()
         except (OSError, IOError) as e:
             showWarning(_("Couldn't save file: %s") % str(e))
         else:
             os.unlink(file)
             exportedMedia = lambda cnt: self.mw.progress.update(
                 label=ngettext("Exported %d media file",
                                "Exported %d media files", cnt) % cnt)
             addHook("exportedMediaFiles", exportedMedia)
             self.exporter.exportInto(file)
             remHook("exportedMediaFiles", exportedMedia)
             if verbatim:
                 if usingHomedir:
                     msg = _(
                         "A file called %s was saved in your home directory."
                     )
                 else:
                     msg = _("A file called %s was saved on your desktop.")
                 msg = msg % "collection.apkg"
                 period = 5000
             else:
                 period = 3000
                 if self.isTextNote:
                     msg = ngettext(
                         "%d note exported.", "%d notes exported.",
                         self.exporter.count) % self.exporter.count
                 else:
                     msg = ngettext(
                         "%d card exported.", "%d cards exported.",
                         self.exporter.count) % self.exporter.count
             tooltip(msg, period=period)
         finally:
             self.mw.progress.finish()
     QDialog.accept(self)