Search in sources :

Example 16 with CARD

use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.

the class CardBrowser method removeNotesView.

/**
 * Removes cards from view. Doesn't delete them in model (database).
 */
private void removeNotesView(Card[] cards, boolean reorderCards) {
    List<Long> cardIds = new ArrayList<>(cards.length);
    for (Card c : cards) {
        cardIds.add(c.getId());
    }
    removeNotesView(cardIds, reorderCards);
}
Also used : ArrayList(java.util.ArrayList) Card(com.ichi2.libanki.Card)

Example 17 with CARD

use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.

the class CardTemplatePreviewer method getDummyCard.

/**
 * Get a dummy card
 */
@Nullable
protected Card getDummyCard(Model model, int ordinal) {
    Timber.d("getDummyCard() Creating dummy note for ordinal %s", ordinal);
    if (model == null) {
        return null;
    }
    Note n = getCol().newNote(model);
    ArrayList<String> fieldNames = Models.fieldNames(model);
    for (int i = 0; i < fieldNames.size() && i < n.getFields().length; i++) {
        n.setField(i, fieldNames.get(i));
    }
    try {
        JSONObject template = model.getJSONArray("tmpls").getJSONObject(ordinal);
        PreviewerCard card = (PreviewerCard) getCol().getNewLinkedCard(new PreviewerCard(getCol()), n, template, 1, 0, false);
        card.setNote(n);
        return card;
    } catch (Exception e) {
        Timber.e("getDummyCard() unable to create card");
    }
    return null;
}
Also used : JSONObject(com.ichi2.utils.JSONObject) Note(com.ichi2.libanki.Note) IOException(java.io.IOException) Nullable(androidx.annotation.Nullable)

Example 18 with CARD

use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.

the class StudyOptionsFragment method getCollectionTaskListener.

/**
 * Returns a listener that rebuilds the interface after execute.
 *
 * @param refreshDecklist If true, the listener notifies the parent activity to update its deck list
 *                        to reflect the latest values.
 */
private TaskListener getCollectionTaskListener(final boolean refreshDecklist) {
    return new TaskListener() {

        @Override
        public void onPreExecute() {
        }

        @Override
        public void onPostExecute(TaskData result) {
            dismissProgressDialog();
            if (result != null) {
                // Get the return values back from the AsyncTask
                Object[] obj = result.getObjArray();
                int newCards = (Integer) obj[0];
                int lrnCards = (Integer) obj[1];
                int revCards = (Integer) obj[1] + (Integer) obj[2];
                int totalNew = (Integer) obj[3];
                int totalCards = (Integer) obj[4];
                Timber.i("start refresh list data:" + newCards + "," + lrnCards + "," + revCards + "," + totalNew + "," + totalCards);
                // Don't do anything if the fragment is no longer attached to it's Activity or col has been closed
                if (getActivity() == null) {
                    Timber.e("StudyOptionsFragment.mRefreshFragmentListener :: can't refresh");
                    return;
                }
                // #5506 If we have no view, short circuit all UI logic
                if (mStudyOptionsView == null) {
                    tryOpenCramDeckOptions();
                    return;
                }
                // Reinitialize controls incase changed to filtered deck
                initAllContentViews(mStudyOptionsView);
                // Set the deck name
                String fullName;
                Deck deck = getCol().getDecks().current();
                // Main deck name
                fullName = deck.getString("name");
                String[] name = Decks.path(fullName);
                StringBuilder nameBuilder = new StringBuilder();
                if (name.length > 0) {
                    nameBuilder.append(name[name.length - 1]);
                }
                // if (name.length > 1) {
                // nameBuilder.append("\n").append(name[1]);
                // }
                // if (name.length > 3) {
                // nameBuilder.append("...");
                // }
                // if (name.length > 2) {
                // nameBuilder.append("\n").append(name[name.length - 1]);
                // }
                // mTextDeckName.setText(nameBuilder.toString());
                mDeckListAdapter.mTextDeckName = nameBuilder.toString();
                if (tryOpenCramDeckOptions()) {
                    return;
                }
                // Switch between the empty view, the ordinary view, and the "congratulations" view
                boolean isDynamic = deck.optInt("dyn", 0) != 0;
                if (totalCards == 0 && !isDynamic) {
                    mCurrentContentView = CONTENT_EMPTY;
                    mDeckListAdapter.mDeckInfoLayoutVisible = View.VISIBLE;
                    mDeckListAdapter.mTextCongratsMessageVisible = View.VISIBLE;
                    // mDeckListAdapter.mTextCongratsMessage=getString(R.string.studyoptions_empty);
                    mDeckListAdapter.mButtonStartEnable = false;
                    mDeckListAdapter.mTextButtonStart = getString(R.string.studyoptions_start);
                } else if (newCards + lrnCards + revCards == 0) {
                    mCurrentContentView = CONTENT_CONGRATS;
                    if (!isDynamic) {
                        mDeckListAdapter.mDeckInfoLayoutVisible = View.GONE;
                        mDeckListAdapter.mButtonStartEnable = true;
                        mDeckListAdapter.mTextButtonStart = getString(R.string.add_today_study_amount);
                    } else {
                        mDeckListAdapter.mButtonStartEnable = true;
                        mDeckListAdapter.mTextButtonStart = getString(R.string.add_today_study_amount);
                    }
                    mDeckListAdapter.mTextCongratsMessageVisible = View.VISIBLE;
                // mDeckListAdapter.mTextCongratsMessage=getCol().getSched().finishedMsg(getActivity()).toString();
                // mTextCongratsMessage.setText(getCol().getSched().finishedMsg(getActivity()));
                } else {
                    mCurrentContentView = CONTENT_STUDY_OPTIONS;
                    mDeckListAdapter.mDeckInfoLayoutVisible = View.VISIBLE;
                    mDeckListAdapter.mTextCongratsMessageVisible = View.GONE;
                    mDeckListAdapter.mButtonStartEnable = true;
                    mDeckListAdapter.mTextButtonStart = getString(R.string.studyoptions_start);
                }
                mDeckListAdapter.setButtonStartClickListener(mButtonClickListener);
                mDeckListAdapter.setSelfStudyClickListener(mSelfStudyListener);
                // Set deck description
                String desc;
                if (isDynamic) {
                    desc = getResources().getString(R.string.dyn_deck_desc);
                } else {
                    desc = "";
                // desc = getCol().getDecks().getActualDescription();
                }
                if (desc.length() > 0) {
                    mDeckListAdapter.mTextDeckDescription = desc;
                    mDeckListAdapter.mTextDeckDescriptionVisible = View.VISIBLE;
                // mTextDeckDescription.setText(formatDescription(desc));
                // mTextDeckDescription.setVisibility(View.VISIBLE);
                } else {
                    mDeckListAdapter.mTextDeckDescriptionVisible = View.GONE;
                }
                // Set new/learn/review card counts
                mDeckListAdapter.mTextTodayNew = String.valueOf(newCards);
                mDeckListAdapter.mTextTodayRev = String.valueOf(revCards);
                // Set the total number of new cards in deck
                if (totalNew < NEW_CARD_COUNT_TRUNCATE_THRESHOLD) {
                // if it hasn't been truncated by libanki then just set it usually
                // mTextNewTotal.setText(String.valueOf(totalNew));
                } else {
                    // mTextNewTotal.setText(">1000");
                    if (mFullNewCountThread != null) {
                        // a thread was previously made -- interrupt it
                        mFullNewCountThread.interrupt();
                    }
                // mFullNewCountThread = new Thread(() -> {
                // Collection collection = getCol();
                // TODO: refactor code to not rewrite this query, add to Sched.totalNewForCurrentDeck()
                // String query = "SELECT count(*) FROM cards WHERE did IN " +
                // Utils.ids2str(collection.getDecks().active()) +
                // " AND queue = " + Consts.QUEUE_TYPE_NEW;
                // final int fullNewCount = collection.getDb().queryScalar(query);
                // if (fullNewCount > 0) {
                // Runnable setNewTotalText = new Runnable() {
                // @Override
                // public void run() {
                // mTextNewTotal.setText(String.valueOf(fullNewCount));
                // }
                // };
                // if (!Thread.currentThread().isInterrupted()) {
                // mTextNewTotal.post(setNewTotalText);
                // }
                // }
                // });
                // mFullNewCountThread.start();
                }
                // Set total number of cards
                // mTextTotal.setText(String.valueOf(totalCards));
                double[] data = calculateStat(getCol(), getCol().getDecks().current().optLong("id"));
                mNewCardsNum = (int) data[2];
                mRevCardsNum = revCards;
                mShouldConfigBeforeStudy = mNewCardsNum == totalCards && mShouldConfigBeforeStudy;
                int hardNum = getLapses(getCol(), getCol().getDecks().current().optLong("id"));
                mDeckListAdapter.mTextCountHandled = String.format(Locale.CHINA, "%d", (int) data[0]);
                mDeckListAdapter.mTextCountLearning = String.format(Locale.CHINA, "%d", (int) data[1]);
                mDeckListAdapter.mTextCountNew = String.format(Locale.CHINA, "%d", (int) data[2]);
                mDeckListAdapter.mTextCountHard = String.format(Locale.CHINA, "%d", hardNum);
                mDeckListAdapter.mTextTotal = String.format(Locale.CHINA, "共%d张卡牌", totalCards);
                double percent = 0;
                if (data[2] == 0) {
                    // 新卡已学完,显示已掌握
                    percent = (data[0] + data[1] + data[2] <= 0) ? 0 : (data[0] / (data[0] + data[1] + data[2]) * 100);
                    mDeckListAdapter.mTextHandledNum = String.format(Locale.CHINA, "%.0f/%.0f", data[0], (data[0] + data[1] + data[2]));
                // holder.handled_percent.setText((String.format(Locale.CHINA, "已掌握 %.1f", percent)) + "%");
                } else {
                    percent = (data[0] + data[1] + data[2] <= 0) ? 0 : ((data[0] + data[1]) / (data[0] + data[1] + data[2]) * 100);
                    mDeckListAdapter.mTextHandledNum = String.format(Locale.CHINA, "%.0f/%.0f", data[0] + data[1], data[0] + data[1] + data[2]);
                // holder.handled_percent.setText((String.format(Locale.CHINA, "已学 %.1f", percent)) + "%");
                }
                // double percent = (data[0] + data[1] + data[2] <= 0) ? 0 : (data[0] / (data[0] + data[1] + data[2]) * 100);
                // mStudyProgress.setMax(100*100);
                mDeckListAdapter.mStudyProgress = (int) (percent * 100);
                mDeckListAdapter.mTextHandledPercent = (String.format(Locale.CHINA, data[2] == 0 ? "已掌握 %.1f" : "已学 %.1f", percent)) + "%";
                // Set estimated time remaining
                int eta = (newCards + revCards) * 10 / 60;
                if ((newCards + revCards) % 60 != 0) {
                    eta++;
                }
                if (eta != -1) {
                    mDeckListAdapter.mTextETA = "" + eta;
                } else {
                    mDeckListAdapter.mTextETA = "-";
                }
                mDeckListAdapter.notifyDataSetChangedAll();
                // Rebuild the options menu
                configureToolbar();
            }
            updateDeckList();
            // If in fragmented mode, refresh the deck list
            if (mFragmented && refreshDecklist) {
                mListener.onRequireDeckListUpdate();
            }
        }
    };
}
Also used : Deck(com.ichi2.libanki.Deck) TaskData(com.ichi2.async.TaskData) TaskListener(com.ichi2.async.TaskListener)

Example 19 with CARD

use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.

the class SelfStudyActivity method removeNotesView.

/**
 * Removes cards from view. Doesn't delete them in model (database).
 *
 * @param reorderCards Whether to rearrange the positions of checked items (DEFECT: Currently deselects all)
 */
private void removeNotesView(java.util.Collection<Long> cardsIds, boolean reorderCards) {
    long reviewerCardId = getReviewerCardId();
    List<CardCache> oldMCards = getCards();
    Map<Long, Integer> idToPos = getPositionMap(oldMCards);
    Set<Long> idToRemove = new HashSet<Long>();
    for (Long cardId : cardsIds) {
        if (cardId == reviewerCardId) {
            mReloadRequired = true;
        }
        if (idToPos.containsKey(cardId)) {
            idToRemove.add(cardId);
        }
    }
    List<CardCache> newMCards = new ArrayList<>();
    int pos = 0;
    for (CardCache card : oldMCards) {
        if (!idToRemove.contains(card.getId())) {
            newMCards.add(new CardCache(card, pos++));
        }
    }
    mCards = newMCards;
    if (reorderCards) {
        // Suboptimal from a UX perspective, we should reorder
        // but this is only hit on a rare sad path and we'd need to rejig the data structures to allow an efficient
        // search
        Timber.w("Removing current selection due to unexpected removal of cards");
    }
    updateList();
}
Also used : CardCache(com.ichi2.anki.CardBrowser.CardCache) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet)

Example 20 with CARD

use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.

the class SelfStudyActivity method updateCardsInList.

/**
 * @param cards           Cards that were changed
 * @param updatedCardTags Mapping note id -> updated tags
 */
private void updateCardsInList(List<Card> cards, Map<Long, String> updatedCardTags) {
    List<CardCache> cardList = getCards();
    Map<Long, Integer> idToPos = getPositionMap(cardList);
    for (Card c : cards) {
        // get position in the mCards search results HashMap
        Integer pos = idToPos.get(c.getId());
        if (pos == null || pos >= getCardCount()) {
            continue;
        }
        // update Q & A etc
        cardList.get(pos).load(true, 0, 1);
    }
    updateList();
}
Also used : CardCache(com.ichi2.anki.CardBrowser.CardCache) CardBrowser.sCardBrowserCard(com.ichi2.anki.CardBrowser.sCardBrowserCard) Card(com.ichi2.libanki.Card)

Aggregations

Card (com.ichi2.libanki.Card)222 Test (org.junit.Test)212 Collection (com.ichi2.libanki.Collection)179 Note (com.ichi2.libanki.Note)173 RobolectricTest (com.ichi2.anki.RobolectricTest)168 JSONObject (com.ichi2.utils.JSONObject)114 JSONArray (com.ichi2.utils.JSONArray)80 DeckConfig (com.ichi2.libanki.DeckConfig)72 ArrayList (java.util.ArrayList)48 NonNull (androidx.annotation.NonNull)33 Deck (com.ichi2.libanki.Deck)32 Intent (android.content.Intent)29 JSONException (com.ichi2.utils.JSONException)27 Model (com.ichi2.libanki.Model)26 Context (android.content.Context)23 SuppressLint (android.annotation.SuppressLint)22 Cursor (android.database.Cursor)22 HashMap (java.util.HashMap)21 Matchers.containsString (org.hamcrest.Matchers.containsString)20 List (java.util.List)17