• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 Google Inc.
3  * Licensed to The Android Open Source Project.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package com.android.mail.ui;
19 
20 import android.content.Context;
21 import android.content.DialogInterface;
22 import android.database.Cursor;
23 import android.net.Uri;
24 
25 import com.android.mail.R;
26 import com.android.mail.providers.Account;
27 import com.android.mail.providers.Conversation;
28 import com.android.mail.providers.Folder;
29 import com.android.mail.providers.UIProvider;
30 import com.android.mail.providers.UIProvider.FolderType;
31 import com.android.mail.ui.FolderSelectorAdapter.FolderRow;
32 import com.android.mail.utils.Utils;
33 import com.google.common.collect.ImmutableSet;
34 
35 import java.util.Arrays;
36 import java.util.Collection;
37 import java.util.HashMap;
38 import java.util.HashSet;
39 import java.util.List;
40 
41 /**
42  * Displays a folder selection dialog for the conversation provided. It allows
43  * the user to mark folders to assign that conversation to.
44  */
45 public class MultiFoldersSelectionDialog extends FolderSelectionDialog {
46     private final boolean mSingle;
47     private final HashMap<Uri, FolderOperation> mOperations;
48 
49     /**
50      * Create a new {@link MultiFoldersSelectionDialog}. It is displayed when
51      * the {@link #show()} method is called.
52      * @param context
53      * @param account the current account
54      * @param updater
55      * @param target conversations that are impacted
56      * @param isBatch whether the dialog is shown during Contextual Action Bar
57      *            (CAB) mode
58      * @param currentFolder the current folder that the
59      *            {@link FolderListFragment} is showing
60      */
MultiFoldersSelectionDialog(final Context context, final Account account, final ConversationUpdater updater, final Collection<Conversation> target, final boolean isBatch, final Folder currentFolder)61     public MultiFoldersSelectionDialog(final Context context, final Account account,
62             final ConversationUpdater updater, final Collection<Conversation> target,
63             final boolean isBatch, final Folder currentFolder) {
64         super(context, account, updater, target, isBatch, currentFolder);
65         mSingle = !account
66                 .supportsCapability(UIProvider.AccountCapabilities.MULTIPLE_FOLDERS_PER_CONV);
67         mOperations = new HashMap<Uri, FolderOperation>();
68 
69         mBuilder.setTitle(R.string.change_folders_selection_dialog_title);
70         mBuilder.setPositiveButton(R.string.ok, this);
71     }
72 
73     @Override
updateAdapterInBackground(Context context)74     protected void updateAdapterInBackground(Context context) {
75         Cursor foldersCursor = null;
76         try {
77             foldersCursor = context.getContentResolver().query(
78                     !Utils.isEmpty(mAccount.fullFolderListUri) ? mAccount.fullFolderListUri
79                             : mAccount.folderListUri, UIProvider.FOLDERS_PROJECTION, null, null,
80                             null);
81             /** All the folders that this conversations is assigned to. */
82             final HashSet<String> checked = new HashSet<String>();
83             for (final Conversation conversation : mTarget) {
84                 final List<Folder> rawFolders = conversation.getRawFolders();
85                 if (rawFolders != null && rawFolders.size() > 0) {
86                     // Parse the raw folders and get all the uris.
87                     checked.addAll(Arrays.asList(Folder.getUriArray(rawFolders)));
88                 } else {
89                     // There are no folders for this conversation, so it must
90                     // belong to the folder we are currently looking at.
91                     checked.add(mCurrentFolder.folderUri.fullUri.toString());
92                 }
93             }
94             // TODO(mindyp) : bring this back in UR8 when Email providers
95             // will have divided folder sections.
96             /* final String[] headers = mContext.getResources()
97              .getStringArray(R.array.moveto_folder_sections);
98              // Currently, the number of adapters are assumed to match the
99              // number of headers in the string array.
100              mAdapter.addSection(new SystemFolderSelectorAdapter(mContext,
101              foldersCursor, checked, R.layout.multi_folders_view, null));
102 
103             // TODO(mindyp): we currently do not support frequently moved to
104             // folders, at headers[1]; need to define what that means.*/
105             mAdapter.addSection(new AddableFolderSelectorAdapter(context,
106                     AddableFolderSelectorAdapter.filterFolders(foldersCursor,
107                             ImmutableSet.of(FolderType.INBOX_SECTION)), checked,
108                     R.layout.multi_folders_view, null));
109             mBuilder.setAdapter(mAdapter, MultiFoldersSelectionDialog.this);
110         } finally {
111             if (foldersCursor != null) {
112                 foldersCursor.close();
113             }
114         }
115     }
116 
117     @Override
onListItemClick(int position)118     protected void onListItemClick(int position) {
119         final Object item = mAdapter.getItem(position);
120         if (item instanceof FolderRow) {
121             update((FolderRow) item);
122         }
123     }
124 
125     /**
126      * Call this to update the state of folders as a result of them being
127      * selected / de-selected.
128      *
129      * @param row The item being updated.
130      */
update(FolderSelectorAdapter.FolderRow row)131     private final void update(FolderSelectorAdapter.FolderRow row) {
132         final boolean add = !row.isPresent();
133         if (mSingle) {
134             if (!add) {
135                 // This would remove the check on a single radio button, so just
136                 // return.
137                 return;
138             }
139             // Clear any other checked items.
140             for (int i = 0, size = mAdapter.getCount(); i < size; i++) {
141                 final Object item = mAdapter.getItem(i);
142                 if (item instanceof FolderRow) {
143                    ((FolderRow)item).setIsPresent(false);
144                    final Folder folder = ((FolderRow)item).getFolder();
145                    mOperations.put(folder.folderUri.fullUri,
146                            new FolderOperation(folder, false));
147                 }
148             }
149         }
150         row.setIsPresent(add);
151         mAdapter.notifyDataSetChanged();
152         final Folder folder = row.getFolder();
153         mOperations.put(folder.folderUri.fullUri, new FolderOperation(folder, add));
154     }
155 
156     @Override
onClick(DialogInterface dialog, int which)157     public void onClick(DialogInterface dialog, int which) {
158         switch (which) {
159             case DialogInterface.BUTTON_POSITIVE:
160                 if (mUpdater != null) {
161                     mUpdater.assignFolder(mOperations.values(), mTarget, mBatch,
162                             true /* showUndo */, false /* isMoveTo */);
163                 }
164                 break;
165             case DialogInterface.BUTTON_NEGATIVE:
166                 break;
167             default:
168                 break;
169         }
170     }
171 }
172