OSDN Git Service

44943eb8c95799e10a950b174b996ce21273f867
[android-x86/packages-apps-Calendar.git] / src / com / android / calendar / SelectCalendarsActivity.java
1 /*
2  * Copyright (C) 2007 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
19 import android.app.Activity;
20 import android.app.AlertDialog;
21 import android.content.AsyncQueryHandler;
22 import android.content.ContentResolver;
23 import android.content.ContentUris;
24 import android.content.ContentValues;
25 import android.content.Context;
26 import android.content.DialogInterface;
27 import android.database.Cursor;
28 import android.net.Uri;
29 import android.os.Bundle;
30 import android.provider.Calendar.Calendars;
31 import android.util.Log;
32 import android.view.Menu;
33 import android.view.MenuItem;
34 import android.view.View;
35 import android.view.Window;
36 import android.view.MenuItem.OnMenuItemClickListener;
37 import android.widget.AdapterView;
38 import android.widget.CheckBox;
39 import android.widget.ListView;
40
41
42 public class SelectCalendarsActivity extends Activity implements ListView.OnItemClickListener {
43
44     private static final String TAG = "Calendar";
45     private View mView = null;
46     private Cursor mCursor = null;
47     private QueryHandler mQueryHandler;
48     private SelectCalendarsAdapter mAdapter;
49     private static final String[] PROJECTION = new String[] {
50         Calendars._ID,
51         Calendars.DISPLAY_NAME,
52         Calendars.COLOR,
53         Calendars.SELECTED,
54         Calendars.SYNC_EVENTS
55     };
56
57     @Override
58     protected void onCreate(Bundle icicle) {
59         super.onCreate(icicle);
60         requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
61         setContentView(R.layout.calendars_activity);
62         getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS,
63                 Window.PROGRESS_INDETERMINATE_ON);
64         mQueryHandler = new QueryHandler(getContentResolver());
65         mView = findViewById(R.id.calendars);
66         ListView items = (ListView) mView.findViewById(R.id.items);
67         Context context = mView.getContext();
68         mCursor = managedQuery(Calendars.CONTENT_URI, PROJECTION,
69                 Calendars.SYNC_EVENTS + "=1",
70                 null /* selectionArgs */,
71                 Calendars.DEFAULT_SORT_ORDER);
72                                      
73         mAdapter = new SelectCalendarsAdapter(context, mCursor);
74         items.setAdapter(mAdapter);
75         items.setOnItemClickListener(this);
76         
77         // Start a background sync to get the list of calendars from the server.
78         startCalendarSync();
79     }
80     
81     @Override
82     public void onPause() {
83         super.onPause();
84     }
85     
86     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
87         CheckBox box = (CheckBox) view.findViewById(R.id.checkbox);
88         box.toggle();
89     }
90     
91     @Override
92     public boolean onCreateOptionsMenu(Menu menu) {
93         super.onCreateOptionsMenu(menu);
94         MenuItem item;
95         item = menu.add(0, 0, 0, R.string.add_calendars)
96                 .setOnMenuItemClickListener(new ChangeCalendarAction(false /* not remove */));
97         item.setIcon(android.R.drawable.ic_menu_add);
98         
99         item = menu.add(0, 0, 0, R.string.remove_calendars)
100                 .setOnMenuItemClickListener(new ChangeCalendarAction(true /* remove */));
101         item.setIcon(android.R.drawable.ic_menu_delete);
102         return true;
103     }
104
105     /**
106      * ChangeCalendarAction is used both for adding and removing calendars.
107      * The constructor takes a boolean argument that is false if adding
108      * calendars and true if removing calendars.  The user selects calendars
109      * to be added or removed from a pop-up list. 
110      */
111     public class ChangeCalendarAction implements OnMenuItemClickListener,
112             DialogInterface.OnClickListener, DialogInterface.OnMultiChoiceClickListener {
113         
114         int mNumItems;
115         long[] mCalendarIds;
116         boolean[] mIsChecked;
117         ContentResolver mContentResolver;
118         boolean mRemove;
119         
120         public ChangeCalendarAction(boolean remove) {
121             mContentResolver = SelectCalendarsActivity.this.getContentResolver();
122             mRemove = remove;
123         }
124
125         /*
126          * This is called when the user selects a calendar from either the
127          * "Add calendars" or "Remove calendars" popup dialog. 
128          */
129         public void onClick(DialogInterface dialog, int position, boolean isChecked) {
130             mIsChecked[position] = isChecked;
131         }
132
133         /*
134          * This is called when the user presses the OK or Cancel button on the
135          * "Add calendars" or "Remove calendars" popup dialog. 
136          */
137         public void onClick(DialogInterface dialog, int which) {
138             // If the user cancelled the dialog, then do nothing.
139             if (which == DialogInterface.BUTTON2) {
140                 return;
141             }
142             
143             boolean changesFound = false;
144             for (int position = 0; position < mNumItems; position++) {
145                 // If this calendar wasn't selected, then skip it.
146                 if (!mIsChecked[position]) {
147                     continue;
148                 }
149                 changesFound = true;
150                 
151                 long id = mCalendarIds[position];
152                 Uri uri = ContentUris.withAppendedId(Calendars.CONTENT_URI, id);
153                 ContentValues values = new ContentValues();
154                 int selected = 1;
155                 if (mRemove) {
156                     selected = 0;
157                 }
158                 values.put(Calendars.SELECTED, selected);
159                 values.put(Calendars.SYNC_EVENTS, selected);
160                 mContentResolver.update(uri, values, null, null);
161             }
162             
163             // If there were any changes, then update the list of calendars
164             // that are synced.
165             if (changesFound) {
166                 mCursor.requery();
167             }
168         }
169         
170         public boolean onMenuItemClick(MenuItem item) {
171             AlertDialog.Builder builder = new AlertDialog.Builder(SelectCalendarsActivity.this);
172             String selection;
173             if (mRemove) {
174                 builder.setTitle(R.string.remove_calendars)
175                     .setIcon(android.R.drawable.ic_dialog_alert);
176                 selection = Calendars.SYNC_EVENTS + "=1";
177             } else {
178                 builder.setTitle(R.string.add_calendars);
179                 selection = Calendars.SYNC_EVENTS + "=0";
180             }
181             ContentResolver cr = getContentResolver();
182             Cursor cursor = cr.query(Calendars.CONTENT_URI, PROJECTION,
183                     selection, null /* selectionArgs */,
184                     Calendars.DEFAULT_SORT_ORDER);
185             if (cursor == null) {
186                 Log.w(TAG, "Cannot get cursor for calendars");
187                 return true;
188             }
189
190             int count = cursor.getCount();
191             mNumItems = count;
192             CharSequence[] calendarNames = new CharSequence[count];
193             mCalendarIds = new long[count];
194             mIsChecked = new boolean[count];
195             try {
196                 int pos = 0;
197                 while (cursor.moveToNext()) {
198                     mCalendarIds[pos] = cursor.getLong(0);
199                     calendarNames[pos] = cursor.getString(1);
200                     pos += 1;
201                 }
202             } finally {
203                 cursor.close();
204             }
205             
206             builder.setMultiChoiceItems(calendarNames, null, this)
207                 .setPositiveButton(android.R.string.ok, this)
208                 .setNegativeButton(android.R.string.cancel, this)
209                 .show();
210             return true;
211         }
212     }
213     
214     private class QueryHandler extends AsyncQueryHandler {
215         public QueryHandler(ContentResolver cr) {
216             super(cr);
217         }
218
219         @Override
220         protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
221             getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS,
222                     Window.PROGRESS_VISIBILITY_OFF);
223
224             // If the Activity is finishing, then close the cursor.
225             // Otherwise, use the new cursor in the adapter.
226             if (isFinishing()) {
227                 stopManagingCursor(cursor);
228                 cursor.close();
229             } else {
230                 if (cursor.getCount() == 0) {
231                     // There are no calendars.  This might happen if we lost
232                     // the wireless connection (in airplane mode, for example).
233                     // Leave the current list of calendars alone and pop up
234                     // a dialog explaining that the connection is down.
235                     // But allow the user to add and remove calendars.
236                     return;
237                 }
238                 if (mCursor != null) {
239                     stopManagingCursor(mCursor);
240                 }
241                 mCursor = cursor;
242                 startManagingCursor(cursor);
243                 mAdapter.changeCursor(cursor);
244             }
245         }
246     }
247
248     // This class implements the menu option "Refresh list from server".
249     // (No longer used.)
250     public class RefreshAction implements Runnable {
251         public void run() {
252             startCalendarSync();
253         }
254     }
255     
256     // startCalendarSync() checks the server for an updated list of Calendars
257     // (in the background) using an AsyncQueryHandler.
258     //
259     // Calendars are never removed from the phone due to a server sync.
260     // But if a Calendar is added on the web (and it is selected and not
261     // hidden) then it will be added to the list of calendars on the phone
262     // (when this asynchronous query finishes).  When a new calendar from the
263     // web is added to the phone, then the events for that calendar are also
264     // downloaded from the web.
265     // 
266     // This sync is done automatically in the background when the
267     // SelectCalendars activity is started.
268     private void startCalendarSync() {
269         getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS,
270                 Window.PROGRESS_VISIBILITY_ON);
271
272         // TODO: make sure the user has login info.
273         
274         Uri uri = Calendars.LIVE_CONTENT_URI;
275         mQueryHandler.startQuery(0, null, uri, PROJECTION,
276                 Calendars.SYNC_EVENTS + "=1",
277                 null, Calendars.DEFAULT_SORT_ORDER);
278     }
279 }