1 /*
2  * Copyright (C) 2016 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.group;
17 
18 import android.content.Context;
19 import android.content.CursorLoader;
20 import android.database.Cursor;
21 import android.net.Uri;
22 import android.provider.ContactsContract;
23 import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
24 import android.provider.ContactsContract.Contacts;
25 import android.provider.ContactsContract.Data;
26 import android.provider.ContactsContract.Directory;
27 import android.view.View;
28 import android.view.ViewGroup;
29 
30 import com.android.contacts.R;
31 import com.android.contacts.list.ContactListItemView;
32 import com.android.contacts.list.MultiSelectEntryContactListAdapter;
33 import com.android.contacts.preference.ContactsPreferences;
34 
35 /** Group members cursor adapter. */
36 public class GroupMembersAdapter extends MultiSelectEntryContactListAdapter {
37 
38     public static class GroupMembersQuery {
39 
40         private static final String[] PROJECTION_PRIMARY = new String[] {
41                 Data.CONTACT_ID,
42                 Data.RAW_CONTACT_ID,
43                 Data.PHOTO_ID,
44                 Data.LOOKUP_KEY,
45                 Data.CONTACT_PRESENCE,
46                 Data.CONTACT_STATUS,
47                 Data.DISPLAY_NAME_PRIMARY,
48         };
49 
50         private static final String[] PROJECTION_ALTERNATIVE = new String[] {
51                 Data.CONTACT_ID,
52                 Data.RAW_CONTACT_ID,
53                 Data.PHOTO_ID,
54                 Data.LOOKUP_KEY,
55                 Data.CONTACT_PRESENCE,
56                 Data.CONTACT_STATUS,
57                 Data.DISPLAY_NAME_ALTERNATIVE,
58         };
59 
60         public static final int CONTACT_ID                   = 0;
61         public static final int RAW_CONTACT_ID               = 1;
62         public static final int CONTACT_PHOTO_ID             = 2;
63         public static final int CONTACT_LOOKUP_KEY           = 3;
64         public static final int CONTACT_PRESENCE             = 4;
65         public static final int CONTACT_STATUS               = 5;
66         public static final int CONTACT_DISPLAY_NAME         = 6;
67     }
68 
69     private final CharSequence mUnknownNameText;
70     private long mGroupId;
71     private boolean mDisplayDeleteButtons;
72 
GroupMembersAdapter(Context context)73     public GroupMembersAdapter(Context context) {
74         super(context, GroupMembersQuery.CONTACT_ID);
75 
76         mUnknownNameText = context.getText(R.string.missing_name);
77     }
78 
79     /** Sets the ID of the group whose members will be displayed. */
setGroupId(long groupId)80     public void setGroupId(long groupId) {
81         mGroupId = groupId;
82     }
83 
84     /** Returns the lookup Uri for the contact at the given position in the underlying cursor. */
getContactUri(int position)85     public Uri getContactUri(int position) {
86         final Cursor cursor = (Cursor) getItem(position);
87         final long contactId = cursor.getLong(GroupMembersQuery.CONTACT_ID);
88         final String lookupKey = cursor.getString(GroupMembersQuery.CONTACT_LOOKUP_KEY);
89         return Contacts.getLookupUri(contactId, lookupKey);
90     }
91 
92     /** Returns the ID of the contact at the given position in the underlying cursor. */
getContactId(int position)93     public long getContactId(int position) {
94         final Cursor cursor = (Cursor) getItem(position);
95         return cursor.getLong(GroupMembersQuery.CONTACT_ID);
96     }
97 
setDisplayDeleteButtons(boolean displayDeleteButtons)98     public void setDisplayDeleteButtons(boolean displayDeleteButtons) {
99         mDisplayDeleteButtons = displayDeleteButtons;
100         notifyDataSetChanged();
101     }
102 
getDisplayDeleteButtons()103     public boolean getDisplayDeleteButtons() {
104         return mDisplayDeleteButtons;
105     }
106 
107     @Override
configureLoader(CursorLoader loader, long directoryId)108     public void configureLoader(CursorLoader loader, long directoryId) {
109         loader.setUri(Data.CONTENT_URI.buildUpon()
110                 .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
111                         String.valueOf(Directory.DEFAULT))
112                 .appendQueryParameter(Contacts.EXTRA_ADDRESS_BOOK_INDEX, "true")
113                 .build());
114 
115         loader.setSelection(Data.MIMETYPE + "=?" + " AND " + GroupMembership.GROUP_ROW_ID + "=?");
116 
117         final String[] selectionArgs = new String[2];
118         selectionArgs[0] = GroupMembership.CONTENT_ITEM_TYPE;
119         selectionArgs[1] = String.valueOf(mGroupId);
120         loader.setSelectionArgs(selectionArgs);
121 
122         loader.setProjection(
123                 getContactNameDisplayOrder() == ContactsPreferences.DISPLAY_ORDER_PRIMARY
124                         ? GroupMembersQuery.PROJECTION_PRIMARY
125                         : GroupMembersQuery.PROJECTION_ALTERNATIVE);
126 
127         loader.setSortOrder(
128                 getSortOrder() == ContactsPreferences.SORT_ORDER_PRIMARY
129                         ? Contacts.SORT_KEY_PRIMARY : Contacts.SORT_KEY_ALTERNATIVE);
130     }
131 
132     @Override
getContactDisplayName(int position)133     public String getContactDisplayName(int position) {
134         return ((Cursor) getItem(position)).getString(GroupMembersQuery.CONTACT_DISPLAY_NAME);
135     }
136 
137     @Override
newView(Context context, int partition, Cursor cursor, int position, ViewGroup parent)138     protected ContactListItemView newView(Context context, int partition, Cursor cursor,
139             int position, ViewGroup parent) {
140         final ContactListItemView view =
141                 super.newView(context, partition, cursor, position, parent);
142         view.setUnknownNameText(mUnknownNameText);
143         return view;
144     }
145 
146     @Override
bindView(View v, int partition, Cursor cursor, int position)147     protected void bindView(View v, int partition, Cursor cursor, int position) {
148         super.bindView(v, partition, cursor, position);
149         final ContactListItemView view = (ContactListItemView) v;
150         bindSectionHeaderAndDivider(view, position);
151         bindName(view, cursor);
152         bindPhoto(view, cursor, GroupMembersQuery.CONTACT_PHOTO_ID,
153                 GroupMembersQuery.CONTACT_LOOKUP_KEY, GroupMembersQuery.CONTACT_DISPLAY_NAME);
154         bindDeleteButton(view, position);
155     }
156 
bindSectionHeaderAndDivider(ContactListItemView view, int position)157     protected void bindSectionHeaderAndDivider(ContactListItemView view, int position) {
158         view.setIsSectionHeaderEnabled(isSectionHeaderDisplayEnabled());
159         if (isSectionHeaderDisplayEnabled()) {
160             final Placement placement = getItemPlacementInSection(position);
161             view.setSectionHeader(placement.sectionHeader);
162         } else {
163             view.setSectionHeader(null);
164         }
165     }
166 
bindName(ContactListItemView view, Cursor cursor)167     private void bindName(ContactListItemView view, Cursor cursor) {
168         view.showDisplayName(cursor, GroupMembersQuery.CONTACT_DISPLAY_NAME,
169                 getContactNameDisplayOrder());
170     }
171 
bindDeleteButton(final ContactListItemView view, int position)172     private void bindDeleteButton(final ContactListItemView view, int position) {
173         if (mDisplayDeleteButtons) {
174             view.getDeleteImageButton(getDeleteContactListener(), position);
175         } else {
176             view.hideDeleteImageButton();
177         }
178     }
179 }
180