| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.calendar.selectcalendars; |
| |
| import android.accounts.Account; |
| import android.app.Activity; |
| import android.app.ListFragment; |
| import android.app.LoaderManager; |
| import android.content.ContentResolver; |
| import android.content.ContentUris; |
| import android.content.ContentValues; |
| import android.content.CursorLoader; |
| import android.content.Intent; |
| import android.content.Loader; |
| import android.content.res.Resources; |
| import android.database.ContentObserver; |
| import android.database.Cursor; |
| import android.net.Uri; |
| import android.os.Bundle; |
| import android.os.Handler; |
| import android.provider.CalendarContract; |
| import android.provider.CalendarContract.Calendars; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| import android.view.View.OnClickListener; |
| import android.view.ViewGroup; |
| import android.widget.Button; |
| import android.widget.ListAdapter; |
| import android.widget.TextView; |
| |
| import com.android.calendar.AsyncQueryService; |
| import com.android.calendar.CalendarColorPickerDialog; |
| import com.android.calendar.R; |
| import com.android.calendar.Utils; |
| import com.android.calendar.selectcalendars.SelectCalendarsSyncAdapter.CalendarRow; |
| |
| import java.util.HashMap; |
| |
| public class SelectCalendarsSyncFragment extends ListFragment |
| implements View.OnClickListener, LoaderManager.LoaderCallbacks<Cursor> { |
| |
| private static final String TAG = "SelectCalendarSync"; |
| |
| private static final String COLLATE_NOCASE = " COLLATE NOCASE"; |
| private static final String SELECTION = Calendars.ACCOUNT_NAME + "=? AND " |
| + Calendars.ACCOUNT_TYPE + "=?"; |
| // is primary lets us sort the user's main calendar to the top of the list |
| private static final String IS_PRIMARY = "\"primary\""; |
| private static final String SORT_ORDER = IS_PRIMARY + " DESC," + Calendars.CALENDAR_DISPLAY_NAME |
| + COLLATE_NOCASE; |
| |
| private static final String[] PROJECTION = new String[] { |
| Calendars._ID, |
| Calendars.CALENDAR_DISPLAY_NAME, |
| Calendars.CALENDAR_COLOR, |
| Calendars.SYNC_EVENTS, |
| "(" + Calendars.ACCOUNT_NAME + "=" + Calendars.OWNER_ACCOUNT + ") AS " + IS_PRIMARY, }; |
| |
| private TextView mSyncStatus; |
| private Button mAccountsButton; |
| private Account mAccount; |
| private final String[] mArgs = new String[2]; |
| private AsyncQueryService mService; |
| private Handler mHandler = new Handler(); |
| private ContentObserver mCalendarsObserver = new ContentObserver(mHandler) { |
| @Override |
| public void onChange(boolean selfChange) { |
| // We don't need our own sync changes to trigger refreshes. |
| if (!selfChange) { |
| getLoaderManager().initLoader(0, null, SelectCalendarsSyncFragment.this); |
| } |
| } |
| }; |
| |
| public SelectCalendarsSyncFragment() { |
| } |
| |
| public SelectCalendarsSyncFragment(Bundle bundle) { |
| mAccount = new Account(bundle.getString(Calendars.ACCOUNT_NAME), |
| bundle.getString(Calendars.ACCOUNT_TYPE)); |
| } |
| |
| @Override |
| public View onCreateView( |
| LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { |
| View v = inflater.inflate(R.layout.account_calendars, null); |
| mSyncStatus = (TextView) v.findViewById(R.id.account_status); |
| mSyncStatus.setVisibility(View.GONE); |
| |
| mAccountsButton = (Button) v.findViewById(R.id.sync_settings); |
| mAccountsButton.setVisibility(View.GONE); |
| mAccountsButton.setOnClickListener(this); |
| |
| return v; |
| } |
| |
| @Override |
| public void onActivityCreated(Bundle savedInstanceState) { |
| super.onActivityCreated(savedInstanceState); |
| // Give some text to display if there is no data. In a real |
| // application this would come from a resource. |
| setEmptyText(getActivity().getText(R.string.no_syncable_calendars)); |
| // Prepare the loader. Either re-connect with an existing one, |
| // or start a new one. |
| getLoaderManager().initLoader(0, null, this); |
| } |
| |
| @Override |
| public void onResume() { |
| super.onResume(); |
| if (!ContentResolver.getMasterSyncAutomatically() |
| || !ContentResolver.getSyncAutomatically(mAccount, CalendarContract.AUTHORITY)) { |
| Resources res = getActivity().getResources(); |
| mSyncStatus.setText(res.getString(R.string.acct_not_synced)); |
| mSyncStatus.setVisibility(View.VISIBLE); |
| mAccountsButton.setText(res.getString(R.string.accounts)); |
| mAccountsButton.setVisibility(View.VISIBLE); |
| } else { |
| mSyncStatus.setVisibility(View.GONE); |
| mAccountsButton.setVisibility(View.GONE); |
| |
| // Start a background sync to get the list of calendars from the server. |
| Utils.startCalendarMetafeedSync(mAccount); |
| getActivity().getContentResolver().registerContentObserver( |
| Calendars.CONTENT_URI, true, mCalendarsObserver); |
| } |
| } |
| |
| @Override |
| public void onAttach(Activity activity) { |
| super.onAttach(activity); |
| mService = new AsyncQueryService(activity); |
| |
| Bundle bundle = getArguments(); |
| if (bundle != null && bundle.containsKey(Calendars.ACCOUNT_NAME) |
| && bundle.containsKey(Calendars.ACCOUNT_TYPE)) { |
| mAccount = new Account(bundle.getString(Calendars.ACCOUNT_NAME), |
| bundle.getString(Calendars.ACCOUNT_TYPE)); |
| } |
| } |
| |
| @Override |
| public void onPause() { |
| final ListAdapter listAdapter = getListAdapter(); |
| if (listAdapter != null) { |
| HashMap<Long, CalendarRow> changes = ((SelectCalendarsSyncAdapter) listAdapter) |
| .getChanges(); |
| if (changes != null && changes.size() > 0) { |
| for (CalendarRow row : changes.values()) { |
| if (row.synced == row.originalSynced) { |
| continue; |
| } |
| long id = row.id; |
| mService.cancelOperation((int) id); |
| // Use the full long id in case it makes a difference |
| Uri uri = ContentUris.withAppendedId(Calendars.CONTENT_URI, row.id); |
| ContentValues values = new ContentValues(); |
| // Toggle the current setting |
| int synced = row.synced ? 1 : 0; |
| values.put(Calendars.SYNC_EVENTS, synced); |
| values.put(Calendars.VISIBLE, synced); |
| mService.startUpdate((int) id, null, uri, values, null, null, 0); |
| } |
| changes.clear(); |
| } |
| } |
| getActivity().getContentResolver().unregisterContentObserver(mCalendarsObserver); |
| super.onPause(); |
| } |
| |
| @Override |
| public Loader<Cursor> onCreateLoader(int id, Bundle args) { |
| mArgs[0] = mAccount.name; |
| mArgs[1] = mAccount.type; |
| return new CursorLoader( |
| getActivity(), Calendars.CONTENT_URI, PROJECTION, SELECTION, mArgs, SORT_ORDER); |
| } |
| |
| @Override |
| public void onLoadFinished(Loader<Cursor> loader, Cursor data) { |
| SelectCalendarsSyncAdapter adapter = (SelectCalendarsSyncAdapter) getListAdapter(); |
| if (adapter == null) { |
| adapter = new SelectCalendarsSyncAdapter(getActivity(), data, getFragmentManager()); |
| setListAdapter(adapter); |
| } else { |
| adapter.changeCursor(data); |
| } |
| getListView().setOnItemClickListener(adapter); |
| } |
| |
| public void onLoaderReset(Loader<Cursor> loader) { |
| setListAdapter(null); |
| } |
| |
| // Called when the Accounts button is pressed. Takes the user to the |
| // Accounts and Sync settings page. |
| @Override |
| public void onClick(View v) { |
| Intent intent = new Intent(); |
| intent.setAction("android.settings.SYNC_SETTINGS"); |
| getActivity().startActivity(intent); |
| } |
| } |