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