use of com.ichi2.anki.CardBrowser.Column.CHANGED in project AnkiChinaAndroid by ankichinateam.
the class TagsDialog method adjustToolbar.
private void adjustToolbar(View tagsDialogView) {
Toolbar mToolbar = tagsDialogView.findViewById(R.id.tags_dialog_toolbar);
mToolbar.setTitle(mDialogTitle);
mToolbar.inflateMenu(R.menu.tags_dialog_menu);
final InputFilter addTagFilter = (source, start, end, dest, dstart, dend) -> {
for (int i = start; i < end; i++) {
if (source.charAt(i) == ' ') {
return "";
}
}
return null;
};
MenuItem mToolbarAddItem = mToolbar.getMenu().findItem(R.id.tags_dialog_action_add);
mToolbarAddItem.setOnMenuItemClickListener(menuItem -> {
String query = mToolbarSearchView.getQuery().toString();
if (mToolbarSearchItem.isActionViewExpanded() && !TextUtils.isEmpty(query)) {
addTag(query);
mToolbarSearchView.setQuery("", true);
} else {
MaterialDialog.Builder addTagBuilder = new MaterialDialog.Builder(getActivity()).title(getString(R.string.add_tag)).negativeText(R.string.dialog_cancel).positiveText(R.string.dialog_ok).inputType(InputType.TYPE_CLASS_TEXT).input(R.string.tag_name, R.string.empty_string, (dialog, input) -> addTag(input.toString()));
final MaterialDialog addTagDialog = addTagBuilder.build();
EditText inputET = addTagDialog.getInputEditText();
inputET.setFilters(new InputFilter[] { addTagFilter });
addTagDialog.show();
}
return true;
});
mToolbarSearchItem = mToolbar.getMenu().findItem(R.id.tags_dialog_action_filter);
mToolbarSearchView = (SearchView) mToolbarSearchItem.getActionView();
EditText queryET = mToolbarSearchView.findViewById(R.id.search_src_text);
queryET.setFilters(new InputFilter[] { addTagFilter });
mToolbarSearchView.setQueryHint(getString(R.string.filter_tags));
mToolbarSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
mToolbarSearchView.clearFocus();
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
TagsArrayAdapter adapter = (TagsArrayAdapter) mTagsListRecyclerView.getAdapter();
adapter.getFilter().filter(newText);
return true;
}
});
MenuItem checkAllItem = mToolbar.getMenu().findItem(R.id.tags_dialog_action_select_all);
checkAllItem.setOnMenuItemClickListener(menuItem -> {
boolean changed = false;
if (mCurrentTags.containsAll(mTagsArrayAdapter.mTagsList)) {
mCurrentTags.removeAll(mTagsArrayAdapter.mTagsList);
changed = true;
} else {
for (String tag : mTagsArrayAdapter.mTagsList) {
if (!mCurrentTags.contains(tag)) {
mCurrentTags.add(tag);
changed = true;
}
}
}
if (changed) {
mTagsArrayAdapter.notifyDataSetChanged();
}
return true;
});
switch(mType) {
case TYPE_ADD_TAG:
mToolbarSearchView.setQueryHint(getString(R.string.add_new_filter_tags));
break;
default:
mToolbarAddItem.setVisible(false);
break;
}
}
use of com.ichi2.anki.CardBrowser.Column.CHANGED in project AnkiChinaAndroid by ankichinateam.
the class CardContentProvider method update.
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
if (!hasReadWritePermission() && shouldEnforceUpdateSecurity(uri)) {
throwSecurityException("update", uri);
}
Collection col = CollectionHelper.getInstance().getCol(mContext);
if (col == null) {
throw new IllegalStateException(COL_NULL_ERROR_MSG);
}
col.log(getLogMessage("update", uri));
// Find out what data the user is requesting
int match = sUriMatcher.match(uri);
// Number of updated entries (return value)
int updated = 0;
switch(match) {
case NOTES_V2:
case NOTES:
throw new IllegalArgumentException("Not possible to update notes directly (only through data URI)");
case NOTES_ID:
{
/* Direct access note details
*/
Note currentNote = getNoteFromUri(uri, col);
// the key of the ContentValues contains the column name
// the value of the ContentValues contains the row value.
Set<Map.Entry<String, Object>> valueSet = values.valueSet();
for (Map.Entry<String, Object> entry : valueSet) {
String key = entry.getKey();
// when the client does not specify FLDS, then don't update the FLDS
if (key.equals(FlashCardsContract.Note.FLDS)) {
// Update FLDS
Timber.d("CardContentProvider: flds update...");
String newFldsEncoded = (String) entry.getValue();
String[] flds = Utils.splitFields(newFldsEncoded);
// Check that correct number of flds specified
if (flds.length != currentNote.getFields().length) {
throw new IllegalArgumentException("Incorrect flds argument : " + newFldsEncoded);
}
// Update the note
for (int idx = 0; idx < flds.length; idx++) {
currentNote.setField(idx, flds[idx]);
}
updated++;
} else if (key.equals(FlashCardsContract.Note.TAGS)) {
// Update tags
Timber.d("CardContentProvider: tags update...");
Object tags = entry.getValue();
if (tags != null) {
currentNote.setTagsFromStr(String.valueOf(tags));
}
updated++;
} else {
// Unsupported column
throw new IllegalArgumentException("Unsupported column: " + key);
}
}
Timber.d("CardContentProvider: Saving note...");
currentNote.flush();
break;
}
case NOTES_ID_CARDS:
// TODO: To be implemented
throw new UnsupportedOperationException("Not yet implemented");
// break;
case NOTES_ID_CARDS_ORD:
{
Card currentCard = getCardFromUri(uri, col);
boolean isDeckUpdate = false;
long did = -1;
// the key of the ContentValues contains the column name
// the value of the ContentValues contains the row value.
Set<Map.Entry<String, Object>> valueSet = values.valueSet();
for (Map.Entry<String, Object> entry : valueSet) {
// Only updates on deck id is supported
String key = entry.getKey();
isDeckUpdate = key.equals(FlashCardsContract.Card.DECK_ID);
did = values.getAsLong(key);
}
if (col.getDecks().isDyn(did)) {
throw new IllegalArgumentException("Cards cannot be moved to a filtered deck");
}
/* now update the card
*/
if ((isDeckUpdate) && (did >= 0)) {
Timber.d("CardContentProvider: Moving card to other deck...");
col.getDecks().flush();
currentCard.setDid(did);
currentCard.flush();
col.save();
updated++;
} else {
// User tries an operation that is not (yet?) supported.
throw new IllegalArgumentException("Currently only updates of decks are supported");
}
break;
}
case MODELS:
throw new IllegalArgumentException("Cannot update models in bulk");
case MODELS_ID:
// Get the input parameters
String newModelName = values.getAsString(FlashCardsContract.Model.NAME);
String newCss = values.getAsString(FlashCardsContract.Model.CSS);
String newDid = values.getAsString(FlashCardsContract.Model.DECK_ID);
String newFieldList = values.getAsString(FlashCardsContract.Model.FIELD_NAMES);
if (newFieldList != null) {
// Changing the field names would require a full-sync
throw new IllegalArgumentException("Field names cannot be changed via provider");
}
Integer newSortf = values.getAsInteger(FlashCardsContract.Model.SORT_FIELD_INDEX);
Integer newType = values.getAsInteger(FlashCardsContract.Model.TYPE);
String newLatexPost = values.getAsString(FlashCardsContract.Model.LATEX_POST);
String newLatexPre = values.getAsString(FlashCardsContract.Model.LATEX_PRE);
// Get the original note JSON
Model model = col.getModels().get(getModelIdFromUri(uri, col));
try {
// Update model name and/or css
if (newModelName != null) {
model.put("name", newModelName);
updated++;
}
if (newCss != null) {
model.put("css", newCss);
updated++;
}
if (newDid != null) {
if (col.getDecks().isDyn(Long.parseLong(newDid))) {
throw new IllegalArgumentException("Cannot set a filtered deck as default deck for a model");
}
model.put("did", newDid);
updated++;
}
if (newSortf != null) {
model.put("sortf", newSortf);
updated++;
}
if (newType != null) {
model.put("type", newType);
updated++;
}
if (newLatexPost != null) {
model.put("latexPost", newLatexPost);
updated++;
}
if (newLatexPre != null) {
model.put("latexPre", newLatexPre);
updated++;
}
col.getModels().save(model);
col.save();
} catch (JSONException e) {
Timber.e(e, "JSONException updating model");
}
break;
case MODELS_ID_TEMPLATES:
throw new IllegalArgumentException("Cannot update templates in bulk");
case MODELS_ID_TEMPLATES_ID:
Long mid = values.getAsLong(CardTemplate.MODEL_ID);
Integer ord = values.getAsInteger(CardTemplate.ORD);
String name = values.getAsString(CardTemplate.NAME);
String qfmt = values.getAsString(CardTemplate.QUESTION_FORMAT);
String afmt = values.getAsString(CardTemplate.ANSWER_FORMAT);
String bqfmt = values.getAsString(CardTemplate.BROWSER_QUESTION_FORMAT);
String bafmt = values.getAsString(CardTemplate.BROWSER_ANSWER_FORMAT);
// Throw exception if read-only fields are included
if (mid != null || ord != null) {
throw new IllegalArgumentException("Updates to mid or ord are not allowed");
}
// Update the model
try {
Integer templateOrd = Integer.parseInt(uri.getLastPathSegment());
Model existingModel = col.getModels().get(getModelIdFromUri(uri, col));
JSONArray templates = existingModel.getJSONArray("tmpls");
JSONObject template = templates.getJSONObject(templateOrd);
if (name != null) {
template.put("name", name);
updated++;
}
if (qfmt != null) {
template.put("qfmt", qfmt);
updated++;
}
if (afmt != null) {
template.put("afmt", afmt);
updated++;
}
if (bqfmt != null) {
template.put("bqfmt", bqfmt);
updated++;
}
if (bafmt != null) {
template.put("bafmt", bafmt);
updated++;
}
// Save the model
templates.put(templateOrd, template);
existingModel.put("tmpls", templates);
col.getModels().save(existingModel, true);
col.save();
} catch (JSONException e) {
throw new IllegalArgumentException("Model is malformed", e);
}
break;
case SCHEDULE:
{
Set<Map.Entry<String, Object>> valueSet = values.valueSet();
int cardOrd = -1;
long noteID = -1;
int ease = -1;
long timeTaken = -1;
int bury = -1;
int suspend = -1;
for (Map.Entry<String, Object> entry : valueSet) {
String key = entry.getKey();
if (key.equals(FlashCardsContract.ReviewInfo.NOTE_ID)) {
noteID = values.getAsLong(key);
} else if (key.equals(FlashCardsContract.ReviewInfo.CARD_ORD)) {
cardOrd = values.getAsInteger(key);
} else if (key.equals(FlashCardsContract.ReviewInfo.EASE)) {
ease = values.getAsInteger(key);
} else if (key.equals(FlashCardsContract.ReviewInfo.TIME_TAKEN)) {
timeTaken = values.getAsLong(key);
} else if (key.equals(FlashCardsContract.ReviewInfo.BURY)) {
bury = values.getAsInteger(key);
} else if (key.equals(FlashCardsContract.ReviewInfo.SUSPEND)) {
suspend = values.getAsInteger(key);
}
}
if (cardOrd != -1 && noteID != -1) {
Card cardToAnswer = getCard(noteID, cardOrd, col);
if (cardToAnswer != null) {
if (bury == 1) {
// bury card
buryOrSuspendCard(col, col.getSched(), cardToAnswer, true);
} else if (suspend == 1) {
// suspend card
buryOrSuspendCard(col, col.getSched(), cardToAnswer, false);
} else {
answerCard(col, col.getSched(), cardToAnswer, ease, timeTaken);
}
updated++;
} else {
Timber.e("Requested card with noteId %d and cardOrd %d was not found. Either the provided " + "noteId/cardOrd were wrong or the card has been deleted in the meantime.", noteID, cardOrd);
}
}
break;
}
case DECKS:
throw new IllegalArgumentException("Can't update decks in bulk");
case DECKS_ID:
// TODO: be sure to throw exception if change to the dyn value of a deck is requested
throw new UnsupportedOperationException("Not yet implemented");
case DECK_SELECTED:
{
Set<Map.Entry<String, Object>> valueSet = values.valueSet();
for (Map.Entry<String, Object> entry : valueSet) {
String key = entry.getKey();
if (key.equals(FlashCardsContract.Deck.DECK_ID)) {
long deckId = values.getAsLong(key);
if (selectDeckWithCheck(col, deckId)) {
updated++;
}
}
}
col.save();
break;
}
default:
// Unknown URI type
throw new IllegalArgumentException("uri " + uri + " is not supported");
}
return updated;
}
use of com.ichi2.anki.CardBrowser.Column.CHANGED in project AnkiChinaAndroid by ankichinateam.
the class CardContentProvider method query.
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String order) {
if (!hasReadWritePermission() && shouldEnforceQueryOrInsertSecurity()) {
throwSecurityException("query", uri);
}
Collection col = CollectionHelper.getInstance().getCol(mContext);
if (col == null) {
throw new IllegalStateException(COL_NULL_ERROR_MSG);
}
Timber.d(getLogMessage("query", uri));
// Find out what data the user is requesting
int match = sUriMatcher.match(uri);
switch(match) {
case NOTES_V2:
{
/* Search for notes using direct SQL query */
String[] proj = sanitizeNoteProjection(projection);
String sql = SQLiteQueryBuilder.buildQueryString(false, "notes", proj, selection, null, null, order, null);
return col.getDb().getDatabase().query(sql, selectionArgs);
}
case NOTES:
{
/* Search for notes using the libanki browser syntax */
String[] proj = sanitizeNoteProjection(projection);
String query = (selection != null) ? selection : "";
List<Long> noteIds = col.findNotes(query);
if ((noteIds != null) && (!noteIds.isEmpty())) {
String sel = String.format("id in (%s)", TextUtils.join(",", noteIds));
String sql = SQLiteQueryBuilder.buildQueryString(false, "notes", proj, sel, null, null, order, null);
return col.getDb().getDatabase().query(sql);
} else {
return null;
}
}
case NOTES_ID:
{
/* Direct access note with specific ID*/
String noteId = uri.getPathSegments().get(1);
String[] proj = sanitizeNoteProjection(projection);
String sql = SQLiteQueryBuilder.buildQueryString(false, "notes", proj, "id=?", null, null, order, null);
return col.getDb().getDatabase().query(sql, new String[] { noteId });
}
case NOTES_ID_CARDS:
{
Note currentNote = getNoteFromUri(uri, col);
String[] columns = ((projection != null) ? projection : FlashCardsContract.Card.DEFAULT_PROJECTION);
MatrixCursor rv = new MatrixCursor(columns, 1);
for (Card currentCard : currentNote.cards()) {
addCardToCursor(currentCard, rv, col, columns);
}
return rv;
}
case NOTES_ID_CARDS_ORD:
{
Card currentCard = getCardFromUri(uri, col);
String[] columns = ((projection != null) ? projection : FlashCardsContract.Card.DEFAULT_PROJECTION);
MatrixCursor rv = new MatrixCursor(columns, 1);
addCardToCursor(currentCard, rv, col, columns);
return rv;
}
case MODELS:
{
Models models = col.getModels();
String[] columns = ((projection != null) ? projection : FlashCardsContract.Model.DEFAULT_PROJECTION);
MatrixCursor rv = new MatrixCursor(columns, 1);
for (Long modelId : models.getModels().keySet()) {
addModelToCursor(modelId, models, rv, columns);
}
return rv;
}
case MODELS_ID:
{
long modelId = getModelIdFromUri(uri, col);
String[] columns = ((projection != null) ? projection : FlashCardsContract.Model.DEFAULT_PROJECTION);
MatrixCursor rv = new MatrixCursor(columns, 1);
addModelToCursor(modelId, col.getModels(), rv, columns);
return rv;
}
case MODELS_ID_TEMPLATES:
{
/* Direct access model templates */
Models models = col.getModels();
Model currentModel = models.get(getModelIdFromUri(uri, col));
String[] columns = ((projection != null) ? projection : CardTemplate.DEFAULT_PROJECTION);
MatrixCursor rv = new MatrixCursor(columns, 1);
try {
JSONArray templates = currentModel.getJSONArray("tmpls");
for (int idx = 0; idx < templates.length(); idx++) {
JSONObject template = templates.getJSONObject(idx);
addTemplateToCursor(template, currentModel, idx + 1, models, rv, columns);
}
} catch (JSONException e) {
throw new IllegalArgumentException("Model is malformed", e);
}
return rv;
}
case MODELS_ID_TEMPLATES_ID:
{
/* Direct access model template with specific ID */
Models models = col.getModels();
int ord = Integer.parseInt(uri.getLastPathSegment());
Model currentModel = models.get(getModelIdFromUri(uri, col));
String[] columns = ((projection != null) ? projection : CardTemplate.DEFAULT_PROJECTION);
MatrixCursor rv = new MatrixCursor(columns, 1);
try {
JSONObject template = getTemplateFromUri(uri, col);
addTemplateToCursor(template, currentModel, ord + 1, models, rv, columns);
} catch (JSONException e) {
throw new IllegalArgumentException("Model is malformed", e);
}
return rv;
}
case SCHEDULE:
{
String[] columns = ((projection != null) ? projection : FlashCardsContract.ReviewInfo.DEFAULT_PROJECTION);
MatrixCursor rv = new MatrixCursor(columns, 1);
long selectedDeckBeforeQuery = col.getDecks().selected();
long deckIdOfTemporarilySelectedDeck = -1;
// the number of scheduled cards to return
int limit = 1;
int selectionArgIndex = 0;
// parsing the selection arguments
if (selection != null) {
// split selection to get arguments like "limit=?"
String[] args = selection.split(",");
for (String arg : args) {
// split arguments into key ("limit") and value ("?")
String[] keyAndValue = arg.split("=");
try {
// check if value is a placeholder ("?"), if so replace with the next value of selectionArgs
String value = "?".equals(keyAndValue[1].trim()) ? selectionArgs[selectionArgIndex++] : keyAndValue[1];
if ("limit".equals(keyAndValue[0].trim())) {
limit = Integer.valueOf(value);
} else if ("deckID".equals(keyAndValue[0].trim())) {
deckIdOfTemporarilySelectedDeck = Long.valueOf(value);
if (!selectDeckWithCheck(col, deckIdOfTemporarilySelectedDeck)) {
// if the provided deckID is wrong, return empty cursor.
return rv;
}
}
} catch (NumberFormatException nfe) {
nfe.printStackTrace();
}
}
}
// retrieve the number of cards provided by the selection parameter "limit"
col.getSched().deferReset();
for (int k = 0; k < limit; k++) {
Card currentCard = col.getSched().getCard();
if (currentCard == null) {
break;
}
int buttonCount = col.getSched().answerButtons(currentCard);
JSONArray buttonTexts = new JSONArray();
for (int i = 0; i < buttonCount; i++) {
buttonTexts.put(col.getSched().nextIvlStr(mContext, currentCard, i + 1));
}
addReviewInfoToCursor(currentCard, buttonTexts, buttonCount, rv, col, columns);
}
if (deckIdOfTemporarilySelectedDeck != -1) {
// if the selected deck was changed
// change the selected deck back to the one it was before the query
col.getDecks().select(selectedDeckBeforeQuery);
}
return rv;
}
case DECKS:
{
List<DeckDueTreeNode> allDecks = col.getSched().deckDueList();
String[] columns = ((projection != null) ? projection : FlashCardsContract.Deck.DEFAULT_PROJECTION);
MatrixCursor rv = new MatrixCursor(columns, allDecks.size());
for (DeckDueTreeNode deck : allDecks) {
long id = deck.getDid();
String name = deck.getFullDeckName();
addDeckToCursor(id, name, getDeckCountsFromDueTreeNode(deck), rv, col, columns);
}
return rv;
}
case DECKS_ID:
{
/* Direct access deck */
String[] columns = ((projection != null) ? projection : FlashCardsContract.Deck.DEFAULT_PROJECTION);
MatrixCursor rv = new MatrixCursor(columns, 1);
List<DeckDueTreeNode> allDecks = col.getSched().deckDueList();
long deckId;
deckId = Long.parseLong(uri.getPathSegments().get(1));
for (DeckDueTreeNode deck : allDecks) {
if (deck.getDid() == deckId) {
addDeckToCursor(deckId, deck.getFullDeckName(), getDeckCountsFromDueTreeNode(deck), rv, col, columns);
return rv;
}
}
return rv;
}
case DECK_SELECTED:
{
long id = col.getDecks().selected();
String name = col.getDecks().name(id);
String[] columns = ((projection != null) ? projection : FlashCardsContract.Deck.DEFAULT_PROJECTION);
MatrixCursor rv = new MatrixCursor(columns, 1);
JSONArray counts = new JSONArray(Arrays.asList(col.getSched().counts()));
addDeckToCursor(id, name, counts, rv, col, columns);
return rv;
}
default:
// Unknown URI type
throw new IllegalArgumentException("uri " + uri + " is not supported");
}
}
use of com.ichi2.anki.CardBrowser.Column.CHANGED in project AnkiChinaAndroid by ankichinateam.
the class CollectionTask method doInBackgroundConfSetSubdecks.
private TaskData doInBackgroundConfSetSubdecks(TaskData param) {
Timber.d("doInBackgroundConfSetSubdecks");
Collection col = getCol();
Object[] data = param.getObjArray();
Deck deck = (Deck) data[0];
DeckConfig conf = (DeckConfig) data[1];
try {
TreeMap<String, Long> children = col.getDecks().children(deck.getLong("id"));
for (Map.Entry<String, Long> entry : children.entrySet()) {
Deck child = col.getDecks().get(entry.getValue());
if (child.getInt("dyn") == 1) {
continue;
}
TaskData newParam = new TaskData(new Object[] { child, conf });
boolean changed = doInBackgroundConfChange(newParam).getBoolean();
if (!changed) {
return new TaskData(false);
}
}
return new TaskData(true);
} catch (JSONException e) {
return new TaskData(false);
}
}
use of com.ichi2.anki.CardBrowser.Column.CHANGED in project AnkiChinaAndroid by ankichinateam.
the class CardTemplateEditorTest method testDeleteTemplateWithGeneratedCards.
/**
* Normal template deletion - with no selective generation should of course work
*/
@SuppressWarnings("PMD.ExcessiveMethodLength")
@Test
public void testDeleteTemplateWithGeneratedCards() {
String modelName = "Basic (and reversed card)";
Model collectionBasicModelOriginal = getCurrentDatabaseModelCopy(modelName);
// Start the CardTemplateEditor with a specific model, and make sure the model starts unchanged
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.putExtra("modelId", collectionBasicModelOriginal.getLong("id"));
ActivityController<CardTemplateEditor> templateEditorController = Robolectric.buildActivity(CardTemplateEditor.class, intent).create().start().resume().visible();
saveControllerForCleanup(templateEditorController);
CardTemplateEditor testEditor = (CardTemplateEditor) templateEditorController.get();
Assert.assertFalse("Model should not have changed yet", testEditor.modelHasChanged());
Assert.assertEquals("Model should have 2 templates now", 2, testEditor.getTempModel().getTemplateCount());
Assert.assertFalse("Ordinal pending add?", TemporaryModel.isOrdinalPendingAdd(testEditor.getTempModel(), 0));
Assert.assertFalse("Ordinal pending add?", TemporaryModel.isOrdinalPendingAdd(testEditor.getTempModel(), 1));
// Create note with forward and back info
Note selectiveGeneratedNote = getCol().newNote(collectionBasicModelOriginal);
selectiveGeneratedNote.setField(0, "TestFront");
selectiveGeneratedNote.setField(1, "TestBack");
getCol().addNote(selectiveGeneratedNote);
Assert.assertEquals("card generation should result in two cards", 2, getModelCardCount(collectionBasicModelOriginal));
// Test if we can delete the template - should be possible - but cancel the delete
ShadowActivity shadowTestEditor = shadowOf(testEditor);
Assert.assertTrue("Unable to click?", shadowTestEditor.clickMenuItem(R.id.action_delete));
advanceRobolectricLooper();
Assert.assertEquals("Did not show dialog about deleting template and it's card?", getQuantityString(R.plurals.card_template_editor_confirm_delete, 1, 1, "Card 1"), getDialogText(true));
clickDialogButton(DialogAction.NEGATIVE, true);
advanceRobolectricLooper();
Assert.assertNotNull("Cannot delete template?", getCol().getModels().getCardIdsForModel(collectionBasicModelOriginal.getLong("id"), new int[] { 0 }));
Assert.assertNotNull("Cannot delete template?", getCol().getModels().getCardIdsForModel(collectionBasicModelOriginal.getLong("id"), new int[] { 1 }));
Assert.assertNull("Can delete both templates?", getCol().getModels().getCardIdsForModel(collectionBasicModelOriginal.getLong("id"), new int[] { 0, 1 }));
Assert.assertEquals("Change in database despite no change?", collectionBasicModelOriginal.toString().trim(), getCurrentDatabaseModelCopy(modelName).toString().trim());
Assert.assertEquals("Model should have 2 templates still", 2, testEditor.getTempModel().getTemplateCount());
// Add a template - click add, click confirm for card add, click confirm again for full sync
shadowTestEditor.clickMenuItem(R.id.action_add);
advanceRobolectricLooper();
Assert.assertTrue("Model should have changed", testEditor.modelHasChanged());
Assert.assertEquals("Change added but not adjusted correctly?", 2, TemporaryModel.getAdjustedAddOrdinalAtChangeIndex(testEditor.getTempModel(), 0));
Assert.assertFalse("Ordinal pending add?", TemporaryModel.isOrdinalPendingAdd(testEditor.getTempModel(), 0));
Assert.assertFalse("Ordinal pending add?", TemporaryModel.isOrdinalPendingAdd(testEditor.getTempModel(), 1));
Assert.assertTrue("Ordinal not pending add?", TemporaryModel.isOrdinalPendingAdd(testEditor.getTempModel(), 2));
Assert.assertTrue("Unable to click?", shadowTestEditor.clickMenuItem(R.id.action_confirm));
advanceRobolectricLooper();
Assert.assertFalse("Model should now be unchanged", testEditor.modelHasChanged());
Assert.assertEquals("card generation should result in three cards", 3, getModelCardCount(collectionBasicModelOriginal));
// reload the model for future comparison after saving the edit
collectionBasicModelOriginal = getCurrentDatabaseModelCopy(modelName);
// Start the CardTemplateEditor back up after saving (which closes the thing...)
intent = new Intent(Intent.ACTION_VIEW);
intent.putExtra("modelId", collectionBasicModelOriginal.getLong("id"));
templateEditorController = Robolectric.buildActivity(CardTemplateEditor.class, intent).create().start().resume().visible();
testEditor = (CardTemplateEditor) templateEditorController.get();
shadowTestEditor = shadowOf(testEditor);
Assert.assertFalse("Model should not have changed yet", testEditor.modelHasChanged());
Assert.assertFalse("Ordinal pending add?", TemporaryModel.isOrdinalPendingAdd(testEditor.getTempModel(), 0));
Assert.assertFalse("Ordinal pending add?", TemporaryModel.isOrdinalPendingAdd(testEditor.getTempModel(), 1));
Assert.assertFalse("Ordinal pending add?", TemporaryModel.isOrdinalPendingAdd(testEditor.getTempModel(), 2));
Assert.assertEquals("Model should have 3 templates now", 3, testEditor.getTempModel().getTemplateCount());
// Add another template - but we work in memory for a while before saving
shadowTestEditor.clickMenuItem(R.id.action_add);
advanceRobolectricLooper();
Assert.assertEquals("Change added but not adjusted correctly?", 3, TemporaryModel.getAdjustedAddOrdinalAtChangeIndex(testEditor.getTempModel(), 0));
Assert.assertTrue("Model should have changed", testEditor.modelHasChanged());
Assert.assertEquals("Model should have 4 templates now", 4, testEditor.getTempModel().getTemplateCount());
Assert.assertFalse("Ordinal pending add?", TemporaryModel.isOrdinalPendingAdd(testEditor.getTempModel(), 0));
Assert.assertFalse("Ordinal pending add?", TemporaryModel.isOrdinalPendingAdd(testEditor.getTempModel(), 1));
Assert.assertFalse("Ordinal pending add?", TemporaryModel.isOrdinalPendingAdd(testEditor.getTempModel(), 2));
Assert.assertTrue("Ordinal not pending add?", TemporaryModel.isOrdinalPendingAdd(testEditor.getTempModel(), 3));
Assert.assertEquals("Change added but not adjusted correctly?", 3, TemporaryModel.getAdjustedAddOrdinalAtChangeIndex(testEditor.getTempModel(), 0));
// Delete two pre-existing templates for real now - but still without saving it out, should work fine
advanceRobolectricLooper();
testEditor.mViewPager.setCurrentItem(0);
Assert.assertTrue("Unable to click?", shadowTestEditor.clickMenuItem(R.id.action_delete));
advanceRobolectricLooper();
Assert.assertEquals("Did not show dialog about deleting template and it's card?", getQuantityString(R.plurals.card_template_editor_confirm_delete, 1, 1, "Card 1"), getDialogText(true));
clickDialogButton(DialogAction.POSITIVE, true);
advanceRobolectricLooper();
advanceRobolectricLooper();
testEditor.mViewPager.setCurrentItem(0);
Assert.assertTrue("Unable to click?", shadowTestEditor.clickMenuItem(R.id.action_delete));
advanceRobolectricLooper();
Assert.assertEquals("Did not show dialog about deleting template and it's card?", getQuantityString(R.plurals.card_template_editor_confirm_delete, 1, 1, "Card 2"), getDialogText(true));
clickDialogButton(DialogAction.POSITIVE, true);
advanceRobolectricLooper();
// - assert can delete any 1 or 2 Card templates but not all
Assert.assertNotNull("Cannot delete template?", getCol().getModels().getCardIdsForModel(collectionBasicModelOriginal.getLong("id"), new int[] { 0 }));
Assert.assertNotNull("Cannot delete template?", getCol().getModels().getCardIdsForModel(collectionBasicModelOriginal.getLong("id"), new int[] { 1 }));
Assert.assertNotNull("Cannot delete template?", getCol().getModels().getCardIdsForModel(collectionBasicModelOriginal.getLong("id"), new int[] { 2 }));
Assert.assertNotNull("Cannot delete two templates?", getCol().getModels().getCardIdsForModel(collectionBasicModelOriginal.getLong("id"), new int[] { 0, 1 }));
Assert.assertNotNull("Cannot delete two templates?", getCol().getModels().getCardIdsForModel(collectionBasicModelOriginal.getLong("id"), new int[] { 0, 2 }));
Assert.assertNotNull("Cannot delete two templates?", getCol().getModels().getCardIdsForModel(collectionBasicModelOriginal.getLong("id"), new int[] { 1, 2 }));
Assert.assertNull("Can delete all templates?", getCol().getModels().getCardIdsForModel(collectionBasicModelOriginal.getLong("id"), new int[] { 0, 1, 2 }));
Assert.assertEquals("Change already in database?", collectionBasicModelOriginal.toString().trim(), getCurrentDatabaseModelCopy(modelName).toString().trim());
Assert.assertEquals("Change added but not adjusted correctly?", 1, TemporaryModel.getAdjustedAddOrdinalAtChangeIndex(testEditor.getTempModel(), 0));
Assert.assertEquals("Change incorrectly pending add?", -1, TemporaryModel.getAdjustedAddOrdinalAtChangeIndex(testEditor.getTempModel(), 1));
Assert.assertEquals("Change incorrectly pending add?", -1, TemporaryModel.getAdjustedAddOrdinalAtChangeIndex(testEditor.getTempModel(), 2));
// Now confirm everything to persist it to the database
Assert.assertTrue("Unable to click?", shadowTestEditor.clickMenuItem(R.id.action_confirm));
advanceRobolectricLooper();
advanceRobolectricLooper();
Assert.assertNotEquals("Change not in database?", collectionBasicModelOriginal.toString().trim(), getCurrentDatabaseModelCopy(modelName).toString().trim());
Assert.assertEquals("Model should have 2 templates now", 2, getCurrentDatabaseModelCopy(modelName).getJSONArray("tmpls").length());
Assert.assertEquals("should be two cards", 2, getModelCardCount(collectionBasicModelOriginal));
}
Aggregations