Search in sources :

Example 11 with CHANGED

use of com.ichi2.anki.CardBrowser.Column.CHANGED in project AnkiChinaAndroid by ankichinateam.

the class CollectionTask method doInBackgroundUpdateNote.

private TaskData doInBackgroundUpdateNote(TaskData param) {
    Timber.d("doInBackgroundUpdateNote");
    // Save the note
    Collection col = getCol();
    AbstractSched sched = col.getSched();
    Card editCard = param.getCard();
    Note editNote = editCard.note();
    boolean fromReviewer = param.getBoolean();
    try {
        col.getDb().getDatabase().beginTransaction();
        try {
            // TODO: undo integration
            editNote.flush();
            // flush card too, in case, did has been changed
            editCard.flush();
            if (fromReviewer) {
                Card newCard;
                if (col.getDecks().active().contains(editCard.getDid())) {
                    newCard = editCard;
                    newCard.load();
                    // reload qa-cache
                    newCard.q(true);
                } else {
                    newCard = sched.getCard();
                }
                publishProgress(new TaskData(newCard));
            } else {
                publishProgress(new TaskData(editCard, editNote.stringTags()));
            }
            col.getDb().getDatabase().setTransactionSuccessful();
        } finally {
            col.getDb().getDatabase().endTransaction();
        }
    } catch (RuntimeException e) {
        Timber.e(e, "doInBackgroundUpdateNote - RuntimeException on updating note");
        AnkiDroidApp.sendExceptionReport(e, "doInBackgroundUpdateNote");
        return new TaskData(false);
    }
    return new TaskData(true);
}
Also used : AbstractSched(com.ichi2.libanki.sched.AbstractSched) Note(com.ichi2.libanki.Note) Collection(com.ichi2.libanki.Collection) Card(com.ichi2.libanki.Card)

Example 12 with CHANGED

use of com.ichi2.anki.CardBrowser.Column.CHANGED in project AnkiChinaAndroid by ankichinateam.

the class CollectionTask method doInBackgroundDismissNotes.

private TaskData doInBackgroundDismissNotes(TaskData param) {
    Collection col = getCol();
    AbstractSched sched = col.getSched();
    Object[] data = param.getObjArray();
    long[] cardIds = (long[]) data[0];
    // query cards
    Card[] cards = new Card[cardIds.length];
    for (int i = 0; i < cardIds.length; i++) {
        cards[i] = col.getCard(cardIds[i]);
    }
    Collection.DismissType type = (Collection.DismissType) data[1];
    try {
        col.getDb().getDatabase().beginTransaction();
        try {
            switch(type) {
                case SUSPEND_CARD_MULTI:
                    {
                        // collect undo information
                        long[] cids = new long[cards.length];
                        boolean[] originalSuspended = new boolean[cards.length];
                        boolean hasUnsuspended = false;
                        for (int i = 0; i < cards.length; i++) {
                            Card card = cards[i];
                            cids[i] = card.getId();
                            if (card.getQueue() != Consts.QUEUE_TYPE_SUSPENDED) {
                                hasUnsuspended = true;
                                originalSuspended[i] = false;
                            } else {
                                originalSuspended[i] = true;
                            }
                        }
                        // otherwise unsuspend all
                        if (hasUnsuspended) {
                            sched.suspendCards(cids);
                        } else {
                            sched.unsuspendCards(cids);
                        }
                        Undoable suspendCardMulti = new UndoSuspendCardMulti(cards, originalSuspended);
                        // mark undo for all at once
                        col.markUndo(suspendCardMulti);
                        // reload cards because they'll be passed back to caller
                        for (Card c : cards) {
                            c.load();
                        }
                        sched.deferReset();
                        break;
                    }
                case FLAG:
                    {
                        int flag = (Integer) data[2];
                        col.setUserFlag(flag, cardIds);
                        for (Card c : cards) {
                            c.load();
                        }
                        break;
                    }
                case MARK_NOTE_MULTI:
                    {
                        Set<Note> notes = CardUtils.getNotes(Arrays.asList(cards));
                        // collect undo information
                        List<Note> originalMarked = new ArrayList<>();
                        List<Note> originalUnmarked = new ArrayList<>();
                        for (Note n : notes) {
                            if (n.hasTag("marked")) {
                                originalMarked.add(n);
                            } else {
                                originalUnmarked.add(n);
                            }
                        }
                        CardUtils.markAll(new ArrayList<>(notes), !originalUnmarked.isEmpty());
                        Undoable markNoteMulti = new UndoMarkNoteMulti(originalMarked, originalUnmarked);
                        // mark undo for all at once
                        col.markUndo(markNoteMulti);
                        // reload cards because they'll be passed back to caller
                        for (Card c : cards) {
                            c.load();
                        }
                        break;
                    }
                case DELETE_NOTE_MULTI:
                    {
                        // list of all ids to pass to remNotes method.
                        // Need Set (-> unique) so we don't pass duplicates to col.remNotes()
                        Set<Note> notes = CardUtils.getNotes(Arrays.asList(cards));
                        List<Card> allCards = CardUtils.getAllCards(notes);
                        // delete note
                        long[] uniqueNoteIds = new long[notes.size()];
                        Note[] notesArr = notes.toArray(new Note[notes.size()]);
                        int count = 0;
                        for (Note note : notes) {
                            uniqueNoteIds[count] = note.getId();
                            count++;
                        }
                        Undoable deleteNoteMulti = new UndoDeleteNoteMulti(notesArr, allCards);
                        col.markUndo(deleteNoteMulti);
                        col.remNotes(uniqueNoteIds);
                        sched.deferReset();
                        // pass back all cards because they can't be retrieved anymore by the caller (since the note is deleted)
                        publishProgress(new TaskData(allCards.toArray(new Card[allCards.size()])));
                        break;
                    }
                case CHANGE_DECK_MULTI:
                    {
                        long newDid = (long) data[2];
                        Timber.i("Changing %d cards to deck: '%d'", cards.length, newDid);
                        Deck deckData = col.getDecks().get(newDid);
                        if (Decks.isDynamic(deckData)) {
                            // #5932 - can't change to a dynamic deck. Use "Rebuild"
                            Timber.w("Attempted to move to dynamic deck. Cancelling task.");
                            return new TaskData(false);
                        }
                        // Confirm that the deck exists (and is not the default)
                        try {
                            long actualId = deckData.getLong("id");
                            if (actualId != newDid) {
                                Timber.w("Attempted to move to deck %d, but got %d", newDid, actualId);
                                return new TaskData(false);
                            }
                        } catch (Exception e) {
                            Timber.e(e, "failed to check deck");
                            return new TaskData(false);
                        }
                        long[] changedCardIds = new long[cards.length];
                        for (int i = 0; i < cards.length; i++) {
                            changedCardIds[i] = cards[i].getId();
                        }
                        col.getSched().remFromDyn(changedCardIds);
                        long[] originalDids = new long[cards.length];
                        for (int i = 0; i < cards.length; i++) {
                            Card card = cards[i];
                            card.load();
                            // save original did for undo
                            originalDids[i] = card.getDid();
                            // then set the card ID to the new deck
                            card.setDid(newDid);
                            Note note = card.note();
                            note.flush();
                            // flush card too, in case, did has been changed
                            card.flush();
                        }
                        Undoable changeDeckMulti = new UndoChangeDeckMulti(cards, originalDids);
                        // mark undo for all at once
                        col.markUndo(changeDeckMulti);
                        break;
                    }
                case RESCHEDULE_CARDS:
                case REPOSITION_CARDS:
                case RESET_CARDS:
                    {
                        // collect undo information, sensitive to memory pressure, same for all 3 cases
                        try {
                            Timber.d("Saving undo information of type %s on %d cards", type, cards.length);
                            Card[] cards_copied = deepCopyCardArray(cards);
                            Undoable repositionRescheduleResetCards = new UndoRepositionRescheduleResetCards(type, cards_copied);
                            col.markUndo(repositionRescheduleResetCards);
                        } catch (CancellationException ce) {
                            Timber.i(ce, "Cancelled while handling type %s, skipping undo", type);
                        }
                        switch(type) {
                            case RESCHEDULE_CARDS:
                                sched.reschedCards(cardIds, (Integer) data[2], (Integer) data[2]);
                                break;
                            case REPOSITION_CARDS:
                                sched.sortCards(cardIds, (Integer) data[2], 1, false, true);
                                break;
                            case RESET_CARDS:
                                sched.forgetCards(cardIds);
                                break;
                        }
                        // In all cases schedule a new card so Reviewer doesn't sit on the old one
                        col.reset();
                        publishProgress(new TaskData(sched.getCard(), 0));
                        break;
                    }
            }
            col.getDb().getDatabase().setTransactionSuccessful();
        } finally {
            col.getDb().getDatabase().endTransaction();
        }
    } catch (RuntimeException e) {
        Timber.e(e, "doInBackgroundSuspendCard - RuntimeException on suspending card");
        AnkiDroidApp.sendExceptionReport(e, "doInBackgroundSuspendCard");
        return new TaskData(false);
    }
    // (querying the cards again is unnecessarily expensive)
    return new TaskData(true, cards);
}
Also used : Undoable(com.ichi2.libanki.Undoable) Set(java.util.Set) AbstractSched(com.ichi2.libanki.sched.AbstractSched) ArrayList(java.util.ArrayList) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) Deck(com.ichi2.libanki.Deck) JSONException(com.ichi2.utils.JSONException) CancellationException(java.util.concurrent.CancellationException) FileNotFoundException(java.io.FileNotFoundException) ConfirmModSchemaException(com.ichi2.anki.exception.ConfirmModSchemaException) ImportExportException(com.ichi2.anki.exception.ImportExportException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) Card(com.ichi2.libanki.Card) CancellationException(java.util.concurrent.CancellationException) Note(com.ichi2.libanki.Note) Collection(com.ichi2.libanki.Collection) JSONObject(com.ichi2.utils.JSONObject)

Example 13 with CHANGED

use of com.ichi2.anki.CardBrowser.Column.CHANGED in project AnkiChinaAndroid by ankichinateam.

the class NoteService method saveMedia.

/**
 * Saves the multimedia associated with this card to proper path inside anki folder. For each field associated with
 * the note it checks for the following condition a. The field content should have changed b. The field content does
 * not already point to a media inside anki media path If both condition satisfies then it copies the file inside
 * the media path and deletes the file referenced by the note
 *
 * @param noteNew
 */
public static void saveMedia(Collection col, final MultimediaEditableNote noteNew) {
    // if (noteNew.getModelId() == noteOld.getModelId())
    // {
    // int fieldCount = noteNew.getNumberOfFields();
    // for (int i = 0; i < fieldCount; i++)
    // {
    // IField newField = noteNew.getField(i);
    // IField oldField = noteOld.getField(i);
    // if
    // (newField.getFormattedValue().equals(oldField.getFormattedValue()))
    // {
    // continue;
    // }
    // importMediaToDirectory(newField);
    // }
    // }
    // else
    // {
    int fieldCount = noteNew.getNumberOfFields();
    for (int i = 0; i < fieldCount; i++) {
        IField newField = noteNew.getField(i);
        importMediaToDirectory(col, newField);
    }
// }
}
Also used : IField(com.ichi2.anki.multimediacard.fields.IField)

Example 14 with CHANGED

use of com.ichi2.anki.CardBrowser.Column.CHANGED in project AnkiChinaAndroid by ankichinateam.

the class Utils method markAsUploaded.

/**
 *       Set usn to 0 in every object.
 *
 *       This method is called during full sync, before uploading, so
 *       during an instant, the value will be zero while the object is
 *       not actually online. This is not a problem because if the sync
 *       fails, a full sync will occur again next time.
 *
 *       @return whether there was a non-zero usn; in this case the list
 *       should be saved before the upload.
 */
public static boolean markAsUploaded(ArrayList<? extends JSONObject> ar) {
    boolean changed = false;
    for (JSONObject obj : ar) {
        if (obj.optInt("usn", 1) != 0) {
            obj.put("usn", 0);
            changed = true;
        }
    }
    return changed;
}
Also used : JSONObject(com.ichi2.utils.JSONObject)

Example 15 with CHANGED

use of com.ichi2.anki.CardBrowser.Column.CHANGED in project AnkiChinaAndroid by ankichinateam.

the class Decks method update.

/**
 * Add or update an existing deck. Used for syncing and merging.
 */
public void update(Deck g) {
    long id = g.getLong("id");
    JSONObject oldDeck = get(id, false);
    if (oldDeck != null) {
        // In case where another update got the name
        // `oldName`, it would be a mistake to remove it from nameMap
        mNameMap.remove(oldDeck.getString("name"), oldDeck);
    }
    mNameMap.add(g);
    mDecks.put(g.getLong("id"), g);
    maybeAddToActive();
    // mark registry changed, but don't bump mod time
    save();
}
Also used : JSONObject(com.ichi2.utils.JSONObject)

Aggregations

JSONObject (com.ichi2.utils.JSONObject)19 Test (org.junit.Test)19 Note (com.ichi2.libanki.Note)16 Card (com.ichi2.libanki.Card)15 Collection (com.ichi2.libanki.Collection)15 Model (com.ichi2.libanki.Model)12 Intent (android.content.Intent)9 JSONArray (com.ichi2.utils.JSONArray)9 JSONException (com.ichi2.utils.JSONException)8 List (java.util.List)7 ShadowActivity (org.robolectric.shadows.ShadowActivity)7 ArrayList (java.util.ArrayList)6 Map (java.util.Map)6 ShadowIntent (org.robolectric.shadows.ShadowIntent)6 ConfirmModSchemaException (com.ichi2.anki.exception.ConfirmModSchemaException)5 Cursor (android.database.Cursor)4 MatrixCursor (android.database.MatrixCursor)4 TaskData (com.ichi2.async.TaskData)4 Deck (com.ichi2.libanki.Deck)4 AbstractSched (com.ichi2.libanki.sched.AbstractSched)4