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