From aaaa9df4e2f487d1559a171d0146537dfa9e1ff4 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Sat, 14 Dec 2024 07:18:23 +0100 Subject: [PATCH] NF: rename model to note type As David mentioned recently, Anki don't use "model" anymore, it should not be in the codebase. There are two places where `model` should not be replaced. When the variable refers to a model that is not a note type (e.g. a viewModel, the Card Browser's model..). And when the word "model" appears in the API. Indeed we should not break the existing code using the API. While it may be considered to extend our API, duplicating the Model commands to introduce a NoteType command with the same meaning. And, maybe one day, deprecate the previous API. But I don't think there is even a need to deprecate the API, it does not really lead to confusion. On top of replacing "model", "models", "Model", "Models", "MODEL", "MODELS", we also rename the variables "m", "m2" and "mm" as those variable where abbreviations for "Model". I renamed some layout, menu, In one case, the documentation was wrong. It mentioned "model" instead of "template". I thus replaced "model" by "template" in order to correct the documentation. Note that all the changes were done manually. I used Android-Studio to rename function, variables, values and constant. But I generally avoided the "search and replace" feature which may have led to erroneous update. (Example of exception: `m` and `mm` in `modelTest` --- .../java/com/ichi2/anki/DeckPickerTest.kt | 2 +- .../java/com/ichi2/anki/PagesTest.kt | 4 +- .../com/ichi2/anki/ReviewerFragmentTest.kt | 4 +- .../java/com/ichi2/anki/ReviewerTest.kt | 4 +- ...st.kt => NoteTypeEditorContextMenuTest.kt} | 10 +- .../ichi2/anki/tests/ContentProviderTest.kt | 298 ++++++------- .../com/ichi2/anki/tests/InstrumentedTest.kt | 10 +- .../ichi2/anki/tests/libanki/NotetypeTest.kt | 12 +- AnkiDroid/src/main/AndroidManifest.xml | 2 +- .../com/ichi2/anki/AbstractFlashcardViewer.kt | 2 +- .../java/com/ichi2/anki/CardTemplateEditor.kt | 186 ++++---- .../com/ichi2/anki/CardTemplateNotetype.kt | 92 ++-- .../main/java/com/ichi2/anki/DeckPicker.kt | 10 +- .../src/main/java/com/ichi2/anki/MetaDB.kt | 6 +- .../main/java/com/ichi2/anki/NoteEditor.kt | 156 +++---- ...lFieldEditor.kt => NoteTypeFieldEditor.kt} | 48 +-- .../anki/browser/BrowserColumnCollection.kt | 3 - ...xtMenu.kt => NoteTypeEditorContextMenu.kt} | 14 +- .../impl/MultimediaEditableNote.kt | 2 +- .../com/ichi2/anki/noteeditor/FieldState.kt | 14 +- .../ichi2/anki/notetype/AddNewNotesType.kt | 8 +- .../ichi2/anki/notetype/ManageNotetypes.kt | 6 +- .../anki/provider/CardContentProvider.kt | 249 +++++------ .../ichi2/anki/servicelayer/NoteService.kt | 22 +- .../com/ichi2/anki/ui/NoteTypeSpinnerUtils.kt | 8 +- .../managespace/ManageSpaceFragment.kt | 2 +- .../com/ichi2/anki/utils/CardTemplateJson.kt | 4 +- .../com/ichi2/async/CollectionOperations.kt | 22 +- .../src/main/java/com/ichi2/libanki/Card.kt | 10 +- .../main/java/com/ichi2/libanki/Collection.kt | 14 +- .../src/main/java/com/ichi2/libanki/Consts.kt | 10 +- .../src/main/java/com/ichi2/libanki/Note.kt | 10 +- .../java/com/ichi2/libanki/NotetypeJson.kt | 18 +- .../main/java/com/ichi2/libanki/Notetypes.kt | 101 ++--- ..._editor.xml => note_type_field_editor.xml} | 0 ...l => note_type_field_editor_list_item.xml} | 0 .../src/main/res/menu-xlarge/deck_picker.xml | 2 +- AnkiDroid/src/main/res/menu/deck_picker.xml | 2 +- ...{model_editor.xml => note_type_editor.xml} | 2 +- .../ichi2/anki/AbstractFlashcardViewerTest.kt | 20 +- .../java/com/ichi2/anki/AnkiDroidJsAPITest.kt | 50 +-- .../java/com/ichi2/anki/CardBrowserTest.kt | 40 +- .../com/ichi2/anki/CardTemplateEditorTest.kt | 408 +++++++++--------- .../ichi2/anki/CardTemplateNotetypeTest.kt | 20 +- .../java/com/ichi2/anki/DeckPickerTest.kt | 12 +- .../java/com/ichi2/anki/NoteEditorTest.kt | 16 +- ...itorTest.kt => NoteTypeFieldEditorTest.kt} | 26 +- .../ichi2/anki/ReviewerKeyboardInputTest.kt | 8 +- .../com/ichi2/anki/ReviewerNoParamTest.kt | 10 +- .../test/java/com/ichi2/anki/ReviewerTest.kt | 38 +- .../java/com/ichi2/anki/RobolectricTest.kt | 6 +- .../anki/browser/CardBrowserColumnTest.kt | 2 +- .../anki/browser/CardBrowserViewModelTest.kt | 28 +- .../anki/cardviewer/CardMediaPlayerTest.kt | 2 +- .../anki/cardviewer/CardSoundConfigTest.kt | 4 +- .../anki/dialogs/CustomStudyDialogTest.kt | 4 +- .../anki/previewer/PreviewerFragmentTest.kt | 2 +- .../ichi2/anki/services/NoteServiceTest.kt | 14 +- .../anki/services/ReminderServiceTest.kt | 4 +- .../com/ichi2/libanki/AbstractSchedTest.kt | 2 +- .../test/java/com/ichi2/libanki/CardTest.kt | 60 +-- .../java/com/ichi2/libanki/CollectionTest.kt | 34 +- .../test/java/com/ichi2/libanki/FinderTest.kt | 14 +- .../com/ichi2/libanki/MathJaxClozeTest.kt | 2 +- .../libanki/{ModelTest.kt => NoteTypeTest.kt} | 152 +++---- .../java/com/ichi2/libanki/SchedulerTest.kt | 22 +- .../java/com/ichi2/libanki/StorageRustTest.kt | 6 +- .../java/com/ichi2/testutils/ActivityList.kt | 6 +- .../java/com/ichi2/testutils/TestClass.kt | 46 +- .../test/java/com/ichi2/utils/NoteTypeTest.kt | 32 +- .../java/com/ichi2/anki/FlashCardsContract.kt | 62 +-- .../java/com/ichi2/anki/api/AddContentApi.kt | 214 ++++----- .../api/{Basic2Model.kt => Basic2NoteType.kt} | 4 +- .../java/com/ichi2/anki/api/BasicModel.kt | 4 +- 74 files changed, 1375 insertions(+), 1368 deletions(-) rename AnkiDroid/src/androidTest/java/com/ichi2/anki/dialogs/{ModelEditorContextMenuTest.kt => NoteTypeEditorContextMenuTest.kt} (87%) rename AnkiDroid/src/main/java/com/ichi2/anki/{ModelFieldEditor.kt => NoteTypeFieldEditor.kt} (93%) rename AnkiDroid/src/main/java/com/ichi2/anki/dialogs/{ModelEditorContextMenu.kt => NoteTypeEditorContextMenu.kt} (79%) rename AnkiDroid/src/main/res/layout/{model_field_editor.xml => note_type_field_editor.xml} (100%) rename AnkiDroid/src/main/res/layout/{model_field_editor_list_item.xml => note_type_field_editor_list_item.xml} (100%) rename AnkiDroid/src/main/res/menu/{model_editor.xml => note_type_editor.xml} (86%) rename AnkiDroid/src/test/java/com/ichi2/anki/{ModelFieldEditorTest.kt => NoteTypeFieldEditorTest.kt} (87%) rename AnkiDroid/src/test/java/com/ichi2/libanki/{ModelTest.kt => NoteTypeTest.kt} (79%) rename api/src/main/java/com/ichi2/anki/api/{Basic2Model.kt => Basic2NoteType.kt} (90%) diff --git a/AnkiDroid/src/androidTest/java/com/ichi2/anki/DeckPickerTest.kt b/AnkiDroid/src/androidTest/java/com/ichi2/anki/DeckPickerTest.kt index 0ce9bdbc0f6a..1c274932ee4c 100644 --- a/AnkiDroid/src/androidTest/java/com/ichi2/anki/DeckPickerTest.kt +++ b/AnkiDroid/src/androidTest/java/com/ichi2/anki/DeckPickerTest.kt @@ -49,7 +49,7 @@ class DeckPickerTest : InstrumentedTest() { @Before fun before() { - addNoteUsingBasicModel() + addNoteUsingBasicNoteType() disableIntroductionSlide() discardPreliminaryViews() } diff --git a/AnkiDroid/src/androidTest/java/com/ichi2/anki/PagesTest.kt b/AnkiDroid/src/androidTest/java/com/ichi2/anki/PagesTest.kt index 755d96c36352..c33c5611f3be 100644 --- a/AnkiDroid/src/androidTest/java/com/ichi2/anki/PagesTest.kt +++ b/AnkiDroid/src/androidTest/java/com/ichi2/anki/PagesTest.kt @@ -86,13 +86,13 @@ class PagesTest : InstrumentedTest() { fun PagesTest.getStatistics(context: Context): Intent = Statistics.getIntent(context) fun PagesTest.getCardInfo(context: Context): Intent = - addNoteUsingBasicModel().firstCard(col).let { card -> + addNoteUsingBasicNoteType().firstCard(col).let { card -> this.card = card CardInfoDestination(card.id).toIntent(context) } fun PagesTest.getCongratsPage(context: Context): Intent = - addNoteUsingBasicModel().firstCard(col).let { card -> + addNoteUsingBasicNoteType().firstCard(col).let { card -> this.card = card CardInfoDestination(card.id).toIntent(context) } diff --git a/AnkiDroid/src/androidTest/java/com/ichi2/anki/ReviewerFragmentTest.kt b/AnkiDroid/src/androidTest/java/com/ichi2/anki/ReviewerFragmentTest.kt index 20fc46f998c8..56ec6373566a 100644 --- a/AnkiDroid/src/androidTest/java/com/ichi2/anki/ReviewerFragmentTest.kt +++ b/AnkiDroid/src/androidTest/java/com/ichi2/anki/ReviewerFragmentTest.kt @@ -69,7 +69,7 @@ class ReviewerFragmentTest : InstrumentedTest() { states.good.normal.review.scheduledDays = 123; customData.good.c += 1; """ - val note = addNoteUsingBasicModel("foo", "bar") + val note = addNoteUsingBasicNoteType("foo", "bar") val card = note.firstCard(col) val deck = col.decks.get(note.notetype.did)!! card.moveToReviewQueue() @@ -107,7 +107,7 @@ class ReviewerFragmentTest : InstrumentedTest() { setNewReviewer() // Issue 15035 - runtime errors weren't handled col.cardStateCustomizer = "states.this_is_not_defined.normal.review = 12;" - addNoteUsingBasicModel() + addNoteUsingBasicNoteType() closeGetStartedScreenIfExists() closeBackupCollectionDialogIfExists() diff --git a/AnkiDroid/src/androidTest/java/com/ichi2/anki/ReviewerTest.kt b/AnkiDroid/src/androidTest/java/com/ichi2/anki/ReviewerTest.kt index 1bdd2dc5ed62..8461c64e5d66 100755 --- a/AnkiDroid/src/androidTest/java/com/ichi2/anki/ReviewerTest.kt +++ b/AnkiDroid/src/androidTest/java/com/ichi2/anki/ReviewerTest.kt @@ -88,7 +88,7 @@ class ReviewerTest : InstrumentedTest() { states.good.normal.review.scheduledDays = 123; customData.good.c += 1; """ - val note = addNoteUsingBasicModel("foo", "bar") + val note = addNoteUsingBasicNoteType("foo", "bar") val card = note.firstCard(col) val deck = col.decks.get(note.notetype.did)!! card.moveToReviewQueue() @@ -136,7 +136,7 @@ class ReviewerTest : InstrumentedTest() { fun testCustomSchedulerWithRuntimeError() { // Issue 15035 - runtime errors weren't handled col.cardStateCustomizer = "states.this_is_not_defined.normal.review = 12;" - addNoteUsingBasicModel() + addNoteUsingBasicNoteType() closeGetStartedScreenIfExists() closeBackupCollectionDialogIfExists() diff --git a/AnkiDroid/src/androidTest/java/com/ichi2/anki/dialogs/ModelEditorContextMenuTest.kt b/AnkiDroid/src/androidTest/java/com/ichi2/anki/dialogs/NoteTypeEditorContextMenuTest.kt similarity index 87% rename from AnkiDroid/src/androidTest/java/com/ichi2/anki/dialogs/ModelEditorContextMenuTest.kt rename to AnkiDroid/src/androidTest/java/com/ichi2/anki/dialogs/NoteTypeEditorContextMenuTest.kt index f6149ad3a911..c4e7acf6974c 100644 --- a/AnkiDroid/src/androidTest/java/com/ichi2/anki/dialogs/ModelEditorContextMenuTest.kt +++ b/AnkiDroid/src/androidTest/java/com/ichi2/anki/dialogs/NoteTypeEditorContextMenuTest.kt @@ -23,25 +23,25 @@ import androidx.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.ext.junit.runners.AndroidJUnit4 import com.ichi2.anki.R -import com.ichi2.anki.dialogs.ModelEditorContextMenu.ModelEditorContextMenuAction +import com.ichi2.anki.dialogs.NoteTypeEditorContextMenu.Action import com.ichi2.anki.tests.InstrumentedTest import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) -class ModelEditorContextMenuTest : InstrumentedTest() { +class NoteTypeEditorContextMenuTest : InstrumentedTest() { private val testDialogTitle = "test editor title" @Test @Ignore("flaky") fun showsAllOptions() { launchFragment( - fragmentArgs = bundleOf(ModelEditorContextMenu.KEY_LABEL to testDialogTitle), + fragmentArgs = bundleOf(NoteTypeEditorContextMenu.KEY_LABEL to testDialogTitle), themeResId = R.style.Theme_Light, - ) { ModelEditorContextMenu() } + ) { NoteTypeEditorContextMenu() } onView(withText(testDialogTitle)).check(matches(isDisplayed())) - ModelEditorContextMenuAction.entries.forEach { + Action.entries.forEach { onView(withText(it.actionTextId)).check(matches(isDisplayed())) } } diff --git a/AnkiDroid/src/androidTest/java/com/ichi2/anki/tests/ContentProviderTest.kt b/AnkiDroid/src/androidTest/java/com/ichi2/anki/tests/ContentProviderTest.kt index fff23dadda40..7b47ca8ee690 100644 --- a/AnkiDroid/src/androidTest/java/com/ichi2/anki/tests/ContentProviderTest.kt +++ b/AnkiDroid/src/androidTest/java/com/ichi2/anki/tests/ContentProviderTest.kt @@ -87,21 +87,21 @@ class ContentProviderTest : InstrumentedTest() { */ private val testDeckIds: MutableList = ArrayList(TEST_DECKS.size + 1) private lateinit var createdNotes: ArrayList - private var modelId: Long = 0 + private var noteTypeId: Long = 0 private var dummyFields = emptyStringArray(1) /** - * Initially create one note for each model. + * Initially create one note for each note type. */ @Before fun setUp() { Timber.i("setUp()") createdNotes = ArrayList() tearDown = true - // Add a new basic model that we use for testing purposes (existing models could potentially be corrupted) - val model = createBasicModel() - modelId = model.getLong("id") - val fields = model.fieldsNames + // Add a new basic note type that we use for testing purposes (existing note types could potentially be corrupted) + val noteType = createBasicNoteType() + noteTypeId = noteType.getLong("id") + val fields = noteType.fieldsNames // Use the names of the fields as test values for the notes which will be added dummyFields = fields.toTypedArray() // create test decks and add one note for every deck @@ -120,21 +120,21 @@ class ContentProviderTest : InstrumentedTest() { * set-down, */ val did = col.decks.byName(partialName!!)?.id ?: col.decks.id(partialName) testDeckIds.add(did) - createdNotes.add(setupNewNote(col, modelId, did, dummyFields, TEST_TAG)) + createdNotes.add(setupNewNote(col, noteTypeId, did, dummyFields, TEST_TAG)) partialName += "::" } } // Add a note to the default deck as well so that testQueryNextCard() works - createdNotes.add(setupNewNote(col, modelId, 1, dummyFields, TEST_TAG)) + createdNotes.add(setupNewNote(col, noteTypeId, 1, dummyFields, TEST_TAG)) } - private fun createBasicModel(name: String = BASIC_MODEL_NAME): NotetypeJson { - val m = + private fun createBasicNoteType(name: String = BASIC_NOTE_TYPE_NAME): NotetypeJson { + val noteTYpe = BackendUtils .fromJsonBytes( col.getStockNotetypeLegacy(StockNotetype.Kind.KIND_BASIC), ).apply { set("name", name) } - col.addNotetypeLegacy(BackendUtils.toJsonBytes(m)) + col.addNotetypeLegacy(BackendUtils.toJsonBytes(noteTYpe)) return col.notetypes.byName(name)!! } @@ -166,21 +166,21 @@ class ContentProviderTest : InstrumentedTest() { numDecksBeforeTest, col.decks.count(), ) - // Delete test model + // Delete test note type col.modSchemaNoCheck() - removeAllModelsByName(col, BASIC_MODEL_NAME) - removeAllModelsByName(col, TEST_MODEL_NAME) + removeAllNoteTypeByName(col, BASIC_NOTE_TYPE_NAME) + removeAllNoteTypeByName(col, TEST_NOTE_TYPE_NAME) } @Throws(Exception::class) - private fun removeAllModelsByName( + private fun removeAllNoteTypeByName( col: com.ichi2.libanki.Collection, name: String, ) { - var testModel = col.notetypes.byName(name) - while (testModel != null) { - col.notetypes.rem(testModel) - testModel = col.notetypes.byName(name) + var testNoteType = col.notetypes.byName(name) + while (testNoteType != null) { + col.notetypes.rem(testNoteType) + testNoteType = col.notetypes.byName(name) } } @@ -224,7 +224,7 @@ class ContentProviderTest : InstrumentedTest() { // Add the note val values = ContentValues().apply { - put(FlashCardsContract.Note.MID, modelId) + put(FlashCardsContract.Note.MID, noteTypeId) put(FlashCardsContract.Note.FLDS, Utils.joinFields(TEST_NOTE_FIELDS)) put(FlashCardsContract.Note.TAGS, TEST_TAG) } @@ -241,9 +241,9 @@ class ContentProviderTest : InstrumentedTest() { TEST_NOTE_FIELDS.toMutableList(), ) assertEquals("Check that tag was set correctly", TEST_TAG, addedNote.tags[0]) - val model: JSONObject? = col.notetypes.get(modelId) - assertNotNull("Check model", model) - val expectedNumCards = model!!.getJSONArray("tmpls").length() + val noteType: JSONObject? = col.notetypes.get(noteTypeId) + assertNotNull("Check note type", noteType) + val expectedNumCards = noteType!!.getJSONArray("tmpls").length() assertEquals("Check that correct number of cards generated", expectedNumCards, addedNote.numberOfCards(col)) // Now delete the note cr.delete(newNoteUri, null, null) @@ -254,14 +254,14 @@ class ContentProviderTest : InstrumentedTest() { } /** - * Check that inserting a note with an invalid modelId returns a reasonable exception + * Check that inserting a note with an invalid noteTypeId returns a reasonable exception */ @Test - fun testInsertNoteWithBadModelId() { - val invalidModelId = 12 + fun testInsertNoteWithBadNoteTypeId() { + val invalidNoteTypeId = 12 val values = ContentValues().apply { - put(FlashCardsContract.Note.MID, invalidModelId) + put(FlashCardsContract.Note.MID, invalidNoteTypeId) put(FlashCardsContract.Note.FLDS, Utils.joinFields(TEST_NOTE_FIELDS)) put(FlashCardsContract.Note.TAGS, TEST_TAG) } @@ -279,23 +279,23 @@ class ContentProviderTest : InstrumentedTest() { // Get required objects for test val cr = contentResolver var col = col - // Add a new basic model that we use for testing purposes (existing models could potentially be corrupted) - var model: NotetypeJson? = createBasicModel() - val modelId = model!!.getLong("id") + // Add a new basic note type that we use for testing purposes (existing note types could potentially be corrupted) + var noteType: NotetypeJson? = createBasicNoteType() + val noteTypeId = noteType!!.getLong("id") // Add the note - val modelUri = ContentUris.withAppendedId(FlashCardsContract.Model.CONTENT_URI, modelId) + val noteTypeUri = ContentUris.withAppendedId(FlashCardsContract.Model.CONTENT_URI, noteTypeId) val testIndex = - TEST_MODEL_CARDS.size - 1 // choose the last one because not the same as the basic model template - val expectedOrd = model.getJSONArray("tmpls").length() + TEST_NOTE_TYPE_CARDS.size - 1 // choose the last one because not the same as the basic note type template + val expectedOrd = noteType.getJSONArray("tmpls").length() val cv = ContentValues().apply { - put(FlashCardsContract.CardTemplate.NAME, TEST_MODEL_CARDS[testIndex]) - put(FlashCardsContract.CardTemplate.QUESTION_FORMAT, TEST_MODEL_QFMT[testIndex]) - put(FlashCardsContract.CardTemplate.ANSWER_FORMAT, TEST_MODEL_AFMT[testIndex]) - put(FlashCardsContract.CardTemplate.BROWSER_QUESTION_FORMAT, TEST_MODEL_QFMT[testIndex]) - put(FlashCardsContract.CardTemplate.BROWSER_ANSWER_FORMAT, TEST_MODEL_AFMT[testIndex]) + put(FlashCardsContract.CardTemplate.NAME, TEST_NOTE_TYPE_CARDS[testIndex]) + put(FlashCardsContract.CardTemplate.QUESTION_FORMAT, TEST_NOTE_TYPE_QFMT[testIndex]) + put(FlashCardsContract.CardTemplate.ANSWER_FORMAT, TEST_NOTE_TYPE_AFMT[testIndex]) + put(FlashCardsContract.CardTemplate.BROWSER_QUESTION_FORMAT, TEST_NOTE_TYPE_QFMT[testIndex]) + put(FlashCardsContract.CardTemplate.BROWSER_ANSWER_FORMAT, TEST_NOTE_TYPE_AFMT[testIndex]) } - val templatesUri = Uri.withAppendedPath(modelUri, "templates") + val templatesUri = Uri.withAppendedPath(noteTypeUri, "templates") val templateUri = cr.insert(templatesUri, cv) col = reopenCol() // test that the changes are physically saved to the DB assertNotNull("Check template uri", templateUri) @@ -306,9 +306,9 @@ class ContentProviderTest : InstrumentedTest() { templateUri!!, ), ) - model = col.notetypes.get(modelId) - assertNotNull("Check model", model) - val template = model!!.getJSONArray("tmpls").getJSONObject(expectedOrd) + noteType = col.notetypes.get(noteTypeId) + assertNotNull("Check note type", noteType) + val template = noteType!!.getJSONArray("tmpls").getJSONObject(expectedOrd) assertEquals( "Check template JSONObject ord", expectedOrd, @@ -316,14 +316,14 @@ class ContentProviderTest : InstrumentedTest() { ) assertEquals( "Check template name", - TEST_MODEL_CARDS[testIndex], + TEST_NOTE_TYPE_CARDS[testIndex], template.getString("name"), ) - assertEquals("Check qfmt", TEST_MODEL_QFMT[testIndex], template.getString("qfmt")) - assertEquals("Check afmt", TEST_MODEL_AFMT[testIndex], template.getString("afmt")) - assertEquals("Check bqfmt", TEST_MODEL_QFMT[testIndex], template.getString("bqfmt")) - assertEquals("Check bafmt", TEST_MODEL_AFMT[testIndex], template.getString("bafmt")) - col.notetypes.rem(model) + assertEquals("Check qfmt", TEST_NOTE_TYPE_QFMT[testIndex], template.getString("qfmt")) + assertEquals("Check afmt", TEST_NOTE_TYPE_AFMT[testIndex], template.getString("afmt")) + assertEquals("Check bqfmt", TEST_NOTE_TYPE_QFMT[testIndex], template.getString("bqfmt")) + assertEquals("Check bafmt", TEST_NOTE_TYPE_AFMT[testIndex], template.getString("bafmt")) + col.notetypes.rem(noteType) } /** @@ -335,23 +335,23 @@ class ContentProviderTest : InstrumentedTest() { // Get required objects for test val cr = contentResolver var col = col - var model: NotetypeJson? = createBasicModel() - val modelId = model!!.getLong("id") + var noteType: NotetypeJson? = createBasicNoteType() + val noteTypeId = noteType!!.getLong("id") val initialFieldsArr = model.flds val initialFieldCount = initialFieldsArr.length() - val noteTypeUri = ContentUris.withAppendedId(FlashCardsContract.Model.CONTENT_URI, modelId) + val noteTypeUri = ContentUris.withAppendedId(FlashCardsContract.Model.CONTENT_URI, noteTypeId) val insertFieldValues = ContentValues() insertFieldValues.put(FlashCardsContract.Model.FIELD_NAME, TEST_FIELD_NAME) val fieldUri = cr.insert(Uri.withAppendedPath(noteTypeUri, "fields"), insertFieldValues) assertNotNull("Check field uri", fieldUri) // Ensure that the changes are physically saved to the DB col = reopenCol() - model = col.notetypes.get(modelId) + noteType = col.notetypes.get(noteTypeId) // Test the field is as expected val fieldId = ContentUris.parseId(fieldUri!!) assertEquals("Check field id", initialFieldCount.toLong(), fieldId) - assertNotNull("Check model", model) - val fldsArr = model!!.flds + assertNotNull("Check note type", noteType) + val fldsArr = noteType!!.flds assertEquals( "Check fields length", (initialFieldCount + 1), @@ -362,7 +362,7 @@ class ContentProviderTest : InstrumentedTest() { TEST_FIELD_NAME, fldsArr.last().name, ) - col.notetypes.rem(model) + col.notetypes.rem(noteType) } /** @@ -376,7 +376,7 @@ class ContentProviderTest : InstrumentedTest() { .query( FlashCardsContract.Note.CONTENT_URI_V2, null, - "mid=$modelId", + "mid=$noteTypeId", null, null, ).use { cursor -> @@ -552,69 +552,69 @@ class ContentProviderTest : InstrumentedTest() { } /** - * Check that inserting a new model works as expected + * Check that inserting a new note type works as expected */ @Test - fun testInsertAndUpdateModel() { + fun testInsertAndUpdateNoteType() { val cr = contentResolver var cv = ContentValues().apply { - // Insert a new model - put(FlashCardsContract.Model.NAME, TEST_MODEL_NAME) - put(FlashCardsContract.Model.FIELD_NAMES, Utils.joinFields(TEST_MODEL_FIELDS)) - put(FlashCardsContract.Model.NUM_CARDS, TEST_MODEL_CARDS.size) + // Insert a new note type + put(FlashCardsContract.Model.NAME, TEST_NOTE_TYPE_NAME) + put(FlashCardsContract.Model.FIELD_NAMES, Utils.joinFields(TEST_NOTE_TYPE_FIELDS)) + put(FlashCardsContract.Model.NUM_CARDS, TEST_NOTE_TYPE_CARDS.size) } - val modelUri = cr.insert(FlashCardsContract.Model.CONTENT_URI, cv) - assertNotNull("Check inserted model isn't null", modelUri) - assertNotNull("Check last path segment exists", modelUri!!.lastPathSegment) - val mid = modelUri.lastPathSegment!!.toLong() + val noteTypeUri = cr.insert(FlashCardsContract.Model.CONTENT_URI, cv) + assertNotNull("Check inserted note type isn't null", noteTypeUri) + assertNotNull("Check last path segment exists", noteTypeUri!!.lastPathSegment) + val mid = noteTypeUri.lastPathSegment!!.toLong() var col = reopenCol() try { - var model: NotetypeJson? = col.notetypes.get(mid) - assertNotNull("Check model", model) - assertEquals("Check model name", TEST_MODEL_NAME, model!!.getString("name")) + var noteType: JSONObject? = col.notetypes.get(mid) + assertNotNull("Check note type", noteType) + assertEquals("Check note type name", TEST_NOTE_TYPE_NAME, noteType!!.getString("name")) assertEquals( "Check templates length", - TEST_MODEL_CARDS.size, - model.getJSONArray("tmpls").length(), + TEST_NOTE_TYPE_CARDS.size, + noteType.getJSONArray("tmpls").length(), ) assertEquals( "Check field length", - TEST_MODEL_FIELDS.size, - model.flds.length(), + TEST_NOTE_TYPE_FIELDS.size, + noteType.getJSONArray("flds").length(), ) - val fields = model.flds + val fields = model.flds for (i in 0 until fields.length()) { assertEquals( "Check name of fields", - TEST_MODEL_FIELDS[i], + TEST_NOTE_TYPE_FIELDS[i], fields[i].name, ) } - // Test updating the model CSS (to test updating MODELS_ID Uri) + // Test updating the note type CSS (to test updating MODELS_ID Uri) cv = ContentValues() - cv.put(FlashCardsContract.Model.CSS, TEST_MODEL_CSS) + cv.put(FlashCardsContract.Model.CSS, TEST_NOTE_TYPE_CSS) assertThat( - cr.update(modelUri, cv, null, null), + cr.update(noteTypeUri, cv, null, null), greaterThan(0), ) col = reopenCol() - model = col.notetypes.get(mid) - assertNotNull("Check model", model) - assertEquals("Check css", TEST_MODEL_CSS, model!!.getString("css")) - // Update each of the templates in model (to test updating MODELS_ID_TEMPLATES_ID Uri) - for (i in TEST_MODEL_CARDS.indices) { + noteType = col.notetypes.get(mid) + assertNotNull("Check note type", noteType) + assertEquals("Check css", TEST_NOTE_TYPE_CSS, noteType!!.getString("css")) + // Update each of the templates in note type (to test updating MODELS_ID_TEMPLATES_ID Uri) + for (i in TEST_NOTE_TYPE_CARDS.indices) { cv = ContentValues().apply { - put(FlashCardsContract.CardTemplate.NAME, TEST_MODEL_CARDS[i]) - put(FlashCardsContract.CardTemplate.QUESTION_FORMAT, TEST_MODEL_QFMT[i]) - put(FlashCardsContract.CardTemplate.ANSWER_FORMAT, TEST_MODEL_AFMT[i]) - put(FlashCardsContract.CardTemplate.BROWSER_QUESTION_FORMAT, TEST_MODEL_QFMT[i]) - put(FlashCardsContract.CardTemplate.BROWSER_ANSWER_FORMAT, TEST_MODEL_AFMT[i]) + put(FlashCardsContract.CardTemplate.NAME, TEST_NOTE_TYPE_CARDS[i]) + put(FlashCardsContract.CardTemplate.QUESTION_FORMAT, TEST_NOTE_TYPE_QFMT[i]) + put(FlashCardsContract.CardTemplate.ANSWER_FORMAT, TEST_NOTE_TYPE_AFMT[i]) + put(FlashCardsContract.CardTemplate.BROWSER_QUESTION_FORMAT, TEST_NOTE_TYPE_QFMT[i]) + put(FlashCardsContract.CardTemplate.BROWSER_ANSWER_FORMAT, TEST_NOTE_TYPE_AFMT[i]) } val tmplUri = Uri.withAppendedPath( - Uri.withAppendedPath(modelUri, "templates"), + Uri.withAppendedPath(noteTypeUri, "templates"), i.toString(), ) assertThat( @@ -623,26 +623,26 @@ class ContentProviderTest : InstrumentedTest() { greaterThan(0), ) col = reopenCol() - model = col.notetypes.get(mid) - assertNotNull("Check model", model) - val template = model!!.getJSONArray("tmpls").getJSONObject(i) + noteType = col.notetypes.get(mid) + assertNotNull("Check note type", noteType) + val template = noteType!!.getJSONArray("tmpls").getJSONObject(i) assertEquals( "Check template name", - TEST_MODEL_CARDS[i], + TEST_NOTE_TYPE_CARDS[i], template.getString("name"), ) - assertEquals("Check qfmt", TEST_MODEL_QFMT[i], template.getString("qfmt")) - assertEquals("Check afmt", TEST_MODEL_AFMT[i], template.getString("afmt")) - assertEquals("Check bqfmt", TEST_MODEL_QFMT[i], template.getString("bqfmt")) - assertEquals("Check bafmt", TEST_MODEL_AFMT[i], template.getString("bafmt")) + assertEquals("Check qfmt", TEST_NOTE_TYPE_QFMT[i], template.getString("qfmt")) + assertEquals("Check afmt", TEST_NOTE_TYPE_AFMT[i], template.getString("afmt")) + assertEquals("Check bqfmt", TEST_NOTE_TYPE_QFMT[i], template.getString("bqfmt")) + assertEquals("Check bafmt", TEST_NOTE_TYPE_AFMT[i], template.getString("bafmt")) } } finally { - // Delete the model (this will force a full-sync) + // Delete the note type (this will force a full-sync) col.modSchemaNoCheck() try { - val model = col.notetypes.get(mid) - assertNotNull("Check model", model) - col.notetypes.rem(model!!) + val noteType = col.notetypes.get(mid) + assertNotNull("Check note type", noteType) + col.notetypes.rem(noteType!!) } catch (e: ConfirmModSchemaException) { // This will never happen } @@ -653,52 +653,52 @@ class ContentProviderTest : InstrumentedTest() { * Query .../models URI */ @Test - fun testQueryAllModels() { + fun testQueryAllNoteType() { val cr = contentResolver - // Query all available models - val allModels = cr.query(FlashCardsContract.Model.CONTENT_URI, null, null, null, null) - assertNotNull(allModels) - allModels.use { + // Query all available note types + val allNoteTypes = cr.query(FlashCardsContract.Model.CONTENT_URI, null, null, null, null) + assertNotNull(allNoteTypes) + allNoteTypes.use { assertThat( "Check that there is at least one result", - allModels.count, + allNoteTypes.count, greaterThan(0), ) - while (allModels.moveToNext()) { - val modelId = - allModels.getLong(allModels.getColumnIndex(FlashCardsContract.Model._ID)) - val modelUri = + while (allNoteTypes.moveToNext()) { + val noteTypeId = + allNoteTypes.getLong(allNoteTypes.getColumnIndex(FlashCardsContract.Model._ID)) + val noteTypeUri = Uri.withAppendedPath( FlashCardsContract.Model.CONTENT_URI, - modelId.toString(), + noteTypeId.toString(), ) - val singleModel = cr.query(modelUri, null, null, null, null) - assertNotNull(singleModel) - singleModel.use { + val singleNoteType = cr.query(noteTypeUri, null, null, null, null) + assertNotNull(singleNoteType) + singleNoteType.use { assertEquals( "Check that there is exactly one result", 1, it.count, ) assertTrue("Move to beginning of cursor", it.moveToFirst()) - val nameFromModels = - allModels.getString(allModels.getColumnIndex(FlashCardsContract.Model.NAME)) - val nameFromModel = - it.getString(allModels.getColumnIndex(FlashCardsContract.Model.NAME)) + val nameFromNoteTypes = + allNoteTypes.getString(allNoteTypes.getColumnIndex(FlashCardsContract.Model.NAME)) + val nameFromNoteType = + it.getString(allNoteTypes.getColumnIndex(FlashCardsContract.Model.NAME)) assertEquals( - "Check that model names are the same", - nameFromModel, - nameFromModels, + "Check that note type names are the same", + nameFromNoteType, + nameFromNoteTypes, ) val flds = - allModels.getString(allModels.getColumnIndex(FlashCardsContract.Model.FIELD_NAMES)) + allNoteTypes.getString(allNoteTypes.getColumnIndex(FlashCardsContract.Model.FIELD_NAMES)) assertThat( "Check that valid number of fields", Utils.splitFields(flds).size, greaterThanOrEqualTo(1), ) val numCards = - allModels.getInt(allModels.getColumnIndex(FlashCardsContract.Model.NUM_CARDS)) + allNoteTypes.getInt(allNoteTypes.getColumnIndex(FlashCardsContract.Model.NUM_CARDS)) assertThat( "Check that valid number of cards", numCards, @@ -776,19 +776,19 @@ class ContentProviderTest : InstrumentedTest() { } /** - * Check that querying the current model gives a valid result + * Check that querying the current note type gives a valid result */ @Test - fun testQueryCurrentModel() { + fun testQueryCurrentNoteType() { val cr = contentResolver val uri = Uri.withAppendedPath( FlashCardsContract.Model.CONTENT_URI, - FlashCardsContract.Model.CURRENT_MODEL_ID, + FlashCardsContract.Model.CURRENT_NOTE_TYPE_ID, ) - val modelCursor = cr.query(uri, null, null, null, null) - assertNotNull(modelCursor) - modelCursor.use { + val noteTypeCursor = cr.query(uri, null, null, null, null) + assertNotNull(noteTypeCursor) + noteTypeCursor.use { assertEquals( "Check that there is exactly one result", 1, @@ -1274,7 +1274,7 @@ class ContentProviderTest : InstrumentedTest() { /** Test that a null did will not crash the provider (#6378) */ @Test - fun testProviderProvidesDefaultForEmptyModelDeck() { + fun testProviderProvidesDefaultForEmptyNoteTypeDeck() { assumeTrue( "This causes mild data corruption - should not be run on a collection you care about", isEmulator(), @@ -1282,16 +1282,16 @@ class ContentProviderTest : InstrumentedTest() { col.notetypes.all()[0].put("did", JSONObject.NULL) val cr = contentResolver - // Query all available models - val allModels = cr.query(FlashCardsContract.Model.CONTENT_URI, null, null, null, null) - assertNotNull(allModels) + // Query all available note types + val allNoteTypes = cr.query(FlashCardsContract.Model.CONTENT_URI, null, null, null, null) + assertNotNull(allNoteTypes) } @Test fun pureAnswerHandledQuotedHtmlElement() { //
is also used - val modelName = addNonClozeModel("Test", arrayOf("One", "Two"), "{{One}}", "{{One}}
{{Two}}") - val note = col.newNote(col.notetypes.byName(modelName)!!) + val noteTypeName = addNonClozeNoteType("Test", arrayOf("One", "Two"), "{{One}}", "{{One}}
{{Two}}") + val note = col.newNote(col.notetypes.byName(noteTypeName)!!) note.setItem("One", "1") note.setItem("Two", "2") col.addNote(note) @@ -1309,7 +1309,7 @@ class ContentProviderTest : InstrumentedTest() { val invalid3 = "[anki:play:a:text]" // string instead of text val back = "$invalid1$invalid2$invalid3" - val note = addNoteUsingBasicModel("Hello$sound", back) + val note = addNoteUsingBasicNoteType("Hello$sound", back) val ord = 0 val noteUri = @@ -1355,7 +1355,7 @@ class ContentProviderTest : InstrumentedTest() { get() = testContext.contentResolver companion object { - private const val BASIC_MODEL_NAME = "com.ichi2.anki.provider.test.basic.x94oa3F" + private const val BASIC_NOTE_TYPE_NAME = "com.ichi2.anki.provider.test.basic.x94oa3F" private const val TEST_FIELD_NAME = "TestFieldName" private const val TEST_FIELD_VALUE = "test field value" private const val TEST_TAG = "aldskfhewjklhfczmxkjshf" @@ -1370,13 +1370,13 @@ class ContentProviderTest : InstrumentedTest() { "cmxieunwoogyxsctnjmv::abcdefgh::ZYXW", "cmxieunwoogyxsctnjmv::INSBGDS", ) - private const val TEST_MODEL_NAME = "com.ichi2.anki.provider.test.a1x6h9l" - private val TEST_MODEL_FIELDS = arrayOf("FRONTS", "BACK") - private val TEST_MODEL_CARDS = arrayOf("cArD1", "caRD2") - private val TEST_MODEL_QFMT = arrayOf("{{FRONTS}}", "{{BACK}}") - private val TEST_MODEL_AFMT = arrayOf("{{BACK}}", "{{FRONTS}}") + private const val TEST_NOTE_TYPE_NAME = "com.ichi2.anki.provider.test.a1x6h9l" + private val TEST_NOTE_TYPE_FIELDS = arrayOf("FRONTS", "BACK") + private val TEST_NOTE_TYPE_CARDS = arrayOf("cArD1", "caRD2") + private val TEST_NOTE_TYPE_QFMT = arrayOf("{{FRONTS}}", "{{BACK}}") + private val TEST_NOTE_TYPE_AFMT = arrayOf("{{BACK}}", "{{FRONTS}}") private val TEST_NOTE_FIELDS = arrayOf("dis is za Fr0nt", "Te\$t") - private const val TEST_MODEL_CSS = "styleeeee" + private const val TEST_NOTE_TYPE_CSS = "styleeeee" @Suppress("SameParameterValue") private fun setupNewNote( @@ -1407,21 +1407,21 @@ class ContentProviderTest : InstrumentedTest() { } } - fun addNonClozeModel( + fun addNonClozeNoteType( name: String, fields: Array, qfmt: String?, afmt: String?, ): String { - val model = col.notetypes.new(name) + val noteType = col.notetypes.new(name) for (field in fields) { - col.notetypes.addFieldInNewModel(model, col.notetypes.newField(field)) + col.notetypes.addFieldInNewNoteType(noteType, col.notetypes.newField(field)) } val t = Notetypes.newTemplate("Card 1") t.put("qfmt", qfmt) t.put("afmt", afmt) - col.notetypes.addTemplateInNewModel(model, t) - col.notetypes.add(model) + col.notetypes.addTemplateInNewNoteType(noteType, t) + col.notetypes.add(noteType) return name } } diff --git a/AnkiDroid/src/androidTest/java/com/ichi2/anki/tests/InstrumentedTest.kt b/AnkiDroid/src/androidTest/java/com/ichi2/anki/tests/InstrumentedTest.kt index 8a14a5fd3e67..28ecfe3745bb 100644 --- a/AnkiDroid/src/androidTest/java/com/ichi2/anki/tests/InstrumentedTest.kt +++ b/AnkiDroid/src/androidTest/java/com/ichi2/anki/tests/InstrumentedTest.kt @@ -156,22 +156,22 @@ abstract class InstrumentedTest { } @DuplicatedCode("This is copied from RobolectricTest. This will be refactored into a shared library later") - internal fun addNoteUsingBasicModel( + internal fun addNoteUsingBasicNoteType( front: String = "Front", back: String = "Back", - ): Note = addNoteUsingModelName("Basic", front, back) + ): Note = addNoteUsingNoteTypeName("Basic", front, back) @DuplicatedCode("This is copied from RobolectricTest. This will be refactored into a shared library later") - private fun addNoteUsingModelName( + private fun addNoteUsingNoteTypeName( name: String, vararg fields: String, ): Note { - val model = + val noteType = col.notetypes.byName(name) ?: throw IllegalArgumentException("Could not find model '$name'") // PERF: if we modify newNote(), we can return the card and return a Pair here. // Saves a database trip afterwards. - val n = col.newNote(model) + val n = col.newNote(noteType) for ((i, field) in fields.withIndex()) { n.setField(i, field) } diff --git a/AnkiDroid/src/androidTest/java/com/ichi2/anki/tests/libanki/NotetypeTest.kt b/AnkiDroid/src/androidTest/java/com/ichi2/anki/tests/libanki/NotetypeTest.kt index 60b51a628153..d0a6faacfd75 100644 --- a/AnkiDroid/src/androidTest/java/com/ichi2/anki/tests/libanki/NotetypeTest.kt +++ b/AnkiDroid/src/androidTest/java/com/ichi2/anki/tests/libanki/NotetypeTest.kt @@ -41,8 +41,8 @@ class NotetypeTest : InstrumentedTest() { "This test is flaky on API29, ignoring", Build.VERSION.SDK_INT != Build.VERSION_CODES.Q, ) - val models = testCol.notetypes - val model = models.all()[0] + val noteTypes = testCol.notetypes + val noteType = noteTypes.all()[0] val testString = "test" val size = testString.length * 1024 * 1024 val buf = StringBuilder((size * 1.01).toInt()) @@ -50,12 +50,12 @@ class NotetypeTest : InstrumentedTest() { for (i in 0 until 1024 * 1024) { buf.append(testString) } - model.put(testString, buf.toString()) + noteType.put(testString, buf.toString()) // Buf should be more than 4MB, so at least two chunks from database. - // Reload models + // Reload noteType testCol.load() - val newModel = models.all()[0] - assertEquals(newModel, model) + val newNoteType = noteTypes.all()[0] + assertEquals(newNoteType, noteType) } } diff --git a/AnkiDroid/src/main/AndroidManifest.xml b/AnkiDroid/src/main/AndroidManifest.xml index ba8d6f6cc241..9ec71e03dfc1 100644 --- a/AnkiDroid/src/main/AndroidManifest.xml +++ b/AnkiDroid/src/main/AndroidManifest.xml @@ -319,7 +319,7 @@ android:exported="false" /> diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/AbstractFlashcardViewer.kt b/AnkiDroid/src/main/java/com/ichi2/anki/AbstractFlashcardViewer.kt index 9f4caa4b2a83..3c02ddafe6fe 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/AbstractFlashcardViewer.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/AbstractFlashcardViewer.kt @@ -1380,7 +1380,7 @@ abstract class AbstractFlashcardViewer : return } - // TODO needs testing: changing a card's model without flipping it back to the front + // TODO needs testing: changing a card's note type without flipping it back to the front // (such as editing a card, then editing the card template) typeAnswer!!.updateInfo(getColUnsafe, currentCard!!, resources) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/CardTemplateEditor.kt b/AnkiDroid/src/main/java/com/ichi2/anki/CardTemplateEditor.kt index 2600811cb72c..6467c630a260 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/CardTemplateEditor.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/CardTemplateEditor.kt @@ -121,10 +121,10 @@ open class CardTemplateEditor : @VisibleForTesting lateinit var viewPager: ViewPager2 private var slidingTabLayout: TabLayout? = null - var tempModel: CardTemplateNotetype? = null + var tempNoteType: CardTemplateNotetype? = null private set private var fieldNames: List? = null - private var modelId: NoteTypeId = 0 + private var noteTypeId: NoteTypeId = 0 private var noteId: NoteId = 0 // the position of the cursor in the editor view @@ -165,10 +165,10 @@ open class CardTemplateEditor : setContentView(R.layout.card_template_editor) // Load the args either from the intent or savedInstanceState bundle if (savedInstanceState == null) { - // get model id - modelId = intent.getLongExtra(EDITOR_MODEL_ID, NOT_FOUND_NOTE_TYPE) - if (modelId == NOT_FOUND_NOTE_TYPE) { - Timber.e("CardTemplateEditor :: no model ID was provided") + // get note type id + noteTypeId = intent.getLongExtra(EDITOR_NOTE_TYPE_ID, NOT_FOUND_NOTE_TYPE) + if (noteTypeId == NOT_FOUND_NOTE_TYPE) { + Timber.e("CardTemplateEditor :: no note type ID was provided") finish() return } @@ -179,12 +179,12 @@ open class CardTemplateEditor : tabToCursorPosition[0] = 0 tabToViewId[0] = R.id.front_edit } else { - modelId = savedInstanceState.getLong(EDITOR_MODEL_ID) + noteTypeId = savedInstanceState.getLong(EDITOR_NOTE_TYPE_ID) noteId = savedInstanceState.getLong(EDITOR_NOTE_ID) startingOrdId = savedInstanceState.getInt(EDITOR_START_ORD_ID) tabToCursorPosition = savedInstanceState.getSerializableCompat>(TAB_TO_CURSOR_POSITION_KEY)!! tabToViewId = savedInstanceState.getSerializableCompat>(TAB_TO_VIEW_ID)!! - tempModel = CardTemplateNotetype.fromBundle(savedInstanceState) + tempNoteType = CardTemplateNotetype.fromBundle(savedInstanceState) } templatePreviewerFrame = findViewById(R.id.fragment_container) @@ -209,14 +209,14 @@ open class CardTemplateEditor : } /** - * Loads or reloads [tempModel] in [R.id.fragment_container] if the view is fragmented. Do nothing otherwise. + * Loads or reloads [tempNoteType] in [R.id.fragment_container] if the view is fragmented. Do nothing otherwise. */ private fun loadTemplatePreviewerFragmentIfFragmented() { if (!fragmented) { return } launchCatchingTask { - val notetype = tempModel!!.notetype + val notetype = tempNoteType!!.notetype val notetypeFile = NotetypeFile(this@CardTemplateEditor, notetype) val ord = viewPager.currentItem val note = withCol { currentFragment?.getNote(this) ?: Note.fromNotetypeId(this@withCol, notetype.id) } @@ -239,8 +239,8 @@ open class CardTemplateEditor : public override fun onSaveInstanceState(outState: Bundle) { with(outState) { - tempModel?.let { putAll(it.toBundle()) } - putLong(EDITOR_MODEL_ID, modelId) + tempNoteType?.let { putAll(it.toBundle()) } + putLong(EDITOR_NOTE_TYPE_ID, noteTypeId) putLong(EDITOR_NOTE_ID, noteId) putInt(EDITOR_START_ORD_ID, startingOrdId) putSerializable(TAB_TO_VIEW_ID, tabToViewId) @@ -266,26 +266,26 @@ open class CardTemplateEditor : // without this call the editor doesn't see the latest changes to notetypes, see #16630 @NeedsTest("Add test to check that renaming notetypes in ManageNotetypes is seen in CardTemplateEditor(#16630)") col.notetypes.clearCache() - // The first time the activity loads it has a model id but no edits yet, so no edited model - // take the passed model id load it up for editing - if (tempModel == null) { - tempModel = CardTemplateNotetype(NotetypeJson(col.notetypes.get(modelId).toString())) - // Timber.d("onCollectionLoaded() model is %s", mTempModel.getModel().toString(2)); + // The first time the activity loads it has a note type id but no edits yet, so no edited note type + // take the passed note type id load it up for editing + if (tempNoteType == null) { + tempNoteType = CardTemplateNotetype(NotetypeJson(col.notetypes.get(noteTypeId).toString())) + // Timber.d("onCollectionLoaded() note type is %s", mTempNoteType.getNoteType().toString(2)); } - fieldNames = tempModel!!.notetype.fieldsNames + fieldNames = tempNoteType!!.notetype.fieldsNames // Set up the ViewPager with the sections adapter. viewPager.adapter = TemplatePagerAdapter(this@CardTemplateEditor) TabLayoutMediator(slidingTabLayout!!, viewPager) { tab: TabLayout.Tab, position: Int -> - tab.text = tempModel!!.getTemplate(position).getString("name") + tab.text = tempNoteType!!.getTemplate(position).getString("name") }.apply { attach() } // Set activity title supportActionBar?.let { it.setTitle(R.string.title_activity_template_editor) - it.subtitle = tempModel!!.notetype.optString("name") + it.subtitle = tempNoteType!!.notetype.optString("name") } // Close collection opening dialog if needed - Timber.i("CardTemplateEditor:: Card template editor successfully started for model id %d", modelId) + Timber.i("CardTemplateEditor:: Card template editor successfully started for note type id %d", noteTypeId) // Set the tab to the current template if an ord id was provided Timber.d("Setting starting tab to %d", startingOrdId) @@ -294,30 +294,30 @@ open class CardTemplateEditor : } } - fun modelHasChanged(): Boolean { - val oldModel: JSONObject? = getColUnsafe.notetypes.get(modelId) - return tempModel != null && tempModel!!.notetype.toString() != oldModel.toString() + fun noteTypeHasChanged(): Boolean { + val oldNoteType: JSONObject? = getColUnsafe.notetypes.get(noteTypeId) + return tempNoteType != null && tempNoteType!!.notetype.toString() != oldNoteType.toString() } private fun showDiscardChangesDialog() = DiscardChangesDialog.showDialog(this) { Timber.i("TemplateEditor:: OK button pressed to confirm discard changes") - // Clear the edited model from any cache files, and clear it from this objects memory to discard changes - CardTemplateNotetype.clearTempModelFiles() - tempModel = null + // Clear the edited note type from any cache files, and clear it from this objects memory to discard changes + CardTemplateNotetype.clearTempNoteTypeFiles() + tempNoteType = null finish() } /** When a deck is selected via Deck Override */ override fun onDeckSelected(deck: SelectableDeck?) { - if (tempModel!!.notetype.isCloze) { - Timber.w("Attempted to set deck for cloze model") + if (tempNoteType!!.notetype.isCloze) { + Timber.w("Attempted to set deck for cloze note type") showSnackbar(getString(R.string.multimedia_editor_something_wrong), Snackbar.LENGTH_SHORT) return } val ordinal = viewPager.currentItem - val template = tempModel!!.getTemplate(ordinal) + val template = tempNoteType!!.getTemplate(ordinal) val templateName = template.getString("name") if (deck != null && getColUnsafe.decks.isFiltered(deck.deckId)) { @@ -394,7 +394,7 @@ open class CardTemplateEditor : } KeyEvent.KEYCODE_O -> { Timber.i("Ctrl+O: Display deck override dialog from keypress") - currentFragment.displayDeckOverrideDialog(currentFragment.tempModel) + currentFragment.displayDeckOverrideDialog(currentFragment.tempNoteType) } KeyEvent.KEYCODE_M -> { Timber.i("Ctrl+M: Copy markdown from keypress") @@ -436,7 +436,7 @@ open class CardTemplateEditor : return CardTemplateFragment.newInstance(position, noteId, editorPosition, editorViewId) } - override fun getItemCount(): Int = tempModel?.templateCount ?: 0 + override fun getItemCount(): Int = tempNoteType?.templateCount ?: 0 override fun getItemId(position: Int): Long = baseId + position @@ -480,7 +480,7 @@ open class CardTemplateEditor : private var cursorPosition = 0 private lateinit var templateEditor: CardTemplateEditor - lateinit var tempModel: CardTemplateNotetype + lateinit var tempNoteType: CardTemplateNotetype lateinit var bottomNavigation: BottomNavigationView override fun onCreateView( @@ -492,11 +492,11 @@ open class CardTemplateEditor : templateEditor = activity as CardTemplateEditor val mainView = inflater.inflate(R.layout.card_template_editor_item, container, false) val cardIndex = requireArguments().getInt(CARD_INDEX) - tempModel = templateEditor.tempModel!! + tempNoteType = templateEditor.tempNoteType!! // Load template val template: JSONObject = try { - tempModel.getTemplate(cardIndex) + tempNoteType.getTemplate(cardIndex) } catch (e: JSONException) { Timber.d(e, "Exception loading template in CardTemplateFragment. Probably stale fragment.") return mainView @@ -513,7 +513,7 @@ open class CardTemplateEditor : val currentSelectedId = item.itemId templateEditor.tabToViewId[cardIndex] = currentSelectedId when (currentSelectedId) { - R.id.styling_edit -> setCurrentEditorView(currentSelectedId, tempModel.css, R.string.card_template_editor_styling) + R.id.styling_edit -> setCurrentEditorView(currentSelectedId, tempNoteType.css, R.string.card_template_editor_styling) R.id.back_edit -> setCurrentEditorView( currentSelectedId, @@ -544,18 +544,18 @@ open class CardTemplateEditor : refreshFragmentRunnable?.let { refreshFragmentHandler.removeCallbacks(it) } templateEditor.tabToCursorPosition[cardIndex] = editorEditText.selectionStart when (currentEditorViewId) { - R.id.styling_edit -> tempModel.updateCss(editorEditText.text.toString()) + R.id.styling_edit -> tempNoteType.updateCss(editorEditText.text.toString()) R.id.back_edit -> template.put("afmt", editorEditText.text) else -> template.put("qfmt", editorEditText.text) } - templateEditor.tempModel!!.updateTemplate(cardIndex, template) + templateEditor.tempNoteType!!.updateTemplate(cardIndex, template) val updateRunnable = Runnable { templateEditor.loadTemplatePreviewerFragmentIfFragmented() } refreshFragmentRunnable = updateRunnable refreshFragmentHandler.postDelayed(updateRunnable, REFRESH_PREVIEW_DELAY) - templateEditor.displayDiscardChangesCallback.isEnabled = modelHasChanged() + templateEditor.displayDiscardChangesCallback.isEnabled = noteTypeHasChanged() } override fun beforeTextChanged( @@ -660,7 +660,7 @@ open class CardTemplateEditor : return } val ordinal = templateEditor.viewPager.currentItem - val template = templateEditor.tempModel!!.getTemplate(ordinal) + val template = templateEditor.tempNoteType!!.getTemplate(ordinal) RenameCardTemplateDialog.showInstance( requireContext(), @@ -740,7 +740,7 @@ open class CardTemplateEditor : */ @NeedsTest("cannot perform operations on Image Occlusion") private fun noteTypeCreatesDynamicNumberOfNotes(): Boolean { - val noteType = templateEditor.tempModel!!.notetype + val noteType = templateEditor.tempNoteType!!.notetype return noteType.isCloze || noteType.isImageOcclusion } @@ -765,29 +765,29 @@ open class CardTemplateEditor : // TODO: Use withCol {} instead fun deleteCardTemplate() { val col = templateEditor.getColUnsafe - val tempModel = templateEditor.tempModel + val tempNoteType = templateEditor.tempNoteType val ordinal = templateEditor.viewPager.currentItem - val template = tempModel!!.getTemplate(ordinal) + val template = tempNoteType!!.getTemplate(ordinal) // Don't do anything if only one template - if (tempModel.templateCount < 2) { + if (tempNoteType.templateCount < 2) { templateEditor.showSimpleMessageDialog(resources.getString(R.string.card_template_editor_cant_delete)) return } - if (deletionWouldOrphanNote(col, tempModel, ordinal)) { + if (deletionWouldOrphanNote(col, tempNoteType, ordinal)) { showOrphanNoteDialog() return } // Show confirmation dialog val numAffectedCards = - if (!CardTemplateNotetype.isOrdinalPendingAdd(tempModel, ordinal)) { + if (!CardTemplateNotetype.isOrdinalPendingAdd(tempNoteType, ordinal)) { Timber.d("Ordinal is not a pending add, so we'll get the current card count for confirmation") - col.notetypes.tmplUseCount(tempModel.notetype, ordinal) + col.notetypes.tmplUseCount(tempNoteType.notetype, ordinal) } else { 0 } - confirmDeleteCards(template, tempModel.notetype, numAffectedCards) + confirmDeleteCards(template, tempNoteType.notetype, numAffectedCards) } /* showOrphanNoteDialog shows a AlertDialog if the deletionWouldOrphanNote returns true @@ -814,18 +814,18 @@ open class CardTemplateEditor : // Show confirmation dialog val ordinal = templateEditor.viewPager.currentItem // isOrdinalPendingAdd method will check if there are any new card types added or not, - // if TempModel has new card type then numAffectedCards will be 0 by default. + // if TempNoteType has new card type then numAffectedCards will be 0 by default. val numAffectedCards = - if (!CardTemplateNotetype.isOrdinalPendingAdd(templateEditor.tempModel!!, ordinal)) { - templateEditor.getColUnsafe.notetypes.tmplUseCount(templateEditor.tempModel!!.notetype, ordinal) + if (!CardTemplateNotetype.isOrdinalPendingAdd(templateEditor.tempNoteType!!, ordinal)) { + templateEditor.getColUnsafe.notetypes.tmplUseCount(templateEditor.tempNoteType!!.notetype, ordinal) } else { 0 } - confirmAddCards(templateEditor.tempModel!!.notetype, numAffectedCards) + confirmAddCards(templateEditor.tempNoteType!!.notetype, numAffectedCards) } fun saveNoteType(): Boolean { - if (modelHasChanged()) { + if (noteTypeHasChanged()) { val confirmButton = templateEditor.findViewById(R.id.action_confirm) if (confirmButton != null) { if (!confirmButton.isEnabled) { @@ -836,12 +836,12 @@ open class CardTemplateEditor : } launchCatchingTask(resources.getString(R.string.card_template_editor_save_error)) { requireActivity().withProgress(resources.getString(R.string.saving_model)) { - withCol { templateEditor.tempModel!!.saveToDatabase(this@withCol) } + withCol { templateEditor.tempNoteType!!.saveToDatabase(this@withCol) } } - onModelSaved() + onNoteTypeSaved() } } else { - Timber.d("CardTemplateEditor:: model has not changed, exiting") + Timber.d("CardTemplateEditor:: note type has not changed, exiting") templateEditor.finish() } return true @@ -853,7 +853,7 @@ open class CardTemplateEditor : fun setupCommonMenu(menu: Menu) { menu.findItem(R.id.action_restore_to_default).title = CollectionManager.TR.cardTemplatesRestoreToDefault() if (noteTypeCreatesDynamicNumberOfNotes()) { - Timber.d("Editing cloze/occlusion model, disabling add/delete card template and deck override functionality") + Timber.d("Editing cloze/occlusion note type, disabling add/delete card template and deck override functionality") menu.findItem(R.id.action_add).isVisible = false menu.findItem(R.id.action_rename).isVisible = false menu.findItem(R.id.action_add_deck_override).isVisible = false @@ -870,7 +870,7 @@ open class CardTemplateEditor : } // It is invalid to delete if there is only one card template, remove the option from UI - if (templateEditor.tempModel!!.templateCount < 2) { + if (templateEditor.tempNoteType!!.templateCount < 2) { menu.findItem(R.id.action_delete).isVisible = false } @@ -886,9 +886,9 @@ open class CardTemplateEditor : @NeedsTest("Notetype is restored to stock kind") private suspend fun restoreNotetypeToStock(kind: StockNotetype.Kind? = null) { - val nid = notetypeId { ntid = tempModel.modelId } + val nid = notetypeId { ntid = tempNoteType.noteTypeId } undoableOp { restoreNotetypeToStock(nid, kind) } - onModelSaved() + onNoteTypeSaved() showThemedToast( requireContext(), TR.cardTemplatesRestoredToDefault(), @@ -935,7 +935,7 @@ open class CardTemplateEditor : } R.id.action_add_deck_override -> { Timber.i("CardTemplateEditor:: Deck override button pressed") - displayDeckOverrideDialog(tempModel) + displayDeckOverrideDialog(tempNoteType) return true } R.id.action_preview -> { @@ -944,7 +944,7 @@ open class CardTemplateEditor : return true } R.id.action_confirm -> { - Timber.i("CardTemplateEditor:: Save model button pressed") + Timber.i("CardTemplateEditor:: Save note type button pressed") saveNoteType() } R.id.action_card_browser_appearance -> { @@ -967,7 +967,7 @@ open class CardTemplateEditor : } } - val originalStockKind = tempModel.notetype.optInt("originalStockKind", ORIGINAL_STOCK_KIND_UNKNOWN_VALUE) + val originalStockKind = tempNoteType.notetype.optInt("originalStockKind", ORIGINAL_STOCK_KIND_UNKNOWN_VALUE) if (originalStockKind != ORIGINAL_STOCK_KIND_UNKNOWN_VALUE) { Timber.d("Asking to restore to original stock kind %s", originalStockKind) askUser() @@ -1001,12 +1001,12 @@ open class CardTemplateEditor : private val currentTemplate: CardTemplate? get() = try { - val tempModel = templateEditor.tempModel - val template: JSONObject = tempModel!!.getTemplate(templateEditor.viewPager.currentItem) + val tempNoteType = templateEditor.tempNoteType + val template: JSONObject = tempNoteType!!.getTemplate(templateEditor.viewPager.currentItem) CardTemplate( front = template.getString("qfmt"), back = template.getString("afmt"), - style = tempModel.css, + style = tempNoteType.css, ) } catch (e: Exception) { Timber.w(e, "Exception loading template in CardTemplateFragment. Probably stale fragment.") @@ -1026,13 +1026,13 @@ open class CardTemplateEditor : } } - private fun onModelSaved() { - Timber.d("saveModelAndExitHandler::postExecute called") + private fun onNoteTypeSaved() { + Timber.d("saveNoteTypeAndExitHandler::postExecute called") val button = templateEditor.findViewById(R.id.action_confirm) if (button != null) { button.isEnabled = true } - templateEditor.tempModel = null + templateEditor.tempNoteType = null templateEditor.finish() } @@ -1043,7 +1043,7 @@ open class CardTemplateEditor : fun performPreview() { launchCatchingTask { - val notetype = templateEditor.tempModel!!.notetype + val notetype = templateEditor.tempNoteType!!.notetype val notetypeFile = NotetypeFile(requireContext(), notetype) val ord = templateEditor.viewPager.currentItem val note = withCol { getNote(this) ?: Note.fromNotetypeId(this@withCol, notetype.id) } @@ -1061,14 +1061,14 @@ open class CardTemplateEditor : } } - fun displayDeckOverrideDialog(tempModel: CardTemplateNotetype) = + fun displayDeckOverrideDialog(tempNoteType: CardTemplateNotetype) = launchCatchingTask { val activity = requireActivity() as AnkiActivity - if (tempModel.notetype.isCloze) { + if (tempNoteType.notetype.isCloze) { showSnackbar(getString(R.string.multimedia_editor_something_wrong), Snackbar.LENGTH_SHORT) return@launchCatchingTask } - val name = getCurrentTemplateName(tempModel) + val name = getCurrentTemplateName(tempNoteType) val explanation = getString(R.string.deck_override_explanation, name) // Anki Desktop allows Dynamic decks, have reported this as a bug: // https://forums.ankiweb.net/t/minor-bug-deck-override-to-filtered-deck/1493 @@ -1078,10 +1078,10 @@ open class CardTemplateEditor : activity.showDialogFragment(dialog) } - private fun getCurrentTemplateName(tempModel: CardTemplateNotetype): String = + private fun getCurrentTemplateName(tempNoteType: CardTemplateNotetype): String = try { val ordinal = templateEditor.viewPager.currentItem - val template = tempModel.getTemplate(ordinal) + val template = tempNoteType.getTemplate(ordinal) template.getString("name") } catch (e: Exception) { Timber.w(e, "Failed to get name for template") @@ -1098,7 +1098,7 @@ open class CardTemplateEditor : private fun getCurrentTemplate(): JSONObject? { val currentCardTemplateIndex = getCurrentCardTemplateIndex() return try { - templateEditor.tempModel!! + templateEditor.tempNoteType!! .notetype .getJSONArray("tmpls") .getJSONObject(currentCardTemplateIndex) @@ -1118,7 +1118,7 @@ open class CardTemplateEditor : private fun deletionWouldOrphanNote( col: Collection, - tempModel: CardTemplateNotetype?, + tempNoteType: CardTemplateNotetype?, position: Int, ): Boolean { // For existing templates, make sure we won't leave orphaned notes if we delete the template @@ -1127,10 +1127,10 @@ open class CardTemplateEditor : // If we were deleting a template we just added, we don't care. If not, then for every // template delete queued up, we check the database to see if this delete in combo with any other // pending deletes could orphan cards - if (!CardTemplateNotetype.isOrdinalPendingAdd(tempModel!!, position)) { - val currentDeletes = tempModel.getDeleteDbOrds(position) + if (!CardTemplateNotetype.isOrdinalPendingAdd(tempNoteType!!, position)) { + val currentDeletes = tempNoteType.getDeleteDbOrds(position) // TODO - this is a SQL query on GUI thread - should see a DeckTask conversion ideally - if (col.notetypes.getCardIdsForModel(tempModel.modelId, currentDeletes) == null) { + if (col.notetypes.getCardIdsForNoteType(tempNoteType.noteTypeId, currentDeletes) == null) { // It is possible but unlikely that a user has an in-memory template addition that would // generate cards making the deletion safe, but we don't handle that. All users who do // not already have cards generated making it safe will see this error message: @@ -1152,7 +1152,7 @@ open class CardTemplateEditor : if (result.resultCode != RESULT_OK) { return@registerForActivityResult } - CardTemplateNotetype.clearTempModelFiles() + CardTemplateNotetype.clearTempNoteTypeFiles() // Make sure the fragments reinitialize, otherwise there is staleness on return (templateEditor.viewPager.adapter as TemplatePagerAdapter).ordinalShift() templateEditor.viewPager.adapter!!.notifyDataSetChanged() @@ -1171,13 +1171,13 @@ open class CardTemplateEditor : } } - private fun modelHasChanged(): Boolean = templateEditor.modelHasChanged() + private fun noteTypeHasChanged(): Boolean = templateEditor.noteTypeHasChanged() /** * Confirm if the user wants to delete all the cards associated with current template * * @param tmpl template to remove - * @param notetype model to remove template from, modified in place by reference + * @param notetype note type to remove template from, modified in place by reference * @param numAffectedCards number of cards which will be affected */ private fun confirmDeleteCards( @@ -1205,7 +1205,7 @@ open class CardTemplateEditor : /** * Confirm if the user wants to add new card template - * @param notetype model to add new template and modified in place by reference + * @param notetype note type to add new template and modified in place by reference * @param numAffectedCards number of cards which will be affected */ private fun confirmAddCards( @@ -1265,7 +1265,7 @@ open class CardTemplateEditor : /** * @param tmpl template to remove - * @param notetype model to remove from, updated in place by reference + * @param notetype note type to remove from, updated in place by reference */ private fun deleteTemplate( tmpl: JSONObject, @@ -1278,7 +1278,7 @@ open class CardTemplateEditor : newTemplates.put(possibleMatch) } else { Timber.d("deleteTemplate() found match - removing template with ord %s", possibleMatch.getInt("ord")) - templateEditor.tempModel!!.removeTemplate(possibleMatch.getInt("ord")) + templateEditor.tempNoteType!!.removeTemplate(possibleMatch.getInt("ord")) } } notetype.put("tmpls", newTemplates) @@ -1290,13 +1290,13 @@ open class CardTemplateEditor : } /** - * Add new template to a given model - * @param model model to add new template to + * Add new template to a given note type + * @param noteType note type to add new template to */ - private fun addNewTemplate(model: JSONObject) { + private fun addNewTemplate(noteType: JSONObject) { // Build new template val oldCardIndex = requireArguments().getInt(CARD_INDEX) - val templates = model.getJSONArray("tmpls") + val templates = noteType.getJSONArray("tmpls") val oldTemplate = templates.getJSONObject(oldCardIndex) val newTemplate = Notetypes.newTemplate(newCardName(templates)) // Set up question & answer formats @@ -1310,7 +1310,7 @@ open class CardTemplateEditor : Timber.d("addNewTemplate() lastExistingOrd was %s", lastExistingOrd) newTemplate.put("ord", lastExistingOrd + 1) templates.put(newTemplate) - templateEditor.tempModel!!.addNewTemplate(newTemplate) + templateEditor.tempNoteType!!.addNewTemplate(newTemplate) templateEditor.viewPager.adapter!!.notifyDataSetChanged() templateEditor.viewPager.setCurrentItem(templates.length() - 1, templateEditor.animationDisabled()) } @@ -1343,7 +1343,7 @@ open class CardTemplateEditor : // If the starting point for name already exists, iteratively increase n until we find a unique name while (true) { // Get new name - val name = CollectionManager.TR.cardTemplatesCard(n) + val name = TR.cardTemplatesCard(n) // Cycle through all templates checking if new name exists if (templates.jsonObjectIterable().all { name != it.getString("name") }) { return name @@ -1393,7 +1393,7 @@ open class CardTemplateEditor : private const val TAB_TO_CURSOR_POSITION_KEY = "tabToCursorPosition" private const val EDITOR_VIEW_ID_KEY = "editorViewId" private const val TAB_TO_VIEW_ID = "tabToViewId" - private const val EDITOR_MODEL_ID = "modelId" + private const val EDITOR_NOTE_TYPE_ID = "noteTypeId" private const val EDITOR_NOTE_ID = "noteId" private const val EDITOR_START_ORD_ID = "ordId" private const val CARD_INDEX = "card_ord" diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/CardTemplateNotetype.kt b/AnkiDroid/src/main/java/com/ichi2/anki/CardTemplateNotetype.kt index 29921c2dc373..222e251dcc4c 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/CardTemplateNotetype.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/CardTemplateNotetype.kt @@ -22,7 +22,7 @@ import android.os.Bundle import android.os.Parcel import android.os.Parcelable import androidx.core.os.bundleOf -import com.ichi2.async.saveModel +import com.ichi2.async.saveNoteType import com.ichi2.compat.CompatHelper.Companion.compat import com.ichi2.compat.CompatHelper.Companion.getSerializableCompat import com.ichi2.libanki.Collection @@ -50,7 +50,7 @@ class CardTemplateNotetype( fun toBundle(): Bundle = bundleOf( - INTENT_MODEL_FILENAME to saveTempModel(AnkiDroidApp.instance.applicationContext, notetype), + INTENT_NOTE_TYPE_FILENAME to saveTempNoteType(AnkiDroidApp.instance.applicationContext, notetype), "mTemplateChanges" to _templateChanges, ) @@ -70,7 +70,7 @@ class CardTemplateNotetype( val templateCount: Int get() = notetype.getJSONArray("tmpls").length() - val modelId: NoteTypeId + val noteTypeId: NoteTypeId get() = notetype.getLong("id") fun updateCss(css: String?) { @@ -100,8 +100,8 @@ class CardTemplateNotetype( fun saveToDatabase(col: Collection) { Timber.d("saveToDatabase() called") dumpChanges() - clearTempModelFiles() - return saveModel(col, notetype, adjustedTemplateChanges) + clearTempNoteTypeFiles() + return saveNoteType(col, notetype, adjustedTemplateChanges) } /** @@ -302,27 +302,27 @@ class CardTemplateNotetype( } companion object { - const val INTENT_MODEL_FILENAME = "editedModelFilename" + const val INTENT_NOTE_TYPE_FILENAME = "editedModelFilename" /** - * Load the TemporaryModel from the filename included in a Bundle + * Load the TemporaryNoteType from the filename included in a Bundle * - * @param bundle a Bundle that should contain persisted JSON under INTENT_MODEL_FILENAME key - * @return re-hydrated TemporaryModel or null if there was a problem, null means should reload from database + * @param bundle a Bundle that should contain persisted JSON under INTENT_NOTE_TYPE_FILENAME key + * @return re-hydrated TemporaryNoteType or null if there was a problem, null means should reload from database */ fun fromBundle(bundle: Bundle): CardTemplateNotetype? { - val editedModelFileName = bundle.getString(INTENT_MODEL_FILENAME) + val editedNoteTypeFileName = bundle.getString(INTENT_NOTE_TYPE_FILENAME) // Bundle.getString is @Nullable, so we have to check. - if (editedModelFileName == null) { - Timber.d("fromBundle() - model file name under key %s", INTENT_MODEL_FILENAME) + if (editedNoteTypeFileName == null) { + Timber.d("fromBundle() - note type file name under key %s", INTENT_NOTE_TYPE_FILENAME) return null } - Timber.d("onCreate() loading saved model file %s", editedModelFileName) + Timber.d("onCreate() loading saved note type file %s", editedNoteTypeFileName) val tempNotetypeJSON: NotetypeJson = try { - getTempModel(editedModelFileName) + getTempNoteType(editedNoteTypeFileName) } catch (e: IOException) { - Timber.w(e, "Unable to load saved model file") + Timber.w(e, "Unable to load saved note type file") return null } return CardTemplateNotetype(tempNotetypeJSON).apply { @@ -331,47 +331,47 @@ class CardTemplateNotetype( } /** - * Save the current model to a temp file in the application internal cache directory + * Save the current note type to a temp file in the application internal cache directory * @return String representing the absolute path of the saved file, or null if there was a problem */ - fun saveTempModel( + fun saveTempNoteType( context: Context, - tempModel: JSONObject, + tempNoteType: JSONObject, ): String? { - Timber.d("saveTempModel() saving tempModel") - var tempModelFile: File + Timber.d("saveTempNoteType() saving tempNoteType") + var tempNoteTypeFile: File try { - ByteArrayInputStream(tempModel.toString().toByteArray()).use { source -> - tempModelFile = File.createTempFile("editedTemplate", ".json", context.cacheDir) - compat.copyFile(source, tempModelFile.absolutePath) + ByteArrayInputStream(tempNoteType.toString().toByteArray()).use { source -> + tempNoteTypeFile = File.createTempFile("editedTemplate", ".json", context.cacheDir) + compat.copyFile(source, tempNoteTypeFile.absolutePath) } } catch (ioe: IOException) { - Timber.e(ioe, "Unable to create+write temp file for model") + Timber.e(ioe, "Unable to create+write temp file for note type") return null } - return tempModelFile.absolutePath + return tempNoteTypeFile.absolutePath } /** - * Get the model temporarily saved into the file represented by the given path - * @return JSONObject holding the model, or null if there was a problem + * Get the note type temporarily saved into the file represented by the given path + * @return JSONObject holding the note type, or null if there was a problem */ @Throws(IOException::class) - fun getTempModel(tempModelFileName: String): NotetypeJson { - Timber.d("getTempModel() fetching tempModel %s", tempModelFileName) + fun getTempNoteType(tempNoteTypeFileName: String): NotetypeJson { + Timber.d("getTempNoteType() fetching tempNoteType %s", tempNoteTypeFileName) try { ByteArrayOutputStream().use { target -> - compat.copyFile(tempModelFileName, target) + compat.copyFile(tempNoteTypeFileName, target) return NotetypeJson(target.toString()) } } catch (e: IOException) { - Timber.e(e, "Unable to read+parse tempModel from file %s", tempModelFileName) + Timber.e(e, "Unable to read+parse tempNoteType from file %s", tempNoteTypeFileName) throw e } } - /** Clear any temp model files saved into internal cache directory */ - fun clearTempModelFiles(): Int { + /** Clear any temp note type files saved into internal cache directory */ + fun clearTempNoteTypeFiles(): Int { var deleteCount = 0 for (c in AnkiDroidApp.instance.cacheDir.listFiles() ?: arrayOf()) { val absolutePath = c.absolutePath @@ -380,7 +380,7 @@ class CardTemplateNotetype( Timber.w("Unable to delete temp file %s", c.absolutePath) } else { deleteCount++ - Timber.d("Deleted temp model file %s", c.absolutePath) + Timber.d("Deleted temp note type file %s", c.absolutePath) } } } @@ -390,17 +390,17 @@ class CardTemplateNotetype( /** * Check if the given ordinal from the current UI state (which includes all pending changes) is a pending add * - * @param ord int representing an ordinal in the model, that might be an unsaved addition + * @param ord int representing an ordinal in the note type, that might be an unsaved addition * @return boolean true if it is a pending addition from this editing session */ fun isOrdinalPendingAdd( - model: CardTemplateNotetype, + noteType: CardTemplateNotetype, ord: Int, ): Boolean { - for (i in model.templateChanges.indices) { + for (i in noteType.templateChanges.indices) { // commented out to make the code compile, why is this unused? - // val change = model.templateChanges[i] - val adjustedOrdinal = getAdjustedAddOrdinalAtChangeIndex(model, i) + // val change = noteType.templateChanges[i] + val adjustedOrdinal = getAdjustedAddOrdinalAtChangeIndex(noteType, i) if (adjustedOrdinal == ord) { Timber.d( "isOrdinalPendingAdd() found ord %s was pending add (would adjust to %s)", @@ -421,17 +421,17 @@ class CardTemplateNotetype( * @return either ordinal adjusted by any pending deletes if it is a pending add, or -1 if the ordinal is not an add */ fun getAdjustedAddOrdinalAtChangeIndex( - model: CardTemplateNotetype, + noteType: CardTemplateNotetype, changesIndex: Int, ): Int { - if (changesIndex >= model.templateChanges.size) { + if (changesIndex >= noteType.templateChanges.size) { return -1 } var ordinalAdjustment = 0 - val change = model.templateChanges[changesIndex] + val change = noteType.templateChanges[changesIndex] val ordinalToInspect = change[0] as Int - for (i in model.templateChanges.size - 1 downTo changesIndex) { - val oldChange = model.templateChanges[i] + for (i in noteType.templateChanges.size - 1 downTo changesIndex) { + val oldChange = noteType.templateChanges[i] val currentOrdinal = change[0] as Int when (oldChange[1] as ChangeType) { ChangeType.DELETE -> { @@ -492,7 +492,7 @@ class NotetypeFile( compat.copyFile(source, this.absolutePath) } } catch (ioe: IOException) { - Timber.w(ioe, "Unable to create+write temp file for model") + Timber.w(ioe, "Unable to create+write temp file for note type") } } @@ -509,7 +509,7 @@ class NotetypeFile( NotetypeJson(target.toString()) } } catch (e: IOException) { - Timber.e(e, "Unable to read+parse tempModel from file %s", absolutePath) + Timber.e(e, "Unable to read+parse tempNoteType from file %s", absolutePath) throw e } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt b/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt index fe6644c3c1ff..70e7df3e71f4 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt @@ -1136,8 +1136,8 @@ open class DeckPicker : handleEmptyCards() return true } - R.id.action_model_browser_open -> { - Timber.i("DeckPicker:: Model browser button pressed") + R.id.action_note_type_browser_open -> { + Timber.i("DeckPicker:: Note type browser button pressed") openManageNoteTypes() return true } @@ -1654,13 +1654,13 @@ open class DeckPicker : if (previous < 20600123) { Timber.i("Fixing font-family definition in templates") try { - val models = getColUnsafe.notetypes - for (m in models.all()) { + val noteTypes = getColUnsafe.notetypes + for (m in noteTypes.all()) { val css = m.getString("css") @Suppress("SpellCheckingInspection") if (css.contains("font-familiy")) { m.put("css", css.replace("font-familiy", "font-family")) - models.save(m) + noteTypes.save(m) } } } catch (e: JSONException) { diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/MetaDB.kt b/AnkiDroid/src/main/java/com/ichi2/anki/MetaDB.kt index 3c18baab1c51..db5fab77c65d 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/MetaDB.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/MetaDB.kt @@ -197,7 +197,7 @@ object MetaDB { return false } - /** Reset the language associations for all the decks and card models. */ + /** Reset the language associations for all the decks and note type. */ fun resetLanguages(context: Context): Boolean { openDBIfClosed(context) try { @@ -231,7 +231,7 @@ object MetaDB { } /** - * Associates a language to a deck, model, and card model for a given type. + * Associates a language to a deck, note type, and note type for a given type. * * @param qa the part of the card for which to store the association, [.LANGUAGES_QA_QUESTION], * [.LANGUAGES_QA_ANSWER], or [.LANGUAGES_QA_UNDEFINED] @@ -275,7 +275,7 @@ object MetaDB { } /** - * Returns the language associated with the given deck, model and card model, for the given type. + * Returns the language associated with the given deck, note type and template, for the given type. * * @param qa the part of the card for which to store the association, [.LANGUAGES_QA_QUESTION], * [.LANGUAGES_QA_ANSWER], or [.LANGUAGES_QA_UNDEFINED] return the language associate with diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt b/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt index d146522f3d03..6cf9fb6a7ce3 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt @@ -194,7 +194,7 @@ const val CALLER_KEY = "caller" /** * Allows the user to edit a note, for instance if there is a typo. A card is a presentation of a note, and has two * sides: a question and an answer. Any number of fields can appear on each side. When you add a note to Anki, cards - * which show that note are generated. Some models generate one card, others generate more than one. + * which show that note are generated. Some note types generate one card, others generate more than one. * Features: * - Implements [MainToolbar.OnMenuItemClickListener] to handle toolbar menu item clicks. * - Implements [DispatchKeyEventListener] to handle key events. @@ -254,11 +254,11 @@ class NoteEditor : @get:VisibleForTesting var deckId: DeckId = 0 private set - private var allModelIds: List? = null + private var allNoteTypeIds: List? = null @KotlinCleanup("this ideally should be Int, Int?") - private var modelChangeFieldMap: MutableMap? = null - private var modelChangeCardMap: HashMap? = null + private var noteTypeChangeFieldMap: MutableMap? = null + private var noteTypeChangeCardMap: HashMap? = null private val customViewIds = ArrayList() // indicates if a new note is added or a card is edited @@ -312,7 +312,7 @@ class NoteEditor : registerForActivityResult( ActivityResultContracts.StartActivityForResult(), NoteEditorActivityResultCallback { - // Model can change regardless of exit type - update ourselves and CardBrowser + // Note type can change regardless of exit type - update ourselves and CardBrowser reloadRequired = true editorNote!!.notetype = getColUnsafe.notetypes.get(editorNote!!.mid)!! if (currentEditedCard == null || @@ -738,7 +738,7 @@ class NoteEditor : // Note type Selector noteTypeSpinner = findViewById(R.id.note_type_spinner) - allModelIds = setupNoteTypeSpinner(requireContext(), noteTypeSpinner!!, col) + allNoteTypeIds = setupNoteTypeSpinner(requireContext(), noteTypeSpinner!!, col) // Deck Selector val deckTextView = findViewById(R.id.CardEditorDeckText) @@ -770,11 +770,11 @@ class NoteEditor : try { // If content has been shared, we can't share to an image occlusion note type if (currentNotetypeIsImageOcclusion() && (sourceText != null || caller == NoteEditorCaller.ADD_IMAGE)) { - val model = + val noteType = col.notetypes.all().first { !it.isImageOcclusion } - changeNoteType(model.id) + changeNoteType(noteType.id) } } catch (e: NoSuchElementException) { showSnackbar(R.string.missing_note_type) @@ -1121,9 +1121,9 @@ class NoteEditor : // changed note type? if (!addNote && currentEditedCard != null) { - val newModel: JSONObject? = currentlySelectedNotetype - val oldModel: JSONObject = currentEditedCard!!.noteType(getColUnsafe) - if (newModel != oldModel) { + val newNoteType: JSONObject? = currentlySelectedNotetype + val oldNoteType: JSONObject = currentEditedCard!!.noteType(getColUnsafe) + if (newNoteType != oldNoteType) { return true } } @@ -1145,7 +1145,7 @@ class NoteEditor : // changed tags? } - private fun collectionHasLoaded(): Boolean = allModelIds != null + private fun collectionHasLoaded(): Boolean = allNoteTypeIds != null // ---------------------------------------------------------------------------- // SAVE NOTE METHODS @@ -1194,7 +1194,7 @@ class NoteEditor : @VisibleForTesting @NeedsTest("14664: 'first field must not be empty' no longer applies after saving the note") - @KotlinCleanup("fix !! on oldModel/newModel") + @KotlinCleanup("fix !! on oldNoteType/newNoteType") suspend fun saveNote() { val res = resources if (selectedTags == null) { @@ -1208,10 +1208,10 @@ class NoteEditor : for (f in editFields!!) { updateField(f) } - // Save deck to model + // Save deck to note type Timber.d("setting 'last deck' of note type %s to %d", editorNote!!.notetype.name, deckId) editorNote!!.notetype.put("did", deckId) - // Save tags to model + // Save tags to note type editorNote!!.setTagsFromStr(getColUnsafe, tagsAsString(selectedTags!!)) val tags = JSONArray() for (t in selectedTags!!) { @@ -1232,12 +1232,12 @@ class NoteEditor : } } else { // Check whether note type has been changed - val newModel = currentlySelectedNotetype - val oldModel = currentEditedCard?.noteType(getColUnsafe) - if (newModel?.id != oldModel?.id) { + val newNoteType = currentlySelectedNotetype + val oldNoteType = currentEditedCard?.noteType(getColUnsafe) + if (newNoteType?.id != oldNoteType?.id) { reloadRequired = true - if (modelChangeCardMap!!.size < editorNote!!.numberOfCards(getColUnsafe) || - modelChangeCardMap!!.containsValue( + if (noteTypeChangeCardMap!!.size < editorNote!!.numberOfCards(getColUnsafe) || + noteTypeChangeCardMap!!.containsValue( null, ) ) { @@ -1247,13 +1247,13 @@ class NoteEditor : val confirm = Runnable { // Bypass the check once the user confirms - changeNoteType(oldModel!!, newModel!!) + changeNoteType(oldNoteType!!, newNoteType!!) } dialog.setConfirm(confirm) showDialogFragment(dialog) } else { // Otherwise go straight to changing note type - changeNoteType(oldModel!!, newModel!!) + changeNoteType(oldNoteType!!, newNoteType!!) } return } @@ -1307,7 +1307,7 @@ class NoteEditor : } /** - * Change the note type from oldModel to newModel, handling the case where a full sync will be required + * Change the note type from oldNoteType to newNoteType, handling the case where a full sync will be required */ @NeedsTest("test changing note type") private fun changeNoteType( @@ -1318,7 +1318,7 @@ class NoteEditor : val noteId = editorNote!!.id undoableOp { - notetypes.change(oldNotetype, noteId, newNotetype, modelChangeFieldMap!!, modelChangeCardMap!!) + notetypes.change(oldNotetype, noteId, newNotetype, noteTypeChangeFieldMap!!, noteTypeChangeCardMap!!) } // refresh the note object to reflect the database changes withCol { editorNote!!.load(this@withCol) } @@ -1578,7 +1578,7 @@ class NoteEditor : setResult(result) } // ensure there are no orphans from possible edit previews - CardTemplateNotetype.clearTempModelFiles() + CardTemplateNotetype.clearTempNoteTypeFiles() // Set the finish animation if there is one on the intent which created the activity val animation = @@ -1627,11 +1627,11 @@ class NoteEditor : private fun showCardTemplateEditor() { val intent = Intent(requireContext(), CardTemplateEditor::class.java) - // Pass the model ID - intent.putExtra("modelId", currentlySelectedNotetype!!.id) + // Pass the note type ID + intent.putExtra("noteTypeId", currentlySelectedNotetype!!.id) Timber.d( - "showCardTemplateEditor() for model %s", - intent.getLongExtra("modelId", NOT_FOUND_NOTE_TYPE), + "showCardTemplateEditor() for note type %s", + intent.getLongExtra("noteTypeId", NOT_FOUND_NOTE_TYPE), ) // Also pass the note id and ord if not adding new note if (!addNote && currentEditedCard != null) { @@ -1695,7 +1695,7 @@ class NoteEditor : private fun populateEditFields( type: FieldChangeType, - editModelMode: Boolean, + editNoteTypeMode: Boolean, ) { val editLines = fieldState.loadFieldEditLines(type) fieldsLayoutContainer!!.removeAllViews() @@ -1755,7 +1755,7 @@ class NoteEditor : // Use custom implementation of ActionMode.Callback customize selection and insert menus editLineView.setActionModeCallbacks(getActionModeCallback(newEditText, View.generateViewId())) editLineView.setHintLocale(getHintLocaleForField(editLineView.name)) - initFieldEditText(newEditText, i, !editModelMode) + initFieldEditText(newEditText, i, !editNoteTypeMode) editFields!!.add(newEditText) val prefs = this.sharedPrefs() if (prefs.getInt(PREF_NOTE_EDITOR_FONT_SIZE, -1) > 0) { @@ -1765,12 +1765,12 @@ class NoteEditor : val mediaButton = editLineView.mediaButton val toggleStickyButton = editLineView.toggleSticky // Make the icon change between media icon and switch field icon depending on whether editing note type - if (editModelMode && allowFieldRemapping()) { + if (editNoteTypeMode && allowFieldRemapping()) { // Allow remapping if originally more than two fields mediaButton.setBackgroundResource(R.drawable.ic_import_export) setRemapButtonListener(mediaButton, i) toggleStickyButton.setBackgroundResource(0) - } else if (editModelMode && !allowFieldRemapping()) { + } else if (editNoteTypeMode && !allowFieldRemapping()) { mediaButton.setBackgroundResource(0) toggleStickyButton.setBackgroundResource(0) } else { @@ -2091,23 +2091,23 @@ class NoteEditor : val idx = item.itemId Timber.i("NoteEditor:: User chose to remap to old field %d", idx) // Retrieve any existing mappings between newFieldIndex and idx - val previousMapping = MapUtil.getKeyByValue(modelChangeFieldMap!!, newFieldIndex) - val mappingConflict = modelChangeFieldMap!![idx] + val previousMapping = MapUtil.getKeyByValue(noteTypeChangeFieldMap!!, newFieldIndex) + val mappingConflict = noteTypeChangeFieldMap!![idx] // Update the mapping depending on any conflicts if (idx == items.size && previousMapping != null) { // Remove the previous mapping if None selected - modelChangeFieldMap!!.remove(previousMapping) + noteTypeChangeFieldMap!!.remove(previousMapping) } else if (idx < items.size && mappingConflict != null && previousMapping != null && newFieldIndex != mappingConflict) { // Swap the two mappings if there was a conflict and previous mapping - modelChangeFieldMap!![previousMapping] = mappingConflict - modelChangeFieldMap!![idx] = newFieldIndex + noteTypeChangeFieldMap!![previousMapping] = mappingConflict + noteTypeChangeFieldMap!![idx] = newFieldIndex } else if (idx < items.size && mappingConflict != null) { // Set the conflicting field to None if no previous mapping to swap into it - modelChangeFieldMap!!.remove(previousMapping) - modelChangeFieldMap!![idx] = newFieldIndex + noteTypeChangeFieldMap!!.remove(previousMapping) + noteTypeChangeFieldMap!![idx] = newFieldIndex } else if (idx < items.size) { // Can simply set the new mapping if no conflicts - modelChangeFieldMap!![idx] = newFieldIndex + noteTypeChangeFieldMap!![idx] = newFieldIndex } // Reload the fields updateFieldsFromMap(currentlySelectedNotetype) @@ -2262,7 +2262,7 @@ class NoteEditor : launchCatchingTask { deckSpinnerSelection!!.selectDeckById(deckId, false) } } - /** Refreshes the UI using the currently selected model as a template */ + /** Refreshes the UI using the currently selected note type as a template */ private fun refreshNoteData(changeType: FieldChangeType) { setNote(null, changeType) } @@ -2493,7 +2493,7 @@ class NoteEditor : private fun setNoteTypePosition() { // Set current note type and deck positions in spinners - val position = allModelIds!!.indexOf(editorNote!!.notetype.getLong("id")) + val position = allNoteTypeIds!!.indexOf(editorNote!!.notetype.getLong("id")) // set selection without firing selectionChanged event noteTypeSpinner!!.setSelection(position, false) } @@ -2528,9 +2528,9 @@ class NoteEditor : } /** Update the list of card templates for current note type */ - private fun updateCards(model: JSONObject?) { + private fun updateCards(noteType: JSONObject?) { Timber.d("updateCards()") - val tmpls = model!!.getJSONArray("tmpls") + val tmpls = noteType!!.getJSONArray("tmpls") var cardsList = StringBuilder() // Build comma separated list of card names Timber.d("updateCards() template count is %s", tmpls.length()) @@ -2539,7 +2539,7 @@ class NoteEditor : // If more than one card, and we have an existing card, underline existing card if (!addNote && tmpls.length() > 1 && - model === editorNote!!.notetype && + noteType === editorNote!!.notetype && currentEditedCard != null && currentEditedCard!!.template(getColUnsafe).optString("name") == name ) { @@ -2576,8 +2576,8 @@ class NoteEditor : private val currentlySelectedNotetype: NotetypeJson? get() = noteTypeSpinner?.selectedItemPosition?.let { position -> - allModelIds?.get(position)?.let { modelId -> - getColUnsafe.notetypes.get(modelId) + allNoteTypeIds?.get(position)?.let { noteTypeId -> + getColUnsafe.notetypes.get(noteTypeId) } } @@ -2585,17 +2585,17 @@ class NoteEditor : * Update all the field EditText views based on the currently selected note type and the mModelChangeFieldMap */ private fun updateFieldsFromMap(newNotetype: NotetypeJson?) { - val type = FieldChangeType.refreshWithMap(newNotetype, modelChangeFieldMap, shouldReplaceNewlines()) + val type = FieldChangeType.refreshWithMap(newNotetype, noteTypeChangeFieldMap, shouldReplaceNewlines()) populateEditFields(type, true) updateCards(newNotetype) } /** * - * @return whether or not to allow remapping of fields for current model + * @return whether or not to allow remapping of fields for current note type */ private fun allowFieldRemapping(): Boolean { - // Map> fMapNew = getCol().getModels().fieldMap(getCurrentlySelectedModel()) + // Map> fMapNew = getCol().getNoteTypes().fieldMap(getCurrentlySelectedModel()) return editorNote!!.items().size > 2 } @@ -2625,27 +2625,27 @@ class NoteEditor : } private fun changeNoteType(newId: NoteTypeId) { - val oldModelId = getColUnsafe.notetypes.current().getLong("id") + val oldNoteTypeId = getColUnsafe.notetypes.current().getLong("id") Timber.i("Changing note type to '%d", newId) - if (oldModelId == newId) { + if (oldNoteTypeId == newId) { return } - val model = getColUnsafe.notetypes.get(newId) - if (model == null) { - Timber.w("New model %s not found, not changing note type", newId) + val noteType = getColUnsafe.notetypes.get(newId) + if (noteType == null) { + Timber.w("New note type %s not found, not changing note type", newId) return } - getColUnsafe.notetypes.setCurrent(model) + getColUnsafe.notetypes.setCurrent(noteType) val currentDeck = getColUnsafe.decks.current() currentDeck.put("mid", newId) getColUnsafe.decks.save(currentDeck) // Update deck if (!getColUnsafe.config.getBool(ConfigKey.Bool.ADDING_DEFAULTS_TO_CURRENT_DECK)) { - deckId = model.optLong("did", Consts.DEFAULT_DECK_ID) + deckId = noteType.optLong("did", Consts.DEFAULT_DECK_ID) } refreshNoteData(FieldChangeType.changeFieldCount(shouldReplaceNewlines())) @@ -2667,7 +2667,7 @@ class NoteEditor : // Timber.i("NoteEditor:: onItemSelected() fired on mNoteTypeSpinner"); // In case the type is changed while adding the card, the menu options need to be invalidated mainToolbar.invalidateMenu() - changeNoteType(allModelIds!![pos]) + changeNoteType(allNoteTypeIds!![pos]) } override fun onNothingSelected(parent: AdapterView<*>?) { @@ -2683,42 +2683,42 @@ class NoteEditor : pos: Int, id: Long, ) { - // Get the current model - val noteModelId = currentEditedCard!!.noteType(getColUnsafe).getLong("id") - // Get new model - val newModel = getColUnsafe.notetypes.get(allModelIds!![pos]) - if (newModel == null) { - Timber.w("newModel %s not found", allModelIds!![pos]) + // Get the current note type + val noteNoteTypeId = currentEditedCard!!.noteType(getColUnsafe).getLong("id") + // Get new note type + val newNoteType = getColUnsafe.notetypes.get(allNoteTypeIds!![pos]) + if (newNoteType == null) { + Timber.w("newNoteType %s not found", allNoteTypeIds!![pos]) return } // Configure the interface according to whether note type is getting changed or not - if (allModelIds!![pos] != noteModelId) { + if (allNoteTypeIds!![pos] != noteNoteTypeId) { @KotlinCleanup("Check if this ever happens") val tmpls = try { - newModel.getJSONArray("tmpls") + newNoteType.getJSONArray("tmpls") } catch (e: Exception) { - Timber.w("error in obtaining templates from model %s", allModelIds!![pos]) + Timber.w("error in obtaining templates from note type %s", allNoteTypeIds!![pos]) return } - // Initialize mapping between fields of old model -> new model + // Initialize mapping between fields of old note type -> new note type val itemsLength = editorNote!!.items().size - modelChangeFieldMap = HashUtil.hashMapInit(itemsLength) + noteTypeChangeFieldMap = HashUtil.hashMapInit(itemsLength) for (i in 0 until itemsLength) { - modelChangeFieldMap!![i] = i + noteTypeChangeFieldMap!![i] = i } - // Initialize mapping between cards new model -> old model + // Initialize mapping between cards new note type -> old note type val templatesLength = tmpls.length() - modelChangeCardMap = HashUtil.hashMapInit(templatesLength) + noteTypeChangeCardMap = HashUtil.hashMapInit(templatesLength) for (i in 0 until templatesLength) { if (i < editorNote!!.numberOfCards(getColUnsafe)) { - modelChangeCardMap!![i] = i + noteTypeChangeCardMap!![i] = i } else { - modelChangeCardMap!![i] = null + noteTypeChangeCardMap!![i] = null } } // Update the field text edits based on the default mapping just assigned - updateFieldsFromMap(newModel) + updateFieldsFromMap(newNoteType) // Don't let the user change any other values at the same time as changing note type selectedTags = editorNote!!.tags updateTags() @@ -2788,8 +2788,8 @@ class NoteEditor : fun getFieldForTest(index: Int): FieldEditText = editFields!![index] @VisibleForTesting(otherwise = VisibleForTesting.NONE) - fun setCurrentlySelectedModel(mid: NoteTypeId) { - val position = allModelIds!!.indexOf(mid) + fun setCurrentlySelectedNoteType(mid: NoteTypeId) { + val position = allNoteTypeIds!!.indexOf(mid) check(position != -1) { "$mid not found" } noteTypeSpinner!!.setSelection(position) } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ModelFieldEditor.kt b/AnkiDroid/src/main/java/com/ichi2/anki/NoteTypeFieldEditor.kt similarity index 93% rename from AnkiDroid/src/main/java/com/ichi2/anki/ModelFieldEditor.kt rename to AnkiDroid/src/main/java/com/ichi2/anki/NoteTypeFieldEditor.kt index 85829becb86a..5cb4925943eb 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ModelFieldEditor.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/NoteTypeFieldEditor.kt @@ -33,8 +33,8 @@ import com.ichi2.anki.CollectionManager.withCol import com.ichi2.anki.dialogs.ConfirmationDialog import com.ichi2.anki.dialogs.LocaleSelectionDialog import com.ichi2.anki.dialogs.LocaleSelectionDialog.LocaleSelectionDialogHandler -import com.ichi2.anki.dialogs.ModelEditorContextMenu.Companion.newInstance -import com.ichi2.anki.dialogs.ModelEditorContextMenu.ModelEditorContextMenuAction +import com.ichi2.anki.dialogs.NoteTypeEditorContextMenu.Action +import com.ichi2.anki.dialogs.NoteTypeEditorContextMenu.Companion.newInstance import com.ichi2.anki.servicelayer.LanguageHintService.setLanguageHintForField import com.ichi2.anki.snackbar.showSnackbar import com.ichi2.anki.utils.ext.dismissAllDialogFragments @@ -55,7 +55,7 @@ import org.json.JSONException import timber.log.Timber import java.util.Locale -class ModelFieldEditor : +class NoteTypeFieldEditor : AnkiActivity(), LocaleSelectionDialogHandler { // Position of the current field selected @@ -76,7 +76,7 @@ class ModelFieldEditor : return } super.onCreate(savedInstanceState) - setContentView(R.layout.model_field_editor) + setContentView(R.layout.note_type_field_editor) fieldsListView = findViewById(R.id.note_type_editor_fields) enableToolbar().apply { setTitle(R.string.model_field_editor_title) @@ -94,7 +94,7 @@ class ModelFieldEditor : override fun onCreateOptionsMenu(menu: Menu): Boolean { super.onCreateOptionsMenu(menu) - menuInflater.inflate(R.menu.model_editor, menu) + menuInflater.inflate(R.menu.note_type_editor, menu) return true } @@ -111,22 +111,22 @@ class ModelFieldEditor : // ---------------------------------------------------------------------------- /** - * Initialize the data holding properties and the UI from the model. This method expects that it + * Initialize the data holding properties and the UI from the note type. This method expects that it * isn't followed by other type of work that access the data properties as it has the capability * to finish the activity. */ private fun initialize() { val noteTypeID = intent.getLongExtra("noteTypeID", 0) - val collectionModel = getColUnsafe.notetypes.get(noteTypeID) - if (collectionModel == null) { + val collectionNoteType = getColUnsafe.notetypes.get(noteTypeID) + if (collectionNoteType == null) { showThemedToast(this, R.string.field_editor_model_not_available, true) finish() return } - notetype = collectionModel + notetype = collectionNoteType noteFields = notetype.flds - fieldsLabels = notetype.fieldsNames - fieldsListView.adapter = ArrayAdapter(this, R.layout.model_field_editor_list_item, fieldsLabels) + fieldsLabels = noteFields.fieldsNames + fieldsListView.adapter = ArrayAdapter(this, R.layout.note_type_field_editor_list_item, fieldsLabels) fieldsListView.onItemClickListener = AdapterView.OnItemClickListener { _, _, position: Int, _ -> showDialogFragment(newInstance(fieldsLabels[position])) @@ -201,7 +201,7 @@ class ModelFieldEditor : } } c.setConfirm(confirm) - this@ModelFieldEditor.showDialogFragment(c) + this@NoteTypeFieldEditor.showDialogFragment(c) } getColUnsafe.notetypes.update(notetype) initialize() @@ -331,7 +331,7 @@ class ModelFieldEditor : } } c.setConfirm(confirm) - this@ModelFieldEditor.showDialogFragment(c) + this@NoteTypeFieldEditor.showDialogFragment(c) } } negativeButton(R.string.dialog_cancel) @@ -340,7 +340,7 @@ class ModelFieldEditor : } /* - * Allows the user to select a number less than the number of fields in the current model to + * Allows the user to select a number less than the number of fields in the current note type to * reposition the current field to * Processing time is scales with number of items */ @@ -384,7 +384,7 @@ class ModelFieldEditor : } } c.setConfirm(confirm) - this@ModelFieldEditor.showDialogFragment(c) + this@NoteTypeFieldEditor.showDialogFragment(c) } } } @@ -449,7 +449,7 @@ class ModelFieldEditor : launchCatchingTask { changeSortField(notetype, currentPos) } } c.setConfirm(confirm) - this@ModelFieldEditor.showDialogFragment(c) + this@NoteTypeFieldEditor.showDialogFragment(c) } } @@ -477,7 +477,7 @@ class ModelFieldEditor : override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) { - R.id.action_add_new_model -> { + R.id.action_add_new_note_type -> { addFieldDialog() true } @@ -488,14 +488,14 @@ class ModelFieldEditor : finish() } - fun handleAction(contextMenuAction: ModelEditorContextMenuAction) { + fun handleAction(contextMenuAction: Action) { when (contextMenuAction) { - ModelEditorContextMenuAction.Sort -> sortByField() - ModelEditorContextMenuAction.Reposition -> repositionFieldDialog() - ModelEditorContextMenuAction.Delete -> deleteFieldDialog() - ModelEditorContextMenuAction.Rename -> renameFieldDialog() - ModelEditorContextMenuAction.ToggleSticky -> toggleStickyField() - ModelEditorContextMenuAction.AddLanguageHint -> localeHintDialog() + Action.Sort -> sortByField() + Action.Reposition -> repositionFieldDialog() + Action.Delete -> deleteFieldDialog() + Action.Rename -> renameFieldDialog() + Action.ToggleSticky -> toggleStickyField() + Action.AddLanguageHint -> localeHintDialog() } } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserColumnCollection.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserColumnCollection.kt index 180c2d5dd436..2da4d8ebe652 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserColumnCollection.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserColumnCollection.kt @@ -24,10 +24,7 @@ import com.ichi2.anki.model.CardsOrNotes import com.ichi2.anki.model.CardsOrNotes.CARDS import com.ichi2.anki.model.CardsOrNotes.NOTES import com.ichi2.libanki.BrowserConfig -import com.ichi2.libanki.BrowserConfig.ACTIVE_CARD_COLUMNS_KEY -import com.ichi2.libanki.BrowserConfig.ACTIVE_NOTE_COLUMNS_KEY import com.ichi2.libanki.BrowserDefaults -import net.ankiweb.rsdroid.Backend import timber.log.Timber /** diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/ModelEditorContextMenu.kt b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/NoteTypeEditorContextMenu.kt similarity index 79% rename from AnkiDroid/src/main/java/com/ichi2/anki/dialogs/ModelEditorContextMenu.kt rename to AnkiDroid/src/main/java/com/ichi2/anki/dialogs/NoteTypeEditorContextMenu.kt index a386cd380679..aff8f815f68e 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/ModelEditorContextMenu.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/NoteTypeEditorContextMenu.kt @@ -9,7 +9,7 @@ import androidx.annotation.StringRes import androidx.annotation.VisibleForTesting import androidx.appcompat.app.AlertDialog import androidx.core.os.bundleOf -import com.ichi2.anki.ModelFieldEditor +import com.ichi2.anki.NoteTypeFieldEditor import com.ichi2.anki.R import com.ichi2.anki.analytics.AnalyticsDialogFragment import com.ichi2.utils.create @@ -18,22 +18,22 @@ import timber.log.Timber /** * Note: the class is declared as open only to support testing. */ -open class ModelEditorContextMenu : AnalyticsDialogFragment() { +open class NoteTypeEditorContextMenu : AnalyticsDialogFragment() { @SuppressLint("CheckResult") override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { super.onCreate(savedInstanceState) - val availableItems = ModelEditorContextMenuAction.entries.sortedBy { it.order } + val availableItems = Action.entries.sortedBy { it.order } return AlertDialog.Builder(requireActivity()).create { setTitle(requireArguments().getString(KEY_LABEL)) setItems(availableItems.map { resources.getString(it.actionTextId) }.toTypedArray()) { _, index -> - (activity as? ModelFieldEditor)?.run { handleAction(availableItems[index]) } + (activity as? NoteTypeFieldEditor)?.run { handleAction(availableItems[index]) } ?: Timber.e("ContextMenu used from outside of its target activity!") } } } - enum class ModelEditorContextMenuAction( + enum class Action( val order: Int, @StringRes val actionTextId: Int, ) { @@ -49,8 +49,8 @@ open class ModelEditorContextMenu : AnalyticsDialogFragment() { @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) const val KEY_LABEL = "key_label" - fun newInstance(label: String): ModelEditorContextMenu = - ModelEditorContextMenu().apply { + fun newInstance(label: String): NoteTypeEditorContextMenu = + NoteTypeEditorContextMenu().apply { arguments = bundleOf(KEY_LABEL to label) } } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/multimediacard/impl/MultimediaEditableNote.kt b/AnkiDroid/src/main/java/com/ichi2/anki/multimediacard/impl/MultimediaEditableNote.kt index 675caf10d89c..dc54b3506eda 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/multimediacard/impl/MultimediaEditableNote.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/multimediacard/impl/MultimediaEditableNote.kt @@ -34,7 +34,7 @@ class MultimediaEditableNote : IMultimediaEditableNote { override var isModified = false private set private var fields: ArrayList? = null - var modelId: NoteTypeId = 0 + var noteTypeId: NoteTypeId = 0 /** * Field values in the note editor, before any editing has taken place diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/noteeditor/FieldState.kt b/AnkiDroid/src/main/java/com/ichi2/anki/noteeditor/FieldState.kt index 39dd7b4922e0..fccaddb47b93 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/noteeditor/FieldState.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/noteeditor/FieldState.kt @@ -92,7 +92,7 @@ class FieldState private constructor( if (type.type == Type.REFRESH_WITH_MAP) { val items = editor.fieldsFromSelectedNote val fMapNew = Notetypes.fieldMap(type.newNotetype!!) - return fromFieldMap(editor.requireContext(), items, fMapNew, type.modelChangeFieldMap) + return fromFieldMap(editor.requireContext(), items, fMapNew, type.noteTypeChangeFieldMap) } return editor.fieldsFromSelectedNote } @@ -106,18 +106,18 @@ class FieldState private constructor( val type: Type, val replaceNewlines: Boolean, ) { - var modelChangeFieldMap: Map? = null + var noteTypeChangeFieldMap: Map? = null var newNotetype: NotetypeJson? = null companion object { fun refreshWithMap( newNotetype: NotetypeJson?, - modelChangeFieldMap: Map?, + noteTypeChangeFieldMap: Map?, replaceNewlines: Boolean, ): FieldChangeType { val typeClass = FieldChangeType(Type.REFRESH_WITH_MAP, replaceNewlines) typeClass.newNotetype = newNotetype - typeClass.modelChangeFieldMap = modelChangeFieldMap + typeClass.noteTypeChangeFieldMap = noteTypeChangeFieldMap return typeClass } @@ -154,7 +154,7 @@ class FieldState private constructor( context: Context, oldFields: Array>, fMapNew: Map>, - modelChangeFieldMap: Map?, + noteTypeChangeFieldMap: Map?, ): Array> { // Build array of label/values to provide to field EditText views val fields = Array(fMapNew.size) { arrayOfNulls(2) } @@ -163,9 +163,9 @@ class FieldState private constructor( // Field index of new note type val i = fieldPair.first // Add values from old note type if they exist in map, otherwise make the new field empty - if (modelChangeFieldMap!!.containsValue(i)) { + if (noteTypeChangeFieldMap!!.containsValue(i)) { // Get index of field from old note type given the field index of new note type - val j = getKeyByValue(modelChangeFieldMap, i) ?: continue + val j = getKeyByValue(noteTypeChangeFieldMap, i) ?: continue // Set the new field label text if (allowFieldRemapping(oldFields)) { // Show the content of old field if remapping is enabled diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/notetype/AddNewNotesType.kt b/AnkiDroid/src/main/java/com/ichi2/anki/notetype/AddNewNotesType.kt index 3cb0a3804cd9..48ba50074ac9 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/notetype/AddNewNotesType.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/notetype/AddNewNotesType.kt @@ -53,7 +53,7 @@ class AddNewNotesType( val (allOptions, currentNames) = activity.withProgress { withCol { - val standardNotetypesModels = + val standardNotetypesNoteTypes = StockNotetype.Kind.entries .filter { it != StockNotetype.Kind.UNRECOGNIZED } .map { @@ -67,7 +67,7 @@ class AddNewNotesType( val foundNotetypes = getNotetypeNames() Pair( mutableListOf().apply { - addAll(standardNotetypesModels) + addAll(standardNotetypesNoteTypes) addAll(foundNotetypes.map { it.toUiModel() }) }, foundNotetypes.map { it.name }, @@ -165,11 +165,11 @@ class AddNewNotesType( private fun cloneStandardNotetype( newName: String, - model: AddNotetypeUiModel, + noteType: AddNotetypeUiModel, ) { activity.launchCatchingTask { activity.runAndRefreshAfter { - val targetNotetype = getNotetype(model.id) + val targetNotetype = getNotetype(noteType.id) val newNotetype = targetNotetype.copy { id = 0 diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/notetype/ManageNotetypes.kt b/AnkiDroid/src/main/java/com/ichi2/anki/notetype/ManageNotetypes.kt index 0ae59b3dd810..0806dd4ac13c 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/notetype/ManageNotetypes.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/notetype/ManageNotetypes.kt @@ -32,7 +32,7 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton import com.ichi2.anki.AnkiActivity import com.ichi2.anki.CardTemplateEditor import com.ichi2.anki.CollectionManager.withCol -import com.ichi2.anki.ModelFieldEditor +import com.ichi2.anki.NoteTypeFieldEditor import com.ichi2.anki.R import com.ichi2.anki.launchCatchingTask import com.ichi2.anki.snackbar.showSnackbar @@ -66,14 +66,14 @@ class ManageNotetypes : AnkiActivity() { NotetypesAdapter( this@ManageNotetypes, onShowFields = { - launchForChanges( + launchForChanges( mapOf( "title" to it.name, "noteTypeID" to it.id, ), ) }, - onEditCards = { launchForChanges(mapOf("modelId" to it.id)) }, + onEditCards = { launchForChanges(mapOf("noteTypeId" to it.id)) }, onRename = ::renameNotetype, onDelete = ::deleteNotetype, ) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/provider/CardContentProvider.kt b/AnkiDroid/src/main/java/com/ichi2/anki/provider/CardContentProvider.kt index 147a4985c301..5b6be17c10ac 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/provider/CardContentProvider.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/provider/CardContentProvider.kt @@ -41,7 +41,6 @@ import com.ichi2.libanki.Consts import com.ichi2.libanki.Deck import com.ichi2.libanki.DeckId import com.ichi2.libanki.Decks -import com.ichi2.libanki.Field import com.ichi2.libanki.Note import com.ichi2.libanki.NoteId import com.ichi2.libanki.NoteTypeId @@ -74,9 +73,9 @@ import java.io.IOException * * .../notes/#/cards (access cards of note) * * .../notes/#/cards/# (access specific card of note) * * .../models (search for models) - * * .../models/# (direct access to model). String id 'current' can be used in place of # for the current model - * * .../models/#/fields (access to field definitions of a model) - * * .../models/#/templates (access to card templates of a model) + * * .../models/# (direct access to model). String id 'current' can be used in place of # for the current note type + * * .../models/#/fields (access to field definitions of a note type) + * * .../models/#/templates (access to card templates of a note type) * * .../schedule (access the study schedule) * * .../decks (access the deck list) * * .../decks/# (access the specified deck) @@ -97,12 +96,12 @@ class CardContentProvider : ContentProvider() { private const val NOTES_ID_CARDS = 1003 private const val NOTES_ID_CARDS_ORD = 1004 private const val NOTES_V2 = 1005 - private const val MODELS = 2000 - private const val MODELS_ID = 2001 - private const val MODELS_ID_EMPTY_CARDS = 2002 - private const val MODELS_ID_TEMPLATES = 2003 - private const val MODELS_ID_TEMPLATES_ID = 2004 - private const val MODELS_ID_FIELDS = 2005 + private const val NOTE_TYPES = 2000 + private const val NOTE_TYPES_ID = 2001 + private const val NOTE_TYPES_ID_EMPTY_CARDS = 2002 + private const val NOTE_TYPES_ID_TEMPLATES = 2003 + private const val NOTE_TYPES_ID_TEMPLATES_ID = 2004 + private const val NOTE_TYPES_ID_FIELDS = 2005 private const val SCHEDULE = 3000 private const val DECKS = 4000 private const val DECK_SELECTED = 4001 @@ -148,12 +147,12 @@ class CardContentProvider : ContentProvider() { addUri("notes/#", NOTES_ID) addUri("notes/#/cards", NOTES_ID_CARDS) addUri("notes/#/cards/#", NOTES_ID_CARDS_ORD) - addUri("models", MODELS) - addUri("models/*", MODELS_ID) // the model ID can also be "current" - addUri("models/*/empty_cards", MODELS_ID_EMPTY_CARDS) - addUri("models/*/templates", MODELS_ID_TEMPLATES) - addUri("models/*/templates/#", MODELS_ID_TEMPLATES_ID) - addUri("models/*/fields", MODELS_ID_FIELDS) + addUri("models", NOTE_TYPES) + addUri("models/*", NOTE_TYPES_ID) // the note type ID can also be "current" + addUri("models/*/empty_cards", NOTE_TYPES_ID_EMPTY_CARDS) + addUri("models/*/templates", NOTE_TYPES_ID_TEMPLATES) + addUri("models/*/templates/#", NOTE_TYPES_ID_TEMPLATES_ID) + addUri("models/*/fields", NOTE_TYPES_ID_FIELDS) addUri("schedule/", SCHEDULE) addUri("decks/", DECKS) addUri("decks/#", DECKS_ID) @@ -182,12 +181,12 @@ class CardContentProvider : ContentProvider() { return when (sUriMatcher.match(uri)) { NOTES_V2, NOTES -> FlashCardsContract.Note.CONTENT_TYPE NOTES_ID -> FlashCardsContract.Note.CONTENT_ITEM_TYPE - NOTES_ID_CARDS, MODELS_ID_EMPTY_CARDS -> FlashCardsContract.Card.CONTENT_TYPE + NOTES_ID_CARDS, NOTE_TYPES_ID_EMPTY_CARDS -> FlashCardsContract.Card.CONTENT_TYPE NOTES_ID_CARDS_ORD -> FlashCardsContract.Card.CONTENT_ITEM_TYPE - MODELS -> FlashCardsContract.Model.CONTENT_TYPE - MODELS_ID -> FlashCardsContract.Model.CONTENT_ITEM_TYPE - MODELS_ID_TEMPLATES -> FlashCardsContract.CardTemplate.CONTENT_TYPE - MODELS_ID_TEMPLATES_ID -> FlashCardsContract.CardTemplate.CONTENT_ITEM_TYPE + NOTE_TYPES -> FlashCardsContract.Model.CONTENT_TYPE + NOTE_TYPES_ID -> FlashCardsContract.Model.CONTENT_ITEM_TYPE + NOTE_TYPES_ID_TEMPLATES -> FlashCardsContract.CardTemplate.CONTENT_TYPE + NOTE_TYPES_ID_TEMPLATES_ID -> FlashCardsContract.CardTemplate.CONTENT_ITEM_TYPE SCHEDULE -> FlashCardsContract.ReviewInfo.CONTENT_TYPE DECKS, DECK_SELECTED, DECKS_ID -> FlashCardsContract.Deck.CONTENT_TYPE else -> throw IllegalArgumentException("uri $uri is not supported") @@ -199,7 +198,7 @@ class CardContentProvider : ContentProvider() { /** Enforce permissions for all updates on Android M and above. Otherwise block depending on URI and client app */ private fun shouldEnforceUpdateSecurity(uri: Uri): Boolean { - val whitelist = listOf(NOTES_ID_CARDS_ORD, MODELS_ID, MODELS_ID_TEMPLATES_ID, SCHEDULE, DECK_SELECTED) + val whitelist = listOf(NOTES_ID_CARDS_ORD, NOTE_TYPES_ID, NOTE_TYPES_ID_TEMPLATES_ID, SCHEDULE, DECK_SELECTED) return !whitelist.contains(sUriMatcher.match(uri)) || knownRogueClient() } @@ -260,53 +259,53 @@ class CardContentProvider : ContentProvider() { addCardToCursor(currentCard, rv, col, columns) rv } - MODELS -> { - val models = col.notetypes + NOTE_TYPES -> { + val noteTypes = col.notetypes val columns = projection ?: FlashCardsContract.Model.DEFAULT_PROJECTION val rv = MatrixCursor(columns, 1) - for (modelId: NoteTypeId in models.ids()) { - addModelToCursor(modelId, models, rv, columns) + for (noteTypeId: NoteTypeId in noteTypes.ids()) { + addNoteTypeToCursor(noteTypeId, noteTypes, rv, columns) } rv } - MODELS_ID -> { - val modelId = getModelIdFromUri(uri, col) + NOTE_TYPES_ID -> { + val noteTypeId = getNoteTypeIdFromUri(uri, col) val columns = projection ?: FlashCardsContract.Model.DEFAULT_PROJECTION val rv = MatrixCursor(columns, 1) - addModelToCursor(modelId, col.notetypes, rv, columns) + addNoteTypeToCursor(noteTypeId, col.notetypes, rv, columns) rv } - MODELS_ID_TEMPLATES -> { - // Direct access model templates - val models = col.notetypes - val currentModel = models.get(getModelIdFromUri(uri, col)) + NOTE_TYPES_ID_TEMPLATES -> { + // Direct access note type templates + val noteTypes = col.notetypes + val currentNoteType = noteTypes.get(getNoteTypeIdFromUri(uri, col)) val columns = projection ?: FlashCardsContract.CardTemplate.DEFAULT_PROJECTION val rv = MatrixCursor(columns, 1) try { - val templates = currentModel!!.getJSONArray("tmpls") + val templates = currentNoteType!!.getJSONArray("tmpls") var idx = 0 while (idx < templates.length()) { val template = templates.getJSONObject(idx) - addTemplateToCursor(template, currentModel, idx + 1, models, rv, columns) + addTemplateToCursor(template, currentNoteType, idx + 1, noteTypes, rv, columns) idx++ } } catch (e: JSONException) { - throw IllegalArgumentException("Model is malformed", e) + throw IllegalArgumentException("Note type is malformed", e) } rv } - MODELS_ID_TEMPLATES_ID -> { - // Direct access model template with specific ID - val models = col.notetypes + NOTE_TYPES_ID_TEMPLATES_ID -> { + // Direct access note type template with specific ID + val noteTypes = col.notetypes val ord = uri.lastPathSegment!!.toInt() - val currentModel = models.get(getModelIdFromUri(uri, col)) + val currentNoteType = noteTypes.get(getNoteTypeIdFromUri(uri, col)) val columns = projection ?: FlashCardsContract.CardTemplate.DEFAULT_PROJECTION val rv = MatrixCursor(columns, 1) try { val template = getTemplateFromUri(uri, col) - addTemplateToCursor(template, currentModel, ord + 1, models, rv, columns) + addTemplateToCursor(template, currentNoteType, ord + 1, noteTypes, rv, columns) } catch (e: JSONException) { - throw IllegalArgumentException("Model is malformed", e) + throw IllegalArgumentException("Note type is malformed", e) } rv } @@ -506,10 +505,10 @@ class CardContentProvider : ContentProvider() { throw IllegalArgumentException("Currently only updates of decks are supported") } } - MODELS -> throw IllegalArgumentException("Cannot update models in bulk") - MODELS_ID -> { + NOTE_TYPES -> throw IllegalArgumentException("Cannot update models in bulk") + NOTE_TYPES_ID -> { // Get the input parameters - val newModelName = values!!.getAsString(FlashCardsContract.Model.NAME) + val newNoteTypeName = values!!.getAsString(FlashCardsContract.Model.NAME) val newCss = values.getAsString(FlashCardsContract.Model.CSS) val newDid = values.getAsString(FlashCardsContract.Model.DECK_ID) val newFieldList = values.getAsString(FlashCardsContract.Model.FIELD_NAMES) @@ -522,47 +521,47 @@ class CardContentProvider : ContentProvider() { val newLatexPost = values.getAsString(FlashCardsContract.Model.LATEX_POST) val newLatexPre = values.getAsString(FlashCardsContract.Model.LATEX_PRE) // Get the original note JSON - val model = col.notetypes.get(getModelIdFromUri(uri, col)) + val noteType = col.notetypes.get(getNoteTypeIdFromUri(uri, col)) try { - // Update model name and/or css - if (newModelName != null) { - model!!.put("name", newModelName) + // Update noteType name and/or css + if (newNoteTypeName != null) { + noteType!!.put("name", newNoteTypeName) updated++ } if (newCss != null) { - model!!.put("css", newCss) + noteType!!.put("css", newCss) updated++ } if (newDid != null) { if (col.decks.isFiltered(newDid.toLong())) { - throw IllegalArgumentException("Cannot set a filtered deck as default deck for a model") + throw IllegalArgumentException("Cannot set a filtered deck as default deck for a noteType") } - model!!.put("did", newDid) + noteType!!.put("did", newDid) updated++ } if (newSortf != null) { - model!!.put("sortf", newSortf) + noteType!!.put("sortf", newSortf) updated++ } if (newType != null) { - model!!.put("type", newType) + noteType!!.put("type", newType) updated++ } if (newLatexPost != null) { - model!!.put("latexPost", newLatexPost) + noteType!!.put("latexPost", newLatexPost) updated++ } if (newLatexPre != null) { - model!!.put("latexPre", newLatexPre) + noteType!!.put("latexPre", newLatexPre) updated++ } - col.notetypes.save(model!!) + col.notetypes.save(noteType!!) } catch (e: JSONException) { - Timber.e(e, "JSONException updating model") + Timber.e(e, "JSONException updating noteType") } } - MODELS_ID_TEMPLATES -> throw IllegalArgumentException("Cannot update templates in bulk") - MODELS_ID_TEMPLATES_ID -> { + NOTE_TYPES_ID_TEMPLATES -> throw IllegalArgumentException("Cannot update templates in bulk") + NOTE_TYPES_ID_TEMPLATES_ID -> { val mid = values!!.getAsLong(FlashCardsContract.CardTemplate.MODEL_ID) val ord = values.getAsInteger(FlashCardsContract.CardTemplate.ORD) val name = values.getAsString(FlashCardsContract.CardTemplate.NAME) @@ -574,11 +573,11 @@ class CardContentProvider : ContentProvider() { if (mid != null || ord != null) { throw IllegalArgumentException("Updates to mid or ord are not allowed") } - // Update the model + // Update the noteType try { val templateOrd = uri.lastPathSegment!!.toInt() - val existingModel = col.notetypes.get(getModelIdFromUri(uri, col)) - val templates = existingModel!!.getJSONArray("tmpls") + val existingNoteType = col.notetypes.get(getNoteTypeIdFromUri(uri, col)) + val templates = existingNoteType!!.getJSONArray("tmpls") val template = templates.getJSONObject(templateOrd) if (name != null) { template.put("name", name) @@ -600,12 +599,12 @@ class CardContentProvider : ContentProvider() { template.put("bafmt", bafmt) updated++ } - // Save the model + // Save the noteType templates.put(templateOrd, template) - existingModel.put("tmpls", templates) - col.notetypes.save(existingModel) + existingNoteType.put("tmpls", templates) + col.notetypes.save(existingNoteType) } catch (e: JSONException) { - throw IllegalArgumentException("Model is malformed", e) + throw IllegalArgumentException("Note type is malformed", e) } } SCHEDULE -> { @@ -690,8 +689,8 @@ class CardContentProvider : ContentProvider() { 1 } // MODELS_ID_EMPTY_CARDS -> { -// val model = col.models.get(getModelIdFromUri(uri, col)) ?: return -1 -// val cids: List = col.genCards(col.models.nids(model), model)!! +// val noteType = col.models.get(getNoteTypeIdFromUri(uri, col)) ?: return -1 +// val cids: List = col.genCards(col.models.nids(noteType), noteType)!! // col.removeCardsAndOrphanedNotes(cids) // cids.size // } @@ -735,7 +734,7 @@ class CardContentProvider : ContentProvider() { } /** - * This implementation optimizes for when the notes are grouped according to model. + * This implementation optimizes for when the notes are grouped according to note type. */ private fun bulkInsertNotes( valuesArr: Array?, @@ -755,14 +754,14 @@ class CardContentProvider : ContentProvider() { val values: ContentValues = valuesArr[i] val flds = values.getAsString(FlashCardsContract.Note.FLDS) ?: continue // val allowEmpty = AllowEmpty.fromBoolean(values.getAsBoolean(FlashCardsContract.Note.ALLOW_EMPTY)) - val thisModelId = values.getAsLong(FlashCardsContract.Note.MID) - if (thisModelId == null || thisModelId < 0) { - Timber.d("Unable to get model at index: %d", i) + val thisNoteTypeId = values.getAsLong(FlashCardsContract.Note.MID) + if (thisNoteTypeId == null || thisNoteTypeId < 0) { + Timber.d("Unable to get note type at index: %d", i) continue } val fldsArray = Utils.splitFields(flds) // Create empty note - val newNote = Note.fromNotetypeId(col, thisModelId) + val newNote = Note.fromNotetypeId(col, thisNoteTypeId) // Set fields // Check that correct number of flds specified if (fldsArray.size != newNote.fields.size) { @@ -803,12 +802,12 @@ class CardContentProvider : ContentProvider() { NOTES -> { /* Insert new note with specified fields and tags */ - val modelId = values!!.getAsLong(FlashCardsContract.Note.MID) + val noteTypeId = values!!.getAsLong(FlashCardsContract.Note.MID) val flds = values.getAsString(FlashCardsContract.Note.FLDS) val tags = values.getAsString(FlashCardsContract.Note.TAGS) // val allowEmpty = AllowEmpty.fromBoolean(values.getAsBoolean(FlashCardsContract.Note.ALLOW_EMPTY)) // Create empty note - val newNote = Note.fromNotetypeId(col, modelId) + val newNote = Note.fromNotetypeId(col, noteTypeId) // Set fields val fldsArray = Utils.splitFields(flds) // Check that correct number of flds specified @@ -833,9 +832,9 @@ class CardContentProvider : ContentProvider() { NOTES_ID_CARDS, NOTES_ID_CARDS_ORD -> throw IllegalArgumentException( "Not possible to insert cards directly (only through NOTES)", ) - MODELS -> { + NOTE_TYPES -> { // Get input arguments - val modelName = values!!.getAsString(FlashCardsContract.Model.NAME) + val noteTypeName = values!!.getAsString(FlashCardsContract.Model.NAME) val css = values.getAsString(FlashCardsContract.Model.CSS) val did = values.getAsLong(FlashCardsContract.Model.DECK_ID) val fieldNames = values.getAsString(FlashCardsContract.Model.FIELD_NAMES) @@ -845,20 +844,20 @@ class CardContentProvider : ContentProvider() { val latexPost = values.getAsString(FlashCardsContract.Model.LATEX_POST) val latexPre = values.getAsString(FlashCardsContract.Model.LATEX_PRE) // Throw exception if required fields empty - if (modelName == null || fieldNames == null || numCards == null) { - throw IllegalArgumentException("Model name, field_names, and num_cards can't be empty") + if (noteTypeName == null || fieldNames == null || numCards == null) { + throw IllegalArgumentException("Note type name, field_names, and num_cards can't be empty") } if (did != null && col.decks.isFiltered(did)) { - throw IllegalArgumentException("Cannot set a filtered deck as default deck for a model") + throw IllegalArgumentException("Cannot set a filtered deck as default deck for a note type") } - // Create a new model - val mm = col.notetypes - val newModel = mm.new(modelName) + // Create a new note type + val noteTypes = col.notetypes + val newNoteType = noteTypes.new(noteTypeName) return try { // Add the fields val allFields = Utils.splitFields(fieldNames) for (f: String? in allFields) { - mm.addFieldInNewModel(newModel, mm.newField(f!!)) + noteTypes.addFieldInNewNoteType(newNoteType, noteTypes.newField(f!!)) } // Add some empty card templates var idx = 0 @@ -871,48 +870,48 @@ class CardContentProvider : ContentProvider() { answerField = allFields[1] } t.put("afmt", "{{FrontSide}}\\n\\n
\\n\\n{{$answerField}}") - mm.addTemplateInNewModel(newModel, t) + noteTypes.addTemplateInNewNoteType(newNoteType, t) idx++ } // Add the CSS if specified if (css != null) { - newModel.put("css", css) + newNoteType.put("css", css) } // Add the did if specified if (did != null) { - newModel.put("did", did) + newNoteType.put("did", did) } if (sortf != null && sortf < allFields.size) { - newModel.put("sortf", sortf) + newNoteType.put("sortf", sortf) } if (type != null) { - newModel.put("type", type) + newNoteType.put("type", type) } if (latexPost != null) { - newModel.put("latexPost", latexPost) + newNoteType.put("latexPost", latexPost) } if (latexPre != null) { - newModel.put("latexPre", latexPre) + newNoteType.put("latexPre", latexPre) } - // Add the model to collection (from this point on edits will require a full-sync) - mm.add(newModel) + // Add the note type to collection (from this point on edits will require a full-sync) + noteTypes.add(newNoteType) // Get the mid and return a URI - val mid = newModel.getLong("id").toString() + val mid = newNoteType.getLong("id").toString() Uri.withAppendedPath(FlashCardsContract.Model.CONTENT_URI, mid) } catch (e: JSONException) { - Timber.e(e, "Could not set a field of new model %s", modelName) + Timber.e(e, "Could not set a field of new note type %s", noteTypeName) null } } - MODELS_ID -> throw IllegalArgumentException("Not possible to insert model with specific ID") - MODELS_ID_TEMPLATES -> { + NOTE_TYPES_ID -> throw IllegalArgumentException("Not possible to insert note type with specific ID") + NOTE_TYPES_ID_TEMPLATES -> { run { val notetypes: Notetypes = col.notetypes - val mid: NoteTypeId = getModelIdFromUri(uri, col) - val existingModel: NotetypeJson = + val mid: NoteTypeId = getNoteTypeIdFromUri(uri, col) + val existingNoteType: NotetypeJson = notetypes.get(mid) - ?: throw IllegalArgumentException("model missing: $mid") + ?: throw IllegalArgumentException("note type missing: $mid") val name: String = values!!.getAsString(FlashCardsContract.CardTemplate.NAME) val qfmt: String = values.getAsString(FlashCardsContract.CardTemplate.QUESTION_FORMAT) val afmt: String = values.getAsString(FlashCardsContract.CardTemplate.ANSWER_FORMAT) @@ -924,9 +923,9 @@ class CardContentProvider : ContentProvider() { t.put("afmt", afmt) t.put("bqfmt", bqfmt) t.put("bafmt", bafmt) - notetypes.addTemplate(existingModel, t) - notetypes.update(existingModel) - t = existingModel.tmpls.get(existingModel.tmpls.length() - 1) as JSONObject + notetypes.addTemplate(existingNoteType, t) + notetypes.update(existingNoteType) + t = existingNoteType.tmpls.get(existingNoteType.tmpls.length() - 1) as JSONObject return ContentUris.withAppendedId(uri, t.getInt("ord").toLong()) } catch (e: ConfirmModSchemaException) { throw IllegalArgumentException("Unable to add template without user requesting/accepting full-sync", e) @@ -935,21 +934,23 @@ class CardContentProvider : ContentProvider() { } } } - MODELS_ID_TEMPLATES_ID -> throw IllegalArgumentException("Not possible to insert template with specific ORD") - MODELS_ID_FIELDS -> { + NOTE_TYPES_ID_TEMPLATES_ID -> throw IllegalArgumentException("Not possible to insert template with specific ORD") + NOTE_TYPES_ID_FIELDS -> { run { val notetypes: Notetypes = col.notetypes - val mid: NoteTypeId = getModelIdFromUri(uri, col) - val existingModel: NotetypeJson = + val mid: NoteTypeId = getNoteTypeIdFromUri(uri, col) + val existingNoteType: NotetypeJson = notetypes.get(mid) - ?: throw IllegalArgumentException("model missing: $mid") + ?: throw IllegalArgumentException("note type missing: $mid") val name: String = values!!.getAsString(FlashCardsContract.Model.FIELD_NAME) - ?: throw IllegalArgumentException("field name missing for model: $mid") - val field: Field = notetypes.newField(name) + ?: throw IllegalArgumentException("field name missing for note type: $mid") + val field = notetypes.newField(name) try { - notetypes.addFieldLegacy(existingModel, field) - return ContentUris.withAppendedId(uri, (existingModel.flds.length() - 1).toLong()) + notetypes.addFieldLegacy(existingNoteType, field) + + val flds: JSONArray = existingNoteType.getJSONArray("flds") + return ContentUris.withAppendedId(uri, (flds.length() - 1).toLong()) } catch (e: ConfirmModSchemaException) { throw IllegalArgumentException("Unable to insert field: $name", e) } catch (e: JSONException) { @@ -1050,18 +1051,18 @@ class CardContentProvider : ContentProvider() { } } - private fun addModelToCursor( - modelId: NoteTypeId, + private fun addNoteTypeToCursor( + noteTypeId: NoteTypeId, notetypes: Notetypes, rv: MatrixCursor, columns: Array, ) { - val jsonObject = notetypes.get(modelId) + val jsonObject = notetypes.get(noteTypeId) val rb = rv.newRow() try { for (column in columns) { when (column) { - FlashCardsContract.Model._ID -> rb.add(modelId) + FlashCardsContract.Model._ID -> rb.add(noteTypeId) FlashCardsContract.Model.NAME -> rb.add(jsonObject!!.getString("name")) FlashCardsContract.Model.FIELD_NAMES -> { @KotlinCleanup("maybe jsonObject.fieldsNames. Difference: optString vs get") @@ -1089,7 +1090,7 @@ class CardContentProvider : ContentProvider() { } } catch (e: JSONException) { Timber.e(e, "Error parsing JSONArray") - throw IllegalArgumentException("Model $modelId is malformed", e) + throw IllegalArgumentException("Model $noteTypeId is malformed", e) } } @@ -1298,19 +1299,19 @@ class CardContentProvider : ContentProvider() { return col.getNote(noteId) } - private fun getModelIdFromUri( + private fun getNoteTypeIdFromUri( uri: Uri, col: Collection, ): Long { - val modelIdSegment = uri.pathSegments[1] + val noteTypeIdSegment = uri.pathSegments[1] val id: Long = - if (modelIdSegment == FlashCardsContract.Model.CURRENT_MODEL_ID) { + if (noteTypeIdSegment == FlashCardsContract.Model.CURRENT_NOTE_TYPE_ID) { col.notetypes.current().optLong("id", -1) } else { try { uri.pathSegments[1].toLong() } catch (e: NumberFormatException) { - throw IllegalArgumentException("Model ID must be either numeric or the String CURRENT_MODEL_ID", e) + throw IllegalArgumentException("Note type ID must be either numeric or the String CURRENT_NOTE_TYPE_ID", e) } } return id @@ -1321,9 +1322,9 @@ class CardContentProvider : ContentProvider() { uri: Uri, col: Collection, ): JSONObject { - val model: JSONObject? = col.notetypes.get(getModelIdFromUri(uri, col)) + val noteType: JSONObject? = col.notetypes.get(getNoteTypeIdFromUri(uri, col)) val ord = uri.lastPathSegment!!.toInt() - return model!!.getJSONArray("tmpls").getJSONObject(ord) + return noteType!!.getJSONArray("tmpls").getJSONObject(ord) } private fun throwSecurityException( diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/servicelayer/NoteService.kt b/AnkiDroid/src/main/java/com/ichi2/anki/servicelayer/NoteService.kt index 180b4c5fce5f..0ce36fac4609 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/servicelayer/NoteService.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/servicelayer/NoteService.kt @@ -49,15 +49,15 @@ import java.io.IOException object NoteService { /** - * Creates an empty Note from given Model + * Creates an empty Note from given Note type * - * @param model the model in JSONObject format + * @param noteType the note type in JSONObject format * @return a new MultimediaEditableNote instance */ - fun createEmptyNote(model: NotetypeJson): MultimediaEditableNote { + fun createEmptyNote(noteType: NotetypeJson): MultimediaEditableNote { val note = MultimediaEditableNote() try { - val fieldsArray = model.flds + val fieldsArray = noteType.flds note.setNumFields(fieldsArray.length()) for ((i, field) in fieldsArray.withIndex()) { val uiTextField = @@ -67,9 +67,9 @@ object NoteService { } note.setField(i, uiTextField) } - note.modelId = model.getLong("id") + note.noteTypeId = noteType.getLong("id") } catch (e: JSONException) { - Timber.w(e, "Error parsing model: %s", model) + Timber.w(e, "Error parsing note type: %s", noteType) // Return note with default/empty fields } return note @@ -78,7 +78,7 @@ object NoteService { fun updateMultimediaNoteFromFields( col: Collection, fields: Array, - modelId: NoteTypeId, + noteTypeId: NoteTypeId, mmNote: MultimediaEditableNote, ) { for (i in fields.indices) { @@ -96,14 +96,14 @@ object NoteService { field.setFormattedString(col, value) mmNote.setField(i, field) } - mmNote.modelId = modelId + mmNote.noteTypeId = noteTypeId mmNote.freezeInitialFieldValues() // TODO: set current id of the note as well } /** - * Updates the JsonNote field values from MultimediaEditableNote When both notes are using the same Model, it updates - * the destination field values with source values. If models are different it throws an Exception + * Updates the JsonNote field values from MultimediaEditableNote When both notes are using the same Note type, it updates + * the destination field values with source values. If note types are different it throws an Exception * * @param noteSrc * @param editorNoteDst @@ -113,7 +113,7 @@ object NoteService { editorNoteDst: Note, ) { if (noteSrc is MultimediaEditableNote) { - if (noteSrc.modelId != editorNoteDst.mid) { + if (noteSrc.noteTypeId != editorNoteDst.mid) { throw RuntimeException("Source and Destination Note ID do not match.") } val totalFields: Int = noteSrc.numberOfFields diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/NoteTypeSpinnerUtils.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/NoteTypeSpinnerUtils.kt index 0b3f052b6b19..02ac3643315a 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/NoteTypeSpinnerUtils.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/NoteTypeSpinnerUtils.kt @@ -28,19 +28,19 @@ fun setupNoteTypeSpinner( noteTypeSpinner: Spinner, col: Collection, ): List { - val sortedModels = col.notetypes.all().sortedWith(NamedJSONComparator.INSTANCE) - val modelNames = sortedModels.map { it.getString("name") } + val sortedNoteTypes = col.notetypes.all().sortedWith(NamedJSONComparator.INSTANCE) + val noteTypeNames = sortedNoteTypes.map { it.getString("name") } noteTypeSpinner.adapter = ArrayAdapter( context, android.R.layout.simple_spinner_dropdown_item, - modelNames, + noteTypeNames, ).apply { // The resource passed to the constructor is normally used for both the spinner view // and the dropdown list. This keeps the former and overrides the latter. setDropDownViewResource(R.layout.spinner_dropdown_item_with_radio) } - return sortedModels.map { it.getLong("id") } + return sortedNoteTypes.map { it.getLong("id") } } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/managespace/ManageSpaceFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/managespace/ManageSpaceFragment.kt index 0f93b6d43ea7..1cdfcb409b4b 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/managespace/ManageSpaceFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/managespace/ManageSpaceFragment.kt @@ -71,7 +71,7 @@ sealed interface Size { } /************************************************************************************************** - ********************************************* Model ********************************************** + ********************************************* Note type ****************************************** **************************************************************************************************/ class ManageSpaceViewModel( diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/utils/CardTemplateJson.kt b/AnkiDroid/src/main/java/com/ichi2/anki/utils/CardTemplateJson.kt index 721e775716fa..8c8affa971e8 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/utils/CardTemplateJson.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/utils/CardTemplateJson.kt @@ -23,7 +23,7 @@ import org.json.JSONObject class CardTemplateJson : JSONObject { /** - * Creates a new empty model object + * Creates a new empty card template object */ constructor() : super() @@ -39,7 +39,7 @@ class CardTemplateJson : JSONObject { } /** - * Creates a model object form json string + * Creates a card template object form json string */ constructor( @Language("json") json: String, diff --git a/AnkiDroid/src/main/java/com/ichi2/async/CollectionOperations.kt b/AnkiDroid/src/main/java/com/ichi2/async/CollectionOperations.kt index c6e1dea5207c..2141a3eb48a3 100644 --- a/AnkiDroid/src/main/java/com/ichi2/async/CollectionOperations.kt +++ b/AnkiDroid/src/main/java/com/ichi2/async/CollectionOperations.kt @@ -94,36 +94,36 @@ suspend fun renderBrowserQA( } /** - * Handles everything for a model change at once - template add / deletes as well as content updates + * Handles everything for a note type change at once - template add / deletes as well as content updates * @return Pair : (true, null) when success, (false, exceptionMessage) when failure */ -fun saveModel( +fun saveNoteType( col: Collection, notetype: NotetypeJson, templateChanges: ArrayList>, ) { - Timber.d("doInBackgroundSaveModel") - val oldModel = col.notetypes.get(notetype.getLong("id")) + Timber.d("doInBackgroundSaveNoteType") + val oldNoteType = col.notetypes.get(notetype.getLong("id")) // TODO: make undoable val newTemplates = notetype.getJSONArray("tmpls") for (change in templateChanges) { - val oldTemplates = oldModel!!.getJSONArray("tmpls") + val oldTemplates = oldNoteType!!.getJSONArray("tmpls") when (change[1] as CardTemplateNotetype.ChangeType) { CardTemplateNotetype.ChangeType.ADD -> { - Timber.d("doInBackgroundSaveModel() adding template %s", change[0]) - col.notetypes.addTemplate(oldModel, newTemplates.getJSONObject(change[0] as Int)) + Timber.d("doInBackgroundSaveNoteType() adding template %s", change[0]) + col.notetypes.addTemplate(oldNoteType, newTemplates.getJSONObject(change[0] as Int)) } CardTemplateNotetype.ChangeType.DELETE -> { - Timber.d("doInBackgroundSaveModel() deleting template currently at ordinal %s", change[0]) - col.notetypes.remTemplate(oldModel, oldTemplates.getJSONObject(change[0] as Int)) + Timber.d("doInBackgroundSaveNoteType() deleting template currently at ordinal %s", change[0]) + col.notetypes.remTemplate(oldNoteType, oldTemplates.getJSONObject(change[0] as Int)) } } } - // required for Rust: the modified time can't go backwards, and we updated the model by adding fields + // required for Rust: the modified time can't go backwards, and we updated the note type by adding fields // This could be done better - notetype.put("mod", oldModel!!.getLong("mod")) + notetype.put("mod", oldNoteType!!.getLong("mod")) col.notetypes.save(notetype) col.notetypes.update(notetype) } diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/Card.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/Card.kt index 4c707dbf5260..24ed9b7d2084 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/Card.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/Card.kt @@ -38,7 +38,7 @@ import org.json.JSONObject * currently belongs to), and the retrieval of presentation elements (filled-in templates). * * Card presentation has two components: the question (front) side and the answer (back) side. The presentation of the - * card is derived from the template of the card's Card Type. The Card Type is a component of the Note Type (see Models) + * card is derived from the template of the card's Card Type. The Card Type is a component of the Note Type (see [anki.notetypes.Notetype]) * that this card is derived from. * * This class is responsible for: @@ -219,11 +219,11 @@ open class Card : Cloneable { @LibAnkiAlias("template") fun template(col: Collection): JSONObject { - val m = noteType(col) - return if (m.isStd) { - m.getJSONArray("tmpls").getJSONObject(ord) + val noteType = this@Card.noteType(col) + return if (noteType.isStd) { + noteType.getJSONArray("tmpls").getJSONObject(ord) } else { - noteType(col).getJSONArray("tmpls").getJSONObject(0) + this@Card.noteType(col).getJSONArray("tmpls").getJSONObject(0) } } diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt index 7905d6b4ef4e..686a03635581 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/Collection.kt @@ -292,16 +292,16 @@ class Collection( fun noteCount(): Int = db.queryScalar("SELECT count() FROM notes") /** - * Return a new note with the model derived from the deck or the configuration - * @param forDeck When true it uses the model specified in the deck (mid), otherwise it uses the model specified in + * Return a new note with the note type derived from the deck or the configuration + * @param forDeck When true it uses the note type specified in the deck (mid), otherwise it uses the note type specified in * the configuration (curModel) * @return The new note */ fun newNote(forDeck: Boolean = true): Note = newNote(notetypes.current(forDeck)) /** - * Return a new note with a specific model - * @param notetype The model to use for the new note + * Return a new note with a specific note type + * @param notetype The note type to use for the new note * @return The new note */ fun newNote(notetype: NotetypeJson): Note = Note.fromNotetypeId(this, notetype.id) @@ -619,17 +619,17 @@ class Collection( mid not in ${ids2str(notetypes.ids())} limit 1""", ) > 0 - // notes without cards or models + // notes without cards or note types if (badNotes) { return false } // invalid ords for (m in notetypes.all()) { // ignore clozes - if (m.getInt("type") != Consts.MODEL_STD) { + if (m.getInt("type") != Consts.NOTE_TYPE_STD) { continue } - // Make a list of valid ords for this model + // Make a list of valid ords for this note type val tmpls = m.getJSONArray("tmpls") val badOrd = db.queryScalar( diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/Consts.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/Consts.kt index 1f0da61df11b..a2113ccb59b6 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/Consts.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/Consts.kt @@ -68,13 +68,13 @@ object Consts { @IntDef(DYN_OLDEST, DYN_RANDOM, DYN_SMALLINT, DYN_BIGINT, DYN_LAPSES, DYN_ADDED, DYN_DUE, DYN_REVADDED, DYN_DUEPRIORITY) annotation class DynPriority - // model types - const val MODEL_STD = 0 - const val MODEL_CLOZE = 1 + // note type types + const val NOTE_TYPE_STD = 0 + const val NOTE_TYPE_CLOZE = 1 @Retention(AnnotationRetention.SOURCE) - @IntDef(MODEL_STD, MODEL_CLOZE) - annotation class ModelType + @IntDef(NOTE_TYPE_STD, NOTE_TYPE_CLOZE) + annotation class NoteTypeType const val STARTING_FACTOR = 2500 diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/Note.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/Note.kt index 12e41d8748bf..03b543a2d954 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/Note.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/Note.kt @@ -21,7 +21,7 @@ import androidx.annotation.CheckResult import androidx.annotation.VisibleForTesting import anki.notes.NoteFieldsCheckResponse import com.ichi2.libanki.Consts.DEFAULT_DECK_ID -import com.ichi2.libanki.Consts.MODEL_STD +import com.ichi2.libanki.Consts.NOTE_TYPE_STD import com.ichi2.libanki.backend.model.toBackendNote import com.ichi2.libanki.utils.NotInLibAnki import com.ichi2.libanki.utils.set @@ -111,13 +111,13 @@ class Note : Cloneable { card.ord = ord card.did = DEFAULT_DECK_ID - val model = customNoteType ?: notetype + val note_type = customNoteType ?: notetype val template = if (customTemplate != null) { customTemplate.deepClone() } else { - val index = if (model.type == MODEL_STD) ord else 0 - model.tmpls.getJSONObject(index) + val index = if (note_type.type == NOTE_TYPE_STD) ord else 0 + note_type.tmpls.getJSONObject(index) } // may differ in cloze case template["ord"] = card.ord @@ -127,7 +127,7 @@ class Note : Cloneable { .fromCardLayout( note = this, card = card, - notetype = model, + notetype = note_type, template = template, fillEmpty = fillEmpty, ).render(col) diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/NotetypeJson.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/NotetypeJson.kt index deeceed3848a..39a3933b5d10 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/NotetypeJson.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/NotetypeJson.kt @@ -26,18 +26,18 @@ import org.json.JSONObject import java.util.HashSet /** - * Represents a note type, a.k.a. Model. + * Represents a note type, a.k.a. Note type. * The content of an object is described in https://github.com/ankidroid/Anki-Android/wiki/Database-Structure - * Each time the object is modified, `Models.save(this)` should be called, otherwise the change will not be synchronized + * Each time the object is modified, `NoteType.save(this)` should be called, otherwise the change will not be synchronized * If a change affect card generation, (i.e. any change on the list of field, or the question side of a card type), - * `Models.save(this, true)` should be called. However, you should do the change in batch and change only when all are d + * `NoteTypes.save(this, true)` should be called. However, you should do the change in batch and change only when all are d * one, because recomputing the list of card is an expensive operation. */ @KotlinCleanup("fix kotlin docs") @KotlinCleanup("IDE Lint") class NotetypeJson : JSONObject { /** - * Creates a new empty model object + * Creates a new empty note type object */ constructor() : super() @@ -49,7 +49,7 @@ class NotetypeJson : JSONObject { } /** - * Creates a model object from json string + * Creates a note type object from json string */ constructor( @Language("json") json: String, @@ -67,16 +67,16 @@ class NotetypeJson : JSONObject { fun getField(pos: Int): Field = flds[pos] /** - * @return model did or default deck id (1) if null + * @return note type's did or default deck id (1) if null */ val did: Long get() = if (isNull("did")) 1L else getLong("did") val templatesNames: List get() = getJSONArray("tmpls").toStringList("name") val isStd: Boolean - get() = getInt("type") == Consts.MODEL_STD + get() = getInt("type") == Consts.NOTE_TYPE_STD val isCloze: Boolean - get() = getInt("type") == Consts.MODEL_CLOZE + get() = getInt("type") == Consts.NOTE_TYPE_CLOZE /** * @param sfld Fields of a note of this note type @@ -132,7 +132,7 @@ class NotetypeJson : JSONObject { } // TODO: Not constrained - @Consts.ModelType + @Consts.NoteTypeType var type: Int get() = getInt("type") set(value) { diff --git a/AnkiDroid/src/main/java/com/ichi2/libanki/Notetypes.kt b/AnkiDroid/src/main/java/com/ichi2/libanki/Notetypes.kt index 1dd58cf4ef1f..08561c40feba 100644 --- a/AnkiDroid/src/main/java/com/ichi2/libanki/Notetypes.kt +++ b/AnkiDroid/src/main/java/com/ichi2/libanki/Notetypes.kt @@ -43,7 +43,7 @@ import anki.notetypes.restoreNotetypeToStockRequest import com.google.protobuf.ByteString import com.ichi2.anki.CrashReportService import com.ichi2.annotations.NeedsTest -import com.ichi2.libanki.Consts.MODEL_CLOZE +import com.ichi2.libanki.Consts.NOTE_TYPE_CLOZE import com.ichi2.libanki.Utils.checksum import com.ichi2.libanki.backend.BackendUtils import com.ichi2.libanki.backend.BackendUtils.fromJsonBytes @@ -152,25 +152,25 @@ class Notetypes( ############################################################# */ - /** Get current model.*/ + /** Get current note type.*/ @RustCleanup("Should use defaultsForAdding() instead") fun current(forDeck: Boolean = true): NotetypeJson { - var m = get(col.decks.current().getLongOrNull("mid")) - if (!forDeck || m == null) { - m = get(col.config.get("curModel") ?: 1L) + var noteType = get(col.decks.current().getLongOrNull("mid")) + if (!forDeck || noteType == null) { + noteType = get(col.config.get(CURRENT_NOTE_TYPE_KEY) ?: 1L) } - if (m != null) { - return m + if (noteType != null) { + return noteType } return get(allNamesAndIds().first().id)!! } fun setCurrent(notetype: NotetypeJson) { - col.config.set("curModel", notetype.id) + col.config.set(CURRENT_NOTE_TYPE_KEY, notetype.id) } /* - # Retrieving and creating models + # Retrieving and creating note types ############################################################# */ @@ -182,7 +182,7 @@ class Notetypes( null } - /** "Get model with ID, or None." */ + /** "Get note type with ID, or None." */ fun get(id: int): NotetypeJson? = get(id as int?) /** Externally, we do not want to pass in a null id */ @@ -207,16 +207,16 @@ class Notetypes( return nt } - /** Get all models */ + /** Get all note types */ fun all(): List = allNamesAndIds().map { get(it.id)!! }.toMutableList() - /** Get model with NAME. */ + /** Get note type with NAME. */ fun byName(name: String): NotetypeJson? { val id = idForName(name) return id?.let { get(it) } } - /** Create a new non-cloze model, and return it. */ + /** Create a new non-cloze note type, and return it. */ fun new(name: String): NotetypeJson { // caller should call save() after modifying val nt = newBasicNotetype() @@ -233,7 +233,7 @@ class Notetypes( ), ) - /** Delete model, and all its cards/notes. */ + /** Delete note type, and all its cards/notes. */ fun rem(notetype: NotetypeJson) { remove(notetype.id) } @@ -258,7 +258,7 @@ class Notetypes( } } - /** Add or update an existing model. Use .save() instead. */ + /** Add or update an existing note type. Use .save() instead. */ fun update( notetype: NotetypeJson, preserveUsnAndMtime: Boolean = true, @@ -289,7 +289,7 @@ class Notetypes( */ @NotInLibAnki - fun nids(model: NotetypeJson): List = nids(model.getLong("id")) + fun nids(notetype: NotetypeJson): List = nids(notetype.getLong("id")) /** Note ids for M. */ fun nids(ntid: int): List = col.db.queryLongList("select id from notes where mid = ?", ntid) @@ -317,12 +317,12 @@ class Notetypes( * This code is currently only used by unit tests. If the GUI starts to use it, the signature * should be updated so that a translated name is passed in. */ fun copy(notetype: NotetypeJson): NotetypeJson { - val m2 = notetype.deepClone() - m2.name = "${m2.name} copy" - // m2.name = col.context.getString(R.string.copy_note_type_name, m2.name) - m2.id = 0 - add(m2) - return m2 + val noteType2 = notetype.deepClone() + noteType2.name = "${noteType2.name} copy" + // noteType2.name = col.context.getString(R.string.copy_note_type_name, noteType2.name) + noteType2.id = 0 + add(noteType2) + return noteType2 } /* @@ -438,37 +438,37 @@ class Notetypes( /** * similar to Anki's addField; but thanks to assumption that - * model is new, it never has to throw + * note type is new, it never has to throw * [ConfirmModSchemaException] */ @RustCleanup("Since Kotlin doesn't have throws, this may not be needed") - fun addFieldInNewModel( + fun addFieldInNewNoteType( notetype: NotetypeJson, field: Field, ) { - check(isModelNew(notetype)) { "Model was assumed to be new, but is not" } + check(isNoteTypeNew(notetype)) { "Note type was assumed to be new, but is not" } try { addFieldLegacy(notetype, field) } catch (e: ConfirmModSchemaException) { Timber.w(e, "Unexpected mod schema") - CrashReportService.sendExceptionReport(e, "addFieldInNewModel: Unexpected mod schema") + CrashReportService.sendExceptionReport(e, "addFieldInNewNoteType: Unexpected mod schema") throw IllegalStateException("ConfirmModSchemaException should not be thrown", e) } } - fun addTemplateInNewModel( + fun addTemplateInNewNoteType( notetype: NotetypeJson, template: JSONObject, ) { // similar to addTemplate, but doesn't throw exception; - // asserting the model is new. - check(isModelNew(notetype)) { "Model was assumed to be new, but is not" } + // asserting the note type is new. + check(isNoteTypeNew(notetype)) { "Note type was assumed to be new, but is not" } try { addTemplate(notetype, template) } catch (e: ConfirmModSchemaException) { Timber.w(e, "Unexpected mod schema") - CrashReportService.sendExceptionReport(e, "addTemplateInNewModel: Unexpected mod schema") + CrashReportService.sendExceptionReport(e, "addTemplateInNewNoteType: Unexpected mod schema") throw IllegalStateException("ConfirmModSchemaException should not be thrown", e) } } @@ -489,7 +489,7 @@ class Notetypes( template: JSONObject, ) { // similar to addTemplate, but doesn't throw exception; - // asserting the model is new. + // asserting the note type is new. check(col.schemaChanged()) { "Mod was assumed to be already changed, but is not" } addTemplate(notetype, template) } @@ -576,10 +576,10 @@ class Notetypes( } /* - # Model changing + # Note type changing ########################################################################## # - maps are ord->ord, and there should not be duplicate targets - # - newModel should be same as m if model is not changing + # - newNoteType should be same as m if note type is not changing */ /** @@ -602,24 +602,24 @@ class Notetypes( fun change( noteType: NotetypeJson, nid: NoteId, - newModel: NotetypeJson, + newNoteType: NotetypeJson, fmap: Map, cmap: Map, ): OpChanges { - val fieldMap = convertLegacyMap(fmap, newModel.fieldsNames.size) + val fieldMap = convertLegacyMap(fmap, newNoteType.fieldsNames.size) val templateMap = - if (cmap.isEmpty() || noteType.type == MODEL_CLOZE || newModel.type == MODEL_CLOZE) { + if (cmap.isEmpty() || noteType.type == NOTE_TYPE_CLOZE || newNoteType.type == NOTE_TYPE_CLOZE) { listOf() } else { - convertLegacyMap(cmap, newModel.templatesNames.size) + convertLegacyMap(cmap, newNoteType.templatesNames.size) } - val isCloze = newModel.isCloze || noteType.isCloze + val isCloze = newNoteType.isCloze || noteType.isCloze return col.backend.changeNotetype( noteIds = listOf(nid), newFields = fieldMap, newTemplates = templateMap, oldNotetypeId = noteType.id, - newNotetypeId = newModel.id, + newNotetypeId = newNoteType.id, currentSchema = col.scm, oldNotetypeName = noteType.name, isCloze = isCloze, @@ -644,7 +644,7 @@ class Notetypes( ########################################################################## */ - /** Return a hash of the schema, to see if models are compatible. */ + /** Return a hash of the schema, to see if note types are compatible. */ fun scmhash(notetype: NotetypeJson): String { var s = "" for (f in notetype.flds) { @@ -665,33 +665,33 @@ class Notetypes( /** * Extracted from remTemplate so we can test if removing templates is safe without actually removing them - * This method will either give you all the card ids for the ordinals sent in related to the model sent in *or* + * This method will either give you all the card ids for the ordinals sent in related to the note type sent in *or* * it will return null if the result of deleting the ordinals is unsafe because it would leave notes with no cards * - * @param modelId long id of the JSON model - * @param ords array of ints, each one is the ordinal a the card template in the given model + * @param noteTypeId long id of the JSON note type + * @param ords array of ints, each one is the ordinal a the card template in the given note type * @return null if deleting ords would orphan notes, long[] of related card ids to delete if it is safe */ @Suppress("ktlint:standard:max-line-length") - fun getCardIdsForModel( - modelId: NoteTypeId, + fun getCardIdsForNoteType( + noteTypeId: NoteTypeId, ords: IntArray, ): List? { val cardIdsToDeleteSql = "select c2.id from cards c2, notes n2 where c2.nid=n2.id and n2.mid = ? and c2.ord in ${Utils.ids2str(ords)}" - val cids: List = col.db.queryLongList(cardIdsToDeleteSql, modelId) + val cids: List = col.db.queryLongList(cardIdsToDeleteSql, noteTypeId) // Timber.d("cardIdsToDeleteSql was ' %s' and got %s", cardIdsToDeleteSql, Utils.ids2str(cids)); - Timber.d("getCardIdsForModel found %s cards to delete for model %s and ords %s", cids.size, modelId, Utils.ids2str(ords)) + Timber.d("getCardIdsForModel found %s cards to delete for note type %s and ords %s", cids.size, noteTypeId, Utils.ids2str(ords)) // all notes with this template must have at least two cards, or we could end up creating orphaned notes val noteCountPreDeleteSql = "select count(distinct(nid)) from cards where nid in (select id from notes where mid = ?)" - val preDeleteNoteCount: Int = col.db.queryScalar(noteCountPreDeleteSql, modelId) + val preDeleteNoteCount: Int = col.db.queryScalar(noteCountPreDeleteSql, noteTypeId) Timber.d("noteCountPreDeleteSql was '%s'", noteCountPreDeleteSql) Timber.d("preDeleteNoteCount is %s", preDeleteNoteCount) val noteCountPostDeleteSql = "select count(distinct(nid)) from cards where nid in (select id from notes where mid = ?) and ord not in ${Utils.ids2str(ords)}" Timber.d("noteCountPostDeleteSql was '%s'", noteCountPostDeleteSql) - val postDeleteNoteCount: Int = col.db.queryScalar(noteCountPostDeleteSql, modelId) + val postDeleteNoteCount: Int = col.db.queryScalar(noteCountPostDeleteSql, noteTypeId) Timber.d("postDeleteNoteCount would be %s", postDeleteNoteCount) if (preDeleteNoteCount != postDeleteNoteCount) { Timber.d("There will be orphan notes if these cards are deleted.") @@ -703,6 +703,7 @@ class Notetypes( // These are all legacy and should be removed when possible companion object { + const val CURRENT_NOTE_TYPE_KEY = "curModel" const val NOT_FOUND_NOTE_TYPE = -1L fun newTemplate(name: String): JSONObject = @@ -719,7 +720,7 @@ class Notetypes( notetype.flds.associateBy({ f -> f.name }, { f -> Pair(f.ord, f) }) // not in anki - fun isModelNew(notetype: NotetypeJson): Boolean = notetype.getLong("id") == 0L + fun isNoteTypeNew(notetype: NotetypeJson): Boolean = notetype.getLong("id") == 0L fun _updateTemplOrds(notetype: NotetypeJson) { val tmpls = notetype.getJSONArray("tmpls") diff --git a/AnkiDroid/src/main/res/layout/model_field_editor.xml b/AnkiDroid/src/main/res/layout/note_type_field_editor.xml similarity index 100% rename from AnkiDroid/src/main/res/layout/model_field_editor.xml rename to AnkiDroid/src/main/res/layout/note_type_field_editor.xml diff --git a/AnkiDroid/src/main/res/layout/model_field_editor_list_item.xml b/AnkiDroid/src/main/res/layout/note_type_field_editor_list_item.xml similarity index 100% rename from AnkiDroid/src/main/res/layout/model_field_editor_list_item.xml rename to AnkiDroid/src/main/res/layout/note_type_field_editor_list_item.xml diff --git a/AnkiDroid/src/main/res/menu-xlarge/deck_picker.xml b/AnkiDroid/src/main/res/menu-xlarge/deck_picker.xml index 36973def2b06..f537f3cc4514 100644 --- a/AnkiDroid/src/main/res/menu-xlarge/deck_picker.xml +++ b/AnkiDroid/src/main/res/menu-xlarge/deck_picker.xml @@ -54,7 +54,7 @@ android:menuCategory="secondary" android:title="@string/backup_restore"/> diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/AbstractFlashcardViewerTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/AbstractFlashcardViewerTest.kt index a2759ff2e245..957f0f49cbd8 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/AbstractFlashcardViewerTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/AbstractFlashcardViewerTest.kt @@ -29,7 +29,7 @@ import com.ichi2.libanki.undoableOp import com.ichi2.testutils.AnkiAssert.assertDoesNotThrow import com.ichi2.testutils.common.Flaky import com.ichi2.testutils.common.OS -import com.ichi2.utils.createBasicTypingModel +import com.ichi2.utils.createBasicTypingNoteType import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.containsString import org.hamcrest.Matchers.equalTo @@ -150,7 +150,7 @@ class AbstractFlashcardViewerTest : RobolectricTest() { fun testEditingCardChangesTypedAnswer() = runTest { // 7363 - addNoteUsingBasicTypedModel("Hello", "World") + addBasicTypedNote("Hello", "World") val viewer: NonAbstractFlashcardViewer = getViewer(true) @@ -171,7 +171,7 @@ class AbstractFlashcardViewerTest : RobolectricTest() { fun testEditingCardChangesTypedAnswerOnDisplayAnswer() = runTest { // 7363 - addNoteUsingBasicTypedModel("Hello", "World") + addBasicTypedNote("Hello", "World") val viewer: NonAbstractFlashcardViewer = getViewer(true) @@ -250,22 +250,22 @@ class AbstractFlashcardViewerTest : RobolectricTest() { @Flaky(OS.ALL, "executeCommand(FLIP_OR_ANSWER_EASE4) cannot be awaited") fun typedLanguageIsSet() = runTest { - val withLanguage = col.createBasicTypingModel("a") - val normal = col.createBasicTypingModel("b") + val withLanguage = col.createBasicTypingNoteType("a") + val normal = col.createBasicTypingNoteType("b") val typedField = 1 // BACK LanguageHintService.setLanguageHintForField(col.notetypes, withLanguage, typedField, Locale("ja")) - addNoteUsingModelName(withLanguage.getString("name"), "ichi", "ni") - addNoteUsingModelName(normal.getString("name"), "one", "two") + addNoteUsingNoteTypeName(withLanguage.getString("name"), "ichi", "ni") + addNoteUsingNoteTypeName(normal.getString("name"), "one", "two") val viewer = getViewer(false) - assertThat("A model with a language hint (japanese) should use it", viewer.hintLocale, equalTo("ja")) + assertThat("A note type with a language hint (japanese) should use it", viewer.hintLocale, equalTo("ja")) viewer.executeCommand(ViewerCommand.FLIP_OR_ANSWER_EASE4) viewer.executeCommand(ViewerCommand.FLIP_OR_ANSWER_EASE4) - assertThat("A default model should have no preference", viewer.hintLocale, nullValue()) + assertThat("A default note type should have no preference", viewer.hintLocale, nullValue()) } @Test @@ -297,7 +297,7 @@ class AbstractFlashcardViewerTest : RobolectricTest() { @Test fun `Show audio play buttons preference handling - sound`() = runTest { - addNoteUsingBasicTypedModel("SOUND [sound:android_audiorec.3gp]", "back") + addBasicTypedNote("SOUND [sound:android_audiorec.3gp]", "back") getViewerContent().let { content -> assertThat("show audio preference default value: enabled", content, containsString("playsound:q:0")) assertThat("show audio preference default value: enabled", content, containsString("SOUND")) diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/AnkiDroidJsAPITest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/AnkiDroidJsAPITest.kt index c0cd3bcc5deb..8e75f977a915 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/AnkiDroidJsAPITest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/AnkiDroidJsAPITest.kt @@ -23,7 +23,7 @@ import com.ichi2.anki.AnkiDroidJsAPI.Companion.SUCCESS_KEY import com.ichi2.anki.AnkiDroidJsAPI.Companion.VALUE_KEY import com.ichi2.libanki.Consts import com.ichi2.libanki.utils.TimeManager -import com.ichi2.utils.BASIC_MODEL_NAME +import com.ichi2.utils.BASIC_NOTE_TYPE_NAME import net.ankiweb.rsdroid.withoutUnicodeIsolation import org.hamcrest.CoreMatchers.equalTo import org.hamcrest.MatcherAssert.assertThat @@ -38,11 +38,11 @@ class AnkiDroidJsAPITest : RobolectricTest() { @Test fun ankiGetNextTimeTest() = runTest { - val models = col.notetypes + val noteTypes = col.notetypes val didA = addDeck("Test", setAsSelected = true) - val basic = models.byName(BASIC_MODEL_NAME) + val basic = noteTypes.byName(BASIC_NOTE_TYPE_NAME) basic!!.put("did", didA) - addNoteUsingBasicModel("foo", "bar") + addBasicNote("foo", "bar") val reviewer: Reviewer = startReviewer() val jsapi = reviewer.jsApi @@ -72,11 +72,11 @@ class AnkiDroidJsAPITest : RobolectricTest() { @Test fun ankiTestCurrentCard() = runTest { - val models = col.notetypes + val noteTypes = col.notetypes val didA = addDeck("Test", setAsSelected = true) - val basic = models.byName(BASIC_MODEL_NAME) + val basic = noteTypes.byName(BASIC_NOTE_TYPE_NAME) basic!!.put("did", didA) - addNoteUsingBasicModel("foo", "bar") + addBasicNote("foo", "bar") val reviewer: Reviewer = startReviewer() val jsapi = reviewer.jsApi @@ -183,11 +183,11 @@ class AnkiDroidJsAPITest : RobolectricTest() { @Test fun ankiJsUiTest() = runTest { - val models = col.notetypes + val noteTypes = col.notetypes val didA = addDeck("Test", setAsSelected = true) - val basic = models.byName(BASIC_MODEL_NAME) + val basic = noteTypes.byName(BASIC_NOTE_TYPE_NAME) basic!!.put("did", didA) - addNoteUsingBasicModel("foo", "bar") + addBasicNote("foo", "bar") val reviewer: Reviewer = startReviewer() val jsapi = reviewer.jsApi @@ -226,11 +226,11 @@ class AnkiDroidJsAPITest : RobolectricTest() { fun ankiMarkAndFlagCardTest() = runTest { // js api test for marking and flagging card - val models = col.notetypes + val noteTypes = col.notetypes val didA = addDeck("Test", setAsSelected = true) - val basic = models.byName(BASIC_MODEL_NAME) + val basic = noteTypes.byName(BASIC_NOTE_TYPE_NAME) basic!!.put("did", didA) - addNoteUsingBasicModel("foo", "bar") + addBasicNote("foo", "bar") val reviewer: Reviewer = startReviewer() val jsapi = reviewer.jsApi @@ -287,15 +287,15 @@ class AnkiDroidJsAPITest : RobolectricTest() { // add five notes, four will be buried and suspended // count number of notes, if buried or suspended then // in scheduling the count will be less than previous scheduling - val models = col.notetypes + val noteTypes = col.notetypes val didA = addDeck("Test", setAsSelected = true) - val basic = models.byName(BASIC_MODEL_NAME) + val basic = noteTypes.byName(BASIC_NOTE_TYPE_NAME) basic!!.put("did", didA) - addNoteUsingBasicModel("foo", "bar") - addNoteUsingBasicModel("baz", "bak") - addNoteUsingBasicModel("Anki", "Droid") - addNoteUsingBasicModel("Test Card", "Bury and Suspend Card") - addNoteUsingBasicModel("Test Note", "Bury and Suspend Note") + addBasicNote("foo", "bar") + addBasicNote("baz", "bak") + addBasicNote("Anki", "Droid") + addBasicNote("Test Card", "Bury and Suspend Card") + addBasicNote("Test Note", "Bury and Suspend Note") val reviewer: Reviewer = startReviewer() val jsapi = reviewer.jsApi @@ -356,12 +356,12 @@ class AnkiDroidJsAPITest : RobolectricTest() { fun ankiSetCardDueTest() = runTest { TimeManager.reset() - val models = col.notetypes + val noteTypes = col.notetypes val didA = addDeck("Test", setAsSelected = true) - val basic = models.byName(BASIC_MODEL_NAME) + val basic = noteTypes.byName(BASIC_NOTE_TYPE_NAME) basic!!.put("did", didA) - addNoteUsingBasicModel("foo", "bar") - addNoteUsingBasicModel("baz", "bak") + addBasicNote("foo", "bar") + addBasicNote("baz", "bak") val reviewer: Reviewer = startReviewer() waitForAsyncTasksToComplete() @@ -385,7 +385,7 @@ class AnkiDroidJsAPITest : RobolectricTest() { @Test fun ankiResetProgressTest() = runTest { - val n = addNoteUsingBasicModel("Front", "Back") + val n = addBasicNote("Front", "Back") val c = n.firstCard() // Make card review with 28L due and 280% ease diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt index d340d685ae2d..27df518c6dde 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt @@ -400,7 +400,7 @@ class CardBrowserTest : RobolectricTest() { @Test fun flagValueIsShownOnCard() { - val n = addNoteUsingBasicModel("1", "back") + val n = addBasicNote("1", "back") flagCardForNote(n, Flag.RED) val cardId = n.cids()[0] @@ -440,7 +440,7 @@ class CardBrowserTest : RobolectricTest() { @Test fun tagWithBracketsDisplaysProperly() = runTest { - val n = addNoteUsingBasicModel("Hello", "World") + val n = addBasicNote("Hello", "World") n.addTag("sketchy::(1)") n.flush() @@ -455,8 +455,8 @@ class CardBrowserTest : RobolectricTest() { fun previewWorksAfterSort() = runTest { // #7286 - val cid1 = addNoteUsingBasicModel("Hello", "World").cards()[0].id - val cid2 = addNoteUsingBasicModel("Hello2", "World2").cards()[0].id + val cid1 = addBasicNote("Hello", "World").cards()[0].id + val cid2 = addBasicNote("Hello2", "World2").cards()[0].id val b = browserWithNoNewCards @@ -557,7 +557,7 @@ class CardBrowserTest : RobolectricTest() { fun resetDataTest() = runTest { TimeManager.reset() - addNoteUsingBasicModel("Hello", "World").firstCard().update { + addBasicNote("Hello", "World").firstCard().update { due = 5 queue = Consts.QUEUE_TYPE_REV type = Consts.CARD_TYPE_REV @@ -648,8 +648,8 @@ class CardBrowserTest : RobolectricTest() { @Test fun checkSearchString() = runTest { - addNoteUsingBasicModel("Hello", "John") - addNoteUsingBasicModel("New", "world").firstCard().update { + addBasicNote("Hello", "John") + addBasicNote("New", "world").firstCard().update { did = addDeck("Deck 1", setAsSelected = true) } @@ -728,8 +728,8 @@ class CardBrowserTest : RobolectricTest() { @Test fun checkIfSearchAllDecksWorks() = runTest { - addNoteUsingBasicModel("Hello", "World") - addNoteUsingBasicModel("Front", "Back").firstCard().update { + addBasicNote("Hello", "World") + addBasicNote("Front", "Back").firstCard().update { did = addDeck("Test Deck", setAsSelected = true) } @@ -752,8 +752,8 @@ class CardBrowserTest : RobolectricTest() { fun `'notes-only mode' returns one card from each note`() = runTest { // #14623: The functionality was broken - addNoteUsingBasicAndReversedModel("Hello", "World") - addNoteUsingBasicAndReversedModel("Hello", "Anki") + addBasicAndReverseNote("Hello", "World") + addBasicAndReverseNote("Hello", "Anki") browserWithNoNewCards.apply { searchAllDecks().join() @@ -860,11 +860,11 @@ class CardBrowserTest : RobolectricTest() { ensureCollectionLoadIsSynchronous() if (reversed) { for (i in 0 until noteCount) { - addNoteUsingBasicAndReversedModel(i.toString(), "back") + addBasicAndReverseNote(i.toString(), "back") } } else { for (i in 0 until noteCount) { - addNoteUsingBasicModel(i.toString(), "back") + addBasicNote(i.toString(), "back") } } return super.startRegularActivity(Intent()).also { @@ -1101,8 +1101,8 @@ class CardBrowserTest : RobolectricTest() { // We're going to move this functionality entirely to the ViewModel over the next few weeks // so this test should be updated and working after the refactorings are completed - addNoteUsingBasicModel().moveToDeck("First") - addNoteUsingBasicModel().moveToDeck("Second") + addBasicNote().moveToDeck("First") + addBasicNote().moveToDeck("Second") val secondDeckId = requireNotNull(col.decks.idForName("Second")) @@ -1138,7 +1138,7 @@ class CardBrowserTest : RobolectricTest() { @Config(qualifiers = "en") fun nextDueTest() { TimeManager.reset() - val n = addNoteUsingBasicModel("Front", "Back") + val n = addBasicNote("Front", "Back") val c = n.firstCard() val decks = col.decks val cal = Calendar.getInstance() @@ -1236,7 +1236,7 @@ class CardBrowserTest : RobolectricTest() { @Test fun `tts tags are stripped`() { val note = - addNonClozeModel( + addNonClozeNoteType( "test", arrayOf("Front", "Back"), "[anki:tts lang=de_DE voices=com.google.android.tts-de-DE-language]{{Front}}[/anki:tts]", @@ -1256,7 +1256,7 @@ class CardBrowserTest : RobolectricTest() { fun `initial value is correct column`() { // Column 1 is [QUESTION, SFLD], the values when [SFLD] is selected - addNoteUsingBasicAndReversedModel("Hello", "World") + addBasicAndReverseNote("Hello", "World") withBrowser { assertThat(viewModel.column1, equalTo(SFLD)) @@ -1272,7 +1272,7 @@ class CardBrowserTest : RobolectricTest() { "use an integration test", ) fun `column text is updated - cardsOrNotes and column change`() { - addNoteUsingBasicAndReversedModel("Hello", "World") + addBasicAndReverseNote("Hello", "World") withBrowser { assertThat("cards: original column", column2TitleText, equalTo("Card Type")) @@ -1295,7 +1295,7 @@ class CardBrowserTest : RobolectricTest() { fun NotetypeJson.addNote( field: String, vararg fields: String, - ): Note = addNoteUsingModelName(this.name, field, *fields) + ): Note = addNoteUsingNoteTypeName(this.name, field, *fields) @Suppress("SameParameterValue") private fun withBrowser( diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/CardTemplateEditorTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/CardTemplateEditorTest.kt index 992a09023494..3982c7f3dc87 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/CardTemplateEditorTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/CardTemplateEditorTest.kt @@ -48,12 +48,12 @@ class CardTemplateEditorTest : RobolectricTest() { @Test @Throws(Exception::class) fun testEditTemplateContents() { - val modelName = "Basic" + val noteTypeName = "Basic" - // Start the CardTemplateEditor with a specific model, and make sure the model starts unchanged - val collectionBasicModelOriginal = getCurrentDatabaseModelCopy(modelName) + // Start the CardTemplateEditor with a specific note type, and make sure the note type starts unchanged + val collectionBasicNoteTypeOriginal = getCurrentDatabaseNoteTypeCopy(noteTypeName) val intent = Intent(Intent.ACTION_VIEW) - intent.putExtra("modelId", collectionBasicModelOriginal.getLong("id")) + intent.putExtra("noteTypeId", collectionBasicNoteTypeOriginal.getLong("id")) var templateEditorController = Robolectric .buildActivity(CardTemplateEditor::class.java, intent) @@ -63,23 +63,23 @@ class CardTemplateEditorTest : RobolectricTest() { .visible() saveControllerForCleanup(templateEditorController) var testEditor = templateEditorController.get() - assertFalse("Model should not have changed yet", testEditor.modelHasChanged()) + assertFalse("Note type should not have changed yet", testEditor.noteTypeHasChanged()) - // Change the model and make sure it registers as changed, but the database is unchanged + // Change the note type and make sure it registers as changed, but the database is unchanged var templateFront = testEditor.findViewById(R.id.editor_editText) - val testModelQfmtEdit = "!@#$%^&*TEST*&^%$#@!" - templateFront.text.append(testModelQfmtEdit) + val testNoteTypeQfmtEdit = "!@#$%^&*TEST*&^%$#@!" + templateFront.text.append(testNoteTypeQfmtEdit) advanceRobolectricLooperWithSleep() - assertTrue("Model did not change after edit?", testEditor.modelHasChanged()) + assertTrue("Note type did not change after edit?", testEditor.noteTypeHasChanged()) assertEquals( "Change already in database?", - collectionBasicModelOriginal.toString().trim { + collectionBasicNoteTypeOriginal.toString().trim { it <= ' ' }, - getCurrentDatabaseModelCopy(modelName).toString().trim { it <= ' ' }, + getCurrentDatabaseNoteTypeCopy(noteTypeName).toString().trim { it <= ' ' }, ) - // Kill and restart the Activity, make sure model edit is preserved + // Kill and restart the Activity, make sure note type edit is preserved val outBundle = Bundle() templateEditorController.saveInstanceState(outBundle) templateEditorController.pause().stop().destroy() @@ -93,13 +93,13 @@ class CardTemplateEditorTest : RobolectricTest() { saveControllerForCleanup(templateEditorController) testEditor = templateEditorController.get() var shadowTestEditor = shadowOf(testEditor) - assertTrue("model change not preserved across activity lifecycle?", testEditor.modelHasChanged()) + assertTrue("note type change not preserved across activity lifecycle?", testEditor.noteTypeHasChanged()) assertEquals( "Change already in database?", - collectionBasicModelOriginal.toString().trim { + collectionBasicNoteTypeOriginal.toString().trim { it <= ' ' }, - getCurrentDatabaseModelCopy(modelName).toString().trim { it <= ' ' }, + getCurrentDatabaseNoteTypeCopy(noteTypeName).toString().trim { it <= ' ' }, ) // Make sure we get a confirmation dialog if we hit the back button @@ -108,14 +108,14 @@ class CardTemplateEditorTest : RobolectricTest() { assertEquals("Wrong dialog shown?", getAlertDialogText(true), "Discard current input?") clickAlertDialogButton(DialogInterface.BUTTON_NEGATIVE, false) advanceRobolectricLooperWithSleep() - assertTrue("model change not preserved despite canceling back button?", testEditor.modelHasChanged()) + assertTrue("note type change not preserved despite canceling back button?", testEditor.noteTypeHasChanged()) // Make sure we things are cleared out after a cancel assertTrue("Unable to click?", shadowTestEditor.clickMenuItem(android.R.id.home)) assertEquals("Wrong dialog shown?", getAlertDialogText(true), "Discard current input?") clickAlertDialogButton(DialogInterface.BUTTON_POSITIVE, false) advanceRobolectricLooperWithSleep() - assertFalse("model change not cleared despite discarding changes?", testEditor.modelHasChanged()) + assertFalse("note type change not cleared despite discarding changes?", testEditor.noteTypeHasChanged()) // Get going for content edit assertions again... templateEditorController = @@ -129,9 +129,9 @@ class CardTemplateEditorTest : RobolectricTest() { testEditor = templateEditorController.get() shadowTestEditor = shadowOf(testEditor) templateFront = testEditor.findViewById(R.id.editor_editText) - templateFront.text.append(testModelQfmtEdit) + templateFront.text.append(testNoteTypeQfmtEdit) advanceRobolectricLooperWithSleep() - assertTrue("Model did not change after edit?", testEditor.modelHasChanged()) + assertTrue("Note type did not change after edit?", testEditor.noteTypeHasChanged()) // Make sure we pass the edit to the Previewer assertTrue("Unable to click?", shadowTestEditor.clickMenuItem(R.id.action_preview)) @@ -142,38 +142,38 @@ class CardTemplateEditorTest : RobolectricTest() { assertEquals("Previewer not started?", CardViewerActivity::class.java.name, shadowIntent.intentClass.name) assertEquals( "Change already in database?", - collectionBasicModelOriginal.toString().trim { + collectionBasicNoteTypeOriginal.toString().trim { it <= ' ' }, - getCurrentDatabaseModelCopy(modelName).toString().trim { it <= ' ' }, + getCurrentDatabaseNoteTypeCopy(noteTypeName).toString().trim { it <= ' ' }, ) shadowTestEditor.receiveResult(startedIntent, Activity.RESULT_OK, Intent()) // Save the template then fetch it from the collection to see if it was saved correctly - val testEditorModelEdited = testEditor.tempModel?.notetype + val testEditorNoteTypeEdited = testEditor.tempNoteType?.notetype advanceRobolectricLooperWithSleep() assertTrue("Unable to click?", shadowTestEditor.clickMenuItem(R.id.action_confirm)) advanceRobolectricLooperWithSleep() - val collectionBasicModelCopyEdited = getCurrentDatabaseModelCopy(modelName) - assertNotEquals("model is unchanged?", collectionBasicModelOriginal, collectionBasicModelCopyEdited) + val collectionBasicNoteTypeCopyEdited = getCurrentDatabaseNoteTypeCopy(noteTypeName) + assertNotEquals("note type is unchanged?", collectionBasicNoteTypeOriginal, collectionBasicNoteTypeCopyEdited) assertEquals( - "model did not save?", - testEditorModelEdited.toString().trim { + "note type did not save?", + testEditorNoteTypeEdited.toString().trim { it <= ' ' }, - collectionBasicModelCopyEdited.toString().trim { it <= ' ' }, + collectionBasicNoteTypeCopyEdited.toString().trim { it <= ' ' }, ) - assertTrue("model does not have our change?", collectionBasicModelCopyEdited.toString().contains(testModelQfmtEdit)) + assertTrue("note type does not have our change?", collectionBasicNoteTypeCopyEdited.toString().contains(testNoteTypeQfmtEdit)) } @Test fun testDeleteTemplate() { - val modelName = "Basic (and reversed card)" + val noteTypeName = "Basic (and reversed card)" - // Start the CardTemplateEditor with a specific model, and make sure the model starts unchanged - val collectionBasicModelOriginal = getCurrentDatabaseModelCopy(modelName) + // Start the CardTemplateEditor with a specific note type, and make sure the note type starts unchanged + val collectionBasicNoteTypeOriginal = getCurrentDatabaseNoteTypeCopy(noteTypeName) val intent = Intent(Intent.ACTION_VIEW) - intent.putExtra("modelId", collectionBasicModelOriginal.getLong("id")) + intent.putExtra("noteTypeId", collectionBasicNoteTypeOriginal.getLong("id")) val templateEditorController = Robolectric .buildActivity(CardTemplateEditor::class.java, intent) @@ -183,8 +183,8 @@ class CardTemplateEditorTest : RobolectricTest() { .visible() saveControllerForCleanup(templateEditorController) val testEditor = templateEditorController.get() - assertFalse("Model should not have changed yet", testEditor.modelHasChanged()) - assertEquals("Model should have 2 templates now", 2, testEditor.tempModel?.templateCount) + assertFalse("Note type should not have changed yet", testEditor.noteTypeHasChanged()) + assertEquals("Note type should have 2 templates now", 2, testEditor.tempNoteType?.templateCount) // Try to delete the template - click delete, click confirm for card delete, click confirm again for full sync val shadowTestEditor = shadowOf(testEditor) @@ -193,8 +193,8 @@ class CardTemplateEditorTest : RobolectricTest() { assertEquals("Wrong dialog shown?", "Delete the “Card 1” card type, and its 0 cards?", getAlertDialogText(true)) clickAlertDialogButton(DialogInterface.BUTTON_POSITIVE, true) advanceRobolectricLooperWithSleep() - assertTrue("Model should have changed", testEditor.modelHasChanged()) - assertEquals("Model should have 1 template now", 1, testEditor.tempModel?.templateCount) + assertTrue("Note type should have changed", testEditor.noteTypeHasChanged()) + assertEquals("Note type should have 1 template now", 1, testEditor.tempNoteType?.templateCount) // Try to delete the template again, but there's only one assertTrue("Unable to click?", shadowTestEditor.clickMenuItem(R.id.action_delete)) @@ -206,24 +206,24 @@ class CardTemplateEditorTest : RobolectricTest() { ) assertEquals( "Change already in database?", - collectionBasicModelOriginal.toString().trim { + collectionBasicNoteTypeOriginal.toString().trim { it <= ' ' }, - getCurrentDatabaseModelCopy(modelName).toString().trim { it <= ' ' }, + getCurrentDatabaseNoteTypeCopy(noteTypeName).toString().trim { it <= ' ' }, ) // Save the change to the database and make sure there's only one template after - val testEditorModelEdited = testEditor.tempModel?.notetype + val testEditorNoteTypeEdited = testEditor.tempNoteType?.notetype assertTrue("Unable to click?", shadowTestEditor.clickMenuItem(R.id.action_confirm)) advanceRobolectricLooperWithSleep() - val collectionBasicModelCopyEdited = getCurrentDatabaseModelCopy(modelName) - assertNotEquals("model is unchanged?", collectionBasicModelOriginal, collectionBasicModelCopyEdited) + val collectionBasicNoteTypeCopyEdited = getCurrentDatabaseNoteTypeCopy(noteTypeName) + assertNotEquals("note type is unchanged?", collectionBasicNoteTypeOriginal, collectionBasicNoteTypeCopyEdited) assertEquals( - "model did not save?", - testEditorModelEdited.toString().trim { + "note type did not save?", + testEditorNoteTypeEdited.toString().trim { it <= ' ' }, - collectionBasicModelCopyEdited.toString().trim { it <= ' ' }, + collectionBasicNoteTypeCopyEdited.toString().trim { it <= ' ' }, ) } @@ -231,10 +231,10 @@ class CardTemplateEditorTest : RobolectricTest() { @Throws(Exception::class) fun testTemplateAdd() { // Make sure we test previewing a new card template - not working for real yet - val modelName = "Basic" - val collectionBasicModelOriginal = getCurrentDatabaseModelCopy(modelName) + val noteTypeName = "Basic" + val collectionBasicNoteTypeOriginal = getCurrentDatabaseNoteTypeCopy(noteTypeName) val intent = Intent(Intent.ACTION_VIEW) - intent.putExtra("modelId", collectionBasicModelOriginal.getLong("id")) + intent.putExtra("noteTypeId", collectionBasicNoteTypeOriginal.getLong("id")) val templateEditorController = Robolectric .buildActivity(CardTemplateEditor::class.java, intent) @@ -244,7 +244,7 @@ class CardTemplateEditorTest : RobolectricTest() { .visible() saveControllerForCleanup(templateEditorController) val testEditor = templateEditorController.get() - assertFalse("Ordinal pending add?", testEditor.tempModel.isOrdinalPendingAdd(0)) + assertFalse("Ordinal pending add?", testEditor.tempNoteType.isOrdinalPendingAdd(0)) // Try to add a template - click add, click confirm for card add, click confirm again for full sync val shadowTestEditor = shadowOf(testEditor) @@ -252,11 +252,11 @@ class CardTemplateEditorTest : RobolectricTest() { // if AnkiDroid moves to match AnkiDesktop it will pop a dialog to confirm card create // Assert.assertEquals("Wrong dialog shown?", "This will create NN cards. Proceed?", getDialogText()); // clickDialogButton(WhichButton.POSITIVE); - assertTrue("Model should have changed", testEditor.modelHasChanged()) - assertEquals("Change not pending add?", 1, CardTemplateNotetype.getAdjustedAddOrdinalAtChangeIndex(testEditor.tempModel!!, 0)) - assertFalse("Ordinal pending add?", testEditor.tempModel.isOrdinalPendingAdd(0)) - assertTrue("Ordinal not pending add?", testEditor.tempModel.isOrdinalPendingAdd(1)) - assertEquals("Model should have 2 templates now", 2, testEditor.tempModel!!.templateCount) + assertTrue("Note type should have changed", testEditor.noteTypeHasChanged()) + assertEquals("Change not pending add?", 1, CardTemplateNotetype.getAdjustedAddOrdinalAtChangeIndex(testEditor.tempNoteType!!, 0)) + assertFalse("Ordinal pending add?", testEditor.tempNoteType.isOrdinalPendingAdd(0)) + assertTrue("Ordinal not pending add?", testEditor.tempNoteType.isOrdinalPendingAdd(1)) + assertEquals("Note type should have 2 templates now", 2, testEditor.tempNoteType!!.templateCount) // Make sure we pass the new template to the Previewer assertTrue("Unable to click?", shadowTestEditor.clickMenuItem(R.id.action_preview)) @@ -265,37 +265,37 @@ class CardTemplateEditorTest : RobolectricTest() { assertEquals("Previewer not started?", CardViewerActivity::class.java.name, shadowIntent.intentClass.name) assertEquals( "Change already in database?", - collectionBasicModelOriginal.toString().trim { + collectionBasicNoteTypeOriginal.toString().trim { it <= ' ' }, - getCurrentDatabaseModelCopy(modelName).toString().trim { it <= ' ' }, + getCurrentDatabaseNoteTypeCopy(noteTypeName).toString().trim { it <= ' ' }, ) // Save the change to the database and make sure there are two templates after - val testEditorModelEdited = testEditor.tempModel?.notetype + val testEditorNoteTypeEdited = testEditor.tempNoteType?.notetype assertTrue("Unable to click?", shadowTestEditor.clickMenuItem(R.id.action_confirm)) advanceRobolectricLooperWithSleep() - val collectionBasicModelCopyEdited = getCurrentDatabaseModelCopy(modelName) - assertNotEquals("model is unchanged?", collectionBasicModelOriginal, collectionBasicModelCopyEdited) + val collectionBasicNoteTypeCopyEdited = getCurrentDatabaseNoteTypeCopy(noteTypeName) + assertNotEquals("note type is unchanged?", collectionBasicNoteTypeOriginal, collectionBasicNoteTypeCopyEdited) assertEquals( - "model did not save?", - testEditorModelEdited.toString().trim { + "note type did not save?", + testEditorNoteTypeEdited.toString().trim { it <= ' ' }, - collectionBasicModelCopyEdited.toString().trim { it <= ' ' }, + collectionBasicNoteTypeCopyEdited.toString().trim { it <= ' ' }, ) } /** - * In a model with two card templates using different fields, some notes may only use card 1, + * In a note type with two card templates using different fields, some notes may only use card 1, * and some may only use card 2. If you delete the 2nd template, * it will cause the notes that only use card 2 to disappear. * - * So the unit test would then be to make a model like the "basic (optional reverse card)" + * So the unit test would then be to make a note type like the "basic (optional reverse card)" * with two fields Enable1 and Enable2, and two templates "card 1" and "card 2". * Both cards use selective generation, so they're empty unless the corresponding field is set. * - * So then in the unit test you make the model, add the two templates, then you add two notes, + * So then in the unit test you make the note type, add the two templates, then you add two notes, * with Enable1 and Enable2 respectively set to "y". * Then you try to delete one of the templates and it should fail * @@ -307,12 +307,12 @@ class CardTemplateEditorTest : RobolectricTest() { @Test fun testDeleteTemplateWithSelectivelyGeneratedCards() = runTest { - val modelName = "Basic (optional reversed card)" - val collectionBasicModelOriginal = getCurrentDatabaseModelCopy(modelName) + val noteTypeName = "Basic (optional reversed card)" + val collectionBasicNoteTypeOriginal = getCurrentDatabaseNoteTypeCopy(noteTypeName) - // Start the CardTemplateEditor with a specific model, and make sure the model starts unchanged + // Start the CardTemplateEditor with a specific note type, and make sure the note type starts unchanged val intent = Intent(Intent.ACTION_VIEW) - intent.putExtra("modelId", collectionBasicModelOriginal.getLong("id")) + intent.putExtra("noteTypeId", collectionBasicNoteTypeOriginal.getLong("id")) val templateEditorController = Robolectric .buildActivity( @@ -324,10 +324,10 @@ class CardTemplateEditorTest : RobolectricTest() { .visible() saveControllerForCleanup(templateEditorController) val testEditor = templateEditorController.get() - assertFalse("Model should not have changed yet", testEditor.modelHasChanged()) - assertEquals("Model should have 2 templates now", 2, testEditor.tempModel?.templateCount) - assertFalse("Ordinal pending add?", testEditor.tempModel.isOrdinalPendingAdd(0)) - assertFalse("Ordinal pending add?", testEditor.tempModel.isOrdinalPendingAdd(1)) + assertFalse("Note type should not have changed yet", testEditor.noteTypeHasChanged()) + assertEquals("Note type should have 2 templates now", 2, testEditor.tempNoteType?.templateCount) + assertFalse("Ordinal pending add?", testEditor.tempNoteType.isOrdinalPendingAdd(0)) + assertFalse("Ordinal pending add?", testEditor.tempNoteType.isOrdinalPendingAdd(1)) // Try to delete Card 1 template - click delete, check confirm for card delete popup indicating it was possible, then dismiss it val shadowTestEditor = shadowOf(testEditor) @@ -336,10 +336,10 @@ class CardTemplateEditorTest : RobolectricTest() { assertEquals("Wrong dialog shown?", "Delete the “Card 1” card type, and its 0 cards?", getAlertDialogText(true)) clickAlertDialogButton(DialogInterface.BUTTON_NEGATIVE, true) advanceRobolectricLooperWithSleep() - assertFalse("Model should not have changed", testEditor.modelHasChanged()) + assertFalse("Note type should not have changed", testEditor.noteTypeHasChanged()) // Create note with forward and back info, Add Reverse is empty, so should only be one card - val selectiveGeneratedNote = col.newNote(collectionBasicModelOriginal) + val selectiveGeneratedNote = col.newNote(collectionBasicNoteTypeOriginal) selectiveGeneratedNote.setField(0, "TestFront") selectiveGeneratedNote.setField(1, "TestBack") val fields = selectiveGeneratedNote.fields @@ -347,7 +347,7 @@ class CardTemplateEditorTest : RobolectricTest() { Timber.d("Got a field: %s", field) } col.addNote(selectiveGeneratedNote) - assertEquals("selective generation should result in one card", 1, getModelCardCount(collectionBasicModelOriginal)) + assertEquals("selective generation should result in one card", 1, getNoteTypeCardCount(collectionBasicNoteTypeOriginal)) // Try to delete the template again, but there's selective generation means it would orphan the note assertTrue("Unable to click?", shadowTestEditor.clickMenuItem(R.id.action_delete)) @@ -361,44 +361,44 @@ class CardTemplateEditorTest : RobolectricTest() { advanceRobolectricLooperWithSleep() assertNull( "Can delete used template?", - collectionBasicModelOriginal.getCardIds(0), + collectionBasicNoteTypeOriginal.getCardIds(0), ) assertEquals( "Change already in database?", - collectionBasicModelOriginal.toString().trim { + collectionBasicNoteTypeOriginal.toString().trim { it <= ' ' }, - getCurrentDatabaseModelCopy(modelName).toString().trim { it <= ' ' }, + getCurrentDatabaseNoteTypeCopy(noteTypeName).toString().trim { it <= ' ' }, ) - assertFalse("Ordinal pending add?", testEditor.tempModel.isOrdinalPendingAdd(0)) + assertFalse("Ordinal pending add?", testEditor.tempNoteType.isOrdinalPendingAdd(0)) assertEquals("Change incorrectly added to list?", 0, testEditor.templateChangeCount) // Assert can delete 'Card 2' - assertNotNull("Cannot delete unused template?", collectionBasicModelOriginal.getCardIds(1)) + assertNotNull("Cannot delete unused template?", collectionBasicNoteTypeOriginal.getCardIds(1)) // Edit note to have Add Reverse set to 'y' so we get a second card selectiveGeneratedNote.setField(2, "y") selectiveGeneratedNote.flush() // - assert two cards - assertEquals("should be two cards now", 2, getModelCardCount(collectionBasicModelOriginal)) + assertEquals("should be two cards now", 2, getNoteTypeCardCount(collectionBasicNoteTypeOriginal)) // - assert can delete either Card template but not both - assertNotNull("Cannot delete template?", collectionBasicModelOriginal.getCardIds(0)) - assertNotNull("Cannot delete template?", collectionBasicModelOriginal.getCardIds(1)) - assertNull("Can delete both templates?", collectionBasicModelOriginal.getCardIds(0, 1)) + assertNotNull("Cannot delete template?", collectionBasicNoteTypeOriginal.getCardIds(0)) + assertNotNull("Cannot delete template?", collectionBasicNoteTypeOriginal.getCardIds(1)) + assertNull("Can delete both templates?", collectionBasicNoteTypeOriginal.getCardIds(0, 1)) // A couple more notes to make sure things are okay - val secondNote = col.newNote(collectionBasicModelOriginal) + val secondNote = col.newNote(collectionBasicNoteTypeOriginal) secondNote.setField(0, "TestFront2") secondNote.setField(1, "TestBack2") secondNote.setField(2, "y") col.addNote(secondNote) // - assert can delete either Card template but not both - assertNotNull("Cannot delete template?", collectionBasicModelOriginal.getCardIds(0)) - assertNotNull("Cannot delete template?", collectionBasicModelOriginal.getCardIds(1)) - assertNull("Can delete both templates?", collectionBasicModelOriginal.getCardIds(0, 1)) + assertNotNull("Cannot delete template?", collectionBasicNoteTypeOriginal.getCardIds(0)) + assertNotNull("Cannot delete template?", collectionBasicNoteTypeOriginal.getCardIds(1)) + assertNull("Can delete both templates?", collectionBasicNoteTypeOriginal.getCardIds(0, 1)) } /** @@ -407,12 +407,12 @@ class CardTemplateEditorTest : RobolectricTest() { @Test fun testDeleteTemplateWithGeneratedCards() = runTest { - val modelName = "Basic (and reversed card)" - var collectionBasicModelOriginal = getCurrentDatabaseModelCopy(modelName) + val noteTypeName = "Basic (and reversed card)" + var collectionBasicNoteTypeOriginal = getCurrentDatabaseNoteTypeCopy(noteTypeName) - // Start the CardTemplateEditor with a specific model, and make sure the model starts unchanged + // Start the CardTemplateEditor with a specific note type, and make sure the note type starts unchanged var intent = Intent(Intent.ACTION_VIEW) - intent.putExtra("modelId", collectionBasicModelOriginal.getLong("id")) + intent.putExtra("noteTypeId", collectionBasicNoteTypeOriginal.getLong("id")) var templateEditorController = Robolectric .buildActivity( @@ -424,17 +424,17 @@ class CardTemplateEditorTest : RobolectricTest() { .visible() saveControllerForCleanup(templateEditorController) var testEditor = templateEditorController.get() - assertFalse("Model should not have changed yet", testEditor.modelHasChanged()) - assertEquals("Model should have 2 templates now", 2, testEditor.tempModel?.templateCount) - assertFalse("Ordinal pending add?", testEditor.tempModel.isOrdinalPendingAdd(0)) - assertFalse("Ordinal pending add?", testEditor.tempModel.isOrdinalPendingAdd(1)) + assertFalse("Note type should not have changed yet", testEditor.noteTypeHasChanged()) + assertEquals("Note type should have 2 templates now", 2, testEditor.tempNoteType?.templateCount) + assertFalse("Ordinal pending add?", testEditor.tempNoteType.isOrdinalPendingAdd(0)) + assertFalse("Ordinal pending add?", testEditor.tempNoteType.isOrdinalPendingAdd(1)) // Create note with forward and back info - val selectiveGeneratedNote = col.newNote(collectionBasicModelOriginal) + val selectiveGeneratedNote = col.newNote(collectionBasicNoteTypeOriginal) selectiveGeneratedNote.setField(0, "TestFront") selectiveGeneratedNote.setField(1, "TestBack") col.addNote(selectiveGeneratedNote) - assertEquals("card generation should result in two cards", 2, getModelCardCount(collectionBasicModelOriginal)) + assertEquals("card generation should result in two cards", 2, getNoteTypeCardCount(collectionBasicNoteTypeOriginal)) // Test if we can delete the template - should be possible - but cancel the delete var shadowTestEditor = shadowOf(testEditor) @@ -447,39 +447,39 @@ class CardTemplateEditorTest : RobolectricTest() { ) clickAlertDialogButton(DialogInterface.BUTTON_NEGATIVE, true) advanceRobolectricLooperWithSleep() - assertNotNull("Cannot delete template?", collectionBasicModelOriginal.getCardIds(0)) - assertNotNull("Cannot delete template?", collectionBasicModelOriginal.getCardIds(1)) - assertNull("Can delete both templates?", collectionBasicModelOriginal.getCardIds(0, 1)) + assertNotNull("Cannot delete template?", collectionBasicNoteTypeOriginal.getCardIds(0)) + assertNotNull("Cannot delete template?", collectionBasicNoteTypeOriginal.getCardIds(1)) + assertNull("Can delete both templates?", collectionBasicNoteTypeOriginal.getCardIds(0, 1)) assertEquals( "Change in database despite no change?", - collectionBasicModelOriginal.toString().trim { + collectionBasicNoteTypeOriginal.toString().trim { it <= ' ' }, - getCurrentDatabaseModelCopy(modelName).toString().trim { it <= ' ' }, + getCurrentDatabaseNoteTypeCopy(noteTypeName).toString().trim { it <= ' ' }, ) - assertEquals("Model should have 2 templates still", 2, testEditor.tempModel?.templateCount) + assertEquals("Note type should have 2 templates still", 2, testEditor.tempNoteType?.templateCount) // Add a template - click add, click confirm for card add, click confirm again for full sync addCardType(testEditor, shadowTestEditor) - assertTrue("Model should have changed", testEditor.modelHasChanged()) + assertTrue("Note type should have changed", testEditor.noteTypeHasChanged()) assertEquals( "Change added but not adjusted correctly?", 2, - CardTemplateNotetype.getAdjustedAddOrdinalAtChangeIndex(testEditor.tempModel!!, 0), + CardTemplateNotetype.getAdjustedAddOrdinalAtChangeIndex(testEditor.tempNoteType!!, 0), ) - assertFalse("Ordinal pending add?", testEditor.tempModel.isOrdinalPendingAdd(0)) - assertFalse("Ordinal pending add?", testEditor.tempModel.isOrdinalPendingAdd(1)) - assertTrue("Ordinal not pending add?", testEditor.tempModel.isOrdinalPendingAdd(2)) + assertFalse("Ordinal pending add?", testEditor.tempNoteType.isOrdinalPendingAdd(0)) + assertFalse("Ordinal pending add?", testEditor.tempNoteType.isOrdinalPendingAdd(1)) + assertTrue("Ordinal not pending add?", testEditor.tempNoteType.isOrdinalPendingAdd(2)) assertTrue("Unable to click?", shadowTestEditor.clickMenuItem(R.id.action_confirm)) advanceRobolectricLooperWithSleep() - assertFalse("Model should now be unchanged", testEditor.modelHasChanged()) - assertEquals("card generation should result in three cards", 3, getModelCardCount(collectionBasicModelOriginal)) - // reload the model for future comparison after saving the edit - collectionBasicModelOriginal = getCurrentDatabaseModelCopy(modelName) + assertFalse("Note type should now be unchanged", testEditor.noteTypeHasChanged()) + assertEquals("card generation should result in three cards", 3, getNoteTypeCardCount(collectionBasicNoteTypeOriginal)) + // reload the note type for future comparison after saving the edit + collectionBasicNoteTypeOriginal = getCurrentDatabaseNoteTypeCopy(noteTypeName) // Start the CardTemplateEditor back up after saving (which closes the thing...) intent = Intent(Intent.ACTION_VIEW) - intent.putExtra("modelId", collectionBasicModelOriginal.id) + intent.putExtra("noteTypeId", collectionBasicNoteTypeOriginal.id) templateEditorController = Robolectric .buildActivity(CardTemplateEditor::class.java, intent) @@ -489,29 +489,29 @@ class CardTemplateEditorTest : RobolectricTest() { .visible() testEditor = templateEditorController.get() shadowTestEditor = shadowOf(testEditor) - assertFalse("Model should not have changed yet", testEditor.modelHasChanged()) - assertFalse("Ordinal pending add?", testEditor.tempModel.isOrdinalPendingAdd(0)) - assertFalse("Ordinal pending add?", testEditor.tempModel.isOrdinalPendingAdd(1)) - assertFalse("Ordinal pending add?", testEditor.tempModel.isOrdinalPendingAdd(2)) - assertEquals("Model should have 3 templates now", 3, testEditor.tempModel?.templateCount) + assertFalse("Note type should not have changed yet", testEditor.noteTypeHasChanged()) + assertFalse("Ordinal pending add?", testEditor.tempNoteType.isOrdinalPendingAdd(0)) + assertFalse("Ordinal pending add?", testEditor.tempNoteType.isOrdinalPendingAdd(1)) + assertFalse("Ordinal pending add?", testEditor.tempNoteType.isOrdinalPendingAdd(2)) + assertEquals("Note type should have 3 templates now", 3, testEditor.tempNoteType?.templateCount) // Add another template - but we work in memory for a while before saving addCardType(testEditor, shadowTestEditor) assertEquals( "Change added but not adjusted correctly?", 3, - CardTemplateNotetype.getAdjustedAddOrdinalAtChangeIndex(testEditor.tempModel!!, 0), + CardTemplateNotetype.getAdjustedAddOrdinalAtChangeIndex(testEditor.tempNoteType!!, 0), ) - assertTrue("Model should have changed", testEditor.modelHasChanged()) - assertEquals("Model should have 4 templates now", 4, testEditor.tempModel?.templateCount) - assertFalse("Ordinal pending add?", testEditor.tempModel.isOrdinalPendingAdd(0)) - assertFalse("Ordinal pending add?", testEditor.tempModel.isOrdinalPendingAdd(1)) - assertFalse("Ordinal pending add?", testEditor.tempModel.isOrdinalPendingAdd(2)) - assertTrue("Ordinal not pending add?", testEditor.tempModel.isOrdinalPendingAdd(3)) + assertTrue("Note type should have changed", testEditor.noteTypeHasChanged()) + assertEquals("Note type should have 4 templates now", 4, testEditor.tempNoteType?.templateCount) + assertFalse("Ordinal pending add?", testEditor.tempNoteType.isOrdinalPendingAdd(0)) + assertFalse("Ordinal pending add?", testEditor.tempNoteType.isOrdinalPendingAdd(1)) + assertFalse("Ordinal pending add?", testEditor.tempNoteType.isOrdinalPendingAdd(2)) + assertTrue("Ordinal not pending add?", testEditor.tempNoteType.isOrdinalPendingAdd(3)) assertEquals( "Change added but not adjusted correctly?", 3, - CardTemplateNotetype.getAdjustedAddOrdinalAtChangeIndex(testEditor.tempModel!!, 0), + CardTemplateNotetype.getAdjustedAddOrdinalAtChangeIndex(testEditor.tempNoteType!!, 0), ) // Delete two pre-existing templates for real now - but still without saving it out, should work fine @@ -539,34 +539,34 @@ class CardTemplateEditorTest : RobolectricTest() { advanceRobolectricLooperWithSleep() // - assert can delete any 1 or 2 Card templates but not all - assertNotNull("Cannot delete template?", collectionBasicModelOriginal.getCardIds(0)) - assertNotNull("Cannot delete template?", collectionBasicModelOriginal.getCardIds(1)) - assertNotNull("Cannot delete template?", collectionBasicModelOriginal.getCardIds(2)) - assertNotNull("Cannot delete two templates?", collectionBasicModelOriginal.getCardIds(0, 1)) - assertNotNull("Cannot delete two templates?", collectionBasicModelOriginal.getCardIds(0, 2)) - assertNotNull("Cannot delete two templates?", collectionBasicModelOriginal.getCardIds(1, 2)) - assertNull("Can delete all templates?", collectionBasicModelOriginal.getCardIds(0, 1, 2)) + assertNotNull("Cannot delete template?", collectionBasicNoteTypeOriginal.getCardIds(0)) + assertNotNull("Cannot delete template?", collectionBasicNoteTypeOriginal.getCardIds(1)) + assertNotNull("Cannot delete template?", collectionBasicNoteTypeOriginal.getCardIds(2)) + assertNotNull("Cannot delete two templates?", collectionBasicNoteTypeOriginal.getCardIds(0, 1)) + assertNotNull("Cannot delete two templates?", collectionBasicNoteTypeOriginal.getCardIds(0, 2)) + assertNotNull("Cannot delete two templates?", collectionBasicNoteTypeOriginal.getCardIds(1, 2)) + assertNull("Can delete all templates?", collectionBasicNoteTypeOriginal.getCardIds(0, 1, 2)) assertEquals( "Change already in database?", - collectionBasicModelOriginal.toString().trim { + collectionBasicNoteTypeOriginal.toString().trim { it <= ' ' }, - getCurrentDatabaseModelCopy(modelName).toString().trim { it <= ' ' }, + getCurrentDatabaseNoteTypeCopy(noteTypeName).toString().trim { it <= ' ' }, ) assertEquals( "Change added but not adjusted correctly?", 1, - CardTemplateNotetype.getAdjustedAddOrdinalAtChangeIndex(testEditor.tempModel!!, 0), + CardTemplateNotetype.getAdjustedAddOrdinalAtChangeIndex(testEditor.tempNoteType!!, 0), ) assertEquals( "Change incorrectly pending add?", -1, - CardTemplateNotetype.getAdjustedAddOrdinalAtChangeIndex(testEditor.tempModel!!, 1), + CardTemplateNotetype.getAdjustedAddOrdinalAtChangeIndex(testEditor.tempNoteType!!, 1), ) assertEquals( "Change incorrectly pending add?", -1, - CardTemplateNotetype.getAdjustedAddOrdinalAtChangeIndex(testEditor.tempModel!!, 2), + CardTemplateNotetype.getAdjustedAddOrdinalAtChangeIndex(testEditor.tempNoteType!!, 2), ) // Now confirm everything to persist it to the database @@ -575,13 +575,17 @@ class CardTemplateEditorTest : RobolectricTest() { advanceRobolectricLooperWithSleep() assertNotEquals( "Change not in database?", - collectionBasicModelOriginal.toString().trim { + collectionBasicNoteTypeOriginal.toString().trim { it <= ' ' }, - getCurrentDatabaseModelCopy(modelName).toString().trim { it <= ' ' }, + getCurrentDatabaseNoteTypeCopy(noteTypeName).toString().trim { it <= ' ' }, ) - assertEquals("Model should have 2 templates now", 2, getCurrentDatabaseModelCopy(modelName).getJSONArray("tmpls").length()) - assertEquals("should be two cards", 2, getModelCardCount(collectionBasicModelOriginal)) + assertEquals( + "Note type should have 2 templates now", + 2, + getCurrentDatabaseNoteTypeCopy(noteTypeName).getJSONArray("tmpls").length(), + ) + assertEquals("should be two cards", 2, getNoteTypeCardCount(collectionBasicNoteTypeOriginal)) } /** @@ -590,12 +594,12 @@ class CardTemplateEditorTest : RobolectricTest() { @Test fun testDeletePendingAddExistingCardCount() = runTest { - val modelName = "Basic (optional reversed card)" - val collectionBasicModelOriginal = getCurrentDatabaseModelCopy(modelName) + val noteTypeName = "Basic (optional reversed card)" + val collectionBasicNoteTypeOriginal = getCurrentDatabaseNoteTypeCopy(noteTypeName) - // Start the CardTemplateEditor with a specific model, and make sure the model starts unchanged + // Start the CardTemplateEditor with a specific note type, and make sure the note type starts unchanged val intent = Intent(Intent.ACTION_VIEW) - intent.putExtra("modelId", collectionBasicModelOriginal.id) + intent.putExtra("noteTypeId", collectionBasicNoteTypeOriginal.id) val templateEditorController = Robolectric .buildActivity( @@ -607,18 +611,18 @@ class CardTemplateEditorTest : RobolectricTest() { .visible() saveControllerForCleanup(templateEditorController) val testEditor = templateEditorController.get() - assertFalse("Model should not have changed yet", testEditor.modelHasChanged()) - assertEquals("Model should have 2 templates now", 2, testEditor.tempModel?.templateCount) - assertFalse("Ordinal pending add?", testEditor.tempModel.isOrdinalPendingAdd(0)) - assertFalse("Ordinal pending add?", testEditor.tempModel.isOrdinalPendingAdd(1)) + assertFalse("Note type should not have changed yet", testEditor.noteTypeHasChanged()) + assertEquals("Note type should have 2 templates now", 2, testEditor.tempNoteType?.templateCount) + assertFalse("Ordinal pending add?", testEditor.tempNoteType.isOrdinalPendingAdd(0)) + assertFalse("Ordinal pending add?", testEditor.tempNoteType.isOrdinalPendingAdd(1)) // Create note with forward and back info - val selectiveGeneratedNote = col.newNote(collectionBasicModelOriginal) + val selectiveGeneratedNote = col.newNote(collectionBasicNoteTypeOriginal) selectiveGeneratedNote.setField(0, "TestFront") selectiveGeneratedNote.setField(1, "TestBack") selectiveGeneratedNote.setField(2, "y") col.addNote(selectiveGeneratedNote) - assertEquals("card generation should result in two cards", 2, getModelCardCount(collectionBasicModelOriginal)) + assertEquals("card generation should result in two cards", 2, getNoteTypeCardCount(collectionBasicNoteTypeOriginal)) // Delete ord 1 / 'Card 2' and check the message val shadowTestEditor = shadowOf(testEditor) @@ -632,30 +636,30 @@ class CardTemplateEditorTest : RobolectricTest() { ) clickAlertDialogButton(DialogInterface.BUTTON_POSITIVE, true) advanceRobolectricLooperWithSleep() - assertTrue("Model should have changed", testEditor.modelHasChanged()) - assertNotNull("Cannot delete template?", collectionBasicModelOriginal.getCardIds(0)) - assertNotNull("Cannot delete template?", collectionBasicModelOriginal.getCardIds(1)) - assertNull("Can delete both templates?", collectionBasicModelOriginal.getCardIds(0, 1)) + assertTrue("Note type should have changed", testEditor.noteTypeHasChanged()) + assertNotNull("Cannot delete template?", collectionBasicNoteTypeOriginal.getCardIds(0)) + assertNotNull("Cannot delete template?", collectionBasicNoteTypeOriginal.getCardIds(1)) + assertNull("Can delete both templates?", collectionBasicNoteTypeOriginal.getCardIds(0, 1)) assertEquals( "Change in database despite no save?", - collectionBasicModelOriginal.toString().trim { + collectionBasicNoteTypeOriginal.toString().trim { it <= ' ' }, - getCurrentDatabaseModelCopy(modelName).toString().trim { it <= ' ' }, + getCurrentDatabaseNoteTypeCopy(noteTypeName).toString().trim { it <= ' ' }, ) - assertEquals("Model should have 1 template", 1, testEditor.tempModel?.templateCount) + assertEquals("Note type should have 1 template", 1, testEditor.tempNoteType?.templateCount) // Add a template - click add, click confirm for card add, click confirm again for full sync addCardType(testEditor, shadowTestEditor) - assertTrue("Model should have changed", testEditor.modelHasChanged()) + assertTrue("Note type should have changed", testEditor.noteTypeHasChanged()) assertEquals( "Change added but not adjusted correctly?", 1, - CardTemplateNotetype.getAdjustedAddOrdinalAtChangeIndex(testEditor.tempModel!!, 1), + CardTemplateNotetype.getAdjustedAddOrdinalAtChangeIndex(testEditor.tempNoteType!!, 1), ) - assertFalse("Ordinal pending add?", testEditor.tempModel.isOrdinalPendingAdd(0)) - assertTrue("Ordinal not pending add?", testEditor.tempModel.isOrdinalPendingAdd(1)) - assertEquals("Model should have 2 templates", 2, testEditor.tempModel?.templateCount) + assertFalse("Ordinal pending add?", testEditor.tempNoteType.isOrdinalPendingAdd(0)) + assertTrue("Ordinal not pending add?", testEditor.tempNoteType.isOrdinalPendingAdd(1)) + assertEquals("Note type should have 2 templates", 2, testEditor.tempNoteType?.templateCount) // Delete ord 1 / 'Card 2' again and check the message - it's in the same spot as the pre-existing template but there are no cards actually associated testEditor.viewPager.currentItem = 1 @@ -668,34 +672,34 @@ class CardTemplateEditorTest : RobolectricTest() { ) clickAlertDialogButton(DialogInterface.BUTTON_POSITIVE, true) advanceRobolectricLooperWithSleep() - assertTrue("Model should have changed", testEditor.modelHasChanged()) - assertNotNull("Cannot delete template?", collectionBasicModelOriginal.getCardIds(0)) - assertNotNull("Cannot delete template?", collectionBasicModelOriginal.getCardIds(1)) - assertNull("Can delete both templates?", collectionBasicModelOriginal.getCardIds(0, 1)) + assertTrue("Note type should have changed", testEditor.noteTypeHasChanged()) + assertNotNull("Cannot delete template?", collectionBasicNoteTypeOriginal.getCardIds(0)) + assertNotNull("Cannot delete template?", collectionBasicNoteTypeOriginal.getCardIds(1)) + assertNull("Can delete both templates?", collectionBasicNoteTypeOriginal.getCardIds(0, 1)) assertEquals( "Change in database despite no save?", - collectionBasicModelOriginal.toString().trim { + collectionBasicNoteTypeOriginal.toString().trim { it <= ' ' }, - getCurrentDatabaseModelCopy(modelName).toString().trim { it <= ' ' }, + getCurrentDatabaseNoteTypeCopy(noteTypeName).toString().trim { it <= ' ' }, ) - assertEquals("Model should have 1 template", 1, testEditor.tempModel?.templateCount) + assertEquals("Note type should have 1 template", 1, testEditor.tempNoteType?.templateCount) // Save it out and make some assertions assertTrue("Unable to click?", shadowTestEditor.clickMenuItem(R.id.action_confirm)) advanceRobolectricLooperWithSleep() - assertFalse("Model should now be unchanged", testEditor.modelHasChanged()) - assertEquals("card generation should result in 1 card", 1, getModelCardCount(collectionBasicModelOriginal)) + assertFalse("Note type should now be unchanged", testEditor.noteTypeHasChanged()) + assertEquals("card generation should result in 1 card", 1, getNoteTypeCardCount(collectionBasicNoteTypeOriginal)) } @Test fun testDeckOverride() { - val modelName = "Basic (optional reversed card)" - val model = getCurrentDatabaseModelCopy(modelName) + val noteTypeName = "Basic (optional reversed card)" + val noteType = getCurrentDatabaseNoteTypeCopy(noteTypeName) val intent = Intent(Intent.ACTION_VIEW) - intent.putExtra("modelId", model.id) + intent.putExtra("noteTypeId", noteType.id) val editor = super.startActivityNormallyOpenCollectionWithIntent(CardTemplateEditor::class.java, intent) - val template = editor.tempModel?.getTemplate(0) + val template = editor.tempNoteType?.getTemplate(0) MatcherAssert.assertThat("Deck ID element should exist", template?.has("did"), Matchers.equalTo(true)) MatcherAssert.assertThat("Deck ID element should be null", template?.get("did"), Matchers.equalTo(JSONObject.NULL)) editor.onDeckSelected(SelectableDeck(1, "hello")) @@ -707,12 +711,12 @@ class CardTemplateEditorTest : RobolectricTest() { @Test fun testContentPreservedAfterChangingEditorView() { - val modelName = "Basic" + val noteTypeName = "Basic" - // Start the CardTemplateEditor with a specific model, and make sure the model starts unchanged - val collectionBasicModelOriginal = getCurrentDatabaseModelCopy(modelName) + // Start the CardTemplateEditor with a specific note type, and make sure the note type starts unchanged + val collectionBasicNoteTypeOriginal = getCurrentDatabaseNoteTypeCopy(noteTypeName) val intent = Intent(Intent.ACTION_VIEW) - intent.putExtra("modelId", collectionBasicModelOriginal.getLong("id")) + intent.putExtra("noteTypeId", collectionBasicNoteTypeOriginal.getLong("id")) val templateEditorController = Robolectric .buildActivity(CardTemplateEditor::class.java, intent) @@ -723,20 +727,20 @@ class CardTemplateEditorTest : RobolectricTest() { saveControllerForCleanup(templateEditorController) val testEditor = templateEditorController.get() - // Change the model and make sure it registers as changed, but the database is unchanged + // Change the note type and make sure it registers as changed, but the database is unchanged val templateEditText = testEditor.findViewById(R.id.editor_editText) - val testModelQfmtEdit = "!@#$%^&*TEST*&^%$#@!" - val updatedFrontContent = templateEditText.text.append(testModelQfmtEdit).toString() + val testNoteTypeQfmtEdit = "!@#$%^&*TEST*&^%$#@!" + val updatedFrontContent = templateEditText.text.append(testNoteTypeQfmtEdit).toString() advanceRobolectricLooperWithSleep() val cardTemplateFragment = testEditor.currentFragment - val tempModel = testEditor.tempModel + val tempNoteType = testEditor.tempNoteType // set Bottom Navigation View to Style - cardTemplateFragment!!.setCurrentEditorView(R.id.styling_edit, tempModel!!.css, R.string.card_template_editor_styling) + cardTemplateFragment!!.setCurrentEditorView(R.id.styling_edit, tempNoteType!!.css, R.string.card_template_editor_styling) // set Bottom Navigation View to Front cardTemplateFragment.setCurrentEditorView( R.id.front_edit, - tempModel.getTemplate(0).getString("qfmt"), + tempNoteType.getTemplate(0).getString("qfmt"), R.string.card_template_editor_front, ) @@ -746,12 +750,12 @@ class CardTemplateEditorTest : RobolectricTest() { @Test fun testBottomNavigationViewLayoutTransition() { - val modelName = "Basic" + val noteTypeName = "Basic" - // Start the CardTemplateEditor with a specific model, and make sure the model starts unchanged - val collectionBasicModelOriginal = getCurrentDatabaseModelCopy(modelName) + // Start the CardTemplateEditor with a specific note type, and make sure the note type starts unchanged + val collectionBasicNoteTypeOriginal = getCurrentDatabaseNoteTypeCopy(noteTypeName) val intent = Intent(Intent.ACTION_VIEW) - intent.putExtra("modelId", collectionBasicModelOriginal.id) + intent.putExtra("noteTypeId", collectionBasicNoteTypeOriginal.id) val templateEditorController = Robolectric .buildActivity(CardTemplateEditor::class.java, intent) @@ -762,21 +766,21 @@ class CardTemplateEditorTest : RobolectricTest() { saveControllerForCleanup(templateEditorController) val testEditor = templateEditorController.get() - // Change the model and make sure it registers as changed, but the database is unchanged + // Change the note type and make sure it registers as changed, but the database is unchanged val templateEditText = testEditor.findViewById(R.id.editor_editText) advanceRobolectricLooperWithSleep() val cardTemplateFragment = testEditor.currentFragment - val tempModel = testEditor.tempModel + val tempNoteType = testEditor.tempNoteType // check if current view is front(default) view - assumeThat(templateEditText.text.toString(), Matchers.equalTo(tempModel!!.getTemplate(0).getString("qfmt"))) + assumeThat(templateEditText.text.toString(), Matchers.equalTo(tempNoteType!!.getTemplate(0).getString("qfmt"))) assumeThat(cardTemplateFragment!!.currentEditorViewId, Matchers.equalTo(R.id.front_edit)) // set Bottom Navigation View to Style - cardTemplateFragment.setCurrentEditorView(R.id.styling_edit, tempModel.css, R.string.card_template_editor_styling) + cardTemplateFragment.setCurrentEditorView(R.id.styling_edit, tempNoteType.css, R.string.card_template_editor_styling) // check if current view is changed or not - assumeThat(templateEditText.text.toString(), Matchers.equalTo(tempModel.css)) + assumeThat(templateEditText.text.toString(), Matchers.equalTo(tempNoteType.css)) assumeThat(cardTemplateFragment.currentEditorViewId, Matchers.equalTo(R.id.styling_edit)) } @@ -788,8 +792,8 @@ class CardTemplateEditorTest : RobolectricTest() { advanceRobolectricLooperWithSleep() val ordinal = testEditor.viewPager.currentItem val numAffectedCards = - if (!testEditor.tempModel.isOrdinalPendingAdd(ordinal)) { - col.notetypes.tmplUseCount(testEditor.tempModel!!.notetype, ordinal) + if (!testEditor.tempNoteType.isOrdinalPendingAdd(ordinal)) { + col.notetypes.tmplUseCount(testEditor.tempNoteType!!.notetype, ordinal) } else { 0 } @@ -837,7 +841,7 @@ Hello World{{Front}} ) } - private fun getModelCardCount(notetype: NotetypeJson): Int { + private fun getNoteTypeCardCount(notetype: NotetypeJson): Int { var cardCount = 0 for (noteId in col.notetypes.nids(notetype)) { cardCount += col.getNote(noteId).numberOfCards() @@ -851,7 +855,7 @@ Hello World{{Front}} } private val CardTemplateEditor.templateChangeCount - get() = tempModel?.templateChanges?.size + get() = tempNoteType?.templateChanges?.size - private suspend fun NotetypeJson.getCardIds(vararg ords: Int): List? = withCol { notetypes.getCardIdsForModel(id, ords) } + private suspend fun NotetypeJson.getCardIds(vararg ords: Int): List? = withCol { notetypes.getCardIdsForNoteType(id, ords) } } diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/CardTemplateNotetypeTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/CardTemplateNotetypeTest.kt index 2c79f612f096..b6a8ba074dac 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/CardTemplateNotetypeTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/CardTemplateNotetypeTest.kt @@ -34,22 +34,22 @@ import kotlin.test.junit5.JUnit5Asserter.assertNotNull class CardTemplateNotetypeTest : RobolectricTest() { @Test @Throws(Exception::class) - fun testTempModelStorage() { + fun testTempNoteTypeStorage() { // Start off with clean state in the cache dir - CardTemplateNotetype.clearTempModelFiles() + CardTemplateNotetype.clearTempNoteTypeFiles() // Make sure save / retrieve works - val tempModelPath = CardTemplateNotetype.saveTempModel(targetContext, JSONObject("{\"foo\": \"bar\"}")) - assertNotNull("Saving temp model unsuccessful", tempModelPath) - val tempModel: JSONObject = CardTemplateNotetype.getTempModel(tempModelPath!!) - assertNotNull("Temp model not read successfully", tempModel) - Assert.assertEquals(JSONObject("{\"foo\": \"bar\"}").toString(), tempModel.toString()) + val tempNoteTypePath = CardTemplateNotetype.saveTempNoteType(targetContext, JSONObject("{\"foo\": \"bar\"}")) + assertNotNull("Saving temp note type unsuccessful", tempNoteTypePath) + val tempNoteType: JSONObject = CardTemplateNotetype.getTempNoteType(tempNoteTypePath!!) + assertNotNull("Temp note type not read successfully", tempNoteType) + Assert.assertEquals(JSONObject("{\"foo\": \"bar\"}").toString(), tempNoteType.toString()) // Make sure clearing works - Assert.assertEquals(1, CardTemplateNotetype.clearTempModelFiles().toLong()) + Assert.assertEquals(1, CardTemplateNotetype.clearTempNoteTypeFiles().toLong()) Timber.i("The following logged NoSuchFileException is an expected part of verifying a file delete.") try { - CardTemplateNotetype.getTempModel(tempModelPath) + CardTemplateNotetype.getTempNoteType(tempNoteTypePath) Assert.fail("Should have caught an exception here because the file is missing") } catch (e: IOException) { // this is expected @@ -58,7 +58,7 @@ class CardTemplateNotetypeTest : RobolectricTest() { @Test fun testAddDeleteTracking() { - // Assume you start with a 2 template model (like "Basic (and reversed)") + // Assume you start with a 2 template note type (like "Basic (and reversed)") // Add a 3rd new template, remove the 2nd, remove the 1st, add a new now-2nd, remove 1st again // ...and it should reduce to just removing the original 1st/2nd and adding the final as first val tempNotetype = CardTemplateNotetype(NotetypeJson("{ \"foo\": \"bar\" }")) diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/DeckPickerTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/DeckPickerTest.kt index b63f60fc5d41..57e16005d02a 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/DeckPickerTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/DeckPickerTest.kt @@ -180,7 +180,7 @@ class DeckPickerTest : RobolectricTest() { dconf.getJSONObject("new").put("perDay", 10) col.decks.save(dconf) for (i in 0..10) { - addNoteUsingBasicModel("Which card is this ?", i.toString()) + addBasicNote("Which card is this ?", i.toString()) } // This set a card as current card sched.card @@ -363,7 +363,7 @@ class DeckPickerTest : RobolectricTest() { Intent(), ) - // Neither collection, not its models will be initialized without storage permission + // Neither collection, not its note types will be initialized without storage permission // assert: Lazy Collection initialization CollectionTask.LoadCollectionComplete fails assertFailsWith { d.getColUnsafe } @@ -387,7 +387,7 @@ class DeckPickerTest : RobolectricTest() { notNullValue(), ) assertThat( - "Collection Models Loaded", + "Collection Note types Loaded", d.getColUnsafe.notetypes, notNullValue(), ) @@ -503,7 +503,7 @@ class DeckPickerTest : RobolectricTest() { val deckId = addDeck("Deck 1") getColUnsafe.decks.select(deckId) getColUnsafe.notetypes.byName("Basic")!!.put("did", deckId) - val card = addNoteUsingBasicModel("front", "back").firstCard() + val card = addBasicNote("front", "back").firstCard() getColUnsafe.sched.buryCards(listOf(card.id)) updateDeckList() assertEquals(1, visibleDeckCount) @@ -519,7 +519,7 @@ class DeckPickerTest : RobolectricTest() { startActivityNormallyOpenCollectionWithIntent(DeckPicker::class.java, Intent()).run { val cardIds = (0..3) - .map { addNoteUsingBasicModel("$it", "").firstCard().id } + .map { addBasicNote("$it", "").firstCard().id } assertTrue(allCardsInSameDeck(cardIds, 1)) val deckId = addDynamicDeck("Deck 1") getColUnsafe.sched.rebuildDyn(deckId) @@ -703,7 +703,7 @@ class DeckPickerTest : RobolectricTest() { col.notetypes.byName("Basic (and reversed card)")!!.also { noteType -> col.notetypes.save(noteType.apply { put("did", deckWithCards) }) } - addNoteUsingBasicAndReversedModel() + addBasicAndReverseNote() // Answer 'Easy' for one of the cards, burying the other col.decks.select(deckWithCards) diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/NoteEditorTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/NoteEditorTest.kt index 5b7e92960fb3..26ed0b0281f5 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/NoteEditorTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/NoteEditorTest.kt @@ -239,7 +239,7 @@ class NoteEditorTest : RobolectricTest() { fun copyNoteCopiesDeckId() { val currentDid = addDeck("Basic::Test") col.config.set(CURRENT_DECK, currentDid) - val n = super.addNoteUsingBasicModel("Test", "Note") + val n = super.addBasicNote("Test", "Note") n.notetype.put("did", currentDid) val editor = getNoteEditorEditingExistingBasicNote("Test", "Note", DECK_LIST) col.config.set(CURRENT_DECK, Consts.DEFAULT_DECK_ID) // Change DID if going through default path @@ -350,7 +350,7 @@ class NoteEditorTest : RobolectricTest() { @Test fun pasteHtmlAsPlainTextTest() { val editor = getNoteEditorAddingNote(DECK_LIST) - editor.setCurrentlySelectedModel(col.notetypes.byName("Basic")!!.getLong("id")) + editor.setCurrentlySelectedNoteType(col.notetypes.byName("Basic")!!.getLong("id")) val field = editor.getFieldForTest(0) field.clipboard!!.setPrimaryClip(ClipData.newHtmlText("text", "text", """text""")) assertTrue(field.clipboard!!.hasPrimaryClip()) @@ -422,7 +422,7 @@ class NoteEditorTest : RobolectricTest() { // by default, the first deck is selected, so move the card to the second deck val homeDeckId = addDeck("B", setAsSelected = true) - val note = addNoteUsingBasicModel().updateCards { did = homeDeckId } + val note = addBasicNote().updateCards { did = homeDeckId } moveToDynamicDeck(note) // ensure note is correctly setup @@ -466,7 +466,7 @@ class NoteEditorTest : RobolectricTest() { fun `editing card in filtered deck retains deck`() = runTest { val homeDeckId = addDeck("A") - val note = addNoteUsingBasicModel().updateCards { did = homeDeckId } + val note = addBasicNote().updateCards { did = homeDeckId } moveToDynamicDeck(note) // ensure note is correctly setup @@ -528,11 +528,11 @@ class NoteEditorTest : RobolectricTest() { NoteType.BASIC -> col.notetypes.byName("Basic") NoteType.CLOZE -> col.notetypes.byName("Cloze") NoteType.BACK_TO_FRONT -> { - val name = super.addNonClozeModel("Reversed", arrayOf("Front", "Back"), "{{Back}}", "{{Front}}") + val name = super.addNonClozeNoteType("Reversed", arrayOf("Front", "Back"), "{{Back}}", "{{Front}}") col.notetypes.byName(name) } NoteType.THREE_FIELD_INVALID_TEMPLATE -> { - val name = super.addNonClozeModel("Invalid", arrayOf("Front", "Back", "Side"), "", "") + val name = super.addNonClozeNoteType("Invalid", arrayOf("Front", "Back", "Side"), "", "") col.notetypes.byName(name) } NoteType.IMAGE_OCCLUSION -> col.notetypes.byName("Image Occlusion") @@ -553,7 +553,7 @@ class NoteEditorTest : RobolectricTest() { back: String, from: FromScreen, ): NoteEditor { - val n = super.addNoteUsingBasicModel(front, back) + val n = super.addBasicNote(front, back) return getNoteEditorEditingExistingBasicNote(n, from) } @@ -661,7 +661,7 @@ class NoteEditorTest : RobolectricTest() { } init { - assertNotNull(notetype) { "model was null" } + assertNotNull(notetype) { "note type was null" } this.notetype = notetype } } diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/ModelFieldEditorTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/NoteTypeFieldEditorTest.kt similarity index 87% rename from AnkiDroid/src/test/java/com/ichi2/anki/ModelFieldEditorTest.kt rename to AnkiDroid/src/test/java/com/ichi2/anki/NoteTypeFieldEditorTest.kt index bd8cd8a92de1..e1cb0fd0a53f 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/ModelFieldEditorTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/NoteTypeFieldEditorTest.kt @@ -31,7 +31,7 @@ import org.junit.runner.RunWith import org.robolectric.ParameterizedRobolectricTestRunner @RunWith(ParameterizedRobolectricTestRunner::class) -class ModelFieldEditorTest( +class NoteTypeFieldEditorTest( private val forbiddenCharacter: String, ) : RobolectricTest() { /** @@ -53,13 +53,13 @@ class ModelFieldEditorTest( } /** - * Assert that model's fields doesn't contain the forbidden field name + * Assert that note type's fields doesn't contain the forbidden field name * * @param forbiddenFieldName The forbidden field name to identify */ private fun testForIllegalCharacters(forbiddenFieldName: String) { - val modelFields = getCurrentDatabaseModelCopy("Basic").fieldsNames - val fieldName = modelFields[modelFields.size - 1] + val noteTypeFields = getCurrentDatabaseNoteTypeCopy("Basic").fieldsNames + val fieldName = noteTypeFields[noteTypeFields.size - 1] MatcherAssert.assertThat("forbidden character detected!", fieldName, Matchers.not(Matchers.equalTo(forbiddenFieldName))) } @@ -90,7 +90,7 @@ class ModelFieldEditorTest( } /** - * Creates a dialog that adds a field with given field name to "Basic" model when its positive button is clicked + * Creates a dialog that adds a field with given field name to "Basic" note type when its positive button is clicked * * @param fieldNameInput EditText with field name inside * @param fieldOperationType Field Operation Type to do (ADD_FIELD or EDIT_FIELD) @@ -104,22 +104,22 @@ class ModelFieldEditorTest( AlertDialog.Builder(ContextThemeWrapper(targetContext, R.style.Theme_Light)).show { positiveButton(text = "") { try { - val modelName = "Basic" + val noteTypeName = "Basic" // start ModelFieldEditor activity val intent = Intent() - intent.putExtra("title", modelName) - intent.putExtra("noteTypeID", col.notetypes.idForName(modelName)!!) - val modelFieldEditor = + intent.putExtra("title", noteTypeName) + intent.putExtra("noteTypeID", col.notetypes.idForName(noteTypeName)!!) + val noteTypeFieldEditor = startActivityNormallyOpenCollectionWithIntent( - this@ModelFieldEditorTest, - ModelFieldEditor::class.java, + this@NoteTypeFieldEditorTest, + NoteTypeFieldEditor::class.java, intent, ) when (fieldOperationType) { - FieldOperationType.ADD_FIELD -> modelFieldEditor.addField(fieldNameInput) + FieldOperationType.ADD_FIELD -> noteTypeFieldEditor.addField(fieldNameInput) FieldOperationType.RENAME_FIELD -> - modelFieldEditor.renameField( + noteTypeFieldEditor.renameField( fieldNameInput, ) } diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/ReviewerKeyboardInputTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/ReviewerKeyboardInputTest.kt index c4ff6b5ebad5..f02f6db6e00f 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/ReviewerKeyboardInputTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/ReviewerKeyboardInputTest.kt @@ -133,7 +133,7 @@ class ReviewerKeyboardInputTest : RobolectricTest() { @Test fun pressingStarWillMarkCard() { val underTest = KeyboardInputTestReviewer.displayingAnswer() - underTest.currentCard = addNoteUsingBasicModel("a", "").firstCard() + underTest.currentCard = addBasicNote("a", "").firstCard() underTest.handleUnicodeKeyPress('*') assertThat("Mark Card was called", underTest.markCardCalled) } @@ -141,7 +141,7 @@ class ReviewerKeyboardInputTest : RobolectricTest() { @Test fun pressingEqualsWillBuryNote() { val underTest = KeyboardInputTestReviewer.displayingAnswer() - underTest.currentCard = addNoteUsingBasicModel("a", "").firstCard() + underTest.currentCard = addBasicNote("a", "").firstCard() underTest.handleUnicodeKeyPress('=') assertThat("Bury Note should be called", underTest.buryNoteCalled) } @@ -151,7 +151,7 @@ class ReviewerKeyboardInputTest : RobolectricTest() { @Test fun pressingAtWillSuspendCard() { val underTest = KeyboardInputTestReviewer.displayingAnswer() - underTest.currentCard = addNoteUsingBasicModel("a", "").firstCard() + underTest.currentCard = addBasicNote("a", "").firstCard() underTest.handleUnicodeKeyPress('@') assertThat("Suspend Card should be called", underTest.suspendCardCalled) } @@ -159,7 +159,7 @@ class ReviewerKeyboardInputTest : RobolectricTest() { @Test fun pressingExclamationWillSuspendNote() { val underTest = KeyboardInputTestReviewer.displayingAnswer() - underTest.currentCard = addNoteUsingBasicModel("a", "").firstCard() + underTest.currentCard = addBasicNote("a", "").firstCard() underTest.handleUnicodeKeyPress('!') assertThat("Suspend Note should be called", underTest.suspendNoteCalled) } diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/ReviewerNoParamTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/ReviewerNoParamTest.kt index e5c1968a9182..3aa9480179c3 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/ReviewerNoParamTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/ReviewerNoParamTest.kt @@ -124,7 +124,7 @@ class ReviewerNoParamTest : RobolectricTest() { @Test fun flippingCardHidesFullscreen() { - addNoteUsingBasicModel("Hello", "World") + addBasicNote("Hello", "World") val reviewer = startReviewerFullScreen() val hideCount = reviewer.delayedHideCount @@ -142,7 +142,7 @@ class ReviewerNoParamTest : RobolectricTest() { " but: <2> was equal to <2>", ) fun showingCardHidesFullScreen() { - addNoteUsingBasicModel("Hello", "World") + addBasicNote("Hello", "World") val reviewer = startReviewerFullScreen() reviewer.displayCardAnswer() @@ -160,7 +160,7 @@ class ReviewerNoParamTest : RobolectricTest() { @Flaky(OS.ALL, "Expected: a value greater than <2> but: <2> was equal to <2>") fun undoingCardHidesFullScreen() = runTest { - addNoteUsingBasicModel("Hello", "World") + addBasicNote("Hello", "World") val reviewer = startReviewerFullScreen() reviewer.displayCardAnswer() @@ -352,7 +352,7 @@ class ReviewerNoParamTest : RobolectricTest() { @CheckResult private fun startReviewerForWhiteboard(): Whiteboard { // we need a card for the reviewer to start - addNoteUsingBasicModel("Hello", "World") + addBasicNote("Hello", "World") val reviewer = startReviewer() @@ -364,7 +364,7 @@ class ReviewerNoParamTest : RobolectricTest() { @CheckResult private fun startReviewerForWhiteboardInDarkMode(): Whiteboard { - addNoteUsingBasicModel("Hello", "World") + addBasicNote("Hello", "World") val reviewer = startReviewer() currentTheme = Theme.DARK diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/ReviewerTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/ReviewerTest.kt index b1e33a041905..4112aa9a59cb 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/ReviewerTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/ReviewerTest.kt @@ -45,7 +45,7 @@ import com.ichi2.libanki.utils.TimeManager import com.ichi2.testutils.MockTime import com.ichi2.testutils.common.Flaky import com.ichi2.testutils.common.OS -import com.ichi2.utils.BASIC_MODEL_NAME +import com.ichi2.utils.BASIC_NOTE_TYPE_NAME import com.ichi2.utils.KotlinCleanup import com.ichi2.utils.deepClone import junit.framework.TestCase.assertEquals @@ -82,8 +82,8 @@ class ReviewerTest : RobolectricTest() { @Test fun testOnSelectedTags() { - // Add a note using basic model - addNoteUsingBasicModel() + // Add a note using basic note type + addBasicNote() // Start the Reviewer activity val viewer = startRegularActivity() @@ -148,7 +148,7 @@ class ReviewerTest : RobolectricTest() { @Test fun noErrorShouldOccurIfSoundFileNotPresent() { - val firstNote = addNoteUsingBasicModel("[[sound:not_on_file_system.mp3]]", "World") + val firstNote = addBasicNote("[[sound:not_on_file_system.mp3]]", "World") moveToReviewQueue(firstNote.firstCard()) val reviewer = startReviewer() @@ -233,9 +233,9 @@ class ReviewerTest : RobolectricTest() { val cards = arrayOf( - addRevNoteUsingBasicModelDueToday("1", "bar").firstCard(), - addNoteUsingBasicModel("2", "bar").firstCard(), - addNoteUsingBasicModel("3", "bar").firstCard(), + addRevNoteUsingBasicNoteTypeDueToday("1", "bar").firstCard(), + addBasicNote("2", "bar").firstCard(), + addBasicNote("3", "bar").firstCard(), ) waitForAsyncTasksToComplete() @@ -271,12 +271,12 @@ class ReviewerTest : RobolectricTest() { @Test fun jsAnkiGetDeckName() = runTest { - val models = col.notetypes + val noteTypes = col.notetypes val didAb = addDeck("A::B") - val basic = models.byName(BASIC_MODEL_NAME) + val basic = noteTypes.byName(BASIC_NOTE_TYPE_NAME) basic!!.put("did", didAb) - addNoteUsingBasicModel("foo", "bar") + addBasicNote("foo", "bar") addDeck("A", setAsSelected = true) @@ -302,7 +302,7 @@ class ReviewerTest : RobolectricTest() { waitForAsyncTasksToComplete() // #6587 - addNoteUsingBasicModel("Hello", "World") + addBasicNote("Hello", "World") val sched = col.sched @@ -447,14 +447,14 @@ class ReviewerTest : RobolectricTest() { @Throws(ConfirmModSchemaException::class) private fun addNoteWithThreeCards() { - val models = col.notetypes - var notetype: NotetypeJson? = models.copy(models.current()) + val noteTypes = col.notetypes + var notetype: NotetypeJson? = noteTypes.copy(noteTypes.current()) notetype!!.put("name", "Three") - models.add(notetype) - notetype = models.byName("Three") + noteTypes.add(notetype) + notetype = noteTypes.byName("Three") - cloneTemplate(models, notetype, "1") - cloneTemplate(models, notetype, "2") + cloneTemplate(noteTypes, notetype, "1") + cloneTemplate(noteTypes, notetype, "2") val newNote = col.newNote() newNote.setField(0, "Hello") @@ -485,7 +485,7 @@ class ReviewerTest : RobolectricTest() { @CheckResult private fun startReviewer(withCards: Int = 0): Reviewer { for (i in 0 until withCards) { - addNoteUsingBasicModel() + addBasicNote() } return startReviewer(this) } @@ -498,7 +498,7 @@ class ReviewerTest : RobolectricTest() { block: suspend Reviewer.() -> Unit, ) = runTest { for (frontSide in cards) { - addNoteUsingBasicModel(front = frontSide) + addBasicNote(front = frontSide) } val reviewer = startReviewer(this@ReviewerTest) block(reviewer) diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt index b6dabb0b61ec..189f4c85300c 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/RobolectricTest.kt @@ -364,9 +364,9 @@ open class RobolectricTest : } @Throws(JSONException::class) - protected fun getCurrentDatabaseModelCopy(modelName: String): NotetypeJson { - val collectionModels = col.notetypes - return NotetypeJson(collectionModels.byName(modelName).toString().trim { it <= ' ' }) + protected fun getCurrentDatabaseNoteTypeCopy(noteType: String): NotetypeJson { + val collectionNoteType = col.notetypes + return NotetypeJson(collectionNoteType.byName(noteType).toString().trim { it <= ' ' }) } internal fun startActivityNormallyOpenCollectionWithIntent( diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserColumnTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserColumnTest.kt index c7e49aaa2218..81dbf1e8c3a4 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserColumnTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserColumnTest.kt @@ -89,7 +89,7 @@ class CardBrowserColumnTest : JvmTest() { ), ) - val note = addNoteUsingBasicModel() + val note = addBasicNote() val cid = note.cids()[0] val nid = note.id diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt index 499f4157675b..9fb75c0e52ff 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt @@ -106,7 +106,7 @@ class CardBrowserViewModelTest : JvmTest() { selectDefaultDeck() for (i in 0 until 5) { - addNoteUsingBasicAndReversedModel() + addBasicAndReverseNote() } setCardsOrNotes(CardsOrNotes.NOTES) waitForSearchResults() @@ -146,13 +146,13 @@ class CardBrowserViewModelTest : JvmTest() { @Test fun filterByFlagDisplaysProperly() = runViewModelTest { - val cardWithRedFlag = addNoteUsingBasicModel("Card with red flag", "Reverse") + val cardWithRedFlag = addBasicNote("Card with red flag", "Reverse") flagCardForNote(cardWithRedFlag, Flag.RED) - val cardWithGreenFlag = addNoteUsingBasicModel("Card with green flag", "Reverse") + val cardWithGreenFlag = addBasicNote("Card with green flag", "Reverse") flagCardForNote(cardWithGreenFlag, Flag.GREEN) - val anotherCardWithRedFlag = addNoteUsingBasicModel("Second card with red flag", "Reverse") + val anotherCardWithRedFlag = addBasicNote("Second card with red flag", "Reverse") flagCardForNote(anotherCardWithRedFlag, Flag.RED) setFlagFilterSync(Flag.RED) @@ -300,7 +300,7 @@ class CardBrowserViewModelTest : JvmTest() { @Test fun `selected card and note ids`() { - val notes = List(2) { addNoteUsingBasicAndReversedModel() } + val notes = List(2) { addBasicAndReverseNote() } val nids = notes.map { it.id }.toTypedArray() val cids = notes.flatMap { it.cids() }.toTypedArray() @@ -644,10 +644,10 @@ class CardBrowserViewModelTest : JvmTest() { @Test fun `notes - search for marked`() = runTest { - addNoteUsingBasicAndReversedModel("hello", "world").also { note -> + addBasicAndReverseNote("hello", "world").also { note -> NoteService.toggleMark(note) } - addNoteUsingBasicAndReversedModel("hello2", "world") + addBasicAndReverseNote("hello2", "world") runViewModelNotesTest { searchForMarkedNotes() @@ -659,10 +659,10 @@ class CardBrowserViewModelTest : JvmTest() { @Test fun `cards - search for marked`() = runTest { - addNoteUsingBasicAndReversedModel("hello", "world").also { note -> + addBasicAndReverseNote("hello", "world").also { note -> NoteService.toggleMark(note) } - addNoteUsingBasicAndReversedModel("hello2", "world") + addBasicAndReverseNote("hello2", "world") runViewModelTest { searchForMarkedNotes() @@ -674,10 +674,10 @@ class CardBrowserViewModelTest : JvmTest() { @Test fun `notes - search for suspended`() = runTest { - addNoteUsingBasicAndReversedModel("hello", "world").also { note -> + addBasicAndReverseNote("hello", "world").also { note -> col.sched.suspendCards(listOf(note.cardIds(col).first())) } - addNoteUsingBasicAndReversedModel("hello2", "world") + addBasicAndReverseNote("hello2", "world") runViewModelNotesTest { searchForSuspendedCards() @@ -689,7 +689,7 @@ class CardBrowserViewModelTest : JvmTest() { @Test fun `cards - search for suspended`() = runTest { - addNoteUsingBasicAndReversedModel("hello", "world").also { note -> + addBasicAndReverseNote("hello", "world").also { note -> col.sched.suspendCards(listOf(note.cardIds(col).first())) } @@ -762,7 +762,7 @@ class CardBrowserViewModelTest : JvmTest() { CardsOrNotes.NOTES.saveToCollection(col) for (i in 0 until notes) { // ensure 1 note = 2 cards - addNoteUsingBasicAndReversedModel() + addBasicAndReverseNote() } val viewModel = CardBrowserViewModel( @@ -785,7 +785,7 @@ class CardBrowserViewModelTest : JvmTest() { testBody: suspend CardBrowserViewModel.() -> Unit, ) = runTest { for (i in 0 until notes) { - addNoteUsingBasicModel() + addBasicNote() } notes.ifNotZero { count -> Timber.d("added %d notes", count) } val viewModel = diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/cardviewer/CardMediaPlayerTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/cardviewer/CardMediaPlayerTest.kt index 0c1c88566b7c..ff8a684f50b2 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/cardviewer/CardMediaPlayerTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/cardviewer/CardMediaPlayerTest.kt @@ -228,7 +228,7 @@ class CardMediaPlayerTest : JvmTest() { replayQuestion: Boolean?, autoplay: Boolean?, ) { - val card = addNoteUsingBasicModel().firstCard() + val card = addBasicNote().firstCard() mockkObject(card) every { card.renderOutput(any()) } answers { diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/cardviewer/CardSoundConfigTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/cardviewer/CardSoundConfigTest.kt index 30b271a27681..4468260e02cd 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/cardviewer/CardSoundConfigTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/cardviewer/CardSoundConfigTest.kt @@ -34,7 +34,7 @@ class CardSoundConfigTest : JvmTest() { fun `default values`() = runTest { // defaults as-of Anki Desktop 23.10 (51a10f09) - val note = addNoteUsingBasicModel() + val note = addBasicNote() val card = note.firstCard() createCardSoundConfig(card).run { assertThat(EXTRA_DECK_ID, deckId, equalTo(card.did)) @@ -50,7 +50,7 @@ class CardSoundConfigTest : JvmTest() { @Test fun `cards from the same note are equal`() = runTest { - val note = addNoteUsingBasicAndReversedModel() + val note = addBasicAndReverseNote() val (card1, card2) = note.cards() createCardSoundConfig(card1).run { assertThat("same note", this.appliesTo(card2)) diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/dialogs/CustomStudyDialogTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/dialogs/CustomStudyDialogTest.kt index 31237b8aa748..c9685b76a66d 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/dialogs/CustomStudyDialogTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/dialogs/CustomStudyDialogTest.kt @@ -78,7 +78,7 @@ class CustomStudyDialogTest : RobolectricTest() { runTest { val studyType = ContextMenuOption.STUDY_PREVIEW // we need a non-empty deck to custom study - addNoteUsingBasicModel() + addBasicNote() withCustomStudyFragment( args = argumentsDisplayingSubscreen(studyType), @@ -128,7 +128,7 @@ class CustomStudyDialogTest : RobolectricTest() { fun `previous value for 'increase new card limit' is suggested`() { // add cards to be sure we can extend successfully. Needs to be > 20 repeat(23) { - addNoteUsingBasicModel() + addBasicNote() } val newExtendByValue = 1 diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/previewer/PreviewerFragmentTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/previewer/PreviewerFragmentTest.kt index 74c25888003c..b32ef0214e00 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/previewer/PreviewerFragmentTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/previewer/PreviewerFragmentTest.kt @@ -31,7 +31,7 @@ import org.junit.runner.RunWith class PreviewerFragmentTest : RobolectricTest() { @Test fun `previewer - back button`() { - val note = addNoteUsingBasicAndReversedModel() + val note = addBasicAndReverseNote() val intent = PreviewerFragment.getIntent( diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/services/NoteServiceTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/services/NoteServiceTest.kt index 2b097acffc67..91e6460d1ca5 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/services/NoteServiceTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/services/NoteServiceTest.kt @@ -55,13 +55,13 @@ class NoteServiceTest : RobolectricTest() { // tests if the text fields of the notes are the same after calling updateJsonNoteFromMultimediaNote @Test fun updateJsonNoteTest() { - val testModel = col.notetypes.byName("Basic") - val multiMediaNote: IMultimediaEditableNote? = NoteService.createEmptyNote(testModel!!) + val testNoteType = col.notetypes.byName("Basic") + val multiMediaNote: IMultimediaEditableNote? = NoteService.createEmptyNote(testNoteType!!) multiMediaNote!!.getField(0)!!.text = "foo" multiMediaNote.getField(1)!!.text = "bar" val basicNote = - Note.fromNotetypeId(col, testModel.id).apply { + Note.fromNotetypeId(col, testNoteType.id).apply { setField(0, "this should be changed to foo") setField(1, "this should be changed to bar") } @@ -74,11 +74,11 @@ class NoteServiceTest : RobolectricTest() { // tests if updateJsonNoteFromMultimediaNote throws a RuntimeException if the ID's of the notes don't match @Test fun updateJsonNoteRuntimeErrorTest() { - // model with ID 42 + // note type with ID 42 var testNotetype = NotetypeJson("""{"flds": [{"name": "foo bar", "ord": "1"}], "id": "42"}""") val multiMediaNoteWithID42: IMultimediaEditableNote? = NoteService.createEmptyNote(testNotetype) - // model with ID 45 + // note type with ID 45 testNotetype = col.notetypes.newBasicNotetype() testNotetype.id = 45 col.notetypes.add(testNotetype) @@ -279,7 +279,7 @@ class NoteServiceTest : RobolectricTest() { @Test fun testAvgEase() { // basic case: no cards are new - val note = addNoteUsingModelName("Cloze", "{{c1::Hello}}{{c2::World}}{{c3::foo}}{{c4::bar}}", "extra") + val note = addNoteUsingNoteTypeName("Cloze", "{{c1::Hello}}{{c2::World}}{{c3::foo}}{{c4::bar}}", "extra") // factor for cards: 3000, 1500, 1000, 750 for ((i, card) in note.cards().withIndex()) { card.update { @@ -306,7 +306,7 @@ class NoteServiceTest : RobolectricTest() { @Test fun testAvgInterval() { // basic case: all cards are relearning or review - val note = addNoteUsingModelName("Cloze", "{{c1::Hello}}{{c2::World}}{{c3::foo}}{{c4::bar}}", "extra") + val note = addNoteUsingNoteTypeName("Cloze", "{{c1::Hello}}{{c2::World}}{{c3::foo}}{{c4::bar}}", "extra") val reviewOrRelearningList = listOf(Consts.CARD_TYPE_REV, Consts.CARD_TYPE_RELEARNING) val newOrLearningList = listOf(Consts.CARD_TYPE_NEW, Consts.CARD_TYPE_LRN) diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/services/ReminderServiceTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/services/ReminderServiceTest.kt index 71dfbb3ce0a0..593ac29fbf5b 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/services/ReminderServiceTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/services/ReminderServiceTest.kt @@ -42,7 +42,7 @@ class ReminderServiceTest : RobolectricTest() { @Test fun testReminderServiceReviewsDue() { - addNoteUsingBasicModel("test front", "test back") + addBasicNote("test front", "test back") assertThat("No notifications exist", notificationManagerShadow.size(), equalTo(0)) buildDefaultDeckReminders() assertThat("No notifications exist", notificationManagerShadow.size(), equalTo(1)) @@ -50,7 +50,7 @@ class ReminderServiceTest : RobolectricTest() { @Test fun testReminderServiceNullCollection() { - addNoteUsingBasicModel("test front", "test back") + addBasicNote("test front", "test back") enableNullCollection() assertThat("No notifications exist", notificationManagerShadow.size(), equalTo(0)) buildDefaultDeckReminders() diff --git a/AnkiDroid/src/test/java/com/ichi2/libanki/AbstractSchedTest.kt b/AnkiDroid/src/test/java/com/ichi2/libanki/AbstractSchedTest.kt index a56df1612226..ffb2f7e6f479 100644 --- a/AnkiDroid/src/test/java/com/ichi2/libanki/AbstractSchedTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/libanki/AbstractSchedTest.kt @@ -61,7 +61,7 @@ class AbstractSchedTest : JvmTest() { col.config.set("collapseTime", 20 * 60) val sched = col.sched - addNoteUsingBasicModel("foo", "bar") + addBasicNote("foo", "bar") var card = sched.card assertNotNull(card) diff --git a/AnkiDroid/src/test/java/com/ichi2/libanki/CardTest.kt b/AnkiDroid/src/test/java/com/ichi2/libanki/CardTest.kt index 3164f36eabdc..1052c87a1f5c 100644 --- a/AnkiDroid/src/test/java/com/ichi2/libanki/CardTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/libanki/CardTest.kt @@ -49,7 +49,7 @@ class CardTest : JvmTest() { } @Test - @SuppressLint("CheckResult") // col.models.current()!!.getLong("id") + @SuppressLint("CheckResult") // col.noteTypes.current()!!.getLong("id") fun test_misc_cards() { val note = col.newNote() note.setItem("Front", "1") @@ -67,19 +67,19 @@ class CardTest : JvmTest() { note.setItem("Back", "") col.addNote(note) assertEquals(1, note.numberOfCards()) - val m = col.notetypes.current() - val mm = col.notetypes + val noteType = col.notetypes.current() + val noteTypes = col.notetypes // adding a new template should automatically create cards var t = Notetypes.newTemplate("rev") t.put("qfmt", "{{Front}}1") t.put("afmt", "") - mm.addTemplateModChanged(m, t) - mm.save(m) + noteTypes.addTemplateModChanged(noteType, t) + noteTypes.save(noteType) assertEquals(2, note.numberOfCards()) // if the template is changed to remove cards, they'll be removed - t = m.getJSONArray("tmpls").getJSONObject(1) + t = noteType.getJSONArray("tmpls").getJSONObject(1) t.put("qfmt", "{{Back}}") - mm.save(m) + noteTypes.save(noteType) val rep = col.emptyCids() col.removeCardsAndOrphanedNotes(rep) assertEquals(1, note.numberOfCards()) @@ -99,7 +99,7 @@ class CardTest : JvmTest() { col.addNote(note) assertEquals(1, col.cardCount()) assertEquals(1, note.cards()[0].did) - // set the model to a new default col + // set the note type to a new default col val newId = addDeck("new") cloze.put("did", newId) col.notetypes.save(cloze) @@ -116,23 +116,23 @@ class CardTest : JvmTest() { @Test @Throws(ConfirmModSchemaException::class) fun test_gen_or() { - val models = col.notetypes - val model = models.byName("Basic") - assertNotNull(model) - models.renameFieldLegacy(model, model.flds[0], "A") - models.renameFieldLegacy(model, model.flds[1], "B") - val fld2 = models.newField("C") + val noteTypes = col.notetypes + val noteType = noteTypes.byName("Basic") + assertNotNull(noteType) + noteTypes.renameFieldLegacy(noteType, noteType.flds[0], "A") + noteTypes.renameFieldLegacy(noteType, noteType.flds[1], "B") + val fld2 = noteTypes.newField("C") fld2.setOrd(null) - models.addFieldLegacy(model, fld2) - val tmpls = model.getJSONArray("tmpls") + noteTypes.addFieldLegacy(noteType, fld2) + val tmpls = noteType.getJSONArray("tmpls") tmpls.getJSONObject(0).put("qfmt", "{{A}}{{B}}{{C}}") // ensure first card is always generated, // because at last one card is generated val tmpl = Notetypes.newTemplate("AND_OR") tmpl.put("qfmt", " {{A}} {{#B}} {{#C}} {{B}} {{/C}} {{/B}}") - models.addTemplate(model, tmpl) - models.save(model) - models.setCurrent(model) + noteTypes.addTemplate(noteType, tmpl) + noteTypes.save(noteType) + noteTypes.setCurrent(noteType) var note = col.newNote() note.setItem("A", "foo") col.addNote(note) @@ -165,24 +165,24 @@ class CardTest : JvmTest() { @Test @Throws(ConfirmModSchemaException::class) fun test_gen_not() { - val models = col.notetypes - val model = models.byName("Basic") - assertNotNull(model) - val tmpls = model.getJSONArray("tmpls") - models.renameFieldLegacy(model, model.flds[0], "First") - models.renameFieldLegacy(model, model.flds[1], "Front") - val fld2 = models.newField("AddIfEmpty") + val noteTypes = col.notetypes + val noteType = noteTypes.byName("Basic") + assertNotNull(noteType) + val tmpls = noteType.getJSONArray("tmpls") + noteTypes.renameFieldLegacy(noteType, noteType.flds[0], "First") + noteTypes.renameFieldLegacy(noteType, noteType.flds[1], "Front") + val fld2 = noteTypes.newField("AddIfEmpty") fld2.name = "AddIfEmpty" - models.addFieldLegacy(model, fld2) + noteTypes.addFieldLegacy(noteType, fld2) // ensure first card is always generated, // because at last one card is generated tmpls.getJSONObject(0).put("qfmt", "{{AddIfEmpty}}{{Front}}{{First}}") val tmpl = Notetypes.newTemplate("NOT") tmpl.put("qfmt", " {{^AddIfEmpty}} {{Front}} {{/AddIfEmpty}} ") - models.addTemplate(model, tmpl) - models.save(model) - models.setCurrent(model) + noteTypes.addTemplate(noteType, tmpl) + noteTypes.save(noteType) + noteTypes.setCurrent(noteType) var note = col.newNote() note.setItem("First", "foo") note.setItem("AddIfEmpty", "foo") diff --git a/AnkiDroid/src/test/java/com/ichi2/libanki/CollectionTest.kt b/AnkiDroid/src/test/java/com/ichi2/libanki/CollectionTest.kt index abb567c9c9d5..c7a6f445a9c1 100644 --- a/AnkiDroid/src/test/java/com/ichi2/libanki/CollectionTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/libanki/CollectionTest.kt @@ -19,7 +19,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import anki.notes.NoteFieldsCheckResponse import anki.notetypes.StockNotetype import com.ichi2.testutils.JvmTest -import com.ichi2.utils.createBasicModel +import com.ichi2.utils.createBasicNoteType import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers import org.hamcrest.Matchers.equalTo @@ -40,7 +40,7 @@ class CollectionTest : JvmTest() { fun editClozeGenerateCardsInSameDeck() { // #7781 // Technically, editing a card with conditional fields can also cause this, but cloze cards are much more common - val n = addNoteUsingModelName("Cloze", "{{c1::Hello}} {{c2::World}}", "Extra") + val n = addNoteUsingNoteTypeName("Cloze", "{{c1::Hello}} {{c2::World}}", "Extra") val did = addDeck("Testing") n.updateCards { this.did = did } assertThat("two cloze notes should be generated", n.numberOfCards(), equalTo(2)) @@ -110,13 +110,13 @@ class CollectionTest : JvmTest() { var n = col.addNote(note) assertEquals(1, n) // test multiple cards - add another template - val m = col.notetypes.current() - val mm = col.notetypes + val noteType = col.notetypes.current() + val noteTypes = col.notetypes val t = Notetypes.newTemplate("Reverse") t.put("qfmt", "{{Back}}") t.put("afmt", "{{Front}}") - mm.addTemplateModChanged(m, t) - mm.save(m) + noteTypes.addTemplateModChanged(noteType, t) + noteTypes.save(noteType) assertEquals(2, col.cardCount()) // creating new notes should use both cards note = col.newNote() @@ -180,22 +180,22 @@ class CollectionTest : JvmTest() { // old code used StdModels.STD_MODELS.size for this variable. There were 6 models: // BASIC_MODEL, BASIC_TYPING_MODEL, FORWARD_REVERSE_MODEL, FORWARD_OPTIONAL_REVERSE_MODEL, // CLOZE_MODEL, IMAGE_OCCLUSION_MODEL - val numberOfStandardModels = StockNotetype.Kind.entries.count { it != StockNotetype.Kind.UNRECOGNIZED } - assertEquals(col.notetypes.all().size, numberOfStandardModels) + val numberOfStandardNoteTypes = StockNotetype.Kind.entries.count { it != StockNotetype.Kind.UNRECOGNIZED } + assertEquals(col.notetypes.all().size, numberOfStandardNoteTypes) for (i in 0..99) { - col.createBasicModel() + col.createBasicNoteType() } - assertEquals(col.notetypes.all().size, (100 + numberOfStandardModels)) + assertEquals(col.notetypes.all().size, (100 + numberOfStandardNoteTypes)) } @Test @Ignore("Pending port of media search from Rust code") fun test_furigana() { - val mm = col.notetypes - val m = mm.current() + val noteTypes = col.notetypes + val noteType = noteTypes.current() // filter should work - m.getJSONArray("tmpls").getJSONObject(0).put("qfmt", "{{kana:Front}}") - mm.save(m) + noteType.getJSONArray("tmpls").getJSONObject(0).put("qfmt", "{{kana:Front}}") + noteTypes.save(noteType) val n = col.newNote() n.setItem("Front", "foo[abc]") col.addNote(n) @@ -207,14 +207,14 @@ class CollectionTest : JvmTest() { val question = c.question(true) assertThat("Question «$question» does not contains «anki:play».", question, Matchers.containsString("anki:play")) // it shouldn't throw an error while people are editing - m.getJSONArray("tmpls").getJSONObject(0).put("qfmt", "{{kana:}}") - mm.save(m) + noteType.getJSONArray("tmpls").getJSONObject(0).put("qfmt", "{{kana:}}") + noteTypes.save(noteType) c.question(true) } @Test fun test_filterToValidCards() { - val cid = addNoteUsingBasicModel("foo", "bar").firstCard().id + val cid = addBasicNote("foo", "bar").firstCard().id assertEquals(ArrayList(setOf(cid)), col.filterToValidCards(longArrayOf(cid, cid + 1))) } diff --git a/AnkiDroid/src/test/java/com/ichi2/libanki/FinderTest.kt b/AnkiDroid/src/test/java/com/ichi2/libanki/FinderTest.kt index fc7e4c47adc0..c94f70907996 100644 --- a/AnkiDroid/src/test/java/com/ichi2/libanki/FinderTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/libanki/FinderTest.kt @@ -49,7 +49,7 @@ class FinderTest : JvmTest() { fun searchForBuriedReturnsManuallyAndSiblingBuried() { val searchQuery = "is:buried" enableBurySiblings() - super.addNoteUsingModelName("Basic (and reversed card)", "Front", "Back") + super.addNoteUsingNoteTypeName("Basic (and reversed card)", "Front", "Back") val toAnswer: Card = col.sched.card!! // act @@ -135,14 +135,14 @@ class FinderTest : JvmTest() { note.setItem("Back", "sheep") col.addNote(note) val catCard = note.cards()[0] - var m = col.notetypes.current() - m = col.notetypes.copy(m) - val mm = col.notetypes + var noteType = col.notetypes.current() + noteType = col.notetypes.copy(noteType) + val noteTypes = col.notetypes val t = Notetypes.newTemplate("Reverse") t.put("qfmt", "{{Back}}") t.put("afmt", "{{Front}}") - mm.addTemplateModChanged(m, t) - mm.save(m) + noteTypes.addTemplateModChanged(noteType, t) + noteTypes.save(noteType) note = col.newNote() note.setItem("Front", "test") note.setItem("Back", "foo bar") @@ -273,7 +273,7 @@ class FinderTest : JvmTest() { col.findCards("", BuiltinSortKind.CARD_DUE, reverse=true).get(0)); */ - // model + // note type assertEquals(3, col.findCards("note:basic").size) assertEquals(2, col.findCards("-note:basic").size) assertEquals(5, col.findCards("-note:foo").size) diff --git a/AnkiDroid/src/test/java/com/ichi2/libanki/MathJaxClozeTest.kt b/AnkiDroid/src/test/java/com/ichi2/libanki/MathJaxClozeTest.kt index 7a619a30ca18..284e3806005b 100644 --- a/AnkiDroid/src/test/java/com/ichi2/libanki/MathJaxClozeTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/libanki/MathJaxClozeTest.kt @@ -19,7 +19,7 @@ class MathJaxClozeTest : JvmTest() { @Test fun verifyMathJaxClozeCards() { val note = - addCloseNote("{{c1::ok}} \\(2^2\\) {{c2::not ok}} \\(2^{{c3::2}}\\) \\(x^3\\) {{c4::blah}} {{c5::text with \\(x^2\\) jax}}") + addClozeNote("{{c1::ok}} \\(2^2\\) {{c2::not ok}} \\(2^{{c3::2}}\\) \\(x^3\\) {{c4::blah}} {{c5::text with \\(x^2\\) jax}}") assertEquals(5, note.numberOfCards()) val cards = note.cards() diff --git a/AnkiDroid/src/test/java/com/ichi2/libanki/ModelTest.kt b/AnkiDroid/src/test/java/com/ichi2/libanki/NoteTypeTest.kt similarity index 79% rename from AnkiDroid/src/test/java/com/ichi2/libanki/ModelTest.kt rename to AnkiDroid/src/test/java/com/ichi2/libanki/NoteTypeTest.kt index 1a79d5b381c9..b00d303fcbe2 100644 --- a/AnkiDroid/src/test/java/com/ichi2/libanki/ModelTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/libanki/NoteTypeTest.kt @@ -16,7 +16,7 @@ package com.ichi2.libanki import androidx.test.ext.junit.runners.AndroidJUnit4 -import com.ichi2.libanki.Consts.MODEL_CLOZE +import com.ichi2.libanki.Consts.NOTE_TYPE_CLOZE import com.ichi2.libanki.Utils.stripHTML import com.ichi2.libanki.exception.ConfirmModSchemaException import com.ichi2.testutils.JvmTest @@ -40,9 +40,9 @@ class NotetypeTest : JvmTest() { @Test fun test_frontSide_field() { // #8951 - Anki Special-cases {{FrontSide}} on the front to return empty string - val m = col.notetypes.current() - m.getJSONArray("tmpls").getJSONObject(0).put("qfmt", "{{Front}}{{FrontSide}}") - col.notetypes.save(m) + val noteType = col.notetypes.current() + noteType.getJSONArray("tmpls").getJSONObject(0).put("qfmt", "{{Front}}{{FrontSide}}") + col.notetypes.save(noteType) val note = col.newNote() note.setItem("Front", "helloworld") col.addNote(note) @@ -63,13 +63,13 @@ class NotetypeTest : JvmTest() { @Test fun test_field_named_frontSide() { // #8951 - A field named "FrontSide" is ignored - this matches Anki 2.1.34 (8af8f565) - val m = col.notetypes.current() + val noteType = col.notetypes.current() // Add a field called FrontSide and FrontSide2 (to ensure that fields are added correctly) - col.notetypes.addFieldModChanged(m, col.notetypes.newField("FrontSide")) - col.notetypes.addFieldModChanged(m, col.notetypes.newField("FrontSide2")) - m.getJSONArray("tmpls").getJSONObject(0).put("qfmt", "{{Front}}{{FrontSide}}{{FrontSide2}}") - col.notetypes.save(m) + col.notetypes.addFieldModChanged(noteType, col.notetypes.newField("FrontSide")) + col.notetypes.addFieldModChanged(noteType, col.notetypes.newField("FrontSide2")) + noteType.getJSONArray("tmpls").getJSONObject(0).put("qfmt", "{{Front}}{{FrontSide}}{{FrontSide2}}") + col.notetypes.save(noteType) val note = col.newNote() note.setItem("Front", "helloworld") @@ -86,11 +86,11 @@ class NotetypeTest : JvmTest() { } /***************** - * Models * + * Note Types * */ @Test @Throws(ConfirmModSchemaException::class) - fun test_modelDelete() { + fun test_noteTypeDelete() { val note = col.newNote() note.setItem("Front", "1") note.setItem("Back", "2") @@ -121,68 +121,68 @@ class NotetypeTest : JvmTest() { note.setItem("Front", "1") note.setItem("Back", "2") col.addNote(note) - val m = col.notetypes.current() + val noteType = col.notetypes.current() // make sure renaming a field updates the templates - col.notetypes.renameFieldLegacy(m, m.flds[0], "NewFront") + col.notetypes.renameFieldLegacy(noteType, noteType.flds[0], "NewFront") assertThat( - m.getJSONArray("tmpls").getJSONObject(0).getString("qfmt"), + noteType.getJSONArray("tmpls").getJSONObject(0).getString("qfmt"), containsString("{{NewFront}}"), ) - val h = col.notetypes.scmhash(m) + val h = col.notetypes.scmhash(noteType) // add a field var field: Field? = col.notetypes.newField("foo") - col.notetypes.addFieldLegacy(m, field!!) + col.notetypes.addFieldLegacy(noteType, field!!) assertEquals( listOf("1", "2", ""), col .getNote( col.notetypes.nids( - m, + noteType, )[0], ).fields, ) - assertNotEquals(h, col.notetypes.scmhash(m)) + assertNotEquals(h, col.notetypes.scmhash(noteType)) // rename it - field = m.flds[2] - col.notetypes.renameFieldLegacy(m, field, "bar") - assertEquals("", col.getNote(col.notetypes.nids(m)[0]).getItem("bar")) + field = noteType.flds[2] + col.notetypes.renameFieldLegacy(noteType, field, "bar") + assertEquals("", col.getNote(col.notetypes.nids(noteType)[0]).getItem("bar")) // delete back - col.notetypes.remFieldLegacy(m, m.flds[1]) + col.notetypes.remFieldLegacy(noteType, noteType.flds[1]) assertEquals( listOf("1", ""), col .getNote( col.notetypes.nids( - m, + noteType, )[0], ).fields, ) // move 0 -> 1 - col.notetypes.moveFieldLegacy(m, m.flds[0], 1) + col.notetypes.moveFieldLegacy(noteType, noteType.flds[0], 1) assertEquals( listOf("", "1"), col .getNote( col.notetypes.nids( - m, + noteType, )[0], ).fields, ) // move 1 -> 0 - col.notetypes.moveFieldLegacy(m, m.flds[1], 0) + col.notetypes.moveFieldLegacy(noteType, noteType.flds[1], 0) assertEquals( listOf("1", ""), col .getNote( col.notetypes.nids( - m, + noteType, )[0], ).fields, ) // add another and put in middle field = col.notetypes.newField("baz") - col.notetypes.addFieldLegacy(m, field) - note = col.getNote(col.notetypes.nids(m)[0]) + col.notetypes.addFieldLegacy(noteType, field) + note = col.getNote(col.notetypes.nids(noteType)[0]) note.setItem("baz", "2") note.flush() assertEquals( @@ -190,40 +190,40 @@ class NotetypeTest : JvmTest() { col .getNote( col.notetypes.nids( - m, + noteType, )[0], ).fields, ) // move 2 -> 1 - col.notetypes.moveFieldLegacy(m, m.flds[2], 1) + col.notetypes.moveFieldLegacy(noteType, noteType.flds[2], 1) assertEquals( listOf("1", "2", ""), col .getNote( col.notetypes.nids( - m, + noteType, )[0], ).fields, ) // move 0 -> 2 - col.notetypes.moveFieldLegacy(m, m.flds[0], 2) + col.notetypes.moveFieldLegacy(noteType, noteType.flds[0], 2) assertEquals( listOf("2", "", "1"), col .getNote( col.notetypes.nids( - m, + noteType, )[0], ).fields, ) // move 0 -> 1 - col.notetypes.moveFieldLegacy(m, m.flds[0], 1) + col.notetypes.moveFieldLegacy(noteType, noteType.flds[0], 1) assertEquals( listOf("", "2", "1"), col .getNote( col.notetypes.nids( - m, + noteType, )[0], ).fields, ) @@ -232,13 +232,13 @@ class NotetypeTest : JvmTest() { @Test @Throws(ConfirmModSchemaException::class) fun test_templates() { - val m = col.notetypes.current() - val mm = col.notetypes + val noteType = col.notetypes.current() + val noteTypes = col.notetypes var t = Notetypes.newTemplate("Reverse") t.put("qfmt", "{{Back}}") t.put("afmt", "{{Front}}") - mm.addTemplateModChanged(m, t) - mm.save(m) + noteTypes.addTemplateModChanged(noteType, t) + noteTypes.save(noteType) val note = col.newNote() note.setItem("Front", "1") note.setItem("Back", "2") @@ -252,13 +252,13 @@ class NotetypeTest : JvmTest() { assertEquals(0, c.ord) assertEquals(1, c2.ord) // switch templates - col.notetypes.moveTemplate(m, c.template(), 1) + col.notetypes.moveTemplate(noteType, c.template(), 1) c.load() c2.load() assertEquals(1, c.ord) assertEquals(0, c2.ord) // removing a template should delete its cards - col.notetypes.remTemplate(m, m.getJSONArray("tmpls").getJSONObject(0)) + col.notetypes.remTemplate(noteType, noteType.getJSONArray("tmpls").getJSONObject(0)) assertEquals(1, col.cardCount()) // and should have updated the other cards' ordinals c = note.cards()[0] @@ -267,8 +267,8 @@ class NotetypeTest : JvmTest() { // it shouldn't be possible to orphan notes by removing templates t = Notetypes.newTemplate("template name") t.put("qfmt", "{{Front}}1") - mm.addTemplateModChanged(m, t) - col.notetypes.remTemplate(m, m.getJSONArray("tmpls").getJSONObject(0)) + noteTypes.addTemplateModChanged(noteType, t) + col.notetypes.remTemplate(noteType, noteType.getJSONArray("tmpls").getJSONObject(0)) assertEquals( 0, col.db.queryLongScalar( @@ -281,16 +281,16 @@ class NotetypeTest : JvmTest() { @Throws(ConfirmModSchemaException::class) fun test_cloze_ordinals() { col.notetypes.setCurrent(col.notetypes.byName("Cloze")!!) - val m = col.notetypes.current() - val mm = col.notetypes + val noteType = col.notetypes.current() + val noteTypes = col.notetypes // We replace the default Cloze template val t = Notetypes.newTemplate("ChainedCloze") t.put("qfmt", "{{text:cloze:Text}}") t.put("afmt", "{{text:cloze:Text}}") - mm.addTemplateModChanged(m, t) - mm.save(m) - col.notetypes.remTemplate(m, m.getJSONArray("tmpls").getJSONObject(0)) + noteTypes.addTemplateModChanged(noteType, t) + noteTypes.save(noteType) + col.notetypes.remTemplate(noteType, noteType.getJSONArray("tmpls").getJSONObject(0)) val note = col.newNote() note.setItem("Text", "{{c1::firstQ::firstA}}{{c2::secondQ::secondA}}") @@ -307,9 +307,9 @@ class NotetypeTest : JvmTest() { @Test fun test_text() { - val m = col.notetypes.current() - m.getJSONArray("tmpls").getJSONObject(0).put("qfmt", "{{text:Front}}") - col.notetypes.save(m) + val noteType = col.notetypes.current() + noteType.getJSONArray("tmpls").getJSONObject(0).put("qfmt", "{{text:Front}}") + col.notetypes.save(noteType) val note = col.newNote() note.setItem("Front", "helloworld") col.addNote(note) @@ -325,7 +325,7 @@ class NotetypeTest : JvmTest() { col.notetypes.setCurrent(col.notetypes.byName("Cloze")!!) var note = col.newNote() assertEquals("Cloze", note.notetype.getString("name")) - // a cloze model with no clozes is not empty + // a cloze note type with no clozes is not empty note.setItem("Text", "nothing") assertEquals(1, col.addNote(note)) clearId(note) @@ -369,10 +369,10 @@ class NotetypeTest : JvmTest() { @Test fun test_type_and_cloze() { - val m = col.notetypes.byName("Cloze") - col.notetypes.setCurrent(m!!) - m.getJSONArray("tmpls").getJSONObject(0).put("qfmt", "{{cloze:Text}}{{type:cloze:Text}}") - col.notetypes.save(m) + val noteType = col.notetypes.byName("Cloze") + col.notetypes.setCurrent(noteType!!) + noteType.getJSONArray("tmpls").getJSONObject(0).put("qfmt", "{{cloze:Text}}{{type:cloze:Text}}") + col.notetypes.save(noteType) val note = col.newNote() note.setItem("Text", "hello {{c1::world}}") col.addNote(note) @@ -387,16 +387,16 @@ class NotetypeTest : JvmTest() { @Suppress("SpellCheckingInspection") // chaine fun test_chained_mods() { col.notetypes.setCurrent(col.notetypes.byName("Cloze")!!) - val m = col.notetypes.current() - val mm = col.notetypes + val noteType = col.notetypes.current() + val noteTypes = col.notetypes // We replace the default Cloze template val t = Notetypes.newTemplate("ChainedCloze") t.put("qfmt", "{{cloze:text:Text}}") t.put("afmt", "{{cloze:text:Text}}") - mm.addTemplateModChanged(m, t) - mm.save(m) - col.notetypes.remTemplate(m, m.getJSONArray("tmpls").getJSONObject(0)) + noteTypes.addTemplateModChanged(noteType, t) + noteTypes.save(noteType) + col.notetypes.remTemplate(noteType, noteType.getJSONArray("tmpls").getJSONObject(0)) val note = col.newNote() val q1 = "phrase" val a1 = "sentence" @@ -416,16 +416,16 @@ class NotetypeTest : JvmTest() { @Test @Throws(ConfirmModSchemaException::class) - fun test_modelChange() { + fun test_noteTypeChange() { val cloze = col.notetypes.byName("Cloze") // enable second template and add a note val basic = col.notetypes.current() - val mm = col.notetypes + val noteTypes = col.notetypes val t = Notetypes.newTemplate("Reverse") t.put("qfmt", "{{Back}}") t.put("afmt", "{{Front}}") - mm.addTemplateModChanged(basic, t) - mm.save(basic) + noteTypes.addTemplateModChanged(basic, t) + noteTypes.save(basic) var note = col.newNote() note.setItem("Front", "note") note.setItem("Back", "b123") @@ -473,12 +473,12 @@ class NotetypeTest : JvmTest() { note.load() assertEquals("", note.getItem("Front")) assertEquals("note", note.getItem("Back")) - // another note to try model conversion + // another note to try note type conversion note = col.newNote() note.setItem("Front", "f2") note.setItem("Back", "b2") col.addNote(note) - // counts = col.getModels().all_use_counts(); + // counts = col.getNoteTypes().all_use_counts(); // Using older version of the test assertEquals(2, col.notetypes.useCount(basic)) assertEquals(0, col.notetypes.useCount(cloze!!)) @@ -506,7 +506,7 @@ class NotetypeTest : JvmTest() { } private fun reqSize(notetype: NotetypeJson?) { - if (notetype!!.getInt("type") == MODEL_CLOZE) { + if (notetype!!.getInt("type") == NOTE_TYPE_CLOZE) { return } assertEquals( @@ -517,8 +517,8 @@ class NotetypeTest : JvmTest() { @Test fun nonEmptyFieldTest() { - val mm = col.notetypes - val basic = mm.byName("Basic") + val noteTypes = col.notetypes + val basic = noteTypes.byName("Basic") val s: MutableSet = HashSet() assertEquals(s, basic!!.nonEmptyFields(arrayOf("", ""))) s.add("Front") @@ -532,24 +532,24 @@ class NotetypeTest : JvmTest() { } /** - * tests if Model.getDid() returns model did + * tests if NoteType.getDid() returns note type did * or default deck id (1) if null */ @Test fun getDid_test() { - val mm = col.notetypes - val basic = mm.byName("Basic") + val noteTypes = col.notetypes + val basic = noteTypes.byName("Basic") basic!!.put("did", 999L) val expected = 999L - assertEquals("getDid() should return the model did", expected, basic.did) + assertEquals("getDid() should return the note type did", expected, basic.did) // Check if returns default deck id (1) when did is null basic.put("did", null as Int?) val expected2 = 1L assertEquals( - "getDid() should return 1 (default deck id) if model did is null", + "getDid() should return 1 (default deck id) if note type did is null", expected2, basic.did, ) diff --git a/AnkiDroid/src/test/java/com/ichi2/libanki/SchedulerTest.kt b/AnkiDroid/src/test/java/com/ichi2/libanki/SchedulerTest.kt index 84602e6d0a25..f3758250d159 100644 --- a/AnkiDroid/src/test/java/com/ichi2/libanki/SchedulerTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/libanki/SchedulerTest.kt @@ -62,7 +62,7 @@ open class SchedulerTest : JvmTest() { @Throws(ConfirmModSchemaException::class) fun handlesSmallSteps() { // a delay of 0 crashed the app (step of 0.01). - addNoteUsingBasicModel("Hello", "World") + addBasicNote("Hello", "World") col.decks .allConfig()[0] .getJSONObject("new") @@ -103,12 +103,12 @@ open class SchedulerTest : JvmTest() { // disabled for now, as the learn fudging makes this randomly fail // // the default order should ensure siblings are not seen together, and // // should show all cards - // Model m = col.getModels().current(); Models mm = col.getModels() - // JSONObject t = mm.newTemplate("Reverse") + // NoteType noteType = col.getNoteTypes().current(); NoteTypes noteTypes = col.getNoteTypes() + // JSONObject t = noteTypes.newTemplate("Reverse") // t['qfmt'] = "{{Back}}" // t['afmt'] = "{{Front}}" - // mm.addTemplateModChanged(m, t) - // mm.save(m) + // noteTypes.addTemplateModChanged(noteType, t) + // noteTypes.save(noteType) // note = col.newNote() // note['Front'] = u"2"; note['Back'] = u"2" // col.addNote(note) @@ -897,17 +897,17 @@ open class SchedulerTest : JvmTest() { @Throws(Exception::class) fun test_ordcycleV2() { // add two more templates and set second active - val m = col.notetypes.current() - val mm = col.notetypes + val noteType = col.notetypes.current() + val noteTypes = col.notetypes var t = Notetypes.newTemplate("Reverse") t.put("qfmt", "{{Back}}") t.put("afmt", "{{Front}}") - mm.addTemplateModChanged(m, t) + noteTypes.addTemplateModChanged(noteType, t) t = Notetypes.newTemplate("f2") t.put("qfmt", "{{Front}}1") t.put("afmt", "{{Back}}") - mm.addTemplateModChanged(m, t) - mm.save(m) + noteTypes.addTemplateModChanged(noteType, t) + noteTypes.save(noteType) // create a new note; it should have 3 cards val note = col.newNote() note.setItem("Front", "1") @@ -1338,7 +1338,7 @@ open class SchedulerTest : JvmTest() { // "https://github.com/ankidroid/Anki-Android/issues/7285" val decks = col.decks val sched = col.sched - addNoteUsingBasicModel("foo", "bar") + addBasicNote("foo", "bar") val did = addDynamicDeck("test") val deck = decks.get(did)!! deck.put("resched", false) diff --git a/AnkiDroid/src/test/java/com/ichi2/libanki/StorageRustTest.kt b/AnkiDroid/src/test/java/com/ichi2/libanki/StorageRustTest.kt index 781e2630e7cc..adb24305c435 100644 --- a/AnkiDroid/src/test/java/com/ichi2/libanki/StorageRustTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/libanki/StorageRustTest.kt @@ -28,10 +28,10 @@ import org.robolectric.annotation.Config class StorageRustTest : JvmTest() { @Test @Config(qualifiers = "en") - fun testModelCount() { - val modelNames = col.notetypes.all().map { x -> x.getString("name") } + fun testNoteTypeCount() { + val noteTypeNames = col.notetypes.all().map { x -> x.getString("name") } MatcherAssert.assertThat( - modelNames, + noteTypeNames, Matchers.containsInAnyOrder( "Basic", "Basic (and reversed card)", diff --git a/AnkiDroid/src/test/java/com/ichi2/testutils/ActivityList.kt b/AnkiDroid/src/test/java/com/ichi2/testutils/ActivityList.kt index 710522c07a70..f8b894eeecd0 100644 --- a/AnkiDroid/src/test/java/com/ichi2/testutils/ActivityList.kt +++ b/AnkiDroid/src/test/java/com/ichi2/testutils/ActivityList.kt @@ -32,8 +32,8 @@ import com.ichi2.anki.IntentHandler import com.ichi2.anki.IntentHandler2 import com.ichi2.anki.IntroductionActivity import com.ichi2.anki.LoginActivity -import com.ichi2.anki.ModelFieldEditor import com.ichi2.anki.MyAccount +import com.ichi2.anki.NoteTypeFieldEditor import com.ichi2.anki.Reviewer import com.ichi2.anki.SharedDecksActivity import com.ichi2.anki.SingleFragmentActivity @@ -70,7 +70,7 @@ object ActivityList { get(IntentHandler2::class.java), get(StudyOptionsActivity::class.java), get(CardBrowser::class.java), - get(ModelFieldEditor::class.java), + get(NoteTypeFieldEditor::class.java), // Likely has unhandled intents get(Reviewer::class.java), get(MyAccount::class.java), @@ -103,7 +103,7 @@ object ActivityList { } } - private fun intentForCardTemplateEditor(): Intent = Intent().apply { putExtra("modelId", 1L) } + private fun intentForCardTemplateEditor(): Intent = Intent().apply { putExtra("noteTypeId", 1L) } class ActivityLaunchParam( var activity: Class, diff --git a/AnkiDroid/src/test/java/com/ichi2/testutils/TestClass.kt b/AnkiDroid/src/test/java/com/ichi2/testutils/TestClass.kt index 47de992fedf5..45aecd80f705 100644 --- a/AnkiDroid/src/test/java/com/ichi2/testutils/TestClass.kt +++ b/AnkiDroid/src/test/java/com/ichi2/testutils/TestClass.kt @@ -47,16 +47,16 @@ import kotlin.time.Duration.Companion.milliseconds interface TestClass { val col: Collection - fun addNoteUsingBasicModel( + fun addBasicNote( front: String = "Front", back: String = "Back", - ): Note = addNoteUsingModelName("Basic", front, back) + ): Note = addNoteUsingNoteTypeName("Basic", front, back) - fun addRevNoteUsingBasicModelDueToday( + fun addRevNoteUsingBasicNoteTypeDueToday( @Suppress("SameParameterValue") front: String, @Suppress("SameParameterValue") back: String, ): Note { - val note = addNoteUsingBasicModel(front, back) + val note = addBasicNote(front, back) val card = note.firstCard() card.queue = Consts.QUEUE_TYPE_REV card.type = Consts.CARD_TYPE_REV @@ -64,17 +64,17 @@ interface TestClass { return note } - fun addNoteUsingBasicAndReversedModel( + fun addBasicAndReverseNote( front: String = "Front", back: String = "Back", - ): Note = addNoteUsingModelName("Basic (and reversed card)", front, back) + ): Note = addNoteUsingNoteTypeName("Basic (and reversed card)", front, back) - fun addNoteUsingBasicTypedModel( + fun addBasicTypedNote( @Suppress("SameParameterValue") front: String, @Suppress("SameParameterValue") back: String, - ): Note = addNoteUsingModelName("Basic (type in the answer)", front, back) + ): Note = addNoteUsingNoteTypeName("Basic (type in the answer)", front, back) - fun addCloseNote( + fun addClozeNote( text: String, extra: String = "Extra", ): Note = @@ -83,16 +83,16 @@ interface TestClass { col.addNote(this) } - fun addNoteUsingModelName( + fun addNoteUsingNoteTypeName( name: String?, vararg fields: String, ): Note { - val model = + val noteType = col.notetypes.byName((name)!!) - ?: throw IllegalArgumentException("Could not find model '$name'") + ?: throw IllegalArgumentException("Could not find note type '$name'") // PERF: if we modify newNote(), we can return the card and return a Pair here. // Saves a database trip afterwards. - val n = col.newNote(model) + val n = col.newNote(noteType) for ((i, field) in fields.withIndex()) { n.setField(i, field) } @@ -100,21 +100,21 @@ interface TestClass { return n } - fun addNonClozeModel( + fun addNonClozeNoteType( name: String, fields: Array, qfmt: String?, afmt: String?, ): String { - val model = col.notetypes.new(name) + val noteType = col.notetypes.new(name) for (field in fields) { - col.notetypes.addFieldInNewModel(model, col.notetypes.newField(field)) + col.notetypes.addFieldInNewNoteType(noteType, col.notetypes.newField(field)) } val t = Notetypes.newTemplate("Card 1") t.put("qfmt", qfmt) t.put("afmt", afmt) - col.notetypes.addTemplateInNewModel(model, t) - col.notetypes.add(model) + col.notetypes.addTemplateInNewNoteType(noteType, t) + col.notetypes.add(noteType) return name } @@ -123,17 +123,17 @@ interface TestClass { front: String, back: String, ) { - addNonClozeModel("TTS", arrayOf("Front", "Back"), "{{Front}}{{tts en_GB:Front}}", "{{tts en_GB:Front}}
{{Back}}") - addNoteUsingModelName("TTS", front, back) + addNonClozeNoteType("TTS", arrayOf("Front", "Back"), "{{Front}}{{tts en_GB:Front}}", "{{tts en_GB:Front}}
{{Back}}") + addNoteUsingNoteTypeName("TTS", front, back) } fun addField( notetype: NotetypeJson, name: String, ) { - val models = col.notetypes + val noteTypes = col.notetypes try { - models.addFieldLegacy(notetype, models.newField(name)) + noteTypes.addFieldLegacy(notetype, noteTypes.newField(name)) } catch (e: ConfirmModSchemaException) { throw RuntimeException(e) } @@ -184,7 +184,7 @@ interface TestClass { } /** Adds [count] notes in the same deck with the same front & back */ - fun addNotes(count: Int): List = (0..count).map { addNoteUsingBasicModel() } + fun addNotes(count: Int): List = (0..count).map { addBasicNote() } fun Note.moveToDeck( deckName: String, diff --git a/AnkiDroid/src/test/java/com/ichi2/utils/NoteTypeTest.kt b/AnkiDroid/src/test/java/com/ichi2/utils/NoteTypeTest.kt index dfe5606a97ce..1d2e9f0cdbbd 100644 --- a/AnkiDroid/src/test/java/com/ichi2/utils/NoteTypeTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/utils/NoteTypeTest.kt @@ -91,37 +91,37 @@ class NoteTypeTest { } } -const val BASIC_MODEL_NAME = "Basic" +const val BASIC_NOTE_TYPE_NAME = "Basic" /** - * Creates a basic model. + * Creates a basic note type. * - * Note: changes to this model will propagate to [createBasicTypingModel] as that model is built on - * top of the model returned by this function. + * Note: changes to this note type will propagate to [createBasicTypingNoteType] as that note type is built on + * top of the note type returned by this function. * - * @param name name of the new model - * @return the new model + * @param name name of the new note type + * @return the new note type */ -fun Collection.createBasicModel(name: String = BASIC_MODEL_NAME): NotetypeJson { - val m = +fun Collection.createBasicNoteType(name: String = BASIC_NOTE_TYPE_NAME): NotetypeJson { + val noteType = BackendUtils .fromJsonBytes( getStockNotetypeLegacy(StockNotetype.Kind.KIND_BASIC), ).apply { set("name", name) } - addNotetypeLegacy(BackendUtils.toJsonBytes(m)) + addNotetypeLegacy(BackendUtils.toJsonBytes(noteType)) return notetypes.byName(name)!! } /** - * Creates a basic typing model. + * Creates a basic typing note type. * - * @see createBasicModel + * @see createBasicNoteType */ -fun Collection.createBasicTypingModel(name: String): NotetypeJson { - val m = createBasicModel(name) - val t = m.getJSONArray("tmpls").getJSONObject(0) +fun Collection.createBasicTypingNoteType(name: String): NotetypeJson { + val noteType = createBasicNoteType(name) + val t = noteType.getJSONArray("tmpls").getJSONObject(0) t.put("qfmt", "{{Front}}\n\n{{type:Back}}") t.put("afmt", "{{Front}}\n\n
\n\n{{type:Back}}") - notetypes.save(m) - return m + notetypes.save(noteType) + return noteType } diff --git a/api/src/main/java/com/ichi2/anki/FlashCardsContract.kt b/api/src/main/java/com/ichi2/anki/FlashCardsContract.kt index 4c4421d5ad33..ef111d81069c 100644 --- a/api/src/main/java/com/ichi2/anki/FlashCardsContract.kt +++ b/api/src/main/java/com/ichi2/anki/FlashCardsContract.kt @@ -55,7 +55,7 @@ import com.ichi2.anki.api.Ease * * A row from the [Card] sub-provider gives access to notes cards. The * cards are accessed as described in the [Card] description. * - * * The format of notes and cards is described in models. The models are accessed as described + * * The format of notes and cards is described in note types. The note types are accessed as described * in the [Model] description. * * @@ -78,10 +78,10 @@ import com.ichi2.anki.api.Ease * notes//cards/ | NoteCard `ord` (with ord = 0... num_cards-1) belonging to note `note_id` as high level data (Deck name, question, answer). * | Supports update(), query(). For code examples see class description of [Card]. * -------------------------------------------------------------------------------------------------------------------- - * models | All models as JSONObjects. + * models | All note types as JSONObjects. * | Supports query(). For code examples see class description of [Model]. * -------------------------------------------------------------------------------------------------------------------- - * model/ | Direct access to model `model_id` as JSONObject. + * model/ | Direct access to note type `model_id` as JSONObject. * | Supports query(). For code examples see class description of [Model]. * -------------------------------------------------------------------------------------------------------------------- * ``` @@ -103,7 +103,7 @@ public object FlashCardsContract { * all the notes that match the query as defined in `selection` argument in the * `query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)` call. * For queries, the `selectionArgs` parameter can contain an optional selection statement for the notes table - * in the sql database. E.g. "mid = 12345678" could be used to limit to a particular model ID. + * in the sql database. E.g. "mid = 12345678" could be used to limit to a particular note type ID. * The `selection` parameter is an optional search string for the Anki browser. The syntax is described * [in the search section of the Anki manual](https://docs.ankiweb.net/searching.html). * @@ -134,11 +134,11 @@ public object FlashCardsContract { * * * In order to insert a new note (the cards for this note will be added to the default deck) - * the [.CONTENT_URI] must be used together with a model (see [Model]) + * the [.CONTENT_URI] must be used together with a note type (see [Model]) * ID, e.g. * * ``` - * Long mId = ... // Use the correct model ID + * Long mId = ... // Use the correct note type ID * ContentValues values = new ContentValues(); * values.put(FlashCardsContract.Note.MID, mId); * Uri newNoteUri = cr.insert(FlashCardsContract.Note.CONTENT_URI, values); @@ -168,8 +168,8 @@ public object FlashCardsContract { * -------------------------------------------------------------------------------------------------------------------- * long | GUID | read-only | See more at https://github.com/ankidroid/Anki-Android/wiki/Database-Structure * -------------------------------------------------------------------------------------------------------------------- - * long | MID | read-only | This is the ID of the model that is used for rendering the cards. This ID can be used for - * | | | accessing the data of the model using the URI + * long | MID | read-only | This is the ID of the note type that is used for rendering the cards. This ID can be used for + * | | | accessing the data of the note type using the URI * | | | "content://com.ichi2.anki.flashcards/model/ * -------------------------------------------------------------------------------------------------------------------- * long | MOD | read-only | See more at https://github.com/ankidroid/Anki-Android/wiki/Database-Structure @@ -232,6 +232,8 @@ public object FlashCardsContract { // field is part of the default projection available to the clients @Suppress("MemberVisibilityCanBePrivate") public const val GUID: String = "guid" + + // "mid" used to mean "note type id". "note type" used to be the name "note type". It can't be changed for compatibility reason. public const val MID: String = "mid" @Suppress("unused") @@ -284,15 +286,16 @@ public object FlashCardsContract { } /** - * A model describes what cards look like. + * "Model" was the previous named of "note type". It is used here for the sake of compatibility with the ecosystem. + * A note type describes what cards look like. * * ``` - * Card model description + * Note Type description * Type | Name | Access | Description * -------------------------------------------------------------------------------------------------------------------- - * long | _ID | read-only | Model ID. + * long | _ID | read-only | Note type ID. * -------------------------------------------------------------------------------------------------------------------- - * String | NAME | | Name of the model. + * String | NAME | | Name of the Note type. * -------------------------------------------------------------------------------------------------------------------- * String | CSS | | CSS styling code which is shared across all the templates * -------------------------------------------------------------------------------------------------------------------- @@ -304,7 +307,7 @@ public object FlashCardsContract { * -------------------------------------------------------------------------------------------------------------------- * Integer | SORT_FIELD_INDEX | read-only | Which field is used as the main sort field * -------------------------------------------------------------------------------------------------------------------- - * Integer | TYPE | read-only | 0 for normal model, 1 for cloze model + * Integer | TYPE | read-only | 0 for normal note type, 1 for cloze note type * -------------------------------------------------------------------------------------------------------------------- * String | LATEX_POST | read-only | Code to go at the end of LaTeX renderings in Anki Desktop * -------------------------------------------------------------------------------------------------------------------- @@ -313,7 +316,7 @@ public object FlashCardsContract { * ``` * * - * It's possible to query all models at once like this + * It's possible to query all note type at once like this * * ``` * Uri noteUri = Uri.withAppendedPath(FlashCardsContract.Note.CONTENT_URI, Long.toString(noteId)); @@ -326,13 +329,13 @@ public object FlashCardsContract { * ``` * * - * It's also possible to access a specific model like this: + * It's also possible to access a specific note type like this: * * * ``` - * long modelId = ...// Use the correct model ID - * Uri modelUri = Uri.withAppendedPath(FlashCardsContract.Model.CONTENT_URI, Long.toString(modelId)); - * final Cursor cur = cr.query(modelUri, + * long noteTypeId = ...// Use the correct note type ID + * Uri noteTypeUri = Uri.withAppendedPath(FlashCardsContract.Model.CONTENT_URI, Long.toString(noteTypeId)); + * final Cursor cur = cr.query(noteTypeUri, * null, // projection * null, // selection is ignored for this URI * null, // selectionArgs is ignored for this URI @@ -341,7 +344,7 @@ public object FlashCardsContract { * ``` * * - * Instead of specifying the model ID, it's also possible to get the currently active model using the following URI: + * Instead of specifying the noteType ID, it's also possible to get the currently active noteType using the following URI: * * * ``` @@ -350,16 +353,16 @@ public object FlashCardsContract { */ public object Model { /** - * The content:// style URI for model. If the it is appended by the model's ID, this + * The content:// style URI for note type. If the it is appended by the note type's ID, this * note can be directly accessed. See class description above for further details. */ @JvmField // required for Java API public val CONTENT_URI: Uri = Uri.withAppendedPath(AUTHORITY_URI, "models") - public const val CURRENT_MODEL_ID: String = "current" + public const val CURRENT_NOTE_TYPE_ID: String = "current" /** - * This is the ID of the model. It is the same as the note ID in Anki. This ID can be - * used for accessing the data of the model using the URI + * This is the ID of the note type. It is the same as the note ID in Anki. This ID can be + * used for accessing the data of the note type using the URI * `content://com.ichi2.anki.flashcards/models/` */ @Suppress("ConstPropertyName", "ktlint:standard:backing-property-naming") @@ -376,7 +379,7 @@ public object FlashCardsContract { public const val NOTE_COUNT: String = "note_count" /** - * The deck ID that is selected by default when adding new notes with this model. + * The deck ID that is selected by default when adding new notes with this note type. * This is only used when the "Deck for new cards" preference is set to "Decide by note type" */ public const val DECK_ID: String = "deck_id" @@ -397,19 +400,19 @@ public object FlashCardsContract { ) /** - * MIME type used for a model. + * MIME type used for a note type. */ public const val CONTENT_ITEM_TYPE: String = "vnd.android.cursor.item/vnd.com.ichi2.anki.model" /** - * MIME type used for model. + * MIME type used for note type. */ public const val CONTENT_TYPE: String = "vnd.android.cursor.dir/vnd.com.ichi2.anki.model" } /** - * Card template for a model. A template defines how to render the fields of a note into the actual HTML that - * makes up a flashcard. A model can define multiple card templates, for example a Forward and Reverse Card could + * Card template for a note type. A template defines how to render the fields of a note into the actual HTML that + * makes up a flashcard. A note type can define multiple card templates, for example a Forward and Reverse Card could * be defined with the forward card allowing to review a word from Japanese -> English (e.g. 犬 -> dog), and the * reverse card allowing review in the "reverse" direction (e.g dog -> 犬). When a Note is inserted, a Card will * be generated for each active CardTemplate which is defined. @@ -432,7 +435,8 @@ public object FlashCardsContract { public const val _ID: String = "_id" /** - * This is the ID of the model that this row belongs to (i.e. [Model._ID]). + * This is the ID of the note type that this row belongs to (i.e. [Model._ID]). + * "Model" was the previous name of "note type". We keep this deprecated name for the sake of compatibility with the ecosystem. */ public const val MODEL_ID: String = "model_id" diff --git a/api/src/main/java/com/ichi2/anki/api/AddContentApi.kt b/api/src/main/java/com/ichi2/anki/api/AddContentApi.kt index 0ce9670eb14d..04b4b95551bd 100644 --- a/api/src/main/java/com/ichi2/anki/api/AddContentApi.kt +++ b/api/src/main/java/com/ichi2/anki/api/AddContentApi.kt @@ -39,7 +39,7 @@ import java.io.File import java.util.Locale /** - * API which can be used to add and query notes,cards,decks, and models to AnkiDroid + * API which can be used to add and query notes,cards,decks, and note types to AnkiDroid * * On Android M (and higher) the #READ_WRITE_PERMISSION is required for all read/write operations. * On earlier SDK levels, the #READ_WRITE_PERMISSION is currently only required for update/delete operations but @@ -53,33 +53,33 @@ public class AddContentApi( private val resolver: ContentResolver = this.context.contentResolver /** - * Create a new note with specified fields, tags, and model and place it in the specified deck. + * Create a new note with specified fields, tags, and note type and place it in the specified deck. * No duplicate checking is performed - so the note should be checked beforehand using #findNotesByKeys - * @param modelId ID for the model used to add the notes + * @param noteTypeId ID for the note type used to add the notes * @param deckId ID for the deck the cards should be stored in (use #DEFAULT_DECK_ID for default deck) - * @param fields fields to add to the note. Length should be the same as number of fields in model + * @param fields fields to add to the note. Length should be the same as number of fields in note type * @param tags tags to include in the new note * @return note id or null if the note could not be added */ public fun addNote( - modelId: Long, + noteTypeId: Long, deckId: Long, fields: Array, tags: Set?, ): Long? { - val noteUri = addNoteInternal(modelId, deckId, fields, tags) ?: return null + val noteUri = addNoteInternal(noteTypeId, deckId, fields, tags) ?: return null return noteUri.lastPathSegment!!.toLong() } private fun addNoteInternal( - modelId: Long, + noteTypeId: Long, deckId: Long, fields: Array, tags: Set?, ): Uri? { val values = ContentValues().apply { - put(Note.MID, modelId) + put(Note.MID, noteTypeId) put(Note.FLDS, Utils.joinFields(fields)) if (tags != null) put(Note.TAGS, Utils.joinTags(tags)) } @@ -106,16 +106,16 @@ public class AddContentApi( } /** - * Create new notes with specified fields, tags and model and place them in the specified deck. + * Create new notes with specified fields, tags and note type and place them in the specified deck. * No duplicate checking is performed - so all notes should be checked beforehand using #findNotesByKeys - * @param modelId id for the model used to add the notes + * @param noteTypeId id for the note type used to add the notes * @param deckId id for the deck the cards should be stored in (use #DEFAULT_DECK_ID for default deck) - * @param fieldsList List of fields arrays (one per note). Array lengths should be same as number of fields in model + * @param fieldsList List of fields arrays (one per note). Array lengths should be same as number of fields in note type * @param tagsList List of tags (one per note) (may be null) * @return The number of notes added (< 0 means there was a problem) */ public fun addNotes( - modelId: Long, + noteTypeId: Long, deckId: Long, fieldsList: List>, tagsList: List?>?, @@ -125,7 +125,7 @@ public class AddContentApi( for (i in fieldsList.indices) { val values = ContentValues().apply { - put(Note.MID, modelId) + put(Note.MID, noteTypeId) put(Note.FLDS, Utils.joinFields(fieldsList[i])) if (tagsList != null && tagsList[i] != null) { put(Note.TAGS, Utils.joinTags(tagsList[i])) @@ -154,14 +154,14 @@ public class AddContentApi( * * Example usage: * ``` - * Long modelId = getModelId(); // implementation can be seen in api sample app + * Long noteTypeId = getNoteTypeId(); // implementation can be seen in api sample app * Long deckId = getDeckId(); // as above * Set tags = getTags(); // as above * Uri fileUri = ... // this will be returned by a File Picker activity where we select an image file * String addedImageFileName = mApi.addMediaFromUri(fileUri, "My_Image_File", "image"); * * String[] fields = new String[] {"text on front of card", "text on back of card " + addedImageFileName}; - * mApi.addNote(modelId, deckId, fields, tags) + * mApi.addNote(noteTypeId, deckId, fields, tags) * ``` * * @param fileUri Uri for the file to be added, required. @@ -202,7 +202,7 @@ public class AddContentApi( /** * Find all existing notes in the collection which have mid and a duplicate key - * @param mid model id + * @param mid note type id * @param key the first field of a note * @return a list of duplicate notes */ @@ -221,7 +221,7 @@ public class AddContentApi( /** * Find all notes in the collection which have mid and a first field that matches key * Much faster than calling findDuplicateNotes(long, String) when the list of keys is large - * @param mid model id + * @param mid note type id * @param keys list of keys * @return a SparseArray with a list of duplicate notes for each key */ @@ -231,9 +231,9 @@ public class AddContentApi( ): SparseArray>? = compat.findDuplicateNotes(mid, keys) /** - * Get the number of notes that exist for the specified model ID - * @param mid id of the model to be used - * @return number of notes that exist with that model ID or -1 if there was a problem + * Get the number of notes that exist for the specified note type ID + * @param mid id of the note type to be used + * @return number of notes that exist with that note type ID or -1 if there was a problem */ public fun getNoteCount(mid: Long): Int = compat.queryNotes(mid)?.use { cursor -> cursor.count } ?: 0 @@ -337,55 +337,55 @@ public class AddContentApi( } /** - * Insert a new basic front/back model with two fields and one card - * @param name name of the model - * @return the mid of the model which was created, or null if it could not be created + * Insert a new basic front/back note type with two fields and one card + * @param name name of the note type + * @return the mid of the note type which was created, or null if it could not be created */ - public fun addNewBasicModel(name: String): Long? = - addNewCustomModel( + public fun addNewBasicNoteType(name: String): Long? = + addNewCustomNoteType( name, - BasicModel.FIELDS, - BasicModel.CARD_NAMES, - BasicModel.QFMT, - BasicModel.AFMT, + BasicNoteType.FIELDS, + BasicNoteType.CARD_NAMES, + BasicNoteType.QFMT, + BasicNoteType.AFMT, null, null, null, ) /** - * Insert a new basic front/back model with two fields and TWO cards + * Insert a new basic front/back note type with two fields and TWO cards * The first card goes from front->back, and the second goes from back->front - * @param name name of the model - * @return the mid of the model which was created, or null if it could not be created + * @param name name of the note type + * @return the mid of the note type which was created, or null if it could not be created */ - public fun addNewBasic2Model(name: String): Long? = - addNewCustomModel( + public fun addNewBasic2NoteType(name: String): Long? = + addNewCustomNoteType( name, - Basic2Model.FIELDS, - Basic2Model.CARD_NAMES, - Basic2Model.QFMT, - Basic2Model.AFMT, + Basic2NoteType.FIELDS, + Basic2NoteType.CARD_NAMES, + Basic2NoteType.QFMT, + Basic2NoteType.AFMT, null, null, null, ) /** - * Insert a new model into AnkiDroid. + * Insert a new note type into AnkiDroid. * See the [Anki Desktop Manual](https://docs.ankiweb.net/templates/intro.html) for more help - * @param name name of model + * @param name name of note type * @param fields array of field names * @param cards array of names for the card templates * @param qfmt array of formatting strings for the question side of each template in cards * @param afmt array of formatting strings for the answer side of each template in cards * @param css css styling information to be shared across all of the templates. Use null for default CSS. - * @param did default deck to add cards to when using this model. Use null or #DEFAULT_DECK_ID for default deck. + * @param did default deck to add cards to when using this note type. Use null or #DEFAULT_DECK_ID for default deck. * @param sortf index of field to be used for sorting. Use null for unspecified (unsupported in provider spec v1) - * @return the mid of the model which was created, or null if it could not be created + * @return the id of the note type which was created, or null if it could not be created */ @Suppress("MemberVisibilityCanBePrivate") // silence IDE - public fun addNewCustomModel( + public fun addNewCustomNoteType( name: String, fields: Array, cards: Array, @@ -397,7 +397,7 @@ public class AddContentApi( ): Long? { // Check that size of arrays are consistent require(!(qfmt.size != cards.size || afmt.size != cards.size)) { "cards, qfmt, and afmt arrays must all be same length" } - // Create the model using dummy templates + // Create the note type using dummy templates var values = ContentValues().apply { put(Model.NAME, name) @@ -407,9 +407,9 @@ public class AddContentApi( put(Model.DECK_ID, did) put(Model.SORT_FIELD_INDEX, sortf) } - val modelUri = resolver.insert(Model.CONTENT_URI, values) ?: return null + val noteTypeUri = resolver.insert(Model.CONTENT_URI, values) ?: return null // Set the remaining template parameters - val templatesUri = Uri.withAppendedPath(modelUri, "templates") + val templatesUri = Uri.withAppendedPath(noteTypeUri, "templates") for (i in cards.indices) { val uri = Uri.withAppendedPath(templatesUri, i.toString()) values = @@ -421,39 +421,39 @@ public class AddContentApi( } resolver.update(uri, values, null, null) } - return modelUri.lastPathSegment!!.toLong() - } // Get the current model + return noteTypeUri.lastPathSegment!!.toLong() + } // Get the current note type /** - * Get the ID for the note type / model which is currently in use - * @return id for current model, or < 0 if there was a problem + * Get the ID for the note type / note type which is currently in use + * @return id for current note type, or < 0 if there was a problem */ - public val currentModelId: Long + public val currentNoteTypeId: Long get() { - // Get the current model - val uri = Uri.withAppendedPath(Model.CONTENT_URI, Model.CURRENT_MODEL_ID) - val singleModelQuery = resolver.query(uri, null, null, null, null) ?: return -1L - return singleModelQuery.use { singleModelCursor -> - singleModelCursor.moveToFirst() - singleModelCursor.getLong(singleModelCursor.getColumnIndex(Model._ID)) + // Get the current note type + val uri = Uri.withAppendedPath(Model.CONTENT_URI, Model.CURRENT_NOTE_TYPE_ID) + val singleNoteTypeQuery = resolver.query(uri, null, null, null, null) ?: return -1L + return singleNoteTypeQuery.use { singleNoteTypeCursor -> + singleNoteTypeCursor.moveToFirst() + singleNoteTypeCursor.getLong(singleNoteTypeCursor.getColumnIndex(Model._ID)) } } /** - * Get the field names belonging to specified model - * @param modelId the ID of the model to use - * @return the names of all the fields, or null if the model doesn't exist or there was some other problem + * Get the field names belonging to specified note type + * @param noteTypeId the ID of the note type to use + * @return the names of all the fields, or null if the note type doesn't exist or there was some other problem */ - public fun getFieldList(modelId: Long): Array? { - // Get the current model - val uri = Uri.withAppendedPath(Model.CONTENT_URI, modelId.toString()) - val modelQuery = resolver.query(uri, null, null, null, null) ?: return null + public fun getFieldList(noteTypeId: Long): Array? { + // Get the current note type + val uri = Uri.withAppendedPath(Model.CONTENT_URI, noteTypeId.toString()) + val noteTypeQuery = resolver.query(uri, null, null, null, null) ?: return null var splitFlds: Array? = null - modelQuery.use { modelCursor -> - if (modelCursor.moveToNext()) { + noteTypeQuery.use { noteTypeCursor -> + if (noteTypeCursor.moveToNext()) { splitFlds = Utils.splitFields( - modelCursor.getString(modelCursor.getColumnIndex(Model.FIELD_NAMES)), + noteTypeCursor.getString(noteTypeCursor.getColumnIndex(Model.FIELD_NAMES)), ) } } @@ -461,44 +461,44 @@ public class AddContentApi( } /** - * Get a map of all model ids and names + * Get a map of all note type ids and names * @return map of (id, name) pairs */ - public val modelList: Map? - get() = getModelList(1) + public val noteTypeList: Map? + get() = getNoteTYpeList(1) /** - * Get a map of all model ids and names with number of fields larger than minNumFields - * @param minNumFields minimum number of fields to consider the model for inclusion + * Get a map of all note type ids and names with number of fields larger than minNumFields + * @param minNumFields minimum number of fields to consider the note type for inclusion * @return map of (id, name) pairs or null if there was a problem */ - public fun getModelList(minNumFields: Int): Map? { - // Get the current model - val allModelsQuery = + public fun getNoteTYpeList(minNumFields: Int): Map? { + // Get the current note type + val allNoteTypesQuery = resolver.query(Model.CONTENT_URI, null, null, null, null) ?: return null - val models: MutableMap = HashMap() - allModelsQuery.use { allModelsCursor -> - while (allModelsCursor.moveToNext()) { - val modelId = allModelsCursor.getLong(allModelsCursor.getColumnIndex(Model._ID)) - val name = allModelsCursor.getString(allModelsCursor.getColumnIndex(Model.NAME)) + val noteTypes: MutableMap = HashMap() + allNoteTypesQuery.use { allNoteTypesCursor -> + while (allNoteTypesCursor.moveToNext()) { + val noteTypeId = allNoteTypesCursor.getLong(allNoteTypesCursor.getColumnIndex(Model._ID)) + val name = allNoteTypesCursor.getString(allNoteTypesCursor.getColumnIndex(Model.NAME)) val flds = - allModelsCursor.getString(allModelsCursor.getColumnIndex(Model.FIELD_NAMES)) + allNoteTypesCursor.getString(allNoteTypesCursor.getColumnIndex(Model.FIELD_NAMES)) val numFlds: Int = Utils.splitFields(flds).size if (numFlds >= minNumFields) { - models[modelId] = name + noteTypes[noteTypeId] = name } } } - return models + return noteTypes } /** - * Get the name of the model which has given ID - * @param mid id of model - * @return the name of the model, or null if no model was found + * Get the name of the note type which has given ID + * @param mid id of note type + * @return the name of the note type, or null if no note type was found */ - public fun getModelName(mid: Long): String? = modelList!![mid] + public fun getNoteTypeName(mid: Long): String? = noteTypeList!![mid] /** * Create a new deck with specified name and save the reference to SharedPreferences for later @@ -537,7 +537,7 @@ public class AddContentApi( null } } - } // Get the current model + } // Get the current note type /** * Get a list of all the deck id / name pairs @@ -545,7 +545,7 @@ public class AddContentApi( */ public val deckList: Map? get() { - // Get the current model + // Get the current note type val allDecksQuery = resolver.query(Deck.CONTENT_ALL_URI, null, null, null, null) ?: return null val decks: MutableMap = HashMap() @@ -624,11 +624,11 @@ public class AddContentApi( private interface Compat { /** - * Query all notes for a given model - * @param modelId the model ID to limit query to - * @return a cursor with all notes matching modelId + * Query all notes for a given note type + * @param noteTypeId the note type ID to limit query to + * @return a cursor with all notes matching noteTypeId */ - fun queryNotes(modelId: Long): Cursor? + fun queryNotes(noteTypeId: Long): Cursor? /** * Add new notes to the AnkiDroid content provider in bulk. @@ -643,20 +643,20 @@ public class AddContentApi( /** * For each key, look for an existing note that has matching first field - * @param modelId the model ID to limit the search to + * @param noteTypeId the note type ID to limit the search to * @param keys list of keys for each note * @return array with a list of NoteInfo objects for each key if duplicates exist */ fun findDuplicateNotes( - modelId: Long, + noteTypeId: Long, keys: List, ): SparseArray>? } private open inner class CompatV1 : Compat { - override fun queryNotes(modelId: Long): Cursor? { - val modelName = getModelName(modelId) ?: return null - val queryFormat = "note:\"$modelName\"" + override fun queryNotes(noteTypeId: Long): Cursor? { + val noteTypeName = getNoteTypeName(noteTypeId) ?: return null + val queryFormat = "note:\"$noteTypeName\"" return resolver.query( Note.CONTENT_URI, PROJECTION, @@ -672,15 +672,15 @@ public class AddContentApi( ): Int = valuesArr.count { addNoteForContentValues(deckId, it) != null } override fun findDuplicateNotes( - modelId: Long, + noteTypeId: Long, keys: List, ): SparseArray>? { // Content provider spec v1 does not support direct querying of the notes table, so use Anki browser syntax - val modelName = getModelName(modelId) ?: return null - val modelFieldList = getFieldList(modelId) ?: return null + val noteTypeName = getNoteTypeName(noteTypeId) ?: return null + val noteTypeFieldList = getFieldList(noteTypeId) ?: return null val duplicates = SparseArray>() // Loop through each item in fieldsArray looking for an existing note, and add it to the duplicates array - val queryFormat = "${modelFieldList[0]}:\"%%s\" note:\"$modelName\"" + val queryFormat = "${noteTypeFieldList[0]}:\"%%s\" note:\"$noteTypeName\"" for (outputPos in keys.indices) { val selection = String.format(queryFormat, keys[outputPos]) val query = @@ -721,11 +721,11 @@ public class AddContentApi( } private inner class CompatV2 : CompatV1() { - override fun queryNotes(modelId: Long): Cursor? = + override fun queryNotes(noteTypeId: Long): Cursor? = resolver.query( Note.CONTENT_URI_V2, PROJECTION, - String.format(Locale.US, "%s=%d", Note.MID, modelId), + String.format(Locale.US, "%s=%d", Note.MID, noteTypeId), null, null, ) @@ -743,7 +743,7 @@ public class AddContentApi( } override fun findDuplicateNotes( - modelId: Long, + noteTypeId: Long, keys: List, ): SparseArray>? { // Build set of checksums and a HashMap from the key (first field) back to the original index in fieldsArray @@ -757,13 +757,13 @@ public class AddContentApi( } keyToIndexesMap[key]!!.add(i) } - // Query for notes that have specified model and checksum of first field matches + // Query for notes that have specified note type and checksum of first field matches val sel = String.format( Locale.US, "%s=%d and %s in (%s)", Note.MID, - modelId, + noteTypeId, Note.CSUM, csums.joinToString(separator = ","), ) diff --git a/api/src/main/java/com/ichi2/anki/api/Basic2Model.kt b/api/src/main/java/com/ichi2/anki/api/Basic2NoteType.kt similarity index 90% rename from api/src/main/java/com/ichi2/anki/api/Basic2Model.kt rename to api/src/main/java/com/ichi2/anki/api/Basic2NoteType.kt index 3bc84b1e3f14..d752669d50db 100644 --- a/api/src/main/java/com/ichi2/anki/api/Basic2Model.kt +++ b/api/src/main/java/com/ichi2/anki/api/Basic2NoteType.kt @@ -2,9 +2,9 @@ package com.ichi2.anki.api /** - * Definitions of the basic with reverse model + * Definitions of the basic with reverse note type */ -internal object Basic2Model { +internal object Basic2NoteType { @JvmField // required for Java API val FIELDS = arrayOf("Front", "Back") diff --git a/api/src/main/java/com/ichi2/anki/api/BasicModel.kt b/api/src/main/java/com/ichi2/anki/api/BasicModel.kt index f8b3e272dc62..d9d8046c1d04 100644 --- a/api/src/main/java/com/ichi2/anki/api/BasicModel.kt +++ b/api/src/main/java/com/ichi2/anki/api/BasicModel.kt @@ -2,9 +2,9 @@ package com.ichi2.anki.api /** - * Definitions of the basic model + * Definitions of the basic note type */ -internal class BasicModel { +internal class BasicNoteType { companion object { @JvmField // required for API @Suppress("ktlint:standard:property-naming")