12aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan/* 22aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * Copyright (C) 2011 The Android Open Source Project 32aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * 42aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * Licensed under the Apache License, Version 2.0 (the "License"); 52aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * you may not use this file except in compliance with the License. 62aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * You may obtain a copy of the License at 72aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * 82aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * http://www.apache.org/licenses/LICENSE-2.0 92aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * 102aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * Unless required by applicable law or agreed to in writing, software 112aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * distributed under the License is distributed on an "AS IS" BASIS, 122aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * See the License for the specific language governing permissions and 142aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan * limitations under the License. 152aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan */ 162aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 172aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanpackage com.android.calendar.selectcalendars; 182aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 19ec23702af6b3255ad4c975a3647e4bb4446e6ea2Michael Chanimport android.app.ActionBar; 202aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.app.ExpandableListActivity; 212aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.content.ContentResolver; 222aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.database.Cursor; 232aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.database.MatrixCursor; 242aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.os.Bundle; 252aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.provider.CalendarContract.Calendars; 26ec23702af6b3255ad4c975a3647e4bb4446e6ea2Michael Chanimport android.view.Menu; 27ec23702af6b3255ad4c975a3647e4bb4446e6ea2Michael Chanimport android.view.MenuItem; 282aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.view.View; 292aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanimport android.widget.ExpandableListView; 302aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 31bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chanimport com.android.calendar.R; 32bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chanimport com.android.calendar.Utils; 33bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan 342aeb8d988aa4b65d3402374832613ab977e009dcMichael Chanpublic class SelectSyncedCalendarsMultiAccountActivity extends ExpandableListActivity 352aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan implements View.OnClickListener { 362aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 372aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static final String TAG = "Calendar"; 382aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static final String EXPANDED_KEY = "is_expanded"; 392aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static final String ACCOUNT_UNIQUE_KEY = "ACCOUNT_KEY"; 402aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private Cursor mCursor = null; 412aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private ExpandableListView mList; 422aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private SelectSyncedCalendarsMultiAccountAdapter mAdapter; 432aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private static final String[] PROJECTION = new String[] { 442aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Calendars._ID, 452aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Calendars.ACCOUNT_TYPE, 462aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Calendars.ACCOUNT_NAME, 472aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Calendars.ACCOUNT_TYPE + " || " + Calendars.ACCOUNT_NAME + " AS " + 482aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan ACCOUNT_UNIQUE_KEY, 492aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan }; 502aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 512aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan @Override 522aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan protected void onCreate(Bundle icicle) { 532aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan super.onCreate(icicle); 542aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan setContentView(R.layout.select_calendars_multi_accounts_fragment); 552aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mList = getExpandableListView(); 562aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan//TODO Move managedQuery into a background thread. 572aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan//TODO change to something that supports group by queries. 582aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mCursor = managedQuery(Calendars.CONTENT_URI, PROJECTION, 592aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan "1) GROUP BY (" + ACCOUNT_UNIQUE_KEY, //Cheap hack to make WHERE a GROUP BY query 602aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan null /* selectionArgs */, 612aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Calendars.ACCOUNT_NAME /*sort order*/); 622aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan MatrixCursor accountsCursor = Utils.matrixCursorFromCursor(mCursor); 636fb869698103a0f897537fa7f4ebabe714db9d37Michael Chan if (accountsCursor != null) { 646fb869698103a0f897537fa7f4ebabe714db9d37Michael Chan startManagingCursor(accountsCursor); 656fb869698103a0f897537fa7f4ebabe714db9d37Michael Chan } 662aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 672aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mAdapter = new SelectSyncedCalendarsMultiAccountAdapter(findViewById(R.id.calendars) 682aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan .getContext(), accountsCursor, this); 692aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mList.setAdapter(mAdapter); 702aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 712aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // TODO initialize from sharepref 722aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan int count = mList.getCount(); 732aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan for(int i = 0; i < count; i++) { 742aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mList.expandGroup(i); 752aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 762aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 772aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // Start a background sync to get the list of calendars from the server. 782aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan startCalendarMetafeedSync(); 792aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 802aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan findViewById(R.id.btn_done).setOnClickListener(this); 812aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan findViewById(R.id.btn_discard).setOnClickListener(this); 822aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 832aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 842aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan @Override 852aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan public void onClick(View view) { 86bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan if (view.getId() == R.id.btn_done) { 87bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan mAdapter.doSaveAction(); 88bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan finish(); 89bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan } else if (view.getId() == R.id.btn_discard) { 90bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan finish(); 912aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 922aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 932aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 942aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan @Override 952aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan protected void onResume() { 962aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan super.onResume(); 972aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan if (mAdapter != null) { 982aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mAdapter.startRefreshStopDelay(); 992aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 1002aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 1012aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 1022aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan @Override 1032aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan protected void onPause() { 1042aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan super.onPause(); 1052aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mAdapter.cancelRefreshStopDelay(); 1062aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 1072aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 1082aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan @Override 1092aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan protected void onSaveInstanceState(Bundle outState) { 1102aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan super.onSaveInstanceState(outState); 1112aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan boolean[] isExpanded; 1122aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mList = getExpandableListView(); 1132aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan if(mList != null) { 1142aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan int count = mList.getCount(); 1152aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan isExpanded = new boolean[count]; 1162aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan for(int i = 0; i < count; i++) { 1172aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan isExpanded[i] = mList.isGroupExpanded(i); 1182aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 1192aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } else { 1202aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan isExpanded = null; 1212aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 1222aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan outState.putBooleanArray(EXPANDED_KEY, isExpanded); 1232aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan //TODO Store this to preferences instead so it remains on restart 1242aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 1252aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 1262aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan @Override 1272aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan protected void onRestoreInstanceState(Bundle state) { 1282aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan super.onRestoreInstanceState(state); 1292aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mList = getExpandableListView(); 1302aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan boolean[] isExpanded = state.getBooleanArray(EXPANDED_KEY); 1312aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan if(mList != null && isExpanded != null && mList.getCount() >= isExpanded.length) { 1322aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan for(int i = 0; i < isExpanded.length; i++) { 1332aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan if(isExpanded[i] && !mList.isGroupExpanded(i)) { 1342aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mList.expandGroup(i); 1352aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } else if(!isExpanded[i] && mList.isGroupExpanded(i)){ 1362aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan mList.collapseGroup(i); 1372aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 1382aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 1392aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 1402aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 1412aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan 142ec23702af6b3255ad4c975a3647e4bb4446e6ea2Michael Chan @Override 143ec23702af6b3255ad4c975a3647e4bb4446e6ea2Michael Chan public boolean onCreateOptionsMenu(Menu menu) { 144ec23702af6b3255ad4c975a3647e4bb4446e6ea2Michael Chan getActionBar() 145ec23702af6b3255ad4c975a3647e4bb4446e6ea2Michael Chan .setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP, ActionBar.DISPLAY_HOME_AS_UP); 146ec23702af6b3255ad4c975a3647e4bb4446e6ea2Michael Chan return true; 147ec23702af6b3255ad4c975a3647e4bb4446e6ea2Michael Chan } 148ec23702af6b3255ad4c975a3647e4bb4446e6ea2Michael Chan 149ec23702af6b3255ad4c975a3647e4bb4446e6ea2Michael Chan @Override 150ec23702af6b3255ad4c975a3647e4bb4446e6ea2Michael Chan public boolean onOptionsItemSelected(MenuItem item) { 151ec23702af6b3255ad4c975a3647e4bb4446e6ea2Michael Chan switch (item.getItemId()) { 152ec23702af6b3255ad4c975a3647e4bb4446e6ea2Michael Chan case android.R.id.home: 153ec23702af6b3255ad4c975a3647e4bb4446e6ea2Michael Chan Utils.returnToCalendarHome(this); 154ec23702af6b3255ad4c975a3647e4bb4446e6ea2Michael Chan return true; 155ec23702af6b3255ad4c975a3647e4bb4446e6ea2Michael Chan } 156ec23702af6b3255ad4c975a3647e4bb4446e6ea2Michael Chan return super.onOptionsItemSelected(item); 157ec23702af6b3255ad4c975a3647e4bb4446e6ea2Michael Chan } 158ec23702af6b3255ad4c975a3647e4bb4446e6ea2Michael Chan 1592aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // startCalendarMetafeedSync() checks the server for an updated list of 1602aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // Calendars (in the background). 1612aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // 1622aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // If a Calendar is added on the web (and it is selected and not 1632aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // hidden) then it will be added to the list of calendars on the phone 1642aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // (when this finishes). When a new calendar from the 1652aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // web is added to the phone, then the events for that calendar are also 1662aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // downloaded from the web. 1672aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // 1682aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // This sync is done automatically in the background when the 1692aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan // SelectCalendars activity is started. 1702aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan private void startCalendarMetafeedSync() { 1712aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Bundle extras = new Bundle(); 1722aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); 1732aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan extras.putBoolean("metafeedonly", true); 1742aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan ContentResolver.requestSync(null /* all accounts */, 1752aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan Calendars.CONTENT_URI.getAuthority(), extras); 1762aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan } 1772aeb8d988aa4b65d3402374832613ab977e009dcMichael Chan} 178