1bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/*
2bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Copyright (C) 2010 The Android Open Source Project
3bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
4bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Licensed under the Apache License, Version 2.0 (the "License");
5bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * you may not use this file except in compliance with the License.
6bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * You may obtain a copy of the License at
7bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
8bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *      http://www.apache.org/licenses/LICENSE-2.0
9bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
10bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Unless required by applicable law or agreed to in writing, software
11bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * distributed under the License is distributed on an "AS IS" BASIS,
12bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * See the License for the specific language governing permissions and
14bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * limitations under the License.
15bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */
16bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
17bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookpackage com.android.email.activity;
18bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
19bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.content.Context;
20bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.content.Loader;
21bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.database.Cursor;
22bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.database.CursorWrapper;
23bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.os.Bundle;
24bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.util.Log;
25bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.view.View;
26bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.view.ViewGroup;
27bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.widget.CursorAdapter;
28bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
29bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.Controller;
30bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.Email;
31bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.MessageListContext;
32bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.ResourceHelper;
33bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.data.ThrottlingCursorLoader;
34bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.Logging;
35bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.mail.MessagingException;
36bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.provider.Account;
37bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.provider.EmailContent;
38bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.provider.EmailContent.Message;
39bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.provider.EmailContent.MessageColumns;
40bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.provider.Mailbox;
41bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.utility.TextUtilities;
42bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.utility.Utility;
43bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.google.common.base.Preconditions;
44bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
45bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.util.HashSet;
46bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.util.Set;
47bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
48bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
49bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/**
50bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * This class implements the adapter for displaying messages based on cursors.
51bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */
52bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/* package */ class MessagesAdapter extends CursorAdapter {
53bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final String STATE_CHECKED_ITEMS =
54bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            "com.android.email.activity.MessagesAdapter.checkedItems";
55bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
56bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /* package */ static final String[] MESSAGE_PROJECTION = new String[] {
57bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        EmailContent.RECORD_ID, MessageColumns.MAILBOX_KEY, MessageColumns.ACCOUNT_KEY,
58bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MessageColumns.DISPLAY_NAME, MessageColumns.SUBJECT, MessageColumns.TIMESTAMP,
59bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MessageColumns.FLAG_READ, MessageColumns.FLAG_FAVORITE, MessageColumns.FLAG_ATTACHMENT,
60bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MessageColumns.FLAGS, MessageColumns.SNIPPET
61bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    };
62bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
63bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final int COLUMN_ID = 0;
64bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final int COLUMN_MAILBOX_KEY = 1;
65bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final int COLUMN_ACCOUNT_KEY = 2;
66bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final int COLUMN_DISPLAY_NAME = 3;
67bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final int COLUMN_SUBJECT = 4;
68bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final int COLUMN_DATE = 5;
69bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final int COLUMN_READ = 6;
70bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final int COLUMN_FAVORITE = 7;
71bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final int COLUMN_ATTACHMENTS = 8;
72bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final int COLUMN_FLAGS = 9;
73bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static final int COLUMN_SNIPPET = 10;
74bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
75bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private final ResourceHelper mResourceHelper;
76bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
77bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** If true, show color chips. */
78bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private boolean mShowColorChips;
79bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
80bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** If not null, the query represented by this group of messages */
81bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private String mQuery;
82bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
83bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
84bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Set of seleced message IDs.
85bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
86bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private final HashSet<Long> mSelectedSet = new HashSet<Long>();
87bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
88bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
89bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Callback from MessageListAdapter.  All methods are called on the UI thread.
90bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
91bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public interface Callback {
92bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        /** Called when the use starts/unstars a message */
93bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        void onAdapterFavoriteChanged(MessageListItem itemView, boolean newFavorite);
94bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        /** Called when the user selects/unselects a message */
95bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        void onAdapterSelectedChanged(MessageListItem itemView, boolean newSelected,
96bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                int mSelectedCount);
97bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
98bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
99bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private final Callback mCallback;
100bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
101bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private ThreePaneLayout mLayout;
102bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
103bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private boolean mIsSearchResult = false;
104bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
105bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
106bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * The actual return type from the loader.
107bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
108bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static class MessagesCursor extends CursorWrapper {
109bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        /**  Whether the mailbox is found. */
110bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public final boolean mIsFound;
111bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        /** {@link Account} that owns the mailbox.  Null for combined mailboxes. */
112bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public final Account mAccount;
113bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        /** {@link Mailbox} for the loaded mailbox. Null for combined mailboxes. */
114bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public final Mailbox mMailbox;
115bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        /** {@code true} if the account is an EAS account */
116bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public final boolean mIsEasAccount;
117bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        /** {@code true} if the loaded mailbox can be refreshed. */
118bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public final boolean mIsRefreshable;
119bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        /** the number of accounts currently configured. */
120bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public final int mCountTotalAccounts;
121bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
122bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        private MessagesCursor(Cursor cursor,
123bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                boolean found, Account account, Mailbox mailbox, boolean isEasAccount,
124bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                boolean isRefreshable, int countTotalAccounts) {
125bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            super(cursor);
126bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mIsFound = found;
127bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mAccount = account;
128bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mMailbox = mailbox;
129bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mIsEasAccount = isEasAccount;
130bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mIsRefreshable = isRefreshable;
131bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mCountTotalAccounts = countTotalAccounts;
132bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
133bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
134bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
135bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public MessagesAdapter(Context context, Callback callback, boolean isSearchResult) {
136bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        super(context.getApplicationContext(), null, 0 /* no auto requery */);
137bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mResourceHelper = ResourceHelper.getInstance(context);
138bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mCallback = callback;
139bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mIsSearchResult = isSearchResult;
140bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
141bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
142bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void setLayout(ThreePaneLayout layout) {
143bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mLayout = layout;
144bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
145bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
146bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void onSaveInstanceState(Bundle outState) {
147bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        outState.putLongArray(STATE_CHECKED_ITEMS, Utility.toPrimitiveLongArray(getSelectedSet()));
148bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
149bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
150bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void loadState(Bundle savedInstanceState) {
151bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        Set<Long> checkedset = getSelectedSet();
152bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        checkedset.clear();
153bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        for (long l: savedInstanceState.getLongArray(STATE_CHECKED_ITEMS)) {
154bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            checkedset.add(l);
155bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
156bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        notifyDataSetChanged();
157bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
158bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
159bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
160bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Set true for combined mailboxes.
161bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
162bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void setShowColorChips(boolean show) {
163bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mShowColorChips = show;
164bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
165bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
166bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void setQuery(String query) {
167bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mQuery = query;
168bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
169bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
170bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public Set<Long> getSelectedSet() {
171bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return mSelectedSet;
172bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
173bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
174bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
175bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Clear the selection.  It's preferable to calling {@link Set#clear()} on
176bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * {@link #getSelectedSet()}, because it also notifies observers.
177bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
178bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void clearSelection() {
179bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        Set<Long> checkedset = getSelectedSet();
180bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (checkedset.size() > 0) {
181bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            checkedset.clear();
182bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            notifyDataSetChanged();
183bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
184bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
185bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
186bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public boolean isSelected(MessageListItem itemView) {
187bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return getSelectedSet().contains(itemView.mMessageId);
188bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
189bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
190bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    @Override
191bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void bindView(View view, Context context, Cursor cursor) {
192bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // Reset the view (in case it was recycled) and prepare for binding
193bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MessageListItem itemView = (MessageListItem) view;
194bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        itemView.bindViewInit(this, mLayout, mIsSearchResult);
195bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
196bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // TODO: just move thise all to a MessageListItem.bindTo(cursor) so that the fields can
197bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // be private, and their inter-dependence when they change can be abstracted away.
198bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
199bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // Load the public fields in the view (for later use)
200bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        itemView.mMessageId = cursor.getLong(COLUMN_ID);
201bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        itemView.mMailboxId = cursor.getLong(COLUMN_MAILBOX_KEY);
202bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        final long accountId = cursor.getLong(COLUMN_ACCOUNT_KEY);
203bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        itemView.mAccountId = accountId;
204bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
205bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        boolean isRead = cursor.getInt(COLUMN_READ) != 0;
206bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        boolean readChanged = isRead != itemView.mRead;
207bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        itemView.mRead = isRead;
208bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        itemView.mIsFavorite = cursor.getInt(COLUMN_FAVORITE) != 0;
209bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        final int flags = cursor.getInt(COLUMN_FLAGS);
210bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        itemView.mHasInvite = (flags & Message.FLAG_INCOMING_MEETING_INVITE) != 0;
211bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        itemView.mHasBeenRepliedTo = (flags & Message.FLAG_REPLIED_TO) != 0;
212bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        itemView.mHasBeenForwarded = (flags & Message.FLAG_FORWARDED) != 0;
213bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        itemView.mHasAttachment = cursor.getInt(COLUMN_ATTACHMENTS) != 0;
214bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        itemView.setTimestamp(cursor.getLong(COLUMN_DATE));
215bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        itemView.mSender = cursor.getString(COLUMN_DISPLAY_NAME);
216bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        itemView.setText(
217bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                cursor.getString(COLUMN_SUBJECT), cursor.getString(COLUMN_SNIPPET), readChanged);
218bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        itemView.mColorChipPaint =
219bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mShowColorChips ? mResourceHelper.getAccountColorPaint(accountId) : null;
220bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
221bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (mQuery != null && itemView.mSnippet != null) {
222bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            itemView.mSnippet =
223bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                TextUtilities.highlightTermsInText(cursor.getString(COLUMN_SNIPPET), mQuery);
224bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
225bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
226bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
227bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    @Override
228bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public View newView(Context context, Cursor cursor, ViewGroup parent) {
229bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MessageListItem item = new MessageListItem(context);
230bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        item.setVisibility(View.VISIBLE);
231bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return item;
232bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
233bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
234bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void toggleSelected(MessageListItem itemView) {
235bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        updateSelected(itemView, !isSelected(itemView));
236bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
237bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
238bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
239bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * This is used as a callback from the list items, to set the selected state
240bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
241bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * <p>Must be called on the UI thread.
242bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
243bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param itemView the item being changed
244bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param newSelected the new value of the selected flag (checkbox state)
245bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
246bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private void updateSelected(MessageListItem itemView, boolean newSelected) {
247bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (newSelected) {
248bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mSelectedSet.add(itemView.mMessageId);
249bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        } else {
250bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mSelectedSet.remove(itemView.mMessageId);
251bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
252bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (mCallback != null) {
253bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mCallback.onAdapterSelectedChanged(itemView, newSelected, mSelectedSet.size());
254bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
255bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
256bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
257bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
258bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * This is used as a callback from the list items, to set the favorite state
259bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
260bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * <p>Must be called on the UI thread.
261bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
262bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param itemView the item being changed
263bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param newFavorite the new value of the favorite flag (star state)
264bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
265bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void updateFavorite(MessageListItem itemView, boolean newFavorite) {
266bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        changeFavoriteIcon(itemView, newFavorite);
267bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (mCallback != null) {
268bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mCallback.onAdapterFavoriteChanged(itemView, newFavorite);
269bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
270bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
271bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
272bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private void changeFavoriteIcon(MessageListItem view, boolean isFavorite) {
273bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        view.invalidate();
274bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
275bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
276bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
277bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Creates the loader for {@link MessageListFragment}.
278bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
279bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return always of {@link MessagesCursor}.
280bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
281bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static Loader<Cursor> createLoader(Context context, MessageListContext listContext) {
282bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
283bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Log.d(Logging.LOG_TAG, "MessagesAdapter createLoader listContext=" + listContext);
284bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
285bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return listContext.isSearch()
286bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                ? new SearchCursorLoader(context, listContext)
287bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                : new MessagesCursorLoader(context, listContext);
288bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
289bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
290bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static class MessagesCursorLoader extends ThrottlingCursorLoader {
291bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        protected final Context mContext;
292bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        private final long mAccountId;
293bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        private final long mMailboxId;
294bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
295bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public MessagesCursorLoader(Context context, MessageListContext listContext) {
296bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // Initialize with no where clause.  We'll set it later.
297bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            super(context, EmailContent.Message.CONTENT_URI,
298bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    MESSAGE_PROJECTION, null, null,
299bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    EmailContent.MessageColumns.TIMESTAMP + " DESC");
300bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mContext = context;
301bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mAccountId = listContext.mAccountId;
302bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mMailboxId = listContext.getMailboxId();
303bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
304bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
305bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        @Override
306bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public Cursor loadInBackground() {
307bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // Build the where cause (which can't be done on the UI thread.)
308bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            setSelection(Message.buildMessageListSelection(mContext, mAccountId, mMailboxId));
309bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // Then do a query to get the cursor
310bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return loadExtras(super.loadInBackground());
311bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
312bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
313bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        private Cursor loadExtras(Cursor baseCursor) {
314bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            boolean found = false;
315bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Account account = null;
316bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Mailbox mailbox = null;
317bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            boolean isEasAccount = false;
318bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            boolean isRefreshable = false;
319bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
320bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            if (mMailboxId < 0) {
321bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                // Magic mailbox.
322bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                found = true;
323bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            } else {
324bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                mailbox = Mailbox.restoreMailboxWithId(mContext, mMailboxId);
325bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                if (mailbox != null) {
326bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    account = Account.restoreAccountWithId(mContext, mailbox.mAccountKey);
327bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    if (account != null) {
328bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        found = true;
329bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        isEasAccount = account.isEasAccount(mContext) ;
330bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        isRefreshable = Mailbox.isRefreshable(mContext, mMailboxId);
331bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    } else { // Account removed?
332bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        mailbox = null;
333bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    }
334bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                }
335bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
336bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            final int countAccounts = EmailContent.count(mContext, Account.CONTENT_URI);
337bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return wrapCursor(baseCursor, found, account, mailbox, isEasAccount,
338bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    isRefreshable, countAccounts);
339bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
340bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
341bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        /**
342bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook         * Wraps a basic cursor containing raw messages with information about the context of
343bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook         * the list that's being loaded, such as the account and the mailbox the messages
344bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook         * are for.
345bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook         * Subclasses may extend this to wrap with additional data.
346bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook         */
347bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        protected Cursor wrapCursor(Cursor cursor,
348bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                boolean found, Account account, Mailbox mailbox, boolean isEasAccount,
349bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                boolean isRefreshable, int countTotalAccounts) {
350bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return new MessagesCursor(cursor, found, account, mailbox, isEasAccount,
351bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    isRefreshable, countTotalAccounts);
352bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
353bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
354bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
355bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public static class SearchResultsCursor extends MessagesCursor {
356bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        private final Mailbox mSearchedMailbox;
357bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        private final int mResultsCount;
358bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        private SearchResultsCursor(Cursor cursor,
359bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                boolean found, Account account, Mailbox mailbox, boolean isEasAccount,
360bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                boolean isRefreshable, int countTotalAccounts,
361bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                Mailbox searchedMailbox, int resultsCount) {
362bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            super(cursor, found, account, mailbox, isEasAccount,
363bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    isRefreshable, countTotalAccounts);
364bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mSearchedMailbox = searchedMailbox;
365bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mResultsCount = resultsCount;
366bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
367bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
368bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        /**
369bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook         * @return the total number of results that match the given search query. Note that
370bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook         *     there may not be that many items loaded in the cursor yet.
371bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook         */
372bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public int getResultsCount() {
373bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return mResultsCount;
374bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
375bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
376bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public Mailbox getSearchedMailbox() {
377bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return mSearchedMailbox;
378bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
379bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
380bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
381bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
382bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * A special loader used to perform a search.
383bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
384bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static class SearchCursorLoader extends MessagesCursorLoader {
385bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        private final MessageListContext mListContext;
386bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        private int mResultsCount = -1;
387bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        private Mailbox mSearchedMailbox = null;
388bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
389bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public SearchCursorLoader(Context context, MessageListContext listContext) {
390bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            super(context, listContext);
391bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Preconditions.checkArgument(listContext.isSearch());
392bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mListContext = listContext;
393bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
394bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
395bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        @Override
396bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public Cursor loadInBackground() {
397bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            if (mResultsCount >= 0) {
398bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                // Result count known - the initial search meta data must have completed.
399bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                return super.loadInBackground();
400bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
401bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
402bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            if (mSearchedMailbox == null) {
403bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                mSearchedMailbox = Mailbox.restoreMailboxWithId(
404bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        mContext, mListContext.getSearchedMailbox());
405bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
406bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
407bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // The search results info hasn't even been loaded yet, so the Controller has not yet
408bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // initialized the search mailbox properly. Kick off the search first.
409bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Controller controller = Controller.getInstance(mContext);
410bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            try {
411bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                mResultsCount = controller.searchMessages(
412bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        mListContext.mAccountId, mListContext.getSearchParams());
413bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            } catch (MessagingException e) {
414bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
415bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
416bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // Return whatever the super would do, now that we know the results are ready.
417bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // After this point, it should behave as a normal mailbox load for messages.
418bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return super.loadInBackground();
419bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
420bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
421bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        @Override
422bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        protected Cursor wrapCursor(Cursor cursor,
423bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                boolean found, Account account, Mailbox mailbox, boolean isEasAccount,
424bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                boolean isRefreshable, int countTotalAccounts) {
425bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return new SearchResultsCursor(cursor, found, account, mailbox, isEasAccount,
426bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    isRefreshable, countTotalAccounts, mSearchedMailbox, mResultsCount);
427bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
428bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
429bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook}
430