Exemple #1
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)
Exemple #2
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()
Exemple #3
0
    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
Exemple #4
0
    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)
Exemple #6
0
    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
Exemple #7
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
Exemple #8
0
    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()