1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.contacts.common.list; 17 18 import android.content.Context; 19 import android.content.CursorLoader; 20 import android.content.SharedPreferences; 21 import android.database.Cursor; 22 import android.net.Uri; 23 import android.net.Uri.Builder; 24 import android.preference.PreferenceManager; 25 import android.provider.ContactsContract; 26 import android.provider.ContactsContract.Contacts; 27 import android.provider.ContactsContract.Directory; 28 import android.provider.ContactsContract.SearchSnippets; 29 import android.text.TextUtils; 30 import android.view.View; 31 import com.android.contacts.common.compat.ContactsCompat; 32 import com.android.contacts.common.preference.ContactsPreferences; 33 import java.util.ArrayList; 34 import java.util.List; 35 36 /** A cursor adapter for the {@link ContactsContract.Contacts#CONTENT_TYPE} content type. */ 37 public class DefaultContactListAdapter extends ContactListAdapter { 38 39 public DefaultContactListAdapter(Context context) { 40 super(context); 41 } 42 43 @Override 44 public void configureLoader(CursorLoader loader, long directoryId) { 45 String sortOrder = null; 46 if (isSearchMode()) { 47 String query = getQueryString(); 48 if (query == null) { 49 query = ""; 50 } 51 query = query.trim(); 52 if (TextUtils.isEmpty(query)) { 53 // Regardless of the directory, we don't want anything returned, 54 // so let's just send a "nothing" query to the local directory. 55 loader.setUri(Contacts.CONTENT_URI); 56 loader.setProjection(getProjection(false)); 57 loader.setSelection("0"); 58 } else { 59 final Builder builder = ContactsCompat.getContentUri().buildUpon(); 60 appendSearchParameters(builder, query, directoryId); 61 loader.setUri(builder.build()); 62 loader.setProjection(getProjection(true)); 63 } 64 } else { 65 final ContactListFilter filter = getFilter(); 66 configureUri(loader, directoryId, filter); 67 loader.setProjection(getProjection(false)); 68 configureSelection(loader, directoryId, filter); 69 } 70 71 if (getSortOrder() == ContactsPreferences.SORT_ORDER_PRIMARY) { 72 if (sortOrder == null) { 73 sortOrder = Contacts.SORT_KEY_PRIMARY; 74 } else { 75 sortOrder += ", " + Contacts.SORT_KEY_PRIMARY; 76 } 77 } else { 78 if (sortOrder == null) { 79 sortOrder = Contacts.SORT_KEY_ALTERNATIVE; 80 } else { 81 sortOrder += ", " + Contacts.SORT_KEY_ALTERNATIVE; 82 } 83 } 84 loader.setSortOrder(sortOrder); 85 } 86 87 private void appendSearchParameters(Builder builder, String query, long directoryId) { 88 builder.appendPath(query); // Builder will encode the query 89 builder.appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(directoryId)); 90 if (directoryId != Directory.DEFAULT && directoryId != Directory.LOCAL_INVISIBLE) { 91 builder.appendQueryParameter( 92 ContactsContract.LIMIT_PARAM_KEY, 93 String.valueOf(getDirectoryResultLimit(getDirectoryById(directoryId)))); 94 } 95 builder.appendQueryParameter(SearchSnippets.DEFERRED_SNIPPETING_KEY, "1"); 96 } 97 98 protected void configureUri(CursorLoader loader, long directoryId, ContactListFilter filter) { 99 Uri uri = Contacts.CONTENT_URI; 100 101 if (directoryId == Directory.DEFAULT && isSectionHeaderDisplayEnabled()) { 102 uri = ContactListAdapter.buildSectionIndexerUri(uri); 103 } 104 105 // The "All accounts" filter is the same as the entire contents of Directory.DEFAULT 106 if (filter != null 107 && filter.filterType != ContactListFilter.FILTER_TYPE_CUSTOM 108 && filter.filterType != ContactListFilter.FILTER_TYPE_SINGLE_CONTACT) { 109 final Uri.Builder builder = uri.buildUpon(); 110 builder.appendQueryParameter( 111 ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(Directory.DEFAULT)); 112 if (filter.filterType == ContactListFilter.FILTER_TYPE_ACCOUNT) { 113 filter.addAccountQueryParameterToUrl(builder); 114 } 115 uri = builder.build(); 116 } 117 118 loader.setUri(uri); 119 } 120 121 private void configureSelection(CursorLoader loader, long directoryId, ContactListFilter filter) { 122 if (filter == null) { 123 return; 124 } 125 126 if (directoryId != Directory.DEFAULT) { 127 return; 128 } 129 130 StringBuilder selection = new StringBuilder(); 131 List<String> selectionArgs = new ArrayList<String>(); 132 133 switch (filter.filterType) { 134 case ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS: 135 { 136 // We have already added directory=0 to the URI, which takes care of this 137 // filter 138 break; 139 } 140 case ContactListFilter.FILTER_TYPE_SINGLE_CONTACT: 141 { 142 // We have already added the lookup key to the URI, which takes care of this 143 // filter 144 break; 145 } 146 case ContactListFilter.FILTER_TYPE_STARRED: 147 { 148 selection.append(Contacts.STARRED + "!=0"); 149 break; 150 } 151 case ContactListFilter.FILTER_TYPE_WITH_PHONE_NUMBERS_ONLY: 152 { 153 selection.append(Contacts.HAS_PHONE_NUMBER + "=1"); 154 break; 155 } 156 case ContactListFilter.FILTER_TYPE_CUSTOM: 157 { 158 selection.append(Contacts.IN_VISIBLE_GROUP + "=1"); 159 if (isCustomFilterForPhoneNumbersOnly()) { 160 selection.append(" AND " + Contacts.HAS_PHONE_NUMBER + "=1"); 161 } 162 break; 163 } 164 case ContactListFilter.FILTER_TYPE_ACCOUNT: 165 { 166 // We use query parameters for account filter, so no selection to add here. 167 break; 168 } 169 } 170 loader.setSelection(selection.toString()); 171 loader.setSelectionArgs(selectionArgs.toArray(new String[0])); 172 } 173 174 @Override 175 protected void bindView(View itemView, int partition, Cursor cursor, int position) { 176 super.bindView(itemView, partition, cursor, position); 177 final ContactListItemView view = (ContactListItemView) itemView; 178 179 view.setHighlightedPrefix(isSearchMode() ? getUpperCaseQueryString() : null); 180 181 bindSectionHeaderAndDivider(view, position, cursor); 182 183 if (isQuickContactEnabled()) { 184 bindQuickContact( 185 view, 186 partition, 187 cursor, 188 ContactQuery.CONTACT_PHOTO_ID, 189 ContactQuery.CONTACT_PHOTO_URI, 190 ContactQuery.CONTACT_ID, 191 ContactQuery.CONTACT_LOOKUP_KEY, 192 ContactQuery.CONTACT_DISPLAY_NAME); 193 } else { 194 if (getDisplayPhotos()) { 195 bindPhoto(view, partition, cursor); 196 } 197 } 198 199 bindNameAndViewId(view, cursor); 200 bindPresenceAndStatusMessage(view, cursor); 201 202 if (isSearchMode()) { 203 bindSearchSnippet(view, cursor); 204 } else { 205 view.setSnippet(null); 206 } 207 } 208 209 private boolean isCustomFilterForPhoneNumbersOnly() { 210 // TODO: this flag should not be stored in shared prefs. It needs to be in the db. 211 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); 212 return prefs.getBoolean( 213 ContactsPreferences.PREF_DISPLAY_ONLY_PHONES, 214 ContactsPreferences.PREF_DISPLAY_ONLY_PHONES_DEFAULT); 215 } 216 } 217