Home | History | Annotate | Download | only in widget
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.email.widget;
     18 
     19 import com.android.email.R;
     20 import com.android.email.data.ThrottlingCursorLoader;
     21 import com.android.emailcommon.provider.Account;
     22 import com.android.emailcommon.provider.EmailContent;
     23 import com.android.emailcommon.provider.EmailContent.Message;
     24 import com.android.emailcommon.provider.EmailContent.MessageColumns;
     25 import com.android.emailcommon.provider.Mailbox;
     26 
     27 import android.content.Context;
     28 import android.content.res.Resources;
     29 import android.database.Cursor;
     30 import android.database.CursorWrapper;
     31 
     32 /**
     33  * Loader for {@link EmailWidget}.
     34  *
     35  * This loader not only loads the messages, but also:
     36  * - The number of accounts.
     37  * - The message count shown in the widget header.
     38  *   It's currently just the same as the message count, but this will be updated to the unread
     39  *   counts for inboxes.
     40  */
     41 class EmailWidgetLoader extends ThrottlingCursorLoader {
     42     private static final String SORT_TIMESTAMP_DESCENDING = MessageColumns.TIMESTAMP + " DESC";
     43 
     44     // The projection to be used by the WidgetLoader
     45     private static final String[] WIDGET_PROJECTION = new String[] {
     46             EmailContent.RECORD_ID, MessageColumns.DISPLAY_NAME, MessageColumns.TIMESTAMP,
     47             MessageColumns.SUBJECT, MessageColumns.FLAG_READ, MessageColumns.FLAG_FAVORITE,
     48             MessageColumns.FLAG_ATTACHMENT, MessageColumns.MAILBOX_KEY, MessageColumns.SNIPPET,
     49             MessageColumns.ACCOUNT_KEY, MessageColumns.FLAGS
     50             };
     51     public static final int WIDGET_COLUMN_ID = 0;
     52     public static final int WIDGET_COLUMN_DISPLAY_NAME = 1;
     53     public static final int WIDGET_COLUMN_TIMESTAMP = 2;
     54     public static final int WIDGET_COLUMN_SUBJECT = 3;
     55     public static final int WIDGET_COLUMN_FLAG_READ = 4;
     56     public static final int WIDGET_COLUMN_FLAG_FAVORITE = 5;
     57     public static final int WIDGET_COLUMN_FLAG_ATTACHMENT = 6;
     58     public static final int WIDGET_COLUMN_MAILBOX_KEY = 7;
     59     public static final int WIDGET_COLUMN_SNIPPET = 8;
     60     public static final int WIDGET_COLUMN_ACCOUNT_KEY = 9;
     61     public static final int WIDGET_COLUMN_FLAGS = 10;
     62 
     63     private long mAccountId;
     64     private long mMailboxId;
     65 
     66     /**
     67      * Cursor data specifically for use by the Email widget. Contains a cursor of messages in
     68      * addition to a message count and account name. The later elements were opportunistically
     69      * placed in this cursor. We could have defined multiple loaders for these items.
     70      */
     71     static class WidgetCursor extends CursorWrapper {
     72         private final int mMessageCount;
     73         private final String mAccountName;
     74         private final String mMailboxName;
     75 
     76         public WidgetCursor(Cursor cursor, int messageCount, String accountName,
     77                 String mailboxName) {
     78             super(cursor);
     79             mMessageCount = messageCount;
     80             mAccountName = accountName;
     81             mMailboxName = mailboxName;
     82         }
     83 
     84         /**
     85          * Gets the count to be shown on the widget header. If the currently viewed mailbox ID is
     86          * not {@link Mailbox#QUERY_ALL_FAVORITES}, it is the unread count, which is different from
     87          * number of records returned by {@link #getCount()}.
     88          */
     89         public int getMessageCount() {
     90             return mMessageCount;
     91         }
     92         /** Gets the display name of the account */
     93         public String getAccountName() {
     94             return mAccountName;
     95         }
     96         /** Gets the display name of the mailbox */
     97         public String getMailboxName() {
     98             return mMailboxName;
     99         }
    100     }
    101 
    102     private final Context mContext;
    103 
    104     EmailWidgetLoader(Context context) {
    105         super(context, Message.CONTENT_URI, WIDGET_PROJECTION, null,
    106                 null, SORT_TIMESTAMP_DESCENDING);
    107         mContext = context;
    108     }
    109 
    110     @Override
    111     public Cursor loadInBackground() {
    112         final Cursor messagesCursor = super.loadInBackground();
    113 
    114         // Reset the notification Uri to our Message table notifier URI
    115         messagesCursor.setNotificationUri(mContext.getContentResolver(), Message.NOTIFIER_URI);
    116 
    117         final int messageCount;
    118         if (mMailboxId != Mailbox.QUERY_ALL_FAVORITES) {
    119             String selection = "(" + getSelection() + " ) AND " + MessageColumns.FLAG_READ + " = 0";
    120             messageCount = EmailContent.count(mContext, Message.CONTENT_URI, selection,
    121                     getSelectionArgs());
    122         } else {
    123             // Just use the number of all messages shown.
    124             messageCount = messagesCursor.getCount();
    125         }
    126         Account account = Account.restoreAccountWithId(mContext, mAccountId);
    127         final String accountName;
    128         if (account != null) {
    129             accountName = account.mDisplayName;
    130         } else {
    131             if (mAccountId == Account.ACCOUNT_ID_COMBINED_VIEW) {
    132                 int accountCount = EmailContent.count(mContext, Account.CONTENT_URI);
    133                 Resources res = mContext.getResources();
    134                 String countString =
    135                         res.getQuantityString(R.plurals.picker_combined_view_account_count,
    136                         accountCount, accountCount);
    137                 accountName = res.getString(R.string.picker_combined_view_fmt, countString);
    138             } else {
    139                 // TODO What to use here? "unknown"? Account is real, but, doesn't exist.
    140                 accountName = null;
    141             }
    142         }
    143         final String mailboxName;
    144         if (mMailboxId > 0) {
    145             Mailbox mailbox = Mailbox.restoreMailboxWithId(mContext, mMailboxId);
    146             if (mailbox != null) {
    147                 mailboxName = mailbox.mDisplayName;    // regular mailbox
    148             } else {
    149                 // TODO What use here? "unknown"? Mailbox is "real", but, doesn't exist.
    150                 mailboxName = null;
    151             }
    152         } else {
    153             if (mMailboxId == Mailbox.QUERY_ALL_INBOXES) {
    154                 mailboxName = mContext.getString(R.string.picker_mailbox_name_all_inbox);
    155             } else { // default to all unread for the account's inbox
    156                 mailboxName = mContext.getString(R.string.picker_mailbox_name_all_unread);
    157             }
    158         }
    159 
    160         return new WidgetCursor(messagesCursor, messageCount, accountName, mailboxName);
    161     }
    162 
    163     /**
    164      * Stop any pending load, reset selection parameters, and start loading.
    165      *
    166      * Must be called from the UI thread
    167      *
    168      * @param accountId The ID of the account. May be {@link Account#ACCOUNT_ID_COMBINED_VIEW}.
    169      * @param mailboxId The mailbox to load; may either be a real mailbox or the pseudo mailbox
    170      *          {@link Mailbox#QUERY_ALL_INBOXES} or {@link Mailbox#QUERY_ALL_UNREAD}. If it's
    171      *          neither of these pseudo mailboxes, {@link Mailbox#QUERY_ALL_UNREAD} will be used.
    172      */
    173     void load(long accountId, long mailboxId) {
    174         reset();
    175         mAccountId = accountId;
    176         mMailboxId = mailboxId;
    177         setSelectionAndArgs();
    178         startLoading();
    179     }
    180 
    181     /** Sets the loader's selection and arguments depending upon the account and mailbox */
    182     private void setSelectionAndArgs() {
    183         if (mAccountId == Account.ACCOUNT_ID_COMBINED_VIEW) {
    184             if (mMailboxId == Mailbox.QUERY_ALL_INBOXES) {
    185                 setSelection(Message.ALL_INBOX_SELECTION);
    186             } else { // default to all unread
    187                 setSelection(Message.ALL_UNREAD_SELECTION);
    188             }
    189             setSelectionArgs(null);
    190         } else {
    191             if (mMailboxId > 0L) {
    192                 // Simple mailbox selection
    193                 setSelection(
    194                     MessageColumns.ACCOUNT_KEY + "=? AND " +
    195                     MessageColumns.MAILBOX_KEY + "=?");
    196                 setSelectionArgs(
    197                         new String[] { Long.toString(mAccountId), Long.toString(mMailboxId) });
    198             } else {
    199                 if (mMailboxId == Mailbox.QUERY_ALL_INBOXES) {
    200                     setSelection(Message.PER_ACCOUNT_INBOX_SELECTION);
    201                 } else { // default to all unread for the account's inbox
    202                     setSelection(Message.PER_ACCOUNT_UNREAD_SELECTION);
    203                 }
    204                 setSelectionArgs(new String[] { Long.toString(mAccountId) });
    205             }
    206         }
    207     }
    208 }
    209