Search in sources :

Example 46 with Models

use of com.ichi2.libanki.Models in project AnkiChinaAndroid by ankichinateam.

the class AnkiChinaSyncer method handleServerData.

// 35%+25%
private void handleServerData(JSONObject item) {
    mCol = CollectionHelper.getInstance().getColSafe(AnkiDroidApp.getInstance());
    CollectionHelper.getInstance().lockCollection();
    updateDialogProgress(SYNCING_DATA, "更新全局配置中", mCurrentProgress + 1);
    DB db = mCol.getDb();
    try {
        JSONObject remoteCol = item.getJSONObject("col").getJSONObject("replace");
        // db.execute("update col set id ="+remoteCol.getInt("id")+","+"set crt =\"+remoteCol.getLong(\"crt\")");
        // db.execute("update col set crt ="+remoteCol.getLong("crt"));
        // db.execute("update col set mod ="+remoteCol.getLong("mod"));
        // db.execute("update col set scm ="+remoteCol.getLong("scm"));
        // db.execute("update col set ver ="+remoteCol.getInt("ver"));
        // db.execute("update col set dty ="+remoteCol.getInt("dty"));
        // db.execute("update col set usn ="+remoteCol.getInt("usn"));
        // db.execute("update col set ls ="+remoteCol.getLong("ls"));
        // db.execute("update col set conf ="+remoteCol.getString("conf"));
        // db.execute("update col set tags ="+remoteCol.getString("tags"));
        // db.execute("update col set tags ="+remoteCol.getString("tags"));
        // db.execute("update col set id = %d,");
        Timber.i("remote col config:%s", remoteCol.toString());
        @SuppressLint("DefaultLocale") String sql = String.format("update col set id = %d,crt = %d,mod=%d,scm=%d,ver=%d,dty=%d,usn=%d,ls=%d,conf='%s',tags='%s'", remoteCol.getInt("id"), remoteCol.getLong("crt"), remoteCol.getLong("mod"), remoteCol.getLong("scm"), remoteCol.getInt("ver"), remoteCol.getInt("dty"), remoteCol.getInt("usn"), remoteCol.getLong("ls"), remoteCol.getString("conf"), remoteCol.getString("tags") == null || !remoteCol.getString("tags").startsWith("{") ? "{}" : remoteCol.getString("tags"));
        db.execute(sql);
        mCol.load();
    } catch (Exception e) {
        e.printStackTrace();
    }
    Decks currentDecks = mCol.getDecks();
    // 删除多余的内容
    try {
        JSONArray deletedDecks = item.getJSONObject("decks").getJSONArray("delete");
        if (deletedDecks.length() > 0) {
            double percent = 2.0 / deletedDecks.length();
            for (int i = 0; i < deletedDecks.length(); i++) {
                String deckID = deletedDecks.getString(i);
                currentDecks.rem(Long.parseLong(deckID));
                updateDialogProgress(SYNCING_DATA, "删除多余牌组中", mCurrentProgress + percent);
            }
            mCol.save();
        }
    } catch (Exception e) {
    // e.printStackTrace();
    }
    try {
        JSONArray deletedDConf = item.getJSONObject("dconf").getJSONArray("delete");
        if (deletedDConf.length() > 0) {
            double percent = 2.0 / deletedDConf.length();
            for (int i = 0; i < deletedDConf.length(); i++) {
                String id = deletedDConf.getString(i);
                mCol.getDecks().remConf(Long.parseLong(id));
                updateDialogProgress(SYNCING_DATA, "删除多余牌组配置中", mCurrentProgress + percent);
            }
            mCol.save();
        }
    } catch (Exception e) {
    // e.printStackTrace();
    }
    try {
        JSONArray deletedModel = item.getJSONObject("models").getJSONArray("delete");
        if (deletedModel.length() > 0) {
            double percent = 2.0 / deletedModel.length();
            for (int i = 0; i < deletedModel.length(); i++) {
                String id = deletedModel.getString(i);
                mCol.getModels().rem(mCol.getModels().get(Long.parseLong(id)));
                updateDialogProgress(SYNCING_DATA, "删除多余模板中", mCurrentProgress + percent);
            }
            mCol.save();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    updateDialogProgress(SYNCING_DATA, "删除多余卡牌中", mCurrentProgress + 2);
    try {
        JSONArray deletedCards = item.getJSONObject("cards").getJSONArray("delete");
        List<Long> sids = ids2longList(deletedCards);
        Timber.e("need delete cards num:%s", sids.size());
        // db.execute("DELETE FROM cards WHERE id IN " + sids);
        mCol.remCards(sids);
        mCol.save();
    } catch (Exception e) {
        e.printStackTrace();
    }
    updateDialogProgress(SYNCING_DATA, "删除多余笔记中", mCurrentProgress + 2);
    try {
        JSONArray deletedNotes = item.getJSONObject("notes").getJSONArray("delete");
        long[] sids = ids2longArray(deletedNotes);
        // db.execute("DELETE FROM notes WHERE id IN " + sids);
        mCol.remNotes(sids);
        mCol.save();
    } catch (Exception e) {
        e.printStackTrace();
    }
    try {
        JSONObject replaceDecks = item.getJSONObject("decks").getJSONObject("replace");
        if (replaceDecks.length() > 0) {
            double percent = 2.0 / replaceDecks.length();
            Iterator<String> it = replaceDecks.keys();
            while (it.hasNext()) {
                String next = it.next();
                try {
                    // mCol.getDecks().getDecks().put(Long.parseLong(next), new Deck(replaceDecks.getJSONObject(next)));
                    mCol.getDecks().update(new Deck(replaceDecks.getJSONObject(next)));
                    updateDialogProgress(SYNCING_DATA, "同步牌组数据中", mCurrentProgress + percent);
                } catch (Exception e) {
                // 只遍历model id
                }
            }
            mCol.save();
        }
    } catch (Exception e) {
    // e.printStackTrace();
    }
    db.getDatabase().beginTransaction();
    try {
        JSONArray replace = item.getJSONObject("revlog").getJSONArray("replace");
        if (replace.length() > 0) {
            for (int i = 0; i < replace.length(); i++) {
                log(replace.getJSONArray(i).get(0), replace.getJSONArray(i).get(1), replace.getJSONArray(i).get(2), replace.getJSONArray(i).get(3), replace.getJSONArray(i).get(4), replace.getJSONArray(i).get(5), replace.getJSONArray(i).get(6), replace.getJSONArray(i).get(7), replace.getJSONArray(i).get(8));
            }
            db.getDatabase().setTransactionSuccessful();
            mCol.save();
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        db.getDatabase().endTransaction();
    }
    // Timber.e("看看是null还是null:%s,%s", (item.getJSONObject("dconf").get("replace")==JSONObject.NULL), (item.getJSONObject("dconf").getString("replace").equals("null")));
    try {
        JSONObject replaceDConf = item.getJSONObject("dconf").getJSONObject("replace");
        if (replaceDConf.length() > 0) {
            double percent = 2.0 / replaceDConf.length();
            Iterator<String> it = replaceDConf.keys();
            while (it.hasNext()) {
                String next = it.next();
                try {
                    Long.parseLong(next);
                    mCol.getDecks().updateConf(new DeckConfig(replaceDConf.getJSONObject(next)));
                    updateDialogProgress(SYNCING_DATA, "同步牌组配置数据中", mCurrentProgress + percent);
                } catch (Exception e) {
                // 只遍历model id
                }
            }
            mCol.save();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    try {
        JSONObject replaceModels = item.getJSONObject("models").getJSONObject("replace");
        if (replaceModels.length() > 0) {
            double percent = 5.0 / replaceModels.length();
            Iterator<String> it = replaceModels.keys();
            while (it.hasNext()) {
                String next = it.next();
                try {
                    Long.parseLong(next);
                    mCol.getModels().update(new Model(replaceModels.getJSONObject(next)));
                    updateDialogProgress(SYNCING_DATA, "同步模板数据中", mCurrentProgress + percent);
                } catch (Exception e) {
                // 只遍历model id
                }
            }
            mCol.save();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    db.getDatabase().beginTransaction();
    try {
        JSONArray replace = item.getJSONObject("notes").getJSONArray("replace");
        if (replace.length() > 0) {
            double percent = mPullNotesPerPercent / replace.length();
            for (int i = 0; i < replace.length(); i++) {
                // String values = replace.getJSONArray(i).toString().replace("[", "").replace("]", "").replaceAll("\"","'").replaceAll("\u001f","\u001f");
                // String sql = "replace into notes(id,guid,mid,mod,usn,tags,flds,sfld,csum,flags,data) values ( " + values + ")";
                // 
                db.execute("insert or replace into notes values (?,?,?,?,?,?,?,?,?,?,?)", replace.getJSONArray(i).get(0), replace.getJSONArray(i).get(1), replace.getJSONArray(i).get(2), replace.getJSONArray(i).get(3), replace.getJSONArray(i).get(4), replace.getJSONArray(i).get(5), replace.getJSONArray(i).get(6), replace.getJSONArray(i).get(7), replace.getJSONArray(i).get(8), replace.getJSONArray(i).get(9), replace.getJSONArray(i).get(10));
                updateDialogProgress(SYNCING_DATA, "同步笔记数据中", mCurrentProgress + percent);
            }
            db.getDatabase().setTransactionSuccessful();
            mCol.save();
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        db.getDatabase().endTransaction();
    }
    db.getDatabase().beginTransaction();
    try {
        JSONArray replace = item.getJSONObject("cards").getJSONArray("replace");
        if (replace.length() > 0) {
            double percent = 5.0 / replace.length();
            for (int i = 0; i < replace.length(); i++) {
                // String values = replace.getJSONArray(i).toString().replace("[", "").replace("]", "").replaceAll("\"","'").replaceAll("\u001f","\u001f");
                // String sql = "replace into cards(id,nid,did,ord,mod,usn,type,queue,due,ivl,factor,reps,lapses,left,odue,odid,flags,data) values ( " + values + ")";
                // Timber.i("update dialog progress:%d", percent);
                db.execute("insert or replace into cards values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", replace.getJSONArray(i).get(0), replace.getJSONArray(i).get(1), replace.getJSONArray(i).get(2), replace.getJSONArray(i).get(3), replace.getJSONArray(i).get(4), replace.getJSONArray(i).get(5), replace.getJSONArray(i).get(6), replace.getJSONArray(i).get(7), replace.getJSONArray(i).get(8), replace.getJSONArray(i).get(9), replace.getJSONArray(i).get(10), replace.getJSONArray(i).get(11), replace.getJSONArray(i).get(12), replace.getJSONArray(i).get(13), replace.getJSONArray(i).get(14), replace.getJSONArray(i).get(15), replace.getJSONArray(i).get(16), replace.getJSONArray(i).get(17));
                updateDialogProgress(SYNCING_DATA, "同步卡牌数据中", mCurrentProgress + percent);
            }
            db.getDatabase().setTransactionSuccessful();
            mCol.save();
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        db.getDatabase().endTransaction();
    }
    CollectionHelper.getInstance().unlockCollection();
}
Also used : Decks(com.ichi2.libanki.Decks) JSONArray(com.ichi2.utils.JSONArray) Deck(com.ichi2.libanki.Deck) FileNotFoundException(java.io.FileNotFoundException) SQLiteConstraintException(android.database.sqlite.SQLiteConstraintException) IOException(java.io.IOException) SuppressLint(android.annotation.SuppressLint) JSONObject(com.ichi2.utils.JSONObject) Model(com.ichi2.libanki.Model) SuppressLint(android.annotation.SuppressLint) DB(com.ichi2.libanki.DB) DeckConfig(com.ichi2.libanki.DeckConfig)

Example 47 with Models

use of com.ichi2.libanki.Models in project AnkiChinaAndroid by ankichinateam.

the class Syncer method changes.

/**
 * Bundle up small objects.
 */
public JSONObject changes() {
    JSONObject o = new JSONObject();
    o.put("models", getModels());
    o.put("decks", getDecks());
    o.put("tags", getTags());
    if (mLNewer) {
        o.put("conf", getConf());
        o.put("crt", mCol.getCrt());
    }
    return o;
}
Also used : JSONObject(com.ichi2.utils.JSONObject)

Example 48 with Models

use of com.ichi2.libanki.Models in project AnkiChinaAndroid by ankichinateam.

the class Collection method fixIntegrity.

/**
 * Fix possible problems and rebuild caches.
 */
public CheckDatabaseResult fixIntegrity(CollectionTask.ProgressCallback progressCallback) {
    File file = new File(mPath);
    CheckDatabaseResult result = new CheckDatabaseResult(file.length());
    final int[] currentTask = { 1 };
    // a few fixes are in all-models loops, the rest are one-offs
    int totalTasks = (getModels().all().size() * 4) + 27;
    Runnable notifyProgress = progressCallback == null ? null : () -> fixIntegrityProgress(progressCallback, currentTask[0]++, totalTasks);
    FunctionalInterfaces.Consumer<FunctionalInterfaces.FunctionThrowable<Runnable, List<String>, JSONException>> executeIntegrityTask = (FunctionalInterfaces.FunctionThrowable<Runnable, List<String>, JSONException> function) -> {
        // DEFECT: notifyProgress will lag if an exception is thrown.
        try {
            mDb.getDatabase().beginTransaction();
            if (notifyProgress != null)
                result.addAll(function.apply(notifyProgress));
            mDb.getDatabase().setTransactionSuccessful();
        } catch (Exception e) {
            Timber.e(e, "Failed to execute integrity check");
            AnkiDroidApp.sendExceptionReport(e, "fixIntegrity");
        } finally {
            try {
                mDb.getDatabase().endTransaction();
            } catch (Exception e) {
                Timber.e(e, "Failed to end integrity check transaction");
                AnkiDroidApp.sendExceptionReport(e, "fixIntegrity - endTransaction");
            }
        }
    };
    try {
        mDb.getDatabase().beginTransaction();
        save();
        notifyProgress.run();
        if (!mDb.getDatabase().isDatabaseIntegrityOk()) {
            return result.markAsFailed();
        }
        mDb.getDatabase().setTransactionSuccessful();
    } catch (SQLiteDatabaseLockedException ex) {
        Timber.e("doInBackgroundCheckDatabase - Database locked");
        return result.markAsLocked();
    } catch (RuntimeException e) {
        Timber.e(e, "doInBackgroundCheckDatabase - RuntimeException on marking card");
        AnkiDroidApp.sendExceptionReport(e, "doInBackgroundCheckDatabase");
        return result.markAsFailed();
    } finally {
        // if the database was locked, we never got the transaction.
        if (mDb.getDatabase().inTransaction()) {
            mDb.getDatabase().endTransaction();
        }
    }
    executeIntegrityTask.consume(this::deleteNotesWithMissingModel);
    // for each model
    for (JSONObject m : getModels().all()) {
        executeIntegrityTask.consume((callback) -> deleteCardsWithInvalidModelOrdinals(callback, m));
        executeIntegrityTask.consume((callback) -> deleteNotesWithWrongFieldCounts(callback, m));
    }
    executeIntegrityTask.consume(this::deleteNotesWithMissingCards);
    executeIntegrityTask.consume(this::deleteCardsWithMissingNotes);
    executeIntegrityTask.consume(this::removeOriginalDuePropertyWhereInvalid);
    executeIntegrityTask.consume(this::removeDynamicPropertyFromNonDynamicDecks);
    executeIntegrityTask.consume(this::removeDeckOptionsFromDynamicDecks);
    executeIntegrityTask.consume(this::resetInvalidDeckOptions);
    executeIntegrityTask.consume(this::rebuildTags);
    executeIntegrityTask.consume(this::updateFieldCache);
    executeIntegrityTask.consume(this::fixNewCardDuePositionOverflow);
    executeIntegrityTask.consume(this::resetNewCardInsertionPosition);
    executeIntegrityTask.consume(this::fixExcessiveReviewDueDates);
    // v2 sched had a bug that could create decimal intervals
    executeIntegrityTask.consume(this::fixDecimalCardsData);
    executeIntegrityTask.consume(this::fixDecimalRevLogData);
    executeIntegrityTask.consume(this::restoreMissingDatabaseIndices);
    executeIntegrityTask.consume(this::ensureModelsAreNotEmpty);
    executeIntegrityTask.consume((progressNotifier) -> this.ensureCardsHaveHomeDeck(progressNotifier, result));
    // and finally, optimize (unable to be done inside transaction).
    try {
        optimize(notifyProgress);
    } catch (Exception e) {
        Timber.e(e, "optimize");
        AnkiDroidApp.sendExceptionReport(e, "fixIntegrity - optimize");
    }
    file = new File(mPath);
    long newSize = file.length();
    result.setNewSize(newSize);
    // if any problems were found, force a full sync
    if (result.hasProblems()) {
        modSchemaNoCheck();
    }
    logProblems(result.getProblems());
    return result;
}
Also used : SQLiteDatabaseLockedException(android.database.sqlite.SQLiteDatabaseLockedException) JSONException(com.ichi2.utils.JSONException) SuppressLint(android.annotation.SuppressLint) JSONException(com.ichi2.utils.JSONException) SQLiteDatabaseLockedException(android.database.sqlite.SQLiteDatabaseLockedException) ConfirmModSchemaException(com.ichi2.anki.exception.ConfirmModSchemaException) IOException(java.io.IOException) NoSuchDeckException(com.ichi2.libanki.exception.NoSuchDeckException) JSONObject(com.ichi2.utils.JSONObject) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) File(java.io.File) FunctionalInterfaces(com.ichi2.utils.FunctionalInterfaces)

Example 49 with Models

use of com.ichi2.libanki.Models in project AnkiChinaAndroid by ankichinateam.

the class Models method flush.

/**
 * Flush the registry if any models were changed.
 */
public void flush() {
    if (mChanged) {
        ensureNotEmpty();
        JSONObject array = new JSONObject();
        for (Map.Entry<Long, Model> o : mModels.entrySet()) {
            array.put(Long.toString(o.getKey()), o.getValue());
        }
        ContentValues val = new ContentValues();
        val.put("models", Utils.jsonToString(array));
        mCol.getDb().update("col", val);
        mChanged = false;
    }
}
Also used : ContentValues(android.content.ContentValues) JSONObject(com.ichi2.utils.JSONObject) HashMap(java.util.HashMap) Map(java.util.Map)

Example 50 with Models

use of com.ichi2.libanki.Models in project AnkiChinaAndroid by ankichinateam.

the class ZipFile method exportInto.

/**
 * Export source database into new destination database Note: The following python syntax isn't supported in
 * Android: for row in mSrc.db.execute("select * from cards where id in "+ids2str(cids)): therefore we use a
 * different method for copying tables
 *
 * @param path String path to destination database
 * @throws JSONException
 * @throws IOException
 */
public void exportInto(String path, Context context) throws JSONException, IOException, ImportExportException {
    // create a new collection at the target
    new File(path).delete();
    Collection dst = Storage.Collection(context, path);
    mSrc = mCol;
    // find cards
    Long[] cids = cardIds();
    // attach dst to src so we can copy data between them. This isn't done in original libanki as Python more
    // flexible
    dst.close();
    Timber.d("Attach DB");
    mSrc.getDb().getDatabase().execSQL("ATTACH '" + path + "' AS DST_DB");
    // copy cards, noting used nids (as unique set)
    Timber.d("Copy cards");
    mSrc.getDb().getDatabase().execSQL("INSERT INTO DST_DB.cards select * from cards where id in " + Utils.ids2str(cids));
    Set<Long> nids = new HashSet<>(mSrc.getDb().queryLongList("select nid from cards where id in " + Utils.ids2str(cids)));
    // notes
    Timber.d("Copy notes");
    ArrayList<Long> uniqueNids = new ArrayList<>(nids);
    String strnids = Utils.ids2str(uniqueNids);
    mSrc.getDb().getDatabase().execSQL("INSERT INTO DST_DB.notes select * from notes where id in " + strnids);
    // remove system tags if not exporting scheduling info
    if (!mIncludeSched) {
        Timber.d("Stripping system tags from list");
        ArrayList<String> srcTags = mSrc.getDb().queryStringList("select tags from notes where id in " + strnids);
        ArrayList<Object[]> args = new ArrayList<>(srcTags.size());
        Object[] arg = new Object[2];
        for (int row = 0; row < srcTags.size(); row++) {
            arg[0] = removeSystemTags(srcTags.get(row));
            arg[1] = uniqueNids.get(row);
            args.add(row, arg);
        }
        mSrc.getDb().executeMany("UPDATE DST_DB.notes set tags=? where id=?", args);
    }
    // models used by the notes
    Timber.d("Finding models used by notes");
    ArrayList<Long> mids = mSrc.getDb().queryLongList("select distinct mid from DST_DB.notes where id in " + strnids);
    // card history and revlog
    if (mIncludeSched) {
        Timber.d("Copy history and revlog");
        mSrc.getDb().getDatabase().execSQL("insert into DST_DB.revlog select * from revlog where cid in " + Utils.ids2str(cids));
        // reopen collection to destination database (different from original python code)
        mSrc.getDb().getDatabase().execSQL("DETACH DST_DB");
        dst.reopen();
    } else {
        Timber.d("Detaching destination db and reopening");
        // first reopen collection to destination database (different from original python code)
        mSrc.getDb().getDatabase().execSQL("DETACH DST_DB");
        dst.reopen();
        // then need to reset card state
        Timber.d("Resetting cards");
        dst.getSched().resetCards(cids);
    }
    // models - start with zero
    Timber.d("Copy models");
    for (Model m : mSrc.getModels().all()) {
        if (mids.contains(m.getLong("id"))) {
            Timber.d("Copy models:%s", m.getLong("id"));
            dst.getModels().update(m);
        }
    }
    for (Model m : dst.getModels().all()) {
        Timber.d("check dst model:%s", m.getLong("id"));
    }
    // decks
    Timber.d("Copy decks");
    ArrayList<Long> dids = new ArrayList<>();
    if (mDid != null) {
        dids.add(mDid);
        for (Long x : mSrc.getDecks().children(mDid).values()) {
            dids.add(x);
        }
    }
    JSONObject dconfs = new JSONObject();
    for (Deck d : mSrc.getDecks().all()) {
        if ("1".equals(d.getString("id"))) {
            continue;
        }
        if (mDid != null && !dids.contains(d.getLong("id"))) {
            continue;
        }
        if (d.getInt("dyn") != 1 && d.getLong("conf") != 1L) {
            if (mIncludeSched) {
                dconfs.put(Long.toString(d.getLong("conf")), true);
            }
        }
        Deck destinationDeck = d.deepClone();
        if (!mIncludeSched) {
            // scheduling not included, so reset deck settings to default
            destinationDeck.put("conf", 1);
        }
        dst.getDecks().update(destinationDeck);
    }
    // copy used deck confs
    Timber.d("Copy deck options");
    for (DeckConfig dc : mSrc.getDecks().allConf()) {
        if (dconfs.has(dc.getString("id"))) {
            dst.getDecks().updateConf(dc);
        }
    }
    // find used media
    Timber.d("Find used media");
    JSONObject media = new JSONObject();
    mMediaDir = mSrc.getMedia().dir();
    if (mIncludeMedia) {
        ArrayList<Long> mid = mSrc.getDb().queryLongList("select mid from notes where id in " + strnids);
        ArrayList<String> flds = mSrc.getDb().queryStringList("select flds from notes where id in " + strnids);
        for (int idx = 0; idx < mid.size(); idx++) {
            for (String file : mSrc.getMedia().filesInStr(mid.get(idx), flds.get(idx))) {
                // skip files in subdirs
                if (file.contains(File.separator)) {
                    continue;
                }
                media.put(file, true);
            }
        }
        if (mMediaDir != null) {
            for (File f : new File(mMediaDir).listFiles()) {
                if (f.isDirectory()) {
                    continue;
                }
                String fname = f.getName();
                if (fname.startsWith("_")) {
                    // Loop through every model that will be exported, and check if it contains a reference to f
                    for (JSONObject model : mSrc.getModels().all()) {
                        if (_modelHasMedia(model, fname)) {
                            media.put(fname, true);
                            break;
                        }
                    }
                }
            }
        }
    }
    JSONArray keys = media.names();
    if (keys != null) {
        for (int i = 0; i < keys.length(); i++) {
            mMediaFiles.add(keys.getString(i));
        }
    }
    Timber.d("Cleanup");
    dst.setCrt(mSrc.getCrt());
    // todo: tags?
    mCount = dst.cardCount();
    dst.setMod();
    postExport();
    dst.close();
}
Also used : ArrayList(java.util.ArrayList) JSONArray(com.ichi2.utils.JSONArray) JSONObject(com.ichi2.utils.JSONObject) JSONObject(com.ichi2.utils.JSONObject) File(java.io.File) HashSet(java.util.HashSet)

Aggregations

JSONObject (com.ichi2.utils.JSONObject)48 Model (com.ichi2.libanki.Model)28 JSONArray (com.ichi2.utils.JSONArray)26 Test (org.junit.Test)26 Collection (com.ichi2.libanki.Collection)25 RobolectricTest (com.ichi2.anki.RobolectricTest)16 Note (com.ichi2.libanki.Note)16 JSONException (com.ichi2.utils.JSONException)13 ArrayList (java.util.ArrayList)13 Card (com.ichi2.libanki.Card)11 Models (com.ichi2.libanki.Models)11 SuppressLint (android.annotation.SuppressLint)10 ConfirmModSchemaException (com.ichi2.anki.exception.ConfirmModSchemaException)7 ModelManager (com.ichi2.libanki.ModelManager)7 File (java.io.File)6 HashMap (java.util.HashMap)6 List (java.util.List)6 Map (java.util.Map)6 ContentValues (android.content.ContentValues)5 NonNull (androidx.annotation.NonNull)5