16b858fc6f8afad95a075595016c5c22547924886Erik/* 26b858fc6f8afad95a075595016c5c22547924886Erik * Copyright (C) 2010 The Android Open Source Project 36b858fc6f8afad95a075595016c5c22547924886Erik * 46b858fc6f8afad95a075595016c5c22547924886Erik * Licensed under the Apache License, Version 2.0 (the "License"); 56b858fc6f8afad95a075595016c5c22547924886Erik * you may not use this file except in compliance with the License. 66b858fc6f8afad95a075595016c5c22547924886Erik * You may obtain a copy of the License at 76b858fc6f8afad95a075595016c5c22547924886Erik * 86b858fc6f8afad95a075595016c5c22547924886Erik * http://www.apache.org/licenses/LICENSE-2.0 96b858fc6f8afad95a075595016c5c22547924886Erik * 106b858fc6f8afad95a075595016c5c22547924886Erik * Unless required by applicable law or agreed to in writing, software 116b858fc6f8afad95a075595016c5c22547924886Erik * distributed under the License is distributed on an "AS IS" BASIS, 126b858fc6f8afad95a075595016c5c22547924886Erik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136b858fc6f8afad95a075595016c5c22547924886Erik * See the License for the specific language governing permissions and 146b858fc6f8afad95a075595016c5c22547924886Erik * limitations under the License. 156b858fc6f8afad95a075595016c5c22547924886Erik */ 166b858fc6f8afad95a075595016c5c22547924886Erik 176b858fc6f8afad95a075595016c5c22547924886Erikpackage com.android.calendar.selectcalendars; 186b858fc6f8afad95a075595016c5c22547924886Erik 196b858fc6f8afad95a075595016c5c22547924886Erikimport com.android.calendar.AsyncQueryService; 206b858fc6f8afad95a075595016c5c22547924886Erikimport com.android.calendar.R; 216b858fc6f8afad95a075595016c5c22547924886Erikimport com.android.calendar.selectcalendars.SelectCalendarsSyncAdapter.CalendarRow; 226b858fc6f8afad95a075595016c5c22547924886Erik 236b858fc6f8afad95a075595016c5c22547924886Erikimport android.accounts.Account; 246b858fc6f8afad95a075595016c5c22547924886Erikimport android.app.Activity; 256b858fc6f8afad95a075595016c5c22547924886Erikimport android.app.ListFragment; 266b858fc6f8afad95a075595016c5c22547924886Erikimport android.app.LoaderManager; 276b858fc6f8afad95a075595016c5c22547924886Erikimport android.content.ContentResolver; 286b858fc6f8afad95a075595016c5c22547924886Erikimport android.content.ContentUris; 296b858fc6f8afad95a075595016c5c22547924886Erikimport android.content.ContentValues; 306b858fc6f8afad95a075595016c5c22547924886Erikimport android.content.CursorLoader; 316b858fc6f8afad95a075595016c5c22547924886Erikimport android.content.Intent; 326b858fc6f8afad95a075595016c5c22547924886Erikimport android.content.Loader; 336b858fc6f8afad95a075595016c5c22547924886Erikimport android.content.res.Resources; 346b858fc6f8afad95a075595016c5c22547924886Erikimport android.database.Cursor; 356b858fc6f8afad95a075595016c5c22547924886Erikimport android.net.Uri; 366b858fc6f8afad95a075595016c5c22547924886Erikimport android.os.Bundle; 37a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract; 38a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Calendars; 396b858fc6f8afad95a075595016c5c22547924886Erikimport android.view.LayoutInflater; 406b858fc6f8afad95a075595016c5c22547924886Erikimport android.view.View; 416b858fc6f8afad95a075595016c5c22547924886Erikimport android.view.ViewGroup; 426b858fc6f8afad95a075595016c5c22547924886Erikimport android.widget.Button; 43c68cc55b8aaa92f0cc8452ef02b2d015bf8a16feMichael Chanimport android.widget.ListAdapter; 446b858fc6f8afad95a075595016c5c22547924886Erikimport android.widget.TextView; 456b858fc6f8afad95a075595016c5c22547924886Erik 466b858fc6f8afad95a075595016c5c22547924886Erikimport java.util.HashMap; 476b858fc6f8afad95a075595016c5c22547924886Erik 486b858fc6f8afad95a075595016c5c22547924886Erikpublic class SelectCalendarsSyncFragment extends ListFragment 496b858fc6f8afad95a075595016c5c22547924886Erik implements View.OnClickListener, LoaderManager.LoaderCallbacks<Cursor> { 506b858fc6f8afad95a075595016c5c22547924886Erik private static final String TAG = "SelectCalendarSync"; 516b858fc6f8afad95a075595016c5c22547924886Erik 526b858fc6f8afad95a075595016c5c22547924886Erik private static final String COLLATE_NOCASE = " COLLATE NOCASE"; 530e1e62408b96e1532eb6f6a609ae4c817751aaf3RoboErik private static final String SELECTION = Calendars.ACCOUNT_NAME + "=? AND " 540e1e62408b96e1532eb6f6a609ae4c817751aaf3RoboErik + Calendars.ACCOUNT_TYPE + "=?"; 556b858fc6f8afad95a075595016c5c22547924886Erik // is primary lets us sort the user's main calendar to the top of the list 566b858fc6f8afad95a075595016c5c22547924886Erik private static final String IS_PRIMARY = "\"primary\""; 57ef2add9145f058ea103ade2870a8ba899b9ed1c9RoboErik private static final String SORT_ORDER = IS_PRIMARY + " DESC," + Calendars.CALENDAR_DISPLAY_NAME 586b858fc6f8afad95a075595016c5c22547924886Erik + COLLATE_NOCASE; 596b858fc6f8afad95a075595016c5c22547924886Erik 60cf7fd2b6d1b5af26c4ac422dde1778e2fd6c7ef6Michael Chan private static final String[] PROJECTION = new String[] { 61cf7fd2b6d1b5af26c4ac422dde1778e2fd6c7ef6Michael Chan Calendars._ID, 62cf7fd2b6d1b5af26c4ac422dde1778e2fd6c7ef6Michael Chan Calendars.CALENDAR_DISPLAY_NAME, 63cf7fd2b6d1b5af26c4ac422dde1778e2fd6c7ef6Michael Chan Calendars.CALENDAR_COLOR, 64cf7fd2b6d1b5af26c4ac422dde1778e2fd6c7ef6Michael Chan Calendars.SYNC_EVENTS, 65cf7fd2b6d1b5af26c4ac422dde1778e2fd6c7ef6Michael Chan "(" + Calendars.ACCOUNT_NAME + "=" + Calendars.OWNER_ACCOUNT + ") AS " + IS_PRIMARY, }; 666b858fc6f8afad95a075595016c5c22547924886Erik 676b858fc6f8afad95a075595016c5c22547924886Erik private TextView mSyncStatus; 686b858fc6f8afad95a075595016c5c22547924886Erik private Button mAccountsButton; 696b858fc6f8afad95a075595016c5c22547924886Erik private Account mAccount; 706b858fc6f8afad95a075595016c5c22547924886Erik private String[] mArgs = new String[2]; 716b858fc6f8afad95a075595016c5c22547924886Erik private AsyncQueryService mService; 726b858fc6f8afad95a075595016c5c22547924886Erik 736b858fc6f8afad95a075595016c5c22547924886Erik public SelectCalendarsSyncFragment() { 746b858fc6f8afad95a075595016c5c22547924886Erik } 756b858fc6f8afad95a075595016c5c22547924886Erik 766b858fc6f8afad95a075595016c5c22547924886Erik public SelectCalendarsSyncFragment(Bundle bundle) { 770e1e62408b96e1532eb6f6a609ae4c817751aaf3RoboErik mAccount = new Account(bundle.getString(Calendars.ACCOUNT_NAME), 780e1e62408b96e1532eb6f6a609ae4c817751aaf3RoboErik bundle.getString(Calendars.ACCOUNT_TYPE)); 796b858fc6f8afad95a075595016c5c22547924886Erik } 806b858fc6f8afad95a075595016c5c22547924886Erik 816b858fc6f8afad95a075595016c5c22547924886Erik @Override 826b858fc6f8afad95a075595016c5c22547924886Erik public View onCreateView( 836b858fc6f8afad95a075595016c5c22547924886Erik LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 846b858fc6f8afad95a075595016c5c22547924886Erik View v = inflater.inflate(R.layout.account_calendars, null); 856b858fc6f8afad95a075595016c5c22547924886Erik mSyncStatus = (TextView) v.findViewById(R.id.account_status); 866b858fc6f8afad95a075595016c5c22547924886Erik mSyncStatus.setVisibility(View.GONE); 876b858fc6f8afad95a075595016c5c22547924886Erik 886b858fc6f8afad95a075595016c5c22547924886Erik mAccountsButton = (Button) v.findViewById(R.id.sync_settings); 896b858fc6f8afad95a075595016c5c22547924886Erik mAccountsButton.setVisibility(View.GONE); 906b858fc6f8afad95a075595016c5c22547924886Erik mAccountsButton.setOnClickListener(this); 916b858fc6f8afad95a075595016c5c22547924886Erik 926b858fc6f8afad95a075595016c5c22547924886Erik return v; 936b858fc6f8afad95a075595016c5c22547924886Erik } 946b858fc6f8afad95a075595016c5c22547924886Erik 956b858fc6f8afad95a075595016c5c22547924886Erik @Override 966b858fc6f8afad95a075595016c5c22547924886Erik public void onActivityCreated(Bundle savedInstanceState) { 976b858fc6f8afad95a075595016c5c22547924886Erik super.onActivityCreated(savedInstanceState); 986b858fc6f8afad95a075595016c5c22547924886Erik // Give some text to display if there is no data. In a real 996b858fc6f8afad95a075595016c5c22547924886Erik // application this would come from a resource. 1006b858fc6f8afad95a075595016c5c22547924886Erik setEmptyText(getActivity().getText(R.string.no_syncable_calendars)); 1016b858fc6f8afad95a075595016c5c22547924886Erik // Prepare the loader. Either re-connect with an existing one, 1026b858fc6f8afad95a075595016c5c22547924886Erik // or start a new one. 1036b858fc6f8afad95a075595016c5c22547924886Erik getLoaderManager().initLoader(0, null, this); 1046b858fc6f8afad95a075595016c5c22547924886Erik } 1056b858fc6f8afad95a075595016c5c22547924886Erik 1066b858fc6f8afad95a075595016c5c22547924886Erik @Override 1076b858fc6f8afad95a075595016c5c22547924886Erik public void onResume() { 1086b858fc6f8afad95a075595016c5c22547924886Erik super.onResume(); 1096b858fc6f8afad95a075595016c5c22547924886Erik if (!ContentResolver.getMasterSyncAutomatically() 110a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErik || !ContentResolver.getSyncAutomatically(mAccount, CalendarContract.AUTHORITY)) { 1116b858fc6f8afad95a075595016c5c22547924886Erik Resources res = getActivity().getResources(); 1126b858fc6f8afad95a075595016c5c22547924886Erik mSyncStatus.setText(res.getString(R.string.acct_not_synced)); 1136b858fc6f8afad95a075595016c5c22547924886Erik mSyncStatus.setVisibility(View.VISIBLE); 1146b858fc6f8afad95a075595016c5c22547924886Erik mAccountsButton.setText(res.getString(R.string.accounts)); 1156b858fc6f8afad95a075595016c5c22547924886Erik mAccountsButton.setVisibility(View.VISIBLE); 1166b858fc6f8afad95a075595016c5c22547924886Erik } else { 1176b858fc6f8afad95a075595016c5c22547924886Erik mSyncStatus.setVisibility(View.GONE); 1186b858fc6f8afad95a075595016c5c22547924886Erik mAccountsButton.setVisibility(View.GONE); 1196b858fc6f8afad95a075595016c5c22547924886Erik } 1206b858fc6f8afad95a075595016c5c22547924886Erik } 1216b858fc6f8afad95a075595016c5c22547924886Erik 1226b858fc6f8afad95a075595016c5c22547924886Erik @Override 1236b858fc6f8afad95a075595016c5c22547924886Erik public void onAttach(Activity activity) { 1246b858fc6f8afad95a075595016c5c22547924886Erik super.onAttach(activity); 1256b858fc6f8afad95a075595016c5c22547924886Erik mService = new AsyncQueryService(activity); 1266b858fc6f8afad95a075595016c5c22547924886Erik 1276b858fc6f8afad95a075595016c5c22547924886Erik Bundle bundle = getArguments(); 1286b858fc6f8afad95a075595016c5c22547924886Erik if (bundle != null && bundle.containsKey(Calendars.ACCOUNT_NAME) 1296b858fc6f8afad95a075595016c5c22547924886Erik && bundle.containsKey(Calendars.ACCOUNT_TYPE)) { 1306b858fc6f8afad95a075595016c5c22547924886Erik mAccount = new Account(bundle.getString(Calendars.ACCOUNT_NAME), 1316b858fc6f8afad95a075595016c5c22547924886Erik bundle.getString(Calendars.ACCOUNT_TYPE)); 1326b858fc6f8afad95a075595016c5c22547924886Erik } 1336b858fc6f8afad95a075595016c5c22547924886Erik } 1346b858fc6f8afad95a075595016c5c22547924886Erik 1356b858fc6f8afad95a075595016c5c22547924886Erik @Override 1366b858fc6f8afad95a075595016c5c22547924886Erik public void onPause() { 137c68cc55b8aaa92f0cc8452ef02b2d015bf8a16feMichael Chan final ListAdapter listAdapter = getListAdapter(); 138c68cc55b8aaa92f0cc8452ef02b2d015bf8a16feMichael Chan if (listAdapter != null) { 139d17780987a421477ae57fe88e48cb2d81c42f517Erik HashMap<Long, CalendarRow> changes = ((SelectCalendarsSyncAdapter) listAdapter) 140c68cc55b8aaa92f0cc8452ef02b2d015bf8a16feMichael Chan .getChanges(); 141c68cc55b8aaa92f0cc8452ef02b2d015bf8a16feMichael Chan if (changes != null && changes.size() > 0) { 142c68cc55b8aaa92f0cc8452ef02b2d015bf8a16feMichael Chan for (CalendarRow row : changes.values()) { 143b331a8217f09c2d48960bc192fc1cda1e6a35faeErik if (row.synced == row.originalSynced) { 144b331a8217f09c2d48960bc192fc1cda1e6a35faeErik continue; 145b331a8217f09c2d48960bc192fc1cda1e6a35faeErik } 146d17780987a421477ae57fe88e48cb2d81c42f517Erik long id = row.id; 147d17780987a421477ae57fe88e48cb2d81c42f517Erik mService.cancelOperation((int) id); 148c68cc55b8aaa92f0cc8452ef02b2d015bf8a16feMichael Chan // Use the full long id in case it makes a difference 149c68cc55b8aaa92f0cc8452ef02b2d015bf8a16feMichael Chan Uri uri = ContentUris.withAppendedId(Calendars.CONTENT_URI, row.id); 150c68cc55b8aaa92f0cc8452ef02b2d015bf8a16feMichael Chan ContentValues values = new ContentValues(); 151c68cc55b8aaa92f0cc8452ef02b2d015bf8a16feMichael Chan // Toggle the current setting 152c68cc55b8aaa92f0cc8452ef02b2d015bf8a16feMichael Chan int synced = row.synced ? 1 : 0; 153c68cc55b8aaa92f0cc8452ef02b2d015bf8a16feMichael Chan values.put(Calendars.SYNC_EVENTS, synced); 154950e8a615f3dcca0b61b2eb8f8de72ecf6825d4bAndy McFadden values.put(Calendars.VISIBLE, synced); 155d17780987a421477ae57fe88e48cb2d81c42f517Erik mService.startUpdate((int) id, null, uri, values, null, null, 0); 156c68cc55b8aaa92f0cc8452ef02b2d015bf8a16feMichael Chan } 157c68cc55b8aaa92f0cc8452ef02b2d015bf8a16feMichael Chan changes.clear(); 1586b858fc6f8afad95a075595016c5c22547924886Erik } 1596b858fc6f8afad95a075595016c5c22547924886Erik } 1606b858fc6f8afad95a075595016c5c22547924886Erik super.onPause(); 1616b858fc6f8afad95a075595016c5c22547924886Erik } 1626b858fc6f8afad95a075595016c5c22547924886Erik 1636b858fc6f8afad95a075595016c5c22547924886Erik @Override 1646b858fc6f8afad95a075595016c5c22547924886Erik public Loader<Cursor> onCreateLoader(int id, Bundle args) { 1656b858fc6f8afad95a075595016c5c22547924886Erik mArgs[0] = mAccount.name; 1666b858fc6f8afad95a075595016c5c22547924886Erik mArgs[1] = mAccount.type; 1676b858fc6f8afad95a075595016c5c22547924886Erik return new CursorLoader( 1686b858fc6f8afad95a075595016c5c22547924886Erik getActivity(), Calendars.CONTENT_URI, PROJECTION, SELECTION, mArgs, SORT_ORDER); 1696b858fc6f8afad95a075595016c5c22547924886Erik } 1706b858fc6f8afad95a075595016c5c22547924886Erik 1716b858fc6f8afad95a075595016c5c22547924886Erik @Override 1726b858fc6f8afad95a075595016c5c22547924886Erik public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 1736b858fc6f8afad95a075595016c5c22547924886Erik SelectCalendarsSyncAdapter adapter = (SelectCalendarsSyncAdapter) getListAdapter(); 1746b858fc6f8afad95a075595016c5c22547924886Erik if (adapter == null) { 1756b858fc6f8afad95a075595016c5c22547924886Erik adapter = new SelectCalendarsSyncAdapter(getActivity(), data); 1766b858fc6f8afad95a075595016c5c22547924886Erik } else { 1776b858fc6f8afad95a075595016c5c22547924886Erik adapter.changeCursor(data); 1786b858fc6f8afad95a075595016c5c22547924886Erik } 1796b858fc6f8afad95a075595016c5c22547924886Erik setListAdapter(adapter); 180cf7fd2b6d1b5af26c4ac422dde1778e2fd6c7ef6Michael Chan getListView().setOnItemClickListener(adapter); 1816b858fc6f8afad95a075595016c5c22547924886Erik } 1826b858fc6f8afad95a075595016c5c22547924886Erik 1831d6d7c6fee68b1641ce8664caf5d6832bf6bb618Dianne Hackborn public void onLoaderReset(Loader<Cursor> loader) { 1841d6d7c6fee68b1641ce8664caf5d6832bf6bb618Dianne Hackborn setListAdapter(null); 1851d6d7c6fee68b1641ce8664caf5d6832bf6bb618Dianne Hackborn } 1861d6d7c6fee68b1641ce8664caf5d6832bf6bb618Dianne Hackborn 1876b858fc6f8afad95a075595016c5c22547924886Erik // Called when the Accounts button is pressed. Takes the user to the 1886b858fc6f8afad95a075595016c5c22547924886Erik // Accounts and Sync settings page. 1896b858fc6f8afad95a075595016c5c22547924886Erik @Override 1906b858fc6f8afad95a075595016c5c22547924886Erik public void onClick(View v) { 1916b858fc6f8afad95a075595016c5c22547924886Erik Intent intent = new Intent(); 1926b858fc6f8afad95a075595016c5c22547924886Erik intent.setAction("android.settings.SYNC_SETTINGS"); 1936b858fc6f8afad95a075595016c5c22547924886Erik getActivity().startActivity(intent); 1946b858fc6f8afad95a075595016c5c22547924886Erik } 1956b858fc6f8afad95a075595016c5c22547924886Erik} 196