Home | History | Annotate | Download | only in selectcalendars
      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 
     17 package com.android.calendar.selectcalendars;
     18 
     19 import android.accounts.Account;
     20 import android.app.Activity;
     21 import android.app.ListFragment;
     22 import android.app.LoaderManager;
     23 import android.content.ContentResolver;
     24 import android.content.ContentUris;
     25 import android.content.ContentValues;
     26 import android.content.CursorLoader;
     27 import android.content.Intent;
     28 import android.content.Loader;
     29 import android.content.res.Resources;
     30 import android.database.ContentObserver;
     31 import android.database.Cursor;
     32 import android.net.Uri;
     33 import android.os.Bundle;
     34 import android.os.Handler;
     35 import android.provider.CalendarContract;
     36 import android.provider.CalendarContract.Calendars;
     37 import android.view.LayoutInflater;
     38 import android.view.View;
     39 import android.view.ViewGroup;
     40 import android.widget.Button;
     41 import android.widget.ListAdapter;
     42 import android.widget.TextView;
     43 
     44 import com.android.calendar.AsyncQueryService;
     45 import com.android.calendar.R;
     46 import com.android.calendar.Utils;
     47 import com.android.calendar.selectcalendars.SelectCalendarsSyncAdapter.CalendarRow;
     48 
     49 import java.util.HashMap;
     50 
     51 public class SelectCalendarsSyncFragment extends ListFragment
     52         implements View.OnClickListener, LoaderManager.LoaderCallbacks<Cursor> {
     53 
     54     private static final String TAG = "SelectCalendarSync";
     55 
     56     private static final String COLLATE_NOCASE = " COLLATE NOCASE";
     57     private static final String SELECTION = Calendars.ACCOUNT_NAME + "=? AND "
     58             + Calendars.ACCOUNT_TYPE + "=?";
     59     // is primary lets us sort the user's main calendar to the top of the list
     60     private static final String IS_PRIMARY = "\"primary\"";
     61     private static final String SORT_ORDER = IS_PRIMARY + " DESC," + Calendars.CALENDAR_DISPLAY_NAME
     62             + COLLATE_NOCASE;
     63 
     64     private static final String[] PROJECTION = new String[] {
     65         Calendars._ID,
     66         Calendars.CALENDAR_DISPLAY_NAME,
     67         Calendars.CALENDAR_COLOR,
     68         Calendars.SYNC_EVENTS,
     69         Calendars.ACCOUNT_NAME,
     70         Calendars.ACCOUNT_TYPE,
     71         "(" + Calendars.ACCOUNT_NAME + "=" + Calendars.OWNER_ACCOUNT + ") AS " + IS_PRIMARY, };
     72 
     73     private TextView mSyncStatus;
     74     private Button mAccountsButton;
     75     private Account mAccount;
     76     private final String[] mArgs = new String[2];
     77     private AsyncQueryService mService;
     78     private Handler mHandler = new Handler();
     79     private ContentObserver mCalendarsObserver = new ContentObserver(mHandler) {
     80         @Override
     81         public void onChange(boolean selfChange) {
     82             // We don't need our own sync changes to trigger refreshes.
     83             if (!selfChange) {
     84                 getLoaderManager().initLoader(0, null, SelectCalendarsSyncFragment.this);
     85             }
     86         }
     87     };
     88 
     89     public SelectCalendarsSyncFragment() {
     90     }
     91 
     92     public SelectCalendarsSyncFragment(Bundle bundle) {
     93         mAccount = new Account(bundle.getString(Calendars.ACCOUNT_NAME),
     94                 bundle.getString(Calendars.ACCOUNT_TYPE));
     95     }
     96 
     97     @Override
     98     public View onCreateView(
     99             LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    100         View v = inflater.inflate(R.layout.account_calendars, null);
    101         mSyncStatus = (TextView) v.findViewById(R.id.account_status);
    102         mSyncStatus.setVisibility(View.GONE);
    103 
    104         mAccountsButton = (Button) v.findViewById(R.id.sync_settings);
    105         mAccountsButton.setVisibility(View.GONE);
    106         mAccountsButton.setOnClickListener(this);
    107 
    108         return v;
    109     }
    110 
    111     @Override
    112     public void onActivityCreated(Bundle savedInstanceState) {
    113         super.onActivityCreated(savedInstanceState);
    114         // Give some text to display if there is no data. In a real
    115         // application this would come from a resource.
    116         setEmptyText(getActivity().getText(R.string.no_syncable_calendars));
    117         // Prepare the loader. Either re-connect with an existing one,
    118         // or start a new one.
    119         getLoaderManager().initLoader(0, null, this);
    120     }
    121 
    122     @Override
    123     public void onResume() {
    124         super.onResume();
    125         if (!ContentResolver.getMasterSyncAutomatically()
    126                 || !ContentResolver.getSyncAutomatically(mAccount, CalendarContract.AUTHORITY)) {
    127             Resources res = getActivity().getResources();
    128             mSyncStatus.setText(res.getString(R.string.acct_not_synced));
    129             mSyncStatus.setVisibility(View.VISIBLE);
    130             mAccountsButton.setText(res.getString(R.string.accounts));
    131             mAccountsButton.setVisibility(View.VISIBLE);
    132         } else {
    133             mSyncStatus.setVisibility(View.GONE);
    134             mAccountsButton.setVisibility(View.GONE);
    135 
    136             // Start a background sync to get the list of calendars from the server.
    137             Utils.startCalendarMetafeedSync(mAccount);
    138             getActivity().getContentResolver().registerContentObserver(
    139                     Calendars.CONTENT_URI, true, mCalendarsObserver);
    140        }
    141     }
    142 
    143     @Override
    144     public void onAttach(Activity activity) {
    145         super.onAttach(activity);
    146         mService = new AsyncQueryService(activity);
    147 
    148         Bundle bundle = getArguments();
    149         if (bundle != null && bundle.containsKey(Calendars.ACCOUNT_NAME)
    150                 && bundle.containsKey(Calendars.ACCOUNT_TYPE)) {
    151             mAccount = new Account(bundle.getString(Calendars.ACCOUNT_NAME),
    152                     bundle.getString(Calendars.ACCOUNT_TYPE));
    153         }
    154     }
    155 
    156     @Override
    157     public void onPause() {
    158         final ListAdapter listAdapter = getListAdapter();
    159         if (listAdapter != null) {
    160             HashMap<Long, CalendarRow> changes = ((SelectCalendarsSyncAdapter) listAdapter)
    161                     .getChanges();
    162             if (changes != null && changes.size() > 0) {
    163                 for (CalendarRow row : changes.values()) {
    164                     if (row.synced == row.originalSynced) {
    165                         continue;
    166                     }
    167                     long id = row.id;
    168                     mService.cancelOperation((int) id);
    169                     // Use the full long id in case it makes a difference
    170                     Uri uri = ContentUris.withAppendedId(Calendars.CONTENT_URI, row.id);
    171                     ContentValues values = new ContentValues();
    172                     // Toggle the current setting
    173                     int synced = row.synced ? 1 : 0;
    174                     values.put(Calendars.SYNC_EVENTS, synced);
    175                     values.put(Calendars.VISIBLE, synced);
    176                     mService.startUpdate((int) id, null, uri, values, null, null, 0);
    177                 }
    178                 changes.clear();
    179             }
    180         }
    181         getActivity().getContentResolver().unregisterContentObserver(mCalendarsObserver);
    182         super.onPause();
    183     }
    184 
    185     @Override
    186     public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    187         mArgs[0] = mAccount.name;
    188         mArgs[1] = mAccount.type;
    189         return new CursorLoader(
    190                 getActivity(), Calendars.CONTENT_URI, PROJECTION, SELECTION, mArgs, SORT_ORDER);
    191     }
    192 
    193     @Override
    194     public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    195         SelectCalendarsSyncAdapter adapter = (SelectCalendarsSyncAdapter) getListAdapter();
    196         if (adapter == null) {
    197             adapter = new SelectCalendarsSyncAdapter(getActivity(), data, getFragmentManager());
    198             setListAdapter(adapter);
    199         } else {
    200             adapter.changeCursor(data);
    201         }
    202         getListView().setOnItemClickListener(adapter);
    203     }
    204 
    205     public void onLoaderReset(Loader<Cursor> loader) {
    206         setListAdapter(null);
    207     }
    208 
    209     // Called when the Accounts button is pressed. Takes the user to the
    210     // Accounts and Sync settings page.
    211     @Override
    212     public void onClick(View v) {
    213         Intent intent = new Intent();
    214         intent.setAction("android.settings.SYNC_SETTINGS");
    215         getActivity().startActivity(intent);
    216     }
    217 }
    218