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()
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)
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
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
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)
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"]
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)
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