use of com.ichi2.libanki.template.Template in project Anki-Android by ankidroid.
the class ModelTest method regression_test_pipe.
@Test
@Config(qualifiers = "en")
public void regression_test_pipe() {
Collection col = getCol();
ModelManager mm = col.getModels();
Model basic = mm.byName("Basic");
JSONObject template = basic.getJSONArray("tmpls").getJSONObject(0);
template.put("qfmt", "{{|Front}}{{Front}}{{/Front}}{{Front}}");
try {
// in V16, the "save" throws, in V11, the "add" throws
mm.save(basic, true);
Note note = addNoteUsingBasicModel("foo", "bar");
fail();
} catch (Exception er) {
}
}
use of com.ichi2.libanki.template.Template in project Anki-Android by ankidroid.
the class ModelTest method test_chained_mods.
@Test
public void test_chained_mods() throws ConfirmModSchemaException {
Collection col = getCol();
col.getModels().setCurrent(col.getModels().byName("Cloze"));
Model m = col.getModels().current();
ModelManager mm = col.getModels();
// We replace the default Cloze template
JSONObject t = Models.newTemplate("ChainedCloze");
t.put("qfmt", "{{cloze:text:Text}}");
t.put("afmt", "{{cloze:text:Text}}");
mm.addTemplateModChanged(m, t);
mm.save(m);
col.getModels().remTemplate(m, m.getJSONArray("tmpls").getJSONObject(0));
Note note = col.newNote();
String q1 = "<span style=\"color:red\">phrase</span>";
String a1 = "<b>sentence</b>";
String q2 = "<span style=\"color:red\">en chaine</span>";
String a2 = "<i>chained</i>";
note.setItem("Text", "This {{c1::" + q1 + "::" + a1 + "}} demonstrates {{c1::" + q2 + "::" + a2 + "}} clozes.");
assertEquals(1, col.addNote(note));
String question = note.cards().get(0).q();
/* TODO: chained modifier
assertThat("Question «"+question+"» does not contain the expected string", question, containsString("This <span class=cloze>[sentence]</span> demonstrates <span class=cloze>[chained]</span> clozes.")
);
assertThat(note.cards().get(0).a(), containsString("This <span class=cloze>phrase</span> demonstrates <span class=cloze>en chaine</span> clozes."
));
*/
}
use of com.ichi2.libanki.template.Template in project Anki-Android by Ramblurr.
the class Collection method _renderQA.
public HashMap<String, String> _renderQA(Object[] data, List<String> args) {
// data is [cid, nid, mid, did, ord, tags, flds]
// unpack fields and create dict
String[] flist = Utils.splitFields((String) data[6]);
Map<String, String> fields = new HashMap<String, String>();
long modelId = (Long) data[2];
JSONObject model = mModels.get(modelId);
Map<String, Pair<Integer, JSONObject>> fmap = mModels.fieldMap(model);
for (String fname : fmap.keySet()) {
fields.put(fname, flist[fmap.get(fname).first]);
}
fields.put("Tags", ((String) data[5]).trim());
try {
fields.put("Type", (String) model.get("name"));
fields.put("Deck", mDecks.name((Long) data[3]));
JSONObject template;
if (model.getInt("type") == Sched.MODEL_STD) {
template = model.getJSONArray("tmpls").getJSONObject((Integer) data[4]);
} else {
template = model.getJSONArray("tmpls").getJSONObject(0);
}
fields.put("Card", template.getString("name"));
fields.put("c" + (((Integer) data[4]) + 1), "1");
// render q & a
HashMap<String, String> d = new HashMap<String, String>();
try {
d.put("id", Long.toString((Long) data[0]));
String qfmt = template.getString("qfmt");
String afmt = template.getString("afmt");
String html;
String format;
// runFilter mungeFields for type "q"
Models.fieldParser fparser = new Models.fieldParser(fields);
Matcher m = fClozePattern.matcher(qfmt);
format = m.replaceFirst(String.format(Locale.US, "{{cq:%d:", ((Integer) data[4]) + 1));
m = fAltClozePattern.matcher(format);
format = m.replaceFirst(String.format(Locale.US, "<%%cq:%d:", ((Integer) data[4]) + 1));
html = mModels.getCmpldTemplate(format).execute(fparser);
html = (String) AnkiDroidApp.getHooks().runFilter("mungeQA", html, "q", fields, model, data, this);
d.put("q", html);
// empty cloze?
if (model.getInt("type") == Sched.MODEL_CLOZE) {
if (getModels()._availClozeOrds(model, (String) data[6], false).size() == 0) {
d.put("q", "Please edit this note and add some cloze deletions.");
}
}
fields.put("FrontSide", mMedia.stripAudio(d.get("q")));
// runFilter mungeFields for type "a"
fparser = new Models.fieldParser(fields);
m = fClozePattern.matcher(afmt);
format = m.replaceFirst(String.format(Locale.US, "{{ca:%d:", ((Integer) data[4]) + 1));
m = fAltClozePattern.matcher(format);
format = m.replaceFirst(String.format(Locale.US, "<%%ca:%d:", ((Integer) data[4]) + 1));
html = mModels.getCmpldTemplate(format).execute(fparser);
html = (String) AnkiDroidApp.getHooks().runFilter("mungeQA", html, "a", fields, model, data, this);
d.put("a", html);
// empty cloze?
if (model.getInt("type") == Sched.MODEL_CLOZE) {
if (getModels()._availClozeOrds(model, (String) data[6], false).size() == 0) {
d.put("q", AnkiDroidApp.getAppResources().getString(com.ichi2.anki.R.string.empty_cloze_warning, "<a href=" + HELP_SITE + "#cloze>" + AnkiDroidApp.getAppResources().getString(com.ichi2.anki.R.string.help_cloze) + "</a>"));
}
}
} catch (MustacheException e) {
Resources res = AnkiDroidApp.getAppResources();
String templateError = String.format(TEMPLATE_ERROR, res.getString(R.string.template_error), res.getString(R.string.template_error_detail), e.getMessage(), res.getString(R.string.note_type), model.getString("name"), res.getString(R.string.card_type), template.getString("name"), res.getString(R.string.template_error_fix));
d.put("q", templateError);
d.put("a", templateError);
}
return d;
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
use of com.ichi2.libanki.template.Template in project Anki-Android by Ramblurr.
the class Reviewer method onCreate.
// ----------------------------------------------------------------------------
// ANDROID METHODS
// ----------------------------------------------------------------------------
@Override
protected void onCreate(Bundle savedInstanceState) {
Themes.applyTheme(this);
super.onCreate(savedInstanceState);
// Remove the status bar and title bar
if (mPrefFullscreenReview) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
// Do not hide the title bar in Honeycomb, since it contains the action bar.
if (AnkiDroidApp.SDK_VERSION <= 11) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
}
}
mChangeBorderStyle = Themes.getTheme() == Themes.THEME_ANDROID_LIGHT || Themes.getTheme() == Themes.THEME_ANDROID_DARK;
// The hardware buttons should control the music volume while reviewing.
setVolumeControlStream(AudioManager.STREAM_MUSIC);
Collection col = AnkiDroidApp.getCol();
if (col == null) {
reloadCollection(savedInstanceState);
return;
} else {
mSched = col.getSched();
mCollectionFilename = col.getPath();
mBaseUrl = Utils.getBaseUrl(col.getMedia().getDir());
restorePreferences();
setFullScreen(mPrefFullscreenReview);
registerExternalStorageListener();
if (mNightMode) {
mCurrentBackgroundColor = Themes.getNightModeCardBackground(this);
} else {
mCurrentBackgroundColor = Color.WHITE;
}
mUseQuickUpdate = shouldUseQuickUpdate();
initLayout(R.layout.flashcard);
try {
String[] title = mSched.getCol().getDecks().current().getString("name").split("::");
AnkiDroidApp.getCompat().setTitle(this, title[title.length - 1], mInvertedColors);
} catch (JSONException e) {
throw new RuntimeException(e);
}
AnkiDroidApp.getCompat().setSubtitle(this, "", mInvertedColors);
if (mPrefTextSelection) {
clipboardSetText("");
}
// Load the template for the card
try {
mCardTemplate = Utils.convertStreamToString(getAssets().open("card_template.html"));
} catch (IOException e) {
e.printStackTrace();
}
// Initialize text-to-speech. This is an asynchronous operation.
if (mSpeakText) {
ReadText.initializeTts(this);
}
// Get last whiteboard state
if (mPrefWhiteboard && mCurrentCard != null && MetaDB.getWhiteboardState(this, mCurrentCard.getDid()) == 1) {
mShowWhiteboard = true;
mWhiteboard.setVisibility(View.VISIBLE);
}
// Load the first card and start reviewing. Uses the answer card
// task to load a card, but since we send null
// as the card to answer, no card will be answered.
DeckTask.launchDeckTask(DeckTask.TASK_TYPE_ANSWER_CARD, mAnswerCardHandler, new DeckTask.TaskData(mSched, null, 0));
// Since we aren't actually answering a card, decrement the rep count
mSched.setReps(mSched.getReps() - 1);
}
}
use of com.ichi2.libanki.template.Template in project AnkiChinaAndroid by ankichinateam.
the class NoteEditor method onCollectionLoaded.
// Finish initializing the activity after the collection has been correctly loaded
@Override
protected void onCollectionLoaded(Collection col) {
super.onCollectionLoaded(col);
Intent intent = getIntent();
Timber.d("NoteEditor() onCollectionLoaded: caller: %d", mCaller);
registerExternalStorageListener();
View mainView = findViewById(android.R.id.content);
mToolbar = findViewById(R.id.editor_toolbar);
mToolbar.setFormatListener(formatter -> {
View currentFocus = getCurrentFocus();
if (!(currentFocus instanceof FieldEditText)) {
return;
}
modifyCurrentSelection(formatter, (FieldEditText) currentFocus);
});
enableToolbar(mainView);
mFieldsLayoutContainer = findViewById(R.id.CardEditorEditFieldsLayout);
mTagsButton = findViewById(R.id.CardEditorTagText);
mCardsButton = findViewById(R.id.CardEditorCardsText);
mCardsButton.setOnClickListener(v -> {
Timber.i("NoteEditor:: Cards button pressed. Opening template editor");
showCardTemplateEditor();
});
mAedictIntent = false;
mCurrentEditedCard = null;
switch(mCaller) {
case CALLER_NOCALLER:
Timber.e("no caller could be identified, closing");
finishWithoutAnimation();
return;
case CALLER_REVIEWER:
mCurrentEditedCard = AbstractFlashcardViewer.getEditorCard();
if (mCurrentEditedCard == null) {
finishWithoutAnimation();
return;
}
mEditorNote = mCurrentEditedCard.note();
mAddNote = false;
break;
case CALLER_STUDYOPTIONS:
case CALLER_DECKPICKER:
case CALLER_REVIEWER_ADD:
case CALLER_CARDBROWSER_ADD:
case CALLER_CARDEDITOR:
mAddNote = true;
break;
case CALLER_CARDBROWSER_EDIT:
mCurrentEditedCard = CardBrowser.sCardBrowserCard;
if (mCurrentEditedCard == null) {
finishWithoutAnimation();
return;
}
mEditorNote = mCurrentEditedCard.note();
mAddNote = false;
break;
case CALLER_CARDEDITOR_INTENT_ADD:
{
fetchIntentInformation(intent);
if (mSourceText == null) {
finishWithoutAnimation();
return;
}
if ("Aedict Notepad".equals(mSourceText[0]) && addFromAedict(mSourceText[1])) {
finishWithoutAnimation();
return;
}
mAddNote = true;
break;
}
default:
break;
}
// Note type Selector
mNoteTypeSpinner = findViewById(R.id.note_type_spinner);
ArrayList<Model> models = getCol().getModels().all();
Collections.sort(models, NamedJSONComparator.instance);
final ArrayList<String> modelNames = new ArrayList<>(models.size());
mAllModelIds = new ArrayList<>(models.size());
for (JSONObject m : models) {
modelNames.add(m.getString("name"));
mAllModelIds.add(m.getLong("id"));
}
ArrayAdapter<String> noteTypeAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, modelNames);
mNoteTypeSpinner.setAdapter(noteTypeAdapter);
noteTypeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Deck Selector
TextView deckTextView = findViewById(R.id.CardEditorDeckText);
// If edit mode and more than one card template distinguish between "Deck" and "Card deck"
if (!mAddNote && mEditorNote.model().getJSONArray("tmpls").length() > 1) {
deckTextView.setText(R.string.CardEditorCardDeck);
}
mNoteDeckSpinner = findViewById(R.id.note_deck_spinner);
ArrayList<Deck> decks = getCol().getDecks().all();
Collections.sort(decks, DeckComparator.instance);
final ArrayList<String> deckNames = new ArrayList<>(decks.size());
mAllDeckIds = new ArrayList<>(decks.size());
for (Deck d : decks) {
// add current deck and all other non-filtered decks to deck list
long thisDid = d.getLong("id");
if (d.getInt("dyn") == 0 || (!mAddNote && mCurrentEditedCard != null && mCurrentEditedCard.getDid() == thisDid)) {
deckNames.add(d.getString("name"));
mAllDeckIds.add(thisDid);
}
}
ArrayAdapter<String> noteDeckAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, deckNames);
mNoteDeckSpinner.setAdapter(noteDeckAdapter);
noteDeckAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mNoteDeckSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
// Timber.i("NoteEditor:: onItemSelected() fired on mNoteDeckSpinner with pos = %d", pos);
mCurrentDid = mAllDeckIds.get(pos);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// Do Nothing
}
});
mCurrentDid = intent.getLongExtra(EXTRA_DID, mCurrentDid);
setDid(mEditorNote);
setNote(mEditorNote, FieldChangeType.onActivityCreation(shouldReplaceNewlines()));
if (mAddNote) {
mNoteTypeSpinner.setOnItemSelectedListener(new SetNoteTypeListener());
setTitle(R.string.menu_add_note);
// set information transferred by intent
String contents = null;
String[] tags = intent.getStringArrayExtra(EXTRA_TAGS);
if (mSourceText != null) {
if (mAedictIntent && (mEditFields.size() == 3) && mSourceText[1].contains("[")) {
contents = mSourceText[1].replaceFirst("\\[", "\u001f" + mSourceText[0] + "\u001f");
contents = contents.substring(0, contents.length() - 1);
} else if (mEditFields.size() > 0) {
mEditFields.get(0).setText(mSourceText[0]);
if (mEditFields.size() > 1) {
mEditFields.get(1).setText(mSourceText[1]);
}
}
} else {
contents = intent.getStringExtra(EXTRA_CONTENTS);
}
if (contents != null) {
setEditFieldTexts(contents);
}
if (tags != null) {
setTags(tags);
}
} else {
mNoteTypeSpinner.setOnItemSelectedListener(new EditNoteTypeListener());
setTitle(R.string.cardeditor_title_edit_card);
}
findViewById(R.id.CardEditorTagButton).setOnClickListener(v -> {
Timber.i("NoteEditor:: Tags button pressed... opening tags editor");
showTagsDialog();
});
if (!mAddNote && mCurrentEditedCard != null) {
Timber.i("onCollectionLoaded() Edit note activity successfully started with card id %d", mCurrentEditedCard.getId());
}
if (mAddNote) {
Timber.i("onCollectionLoaded() Edit note activity successfully started in add card mode with node id %d", mEditorNote.getId());
}
// don't open keyboard if not adding note
if (!mAddNote) {
this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
}
// set focus to FieldEditText 'first' on startup like Anki desktop
if (mEditFields != null && !mEditFields.isEmpty()) {
mEditFields.getFirst().requestFocus();
}
}
Aggregations