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 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 _(nid): note = col.getNote(nid) model = note._model # Create new note note_copy = Note(col, model=model) # Copy tags and fields (all model fields) from original note note_copy.tags = note.tags note_copy.fields = note.fields new_id = timestampID(note.col.db, "notes", note.id) note_copy.id = new_id # Refresh note and add to database note_copy.flush() col.addNote(note_copy) nid_copy = note_copy.id cards_copy = note_copy.cards() cards = note.cards() ord_to_card = {card.ord: card for card in cards} ord_to_card_copy = {card.ord: card for card in cards_copy} for card in cards: ord = card.ord card_copy = ord_to_card_copy.get(ord) if card_copy: card.id = card_copy.id card.nid = nid_copy else: card.id = timestampID(col.db, "cards") card.nid = nid_copy card.flush() return new_id
def _save_mask_and_add_note(self, note_number, mask): mask_path = self._save_mask(mask, note_number) editor_note = self.current_editor.note #see anki.collection._Collection#_newCard model = mw.col.models.byName('PicOcc') #Have to do this as not corrent if first card # editor_note.model()['did'] did = self.current_editor.parentWindow.deckChooser.selectedId() model['did'] = did def field_content(field_name): return editor_note[field_name] if field_name in editor_note else u'' new_note = Note(mw.col, model) def fname2img(path): return '<img src="%s" />' % os.path.split(path)[1] #This is all highly specific to my own workflow/note models etc #but it should not break extra_field = field_content( u'Extra') if self.kbd_modifiers["ctrl"] else u'' intro_field = editor_note.fields[0] if self.kbd_modifiers[ "shift"] else u'' new_note.fields = [('%s' % new_note.id), fname2img(self.image_path), extra_field, field_content(u'Context'), intro_field, field_content(u'RefLink'), fname2img(mask_path)] new_note.tags = copy.copy(editor_note.tags) mw.col.addNote(new_note)
def _save_mask_and_add_note(self, note_number, mask): mask_path = self._save_mask(mask, note_number) editor_note = self.current_editor.note #see anki.collection._Collection#_newCard model = mw.col.models.byName('PicOcc') #Have to do this as not corrent if first card # editor_note.model()['did'] did = self.current_editor.parentWindow.deckChooser.selectedId() model['did'] = did def field_content(field_name): return editor_note[field_name] if field_name in editor_note else u'' new_note = Note(mw.col, model) def fname2img(path): return '<img src="%s" />' % os.path.split(path)[1] #This is all highly specific to my own workflow/note models etc #but it should not break extra_field = field_content(u'Extra') if self.kbd_modifiers["ctrl"] else u'' intro_field = editor_note.fields[0] if self.kbd_modifiers["shift"] else u'' new_note.fields = [('%s' % new_note.id), fname2img(self.image_path), extra_field, field_content(u'Context'), intro_field, field_content(u'RefLink'), fname2img(mask_path)] new_note.tags = copy.copy(editor_note.tags) mw.col.addNote(new_note)
def dupNote(self, note, model, deckId): ''' Parameters should be objects (not IDs) Returns the new note, or None on failure ''' mw.col.models.setCurrent(model) # TODO: To really copy the whole thing, not just the data fields, we could # deepcopy the whole note, then get unique IDs by creating a temp Note just to steal its id and guid, # then delete the temp note. (I tried that and couldn't get it to work, so far.) ''' n2tmp = Note(mw.col, model) n2 = copy.deepcopy(note) n2.id = n2tmp.id n2.guid = n2tmp.guid del n2tmp # just being explicit # overwrite model info n2._model = model n2.mid = model['id'] ''' n2 = Note(mw.col, model) assert( len(n2.model()['flds']) >= len(note.fields) ) # copy data n2.fields = copy.deepcopy(note.fields) n2.tags = copy.deepcopy(note.tags) # anything else?? n2.flush(intTime()) #save #n2.load() # Copying its cards technically shouldn't be necessary since they should auto-generate. (Make sure they do? Orphaned notes are inaccessible in Anki's UI.) # It would be nice to copy c.queue , at least if it's -1 (suspended) # But we do need actual cards in order to specify a target deck. cardCount = mw.col.addNote(n2) if cardCount: q = "select distinct cards.id from cards where cards.nid = %s" % (n2.id) cards = mw.col.db.list(q) for cid in cards: c = mw.col.getCard(cid) c.did = deckId # Move card into the target deck c.flush() self.cardsCopied += 1 return n2 self.errors.add('Copy Note failed.') self.errorCount += 1 print "Copy failed for: %s" % note return None
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 doImport(self): logDebug('beginning import') currentProfileDeckId = self.currentProfileDeckCombo.itemData( self.currentProfileDeckCombo.currentIndex()) logDebug('current profile deck id %d' % currentProfileDeckId) # get the note ids of all selected notes noteIds = [ self.noteListModel.itemFromIndex(idx).data() for idx in self.noteListView.selectedIndexes() ] # clear the selection self.noteListView.clearSelection() logDebug('importing %d notes' % len(noteIds)) statSuccess = 0 statNoMatchingModel = 0 statDupe = 0 for nid in noteIds: # load the note logDebug('import note id %d' % nid) otherNote = self.otherProfileCollection.getNote(nid) # find the model name of the note modelName = otherNote._model['name'] logDebug('model name %r' % modelName) # find a model in current profile that matches the name of model from other profile matchingModel = mw.col.models.byName(modelName) if matchingModel: # TODO: ensure that field map is same between two models (or same length?), otherwise skip or error? logDebug('matching model found, id %s' % matchingModel['id']) else: logDebug('no matching model, copying') copiedModel = deepcopy( otherNote._model ) # do deep copy just to be safe. model is a dict, but might be nested copiedModel['id'] = None mw.col.models.add(copiedModel) matchingModel = copiedModel # create a new note object newNote = Note(mw.col, matchingModel) logDebug('new note %s %s' % (newNote.id, newNote.mid)) # set the deck that the note will generate cards into newNote.model()['did'] = currentProfileDeckId # copy field values into new note object newNote.fields = otherNote.fields[:] # list of strings, so clone it # check if note is dupe of existing one if newNote.dupeOrEmpty(): logDebug('dupe') statDupe += 1 continue # check if there are any media files referenced by the note mediaFiles = self.otherProfileCollection.media.filesInStr( otherNote.mid, otherNote.joinedFields()) logDebug('mediaFiles %s' % (mediaFiles, )) for fn in mediaFiles: fullfn = os.path.join(self.otherProfileCollection.media.dir(), fn) # referenced media might not exist, in which case we skip it if not os.path.exists(fullfn): continue logDebug('copying from %s' % fullfn) addedFn = mw.col.media.addFile(fullfn) # NOTE: addedFn may differ from fn (name conflict, different contents), in which case we need to update the note. if addedFn != fn: logDebug('name conflict') newNote.fields = [ f.replace(fn, addedFn) for f in newNote.fields ] addedCardCount = mw.col.addNote(newNote) statSuccess += 1 if statSuccess: mw.requireReset() if statSuccess: self.statSuccessLabel.setText('%d notes successfully imported' % statSuccess) self.statSuccessLabel.show() else: self.statSuccessLabel.hide() if statNoMatchingModel: self.statNoMatchingModelLabel.setText( '%d notes failed to import because there is no matching Note Type in the current profile' % statNoMatchingModel) self.statNoMatchingModelLabel.show() else: self.statNoMatchingModelLabel.hide() if statDupe: self.statDupeLabel.setText( '%d notes were duplicates, and skipped' % statDupe) self.statDupeLabel.show() else: self.statDupeLabel.hide()