1bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/*
2bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Copyright (C) 2011 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.ContentUris;
20bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.content.Context;
21bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.content.Loader;
22bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.database.Cursor;
23bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.database.CursorWrapper;
24bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.database.MatrixCursor;
25bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.database.MatrixCursor.RowBuilder;
26bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.database.MergeCursor;
27bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.util.Log;
28bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.view.LayoutInflater;
29bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.view.View;
30bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.view.ViewGroup;
31bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.widget.AdapterView;
32bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.widget.CursorAdapter;
33bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.widget.ImageView;
34bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport android.widget.TextView;
35bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
36bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.Email;
37bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.FolderProperties;
38bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.R;
39bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.ResourceHelper;
40bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.data.ClosingMatrixCursor;
41bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.email.data.ThrottlingCursorLoader;
42bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.Logging;
43bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.provider.Account;
44bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.provider.EmailContent;
45bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.provider.EmailContent.AccountColumns;
46bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.provider.EmailContent.MailboxColumns;
47bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.provider.EmailContent.Message;
48bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.provider.Mailbox;
49bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.android.emailcommon.utility.Utility;
50bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport com.google.common.annotations.VisibleForTesting;
51bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
52bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.util.ArrayList;
53bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
54bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/**
55bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Mailbox cursor adapter for the mailbox list fragment.
56bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
57bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * A mailbox cursor may contain one of several different types of data. Currently, this
58bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * adapter supports the following views:
59bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 1. The standard inbox, mailbox view
60bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 2. The combined mailbox view
61bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 3. Nested folder navigation
62bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
63bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * TODO At a minimum, we should break out the loaders. They have no relation to the view code
64bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * and only serve to confuse the user.
65bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * TODO Determine if we actually need a separate adapter / view / loader for nested folder
66bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * navigation. It's a little convoluted at the moment, but, still manageable.
67bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */
68bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookclass MailboxFragmentAdapter extends CursorAdapter {
69bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
70bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Callback interface used to report clicks other than the basic list item click or long press.
71bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
72bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    interface Callback {
73bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        /** Callback for setting background of mailbox list items during a drag */
74bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public void onBind(MailboxListItem listItem);
75bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
76bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
77bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** Do-nothing callback to avoid null tests for <code>mCallback</code>. */
78bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final class EmptyCallback implements Callback {
79bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public static final Callback INSTANCE = new EmptyCallback();
80bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        @Override public void onBind(MailboxListItem listItem) { }
81bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
82bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
83bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /*
84bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * The type of the row to present to the user. There are 4 defined rows that each
85bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * have a slightly different look. These are typically used in the constant column
86bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * {@link #ROW_TYPE} specified in {@link #PROJECTION} and {@link #SUBMAILBOX_PROJECTION}.
87bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
88bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** Both regular and combined mailboxes */
89bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final int ROW_TYPE_MAILBOX = 0;
90bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** Account "mailboxes" in the combined view */
91bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final int ROW_TYPE_ACCOUNT = 1;
92bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    // The following types are used when drilling into a mailbox
93bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** The current mailbox */
94bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final int ROW_TYPE_CURMAILBOX = 2;
95bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** Sub mailboxes */
96bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final int ROW_TYPE_SUBMAILBOX = 3;
97bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** Header */
98bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final int ROW_TYPE_HEADER = 4;
99bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
100bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** The type of data contained in the cursor row. */
101bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final String ROW_TYPE = "rowType";
102bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** The original ID of the cursor row. May be negative. */
103bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final String ORIGINAL_ID = "orgMailboxId";
104bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
105bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Projection for a typical mailbox or account row.
106bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * <p><em>NOTE</em> This projection contains two ID columns. The first, named "_id", is used
107bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * by the framework ListView implementation. Since ListView does not handle negative IDs in
108bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * this column, we define a "mailbox_id" column that contains the real mailbox ID; which
109bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * may be negative for special mailboxes.
110bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
111bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final String[] PROJECTION = new String[] { MailboxColumns.ID,
112bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            MailboxColumns.ID + " AS " + ORIGINAL_ID,
113bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            MailboxColumns.DISPLAY_NAME, MailboxColumns.TYPE, MailboxColumns.UNREAD_COUNT,
114bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            MailboxColumns.MESSAGE_COUNT, ROW_TYPE_MAILBOX + " AS " + ROW_TYPE,
115bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            MailboxColumns.FLAGS, MailboxColumns.ACCOUNT_KEY };
116bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
117bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Projection used to retrieve immediate children for a mailbox. The columns need to
118bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * be identical to those in {@link #PROJECTION}. We are only changing the constant
119bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * column {@link #ROW_TYPE}.
120bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
121bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final String[] SUBMAILBOX_PROJECTION = new String[] { MailboxColumns.ID,
122bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MailboxColumns.ID + " AS " + ORIGINAL_ID,
123bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MailboxColumns.DISPLAY_NAME, MailboxColumns.TYPE, MailboxColumns.UNREAD_COUNT,
124bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MailboxColumns.MESSAGE_COUNT, ROW_TYPE_SUBMAILBOX + " AS " + ROW_TYPE,
125bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MailboxColumns.FLAGS, MailboxColumns.ACCOUNT_KEY };
126bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final String[] CURMAILBOX_PROJECTION = new String[] { MailboxColumns.ID,
127bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MailboxColumns.ID + " AS " + ORIGINAL_ID,
128bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MailboxColumns.DISPLAY_NAME, MailboxColumns.TYPE, MailboxColumns.UNREAD_COUNT,
129bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MailboxColumns.MESSAGE_COUNT, ROW_TYPE_CURMAILBOX + " AS " + ROW_TYPE,
130bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MailboxColumns.FLAGS, MailboxColumns.ACCOUNT_KEY };
131bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** Project to use for matrix cursors; rows MUST be identical to {@link #PROJECTION} */
132bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final String[] MATRIX_PROJECTION = new String[] {
133bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MailboxColumns.ID, ORIGINAL_ID, MailboxColumns.DISPLAY_NAME, MailboxColumns.TYPE,
134bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MailboxColumns.UNREAD_COUNT, MailboxColumns.MESSAGE_COUNT, ROW_TYPE, MailboxColumns.FLAGS,
135bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MailboxColumns.ACCOUNT_KEY };
136bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
137bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** All mailboxes for the account */
138bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final String ALL_MAILBOX_SELECTION = MailboxColumns.ACCOUNT_KEY + "=?" +
139bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            " AND " + Mailbox.USER_VISIBLE_MAILBOX_SELECTION;
140bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** All system mailboxes for an account */
141bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final String SYSTEM_MAILBOX_SELECTION = ALL_MAILBOX_SELECTION
142bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            + " AND " + MailboxColumns.TYPE + "!=" + Mailbox.TYPE_MAIL;
143bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** All mailboxes with the given parent */
144bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final String USER_MAILBOX_SELECTION_WITH_PARENT = ALL_MAILBOX_SELECTION
145bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            + " AND " + MailboxColumns.PARENT_KEY + "=?"
146bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            + " AND " + MailboxColumns.TYPE + "=" + Mailbox.TYPE_MAIL;
147bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** Selection for a specific mailbox */
148bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final String MAILBOX_SELECTION = MailboxColumns.ACCOUNT_KEY + "=?"
149bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            + " AND " + MailboxColumns.ID + "=?";
150bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
151bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final String MAILBOX_ORDER_BY = "CASE " + MailboxColumns.TYPE
152bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            + " WHEN " + Mailbox.TYPE_INBOX   + " THEN 0"
153bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            + " WHEN " + Mailbox.TYPE_DRAFTS  + " THEN 1"
154bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            + " WHEN " + Mailbox.TYPE_OUTBOX  + " THEN 2"
155bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            + " WHEN " + Mailbox.TYPE_SENT    + " THEN 3"
156bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            + " WHEN " + Mailbox.TYPE_TRASH   + " THEN 4"
157bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            + " WHEN " + Mailbox.TYPE_JUNK    + " THEN 5"
158bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // Other mailboxes (i.e. of Mailbox.TYPE_MAIL) are shown in alphabetical order.
159bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            + " ELSE 10 END"
160bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            + " ," + MailboxColumns.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
161bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
162bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** View is of a "normal" row */
163bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final int ITEM_VIEW_TYPE_NORMAL = 0;
164bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** View is of a separator row */
165bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static final int ITEM_VIEW_TYPE_HEADER = AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
166bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
167bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static boolean sEnableUpdate = true;
168bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private final LayoutInflater mInflater;
169bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private final ResourceHelper mResourceHelper;
170bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private final Callback mCallback;
171bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
172bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public MailboxFragmentAdapter(Context context, Callback callback) {
173bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        super(context, null, 0 /* flags; no content observer */);
174bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
175bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mCallback = (callback == null) ? EmptyCallback.INSTANCE : callback;
176bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mResourceHelper = ResourceHelper.getInstance(context);
177bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
178bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
179bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    @Override
180bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public int getViewTypeCount() {
181bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return 2;
182bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
183bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
184bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    @Override
185bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public int getItemViewType(int position) {
186bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return isHeader(position) ? ITEM_VIEW_TYPE_HEADER : ITEM_VIEW_TYPE_NORMAL;
187bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
188bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
189bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    @Override
190bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public boolean isEnabled(int position) {
191bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return !isHeader(position);
192bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
193bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
194bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    // The LabelList has headers which are not
195bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    // enabled.
196bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    @Override
197bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public boolean areAllItemsEnabled() {
198bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return false;
199bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
200bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
201bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    @Override
202bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void bindView(View view, Context context, Cursor cursor) {
203bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (view instanceof MailboxListItem) {
204bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            bindListItem(view, context, cursor);
205bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        } else {
206bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            bindListHeader(view, context, cursor);
207bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
208bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
209bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
210bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    @Override
211bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public View newView(Context context, Cursor cursor, ViewGroup parent) {
212bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (cursor.getInt(cursor.getColumnIndex(ROW_TYPE)) == ROW_TYPE_HEADER) {
213bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return mInflater.inflate(R.layout.mailbox_list_header, parent, false);
214bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
215bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return mInflater.inflate(R.layout.mailbox_list_item, parent, false);
216bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
217bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
218bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private boolean isHeader(int position) {
219bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        Cursor c = getCursor();
220bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if ((c == null) || c.isClosed()) {
221bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return false;
222bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
223bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        c.moveToPosition(position);
224bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        int rowType = c.getInt(c.getColumnIndex(ROW_TYPE));
225bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return rowType == ROW_TYPE_HEADER;
226bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
227bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
228bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** Returns {@code true} if the specified row is of an account in the combined view. */
229bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    boolean isAccountRow(int position) {
230bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return isAccountRow((Cursor) getItem(position));
231bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
232bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
233bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
234bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Returns {@code true} if the specified row is a mailbox.
235bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * ({@link #ROW_TYPE_MAILBOX}, {@link #ROW_TYPE_CURMAILBOX} and {@link #ROW_TYPE_SUBMAILBOX})
236bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
237bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    boolean isMailboxRow(int position) {
238bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return isMailboxRow((Cursor) getItem(position));
239bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
240bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
241bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** Returns {@code true} if the current row is of an account in the combined view. */
242bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static boolean isAccountRow(Cursor cursor) {
243bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return getRowType(cursor) == ROW_TYPE_ACCOUNT;
244bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
245bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
246bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /** Returns {@code true} if the current row is a header */
247bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static boolean isHeaderRow(Cursor cursor) {
248bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return getRowType(cursor) == ROW_TYPE_HEADER;
249bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
250bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
251bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
252bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Returns {@code true} if the current row is a mailbox.
253bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * ({@link #ROW_TYPE_MAILBOX}, {@link #ROW_TYPE_CURMAILBOX} and {@link #ROW_TYPE_SUBMAILBOX})
254bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
255bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static boolean isMailboxRow(Cursor cursor) {
256bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return !(isAccountRow(cursor) || isHeaderRow(cursor));
257bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
258bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
259bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
260bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Returns the ID of the given row. It may be a mailbox or account ID depending upon the
261bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * result of {@link #isAccountRow}.
262bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
263bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    long getId(int position) {
264bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        Cursor c = (Cursor) getItem(position);
265bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return getId(c);
266bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
267bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
268bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
269bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Returns the account ID of the mailbox owner for the given row. If the given row is a
270bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * combined mailbox, {@link Account#ACCOUNT_ID_COMBINED_VIEW} is returned. If the given
271bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * row is an account, returns the account's ID [the same as {@link #ORIGINAL_ID}].
272bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
273bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    long getAccountId(int position) {
274bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        Cursor c = (Cursor) getItem(position);
275bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return getAccountId(c);
276bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
277bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
278bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
279bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Turn on and off list updates; during a drag operation, we do NOT want to the list of
280bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * mailboxes to update, as this would be visually jarring
281bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param state whether or not the MailboxList can be updated
282bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
283bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    static void enableUpdates(boolean state) {
284bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        sEnableUpdate = state;
285bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
286bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
287bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static String getDisplayName(Context context, Cursor cursor) {
288bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        final String name = cursor.getString(cursor.getColumnIndex(MailboxColumns.DISPLAY_NAME));
289bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (isHeaderRow(cursor) || isAccountRow(cursor)) {
290bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // Always use actual name
291bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return name;
292bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        } else {
293bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // Use this method for two purposes:
294bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // - Set combined mailbox names
295bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // - Rewrite special mailbox names (e.g. trash)
296bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            FolderProperties fp = FolderProperties.getInstance(context);
297bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return fp.getDisplayName(getType(cursor), getId(cursor), name);
298bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
299bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
300bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
301bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    static long getId(Cursor cursor) {
302bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return cursor.getLong(cursor.getColumnIndex(ORIGINAL_ID));
303bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
304bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
305bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    static int getType(Cursor cursor) {
306bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return cursor.getInt(cursor.getColumnIndex(MailboxColumns.TYPE));
307bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
308bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
309bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    static int getMessageCount(Cursor cursor) {
310bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return cursor.getInt(cursor.getColumnIndex(MailboxColumns.MESSAGE_COUNT));
311bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
312bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
313bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    static int getUnreadCount(Cursor cursor) {
314bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return cursor.getInt(cursor.getColumnIndex(MailboxColumns.UNREAD_COUNT));
315bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
316bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
317bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    static long getAccountId(Cursor cursor) {
318bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return cursor.getLong(cursor.getColumnIndex(MailboxColumns.ACCOUNT_KEY));
319bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
320bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
321bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static int getRowType(Cursor cursor) {
322bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return cursor.getInt(cursor.getColumnIndex(ROW_TYPE));
323bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
324bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
325bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static int getFlags(Cursor cursor) {
326bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return cursor.getInt(cursor.getColumnIndex(MailboxColumns.FLAGS));
327bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
328bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
329bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
330bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * {@link Cursor} with extra information which is returned by the loader created by
331bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * {@link MailboxFragmentAdapter#createMailboxesLoader}.
332bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
333bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    static class CursorWithExtras extends CursorWrapper {
334bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        /**
335bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook         * The number of mailboxes in the cursor if the cursor contains top-level mailboxes.
336bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook         * Otherwise, the number of *child* mailboxes.
337bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook         */
338bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public final int mChildCount;
339bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
340bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        CursorWithExtras(Cursor cursor, int childCount) {
341bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            super(cursor);
342bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mChildCount = childCount;
343bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
344bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
345bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
346bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private void bindListHeader(View view, Context context, Cursor cursor) {
347bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        final TextView nameView = (TextView) view.findViewById(R.id.display_name);
348bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        nameView.setText(getDisplayName(context, cursor));
349bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
350bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
351bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private void bindListItem(View view, Context context, Cursor cursor) {
352bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        final boolean isAccount = isAccountRow(cursor);
353bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        final int type = getType(cursor);
354bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        final long id = getId(cursor);
355bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        final long accountId = getAccountId(cursor);
356bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        final int flags = getFlags(cursor);
357bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        final int rowType = getRowType(cursor);
358bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        final boolean hasVisibleChildren = (flags & Mailbox.FLAG_HAS_CHILDREN) != 0
359bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                && (flags & Mailbox.FLAG_CHILDREN_VISIBLE) != 0;
360bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
361bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MailboxListItem listItem = (MailboxListItem)view;
362bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        listItem.mMailboxId = isAccountRow(cursor) ? Mailbox.NO_MAILBOX : id;
363bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        listItem.mMailboxType = type;
364bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        listItem.mAccountId = accountId;
365bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        listItem.mIsValidDropTarget = (id >= 0)
366bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                && !Utility.arrayContains(Mailbox.INVALID_DROP_TARGETS, type)
367bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                && (flags & Mailbox.FLAG_ACCEPTS_MOVED_MAIL) != 0;
368bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        listItem.mIsNavigable = hasVisibleChildren;
369bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
370bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        listItem.mAdapter = this;
371bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // Set the background depending on whether we're in drag mode, the mailbox is a valid
372bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // target, etc.
373bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mCallback.onBind(listItem);
374bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
375bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // Set mailbox name
376bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        final TextView nameView = (TextView) view.findViewById(R.id.mailbox_name);
377bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        nameView.setText(getDisplayName(context, cursor));
378bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // Set count
379bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        final int count;
380bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (isAccountRow(cursor)) {
381bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            count = getUnreadCount(cursor);
382bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        } else {
383bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            FolderProperties fp = FolderProperties.getInstance(context);
384bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            count = fp.getMessageCount(type, getUnreadCount(cursor), getMessageCount(cursor));
385bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
386bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        final TextView countView = (TextView) view.findViewById(R.id.message_count);
387bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
388bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // Set folder icon
389bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        final ImageView folderIcon = (ImageView) view.findViewById(R.id.folder_icon);
390bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        folderIcon.setImageDrawable(
391bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                FolderProperties.getInstance(context).getIcon(type, id, flags));
392bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
393bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        final ImageView mailboxExpandedIcon =
394bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                (ImageView) view.findViewById(R.id.folder_expanded_icon);
395bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        switch (rowType) {
396bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            case ROW_TYPE_SUBMAILBOX:
397bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                if (hasVisibleChildren) {
398bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    mailboxExpandedIcon.setVisibility(View.VISIBLE);
399bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    mailboxExpandedIcon.setImageResource(
400bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                            R.drawable.ic_mailbox_collapsed_holo_light);
401bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                } else {
402bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    mailboxExpandedIcon.setVisibility(View.INVISIBLE);
403bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    mailboxExpandedIcon.setImageDrawable(null);
404bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                }
405bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                folderIcon.setVisibility(View.INVISIBLE);
406bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                break;
407bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            case ROW_TYPE_CURMAILBOX:
408bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                mailboxExpandedIcon.setVisibility(View.GONE);
409bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                mailboxExpandedIcon.setImageDrawable(null);
410bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                folderIcon.setVisibility(View.GONE);
411bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                break;
412bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            case ROW_TYPE_MAILBOX:
413bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            default: // Includes ROW_TYPE_ACCOUNT
414bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                if (hasVisibleChildren) {
415bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    mailboxExpandedIcon.setVisibility(View.VISIBLE);
416bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    mailboxExpandedIcon.setImageResource(
417bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                            R.drawable.ic_mailbox_collapsed_holo_light);
418bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                } else {
419bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    mailboxExpandedIcon.setVisibility(View.GONE);
420bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    mailboxExpandedIcon.setImageDrawable(null);
421bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                }
422bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                folderIcon.setVisibility(View.VISIBLE);
423bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                break;
424bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
425bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
426bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // If the unread count is zero, not to show countView.
427bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (count > 0) {
428bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            countView.setVisibility(View.VISIBLE);
429bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            countView.setText(Integer.toString(count));
430bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        } else {
431bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            countView.setVisibility(View.GONE);
432bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
433bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
434bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        final View chipView = view.findViewById(R.id.color_chip);
435bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (isAccount) {
436bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            chipView.setVisibility(View.VISIBLE);
437bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            chipView.setBackgroundColor(mResourceHelper.getAccountColor(id));
438bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        } else {
439bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            chipView.setVisibility(View.GONE);
440bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
441bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
442bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
443bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
444bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Returns a cursor loader for the mailboxes of the given account.  If <code>parentKey</code>
445bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * refers to a valid mailbox ID [e.g. non-zero], restrict the loader to only those mailboxes
446bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * contained by this parent mailbox.
447bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
448bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Note the returned loader always returns a {@link CursorWithExtras}.
449bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
450bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    static Loader<Cursor> createMailboxesLoader(Context context, long accountId,
451bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            long parentMailboxId) {
452bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
453bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Log.d(Logging.LOG_TAG, "MailboxFragmentAdapter#CursorWithExtras accountId=" + accountId
454bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    + " parentMailboxId=" + parentMailboxId);
455bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
456bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (accountId == Account.ACCOUNT_ID_COMBINED_VIEW) {
457bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            throw new IllegalArgumentException();
458bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
459bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return new MailboxFragmentLoader(context, accountId, parentMailboxId);
460bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
461bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
462bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
463bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Returns a cursor loader for the combined view.
464bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
465bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    static Loader<Cursor> createCombinedViewLoader(Context context) {
466bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (Logging.DEBUG_LIFECYCLE && Email.DEBUG) {
467bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            Log.d(Logging.LOG_TAG, "MailboxFragmentAdapter#createCombinedViewLoader");
468bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
469bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return new CombinedMailboxLoader(context);
470bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
471bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
472bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
473bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Adds a new row into the given cursor.
474bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
475bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static void addMailboxRow(MatrixCursor cursor, long mailboxId, String displayName,
476bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            int mailboxType, int unreadCount, int messageCount, int rowType, int flags,
477bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            long accountId) {
478bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        long listId = mailboxId;
479bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (mailboxId < 0) {
480bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            listId = Long.MAX_VALUE + mailboxId; // IDs for the list view must be positive
481bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
482bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        RowBuilder row = cursor.newRow();
483bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        row.add(listId);
484bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        row.add(mailboxId);
485bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        row.add(displayName);
486bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        row.add(mailboxType);
487bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        row.add(unreadCount);
488bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        row.add(messageCount);
489bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        row.add(rowType);
490bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        row.add(flags);
491bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        row.add(accountId);
492bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
493bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
494bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static void addCombinedMailboxRow(Context context, MatrixCursor cursor, long id,
495bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            int mailboxType, boolean showAlways) {
496bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (id >= 0) {
497bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            throw new IllegalArgumentException(); // Must be QUERY_ALL_*, which are all negative
498bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
499bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        int count = FolderProperties.getMessageCountForCombinedMailbox(context, id);
500bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (showAlways || (count > 0)) {
501bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            addMailboxRow(
502bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    cursor, id, "", mailboxType, count, count, ROW_TYPE_MAILBOX, Mailbox.FLAG_NONE,
503bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    Account.ACCOUNT_ID_COMBINED_VIEW);
504bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
505bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
506bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
507bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
508bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Loads mailboxes that are the children of a given mailbox ID.
509bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
510bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * The returned {@link Cursor} is always a {@link CursorWithExtras}.
511bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
512bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private static class MailboxFragmentLoader extends ThrottlingCursorLoader {
513bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        private final Context mContext;
514bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        private final long mAccountId;
515bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        private final long mParentKey;
516bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
517bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        MailboxFragmentLoader(Context context, long accountId, long parentKey) {
518bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            super(context, Mailbox.CONTENT_URI,
519bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    (parentKey != Mailbox.NO_MAILBOX)
520bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                            ? SUBMAILBOX_PROJECTION
521bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                            : PROJECTION,
522bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    USER_MAILBOX_SELECTION_WITH_PARENT,
523bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    new String[] { Long.toString(accountId), Long.toString(parentKey) },
524bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    MAILBOX_ORDER_BY);
525bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mContext = context;
526bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mAccountId = accountId;
527bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mParentKey = parentKey;
528bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
529bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
530bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        @Override
531bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public void onContentChanged() {
532bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            if (sEnableUpdate) {
533bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                super.onContentChanged();
534bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
535bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
536bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
537bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        @Override
538bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public Cursor loadInBackground() {
539bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            boolean parentRemoved = false;
540bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
541bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            final Cursor userMailboxCursor = super.loadInBackground();
542bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            final Cursor returnCursor;
543bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
544bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            final int childCount = userMailboxCursor.getCount();
545bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
546bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            if (mParentKey != Mailbox.NO_MAILBOX) {
547bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                // If we're not showing the top level mailboxes, add the "parent" mailbox.
548bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                final Cursor parentCursor = getContext().getContentResolver().query(
549bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        Mailbox.CONTENT_URI, CURMAILBOX_PROJECTION, MAILBOX_SELECTION,
550bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        new String[] { Long.toString(mAccountId), Long.toString(mParentKey) },
551bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        null);
552bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                returnCursor = new MergeCursor(new Cursor[] { parentCursor, userMailboxCursor });
553bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            } else {
554bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                // TODO Add per-account starred mailbox support
555bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                final MatrixCursor starredCursor = new MatrixCursor(MATRIX_PROJECTION);
556bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                final Cursor systemMailboxCursor = mContext.getContentResolver().query(
557bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        Mailbox.CONTENT_URI, PROJECTION, SYSTEM_MAILBOX_SELECTION,
558bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        new String[] { Long.toString(mAccountId) }, MAILBOX_ORDER_BY);
559bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                final MatrixCursor recentCursor = new MatrixCursor(MATRIX_PROJECTION);
560bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                final MatrixCursor headerCursor = new MatrixCursor(MATRIX_PROJECTION);
561bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                if (childCount > 0) {
562bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    final String name = mContext.getString(R.string.mailbox_list_user_mailboxes);
563bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    addMailboxRow(headerCursor, 0L, name, 0, 0, 0, ROW_TYPE_HEADER, 0, 0L);
564bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                }
565bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                ArrayList<Long> recentList = null;
566bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                boolean useTwoPane = UiUtilities.useTwoPane(mContext);
567bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                if (useTwoPane) {
568bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    recentList = RecentMailboxManager.getInstance(mContext)
569bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                            .getMostRecent(mAccountId, true);
570bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                }
571bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                if (recentList != null && recentList.size() > 0) {
572bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    final String name = mContext.getString(R.string.mailbox_list_recent_mailboxes);
573bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    addMailboxRow(recentCursor, 0L, name, 0, 0, 0, ROW_TYPE_HEADER, 0, 0L);
574bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    for (long mailboxId : recentList) {
575bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        final Mailbox mailbox = Mailbox.restoreMailboxWithId(mContext, mailboxId);
576bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        if (mailbox == null) continue;
577bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        final int messageCount = Utility.getFirstRowInt(mContext,
578bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                            ContentUris.withAppendedId(Mailbox.CONTENT_URI, mailboxId),
579bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                            new String[] { MailboxColumns.MESSAGE_COUNT }, null, null, null, 0);
580bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        final int unreadCount = Utility.getFirstRowInt(mContext,
581bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                            ContentUris.withAppendedId(Mailbox.CONTENT_URI, mailboxId),
582bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                            new String[] { MailboxColumns.UNREAD_COUNT }, null, null, null, 0);
583bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        addMailboxRow(recentCursor, mailboxId, mailbox.mDisplayName, mailbox.mType,
584bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                            unreadCount, messageCount, ROW_TYPE_MAILBOX, mailbox.mFlags,
585bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                            mailbox.mAccountKey);
586bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    }
587bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                }
588bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                int accountStarredCount = Message.getFavoriteMessageCount(mContext, mAccountId);
589bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                if (accountStarredCount > 0) {
590bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    // Only add "Starred", if there is at least one starred message
591bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    addCombinedMailboxRow(mContext, starredCursor, Mailbox.QUERY_ALL_FAVORITES,
592bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                            Mailbox.TYPE_MAIL, true);
593bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                }
594bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                returnCursor = new MergeCursor(new Cursor[] {
595bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        starredCursor, systemMailboxCursor, recentCursor, headerCursor,
596bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        userMailboxCursor, });
597bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
598bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return new CursorWithExtras(returnCursor, childCount);
599bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
600bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
601bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
602bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
603bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Loader for mailboxes in "Combined view".
604bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
605bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    @VisibleForTesting
606bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    static class CombinedMailboxLoader extends ThrottlingCursorLoader {
607bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        private static final String[] ACCOUNT_PROJECTION = new String[] {
608bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            EmailContent.RECORD_ID, AccountColumns.DISPLAY_NAME,
609bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        };
610bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        private static final int COLUMN_ACCOUND_ID = 0;
611bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        private static final int COLUMN_ACCOUNT_DISPLAY_NAME = 1;
612bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
613bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        private final Context mContext;
614bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
615bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        private CombinedMailboxLoader(Context context) {
616bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            super(context, Account.CONTENT_URI, ACCOUNT_PROJECTION, null, null, null);
617bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            mContext = context;
618bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
619bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
620bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        @Override
621bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        public Cursor loadInBackground() {
622bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            final Cursor accounts = super.loadInBackground();
623bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
624bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // Build combined mailbox rows.
625bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            final MatrixCursor returnCursor = buildCombinedMailboxes(mContext, accounts);
626bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
627bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // Add account rows.
628bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            accounts.moveToPosition(-1);
629bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            while (accounts.moveToNext()) {
630bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                final long accountId = accounts.getLong(COLUMN_ACCOUND_ID);
631bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                final String accountName = accounts.getString(COLUMN_ACCOUNT_DISPLAY_NAME);
632bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                final int unreadCount = Mailbox.getUnreadCountByAccountAndMailboxType(
633bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        mContext, accountId, Mailbox.TYPE_INBOX);
634bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                addMailboxRow(returnCursor, accountId, accountName, Mailbox.TYPE_NONE,
635bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        unreadCount, unreadCount, ROW_TYPE_ACCOUNT, Mailbox.FLAG_NONE,
636bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                        accountId);
637bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
638bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return returnCursor;
639bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
640bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
641bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        @VisibleForTesting
642bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        static MatrixCursor buildCombinedMailboxes(Context c, Cursor innerCursor) {
643bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            MatrixCursor cursor = new ClosingMatrixCursor(MATRIX_PROJECTION, innerCursor);
644bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // Combined inbox -- show unread count
645bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            addCombinedMailboxRow(c, cursor, Mailbox.QUERY_ALL_INBOXES, Mailbox.TYPE_INBOX, true);
646bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
647bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // Favorite (starred) -- show # of favorites
648bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            addCombinedMailboxRow(c, cursor, Mailbox.QUERY_ALL_FAVORITES, Mailbox.TYPE_MAIL, false);
649bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
650bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // Drafts -- show # of drafts
651bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            addCombinedMailboxRow(c, cursor, Mailbox.QUERY_ALL_DRAFTS, Mailbox.TYPE_DRAFTS, false);
652bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
653bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            // Outbox -- # of outstanding messages
654bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            addCombinedMailboxRow(c, cursor, Mailbox.QUERY_ALL_OUTBOX, Mailbox.TYPE_OUTBOX, false);
655bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
656bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return cursor;
657bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
658bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
659bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook}
660