Example #1
0
 def on_done(future: Future):
     mw.progress.finish()
     try:
         future.result()
     except UnicodeDecodeError:
         showUnicodeWarning()
         return
     except Exception as e:
         msg = tr(TR.IMPORTING_FAILED_DEBUG_INFO) + "\n"
         err = repr(str(e))
         if "1-character string" in err:
             msg += err
         elif "invalidTempFolder" in err:
             msg += mw.errorHandler.tempFolderMsg()
         else:
             msg += traceback.format_exc()
         showText(msg)
         return
     else:
         txt = _("Importing complete.") + "\n"
         if importer.log:
             txt += "\n".join(importer.log)
         # fixme: the main window gets minimized when this dialog is closed
         showText(txt)
         mw.reset()
         return
Example #2
0
def getOrCreateDeck(deckName):
    deck_id = mw.col.decks.id(deckName)
    deck = mw.col.decks.get(deck_id)
    mw.col.decks.save(deck)
    mw.col.reset()
    mw.reset()
    return deck
Example #3
0
def search_word(browser, type=0):
    # if type == 0:
    #     showInfo('科林辞典')
    # else:
    #     showInfo('人人词典')

    notes = [mw.col.getNote(note_id) for note_id in browser.selectedNotes()]

    total = len(notes)
    n = 0
    for note in notes:
        result = ''
        if type == 0:
            result = searchWord_kelin(note['Front'])
        else:
            result = searchWord_renren(note['Front'])
        if result == '':
            # showInfo('查询失败,可以尝试使用别的词典')
            n += 1
        else:
            # showInfo('查询成功'+note['Back'])
            note['Back'] = result
            note.flush()
    mw.reset()
    msg = '查询单词' + str(total) + '个,其中' + str(total -
                                             n) + '个成功,' + str(n) + '个失败'
    showInfo(msg)
def regeneratePronunciations(nids):
    mw.checkpoint("Bulk-add Pronunciations")
    mw.progress.start()
    for nid in nids:
        note = mw.col.getNote(nid)
        if "japanese" not in note.model()['name'].lower():
            continue

        src, srcIdx, dst, dstIdx = get_src_dst_fields(note)

        if src is None or dst is None:
            continue

        if note[dst] and not regenerate_readings:
            # already contains data, skip
            continue

        srcTxt = mw.col.media.strip(note[src])
        if not srcTxt.strip():
            continue

        prons = getPronunciations(srcTxt)
        note[dst] = "  ***  ".join(prons)

        note.flush()
    mw.progress.finish()
    mw.reset()
Example #5
0
def import_apkg_model(path, delete=False):
    #If delete==True, our sole purpose is to import the note types and flashcard templates, not the data.

    imp = AnkiPackageImporter(mw.col, path)
    imp.run()
    mw.col.models.flush()
    mw.reset(
        True)  # refresh the screen so that the newly imported deck is visible

    if delete:
        # Delete ALL cards/notes in the LIFT deck. Ignore errors
        try:
            #            deck = mw.col.decks.byName(TARGET_DECK)  #hmm, this returns a Python dict(); how to get the deck object?
            #            assert deck.cardCount() > 0
            #            assert deck.noteCount() > 0
            ids = mw.col.findCards("deck:{}".format(TARGET_DECK))
            mw.col.remCards(ids, True)
#            assert deck.cardCount() == 0
#            assert deck.noteCount() == 0
        except:
            return "Failed to delete cards and notes after importing the APKG file."

    mw.col.models.flush()
    mw.reset(True)
    return ""
def toggleSameDaySpacing():
    global nospacing
    nospacing ^= True
    mw.col.conf['268644742_intraday_spacing'] ^= True
    mw.col.setMod()
    showInfo(msg_ger if German else msg_en)
    mw.reset()
Example #7
0
    def _onAddNotesButton(self, choice, close, svg):
        """Get occlusion settings in and pass them to the note generator (add)"""
        dialog = self.imgoccedit

        r1 = self.getUserInputs(dialog)
        if r1 is False:
            return False
        (fields, tags) = r1
        did = dialog.deckChooser.selectedId()

        noteGenerator = genByKey(choice)
        gen = noteGenerator(self.ed, svg, self.image_path, self.opref, tags,
                            fields, did)
        r = gen.generateNotes()
        if r is False:
            return False

        if self.origin == "addcards" and self.ed.note:
            # Update Editor with modified tags and sources field
            self.ed.tags.setText(" ".join(tags))
            self.ed.saveTags()
            for i in self.ioflds_prsv:
                if i in self.ed.note:
                    self.ed.note[i] = fields[i]
            self.ed.loadNote()
            deck = mw.col.decks.nameOrNone(did)
            self.ed.parentWindow.deckChooser.deck.setText(deck)

        if close:
            dialog.close()

        mw.reset()
Example #8
0
def import_from_json():
    path = getFile(mw, "Org file to import", cb=None, dir=expanduser("~"))
    if not path:
        return
    with open(path, 'r') as f:
        content = f.read().decode('utf-8')

    entries = json.loads(content)
    import itertools
    get_deck = lambda e: e['deck']
    entries = sorted(entries, key=get_deck)

    mw.checkpoint(_("Import"))
    logs = []
    for deck_name, entries in itertools.groupby(entries, get_deck):
        # FIXME: If required we could group by model name also!
        importer = JsonImporter(mw.col, path, MODEL_NAME, deck_name)
        importer.initMapping()
        importer.run(list(entries))
        if importer.log:
            logs.append('\n'.join(importer.log))

    txt = _("Importing complete.") + "\n"
    txt += '\n'.join(logs)
    showText(txt)
    mw.reset()
Example #9
0
def onDeckBrowserResetCards(did):
    if mw.col.decks.isDyn(did):
        tooltip("Can't reset scheduling for filtered/custom decks.")
    deck_name = mw.col.decks.name(did)
    cids = mw.col.decks.cids(did, children=True)
    if not cids:
        tooltip("Deck contains no cards.")
        return
    r = askUser("This will reset <b>ALL</b> scheduling information and "
                "progress in the deck '{}' and all of its subdecks ({} cards)."
                "<br><br>Are you sure you want to proceed?".format(
                    deck_name, len(cids)),
                defaultno=True,
                title="Reset Card Scheduling")
    if not r:
        return
    mw.checkpoint("Reset selected deck")
    mw.progress.start()

    resetSelectedCardScheduling(cids)

    mw.progress.finish()
    mw.reset()

    tooltip("{} card(s) reset.".format(len(cids)), parent=mw)
Example #10
0
def run():

    # Stats
    updated = 0
    numcards = mw.col.cardCount()

    # Get the RevTK file
    fname = QFileDialog.getOpenFileName(None, 'Open file', '', 'CSV (*.csv)')

    # Open
    try:
        f = open(fname, 'r')
    except:
        print 'Could not open file %s' % fname
        return

    # Process
    reader = csv.reader(f, delimiter=',', quotechar='"')
    for line in reader:

        if processCard(*line):
            updated += 1

    # Close
    f.close()

    # Finished
    showInfo('Updated %d/%d cards.' % (updated, numcards))
    mw.reset()
def process_one_feed(**kw):
    # get deck and model
    deck = mw.col.decks.get(mw.col.decks.id(kw['Deck']))
    model = mw.col.models.byName(kw['Note type'])

    # assign model to deck
    mw.col.decks.select(deck['id'])
    mw.col.decks.get(deck)['mid'] = model['id']
    mw.col.decks.save(deck)

    # assign deck to model
    mw.col.models.setCurrent(model)
    mw.col.models.current()['did'] = deck['id']
    mw.col.models.save(model)

    # retrieve rss
    data, errmsg = getFeed(kw['Url'])
    if errmsg:
        return errmsg

    #parse xml
    doc = BeautifulSoup(data, "html.parser")

    if not doc.find('item') is None:
        items = doc.findAll('item')
        feed = "rss"
    elif not doc.find('entry') is None:
        items = doc.findAll('entry')
        feed = "atom"
    else:
        return

    # iterate notes
    dups = 0
    adds = 0

    tofill = fields_to_fill_for_nonempty_front_template(model["id"])
    for item in items:
        note, increasedups = process_one_item(item, kw, feed, tofill)
        if increasedups:
            dups += 1
        if not note:
            continue
        mw.col.addNote(note)
        if not tofill:  # now one note of the note type exists
            tofill = fields_to_fill_for_nonempty_front_template(model["id"])
        adds += 1

    mw.col.reset()
    mw.reset()

    # show result
    msg = ngettext("%d note added", "%d notes added", adds) % adds
    msg += "\n"
    if dups > 0:
        msg += _("<ignored>") + "\n"
        msg += _("duplicate") + ": "
        msg += ngettext("%d note", "%d notes", dups) % dups
        msg += "\n"
    return msg
Example #12
0
def addKanjiSplits_bulk(nids):
    try:

        mw.checkpoint("Add Kanji Splits")

        mw.progress.start()
        # For each seleccted card
        for nid in nids:
            note = mw.col.getNote(nid)

            # do the note and handle the results
            if False == doNote(note):
                continue

            # Add the data to the dst field
            if True == doNote(note):
                note.flush()

    except KeyError:

        mw.hDialog = hDialog = QMessageBox()
        hDialog.setText(
            "Please make sure that these fields exist: 'Kanji Removed 1' ~ 'Kanji Removed 6', and 'Kanji Removed All'"
        )
        hDialog.exec_()

    finally:
        mw.progress.finish()
        mw.reset()
def addKDStories(nids):
	readStories()
	
	
	fields = []
	
	anote=mw.col.getNote(nids[0])
	#get the fields of the first note
	for (i, f) in anote.items():
		fields.append(i)
	
	#get input/output fields from user
	expField = addinfofuncts.getKeyFromList("Select field to read from", "Read relevant kanji/expression from:", fields)
	if (expField is None):
		return
	
	compoundMeaning = addinfofuncts.getKeyFromList("Select field to write to", "Write compound information to:", fields)
	if (compoundMeaning is None):
		return 
	
	Mnemonic = addinfofuncts.getKeyFromList("Select field to write to", "Write Mnemonic to:", fields)
	if (Mnemonic is None):
		return 
	
	EngMeaning = addinfofuncts.getKeyFromList("Select field to write to", "Write English meanings to:", fields)
	if (EngMeaning  is None):
		return 
	
	mw.checkpoint("Add KD Stories")
	mw.progress.start()
	#For each seleccted card
	for nid in nids:
		note = mw.col.getNote(nid)
		srcTxt = mw.col.media.strip(note[expField])
		if not srcTxt.strip():
			continue
		
		#Add the data to the dst field
		
		kanjizz = extractKanji(note[expField])
		if kanjiIndex.get(kanjizz):
			if kanjiIndex[kanjizz]['compound']:
				note[compoundMeaning] = kanjiIndex[kanjizz]['compound'].decode('utf8')
			else:
				note[compoundMeaning] = ""
				
				
			if kanjiIndex[kanjizz]['eng2meaning']:
				note[Mnemonic] = kanjiIndex[kanjizz]['eng2meaning'].decode('utf8')
			else:
				note[Mnemonic] = ""
				
				
			if kanjiIndex[kanjizz]['engmeaning']:
				note[EngMeaning] = kanjiIndex[kanjizz]['engmeaning'].decode('utf8')
			else:
				note[EngMeaning] = ""
			note.flush()
	mw.progress.finish()
	mw.reset()
    def createDeck(self, result):

        # create new deck and custom model
        name = result['title']
        terms = result['terms']
        deck = mw.col.decks.get(mw.col.decks.id(name))
        model = addCustomModel(name, mw.col)

        # assign custom model to new deck
        mw.col.decks.select(deck["id"])
        mw.col.decks.get(deck)["mid"] = model["id"]
        mw.col.decks.save(deck)

        # assign new deck to custom model
        mw.col.models.setCurrent(model)
        mw.col.models.current()["did"] = deck["id"]
        mw.col.models.save(model)
        txt = u"""
        <div><img src="{0}" /></div>
        """
        for term in terms:
            note = mw.col.newNote()
            note["Front"] = term["term"]
            note["Back"] = term["definition"].replace('\n', '<br>')
            if not term["image"] is None:
                #stop the previous thread first
                file_name = self.fileDownloader(term["image"]["url"])
                note["Back"] += txt.format(file_name)
                mw.app.processEvents()
            mw.col.addNote(note)
        mw.col.reset()
        mw.reset()
Example #15
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()
Example #16
0
    def execute(self, action):
        mw.checkpoint(action)

        for cmd in self:
            try:
                self._parse(cmd,
                            course=self.course,
                            datasource=self.datasource)
            except Exception as x:
                msg = 'Undoing {0} due to error "{1}"'.format(action, x)
                if hasattr(x, 'cmd'):
                    msg = msg + '\n\nWas processing command:\n{0}'.format(
                        x.cmd)
                msg = msg + '''

------------------------------------------------------------------
Please include the information below if reporting an error
------------------------------------------------------------------

{0}'''.format(traceback.format_exc())
                showWarning(msg, title=self.course.name)
                mw.onUndo()
                return False

        if self._warnings:
            showWarning('\n'.join(self._warnings))

        # refresh main view so changes are visible
        mw.reset()
        return True
Example #17
0
def regeneratePronunciations(nids):
    mw.checkpoint("Bulk-add Pronunciations")
    mw.progress.start()
    for nid in nids:
        note = mw.col.getNote(nid)
        #if "japanese" not in note.model()['name'].lower():
        #    continue

        src, srcIdx, dst, dstIdx, snd, sndIdx, color, colorIdx = get_src_dst_fields(
            note)

        if not src or dst is None:
            continue

        if note[dst] and not config["regenerate_prons"]:
            # already contains data, skip
            continue

        srcTxt = mw.col.media.strip(note[src])
        if not srcTxt.strip():
            continue

        color_src = mw.col.media.strip(note[color]) if color else ''

        note[src], note[dst], new_color_field, audio = multi_lookup(
            srcTxt, getPronunciations, colorTxt=color_src)
        if snd and audio: note[snd] = add_audio(audio)
        if color:
            note[color] = new_color_field
        note.flush()
    mw.progress.finish()
    mw.reset()
Example #18
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()
Example #19
0
  def importDeckFromCSV(self, filename, name):
    #file = r"C:\Users\aarun\OneDrive\Documents\Anki\addons\import.txt"
   
    # select deck
    did = mw.col.decks.id(name)
    #model = self.addNewModel()

    mw.col.decks.select(did)
    # set note type for deck
    model = mw.col.models.byName("Basic")
    deck = mw.col.decks.get(did)
    deck['mid'] = model['id']
    mw.col.decks.save(deck)

    # Assign new deck to model
    mw.col.models.setCurrent(model)
    model['did'] = did
    mw.col.models.save(model)

    # import into the collection
    ti = TextImporter(mw.col, filename)
    ti.initMapping()
    ti.run()

    mw.col.reset()
    mw.reset()
Example #20
0
 def r():
     #debug(f"Call function defined thanks to ({map})")
     card = mw.reviewer.card
     note = card.note()
     if 'bury' in map and map[
             'bury']:  #old config. May eventually be removed.
         map['action'] = 'bury note'
         del map['bury']
         updateConfig()
     action = map.get('action', "")
     checkSuffix = {
         "bury card": " and Bury Card",
         "bury note": " and Bury Note",
         "suspend card": " and Suspend Card",
     }.get(action, "")
     mw.checkpoint("Add Tags" + checkSuffix)
     addTags(note, map['tags'])
     if action == "bury card":
         mw.col.sched.buryCards([card.id])
     elif action == "bury note":
         mw.col.sched.buryNote(note.id)
     elif action == "suspend card":
         mw.col.sched.suspendCards([card.id])
     if action:
         mw.reset()
     tooltipSuffix = {
         "bury card": " and buried card",
         "bury note": " and buried note",
         "suspend card": " and suspended card",
     }.get(action, "")
     tooltip(f'Added tag(s) "%s"{tooltipSuffix}' % map['tags'])
Example #21
0
def showConfDialog():
    global wkconf
    d = QDialog()
    form = forms.configuration.Ui_Dialog()
    form.setupUi(d)

    form.key.setText(wkconf['key'])
    
    button = d.findChild(QRadioButton,wkconf['deck_separation'])
    if button:
        button.setChecked(True)
    button = d.findChild(QRadioButton,wkconf['card_direction'])
    if button:
        button.setChecked(True)

    button = d.findChild(QCheckBox,'includeTangorinLink')
    button.setChecked(wkconf.get('include_tangorin_link', False))

    button = d.findChild(QPushButton,'updateWaniKaniDecks')
    button.clicked.connect(updateWaniKaniDeck)

    d.setWindowModality(Qt.WindowModal)

    if d.exec_():
        wkconf['key'] = form.key.text()
        wkconf['deck_separation'] = form.deckSeparation.checkedButton().objectName()
        wkconf['card_direction'] = form.cardDirection.checkedButton().objectName()
        wkconf['include_tangorin_link'] = form.includeTangorinLink.isChecked()
        writeConf();

    mw.app.processEvents()
    mw.reset()
    mw.deckBrowser.show()
def regenerateKeywords(nids):
    mw.checkpoint("Bulk-add RTK Keywords")
    mw.progress.start()
    for nid in nids:
        note = mw.col.getNote(nid)

        src = None
        for fld in srcFields:
            if fld in note:
                src = fld
                break
        if not src:
            # no src field
            continue
        dst = None
        for fld in dstFields:
            if fld in note:
                dst = fld
                break
        if not dst:
            # no dst field
            continue
        if note[dst] and not OVERRIDE:
            # already contains data, skip
            continue
        srcTxt = mw.col.media.strip(note[src])
        if not srcTxt.strip():
            continue
        try:
            note[dst] = getKeywordsFast(srcTxt)
        except Exception as e:
            raise
        note.flush()
    mw.progress.finish()
    mw.reset()
Example #23
0
def onClearFormatting(browser):
    """
    Clears the formatting for every selected note.
    Also creates a restore point, allowing a single undo operation.

    Parameters
    ----------
    browser : Browser
        the anki browser from which the function is called
    """
    mw.checkpoint("Bulk-Clear Formatting")
    mw.progress.start()
    for nid in browser.selectedNotes():
        note = mw.col.getNote(nid)

        def clearField(field):
            result = stripFormatting(field)
            # if result != field:
            #     sys.stderr.write("Changed: \"" + field
            #                      + "\" ==> \"" + result + "\"")
            return result

        note.fields = map(clearField, note.fields)
        note.flush()
    mw.progress.finish()
    mw.reset()
Example #24
0
 def _onTreeDeckAdd(self, item=None):
     parent = item.fullname + "::" if item and item.type == 'deck' else ''
     subdeck = getOnlyText(_("Name for deck/subdeck:"))
     if subdeck:
         mw.col.decks.id(parent + subdeck)
         self._saveDecks()
         mw.reset(True)
Example #25
0
def import_from_json():
    path = getFile(mw, "Org file to import", cb=None, dir=expanduser("~"))
    if not path:
        return
    with open(path, 'r') as f:
        content = f.read().decode('utf-8')

    entries = json.loads(content)
    import itertools
    get_deck = lambda e: e['deck']
    entries = sorted(entries, key=get_deck)

    mw.checkpoint(_("Import"))
    logs = []
    for deck_name, entries in itertools.groupby(entries, get_deck):
        # FIXME: If required we could group by model name also!
        importer = JsonImporter(mw.col, path, MODEL_NAME, deck_name)
        importer.initMapping()
        importer.run(list(entries))
        if importer.log:
            logs.append('\n'.join(importer.log))

    txt = _("Importing complete.") + "\n"
    txt += '\n'.join(logs)
    showText(txt)
    mw.reset()
Example #26
0
def importFromFolder():
    mw.importDialog = QFileDialog()
    mw.importDialog.setFileMode(QFileDialog.Directory)

    if mw.importDialog.exec_():
        fileNames = mw.importDialog.selectedFiles()

        if len(fileNames) > 0:
            rootDir = fileNames[0]
            baseName = os.path.basename(rootDir)
            prefixLen = len(rootDir) - len(baseName)
            for root, subDirs, files in os.walk(rootDir):
                for f in files:
                    if f.endswith(".apkg"):
                        # Get name for deck
                        deckName = "::".join(root[prefixLen:].split(
                            os.sep)) + "::" + f[0:len(f) - 5]

                        did = mw.col.decks.id(deckName)
                        mw.col.decks.save(mw.col.decks.get(did))
                        importer = CustomImporter(mw.col,
                                                  os.path.join(root, f))
                        importer.deckPrefix = deckName
                        importer.run()

            mw.reset()
Example #27
0
def addDelay(cids):
    (delay, delayResp) = getDelayWithResponse()
    if delay is None:
        if delayResp:
            showWarning("Please enter an integral number of days")
        return

    mw.checkpoint("Adding delay")
    mw.progress.start()

    ivlDelay = max(
        0,
        round(delay * (getIntervalCoefficient()
                       if delay > 0 else getIntervalForNegativeCoefficient())))
    for cid in cids:
        card = mw.col.getCard(cid)
        if card.type != 2:
            continue
        card.ivl += ivlDelay
        if card.odid:  # Also update cards in filtered decks
            card.odue += delay
        else:
            card.due += delay
        card.flush()

    mw.progress.finish()
    mw.col.reset()
    mw.reset()

    tooltip(_("""Delay added."""))
Example #28
0
def bulkAddJDefs(nids):
        
    mw.checkpoint("Add JDefs")
    mw.progress.start()
    
    
    #For each seleccted card
    for nid in nids:
        note = mw.col.getNote(nid)
    
        #Check if we should do it
        #First check to see if the fields exist
        
        #If field check fails then cancel (does any field not exist and are all of them full?
        if not definitionField in note or \
            not dictionaryForm in note or \
            (note[definitionField] and  \
            note[dictionaryForm]):
        
            continue
        
        
        #do the note
        if True == doNote(note, 1):
            note.flush()
            
    #save
    mw.progress.finish()
    mw.reset()        
    def _onAddNotesButton(self, choice, close, svg):
        """Get occlusion settings in and pass them to the note generator (add)"""
        dialog = self.imgoccedit

        r1 = self.getUserInputs(dialog)
        if r1 is False:
            return False
        (fields, tags) = r1
        did = dialog.deckChooser.selectedId()

        noteGenerator = genByKey(choice)
        gen = noteGenerator(self.ed, svg, self.image_path,
                            self.opref, tags, fields, did)
        r = gen.generateNotes()
        if r is False:
            return False

        if self.origin == "addcards" and self.ed.note:
            # Update Editor with modified tags and sources field
            self.ed.tags.setText(" ".join(tags))
            self.ed.saveTags()
            for i in self.ioflds_prsv:
                if i in self.ed.note:
                    self.ed.note[i] = fields[i]
            self.ed.loadNote()
            deck = mw.col.decks.nameOrNone(did)
            self.ed.parentWindow.deckChooser.deck.setText(deck)

        if close:
            dialog.close()

        mw.reset()
def regeneratePronunciations(nids):
    mw.checkpoint("Bulk-add Pronunciations")
    mw.progress.start()
    for nid in nids:
        note = mw.col.getNote(nid)

        # Check if this is a supported note type. If it is not, skip.
        # If no note type has been specified, we always continue the lookup proces.
        if config["noteTypes"] and not any(nt.lower() in note.model()['name'].lower() for nt in config["noteTypes"]):
            continue

        src, srcIdx, dst, dstIdx = get_src_dst_fields(note)

        if src is None or dst is None:
            continue

        if note[dst] and not config["regenerateReadings"]:
            # already contains data, skip
            continue

        srcTxt = mw.col.media.strip(note[src])
        if not srcTxt.strip():
            continue

        note[dst] = getFormattedPronunciations(srcTxt)

        note.flush()
    mw.progress.finish()
    mw.reset()
Example #31
0
def maybeCreateTemplate():
    if not config["local"]["dictionaryEnabled"]:
        return
    mid = mw.col.models.byName(config["local"]["dictionaryNoteTypeName"])
    if not mid:
        addModel()
        mw.reset()
Example #32
0
def bulkAddJDefs(nids):

    mw.checkpoint("Add JDefs")
    mw.progress.start()

    #For each seleccted card
    for nid in nids:
        note = mw.col.getNote(nid)

        #Check if we should do it
        #First check to see if the fields exist

        #If field check fails then cancel (does any field not exist and are all of them full?
        if not definitionField in note or \
            not dictionaryForm in note or \
            (note[definitionField] and  \
            note[dictionaryForm]):

            continue

        #do the note
        if True == doNote(note, 1):
            note.flush()

    #save
    mw.progress.finish()
    mw.reset()
Example #33
0
def rename(old_name, new_name):
    SEPARATOR = get_config()["separator"]
    tags = mw.col.tags.all()
    rename_dict = {old_name: new_name}  # {old : new}

    for tag in tags:
        parts = tag.split(SEPARATOR)
        for i in range(len(parts)):
            if old_name == SEPARATOR.join(parts[:i]):
                retained_stub = SEPARATOR.join(parts[i:len(parts)])
                rename_dict[tag] = SEPARATOR.join([new_name, retained_stub])

    mw.checkpoint("Rename Tag")
    mw.progress.start()
    nids = mw.col.db.list('select id from notes')
    for id in nids:
        note = mw.col.getNote(id)

        for k, v, in rename_dict.items():
            if note.hasTag(k):
                note.delTag(k)
                note.addTag(v)
                note.flush()
    mw.reset()
    mw.progress.finish()
Example #34
0
def bulkAdd(browser):
    nids=browser.selectedNotes()
    
    mw.checkpoint("Bulk-add Tatoeba")
    mw.progress.start()
    
    #connect to database
    #connection = sqlite3.connect(databasePath)
    global cursor
    #cursor = connection.cursor()
    
    #For each seleccted card
    for nid in nids:
        note = mw.col.getNote(nid)
    
        #Check if we should do it
        #First check to see if the fields exist
        
        #If field check fails then cancel (does any field not exist and are all of them full?
        ##skip, deal with it in doNote
        
        #do the note
        if True == doNote(note):
            note.flush()
            
    #save
    cursor.close()
    mw.progress.finish()
    mw.reset()        
Example #35
0
 def _onTreeDeckDelete(self, item):
     self.browser._lastSearchTxt = ""
     sel = mw.col.decks.byName(item.fullname)
     mw.deckBrowser._delete(sel['id'])
     mw.col.decks.save()
     mw.col.decks.flush()
     mw.reset(True)
    def compare(self, remoteWordList):
        localWordList = cardManager.getDeckWordList(
            deckName=self.ui.deckComboBox.currentText(), )
        local = set(localWordList)
        remote = set(remoteWordList)

        needToAddWords = remote - local
        needToDeleteWords = local - remote
        needToDeleteIds = cardManager.getNoteByWord(
            words=needToDeleteWords,
            deckName=self.ui.deckComboBox.currentText())

        if needToDeleteWords and askUser(
                f'远程单词({len(needToDeleteWords)}个):\n{", ".join(list(needToDeleteWords)[:3])}...已经删除,\n是否删除Anki相应卡片?',
                title='Dict2Anki',
                parent=self):
            self.log(f'准备删除:\n{list(needToDeleteWords)}')
            self.log(f'卡片 Ids:\n{needToDeleteIds}')
            mw.col.remNotes(needToDeleteIds)
            mw.col.reset()
            mw.reset()
            self.log(f'删除成功。')
        if needToAddWords:
            self.log(f'准备查询:{list(needToAddWords)}')
        else:
            self.log("没有需要查询的单词。")

        return needToAddWords
Example #37
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()
def regeneratePronunciations(nids):
    mw.checkpoint("Bulk-add Pronunciations")
    mw.progress.start()
    for nid in nids:
        note = mw.col.getNote(nid)
        if "japanese" not in note.model()["name"].lower():
            continue

        src, srcIdx, dst, dstIdx = get_src_dst_fields(note)

        if src is None or dst is None:
            continue

        if note[dst] and not regenerate_readings:
            # already contains data, skip
            continue

        srcTxt = mw.col.media.strip(note[src])
        if not srcTxt.strip():
            continue

        prons = getPronunciations(srcTxt)
        note[dst] = "  ***  ".join(prons)

        note.flush()
    mw.progress.finish()
    mw.reset()
Example #39
0
    def createDeck(self, name, terms):
        """create new Anki deck from downloaded data"""
        #create new deck and custom model
        deck = mw.col.decks.get(mw.col.decks.id(name))
        model = addCustomModel(name, mw.col)

        #assign custom model to new deck
        mw.col.decks.select(deck["id"])
        mw.col.decks.get(deck)["mid"] = model["id"]
        mw.col.decks.save(deck)

        #assign new deck to custom model
        mw.col.models.setCurrent(model)
        mw.col.models.current()["did"] = deck["id"]
        mw.col.models.save(model)
#         f=open('terms.txt','wb')
        txt=u"""
        <div><img src="{0}" /></div>
        """
        for term in terms:            
            note = mw.col.newNote()
            note[_("Front")] = term["term"]
            note[_("Back")] = term["definition"]
            if not term["image"] is None:
                #stop the previous thread first
                self.fileDownloader(term["image"]["url"])
                note[_("Back")]+=txt.format(term["image"]["url"].split('/')[-1])
                mw.app.processEvents()
            mw.col.addNote(note)
#         f.close()
        mw.col.reset()
        mw.reset()
Example #40
0
    def _onTreeDeckRenameLeaf(self, item):
        mw.checkpoint(_("Rename Deck"))
        from aqt.utils import showWarning
        from anki.errors import DeckRenameError

        self.browser._lastSearchTxt = ""
        sel = mw.col.decks.byName(item.fullname)
        try:
            path, leaf = item.fullname.rsplit('::', 1)
            newName = path + '::' + getOnlyText(_("New deck name:"),
                                                default=leaf)
        except ValueError:
            newName = getOnlyText(_("New deck name:"), default=item.fullname)
        newName = newName.replace('"', "")
        if not newName or newName == item.fullname:
            return

        newName = unicodedata.normalize("NFC", newName)
        deck = mw.col.decks.get(sel["id"])
        try:
            mw.col.decks.rename(deck, newName)
        except DeckRenameError as e:
            return showWarning(e.description)
        self._swapHighlight(item.type, item.fullname, newName)
        self._saveDecks()
        # self.highlight('deck',newName)
        mw.show()
        mw.reset(True)
def bulkAdd(browser):
    nids = browser.selectedNotes()

    mw.checkpoint("Bulk-add Tatoeba")
    mw.progress.start()

    #connect to database
    #connection = sqlite3.connect(databasePath)
    global cursor
    #cursor = connection.cursor()

    #For each seleccted card
    for nid in nids:
        note = mw.col.getNote(nid)

        #Check if we should do it
        #First check to see if the fields exist

        #If field check fails then cancel (does any field not exist and are all of them full?
        ##skip, deal with it in doNote

        #do the note
        if True == doNote(note):
            note.flush()

    #save
    cursor.close()
    mw.progress.finish()
    mw.reset()
Example #42
0
def regeneratePronunciations(nids):
    mw.checkpoint("Bulk-add Pronunciations")
    mw.progress.start()
    for nid in nids:
        note = mw.col.getNote(nid)

        # Check if this is a supported note type. If it is not, skip.
        # If no note type has been specified, we always continue the lookup proces.
        if config["noteTypes"] and not any(
                nt.lower() in note.model()['name'].lower()
                for nt in config["noteTypes"]):
            continue

        src, srcIdx, dst, dstIdx = get_src_dst_fields(note)

        if src is None or dst is None:
            continue

        if note[dst] and not config["regenerateReadings"]:
            # already contains data, skip
            continue

        srcTxt = mw.col.media.strip(note[src])
        if not srcTxt.strip():
            continue

        note[dst] = getFormattedPronunciations(srcTxt)

        note.flush()
    mw.progress.finish()
    mw.reset()
def paste_to_my_field(editor):
    u'''Paste clipboard text to field specified by constant FIELD_NAMES '''
    note = editor.note
    # enumerate all fieldNames of the current note
    for _, field_name in enumerate(mw.col.models.fieldNames(note.model())):
        if field_name in FIELD_NAMES:
            note[field_name] = pyperclip.paste()
    mw.reset()
def clear_all_editor_fields(editor):
    u'''Remove text from fields in editor. '''
    note = editor.note
    # enumerate all fieldNames of the current note
    for c, field_name in enumerate(mw.col.models.fieldNames(note.model())):
        note[field_name] = ''
    note.flush()  # never forget to flush
    mw.reset()  # refresh gui
Example #45
0
def onBulkadd(browser):
    nids = browser.selectedNotes()
    for nid in nids:
        note = mw.col.getNote(nid)
        onFocusLost(False, note, None)
        note.flush()
    mw.progress.finish()
    mw.reset()
Example #46
0
 def processTransactions(self, transactions):
   # transactions is an array
   transactions.sort(cmp=compare)
   for t in transactions:
       if t["query"] in self.CARD_QUERIES:
           self.CARD_QUERIES[t["query"]](self, t["data"])
       else:
           pass # uh oh, unsupported query
   mw.reset()
Example #47
0
def reset_and_redraw(same_card_shown=False):
    """Rebuild the scheduler and redraw the card."""
    answer_state = mw.reviewer.state == "answer"
    mw.reset()
    if answer_state and same_card_shown:
        try:
            mw.reviewer._showAnswerHack()
        except:
            pass
Example #48
0
def changeFont():
    f = QFontInfo(QFont(FONT))
    ws = QWebSettings.globalSettings()
    mw.fontHeight = f.pixelSize()
    mw.fontFamily = f.family()
    mw.fontHeightDelta = max(0, mw.fontHeight - 13)
    ws.setFontFamily(QWebSettings.StandardFont, mw.fontFamily)
    ws.setFontSize(QWebSettings.DefaultFontSize, mw.fontHeight)
    mw.reset()
Example #49
0
def onResetTimes(browser):

    # Make sure user selected something.
    if not browser.form.tableView.selectionModel().hasSelection():
        showWarning("Please select at least one card to reset creation date.", parent=browser)
        return
 
    # Preprocess cards, collecting note IDs.
    (card_cnt, nids) = identifyNotes(browser.selectedCards())
    
    # debug
    #showInfo(("Processed %s cards leading to %s notes") % (card_cnt, len(nids)))
    
    # Prompt for date.
    todaystr = time.strftime('%Y/%m/%d', time.localtime())
    (s, ret) = getText("Enter a date as YYYY/MM/DD to set as the creation time, or 'today' for current date (%s):" % todaystr, parent=browser)

    if (not s) or (not ret):
        return
    
    # Generate a random MM:HH:SS. This will help prevent the same timestamp from
    # being used if this addon is executed multiple times with the same date.
    random_time = ("%s:%s:%s") % (random.randint(0, 23), random.randint(0, 59), random.randint(0, 59))

    # Don't want random? Uncomment the following line and specify any time you 
    # want in the format HH:MM:SS where HH is 00-24:
    #random_time = "15:01:01"

    
    if s == 'today':
        desttime = time.mktime(time.strptime(("%s %s") % (todaystr, random_time), '%Y/%m/%d %H:%M:%S'))
    else:
        try:
            desttime = time.mktime(time.strptime(("%s %s") % (s, random_time), '%Y/%m/%d %H:%M:%S'))
        except ValueError:
            showWarning("Sorry, I didn't understand that date.  Please enter 'today' or a date in YYYY/MM/DD format", parent=browser)
            return
   
    # This mimics anki/utils.py timestampID function (which calls intTime for
    # seconds since epoch and multiplies those seconds by 1000).
    desttime = desttime * 1000
    
    # debug
    # showInfo(("desttime %s") % desttime)

    # Force a full sync if collection isn't already marked for one. This is
    # apparently because we are changing the key column of the table.
    # (Per Damien on 2013/01/07: http://groups.google.com/group/anki-users/msg/3c8910e10f6fd0ac?hl=en )
    mw.col.modSchema(check=True)
    
    # Do it.
    resetCreationTimes(nids, desttime)
        
    # Done.
    mw.reset()
    tooltip(ngettext("Creation time reset for %d note.", "Creation time reset for %d notes.", len(nids)) % len(nids))
Example #50
0
def changeModel(name):
    deck = mw.col
    #m = deck.models.byName(u'Básico')
    m = deck.models.byName(name)
    deck.conf['curModel'] = m['id']
    cdeck = deck.decks.current()
    cdeck['mid'] = m['id']
    deck.decks.save(cdeck)
    runHook("currentModelChanged")
    mw.reset()
Example #51
0
 def processDeckTransactions(self, transactions):
   # transactions is an array
   # need to sort transactions by timestamp/grouping here
   transactions.sort(cmp=compare)
   for t in transactions:
       if t["query"] in self.DECK_QUERIES:
           self.DECK_QUERIES[t["query"]](self, t)
       else:
           pass # uh oh, unsupported query
   mw.reset()
def addHeisigNumbers(nids):
    #get version to use
    
    version = getHeisigVersion()
    if version == False:
        return
    
    
    fields = []
    
    anote=mw.col.getNote(nids[0])
    #get the fields of the first note
    for (i, f) in anote.items():
        fields.append(i)
    
    #get input/output fields from user
    expField = getKeyFromList("Select field to read from", "Read relevant kanji/expression from:", fields)
    if (expField is None):
        return
    heisigNumDstField = getKeyFromList("Select field to write to", "Write Heisig numbers to:", fields)
    if (heisigNumDstField is None):
        return
    
    
    
    mw.checkpoint("Add Heisig Numbers")
    mw.progress.start()
    readRTK()
    
    #For each seleccted card
    for nid in nids:
        note = mw.col.getNote(nid)
        src = None
        if expField in note:
            src = expField
        if not src:
            # no src field then next card
            continue
        dst = None
        if heisigNumDstField in note:
            dst = heisigNumDstField
        if not dst:
            # no dst field then skip card
            continue
        srcTxt = mw.col.media.strip(note[src])
        if not srcTxt.strip():
            continue
        #Add the data to the dst field
        num = joinseparator.join(lookupKanjiInfo(srcTxt, 'heisig'+version))
        if num!=0:
            note[dst] = str(num)
        #sys.stderr.write("Results:" + note[dst])
        note.flush()
    mw.progress.finish()
    mw.reset()	
Example #53
0
def mergeDupes(res):
    if not res:
        return

    mw.checkpoint(_("Merge Duplicates"))
    
    def update(ncc, nc):
        #if not mw.col.decks.current()['dyn']:
        #    curdid = mw.col.decks.current()['id']
        #else:
        curdid = nc.did
        mw.col.db.execute("update cards set did=?, mod=?, usn=?, type=?, queue=?, due=?, ivl=?, factor=?, reps=?, lapses=?, left=?, odue=0, odid=0 where id = ?",
            curdid, intTime(), mw.col.usn(), nc.type, nc.queue, nc.due, nc.ivl, nc.factor, nc.reps, nc.lapses, nc.left, ncc.id)

    for s, nidlist in res:
        note_copy = mw.col.newNote()
        for i, nid in enumerate(nidlist):
            n = mw.col.getNote(nid)
            note_copy.tags += n.tags

            # Because apparently it's nontrivial to retrive cards by ord# so force all cards to exist before we copy the scheduling
            for (name, value) in n.items():
                if not n[name]:
                    n[name] = "BLANK"
            n.flush()

            # Add note to database now to force anki to generate cards, then copy an initial state for the new cards
            if (i == 0):
                note_copy.fields = n.fields
                mw.col.addNote(note_copy)
                for ncc, nc in zip(note_copy.cards(), n.cards()):
                    update(ncc, nc)

            for (name, value) in note_copy.items():
                if value == "BLANK":
                    note_copy[name] = ""
                if n[name] != "BLANK":
                    if not value or value == "BLANK":
                        note_copy[name] = n[name]
                        continue
                    arr = value.split(" / ")
                    if (n[name] not in arr):
                        note_copy[name] = value + " / " + n[name]

            for ncc, nc in zip(note_copy.cards(), n.cards()):
                if nc.ivl > ncc.ivl or nc.queue > ncc.queue:
                    update(ncc, nc)
        note_copy.flush()
        mw.col.remNotes(nidlist)
        mw.col.tags.bulkRem([note_copy.id], _("duplicate"))

    mw.progress.finish()
    mw.col.reset()
    mw.reset()
    tooltip(_("Notes merged."))
Example #54
0
    def make_cards(self, terms):
        
        title      = self.DECK_FIELD.text()
        img_side   = self.I_BUTTON.checkedButton().text()
        tags       = re.split(' |, ', self.TAGS_FIELD.text())
        model_name = 'HTML 2 ANKI'
        
        #log.info(terms)
        
        # MAKE DECK
        deck = mw.col.decks.get(mw.col.decks.id(title))
        
        # MAKE MODEL IF IT DOESN'T EXIST
        if self.THEME.isChecked():
            if not mw.col.models.byName('Basic (HTML 2 ANKI DARK)') is None:
                model = mw.col.models.byName('Basic (HTML 2 ANKI DARK)')
            else:
                model = dark_theme(model_name, mw.col)
        else:
            if not mw.col.models.byName('Basic (HTML 2 ANKI)') is None:
                model = mw.col.models.byName('Basic (HTML 2 ANKI)')
            else:
                model = basic_theme(model_name, mw.col)
            
        # ASSIGN MODEL TO DECK
        mw.col.decks.select(deck['id'])
        mw.col.decks.get(deck)['mid'] = model['id']
        mw.col.decks.save(deck)

        # ASSIGN DECK TO MODEL
        mw.col.models.setCurrent(model)
        mw.col.models.current()['did'] = deck['id']
        mw.col.models.save(model)
        

        # ITERATE CARDS
        for term in terms:            
            card = mw.col.newNote()
            if not term['question'] is None:
                card['Front']   = u''.join(unicode(i) for i in term['question'])
            if not term['answer'] is None:
                card['Back']    = u''.join(unicode(i) for i in term['answer'])
            if not term['image'] is None:
                card[img_side] += u'<img src="%s">' % term['image']
                mw.app.processEvents()

            card['http'] = u''.join(unicode(i) for i in term['url'])
            card.tags = filter(None, tags)
            mw.col.addNote(card)

        mw.col.reset()
        mw.reset()
        
        return terms
Example #55
0
 def run(self, apiKey):
     """Import all available cards."""
     mw.checkpoint("Import from SRS Collector")
     self._apiKey = apiKey
     data = self._downloadCardData()
     self._checkMeta(data["meta"]["anki_addon"])
     if "card_models" in data:
         self._ensureCardModels(data["card_models"])
     self._importCardsWithTempDir(data["cards"])
     mw.col.autosave()
     mw.reset()
Example #56
0
def add_tag(q, t):
    # adds tag to note
    self = get_plugin()
    setup()

    note = get_note(q)
    if not note:
        raise "Najpierw otaguj siebie, zanim zaczniesz tagować to co nie istnieje..."
    note.tags.append(t)
    note.flush()
    mw.reset()
Example #57
0
def doOnCardSelection( b, preF, perF, postF ):
    st = preF( b )
    if not st: return

    cids = b.selectedCards()
    for i,cid in enumerate( cids ):
        card = mw.col.getCard( cid )
        st = perF( st, card )

    st = postF( st )
    if not st or st.get( '__reset', True ):
        mw.reset()
def promptNewInterval(self, card):

    dayString = getText("Number of days until next review: ")
    try:
        days = int(dayString[0])
    except ValueError:
        return

    if days > 0:
        mw.col.sched.reschedCards( [card.id], days, days )
        tooltip('Rescheduled for review in ' + str(days) + ' days'  )
        mw.reset()
Example #59
0
def repositionCards(nids):
    mw.checkpoint("Reposition cards")
    mw.progress.start()
    for nid in nids:
        note = mw.col.getNote(nid)
        (c,e) = clozeFields(note)
        # does it contain data?
        if not c or not e:
           continue
        _repositionCards(note, c, e)
    mw.progress.finish()
    mw.reset()