ContactDeletionInteraction.java revision 69e7fec6dd8a3d24054863c6c648512577fce35c
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
17package com.android.contacts.interactions;
18
19import com.android.contacts.R;
20import com.android.contacts.model.ContactsSource;
21import com.android.contacts.model.Sources;
22
23import android.app.Activity;
24import android.app.AlertDialog;
25import android.app.Dialog;
26import android.content.ContentUris;
27import android.content.Context;
28import android.content.CursorLoader;
29import android.content.DialogInterface;
30import android.content.Loader;
31import android.database.Cursor;
32import android.net.Uri;
33import android.os.Bundle;
34import android.provider.ContactsContract.RawContacts;
35import android.util.Log;
36
37// TODO: This should respect the lookup element. The Id might by now refer to a different contact
38/**
39 * An interaction invoked to delete a contact.
40 */
41public class ContactDeletionInteraction {
42
43    private static final String TAG = "ContactDeletionInteraction";
44
45    public static final String EXTRA_KEY_CONTACT_URI = "contactUri";
46    public static final String EXTRA_KEY_MESSAGE_ID = "messageId";
47
48    private static final String[] RAW_CONTACTS_PROJECTION = new String[] {
49        RawContacts._ID, //0
50        RawContacts.ACCOUNT_TYPE, //1
51    };
52
53    private final class RawContactLoader extends CursorLoader {
54        private final Uri mContactUri;
55
56        private RawContactLoader(Context context, Uri contactUri) {
57            super(context,
58                    RawContacts.CONTENT_URI,
59                    RAW_CONTACTS_PROJECTION,
60                    RawContacts.CONTACT_ID + "=?",
61                    new String[] { String.valueOf(ContentUris.parseId(contactUri)) },
62                    null);
63            this.mContactUri = contactUri;
64        }
65
66        @Override
67        public void deliverResult(Cursor data) {
68            if (data == null || data.getCount() == 0) {
69                Log.e(TAG, "No such contact: " + mContactUri);
70                return;
71            }
72
73            showConfirmationDialog(data, mContactUri);
74        }
75    }
76
77    private final class ConfirmationDialogClickListener implements DialogInterface.OnClickListener {
78        private final Uri mContactUri;
79
80        public ConfirmationDialogClickListener(Uri contactUri) {
81            this.mContactUri = contactUri;
82        }
83
84        public void onClick(DialogInterface dialog, int which) {
85            doDeleteContact(mContactUri);
86        }
87    }
88
89    private Context mContext;
90    private CursorLoader mLoader;
91
92    public void attachToActivity(Activity activity) {
93        setContext(activity);
94    }
95
96    /* Visible for testing */
97    void setContext(Context context) {
98        mContext = context;
99    }
100
101    public void deleteContact(Uri contactUri) {
102        if (mLoader != null) {
103            mLoader.destroy();
104        }
105        mLoader = new RawContactLoader(mContext, contactUri);
106        startLoading(mLoader);
107    }
108
109    protected void showConfirmationDialog(Cursor cursor, Uri contactUri) {
110        int  writableSourcesCnt = 0;
111        int  readOnlySourcesCnt = 0;
112
113        Sources sources = getSources();
114        try {
115            while (cursor.moveToNext()) {
116                final long rawContactId = cursor.getLong(0);
117                final String accountType = cursor.getString(1);
118                ContactsSource contactsSource = sources.getInflatedSource(accountType,
119                        ContactsSource.LEVEL_SUMMARY);
120                boolean readonly = contactsSource != null && contactsSource.readOnly;
121                if (readonly) {
122                    readOnlySourcesCnt ++;
123                } else {
124                    writableSourcesCnt ++;
125                }
126            }
127        } finally {
128            cursor.close();
129        }
130
131        int messageId;
132        if (readOnlySourcesCnt > 0 && writableSourcesCnt > 0) {
133            messageId = R.string.readOnlyContactDeleteConfirmation;
134        } else if (readOnlySourcesCnt > 0 && writableSourcesCnt == 0) {
135            messageId = R.string.readOnlyContactWarning;
136        } else if (readOnlySourcesCnt == 0 && writableSourcesCnt > 1) {
137            messageId = R.string.multipleContactDeleteConfirmation;
138        } else {
139            messageId = R.string.deleteConfirmation;
140        }
141
142        Bundle bundle = new Bundle();
143        bundle.putParcelable(EXTRA_KEY_CONTACT_URI, contactUri);
144        bundle.putInt(EXTRA_KEY_MESSAGE_ID, messageId);
145
146        showDialog(bundle);
147    }
148
149    /**
150     * Creates a delete confirmation dialog and returns it.  Returns null if the
151     * id is not for a deletion confirmation.
152     */
153    public Dialog onCreateDialog(int id, Bundle bundle) {
154        if (id != R.id.dialog_delete_contact_confirmation) {
155            return null;
156        }
157
158        return new AlertDialog.Builder(mContext)
159                .setTitle(R.string.deleteConfirmation_title)
160                .setIcon(android.R.drawable.ic_dialog_alert)
161                .setMessage(R.string.deleteConfirmation)
162                .setNegativeButton(android.R.string.cancel, null)
163                .setPositiveButton(android.R.string.ok, null)
164                .create();
165    }
166
167    public boolean onPrepareDialog(int id, Dialog dialog, Bundle bundle) {
168        if (id != R.id.dialog_delete_contact_confirmation) {
169            return false;
170        }
171
172        Uri contactUri = bundle.getParcelable(EXTRA_KEY_CONTACT_URI);
173        int messageId = bundle.getInt(EXTRA_KEY_MESSAGE_ID, R.string.deleteConfirmation);
174
175        ((AlertDialog)dialog).setMessage(mContext.getText(messageId));
176        ((AlertDialog)dialog).setButton(DialogInterface.BUTTON_POSITIVE,
177                mContext.getText(android.R.string.ok),
178                new ConfirmationDialogClickListener(contactUri));
179
180        return true;
181    }
182
183    protected void doDeleteContact(Uri contactUri) {
184        mContext.getContentResolver().delete(contactUri, null, null);
185    }
186
187    /* Visible for testing */
188    void startLoading(Loader<Cursor> loader) {
189        loader.startLoading();
190    }
191
192    /* Visible for testing */
193    Sources getSources() {
194        return Sources.getInstance(mContext);
195    }
196
197    /* Visible for testing */
198    void showDialog(Bundle bundle) {
199        ((Activity)mContext).showDialog(R.id.dialog_delete_contact_confirmation, bundle);
200    }
201}
202