Beispiel #1
0
def duplicate_selected_note(browser):
    assert(len(browser.selectedNotes()) == 1)
    base_note = browser.card.note()
    base_did = browser.card.did
    new_note = Note(mw.col, base_note.model())
    #self.id = timestampID(col.db, "notes")
    t = base_note.id + 1
    while mw.col.db.scalar("select id from %s where id = ?" % "notes", t):
        t += 1
    new_note.id = t
    #No change needed: self.guid = guid64()
    #No change needed: self._model = model
    #No change needed: self.mid = model['id']
    new_note.tags = copy.copy(base_note.tags)  #self.tags = []
    new_note.fields = copy.copy(base_note.fields) #self.fields = [""] * len(self._model['flds'])
    new_note.flags = base_note.flags #self.flags = 0
    new_note.data = base_note.data #self.data = ""
    #No change needed: self._fmap = self.col.models.fieldMap(self._model)
    #No change needed: self.scm = self.col.scm

    new_note.addTag(u'Copied')
    browser.model.beginReset()
    #The cards will be added to the deck set into the current template.
    #Changing the template's deck would be unexpected,
    #   so change the decks manually
    cards = mw.col.addNote(new_note)
    for card in new_note.cards():
        if card.did != base_did:
            card.did = base_did
            card.flush()

    browser.model.endReset()
Beispiel #2
0
def add_note(model, deck, flds, tags = []):
    note = Note(col(), get_model(model))
    note.model()['did'] = get_deck(deck)
    note.fields = map(lambda s: (s in flds and flds[s]) or empty_field(), conf.models[model]['fields'])

    map(lambda tag: note.addTag(conf.tags[tag]), tags)
    col().addNote(note)
Beispiel #3
0
def addBackNote(line, wrongMids, presentNids):
    elements = line.split("\t")
    #print(f"Considering line «{elements}»")
    nid = elements[0]
    #print(f"nid is {nid}")
    mid = elements[1]
    if mw.col.db.list("""select id from notes where id = ?""", nid):
        print(f"Note {nid} was already present")
        presentNids.add(nid)
        return "nid present"
    #print(f"mid is {mid}")
    fields = elements[2:]
    model = mw.col.models.get(mid)
    if model is None:
        wrongMids.add(mid)
        return "no mid"
    nbFieldEntry = len(fields)
    nbFieldModel = len(model["flds"])
    if nbFieldModel < nbFieldEntry:
        end = fields[nbFieldModel - 1:]
        last_field = "EXTRAFIELD".join(end)
        fields = fields[:nbFieldModel - 1]
        fields.append(last_field)
    elif nbFieldModel > nbFieldEntry:
        fields += [""] * (nbFieldModel - nbFieldEntry)
    note = Note(mw.col, model)
    note.id = nid
    note.fields = fields
    note.addTag("NoteBackFromDeleted")
    nbCard = mw.col.addNote(note)
    if nbCard == 0:
        note.addTag("NoteWithNoCard")
        note.flush()
        template0 = model["tmpls"][0]
        mw.col._newCard(note, template0, mw.col.nextID("pos"))
        return "no card"
    return True
def tagCard():
    col = mw.col
    nids = col.db.list("select id from notes ")
    cids = col.genCards(nids)
    cids = ids2str(cids)
    request = "select nid,ord from cards where (id in " + cids + ")"
    print request
    toTagCids = col.db.execute(request)
    for nid, card_ord in toTagCids:
        print "-----------\nConsidering nid:%s, card_ord:%s" % (str(nid),
                                                                str(card_ord))
        note = Note(col, id=nid)
        model = note._model
        isCloze = model["type"] == 1
        print "Model %s: %s." % (str(model["id"]), model["name"])
        if not isCloze:
            print "is cloze."
            templates = model['tmpls']
            template = templates[card_ord]
            try:
                print "Template %s" % (template["name"].encode('utf-8'))
            except UnicodeEncodeError:
                print "Template (unicode error)"
            templateName = template["name"]
            templateName = re.sub(r"\s", r"_", templateName)
        else:
            print "is not cloze."
            templateName = "cloze_%s" % (str(card_ord + 1))
        print "template name is %s" % templateName
        tag = ("empty_%s" % templateName)
        try:
            print "tagging %s: %s" % (str(nid), tag.encode('utf-8'))
        except UnicodeEncodeError:
            print "tagging %s: %s (unicode error)" % (str(nid), str(card_ord))
        note.addTag(tag)
        note.flush()
    return cids
Beispiel #5
0
def mergeNotes(note1, note2):
    mw.checkpoint("Merge Notes")

    model1 = note1.model()
    model2 = note2.model()
    if model1 != model2:
        showWarning(_("Please select notes of the same type to merge them"))
        return
    note = Note(mw.col, id=note1.id)
    if not getUserOption("Delete original cards", True):
        note.id = timestampID(mw.col.db, "notes", note.id)

    weak = maybeGetWeakNote(note1, note2)

    overwrite_patterns = [
        re.compile(p) for p in (getUserOption("Overwrite patterns", []) or [])
    ]
    for i in range(len(note.fields)):
        if maybeOverwriteField(overwrite_patterns, i, note, note2):
            continue
        elif note1 == weak:
            note.fields[i] = note2.fields[
                i] if note2.fields[i] != "" else note1.fields[i]
        elif note2 == weak:
            note.fields[i] = note1.fields[
                i] if note1.fields[i] != "" else note2.fields[i]
        elif note1.fields[i] != note2.fields[i] or not getUserOption(
                "When identical keep a single field", True):
            note.fields[i] += note2.fields[i]
    cards = [None] * len(model1['tmpls'])

    # Choosing which card to keep
    cards_to_delete = []
    for card1 in note1.cards():
        cards[card1.ord] = card1
    for card2 in note2.cards():
        ord = card2.ord
        card1 = cards[ord]
        if card1 is None or card1.type == CARD_NEW or card1.ivl < card2.ivl or (
                card1.ivl == card2.ivl and card1.factor < card2.factor):
            cards[ord] = card2
            cards_to_delete.append(card1.id)
        else:
            cards_to_delete.append(card2.id)

    # tags
    note.addTag(note2.stringTags())
    note.addTag(f"merged merged_{note1.id} merged_{note2.id}")

    if getUserOption("Delete original cards", False):
        mw.col.remNotes([note2.id])
        mw.col.remCards(cards_to_delete, notes=False)

    for card in cards:
        if card is None:
            continue
        if not getUserOption("Delete original cards", True):
            card.id = timestampID(mw.col.db, "cards", card.id)
        card.nid = note.id
        card.flush()
    note.flush()

    tooltip(_("Notes merged"))
    return note
Beispiel #6
0
def merge_tags(note1: Note, note2: Note) -> None:
    for tag in note2.tags:
        if tag == 'leech':
            continue
        if not note1.hasTag(tag):
            note1.addTag(tag)
Beispiel #7
0
    else:
        is_my_sol = False
        answer_list = official_answer_list
    answer = md_util.md_convert("\r\n<hr>答案分隔线<hr>\r\n".join(answer_list))

    # 答案可能会变化,但文件名和问题会相对固定,所以以这两者取 guid
    guid = util.java_string_hashcode(deck_name + "|" + problem_slug)
    item_id = util.get_item_id(col, guid)
    fields0 = question
    fields1 = answer

    if item_id > 0:
        note = Note(col, id=item_id)
        old_tags = deepcopy(note.tags)
        if is_my_sol:
            note.addTag("mysol")
        for tag in tags:
            note.addTag(tag)
        if old_tags != note.tags:
            note.flush()
        if not (note.fields[0] == fields0 and note.fields[1] == fields1):
            note.guid = guid
            note.model()['did'] = deck['id']
            note.fields[0] = fields0
            note.fields[1] = fields1
            note.flush(int(time.time()))
    # 如果没有此 item 则建立新的 item
    else:
        note = col.newNote()
        note.guid = guid
        note.model()["did"] = deck["id"]
Beispiel #8
0
    def check(self, local=None):
        "Return (missingFiles, unusedFiles)."

        mdir = self.dir()
        # gather all media references in NFC form
        allRefs = set()
        refsToNid = dict()  # this dic is new
        for nid, mid, flds in self.col.db.execute(
                "select id, mid, flds from notes"):
            noteRefs = self.filesInStr(mid, flds)
            # check the refs are in NFC
            for f in noteRefs:
                # if they're not, we'll need to fix them first
                if f != unicodedata.normalize("NFC", f):
                    self._normalizeNoteRefs(nid)
                    noteRefs = self.filesInStr(mid, flds)
                    break
            # new. update refsToNid
            for f in noteRefs:
                if f not in refsToNid:
                    refsToNid[f] = set()
                refsToNid[f].add(nid)
            # end new
            allRefs.update(noteRefs)

        # loop through media folder
        unused = []
        if local is None:
            files = os.listdir(mdir)
        else:
            files = local
        renamedFiles = False
        dirFound = False
        warnings = []
        for file in files:
            if not local:
                if not os.path.isfile(file):
                    if self.processSubdir:
                        dir = file
                        path = [dir + '/' + f for f in os.listdir(dir)]
                        files.extend(path)
                    else:
                        # ignore directories
                        dirFound = True
                    continue

            if file.startswith("_"):
                # leading _ says to ignore file
                continue

            if self.hasIllegal(file):
                name = file.encode(sys.getfilesystemencoding(),
                                   errors="replace")
                name = str(name, sys.getfilesystemencoding())
                warnings.append(
                    _("Invalid file name, please rename: %s") % name)
                continue

            nfcFile = unicodedata.normalize("NFC", file)

            # we enforce NFC fs encoding on non-macs
            if not isMac and not local:
                if file != nfcFile:
                    # delete if we already have the NFC form, otherwise rename
                    if os.path.exists(nfcFile):
                        os.unlink(file)
                        renamedFiles = True
                    else:
                        os.rename(file, nfcFile)
                        renamedFiles = True
                    file = nfcFile

            # compare
            if nfcFile not in allRefs:
                unused.append(file)
            else:
                allRefs.discard(nfcFile)

        # if we renamed any files to nfc format, we must rerun the check
        # to make sure the renamed files are not marked as unused
        if renamedFiles:
            return self.check(local=local)

        #This line was removed in the addon, but was causing problems for
        #_ files, so it's added it back in for now.
        nohave = [x for x in allRefs if not x.startswith("_") and not isURL(x)]

        # NEW: A line here removed because it was a bug
        # New
        finder = Finder(self.col)
        alreadyMissingNids = finder.findNotes("tag:MissingMedia")
        nidsOfMissingRefs = set()
        for ref in nohave:
            nidsOfMissingRefs.update(refsToNid[ref])
            #print(f"nidsOfMissingRefs is now {nidsOfMissingRefs}")

        for nid in nidsOfMissingRefs:
            if nid not in alreadyMissingNids:
                # print(f"missing nid {nid}")
                note = Note(self.col, id=nid)
                note.addTag("MissingMedia")
                note.flush()

        for nid in alreadyMissingNids:
            if nid not in nidsOfMissingRefs:
                # print(f"not missing anymore nid {nid}")
                note = Note(self.col, id=nid)
                note.delTag("MissingMedia")
                note.flush()
        # end new

        # make sure the media DB is valid
        try:
            self.findChanges()
        except DBError:
            self._deleteDB()
        if not self.processSubdir and dirFound:
            warnings.append(
                _("Anki does not support files in subfolders of the collection.media folder."
                  ))

        return (nohave, unused, warnings)
Beispiel #9
0
def mergeNotes(note1, note2):
    """Merge note1 and note2 following the configuration rules. If they have distinct note type, fails."""
    mw.checkpoint("Merge Notes")

    model1 = note1.model()
    model2 = note2.model()
    if model1 != model2:
        showWarning(_("Please select notes of the same type to merge them"))
        return
    merged_note = Note(mw.col, note1.model())
    new_nid = merge_id(note1, note2)

    weak = maybeGetWeakNote(note1, note2)

    overwrite_patterns = [
        re.compile(p) for p in (getUserOption("Overwrite patterns", []) or [])
    ]
    for i in range(len(merged_note.fields)):
        if maybeOverwriteField(overwrite_patterns, i, note1, note2):
            continue
        elif note1 == weak:
            merged_note.fields[i] = note2.fields[
                i] if note2.fields[i] != "" else note1.fields[i]
        elif note2 == weak:
            merged_note.fields[i] = note1.fields[
                i] if note1.fields[i] != "" else note2.fields[i]
        elif note1.fields[i] != note2.fields[i] or not getUserOption(
                "When identical keep a single field", True):
            merged_note.fields[i] = note1.fields[i] + note2.fields[i]
        else:  # identical
            merged_note.fields[i] = note1.fields[i]
    cards = dict()

    # tags
    merged_note.addTag(note1.stringTags())
    merged_note.addTag(note2.stringTags())
    merged_note.addTag(f"merged merged_{note1.id} merged_{note2.id}")

    # Choosing which card to keep
    cards_to_delete = []
    for card1 in note1.cards():
        cards[card1.ord] = card1
    for card2 in note2.cards():
        ord = card2.ord
        card1 = cards.get(ord)
        if card1 is None or card1.type == CARD_NEW or card1.ivl < card2.ivl or (
                card1.ivl == card2.ivl and card1.factor < card2.factor):
            cards[ord] = card2
            cards_to_delete.append(card1)
        else:
            cards_to_delete.append(card2)

    if getUserOption("Delete original cards", False):
        mw.col._remNotes([note1.id])
        mw.col._remNotes([note2.id])
        mw.col.remCards(
            [card.id for card in cards_to_delete if card is not None],
            notes=False)

    for card in cards.values():
        if card is None:
            continue
        if not getUserOption("Delete original cards", False):
            tmp_card = Card(mw.col)
            card.id = tmp_card.id
        card.nid = new_nid
        card.flush()
    mw.col.add_note(merged_note, 1)
    tmp_nid = merged_note.id

    mw.col.db.execute("""
    update notes
    set id=?
    where id=?
    """, new_nid, merged_note.id)

    mw.col.db.execute("""
    delete from cards
    where nid=?
    """, tmp_nid)
    merged_note.id = new_nid

    tooltip(_("Notes merged"))
    return merged_note