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