Example #1
0
  private TaskData doInBackgroundSuspendCard(TaskData... params) {
    long start, stop;
    Deck deck = params[0].getDeck();
    Card oldCard = params[0].getCard();
    Card newCard;

    AnkiDb.database.beginTransaction();
    try {
      if (oldCard != null) {
        start = System.currentTimeMillis();
        deck.suspendCard(oldCard.id);
        stop = System.currentTimeMillis();
        Log.v(TAG, "doInBackgroundSuspendCard - Suspended card in " + (stop - start) + " ms.");
      }

      start = System.currentTimeMillis();
      newCard = deck.getCard();
      stop = System.currentTimeMillis();
      Log.v(TAG, "doInBackgroundSuspendCard - Loaded new card in " + (stop - start) + " ms.");
      publishProgress(new TaskData(newCard));
      AnkiDb.database.setTransactionSuccessful();
    } finally {
      AnkiDb.database.endTransaction();
    }

    return null;
  }
    @Override
    protected Payload doInBackground(Payload... args) {

      Payload data = doInBackgroundLoadDeck(args);
      if (data.returnType == DeckTask.DECK_LOADED) {
        double now = System.currentTimeMillis();
        HashMap<String, Object> results = (HashMap<String, Object>) data.result;
        Deck deck = (Deck) results.get("deck");
        // deck.beforeUpdateCards();
        // deck.updateAllCards();
        SharedDeckDownload download = (SharedDeckDownload) args[0].data[0];
        SharedPreferences pref = PrefSettings.getSharedPrefs(getBaseContext());
        String updatedCardsPref =
            "numUpdatedCards:" + mDestination + "/tmp/" + download.getTitle() + ".anki.updating";
        long totalCards = deck.retrieveCardCount();
        download.setNumTotalCards((int) totalCards);
        long updatedCards = pref.getLong(updatedCardsPref, 0);
        download.setNumUpdatedCards((int) updatedCards);
        long batchSize = Math.max(100, totalCards / 200);
        mRecentBatchTimings = new long[sRunningAvgLength];
        mTotalBatches = ((double) totalCards) / batchSize;
        int currentBatch = (int) (updatedCards / batchSize);
        long runningAvgCount = 0;
        long batchStart;
        mElapsedTime = 0;
        while (updatedCards < totalCards
            && download.getStatus() == SharedDeckDownload.STATUS_UPDATING) {
          batchStart = System.currentTimeMillis();
          updatedCards = deck.updateAllCardsFromPosition(updatedCards, batchSize);
          Editor editor = pref.edit();
          editor.putLong(updatedCardsPref, updatedCards);
          editor.commit();
          download.setNumUpdatedCards((int) updatedCards);
          publishProgress();
          estimateTimeToCompletion(
              download, currentBatch, runningAvgCount, System.currentTimeMillis() - batchStart);
          currentBatch++;
          runningAvgCount++;
        }
        if (download.getStatus() == SharedDeckDownload.STATUS_UPDATING) {
          data.success = true;
        } else if (download.getStatus() == SharedDeckDownload.STATUS_PAUSED) {
          Editor editor = pref.edit();
          String pausedPref =
              "paused:" + mDestination + "/tmp/" + download.getTitle() + ".anki.updating";
          editor.putBoolean(pausedPref, true);
          editor.commit();
          data.success = false;
          Log.i(AnkiDroidApp.TAG, "pausing deck " + download.getTitle());
        } else if (download.getStatus() == SharedDeckDownload.STATUS_CANCELLED) {
          data.success = false;
        }
        // Log.i(AnkiDroidApp.TAG, "Time to update deck = " + download.getEstTimeToCompletion() + "
        // sec.");
        // deck.afterUpdateCards();
      } else {
        data.success = false;
      }
      return data;
    }
Example #3
0
  private TaskData doInBackgroundAnswerCard(TaskData... params) {
    long start, stop;
    Deck deck = params[0].getDeck();
    Card oldCard = params[0].getCard();
    int ease = params[0].getInt();
    Card newCard;

    if (oldCard != null) {
      start = System.currentTimeMillis();
      oldCard.temporarilySetLowestPriority();
      deck.decreaseCounts(oldCard);
      stop = System.currentTimeMillis();
      Log.v(TAG, "doInBackground - Set old card 0 priority in " + (stop - start) + " ms.");
    }

    start = System.currentTimeMillis();
    newCard = deck.getCard();
    stop = System.currentTimeMillis();
    Log.v(TAG, "doInBackground - Loaded new card in " + (stop - start) + " ms.");
    publishProgress(new TaskData(newCard));

    if (ease != 0 && oldCard != null) {
      start = System.currentTimeMillis();
      deck.answerCard(oldCard, ease);
      stop = System.currentTimeMillis();
      Log.v(TAG, "doInBackground - Answered old card in " + (stop - start) + " ms.");
    }

    return null;
  }
    @Override
    protected void onPostExecute(Payload result) {
      super.onPostExecute(result);
      HashMap<String, Object> results = (HashMap<String, Object>) result.result;
      Deck deck = (Deck) results.get("deck");
      // Close the previously opened deck.
      if (deck != null) {
        deck.closeDeck();
      }
      SharedDeckDownload download = (SharedDeckDownload) result.data[0];
      SharedPreferences pref = PrefSettings.getSharedPrefs(getBaseContext());
      Editor editor = pref.edit();

      Log.i(AnkiDroidApp.TAG, "Finished deck " + download.getTitle() + " " + result.success);
      if (result.success) {
        // Put updated cards to 0
        // TODO: Why do we need to zero the updated cards?
        editor.putLong(
            "numUpdatedCards:" + mDestination + "/tmp/" + download.getTitle() + ".anki.updating",
            0);
        editor.commit();
        // Move deck and media to the default deck path
        new File(mDestination + "/tmp/" + download.getTitle() + ".anki.updating")
            .renameTo(new File(mDestination + "/" + download.getTitle() + ".anki"));
        new File(mDestination + "/tmp/" + download.getTitle() + ".media/")
            .renameTo(new File(mDestination + "/" + download.getTitle() + ".media/"));
        mSharedDeckDownloads.remove(download);
        showNotification(download.getTitle());
      } else {
        // If paused do nothing, if cancelled clean up
        if (download.getStatus() == Download.STATUS_CANCELLED) {
          try {
            new File(mDestination + "/tmp/" + download.getTitle() + ".anki.updating").delete();
            File mediaFolder = new File(mDestination + "/tmp/" + download.getTitle() + ".media/");
            if (mediaFolder != null && mediaFolder.listFiles() != null) {
              for (File f : mediaFolder.listFiles()) {
                f.delete();
              }
              mediaFolder.delete();
            }
          } catch (SecurityException e) {
            Log.e(AnkiDroidApp.TAG, "SecurityException = " + e.getMessage());
            e.printStackTrace();
          }
          editor.remove(
              "numUpdatedCards:" + mDestination + "/tmp/" + download.getTitle() + ".anki.updating");
          editor.remove(
              "paused:" + mDestination + "/tmp/" + download.getTitle() + ".anki.updating");
          editor.commit();
          mSharedDeckDownloads.remove(download);
        }
      }
      notifySharedDeckObservers();
      stopIfFinished();
    }
 private void updateList() {
   mCardsAdapter.notifyDataSetChanged();
   int count = mCards.size();
   setTitle(
       getResources()
           .getQuantityString(
               R.plurals.card_browser_title, count, mDeck.getDeckName(), count, mAllCards.size()));
 }
 @Override
 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
   super.onCreateContextMenu(menu, v, menuInfo);
   int selectedPosition = ((AdapterView.AdapterContextMenuInfo) menuInfo).position;
   Resources res = getResources();
   @SuppressWarnings("unused")
   MenuItem item;
   mSelectedCard = mDeck.cardFromId(Long.parseLong(mCards.get(selectedPosition).get("id")));
   if (mSelectedCard.isMarked()) {
     item =
         menu.add(
             Menu.NONE,
             CONTEXT_MENU_MARK,
             Menu.NONE,
             res.getString(R.string.card_browser_unmark_card));
     mIsMarked = true;
     Log.i(AnkiDroidApp.TAG, "Selected Card is currently marked");
   } else {
     item =
         menu.add(
             Menu.NONE,
             CONTEXT_MENU_MARK,
             Menu.NONE,
             res.getString(R.string.card_browser_mark_card));
     mIsMarked = false;
   }
   if (mSelectedCard.getSuspendedState()) {
     item =
         menu.add(
             Menu.NONE,
             CONTEXT_MENU_SUSPEND,
             Menu.NONE,
             res.getString(R.string.card_browser_unsuspend_card));
     mIsSuspended = true;
     Log.i(AnkiDroidApp.TAG, "Selected Card is currently suspended");
   } else {
     item =
         menu.add(
             Menu.NONE,
             CONTEXT_MENU_SUSPEND,
             Menu.NONE,
             res.getString(R.string.card_browser_suspend_card));
     mIsSuspended = false;
   }
   item =
       menu.add(
           Menu.NONE,
           CONTEXT_MENU_DELETE,
           Menu.NONE,
           res.getString(R.string.card_browser_delete_card));
   item =
       menu.add(
           Menu.NONE,
           CONTEXT_MENU_DETAILS,
           Menu.NONE,
           res.getString(R.string.card_browser_card_details));
   menu.setHeaderTitle(mCards.get(selectedPosition).get("question"));
 }
Example #7
0
  private TaskData doInBackgroundAnswerCard(TaskData... params) {
    long start, start2;
    Deck deck = params[0].getDeck();
    Card oldCard = params[0].getCard();
    int ease = params[0].getInt();
    Card newCard;

    start2 = System.currentTimeMillis();

    AnkiDb.database.beginTransaction();
    try {
      if (oldCard != null) {
        start = System.currentTimeMillis();
        deck.answerCard(oldCard, ease);
        Log.v(
            TAG,
            "doInBackgroundAnswerCard - Answered card in "
                + (System.currentTimeMillis() - start)
                + " ms.");
      }

      start = System.currentTimeMillis();
      newCard = deck.getCard();
      Log.v(
          TAG,
          "doInBackgroundAnswerCard - Loaded new card in "
              + (System.currentTimeMillis() - start)
              + " ms.");
      publishProgress(new TaskData(newCard));

      AnkiDb.database.setTransactionSuccessful();
    } finally {
      AnkiDb.database.endTransaction();
    }

    Log.w(
        TAG,
        "doInBackgroundAnswerCard - DB operations in "
            + (System.currentTimeMillis() - start2)
            + " ms.");

    return null;
  }
 private void updateCard(Card card, ArrayList<HashMap<String, String>> list, int position) {
   list.get(position).put("question", Utils.stripHTML(card.getQuestion().replace("<br>", "\n")));
   list.get(position).put("answer", Utils.stripHTML(card.getAnswer().replace("<br>", "\n")));
   for (long cardId : mDeck.getCardsFromFactId(card.getFactId())) {
     if (cardId != card.getId()) {
       int positionC = getPosition(mCards, cardId);
       int positionA = getPosition(mAllCards, cardId);
       Card c = mDeck.cardFromId(cardId);
       String question = Utils.stripHTML(c.getQuestion().replace("<br>", "\n"));
       String answer = Utils.stripHTML(c.getAnswer().replace("<br>", "\n"));
       if (positionC != -1) {
         mCards.get(positionC).put("question", question);
         mCards.get(positionC).put("answer", answer);
       }
       mAllCards.get(positionA).put("question", question);
       mAllCards.get(positionA).put("answer", answer);
     }
   }
 }
Example #9
0
  private TaskData doInBackgroundUpdateFact(TaskData[] params) {

    // Save the fact
    Deck deck = params[0].getDeck();
    Card editCard = params[0].getCard();
    Fact editFact = editCard.fact;
    editFact.toDb();
    LinkedList<Card> saveCards = editFact.getUpdatedRelatedCards();

    Iterator<Card> iter = saveCards.iterator();
    while (iter.hasNext()) {
      Card modifyCard = iter.next();
      deck.updateCard(modifyCard);
    }
    // Find all cards based on this fact and update them with the updateCard method.

    publishProgress(new TaskData(deck.getCurrentCard()));

    return null;
  }
Example #10
0
  private TaskData doInBackgroundSuspendCard(TaskData... params) {
    long start, stop;
    Deck deck = params[0].getDeck();
    Card oldCard = params[0].getCard();
    Card newCard;

    if (oldCard != null) {
      start = System.currentTimeMillis();
      deck.suspendCard(oldCard.id);
      stop = System.currentTimeMillis();
      Log.v(TAG, "doInBackgroundSuspendCard - Suspended card in " + (stop - start) + " ms.");
    }

    start = System.currentTimeMillis();
    newCard = deck.getCard();
    stop = System.currentTimeMillis();
    Log.v(TAG, "doInBackgroundSuspendCard - Loaded new card in " + (stop - start) + " ms.");
    publishProgress(new TaskData(newCard));

    return null;
  }
    private Payload doInBackgroundLoadDeck(Payload... params) {
      Payload data = params[0];
      SharedDeckDownload download = (SharedDeckDownload) data.data[0];
      String deckFilename = mDestination + "/tmp/" + download.getTitle() + ".anki.updating";
      Log.i(AnkiDroidApp.TAG, "doInBackgroundLoadDeck - deckFilename = " + deckFilename);

      Log.i(AnkiDroidApp.TAG, "loadDeck - SD card mounted and existent file -> Loading deck...");
      try {
        // Open the right deck.
        Deck deck = Deck.openDeck(deckFilename);
        // Start by getting the first card and displaying it.
        Card card = deck.getCard();
        Log.i(AnkiDroidApp.TAG, "Deck loaded!");

        // Set the result
        data.returnType = DeckTask.DECK_LOADED;
        HashMap<String, Object> results = new HashMap<String, Object>();
        results.put("deck", deck);
        results.put("card", card);
        results.put("position", download.getNumUpdatedCards());
        data.result = results;
        return data;
      } catch (SQLException e) {
        Log.i(
            AnkiDroidApp.TAG,
            "The database " + deckFilename + " could not be opened = " + e.getMessage());
        data.success = false;
        data.returnType = DeckTask.DECK_NOT_LOADED;
        data.exception = e;
        return data;
      } catch (CursorIndexOutOfBoundsException e) {
        // XXX: Where is this exception thrown?
        Log.i(AnkiDroidApp.TAG, "The deck has no cards = " + e.getMessage());
        data.success = false;
        data.returnType = DeckTask.DECK_EMPTY;
        data.exception = e;
        return data;
      }
    }
Example #12
0
  private TaskData doInBackgroundLoadDeck(TaskData... params) {
    String deckFilename = params[0].getString();
    Log.i(TAG, "doInBackgroundLoadDeck - deckFilename = " + deckFilename);

    Log.i(TAG, "loadDeck - SD card mounted and existent file -> Loading deck...");
    try {
      // Open the right deck.
      Deck deck = Deck.openDeck(deckFilename);
      // Start by getting the first card and displaying it.
      Card card = deck.getCard();
      Log.i(TAG, "Deck loaded!");

      return new TaskData(AnkiDroid.DECK_LOADED, deck, card);
    } catch (SQLException e) {
      Log.i(TAG, "The database " + deckFilename + " could not be opened = " + e.getMessage());
      return new TaskData(AnkiDroid.DECK_NOT_LOADED);
    } catch (CursorIndexOutOfBoundsException e) {
      Log.i(TAG, "The deck has no cards = " + e.getMessage());
      ;
      return new TaskData(AnkiDroid.DECK_EMPTY);
    }
  }
 @Override
 public void onPostExecute(DeckTask.TaskData result) {
   mUndoRedoCardId = result.getLong();
   String undoType = result.getString();
   if (undoType.equals(Deck.UNDO_TYPE_DELETE_CARD)) {
     int position = getPosition(mDeletedCards, mUndoRedoCardId);
     if (position != -1) {
       HashMap<String, String> data = new HashMap<String, String>();
       data.put("id", mDeletedCards.get(position).get("id"));
       data.put("question", mDeletedCards.get(position).get("question"));
       data.put("answer", mDeletedCards.get(position).get("answer"));
       data.put("marSus", mDeletedCards.get(position).get("marSus"));
       mAllCards.add(Integer.parseInt(mDeletedCards.get(position).get("allCardPos")), data);
       mDeletedCards.remove(position);
       updateCardsList();
     } else {
       deleteCard(Long.toString(mUndoRedoCardId), getPosition(mCards, mUndoRedoCardId));
     }
     mProgressDialog.dismiss();
   } else {
     mUndoRedoCard = mDeck.cardFromId(mUndoRedoCardId);
     if (undoType.equals(Deck.UNDO_TYPE_EDIT_CARD)) {
       mUndoRedoCard.fromDB(mUndoRedoCardId);
       int pos = getPosition(mAllCards, mUndoRedoCardId);
       updateCard(mUndoRedoCard, mAllCards, pos);
       pos = getPosition(mCards, mUndoRedoCardId);
       if (pos != -1) {
         updateCard(mUndoRedoCard, mCards, pos);
       }
       updateList();
       mProgressDialog.dismiss();
     } else if (undoType.equals(Deck.UNDO_TYPE_MARK_CARD)) {
       markCards(mUndoRedoCard.getFactId(), mUndoRedoCard.isMarked());
       mProgressDialog.dismiss();
     } else if (undoType.equals(Deck.UNDO_TYPE_SUSPEND_CARD)) {
       suspendCard(
           mUndoRedoCard,
           getPosition(mCards, mUndoRedoCardId),
           mUndoRedoCard.getSuspendedState());
       mProgressDialog.dismiss();
     } else {
       mUndoRedoDialogShowing = true;
       getCards();
     }
   }
 }
 private void markCards(long factId, boolean mark) {
   for (long cardId : mDeck.getCardsFromFactId(factId)) {
     int positionC = getPosition(mCards, cardId);
     int positionA = getPosition(mAllCards, cardId);
     String marSus = mAllCards.get(positionA).get("marSus");
     if (mark) {
       marSus = "1" + marSus.substring(1, 2);
       if (positionC != -1) {
         mCards.get(positionC).put("marSus", marSus);
       }
       mAllCards.get(positionA).put("marSus", marSus);
     } else {
       marSus = "0" + marSus.substring(1, 2);
       if (positionC != -1) {
         mCards.get(positionC).put("marSus", marSus);
       }
       mAllCards.get(positionA).put("marSus", marSus);
     }
   }
   updateList();
 }
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    Themes.applyTheme(this);
    super.onCreate(savedInstanceState);

    setContentView(R.layout.card_browser);

    mDeck = AnkiDroidApp.deck();
    mDeck.resetUndo();

    mBackground = Themes.getCardBrowserBackground();

    SharedPreferences preferences = PrefSettings.getSharedPrefs(getBaseContext());
    mrelativeBrowserFontSize =
        preferences.getInt("relativeCardBrowserFontSize", DEFAULT_FONT_SIZE_RATIO);
    mPrefFixArabic = preferences.getBoolean("fixArabicText", false);

    mCards = new ArrayList<HashMap<String, String>>();
    mAllCards = new ArrayList<HashMap<String, String>>();
    mCardsListView = (ListView) findViewById(R.id.card_browser_list);

    mCardsAdapter =
        new SizeControlledListAdapter(
            this,
            mCards,
            R.layout.card_item,
            new String[] {"question", "answer", "marSus"},
            new int[] {R.id.card_question, R.id.card_answer, R.id.card_item},
            mrelativeBrowserFontSize);
    mCardsAdapter.setViewBinder(
        new SimpleAdapter.ViewBinder() {
          @Override
          public boolean setViewValue(View view, Object arg1, String text) {
            if (view.getId() == R.id.card_item) {
              int which = BACKGROUND_NORMAL;
              if (text.equals("11")) {
                which = BACKGROUND_MARKED_SUSPENDED;
              } else if (text.substring(1, 2).equals("1")) {
                which = BACKGROUND_SUSPENDED;
              } else if (text.substring(0, 1).equals("1")) {
                which = BACKGROUND_MARKED;
              }
              view.setBackgroundResource(mBackground[which]);
              return true;
            }
            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);
            mPositionInCardsList = position;
            mSelectedCard =
                mDeck.cardFromId(Long.parseLong(mCards.get(mPositionInCardsList).get("id")));
            sEditorCard = mSelectedCard;
            editCard.putExtra("callfromcardbrowser", true);
            startActivityForResult(editCard, EDIT_CARD);
            if (Integer.valueOf(android.os.Build.VERSION.SDK) > 4) {
              ActivityTransitionAnimation.slide(CardBrowser.this, ActivityTransitionAnimation.LEFT);
            }
          }
        });
    registerForContextMenu(mCardsListView);

    mSearchEditText = (EditText) findViewById(R.id.card_browser_search);
    mSearchEditText.addTextChangedListener(
        new TextWatcher() {
          public void afterTextChanged(Editable s) {
            mTimerHandler.removeCallbacks(updateList);
            mTimerHandler.postDelayed(updateList, WAIT_TIME_UNTIL_UPDATE);
          }

          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);

    setTitle(mDeck.getDeckName());

    allTags = null;
    mSelectedTags = new HashSet<String>();

    getCards();
  }
Example #16
0
  public static Deck openDeck(String path) throws SQLException {
    Deck deck = null;
    Cursor cursor = null;
    Log.i(TAG, "openDeck - Opening database " + path);
    AnkiDb.openDatabase(path);

    try {
      // Read in deck table columns
      cursor = AnkiDb.database.rawQuery("SELECT *" + " FROM decks" + " LIMIT 1", null);

      if (!cursor.moveToFirst()) return null;

      deck = new Deck();
      deck.id = cursor.getLong(0);
      deck.created = cursor.getDouble(1);
      deck.modified = cursor.getDouble(2);
      deck.description = cursor.getString(3);
      deck.version = cursor.getInt(4);
      deck.currentModelId = cursor.getLong(5);
      deck.syncName = cursor.getString(6);
      deck.lastSync = cursor.getDouble(7);
      deck.hardIntervalMin = cursor.getDouble(8);
      deck.hardIntervalMax = cursor.getDouble(9);
      deck.midIntervalMin = cursor.getDouble(10);
      deck.midIntervalMax = cursor.getDouble(11);
      deck.easyIntervalMin = cursor.getDouble(12);
      deck.easyIntervalMax = cursor.getDouble(13);
      deck.delay0 = cursor.getDouble(14);
      deck.delay1 = cursor.getDouble(15);
      deck.delay2 = cursor.getDouble(16);
      deck.collapseTime = cursor.getDouble(17);
      deck.highPriority = cursor.getString(18);
      deck.medPriority = cursor.getString(19);
      deck.lowPriority = cursor.getString(20);
      deck.suspended = cursor.getString(21);
      deck.newCardOrder = cursor.getInt(22);
      deck.newCardSpacing = cursor.getInt(23);
      deck.failedCardMax = cursor.getInt(24);
      deck.newCardsPerDay = cursor.getInt(25);
      deck.sessionRepLimit = cursor.getInt(26);
      deck.sessionTimeLimit = cursor.getInt(27);
      deck.utcOffset = cursor.getDouble(28);
      deck.cardCount = cursor.getInt(29);
      deck.factCount = cursor.getInt(30);
      deck.failedNowCount = cursor.getInt(31);
      deck.failedSoonCount = cursor.getInt(32);
      deck.revCount = cursor.getInt(33);
      deck.newCount = cursor.getInt(34);
      deck.revCardOrder = cursor.getInt(35);

      Log.i(TAG, "openDeck - Read " + cursor.getColumnCount() + " columns from decks table.");
    } finally {
      if (cursor != null) cursor.close();
    }
    Log.i(
        TAG,
        String.format(
            ENGLISH_LOCALE,
            "openDeck - modified: %f currentTime: %f",
            deck.modified,
            System.currentTimeMillis() / 1000.0));

    deck.initVars();

    // Ensure necessary indices are available
    deck.updateDynamicIndices();
    // Save counts to determine if we should save deck after check
    int oldCount = deck.failedSoonCount + deck.revCount + deck.newCount;
    // Update counts
    deck.rebuildQueue();

    try {
      // Unsuspend reviewed early & buried
      cursor =
          AnkiDb.database.rawQuery(
              "SELECT id "
                  + "FROM cards "
                  + "WHERE type in (0,1,2) and "
                  + "isDue = 0 and "
                  + "priority in (-1,-2)",
              null);

      if (cursor.moveToFirst()) {
        int count = cursor.getCount();
        long[] ids = new long[count];
        for (int i = 0; i < count; i++) {
          ids[i] = cursor.getLong(0);
          cursor.moveToNext();
        }
        deck.updatePriorities(ids);
        deck.checkDue();
      }
    } finally {
      if (cursor != null) cursor.close();
    }

    // Save deck to database if it has been modified
    if ((oldCount != (deck.failedSoonCount + deck.revCount + deck.newCount))
        || deck.modifiedSinceSave()) deck.commitToDB();

    // Create a temporary view for random new cards. Randomizing the cards by themselves
    // as is done in desktop Anki in Deck.randomizeNewCards() takes too long.
    AnkiDb.database.execSQL(
        "CREATE TEMPORARY VIEW acqCardsRandom AS "
            + "SELECT * FROM cards "
            + "WHERE type = 2 AND isDue = 1 "
            + "ORDER BY RANDOM()");

    return deck;
  }
 @Override
 public boolean onPrepareOptionsMenu(Menu menu) {
   menu.findItem(MENU_UNDO).setEnabled(mDeck.undoAvailable());
   menu.findItem(MENU_REDO).setEnabled(mDeck.redoAvailable());
   return true;
 }