EmailWidgetLoader.java revision cf772cc8ad38fe4eb929964c3839d7388dfd585c
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
17package com.android.email.widget;
18
19import com.android.email.R;
20import com.android.email.data.ThrottlingCursorLoader;
21import com.android.emailcommon.provider.EmailContent;
22import com.android.emailcommon.provider.EmailContent.Account;
23import com.android.emailcommon.provider.EmailContent.Message;
24import com.android.emailcommon.provider.EmailContent.MessageColumns;
25import com.android.emailcommon.provider.Mailbox;
26
27import android.content.Context;
28import android.content.res.Resources;
29import android.database.Cursor;
30import 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 */
41class 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