The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2008 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 | |
| 17 | package com.android.calendar; |
| 18 | |
Erik | fbce65e | 2010-08-16 12:43:13 -0700 | [diff] [blame] | 19 | import com.android.calendar.event.EditEventHelper; |
Michael Chan | 8a528ad | 2012-06-26 17:44:34 -0700 | [diff] [blame] | 20 | import com.android.calendarcommon2.EventRecurrence; |
Erik | fbce65e | 2010-08-16 12:43:13 -0700 | [diff] [blame] | 21 | |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 22 | import android.app.Activity; |
| 23 | import android.app.AlertDialog; |
Isaac Katzenelson | b0a313a | 2011-10-24 11:41:56 -0700 | [diff] [blame] | 24 | import android.app.Dialog; |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 25 | import android.content.ContentUris; |
| 26 | import android.content.ContentValues; |
Michael Chan | 1251cb0 | 2010-07-01 14:50:50 -0700 | [diff] [blame] | 27 | import android.content.Context; |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 28 | import android.content.DialogInterface; |
RoboErik | e3e1f55 | 2011-09-27 13:33:50 -0700 | [diff] [blame] | 29 | import android.content.res.Resources; |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 30 | import android.database.Cursor; |
| 31 | import android.net.Uri; |
RoboErik | a7c0390 | 2011-06-14 11:06:44 -0700 | [diff] [blame] | 32 | import android.provider.CalendarContract; |
| 33 | import android.provider.CalendarContract.Events; |
Michael Chan | 66b2067 | 2010-12-20 13:50:28 -0800 | [diff] [blame] | 34 | import android.text.TextUtils; |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 35 | import android.text.format.Time; |
RoboErik | e3e1f55 | 2011-09-27 13:33:50 -0700 | [diff] [blame] | 36 | import android.widget.ArrayAdapter; |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 37 | import android.widget.Button; |
| 38 | |
RoboErik | e3e1f55 | 2011-09-27 13:33:50 -0700 | [diff] [blame] | 39 | import java.util.ArrayList; |
| 40 | import java.util.Arrays; |
| 41 | |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 42 | /** |
| 43 | * A helper class for deleting events. If a normal event is selected for |
| 44 | * deletion, then this pops up a confirmation dialog. If the user confirms, |
| 45 | * then the normal event is deleted. |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 46 | * |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 47 | * <p> |
| 48 | * If a repeating event is selected for deletion, then this pops up dialog |
| 49 | * asking if the user wants to delete just this one instance, or all the |
| 50 | * events in the series, or this event plus all following events. The user |
| 51 | * may also cancel the delete. |
| 52 | * </p> |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 53 | * |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 54 | * <p> |
| 55 | * To use this class, create an instance, passing in the parent activity |
| 56 | * and a boolean that determines if the parent activity should exit if the |
| 57 | * event is deleted. Then to use the instance, call one of the |
| 58 | * {@link delete()} methods on this class. |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 59 | * |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 60 | * An instance of this class may be created once and reused (by calling |
| 61 | * {@link #delete()} multiple times). |
| 62 | */ |
| 63 | public class DeleteEventHelper { |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 64 | private final Activity mParent; |
Michael Chan | 1251cb0 | 2010-07-01 14:50:50 -0700 | [diff] [blame] | 65 | private Context mContext; |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 66 | |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 67 | private long mStartMillis; |
| 68 | private long mEndMillis; |
Erik | 88c483a | 2010-06-21 11:27:38 -0700 | [diff] [blame] | 69 | private CalendarEventModel mModel; |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 70 | |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 71 | /** |
| 72 | * If true, then call finish() on the parent activity when done. |
| 73 | */ |
| 74 | private boolean mExitWhenDone; |
Erik | 89ad082 | 2011-01-18 15:55:17 -0800 | [diff] [blame] | 75 | // the runnable to execute when the delete is confirmed |
| 76 | private Runnable mCallback; |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 77 | |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 78 | /** |
| 79 | * These are the corresponding indices into the array of strings |
| 80 | * "R.array.delete_repeating_labels" in the resource file. |
| 81 | */ |
Erik | fbce65e | 2010-08-16 12:43:13 -0700 | [diff] [blame] | 82 | public static final int DELETE_SELECTED = 0; |
| 83 | public static final int DELETE_ALL_FOLLOWING = 1; |
| 84 | public static final int DELETE_ALL = 2; |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 85 | |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 86 | private int mWhichDelete; |
RoboErik | e3e1f55 | 2011-09-27 13:33:50 -0700 | [diff] [blame] | 87 | private ArrayList<Integer> mWhichIndex; |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 88 | private AlertDialog mAlertDialog; |
Isaac Katzenelson | b0a313a | 2011-10-24 11:41:56 -0700 | [diff] [blame] | 89 | private Dialog.OnDismissListener mDismissListener; |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 90 | |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 91 | private String mSyncId; |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 92 | |
Erik | 88c483a | 2010-06-21 11:27:38 -0700 | [diff] [blame] | 93 | private AsyncQueryService mService; |
| 94 | |
Isaac Katzenelson | b33cdf4 | 2011-10-14 18:15:18 -0700 | [diff] [blame] | 95 | private DeleteNotifyListener mDeleteStartedListener = null; |
| 96 | |
| 97 | public interface DeleteNotifyListener { |
| 98 | public void onDeleteStarted(); |
| 99 | } |
| 100 | |
| 101 | |
Michael Chan | 1251cb0 | 2010-07-01 14:50:50 -0700 | [diff] [blame] | 102 | public DeleteEventHelper(Context context, Activity parentActivity, boolean exitWhenDone) { |
| 103 | if (exitWhenDone && parentActivity == null) { |
| 104 | throw new IllegalArgumentException("parentActivity is required to exit when done"); |
| 105 | } |
| 106 | |
| 107 | mContext = context; |
| 108 | mParent = parentActivity; |
Erik | 88c483a | 2010-06-21 11:27:38 -0700 | [diff] [blame] | 109 | // TODO move the creation of this service out into the activity. |
Michael Chan | 1251cb0 | 2010-07-01 14:50:50 -0700 | [diff] [blame] | 110 | mService = new AsyncQueryService(mContext) { |
Erik | 88c483a | 2010-06-21 11:27:38 -0700 | [diff] [blame] | 111 | @Override |
| 112 | protected void onQueryComplete(int token, Object cookie, Cursor cursor) { |
| 113 | if (cursor == null) { |
| 114 | return; |
| 115 | } |
| 116 | cursor.moveToFirst(); |
| 117 | CalendarEventModel mModel = new CalendarEventModel(); |
| 118 | EditEventHelper.setModelFromCursor(mModel, cursor); |
| 119 | cursor.close(); |
| 120 | DeleteEventHelper.this.delete(mStartMillis, mEndMillis, mModel, mWhichDelete); |
| 121 | } |
| 122 | }; |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 123 | mExitWhenDone = exitWhenDone; |
| 124 | } |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 125 | |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 126 | public void setExitWhenDone(boolean exitWhenDone) { |
| 127 | mExitWhenDone = exitWhenDone; |
| 128 | } |
| 129 | |
| 130 | /** |
| 131 | * This callback is used when a normal event is deleted. |
| 132 | */ |
| 133 | private DialogInterface.OnClickListener mDeleteNormalDialogListener = |
| 134 | new DialogInterface.OnClickListener() { |
| 135 | public void onClick(DialogInterface dialog, int button) { |
Isaac Katzenelson | b33cdf4 | 2011-10-14 18:15:18 -0700 | [diff] [blame] | 136 | deleteStarted(); |
Erik | 88c483a | 2010-06-21 11:27:38 -0700 | [diff] [blame] | 137 | long id = mModel.mId; // mCursor.getInt(mEventIndexId); |
RoboErik | a7c0390 | 2011-06-14 11:06:44 -0700 | [diff] [blame] | 138 | Uri uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, id); |
Erik | 37960c0 | 2010-06-22 13:40:18 -0700 | [diff] [blame] | 139 | mService.startDelete(mService.getNextToken(), null, uri, null, null, Utils.UNDO_DELAY); |
Erik | 89ad082 | 2011-01-18 15:55:17 -0800 | [diff] [blame] | 140 | if (mCallback != null) { |
| 141 | mCallback.run(); |
| 142 | } |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 143 | if (mExitWhenDone) { |
| 144 | mParent.finish(); |
| 145 | } |
| 146 | } |
| 147 | }; |
| 148 | |
| 149 | /** |
Erik | 83f7ce1 | 2010-04-27 10:06:41 -0700 | [diff] [blame] | 150 | * This callback is used when an exception to an event is deleted |
| 151 | */ |
| 152 | private DialogInterface.OnClickListener mDeleteExceptionDialogListener = |
| 153 | new DialogInterface.OnClickListener() { |
| 154 | public void onClick(DialogInterface dialog, int button) { |
Isaac Katzenelson | b33cdf4 | 2011-10-14 18:15:18 -0700 | [diff] [blame] | 155 | deleteStarted(); |
Erik | 83f7ce1 | 2010-04-27 10:06:41 -0700 | [diff] [blame] | 156 | deleteExceptionEvent(); |
Erik | 89ad082 | 2011-01-18 15:55:17 -0800 | [diff] [blame] | 157 | if (mCallback != null) { |
| 158 | mCallback.run(); |
| 159 | } |
Erik | 83f7ce1 | 2010-04-27 10:06:41 -0700 | [diff] [blame] | 160 | if (mExitWhenDone) { |
| 161 | mParent.finish(); |
| 162 | } |
| 163 | } |
| 164 | }; |
| 165 | |
| 166 | /** |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 167 | * This callback is used when a list item for a repeating event is selected |
| 168 | */ |
| 169 | private DialogInterface.OnClickListener mDeleteListListener = |
| 170 | new DialogInterface.OnClickListener() { |
| 171 | public void onClick(DialogInterface dialog, int button) { |
RoboErik | e3e1f55 | 2011-09-27 13:33:50 -0700 | [diff] [blame] | 172 | // set mWhichDelete to the delete type at that index |
| 173 | mWhichDelete = mWhichIndex.get(button); |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 174 | |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 175 | // Enable the "ok" button now that the user has selected which |
| 176 | // events in the series to delete. |
| 177 | Button ok = mAlertDialog.getButton(DialogInterface.BUTTON_POSITIVE); |
| 178 | ok.setEnabled(true); |
| 179 | } |
| 180 | }; |
| 181 | |
| 182 | /** |
| 183 | * This callback is used when a repeating event is deleted. |
| 184 | */ |
| 185 | private DialogInterface.OnClickListener mDeleteRepeatingDialogListener = |
| 186 | new DialogInterface.OnClickListener() { |
| 187 | public void onClick(DialogInterface dialog, int button) { |
Isaac Katzenelson | b33cdf4 | 2011-10-14 18:15:18 -0700 | [diff] [blame] | 188 | deleteStarted(); |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 189 | if (mWhichDelete != -1) { |
| 190 | deleteRepeatingEvent(mWhichDelete); |
| 191 | } |
| 192 | } |
| 193 | }; |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 194 | |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 195 | /** |
| 196 | * Does the required processing for deleting an event, which includes |
| 197 | * first popping up a dialog asking for confirmation (if the event is |
| 198 | * a normal event) or a dialog asking which events to delete (if the |
| 199 | * event is a repeating event). The "which" parameter is used to check |
| 200 | * the initial selection and is only used for repeating events. Set |
| 201 | * "which" to -1 to have nothing selected initially. |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 202 | * |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 203 | * @param begin the begin time of the event, in UTC milliseconds |
| 204 | * @param end the end time of the event, in UTC milliseconds |
| 205 | * @param eventId the event id |
| 206 | * @param which one of the values {@link DELETE_SELECTED}, |
| 207 | * {@link DELETE_ALL_FOLLOWING}, {@link DELETE_ALL}, or -1 |
| 208 | */ |
| 209 | public void delete(long begin, long end, long eventId, int which) { |
RoboErik | a7c0390 | 2011-06-14 11:06:44 -0700 | [diff] [blame] | 210 | Uri uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventId); |
Erik | 37960c0 | 2010-06-22 13:40:18 -0700 | [diff] [blame] | 211 | mService.startQuery(mService.getNextToken(), null, uri, EditEventHelper.EVENT_PROJECTION, |
| 212 | null, null, null); |
Erik | 88c483a | 2010-06-21 11:27:38 -0700 | [diff] [blame] | 213 | mStartMillis = begin; |
| 214 | mEndMillis = end; |
| 215 | mWhichDelete = which; |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 216 | } |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 217 | |
Erik | 89ad082 | 2011-01-18 15:55:17 -0800 | [diff] [blame] | 218 | public void delete(long begin, long end, long eventId, int which, Runnable callback) { |
| 219 | delete(begin, end, eventId, which); |
| 220 | mCallback = callback; |
| 221 | } |
| 222 | |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 223 | /** |
| 224 | * Does the required processing for deleting an event. This method |
Erik | 88c483a | 2010-06-21 11:27:38 -0700 | [diff] [blame] | 225 | * takes a {@link CalendarEventModel} object, which must have a valid |
| 226 | * uri for referencing the event in the database and have the required |
| 227 | * fields listed below. |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 228 | * The required fields for a normal event are: |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 229 | * |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 230 | * <ul> |
| 231 | * <li> Events._ID </li> |
| 232 | * <li> Events.TITLE </li> |
| 233 | * <li> Events.RRULE </li> |
| 234 | * </ul> |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 235 | * |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 236 | * The required fields for a repeating event include the above plus the |
| 237 | * following fields: |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 238 | * |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 239 | * <ul> |
| 240 | * <li> Events.ALL_DAY </li> |
| 241 | * <li> Events.CALENDAR_ID </li> |
| 242 | * <li> Events.DTSTART </li> |
| 243 | * <li> Events._SYNC_ID </li> |
| 244 | * <li> Events.EVENT_TIMEZONE </li> |
| 245 | * </ul> |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 246 | * |
Erik | 88c483a | 2010-06-21 11:27:38 -0700 | [diff] [blame] | 247 | * If the event no longer exists in the db this will still prompt |
| 248 | * the user but will return without modifying the db after the query |
| 249 | * returns. |
| 250 | * |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 251 | * @param begin the begin time of the event, in UTC milliseconds |
| 252 | * @param end the end time of the event, in UTC milliseconds |
| 253 | * @param cursor the database cursor containing the required fields |
| 254 | * @param which one of the values {@link DELETE_SELECTED}, |
| 255 | * {@link DELETE_ALL_FOLLOWING}, {@link DELETE_ALL}, or -1 |
| 256 | */ |
Erik | 88c483a | 2010-06-21 11:27:38 -0700 | [diff] [blame] | 257 | public void delete(long begin, long end, CalendarEventModel model, int which) { |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 258 | mWhichDelete = which; |
| 259 | mStartMillis = begin; |
| 260 | mEndMillis = end; |
Erik | 88c483a | 2010-06-21 11:27:38 -0700 | [diff] [blame] | 261 | mModel = model; |
| 262 | mSyncId = model.mSyncId; |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 263 | |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 264 | // If this is a repeating event, then pop up a dialog asking the |
| 265 | // user if they want to delete all of the repeating events or |
| 266 | // just some of them. |
Erik | 88c483a | 2010-06-21 11:27:38 -0700 | [diff] [blame] | 267 | String rRule = model.mRrule; |
RoboErik | 28dab65 | 2011-07-21 15:08:39 -0700 | [diff] [blame] | 268 | String originalEvent = model.mOriginalSyncId; |
Michael Chan | 66b2067 | 2010-12-20 13:50:28 -0800 | [diff] [blame] | 269 | if (TextUtils.isEmpty(rRule)) { |
Michael Chan | 42ecaa3 | 2011-10-13 11:07:25 -0700 | [diff] [blame] | 270 | AlertDialog dialog = new AlertDialog.Builder(mContext) |
Erik | f6b6fb3 | 2011-01-18 11:54:50 -0800 | [diff] [blame] | 271 | .setMessage(R.string.delete_this_event_title) |
| 272 | .setIconAttribute(android.R.attr.alertDialogIcon) |
| 273 | .setNegativeButton(android.R.string.cancel, null).create(); |
Erik | 83f7ce1 | 2010-04-27 10:06:41 -0700 | [diff] [blame] | 274 | |
| 275 | if (originalEvent == null) { |
| 276 | // This is a normal event. Pop up a confirmation dialog. |
| 277 | dialog.setButton(DialogInterface.BUTTON_POSITIVE, |
Michael Chan | 1251cb0 | 2010-07-01 14:50:50 -0700 | [diff] [blame] | 278 | mContext.getText(android.R.string.ok), |
Erik | 83f7ce1 | 2010-04-27 10:06:41 -0700 | [diff] [blame] | 279 | mDeleteNormalDialogListener); |
| 280 | } else { |
| 281 | // This is an exception event. Pop up a confirmation dialog. |
| 282 | dialog.setButton(DialogInterface.BUTTON_POSITIVE, |
Michael Chan | 1251cb0 | 2010-07-01 14:50:50 -0700 | [diff] [blame] | 283 | mContext.getText(android.R.string.ok), |
Erik | 83f7ce1 | 2010-04-27 10:06:41 -0700 | [diff] [blame] | 284 | mDeleteExceptionDialogListener); |
| 285 | } |
Isaac Katzenelson | b0a313a | 2011-10-24 11:41:56 -0700 | [diff] [blame] | 286 | dialog.setOnDismissListener(mDismissListener); |
Erik | 83f7ce1 | 2010-04-27 10:06:41 -0700 | [diff] [blame] | 287 | dialog.show(); |
Isaac Katzenelson | b0a313a | 2011-10-24 11:41:56 -0700 | [diff] [blame] | 288 | mAlertDialog = dialog; |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 289 | } else { |
| 290 | // This is a repeating event. Pop up a dialog asking which events |
| 291 | // to delete. |
RoboErik | e3e1f55 | 2011-09-27 13:33:50 -0700 | [diff] [blame] | 292 | Resources res = mContext.getResources(); |
| 293 | ArrayList<String> labelArray = new ArrayList<String>(Arrays.asList(res |
| 294 | .getStringArray(R.array.delete_repeating_labels))); |
| 295 | // asList doesn't like int[] so creating it manually. |
| 296 | int[] labelValues = res.getIntArray(R.array.delete_repeating_values); |
| 297 | ArrayList<Integer> labelIndex = new ArrayList<Integer>(); |
| 298 | for (int val : labelValues) { |
| 299 | labelIndex.add(val); |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 300 | } |
RoboErik | e3e1f55 | 2011-09-27 13:33:50 -0700 | [diff] [blame] | 301 | |
| 302 | if (mSyncId == null) { |
| 303 | // remove 'Only this event' item |
| 304 | labelArray.remove(0); |
| 305 | labelIndex.remove(0); |
| 306 | if (!model.mIsOrganizer) { |
| 307 | // remove 'This and future events' item |
| 308 | labelArray.remove(0); |
| 309 | labelIndex.remove(0); |
| 310 | } |
| 311 | } else if (!model.mIsOrganizer) { |
| 312 | // remove 'This and future events' item |
| 313 | labelArray.remove(1); |
| 314 | labelIndex.remove(1); |
| 315 | } |
| 316 | if (which != -1) { |
| 317 | // transform the which to the index in the array |
| 318 | which = labelIndex.indexOf(which); |
| 319 | } |
| 320 | mWhichIndex = labelIndex; |
| 321 | ArrayAdapter<String> adapter = new ArrayAdapter<String>(mContext, |
| 322 | android.R.layout.simple_list_item_single_choice, labelArray); |
Michael Chan | 42ecaa3 | 2011-10-13 11:07:25 -0700 | [diff] [blame] | 323 | AlertDialog dialog = new AlertDialog.Builder(mContext) |
Mindy Pereira | 512c8cf | 2012-05-10 10:35:29 -0700 | [diff] [blame] | 324 | .setTitle( |
| 325 | mContext.getString(R.string.delete_recurring_event_title,model.mTitle)) |
Erik | f6b6fb3 | 2011-01-18 11:54:50 -0800 | [diff] [blame] | 326 | .setIconAttribute(android.R.attr.alertDialogIcon) |
RoboErik | e3e1f55 | 2011-09-27 13:33:50 -0700 | [diff] [blame] | 327 | .setSingleChoiceItems(adapter, which, mDeleteListListener) |
Erik | f6b6fb3 | 2011-01-18 11:54:50 -0800 | [diff] [blame] | 328 | .setPositiveButton(android.R.string.ok, mDeleteRepeatingDialogListener) |
| 329 | .setNegativeButton(android.R.string.cancel, null).show(); |
Isaac Katzenelson | b0a313a | 2011-10-24 11:41:56 -0700 | [diff] [blame] | 330 | dialog.setOnDismissListener(mDismissListener); |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 331 | mAlertDialog = dialog; |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 332 | |
The Android Open Source Project | 3cfe2e5 | 2009-03-13 13:04:24 -0700 | [diff] [blame] | 333 | if (which == -1) { |
| 334 | // Disable the "Ok" button until the user selects which events |
| 335 | // to delete. |
| 336 | Button ok = dialog.getButton(DialogInterface.BUTTON_POSITIVE); |
| 337 | ok.setEnabled(false); |
| 338 | } |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 339 | } |
| 340 | } |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 341 | |
Erik | 83f7ce1 | 2010-04-27 10:06:41 -0700 | [diff] [blame] | 342 | private void deleteExceptionEvent() { |
Erik | 88c483a | 2010-06-21 11:27:38 -0700 | [diff] [blame] | 343 | long id = mModel.mId; // mCursor.getInt(mEventIndexId); |
Erik | 83f7ce1 | 2010-04-27 10:06:41 -0700 | [diff] [blame] | 344 | |
| 345 | // update a recurrence exception by setting its status to "canceled" |
| 346 | ContentValues values = new ContentValues(); |
| 347 | values.put(Events.STATUS, Events.STATUS_CANCELED); |
| 348 | |
RoboErik | a7c0390 | 2011-06-14 11:06:44 -0700 | [diff] [blame] | 349 | Uri uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, id); |
Erik | 37960c0 | 2010-06-22 13:40:18 -0700 | [diff] [blame] | 350 | mService.startUpdate(mService.getNextToken(), null, uri, values, null, null, |
| 351 | Utils.UNDO_DELAY); |
Erik | 83f7ce1 | 2010-04-27 10:06:41 -0700 | [diff] [blame] | 352 | } |
| 353 | |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 354 | private void deleteRepeatingEvent(int which) { |
Erik | 88c483a | 2010-06-21 11:27:38 -0700 | [diff] [blame] | 355 | String rRule = mModel.mRrule; |
| 356 | boolean allDay = mModel.mAllDay; |
| 357 | long dtstart = mModel.mStart; |
| 358 | long id = mModel.mId; // mCursor.getInt(mEventIndexId); |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 359 | |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 360 | switch (which) { |
Erik | 8d69cd0 | 2010-06-23 17:32:51 -0700 | [diff] [blame] | 361 | case DELETE_SELECTED: { |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 362 | // If we are deleting the first event in the series, then |
| 363 | // instead of creating a recurrence exception, just change |
| 364 | // the start time of the recurrence. |
| 365 | if (dtstart == mStartMillis) { |
| 366 | // TODO |
| 367 | } |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 368 | |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 369 | // Create a recurrence exception by creating a new event |
| 370 | // with the status "cancelled". |
| 371 | ContentValues values = new ContentValues(); |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 372 | |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 373 | // The title might not be necessary, but it makes it easier |
| 374 | // to find this entry in the database when there is a problem. |
Erik | 88c483a | 2010-06-21 11:27:38 -0700 | [diff] [blame] | 375 | String title = mModel.mTitle; |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 376 | values.put(Events.TITLE, title); |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 377 | |
Erik | 88c483a | 2010-06-21 11:27:38 -0700 | [diff] [blame] | 378 | String timezone = mModel.mTimezone; |
| 379 | long calendarId = mModel.mCalendarId; |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 380 | values.put(Events.EVENT_TIMEZONE, timezone); |
| 381 | values.put(Events.ALL_DAY, allDay ? 1 : 0); |
RoboErik | fcba1f1 | 2011-04-08 11:43:47 -0700 | [diff] [blame] | 382 | values.put(Events.ORIGINAL_ALL_DAY, allDay ? 1 : 0); |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 383 | values.put(Events.CALENDAR_ID, calendarId); |
| 384 | values.put(Events.DTSTART, mStartMillis); |
| 385 | values.put(Events.DTEND, mEndMillis); |
RoboErik | 0e1e624 | 2011-05-05 15:25:02 -0700 | [diff] [blame] | 386 | values.put(Events.ORIGINAL_SYNC_ID, mSyncId); |
RoboErik | e0c5580 | 2011-08-09 16:34:31 -0700 | [diff] [blame] | 387 | values.put(Events.ORIGINAL_ID, id); |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 388 | values.put(Events.ORIGINAL_INSTANCE_TIME, mStartMillis); |
| 389 | values.put(Events.STATUS, Events.STATUS_CANCELED); |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 390 | |
Erik | 37960c0 | 2010-06-22 13:40:18 -0700 | [diff] [blame] | 391 | mService.startInsert(mService.getNextToken(), null, Events.CONTENT_URI, values, |
| 392 | Utils.UNDO_DELAY); |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 393 | break; |
| 394 | } |
| 395 | case DELETE_ALL: { |
RoboErik | a7c0390 | 2011-06-14 11:06:44 -0700 | [diff] [blame] | 396 | Uri uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, id); |
Erik | 37960c0 | 2010-06-22 13:40:18 -0700 | [diff] [blame] | 397 | mService.startDelete(mService.getNextToken(), null, uri, null, null, |
| 398 | Utils.UNDO_DELAY); |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 399 | break; |
| 400 | } |
| 401 | case DELETE_ALL_FOLLOWING: { |
| 402 | // If we are deleting the first event in the series and all |
| 403 | // following events, then delete them all. |
| 404 | if (dtstart == mStartMillis) { |
RoboErik | a7c0390 | 2011-06-14 11:06:44 -0700 | [diff] [blame] | 405 | Uri uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, id); |
Erik | 37960c0 | 2010-06-22 13:40:18 -0700 | [diff] [blame] | 406 | mService.startDelete(mService.getNextToken(), null, uri, null, null, |
| 407 | Utils.UNDO_DELAY); |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 408 | break; |
| 409 | } |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 410 | |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 411 | // Modify the repeating event to end just before this event time |
| 412 | EventRecurrence eventRecurrence = new EventRecurrence(); |
| 413 | eventRecurrence.parse(rRule); |
| 414 | Time date = new Time(); |
| 415 | if (allDay) { |
| 416 | date.timezone = Time.TIMEZONE_UTC; |
| 417 | } |
| 418 | date.set(mStartMillis); |
| 419 | date.second--; |
| 420 | date.normalize(false); |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 421 | |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 422 | // Google calendar seems to require the UNTIL string to be |
| 423 | // in UTC. |
| 424 | date.switchTimezone(Time.TIMEZONE_UTC); |
| 425 | eventRecurrence.until = date.format2445(); |
Michael Chan | ad36a3c | 2010-01-27 18:03:25 -0800 | [diff] [blame] | 426 | |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 427 | ContentValues values = new ContentValues(); |
| 428 | values.put(Events.DTSTART, dtstart); |
| 429 | values.put(Events.RRULE, eventRecurrence.toString()); |
RoboErik | a7c0390 | 2011-06-14 11:06:44 -0700 | [diff] [blame] | 430 | Uri uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, id); |
Erik | 37960c0 | 2010-06-22 13:40:18 -0700 | [diff] [blame] | 431 | mService.startUpdate(mService.getNextToken(), null, uri, values, null, null, |
| 432 | Utils.UNDO_DELAY); |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 433 | break; |
| 434 | } |
| 435 | } |
Erik | 89ad082 | 2011-01-18 15:55:17 -0800 | [diff] [blame] | 436 | if (mCallback != null) { |
| 437 | mCallback.run(); |
| 438 | } |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 439 | if (mExitWhenDone) { |
| 440 | mParent.finish(); |
| 441 | } |
| 442 | } |
Isaac Katzenelson | b33cdf4 | 2011-10-14 18:15:18 -0700 | [diff] [blame] | 443 | |
| 444 | public void setDeleteNotificationListener(DeleteNotifyListener listener) { |
| 445 | mDeleteStartedListener = listener; |
| 446 | } |
| 447 | |
| 448 | private void deleteStarted() { |
| 449 | if (mDeleteStartedListener != null) { |
| 450 | mDeleteStartedListener.onDeleteStarted(); |
| 451 | } |
| 452 | } |
Isaac Katzenelson | b0a313a | 2011-10-24 11:41:56 -0700 | [diff] [blame] | 453 | |
| 454 | public void setOnDismissListener(Dialog.OnDismissListener listener) { |
| 455 | if (mAlertDialog != null) { |
| 456 | mAlertDialog.setOnDismissListener(listener); |
| 457 | } |
| 458 | mDismissListener = listener; |
| 459 | } |
| 460 | |
| 461 | public void dismissAlertDialog() { |
| 462 | if (mAlertDialog != null) { |
| 463 | mAlertDialog.dismiss(); |
| 464 | } |
| 465 | } |
The Android Open Source Project | 146de36 | 2009-03-03 19:32:18 -0800 | [diff] [blame] | 466 | } |