Search in sources :

Example 16 with ModelManager

use of com.ichi2.libanki.ModelManager in project Anki-Android by ankidroid.

the class SchedV2Test method test_ordcycleV2.

@Test
public void test_ordcycleV2() throws Exception {
    Collection col = getColV2();
    // add two more templates and set second active
    Model m = col.getModels().current();
    ModelManager mm = col.getModels();
    JSONObject t = Models.newTemplate("Reverse");
    t.put("qfmt", "{{Back}}");
    t.put("afmt", "{{Front}}");
    mm.addTemplateModChanged(m, t);
    t = Models.newTemplate("f2");
    t.put("qfmt", "{{Front}}");
    t.put("afmt", "{{Back}}");
    mm.addTemplateModChanged(m, t);
    mm.save(m);
    // create a new note; it should have 3 cards
    Note note = col.newNote();
    note.setItem("Front", "1");
    note.setItem("Back", "1");
    col.addNote(note);
    assertEquals(3, col.cardCount());
    col.reset();
    // ordinals should arrive in order
    AbstractSched sched = col.getSched();
    Card c = sched.getCard();
    advanceRobolectricLooperWithSleep();
    // not upstream. But we are not expecting multiple getCard without review
    sched.answerCard(c, sched.answerButtons(c) - 1);
    assertEquals(0, c.getOrd());
    c = sched.getCard();
    advanceRobolectricLooperWithSleep();
    // not upstream. But we are not expecting multiple getCard without review
    sched.answerCard(c, sched.answerButtons(c) - 1);
    assertEquals(1, c.getOrd());
    c = sched.getCard();
    advanceRobolectricLooperWithSleep();
    // not upstream. But we are not expecting multiple getCard without review
    sched.answerCard(c, sched.answerButtons(c) - 1);
    advanceRobolectricLooperWithSleep();
    assertEquals(2, c.getOrd());
}
Also used : JSONObject(com.ichi2.utils.JSONObject) Note(com.ichi2.libanki.Note) Model(com.ichi2.libanki.Model) Collection(com.ichi2.libanki.Collection) ModelManager(com.ichi2.libanki.ModelManager) Card(com.ichi2.libanki.Card) RobolectricTest(com.ichi2.anki.RobolectricTest) Test(org.junit.Test)

Example 17 with ModelManager

use of com.ichi2.libanki.ModelManager in project Anki-Android by ankidroid.

the class CardContentProvider method query.

@Override
public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String order) {
    if (!hasReadWritePermission() && shouldEnforceQueryOrInsertSecurity()) {
        throwSecurityException("query", uri);
    }
    Collection col = CollectionHelper.getInstance().getCol(mContext);
    if (col == null) {
        throw new IllegalStateException(COL_NULL_ERROR_MSG);
    }
    Timber.d(getLogMessage("query", uri));
    // Find out what data the user is requesting
    int match = sUriMatcher.match(uri);
    switch(match) {
        case NOTES_V2:
            {
                /* Search for notes using direct SQL query */
                String[] proj = sanitizeNoteProjection(projection);
                String sql = SQLiteQueryBuilder.buildQueryString(false, "notes", proj, selection, null, null, order, null);
                // Needed for varargs of query
                return col.getDb().query(sql, (Object[]) selectionArgs);
            }
        case NOTES:
            {
                /* Search for notes using the libanki browser syntax */
                String[] proj = sanitizeNoteProjection(projection);
                String query = (selection != null) ? selection : "";
                List<Long> noteIds = col.findNotes(query);
                if ((noteIds != null) && (!noteIds.isEmpty())) {
                    String sel = String.format("id in (%s)", TextUtils.join(",", noteIds));
                    String sql = SQLiteQueryBuilder.buildQueryString(false, "notes", proj, sel, null, null, order, null);
                    return col.getDb().getDatabase().query(sql);
                } else {
                    return null;
                }
            }
        case NOTES_ID:
            {
                /* Direct access note with specific ID*/
                String noteId = uri.getPathSegments().get(1);
                String[] proj = sanitizeNoteProjection(projection);
                String sql = SQLiteQueryBuilder.buildQueryString(false, "notes", proj, "id=?", null, null, order, null);
                return col.getDb().query(sql, noteId);
            }
        case NOTES_ID_CARDS:
            {
                Note currentNote = getNoteFromUri(uri, col);
                String[] columns = ((projection != null) ? projection : FlashCardsContract.Card.DEFAULT_PROJECTION);
                MatrixCursor rv = new MatrixCursor(columns, 1);
                for (Card currentCard : currentNote.cards()) {
                    addCardToCursor(currentCard, rv, col, columns);
                }
                return rv;
            }
        case NOTES_ID_CARDS_ORD:
            {
                Card currentCard = getCardFromUri(uri, col);
                String[] columns = ((projection != null) ? projection : FlashCardsContract.Card.DEFAULT_PROJECTION);
                MatrixCursor rv = new MatrixCursor(columns, 1);
                addCardToCursor(currentCard, rv, col, columns);
                return rv;
            }
        case MODELS:
            {
                ModelManager models = col.getModels();
                String[] columns = ((projection != null) ? projection : FlashCardsContract.Model.DEFAULT_PROJECTION);
                MatrixCursor rv = new MatrixCursor(columns, 1);
                for (Long modelId : models.getModels().keySet()) {
                    addModelToCursor(modelId, models, rv, columns);
                }
                return rv;
            }
        case MODELS_ID:
            {
                long modelId = getModelIdFromUri(uri, col);
                String[] columns = ((projection != null) ? projection : FlashCardsContract.Model.DEFAULT_PROJECTION);
                MatrixCursor rv = new MatrixCursor(columns, 1);
                addModelToCursor(modelId, col.getModels(), rv, columns);
                return rv;
            }
        case MODELS_ID_TEMPLATES:
            {
                /* Direct access model templates */
                ModelManager models = col.getModels();
                Model currentModel = models.get(getModelIdFromUri(uri, col));
                String[] columns = ((projection != null) ? projection : CardTemplate.DEFAULT_PROJECTION);
                MatrixCursor rv = new MatrixCursor(columns, 1);
                try {
                    JSONArray templates = currentModel.getJSONArray("tmpls");
                    for (int idx = 0; idx < templates.length(); idx++) {
                        JSONObject template = templates.getJSONObject(idx);
                        addTemplateToCursor(template, currentModel, idx + 1, models, rv, columns);
                    }
                } catch (JSONException e) {
                    throw new IllegalArgumentException("Model is malformed", e);
                }
                return rv;
            }
        case MODELS_ID_TEMPLATES_ID:
            {
                /* Direct access model template with specific ID */
                ModelManager models = col.getModels();
                int ord = Integer.parseInt(uri.getLastPathSegment());
                Model currentModel = models.get(getModelIdFromUri(uri, col));
                String[] columns = ((projection != null) ? projection : CardTemplate.DEFAULT_PROJECTION);
                MatrixCursor rv = new MatrixCursor(columns, 1);
                try {
                    JSONObject template = getTemplateFromUri(uri, col);
                    addTemplateToCursor(template, currentModel, ord + 1, models, rv, columns);
                } catch (JSONException e) {
                    throw new IllegalArgumentException("Model is malformed", e);
                }
                return rv;
            }
        case SCHEDULE:
            {
                String[] columns = ((projection != null) ? projection : FlashCardsContract.ReviewInfo.DEFAULT_PROJECTION);
                MatrixCursor rv = new MatrixCursor(columns, 1);
                long selectedDeckBeforeQuery = col.getDecks().selected();
                long deckIdOfTemporarilySelectedDeck = -1;
                // the number of scheduled cards to return
                int limit = 1;
                int selectionArgIndex = 0;
                // parsing the selection arguments
                if (selection != null) {
                    // split selection to get arguments like "limit=?"
                    String[] args = selection.split(",");
                    for (String arg : args) {
                        // split arguments into key ("limit") and value ("?")
                        String[] keyAndValue = arg.split("=");
                        try {
                            // check if value is a placeholder ("?"), if so replace with the next value of selectionArgs
                            String value = "?".equals(keyAndValue[1].trim()) ? selectionArgs[selectionArgIndex++] : keyAndValue[1];
                            if ("limit".equals(keyAndValue[0].trim())) {
                                limit = Integer.parseInt(value);
                            } else if ("deckID".equals(keyAndValue[0].trim())) {
                                deckIdOfTemporarilySelectedDeck = Long.parseLong(value);
                                if (!selectDeckWithCheck(col, deckIdOfTemporarilySelectedDeck)) {
                                    // if the provided deckID is wrong, return empty cursor.
                                    return rv;
                                }
                            }
                        } catch (NumberFormatException nfe) {
                            Timber.w(nfe);
                        }
                    }
                }
                // retrieve the number of cards provided by the selection parameter "limit"
                col.getSched().deferReset();
                for (int k = 0; k < limit; k++) {
                    Card currentCard = col.getSched().getCard();
                    if (currentCard == null) {
                        break;
                    }
                    int buttonCount = col.getSched().answerButtons(currentCard);
                    JSONArray buttonTexts = new JSONArray();
                    for (int i = 0; i < buttonCount; i++) {
                        buttonTexts.put(col.getSched().nextIvlStr(mContext, currentCard, i + 1));
                    }
                    addReviewInfoToCursor(currentCard, buttonTexts, buttonCount, rv, col, columns);
                }
                if (deckIdOfTemporarilySelectedDeck != -1) {
                    // if the selected deck was changed
                    // change the selected deck back to the one it was before the query
                    col.getDecks().select(selectedDeckBeforeQuery);
                }
                return rv;
            }
        case DECKS:
            {
                List<DeckDueTreeNode> allDecks = col.getSched().deckDueList();
                String[] columns = ((projection != null) ? projection : FlashCardsContract.Deck.DEFAULT_PROJECTION);
                MatrixCursor rv = new MatrixCursor(columns, allDecks.size());
                for (DeckDueTreeNode deck : allDecks) {
                    long id = deck.getDid();
                    String name = deck.getFullDeckName();
                    addDeckToCursor(id, name, getDeckCountsFromDueTreeNode(deck), rv, col, columns);
                }
                return rv;
            }
        case DECKS_ID:
            {
                /* Direct access deck */
                String[] columns = ((projection != null) ? projection : FlashCardsContract.Deck.DEFAULT_PROJECTION);
                MatrixCursor rv = new MatrixCursor(columns, 1);
                List<DeckDueTreeNode> allDecks = col.getSched().deckDueList();
                long deckId = Long.parseLong(uri.getPathSegments().get(1));
                for (DeckDueTreeNode deck : allDecks) {
                    if (deck.getDid() == deckId) {
                        addDeckToCursor(deckId, deck.getFullDeckName(), getDeckCountsFromDueTreeNode(deck), rv, col, columns);
                        return rv;
                    }
                }
                return rv;
            }
        case DECK_SELECTED:
            {
                long id = col.getDecks().selected();
                String name = col.getDecks().name(id);
                String[] columns = ((projection != null) ? projection : FlashCardsContract.Deck.DEFAULT_PROJECTION);
                MatrixCursor rv = new MatrixCursor(columns, 1);
                JSONArray counts = new JSONArray(Collections.singletonList(col.getSched().counts()));
                addDeckToCursor(id, name, counts, rv, col, columns);
                return rv;
            }
        default:
            // Unknown URI type
            throw new IllegalArgumentException("uri " + uri + " is not supported");
    }
}
Also used : JSONArray(com.ichi2.utils.JSONArray) JSONException(com.ichi2.utils.JSONException) ModelManager(com.ichi2.libanki.ModelManager) MatrixCursor(android.database.MatrixCursor) Card(com.ichi2.libanki.Card) DeckDueTreeNode(com.ichi2.libanki.sched.DeckDueTreeNode) JSONObject(com.ichi2.utils.JSONObject) Note(com.ichi2.libanki.Note) Model(com.ichi2.libanki.Model) Collection(com.ichi2.libanki.Collection) List(java.util.List) ArrayList(java.util.ArrayList)

Example 18 with ModelManager

use of com.ichi2.libanki.ModelManager in project Anki-Android by ankidroid.

the class CardContentProvider method addModelToCursor.

private void addModelToCursor(Long modelId, ModelManager models, MatrixCursor rv, String[] columns) {
    Model jsonObject = models.get(modelId);
    MatrixCursor.RowBuilder rb = rv.newRow();
    try {
        for (String column : columns) {
            switch(column) {
                case FlashCardsContract.Model._ID:
                    rb.add(modelId);
                    break;
                case FlashCardsContract.Model.NAME:
                    rb.add(jsonObject.getString("name"));
                    break;
                case FlashCardsContract.Model.FIELD_NAMES:
                    JSONArray flds = jsonObject.getJSONArray("flds");
                    String[] allFlds = new String[flds.length()];
                    for (int idx = 0; idx < flds.length(); idx++) {
                        allFlds[idx] = flds.getJSONObject(idx).optString("name", "");
                    }
                    rb.add(Utils.joinFields(allFlds));
                    break;
                case FlashCardsContract.Model.NUM_CARDS:
                    rb.add(jsonObject.getJSONArray("tmpls").length());
                    break;
                case FlashCardsContract.Model.CSS:
                    rb.add(jsonObject.getString("css"));
                    break;
                case FlashCardsContract.Model.DECK_ID:
                    // #6378 - Anki Desktop changed schema temporarily to allow null
                    rb.add(jsonObject.optLong("did", Consts.DEFAULT_DECK_ID));
                    break;
                case FlashCardsContract.Model.SORT_FIELD_INDEX:
                    rb.add(jsonObject.getLong("sortf"));
                    break;
                case FlashCardsContract.Model.TYPE:
                    rb.add(jsonObject.getLong("type"));
                    break;
                case FlashCardsContract.Model.LATEX_POST:
                    rb.add(jsonObject.getString("latexPost"));
                    break;
                case FlashCardsContract.Model.LATEX_PRE:
                    rb.add(jsonObject.getString("latexPre"));
                    break;
                case FlashCardsContract.Model.NOTE_COUNT:
                    rb.add(models.useCount(jsonObject));
                    break;
                default:
                    throw new UnsupportedOperationException("Queue \"" + column + "\" is unknown");
            }
        }
    } catch (JSONException e) {
        Timber.e(e, "Error parsing JSONArray");
        throw new IllegalArgumentException("Model " + modelId + " is malformed", e);
    }
}
Also used : Model(com.ichi2.libanki.Model) JSONArray(com.ichi2.utils.JSONArray) JSONException(com.ichi2.utils.JSONException) MatrixCursor(android.database.MatrixCursor)

Example 19 with ModelManager

use of com.ichi2.libanki.ModelManager in project Anki-Android by ankidroid.

the class DeckPicker method showStartupScreensAndDialogs.

private void showStartupScreensAndDialogs(SharedPreferences preferences, int skip) {
    // For Android 8/8.1 we want to use software rendering by default or the Reviewer UI is broken #7369
    if (CompatHelper.getSdkVersion() == Build.VERSION_CODES.O || CompatHelper.getSdkVersion() == Build.VERSION_CODES.O_MR1) {
        if (!preferences.contains("softwareRender")) {
            Timber.i("Android 8/8.1 detected with no render preference. Turning on software render.");
            preferences.edit().putBoolean("softwareRender", true).apply();
        } else {
            Timber.i("Android 8/8.1 detected, software render preference already exists.");
        }
    }
    if (!BackupManager.enoughDiscSpace(CollectionHelper.getCurrentAnkiDroidDirectory(this))) {
        Timber.i("Not enough space to do backup");
        showDialogFragment(DeckPickerNoSpaceLeftDialog.newInstance());
    } else if (preferences.getBoolean("noSpaceLeft", false)) {
        Timber.i("No space left");
        showDialogFragment(DeckPickerBackupNoSpaceLeftDialog.newInstance());
        preferences.edit().remove("noSpaceLeft").apply();
    } else if (InitialActivity.performSetupFromFreshInstallOrClearedPreferences(preferences)) {
        onFinishedStartup();
    } else if (skip < 2 && !InitialActivity.isLatestVersion(preferences)) {
        Timber.i("AnkiDroid is being updated and a collection already exists.");
        // The user might appreciate us now, see if they will help us get better?
        if (!preferences.contains(UsageAnalytics.ANALYTICS_OPTIN_KEY)) {
            displayAnalyticsOptInDialog();
        }
        // For upgrades, we check if we are upgrading
        // to a version that contains additions to the database integrity check routine that we would
        // like to run on all collections. A missing version number is assumed to be a fresh
        // installation of AnkiDroid and we don't run the check.
        long current = VersionUtils.getPkgVersionCode();
        Timber.i("Current AnkiDroid version: %s", current);
        long previous;
        if (preferences.contains(UPGRADE_VERSION_KEY)) {
            // Upgrading currently installed app
            previous = getPreviousVersion(preferences, current);
        } else {
            // Fresh install
            previous = current;
        }
        preferences.edit().putLong(UPGRADE_VERSION_KEY, current).apply();
        // It is rebuilt on the next sync or media check
        if (previous < 20300200) {
            Timber.i("Deleting media database");
            File mediaDb = new File(CollectionHelper.getCurrentAnkiDroidDirectory(this), "collection.media.ad.db2");
            if (mediaDb.exists()) {
                mediaDb.delete();
            }
        }
        // Recommend the user to do a full-sync if they're upgrading from before 2.3.1beta8
        if (previous < 20301208) {
            Timber.i("Recommend the user to do a full-sync");
            mRecommendFullSync = true;
        }
        // Fix "font-family" definition in templates created by AnkiDroid before 2.6alhpa23
        if (previous < 20600123) {
            Timber.i("Fixing font-family definition in templates");
            try {
                ModelManager models = getCol().getModels();
                for (Model m : models.all()) {
                    String css = m.getString("css");
                    if (css.contains("font-familiy")) {
                        m.put("css", css.replace("font-familiy", "font-family"));
                        models.save(m);
                    }
                }
                models.flush();
            } catch (JSONException e) {
                Timber.e(e, "Failed to upgrade css definitions.");
            }
        }
        // Check if preference upgrade or database check required, otherwise go to new feature screen
        int upgradeDbVersion = AnkiDroidApp.CHECK_DB_AT_VERSION;
        // Specifying a checkpoint in the future is not supported, please don't do it!
        if (current < upgradeDbVersion) {
            Timber.e("Invalid value for CHECK_DB_AT_VERSION");
            UIUtils.showSimpleSnackbar(this, "Invalid value for CHECK_DB_AT_VERSION", false);
            onFinishedStartup();
            return;
        }
        // Skip full DB check if the basic check is OK
        // TODO: remove this variable if we really want to do the full db check on every user
        boolean skipDbCheck = false;
        // if (previous < upgradeDbVersion && getCol().basicCheck()) {
        // skipDbCheck = true;
        // }
        boolean upgradedPreferences = InitialActivity.upgradePreferences(this, previous);
        // noinspection ConstantConditions
        if (!skipDbCheck && previous < upgradeDbVersion) {
            Timber.i("showStartupScreensAndDialogs() running integrityCheck()");
            // #5852 - since we may have a warning about disk space, we don't want to force a check database
            // and show a warning before the user knows what is happening.
            new MaterialDialog.Builder(this).title(R.string.integrity_check_startup_title).content(R.string.integrity_check_startup_content).positiveText(R.string.check_db).negativeText(R.string.close).onPositive((materialDialog, dialogAction) -> integrityCheck()).onNeutral((materialDialog, dialogAction) -> restartActivity()).onNegative((materialDialog, dialogAction) -> restartActivity()).canceledOnTouchOutside(false).cancelable(false).build().show();
            return;
        }
        if (upgradedPreferences) {
            Timber.i("Updated preferences with no integrity check - restarting activity");
            // If integrityCheck() doesn't occur, but we did update preferences we should restart DeckPicker to
            // proceed
            restartActivity();
            return;
        }
        // There the "lastVersion" is set, so that this code is not reached again
        if (VersionUtils.isReleaseVersion()) {
            Timber.i("Displaying new features");
            Intent infoIntent = new Intent(this, Info.class);
            infoIntent.putExtra(Info.TYPE_EXTRA, Info.TYPE_NEW_VERSION);
            if (skip != 0) {
                startActivityForResultWithAnimation(infoIntent, SHOW_INFO_NEW_VERSION, START);
            } else {
                startActivityForResultWithoutAnimation(infoIntent, SHOW_INFO_NEW_VERSION);
            }
        } else {
            Timber.i("Dev Build - not showing 'new features'");
            // Don't show new features dialog for development builds
            InitialActivity.setUpgradedToLatestVersion(preferences);
            String ver = getResources().getString(R.string.updated_version, VersionUtils.getPkgVersionName());
            UIUtils.showSnackbar(this, ver, true, -1, null, findViewById(R.id.root_layout), null);
            showStartupScreensAndDialogs(preferences, 2);
        }
    } else {
        // This is the main call when there is nothing special required
        Timber.i("No startup screens required");
        onFinishedStartup();
    }
}
Also used : DividerItemDecoration(androidx.recyclerview.widget.DividerItemDecoration) StartupFailure(com.ichi2.anki.InitialActivity.StartupFailure) Bundle(android.os.Bundle) NonNull(androidx.annotation.NonNull) Uri(android.net.Uri) DialogHandler(com.ichi2.anki.dialogs.DialogHandler) Drawable(android.graphics.drawable.Drawable) ShortcutManagerCompat(androidx.core.content.pm.ShortcutManagerCompat) Manifest(android.Manifest) Decks(com.ichi2.libanki.Decks) Fragment(androidx.fragment.app.Fragment) JSONException(com.ichi2.utils.JSONException) ContextCompat(androidx.core.content.ContextCompat) DeckPickerBackupNoSpaceLeftDialog(com.ichi2.anki.dialogs.DeckPickerBackupNoSpaceLeftDialog) IntentFilter(android.content.IntentFilter) Triple(com.ichi2.utils.Triple) SearchView(androidx.appcompat.widget.SearchView) DeckPickerContextMenu(com.ichi2.anki.dialogs.DeckPickerContextMenu) Cancellable(com.ichi2.async.Cancellable) DeckRenameException(com.ichi2.libanki.backend.exception.DeckRenameException) StringRes(androidx.annotation.StringRes) Unit(kotlin.Unit) Nullable(androidx.annotation.Nullable) Message(android.os.Message) HostNumFactory(com.ichi2.anki.web.HostNumFactory) CompatHelper(com.ichi2.compat.CompatHelper) DeckAdapter(com.ichi2.anki.widgets.DeckAdapter) LinearLayoutManager(androidx.recyclerview.widget.LinearLayoutManager) DeckPickerNoSpaceToDowngradeDialog(com.ichi2.anki.dialogs.DeckPickerNoSpaceToDowngradeDialog) DeckPickerConfirmDeleteDeckDialog(com.ichi2.anki.dialogs.DeckPickerConfirmDeleteDeckDialog) Direction(com.ichi2.anim.ActivityTransitionAnimation.Direction) FULL_DOWNLOAD(com.ichi2.async.Connection.ConflictResolution.FULL_DOWNLOAD) SdCardReceiver(com.ichi2.anki.receiver.SdCardReceiver) Editor(android.content.SharedPreferences.Editor) CustomSyncServerUrlException(com.ichi2.libanki.sync.CustomSyncServerUrlException) FileSizeFormatter(com.ichi2.anki.dialogs.DeckPickerNoSpaceToDowngradeDialog.FileSizeFormatter) DeckPickerNoSpaceLeftDialog(com.ichi2.anki.dialogs.DeckPickerNoSpaceLeftDialog) StudyOptionsListener(com.ichi2.anki.StudyOptionsFragment.StudyOptionsListener) BadgeDrawableBuilder(com.ichi2.ui.BadgeDrawableBuilder) Menu(android.view.Menu) DeckService(com.ichi2.anki.servicelayer.DeckService) Connection(com.ichi2.async.Connection) Settings(android.provider.Settings) AnkiPackageImporter(com.ichi2.libanki.importer.AnkiPackageImporter) SwipeRefreshLayout(androidx.swiperefreshlayout.widget.SwipeRefreshLayout) CollectionIntegrityStorageCheck(com.ichi2.anki.CollectionHelper.CollectionIntegrityStorageCheck) ActivityExportingDelegate(com.ichi2.anki.export.ActivityExportingDelegate) TextUtils(android.text.TextUtils) File(java.io.File) SharedPreferences(android.content.SharedPreferences) TypedValue(android.util.TypedValue) IconCompat(androidx.core.graphics.drawable.IconCompat) ImportUtils(com.ichi2.utils.ImportUtils) EditText(android.widget.EditText) SchedulerService(com.ichi2.anki.servicelayer.SchedulerService) LinearLayout(android.widget.LinearLayout) AsyncDialogFragment(com.ichi2.anki.dialogs.AsyncDialogFragment) PackageManager(android.content.pm.PackageManager) TaskManager(com.ichi2.async.TaskManager) WindowManager(android.view.WindowManager) UsageAnalytics(com.ichi2.anki.analytics.UsageAnalytics) ModelManager(com.ichi2.libanki.ModelManager) ConfirmationDialog(com.ichi2.anki.dialogs.ConfirmationDialog) AnkiStatsTaskHandler(com.ichi2.anki.stats.AnkiStatsTaskHandler) Permissions(com.ichi2.utils.Permissions) View(android.view.View) RecyclerView(androidx.recyclerview.widget.RecyclerView) SyncStatus(com.ichi2.utils.SyncStatus) FragmentTransaction(androidx.fragment.app.FragmentTransaction) BroadcastReceiver(android.content.BroadcastReceiver) DatabaseErrorDialog(com.ichi2.anki.dialogs.DatabaseErrorDialog) CustomStudyDialogFactory(com.ichi2.anki.dialogs.customstudy.CustomStudyDialogFactory) Timber(timber.log.Timber) UndoService(com.ichi2.anki.servicelayer.UndoService) List(java.util.List) TextView(android.widget.TextView) ImportFileSelectionFragment(com.ichi2.anki.dialogs.ImportFileSelectionFragment) RelativeLayout(android.widget.RelativeLayout) Filterable(android.widget.Filterable) TaskListenerWithContext(com.ichi2.async.TaskListenerWithContext) ViewPropertyAnimator(android.view.ViewPropertyAnimator) MaterialDialog(com.afollestad.materialdialogs.MaterialDialog) Snackbar(com.google.android.material.snackbar.Snackbar) Window(android.view.Window) VersionUtils(com.ichi2.utils.VersionUtils) Context(android.content.Context) TaskListener(com.ichi2.async.TaskListener) KeyEvent(android.view.KeyEvent) GravityEnum(com.afollestad.materialdialogs.GravityEnum) Pair(android.util.Pair) DeckPickerAnalyticsOptInDialog(com.ichi2.anki.dialogs.DeckPickerAnalyticsOptInDialog) ImportDialog(com.ichi2.anki.dialogs.ImportDialog) Intent(android.content.Intent) Collection(com.ichi2.libanki.Collection) StyledProgressDialog(com.ichi2.themes.StyledProgressDialog) PixelFormat(android.graphics.PixelFormat) TypedArray(android.content.res.TypedArray) MenuItem(android.view.MenuItem) WidgetStatus(com.ichi2.widget.WidgetStatus) SyncErrorDialog(com.ichi2.anki.dialogs.SyncErrorDialog) Payload(com.ichi2.async.Connection.Payload) Model(com.ichi2.libanki.Model) Build(android.os.Build) ShortcutInfoCompat(androidx.core.content.pm.ShortcutInfoCompat) Utils(com.ichi2.libanki.Utils) DialogInterface(android.content.DialogInterface) ConfirmModSchemaException(com.ichi2.anki.exception.ConfirmModSchemaException) Computation(com.ichi2.utils.Computation) AbstractDeckTreeNode(com.ichi2.libanki.sched.AbstractDeckTreeNode) ActivityCompat(androidx.core.app.ActivityCompat) CreateDeckDialog(com.ichi2.anki.dialogs.CreateDeckDialog) CollectionTask(com.ichi2.async.CollectionTask) SQLException(android.database.SQLException) CustomStudyDialog(com.ichi2.anki.dialogs.customstudy.CustomStudyDialog) Syncer(com.ichi2.libanki.sync.Syncer) MediaCheckDialog(com.ichi2.anki.dialogs.MediaCheckDialog) AdaptionUtil(com.ichi2.utils.AdaptionUtil) VisibleForTesting(androidx.annotation.VisibleForTesting) Resources(android.content.res.Resources) OnClickListener(android.view.View.OnClickListener) BadgeDrawableBuilder(com.ichi2.ui.BadgeDrawableBuilder) Model(com.ichi2.libanki.Model) JSONException(com.ichi2.utils.JSONException) Intent(android.content.Intent) ModelManager(com.ichi2.libanki.ModelManager) File(java.io.File)

Example 20 with ModelManager

use of com.ichi2.libanki.ModelManager in project Anki-Android by ankidroid.

the class ImportTest method addFieldToCurrentModel.

private void addFieldToCurrentModel(String fieldName) throws ConfirmModSchemaException {
    ModelManager mm = mTestCol.getModels();
    Model m = mm.current();
    JSONObject f = mm.newField(fieldName);
    mm.addField(m, f);
    mm.save(m);
}
Also used : JSONObject(com.ichi2.utils.JSONObject) Model(com.ichi2.libanki.Model) ModelManager(com.ichi2.libanki.ModelManager)

Aggregations

Test (org.junit.Test)16 JSONObject (com.ichi2.utils.JSONObject)14 RobolectricTest (com.ichi2.anki.RobolectricTest)12 Model (com.ichi2.libanki.Model)12 ModelManager (com.ichi2.libanki.ModelManager)11 Collection (com.ichi2.libanki.Collection)7 Note (com.ichi2.libanki.Note)6 JSONArray (com.ichi2.utils.JSONArray)5 JSONException (com.ichi2.utils.JSONException)4 Card (com.ichi2.libanki.Card)3 Matchers.containsString (org.hamcrest.Matchers.containsString)3 MatrixCursor (android.database.MatrixCursor)2 NonNull (androidx.annotation.NonNull)2 ConfirmModSchemaException (com.ichi2.anki.exception.ConfirmModSchemaException)2 InstrumentedTest (com.ichi2.anki.tests.InstrumentedTest)2 List (java.util.List)2 Manifest (android.Manifest)1 BroadcastReceiver (android.content.BroadcastReceiver)1 Context (android.content.Context)1 DialogInterface (android.content.DialogInterface)1