0
0
mirror of https://github.com/ankidroid/Anki-Android.git synced 2024-09-20 03:52:15 +02:00

add card browser

This commit is contained in:
nobnago 2011-02-08 20:56:39 +01:00
parent 60c850cd32
commit fde5066033
14 changed files with 269 additions and 17 deletions

View File

@ -4,6 +4,7 @@
~ Copyright (c) 2009 Nicolas Raoul <nicolas.raoul@gmail.com>
~ Copyright (c) 2009 Edu Zamora <edu.zasu@gmail.com>
~ Copyright (c) 2009 Casey Link <unnamedrambler@gmail.com>
~ Copyright (c) 2011 Norbert Nagold <norbert.nagold@gmail.com>
~
~ This program is free software; you can redistribute it and/or modify it under
~ the terms of the GNU General Public License as published by the Free Software
@ -40,6 +41,9 @@
<activity android:name="DeckPicker"
android:label="DeckPicker"
android:configChanges="keyboardHidden|orientation"/>
<activity android:name="CardBrowser"
android:label="@string/card_browser_title"
android:configChanges="keyboardHidden|orientation"/>
<activity android:name="PersonalDeckPicker"
android:label="@string/personaldeckpicker_title"
android:configChanges="keyboardHidden|orientation"/>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<EditText
android:id="@+id/card_browser_search"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:lines="1"
android:hint="@string/downloaddeck_search"/>
<ListView android:id="@+id/card_browser_list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:fastScrollEnabled="true"/>
</LinearLayout>

18
res/layout/card_item.xml Normal file
View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/card_question"
android:layout_width="0dip"
android:layout_height="fill_parent"
android:layout_weight="1"
/>
<TextView
android:id="@+id/card_answer"
android:layout_width="0dip"
android:layout_height="fill_parent"
android:layout_weight="1"
/>
</LinearLayout>

View File

@ -178,13 +178,21 @@
android:textOn="@string/cram"
android:layout_marginBottom="1.5dip"/>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<CheckBox android:id="@+id/studyoptions_night_mode"
android:layout_width="wrap_content"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/studyoptions_night_mode"
android:layout_marginLeft="4dip"
android:layout_weight="1"
android:textSize="14dip"/>
<Button android:id="@+id/studyoptions_card_browser"
android:layout_height="fill_parent"
android:layout_width="0dip"
android:layout_weight="1"
android:text="card browser"/>
</LinearLayout>
</LinearLayout>

View File

@ -187,7 +187,9 @@
<string name="select_card_model">Select Card Model</string>
<string name="select">Select</string>
<!-- CardBrowser -->
<string name="card_browser_title">Card Browser</string>
<string name="card_browser_load">Loading cards</string>
<!-- AnkiDroid.java -->
<!--<string name="loading_new_card">Loading new card...</string>-->

View File

@ -0,0 +1,128 @@
package com.ichi2.anki;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.AdapterView.OnItemClickListener;
import java.util.ArrayList;
import java.util.HashMap;
public class CardBrowser extends Activity {
private ArrayList<HashMap<String, String>> mCards;
private ArrayList<HashMap<String, String>> mAllCards;
private ListView mCardsListView;
private SimpleAdapter mCardsAdapter;
private EditText mSearchEditText;
private ProgressDialog mProgressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.card_browser);
mCards = new ArrayList<HashMap<String, String>>();
mAllCards = new ArrayList<HashMap<String, String>>();
mCardsListView = (ListView) findViewById(R.id.card_browser_list);
mCardsAdapter = new SimpleAdapter(this, mCards,
R.layout.card_item, new String[] { "question", "answer" }, new int[] {
R.id.card_question, R.id.card_answer });
mCardsAdapter.setViewBinder(new SimpleAdapter.ViewBinder() {
@Override
public boolean setViewValue(View arg0, Object arg1, String arg2) {
return false;
}
});
mCardsListView.setAdapter(mCardsAdapter);
mCardsListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent editCard = new Intent(CardBrowser.this, CardEditor.class);
editCard.putExtra("card", Long.parseLong(mCards.get(position).get("id")));
startActivityForResult(editCard, 0);
}
});
mSearchEditText = (EditText) findViewById(R.id.card_browser_search);
mSearchEditText.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
mCards.clear();
for (int i = 0; i < mAllCards.size(); i++) {
if (mAllCards.get(i).get("question").toLowerCase().indexOf(mSearchEditText.getText().toString().toLowerCase()) != -1 ||
mAllCards.get(i).get("answer").toLowerCase().indexOf(mSearchEditText.getText().toString().toLowerCase()) != -1) {
mCards.add(mAllCards.get(i));
}
}
mCardsAdapter.notifyDataSetChanged();
}
public void beforeTextChanged(CharSequence s, int start, int count, int after){}
public void onTextChanged(CharSequence s, int start, int before, int count){}
});
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
getCards();
}
private void getCards() {
DeckTask.launchDeckTask(DeckTask.TASK_LOAD_CARDS, mLoadCardsHandler, new DeckTask.TaskData(AnkiDroidApp.deck(), "answer"));
}
DeckTask.TaskListener mLoadCardsHandler = new DeckTask.TaskListener() {
@Override
public void onPreExecute() {
mProgressDialog = ProgressDialog.show(CardBrowser.this, "", getResources().getString(R.string.card_browser_load), true);
}
@Override
public void onPostExecute(DeckTask.TaskData result) {
mAllCards.clear();
ArrayList<String[]> allCards = new ArrayList<String[]>();
allCards.addAll(result.getAllCards());
for (String[] item : allCards) {
HashMap<String, String> data = new HashMap<String, String>();
data.put("id", item[0]);
data.put("question", item[1]);
data.put("answer", item[2]);
mAllCards.add(data);
}
mCardsAdapter.notifyDataSetChanged();
mCards.clear();
mCards.addAll(mAllCards);
// This verification would not be necessary if onConfigurationChanged it's executed correctly (which seems
// that emulator does not do)
if (mProgressDialog.isShowing()) {
try {
mProgressDialog.dismiss();
} catch (Exception e) {
Log.e(AnkiDroidApp.TAG, "onPostExecute - Dialog dismiss Exception = " + e.getMessage());
}
}
}
@Override
public void onProgressUpdate(DeckTask.TaskData... values) {
}
};
}

View File

@ -77,8 +77,8 @@ public class CardEditor extends Activity {
mSave = (Button) findViewById(R.id.CardEditorSaveButton);
mCancel = (Button) findViewById(R.id.CardEditorCancelButton);
mEditorCard = Reviewer.getEditorCard();
mEditorCard = AnkiDroidApp.deck().cardFromId(getIntent().getExtras().getLong("card"));
// Card -> FactID -> FieldIDs -> FieldModels
Fact cardFact = mEditorCard.getFact();

View File

@ -2989,6 +2989,31 @@ public class Deck {
}
public ArrayList<String[]> getAllCards(String order) {
ArrayList<String[]> allCards = new ArrayList<String[]>();
Cursor cur = null;
try {
cur = getDB().getDatabase().rawQuery("SELECT id, question, answer FROM cards ORDER BY " + order, null);
while (cur.moveToNext()) {
String[] data = new String[3];
data[0] = Long.toString(cur.getLong(0));
data[1] = Utils.stripHTML(cur.getString(1));
data[2] = Utils.stripHTML(cur.getString(2));
allCards.add(data);
}
} catch (SQLException e) {
Log.e(AnkiDroidApp.TAG, "getAllCards: " + e.toString());
throw new RuntimeException(e);
} finally {
if (cur != null && !cur.isClosed()) {
cur.close();
}
}
return allCards;
}
/*
* Tags: adding/removing in bulk*********************************************************
*/

View File

@ -17,6 +17,9 @@
package com.ichi2.anki;
import java.util.ArrayList;
import java.util.HashMap;
import android.database.CursorIndexOutOfBoundsException;
import android.database.SQLException;
import android.os.AsyncTask;
@ -35,6 +38,7 @@ public class DeckTask extends AsyncTask<DeckTask.TaskData, DeckTask.TaskData, De
public static final int TASK_TYPE_UPDATE_FACT = 5;
public static final int TASK_TYPE_UNDO = 6;
public static final int TASK_TYPE_REDO = 7;
public static final int TASK_LOAD_CARDS = 8;
/**
* Possible outputs trying to load a deck.
@ -116,7 +120,10 @@ public class DeckTask extends AsyncTask<DeckTask.TaskData, DeckTask.TaskData, De
return doInBackgroundUndo(params);
case TASK_TYPE_REDO:
return doInBackgroundRedo(params);
return doInBackgroundRedo(params);
case TASK_LOAD_CARDS:
return doInBackgroundLoadCards(params);
default:
return null;
@ -317,7 +324,17 @@ public class DeckTask extends AsyncTask<DeckTask.TaskData, DeckTask.TaskData, De
return null;
}
private TaskData doInBackgroundLoadCards(TaskData... params) {
Deck deck = params[0].getDeck();
String order = params[0].getOrder();
Log.i(AnkiDroidApp.TAG, "doInBackgroundLoadCards");
return new TaskData(deck.getAllCards(order));
}
public static interface TaskListener {
public void onPreExecute();
@ -337,6 +354,8 @@ public class DeckTask extends AsyncTask<DeckTask.TaskData, DeckTask.TaskData, De
private boolean previousCardLeech; // answer card resulted in card marked as leech
private boolean previousCardSuspended; // answer card resulted in card marked as leech and suspended
private boolean mLastCardInQueue;
private ArrayList<String[]> mAllCards;
private String mOrder;
public TaskData(int value, Deck deck, Card card) {
@ -362,6 +381,12 @@ public class DeckTask extends AsyncTask<DeckTask.TaskData, DeckTask.TaskData, De
}
public TaskData(ArrayList<String[]> allCards) {
mAllCards = new ArrayList<String[]>();
mAllCards.addAll(allCards);
}
public TaskData(Card card, boolean markedLeech, boolean suspendedLeech, boolean lastCardInQueue) {
mCard = card;
previousCardLeech = markedLeech;
@ -370,6 +395,12 @@ public class DeckTask extends AsyncTask<DeckTask.TaskData, DeckTask.TaskData, De
}
public TaskData(Deck deck, String order) {
mDeck = deck;
mOrder = order;
}
public TaskData(int value) {
mInteger = value;
}
@ -385,6 +416,16 @@ public class DeckTask extends AsyncTask<DeckTask.TaskData, DeckTask.TaskData, De
}
public String getOrder() {
return mOrder;
}
public ArrayList<String[]> getAllCards() {
return mAllCards;
}
public Card getCard() {
return mCard;
}

View File

@ -131,8 +131,6 @@ public class Reviewer extends Activity {
private static final int HQIA_DO_SHOW = 1;
private static final int HQIA_CARD_MODEL = 2;
private static Card sEditorCard; // To be assigned as the currentCard or a new card to be sent to and from editor
private static boolean sDisplayAnswer = false; // Indicate if "show answer" button has been pressed
/** The percentage of the absolute font size specified in the deck. */
@ -761,8 +759,9 @@ public class Reviewer extends Activity {
cramEditWarning.show();
return false;
} else {
sEditorCard = mCurrentCard;
Intent editCard = new Intent(Reviewer.this, CardEditor.class);
editCard.putExtra("card", mCurrentCard.getId());
startActivityForResult(editCard, EDIT_CURRENT_CARD);
return true;
}
@ -1560,11 +1559,6 @@ public class Reviewer extends Activity {
}
public static Card getEditorCard() {
return sEditorCard;
}
private int getAvailableWidthInCard() {
// The width available is equals to
// the screen's width divided by the default scale factor used by the WebView, because this scale factor will be

View File

@ -99,6 +99,7 @@ public class StudyOptions extends Activity {
private static final int DOWNLOAD_SHARED_DECK = 4;
private static final int REPORT_ERROR = 5;
private static final int ADD_FACT = 6;
private static final int BROWSE_CARDS = 7;
/**
* Constants for selecting which content view to display
@ -183,6 +184,7 @@ public class StudyOptions extends Activity {
private EditText mEditSessionTime;
private EditText mEditSessionQuestions;
private CheckBox mNightMode;
private Button mCardBrowser;
/**
* UI elements for "More Options" dialog
@ -276,6 +278,9 @@ public class StudyOptions extends Activity {
case R.id.studyoptions_download_deck:
showDownloadSelector();
return;
case R.id.studyoptions_card_browser:
openCardBrowser();
return;
default:
return;
}
@ -564,6 +569,7 @@ public class StudyOptions extends Activity {
mButtonStart = (Button) mStudyOptionsView.findViewById(R.id.studyoptions_start);
mToggleCram = (ToggleButton) mStudyOptionsView.findViewById(R.id.studyoptions_cram);
mCardBrowser = (Button) mStudyOptionsView.findViewById(R.id.studyoptions_card_browser);
mTextReviewsDue = (TextView) mStudyOptionsView.findViewById(R.id.studyoptions_reviews_due);
mTextNewToday = (TextView) mStudyOptionsView.findViewById(R.id.studyoptions_new_today);
@ -587,7 +593,8 @@ public class StudyOptions extends Activity {
mButtonStart.setOnClickListener(mButtonClickListener);
mToggleCram.setOnClickListener(mButtonClickListener);
mCardBrowser.setOnClickListener(mButtonClickListener);
mEditNewPerDay.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
Deck deck = AnkiDroidApp.deck();
@ -1112,6 +1119,14 @@ public class StudyOptions extends Activity {
// Log.i(AnkiDroidApp.TAG, "openDeckPicker - Ending");
}
private void openCardBrowser() {
Intent cardBrowser = new Intent(StudyOptions.this, CardBrowser.class);
cardBrowser.putExtra("deckFilename", mDeckFilename);
startActivityForResult(cardBrowser, BROWSE_CARDS);
}
public void openPersonalDeckPicker() {
if (AnkiDroidApp.isUserLoggedIn()) {
if (AnkiDroidApp.deck() != null)// && sdCardAvailable)

0
tools/comment-logs.sh Executable file → Normal file
View File

0
tools/translation-rates.sh Executable file → Normal file
View File

0
tools/uncomment-logs.sh Executable file → Normal file
View File