use of com.ichi2.anki.R in project AnkiChinaAndroid by ankichinateam.
the class ModelFieldEditor method addFieldDialog.
// ----------------------------------------------------------------------------
// CONTEXT MENU DIALOGUES
// ----------------------------------------------------------------------------
/*
* Creates a dialog to create a field
*/
private void addFieldDialog() {
mFieldNameInput = new EditText(this);
mFieldNameInput.setSingleLine(true);
new MaterialDialog.Builder(this).title(R.string.model_field_editor_add).positiveText(R.string.dialog_ok).customView(mFieldNameInput, true).onPositive((dialog, which) -> {
String fieldName = mFieldNameInput.getText().toString().replaceAll("[\\n\\r]", "");
if (fieldName.length() == 0) {
UIUtils.showThemedToast(this, getResources().getString(R.string.toast_empty_name), true);
} else if (containsField(fieldName)) {
UIUtils.showThemedToast(this, getResources().getString(R.string.toast_duplicate_field), true);
} else {
// Name is valid, now field is added
changeHandler listener = changeFieldHandler();
try {
mCol.modSchema();
CollectionTask.launchCollectionTask(ADD_FIELD, listener, new TaskData(new Object[] { mMod, fieldName }));
} catch (ConfirmModSchemaException e) {
// Create dialogue to for schema change
ConfirmationDialog c = new ConfirmationDialog();
c.setArgs(getResources().getString(R.string.full_sync_confirmation));
Runnable confirm = () -> {
mCol.modSchemaNoCheck();
String fieldName1 = mFieldNameInput.getText().toString().replaceAll("[\\n\\r]", "");
CollectionTask.launchCollectionTask(ADD_FIELD, listener, new TaskData(new Object[] { mMod, fieldName1 }));
dismissContextMenu();
};
c.setConfirm(confirm);
c.setCancel(mConfirmDialogCancel);
ModelFieldEditor.this.showDialogFragment(c);
}
mCol.getModels().update(mMod);
fullRefreshList();
}
}).negativeText(R.string.dialog_cancel).show();
}
use of com.ichi2.anki.R in project AnkiChinaAndroid by ankichinateam.
the class ZipFile method exportFiltered.
private JSONObject exportFiltered(ZipFile z, String path, Context context) throws IOException, JSONException, ImportExportException {
// export into the anki2 file
String colfile = path.replace(".apkg", ".anki2");
super.exportInto(colfile, context);
z.write(colfile, CollectionHelper.COLLECTION_FILENAME);
// and media
prepareMedia();
JSONObject media = _exportMedia(z, mMediaFiles, mCol.getMedia().dir());
// tidy up intermediate files
SQLiteDatabase.deleteDatabase(new File(colfile));
SQLiteDatabase.deleteDatabase(new File(path.replace(".apkg", ".media.ad.db2")));
String tempPath = path.replace(".apkg", ".media");
File file = new File(tempPath);
if (file.exists()) {
String deleteCmd = "rm -r " + tempPath;
Runtime runtime = Runtime.getRuntime();
try {
runtime.exec(deleteCmd);
} catch (IOException e) {
}
}
return media;
}
use of com.ichi2.anki.R in project AnkiChinaAndroid by ankichinateam.
the class Sched method _fillRev.
@Override
protected boolean _fillRev(boolean allowSibling) {
if (!mRevQueue.isEmpty()) {
return true;
}
if (mRevCount == 0) {
return false;
}
SupportSQLiteDatabase db = mCol.getDb().getDatabase();
while (!mRevDids.isEmpty()) {
long did = mRevDids.getFirst();
int lim = Math.min(mQueueLimit, _deckRevLimit(did));
Cursor cur = null;
if (lim != 0) {
mRevQueue.clear();
// fill the queue with the current did
try {
/* Difference with upstream: we take current card into account.
*
* When current card is answered, the card is not due anymore, so does not belong to the queue.
* Furthermore, _burySiblings ensure that the siblings of the current cards are removed from the
* queue to ensure same day spacing. We simulate this action by ensuring that those siblings are not
* filled, except if we know there are cards and we didn't find any non-sibling card. This way, the
* queue is not empty if it should not be empty (important for the conditional belows), but the
* front of the queue contains distinct card.
*/
String idName = (allowSibling) ? "id" : "nid";
long id = (allowSibling) ? currentCardId() : currentCardNid();
cur = db.query("SELECT id FROM cards WHERE did = ? AND queue = " + Consts.QUEUE_TYPE_REV + " AND due <= ?" + " AND " + idName + " != ? LIMIT ?", new Object[] { did, mToday, id, lim });
while (cur.moveToNext()) {
mRevQueue.add(cur.getLong(0));
}
} finally {
if (cur != null && !cur.isClosed()) {
cur.close();
}
}
if (!mRevQueue.isEmpty()) {
// ordering
if (mCol.getDecks().get(did).getInt("dyn") != 0) {
// dynamic decks need due order preserved
// Note: libanki reverses mRevQueue and returns the last element in _getRevCard().
// AnkiDroid differs by leaving the queue intact and returning the *first* element
// in _getRevCard().
} else {
Random r = new Random();
r.setSeed(mToday);
mRevQueue.shuffle(r);
}
// is the current did empty?
if (mRevQueue.size() < lim) {
mRevDids.remove();
}
return true;
}
}
// nothing left in the deck; move to next
mRevDids.remove();
}
// Since we didn't get a card and the count is non-zero, we
// need to check again for any cards that were removed from
// the queue but not buried
_resetRev();
return _fillRev(true);
}
use of com.ichi2.anki.R in project AnkiChinaAndroid by ankichinateam.
the class Syncer method mergeModels.
private void mergeModels(JSONArray rchg) throws UnexpectedSchemaChange {
for (int i = 0; i < rchg.length(); i++) {
Model r = new Model(rchg.getJSONObject(i));
Model l = mCol.getModels().get(r.getLong("id"));
// if missing locally or server is newer, update
if (l == null || r.getLong("mod") > l.getLong("mod")) {
// syncing algorithm should handle this in a better way.
if (l != null) {
if (l.getJSONArray("flds").length() != r.getJSONArray("flds").length()) {
throw new UnexpectedSchemaChange();
}
if (l.getJSONArray("tmpls").length() != r.getJSONArray("tmpls").length()) {
throw new UnexpectedSchemaChange();
}
}
mCol.getModels().update(r);
}
}
}
use of com.ichi2.anki.R in project AnkiChinaAndroid by ankichinateam.
the class Syncer method newerRows.
private ArrayList<Object[]> newerRows(JSONArray data, String table, int modIdx) {
long[] ids = new long[data.length()];
for (int i = 0; i < data.length(); i++) {
ids[i] = data.getJSONArray(i).getLong(0);
}
HashMap<Long, Long> lmods = new HashMap<>();
Cursor cur = null;
try {
cur = mCol.getDb().getDatabase().query("SELECT id, mod FROM " + table + " WHERE id IN " + Utils.ids2str(ids) + " AND " + usnLim(), null);
while (cur.moveToNext()) {
lmods.put(cur.getLong(0), cur.getLong(1));
}
} finally {
if (cur != null && !cur.isClosed()) {
cur.close();
}
}
ArrayList<Object[]> update = new ArrayList<>();
for (int i = 0; i < data.length(); i++) {
JSONArray r = data.getJSONArray(i);
if (!lmods.containsKey(r.getLong(0)) || lmods.get(r.getLong(0)) < r.getLong(modIdx)) {
update.add(Utils.jsonArray2Objects(r));
}
}
mCol.log(table, data);
return update;
}
Aggregations