Home | History | Annotate | Download | only in list
      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