com.nononsenseapps.notepad.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.nononsenseapps.notepad.MainActivity.java

Source

/*
 * Copyright (C) 2012 Jonas Kalderstam
 *
 * 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.nononsenseapps.notepad;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Locale;

import sheetrock.panda.changelog.ChangeLog;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.annotation.TargetApi;
import android.app.ActionBar;
import android.app.ActionBar.OnNavigationListener;
import android.app.Activity;
import android.app.Dialog;
import android.app.LoaderManager;
import android.app.SearchManager;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.Cursor;
import android.database.SQLException;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;

import com.nononsenseapps.helpers.Log;
import com.nononsenseapps.helpers.NotificationHelper;
import com.nononsenseapps.helpers.SyncHelper;
import com.nononsenseapps.helpers.UpdateNotifier;
import com.nononsenseapps.helpers.dualpane.DualLayoutActivity;
import com.nononsenseapps.notepad.NotesListFragment.Callbacks;
import com.nononsenseapps.notepad.PasswordDialog.ActionResult;
import com.nononsenseapps.notepad.interfaces.PasswordChecker;
import com.nononsenseapps.notepad.prefs.MainPrefs;
import com.nononsenseapps.notepad.prefs.PrefsActivity;
import com.nononsenseapps.notepad.prefs.SyncPrefs;
import com.nononsenseapps.notepad.sync.SyncAdapter;
//import com.nononsenseapps.notepad.sync.SyncAdapter;
import com.nononsenseapps.ui.ListPagerAdapter;

import android.content.res.Configuration;

/**
 * Showing a single fragment in an activity.
 */
public class MainActivity extends DualLayoutActivity implements OnSharedPreferenceChangeListener,
        OnNavigationListener, LoaderManager.LoaderCallbacks<Cursor>, PasswordChecker, Callbacks {
    public static final String TAG = "nononsensenotes";
    private static final String CURRENT_LIST_ID = "currentlistid";
    private static final String CURRENT_LIST_POS = "currentlistpos";
    private static final String RESUMING = "resuming";
    private static final int CREATE_LIST = 0;
    private static final int RENAME_LIST = 1;
    private static final int DELETE_LIST = 2;
    // public static boolean lightTheme = false;
    public static String currentTheme = MainPrefs.THEME_LIGHT_ICS_AB;
    public static boolean shouldRestart = false;

    // For my special dropdown navigation items
    public static final int ALL_NOTES_ID = -2;
    public static final int CREATE_LIST_ID = -3;

    private SimpleCursorAdapter mSpinnerAdapter;
    private SimpleCursorAdapter mSectionAdapter;
    private long currentListId = -1;
    private int currentListPos = 0;

    private boolean resuming = false;

    private long listIdToSelect = -1;
    private boolean beforeBoot = false; // Used to indicate the intent handling
    // private NotesListFragment list;

    /**
     * The {@link android.support.v4.view.PagerAdapter} that will provide
     * fragments for each of the sections. We use a
     * {@link android.support.v4.app.FragmentPagerAdapter} derivative, which
     * will keep every loaded fragment in memory. If this becomes too memory
     * intensive, it may be best to switch to a
     * {@link android.support.v4.app.FragmentStatePagerAdapter}.
     */
    private ListPagerAdapter mSectionsPagerAdapter;

    /**
     * The {@link ViewPager} that will host the section contents.
     */
    private ViewPager mViewPager;
    private long noteIdToSelect;
    private Intent noteIntentToSelect;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // Must set theme before calling super
        readAndSetSettings();
        super.onCreate(savedInstanceState);

        if (savedInstanceState != null) {
            resuming = savedInstanceState.getBoolean(RESUMING);
        }

        if (currentContent.equals(CONTENTVIEW.DUAL) || currentContent.equals(CONTENTVIEW.LEFT)) {
            leftOrTabletCreate(savedInstanceState);
        } else {
            rightCreate();
        }

        // Synchronize on app open
        syncOnStart();

        // Schedule notifications if needed
        NotificationHelper.schedule(this);
    }

    protected void syncOnStart() {
        SyncHelper.requestSyncIf(this, SyncHelper.ONAPPSTART);
    }

    private void leftOrTabletCreate(Bundle savedInstanceState) {
        if (savedInstanceState != null) {
            // currentListId = savedInstanceState.getLong(CURRENT_LIST_ID);
            listIdToSelect = savedInstanceState.getLong(CURRENT_LIST_ID);
            // currentListPos = savedInstanceState.getInt(CURRENT_LIST_POS);
        }

        // Set up dropdown navigation
        final ActionBar actionBar = getActionBar();
        actionBar.setDisplayShowTitleEnabled(false);
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);

        // Will set cursor in Loader
        // mSpinnerAdapter = new ExtrasCursorAdapter(this,
        // R.layout.actionbar_dropdown_item, null,
        // new String[] { NotePad.Lists.COLUMN_NAME_TITLE },
        // new int[] { android.R.id.text1 }, new int[] { -9, -8 },
        // new int[] { R.string.show_from_all_lists, R.string.error_title });
        mSpinnerAdapter = new SimpleCursorAdapter(this, R.layout.actionbar_dropdown_item, null,
                new String[] { NotePad.Lists.COLUMN_NAME_TITLE }, new int[] { android.R.id.text1 }, 0);

        mSpinnerAdapter.setDropDownViewResource(R.layout.actionbar_dropdown_item);

        // This will listen for navigation callbacks
        actionBar.setListNavigationCallbacks(mSpinnerAdapter, this);

        // setContentView(R.layout.fragment_layout);

        // setUpList();

        mSectionAdapter = new SimpleCursorAdapter(this, R.layout.actionbar_dropdown_item, null,
                new String[] { NotePad.Lists.COLUMN_NAME_TITLE }, new int[] { android.R.id.text1 }, 0);

        mSectionsPagerAdapter = new ListPagerAdapter(this, getFragmentManager(), mSectionAdapter);

        // Set up the ViewPager with the sections adapter.
        mViewPager = (ViewPager) findViewById(R.id.leftFragment);
        mViewPager.setAdapter(mSectionsPagerAdapter);

        mViewPager.setOnPageChangeListener(new OnPageChangeListener() {

            @Override
            public void onPageSelected(int pos) {
                currentListId = mSectionsPagerAdapter.getItemId(pos);
                currentListPos = pos;
                actionBar.setSelectedNavigationItem(pos);
            }

            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) {

            }

            @Override
            public void onPageScrollStateChanged(int arg0) {

            }
        });

        // Set up navigation list
        // Set a default list to open if one is set
        if (listIdToSelect < 0) {
            listIdToSelect = getAList(this, -1);
            // Select the first note in that list to open also
            noteIdToSelect = getANote(this, listIdToSelect);
        }
        // Handle the intent first, so we know what to possibly select once
        // the
        // loader is finished
        beforeBoot = true;

        if (!resuming) {
            onNewIntent(getIntent());
        }

        getLoaderManager().initLoader(0, null, this);
    }

    private static long getANote(Context context, long listId) {
        long noteId = -1;
        if (listId < 0)
            return noteId;

        Cursor cursor;
        final String listString = Long.toString(listId);
        cursor = context.getContentResolver().query(NotePad.Notes.CONTENT_VISIBLE_URI,
                new String[] { NotePad.Notes._ID }, NotePad.Notes.COLUMN_NAME_LIST + " IS ?",
                new String[] { listString }, NotePad.Notes.SORT_ORDER + " LIMIT 1");

        if (cursor != null && cursor.moveToFirst()) {
            noteId = cursor.getLong(cursor.getColumnIndex(NotePad.Notes._ID));
            Log.d(TAG, "getANote: " + noteId);
        }
        if (cursor != null)
            cursor.close();

        return noteId;
    }

    private void rightCreate() {
        // Set up navigation (adds nice arrow to icon)
        ActionBar actionBar = getActionBar();
        if (actionBar != null) {
            actionBar.setDisplayShowTitleEnabled(false);
        }
        if (!resuming) {
            onNewIntent(getIntent());
        }
    }

    // private void setUpList() {
    // if (leftFragment != null) {
    // NotesListFragment list = (NotesListFragment) leftFragment;
    //
    // this.list = list;
    // }
    // }

    /**
     * Launches the main activity
     */
    @Override
    protected void goUp() {
        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).setClass(this, MainActivity.class);

        startActivity(intent);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_options_menu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        // Hide entire sub menu in editor.
        if (currentContent == CONTENTVIEW.RIGHT) {
            MenuItem manageLists = menu.findItem(R.id.menu_managelists);
            if (manageLists != null)
                manageLists.setVisible(false);
            MenuItem clear = menu.findItem(R.id.menu_clearcompleted);
            if (clear != null)
                clear.setVisible(false);
            MenuItem sync = menu.findItem(R.id.menu_sync);
            if (sync != null)
                sync.setVisible(false);
        } else {
            MenuItem deleteList = menu.findItem(R.id.menu_deletelist);
            MenuItem renameList = menu.findItem(R.id.menu_renamelist);
            MenuItem setDefaultList = menu.findItem(R.id.menu_setdefaultlist);
            if (null != mSectionAdapter) {
                if (deleteList != null) {
                    // Only show this button if there is a list
                    if (mSectionAdapter.getCount() <= 0) {
                        deleteList.setVisible(false);
                    } else {
                        deleteList.setVisible(true);
                    }
                }
                if (renameList != null) {
                    // Only show this button if there is a list
                    if (mSectionAdapter.getCount() <= 0) {
                        renameList.setVisible(false);
                    } else {
                        renameList.setVisible(true);
                    }
                }
                if (setDefaultList != null) {
                    // Only show this button if there is a list
                    if (mSectionAdapter.getCount() <= 0) {
                        setDefaultList.setVisible(false);
                    } else {
                        setDefaultList.setVisible(true);
                    }
                }
            } else {
                // with null adapter, must hide
                if (deleteList != null) {
                    deleteList.setVisible(false);
                }
                if (renameList != null) {
                    renameList.setVisible(false);
                }
                if (setDefaultList != null)
                    setDefaultList.setVisible(false);
            }
        }

        return super.onPrepareOptionsMenu(menu);
    }

    /**
     * If the user has a search button, ideally he should be able to use it.
     * Expand the search provider in that case
     */
    @TargetApi(14)
    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        switch (keyCode) {
        case KeyEvent.KEYCODE_SEARCH:
            // Ignore this in HC because it will crash there
            if (getResources().getBoolean(R.bool.atLeast14)) {
                NotesListFragment list = getLeftFragment();
                if (list != null && list.mSearchItem != null) {
                    list.mSearchItem.expandActionView();
                } else if (list != null) {
                    onSearchRequested();
                }
            }
            return true;
        case KeyEvent.KEYCODE_BACK:
            // Exit app
            finish();
            return true;
        }
        return false;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean(RESUMING, true);
        // Save current list
        outState.putLong(CURRENT_LIST_ID, currentListId);
        outState.putInt(CURRENT_LIST_POS, currentListPos);
    }

    private void handleEditIntent(Intent intent) {
        // First, if we should display a list
        if (intent.getData() != null && (intent.getData().getPath().startsWith(NotePad.Lists.PATH_VISIBLE_LIST_ID)
                || intent.getData().getPath().startsWith(NotePad.Lists.PATH_LIST_ID))) {
            // Get id to display
            String newId = intent.getData().getPathSegments().get(NotePad.Lists.ID_PATH_POSITION);
            long listId = Long.parseLong(newId);
            // Handle it differently depending on if the app has already
            // loaded or not.
            openListFromIntent(listId, null);
        } else if (intent.getData() != null
                && (intent.getData().getPath().startsWith(NotePad.Notes.PATH_VISIBLE_NOTES)
                        || intent.getData().getPath().startsWith(NotePad.Notes.PATH_NOTES))) {
            openNoteFragment(intent);
        }
    }

    /**
     * Creates an editor fragment for the note specified in the intent. Use for
     * edit and complete intents.
     * 
     * @param intent
     */
    private void openNoteFragment(Intent intent) {
        Log.d(TAG, "openNoteFragment");
        Bundle arguments = new Bundle();
        arguments.putLong(NotesEditorFragment.KEYID, NotesEditorFragment.getIdFromUri(intent.getData()));
        NotesEditorFragment fragment = new NotesEditorFragment();
        fragment.setArguments(arguments);
        getFragmentManager().beginTransaction().replace(R.id.rightFragment, fragment).commit();
        // Open appropriate list if tablet mode
        if (this.currentContent == CONTENTVIEW.DUAL) {
            long listId = getAList(intent);
            /*
             * Open the containing list if we have to. No need to change lists
             * if we are already displaying all notes.
             */
            openListFromIntent(listId, intent);
        }
    }

    private void handleInsertIntent(Intent intent) {
        if (intent.getType() != null && intent.getType().equals(NotePad.Lists.CONTENT_TYPE)
                || intent.getData() != null && intent.getData().equals(NotePad.Lists.CONTENT_VISIBLE_URI)) {
            // get Title
            if (intent.getExtras() != null) {
                String title = intent.getExtras().getString(NotePad.Lists.COLUMN_NAME_TITLE, "");
                createList(title);
            }
        } else if (intent.getType() != null
                && (intent.getType().equals(NotePad.Notes.CONTENT_TYPE) || intent.getType().startsWith("text/"))
                || intent.getData() != null && intent.getData().equals(NotePad.Notes.CONTENT_VISIBLE_URI)) {
            Log.d("FragmentLayout", "INSERT NOTE");
            // Get list to create note in first
            long listId = getAList(intent);
            String text = "";
            if (intent.getExtras() != null) {
                text = intent.getExtras().getCharSequence(Intent.EXTRA_TEXT, "").toString();
            }

            if (listId > -1) {
                Uri noteUri = MainActivity.createNote(this, listId, text);

                if (noteUri != null) {
                    Bundle arguments = new Bundle();
                    arguments.putLong(NotesEditorFragment.KEYID, NotesEditorFragment.getIdFromUri(noteUri));
                    NotesEditorFragment fragment = new NotesEditorFragment();
                    fragment.setArguments(arguments);
                    getFragmentManager().beginTransaction().replace(R.id.rightFragment, fragment).commit();
                }

                // Open appropriate list if tablet mode
                if (this.currentContent == CONTENTVIEW.DUAL) {
                    // Open the containing list if we have to. No need to
                    // change
                    // lists
                    // if we are already displaying all notes.
                    openListFromIntent(listId, intent);
                }
            }
        }
    }

    public static long getAList(Context context, long tempList) {
        long returnList = -1;

        if (tempList < 0) {
            // Then check if a default list is specified
            tempList = Long.parseLong(PreferenceManager.getDefaultSharedPreferences(context)
                    .getString(MainPrefs.KEY_DEFAULT_LIST, "-1"));
            Log.d(TAG, "Default list: " + tempList);
        }
        // Not guaranteed that this is valid. Check the database even if it
        // exists.
        // Limit to 1 result. Returns default list if it exists
        final String criteria = NotePad.Lists._ID + " = ?";
        Cursor cursor;
        if (tempList > -1) {
            final String listString = Long.toString(tempList);
            cursor = context.getContentResolver().query(NotePad.Lists.CONTENT_VISIBLE_URI,
                    new String[] { NotePad.Lists._ID },
                    criteria + " OR NOT (EXISTS (SELECT NULL FROM " + NotePad.Lists.TABLE_NAME + " WHERE "
                            + criteria + "))",
                    new String[] { listString, listString }, NotePad.Lists.SORT_ORDER + " LIMIT 1");
        } else {
            cursor = context.getContentResolver().query(NotePad.Lists.CONTENT_VISIBLE_URI,
                    new String[] { NotePad.Lists._ID }, null, null, NotePad.Lists.SORT_ORDER + " LIMIT 1");
        }
        if (cursor != null && cursor.moveToFirst()) {
            returnList = cursor.getLong(cursor.getColumnIndex(NotePad.Lists._ID));
            Log.d(TAG, "database list: " + returnList);
        }
        if (cursor != null)
            cursor.close();

        return returnList;
    }

    /**
     * Will find a suitable list. Which is first ' If the intent contains a list
     * or the default list, if no valid default list then the first list is
     * returned. If there are no lists, then -1 is returned.
     */
    private long getAList(Intent intent) {
        long tempList = -1;
        // First see if the intent specifies a list
        if (intent != null && intent.getExtras() != null) {
            long intentId = intent.getExtras().getLong(NotePad.Notes.COLUMN_NAME_LIST, -1);

            if (intentId > -1) {
                tempList = intentId;
                Log.d(TAG, "Intent list: " + intentId);
            }
        }

        return getAList(this, tempList);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        // Search
        if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
            String query = intent.getStringExtra(SearchManager.QUERY);
            // list.onQueryTextChange(query);
            NotesListFragment list = getLeftFragment();
            if (list != null && list.mSearchView != null) {
                list.mSearchView.setQuery(query, false);
            } else if (list != null) {
                list.onQueryTextSubmit(query);
            }
            // Edit or View a list or a note.
        } else if (Intent.ACTION_EDIT.equals(intent.getAction()) || Intent.ACTION_VIEW.equals(intent.getAction())) {
            handleEditIntent(intent);
        } else if (Intent.ACTION_INSERT.equals(intent.getAction())) {
            handleInsertIntent(intent);
        } else if (Intent.ACTION_SEND.equals(intent.getAction())) {
            handleInsertIntent(intent);
        } else if (getString(R.string.complete_note_broadcast_intent).equals(intent.getAction())) {
            // Sent from lock-screen widget on 4.2 and above.
            // Send complete broadcast and finish
            long noteId = NotesEditorFragment.getIdFromUri(intent.getData());
            // This will complete the note
            if (noteId > -1) {
                Intent bintent = new Intent(this, NotePadBroadcastReceiver.class);
                bintent.setAction(getString(R.string.complete_note_broadcast_intent));
                bintent.putExtra(NotePad.Notes._ID, noteId);
                Log.d(TAG, "Sending complete broadcast");
                sendBroadcast(bintent);

                openNoteFragment(intent);

                // Toast.makeText(this, getString(R.string.completed),
                // Toast.LENGTH_SHORT).show();
            }
        } else {
            // Open a note
            if (noteIdToSelect > -1 && currentContent == CONTENTVIEW.DUAL) {
                Bundle arguments = new Bundle();
                arguments.putLong(NotesEditorFragment.KEYID, noteIdToSelect);
                NotesEditorFragment fragment = new NotesEditorFragment();
                fragment.setArguments(arguments);
                getFragmentManager().beginTransaction().replace(R.id.rightFragment, fragment).commit();
                noteIdToSelect = -1;
            }
        }
    }

    /**
     * This is meant to be called from the intent handling. It handles the two
     * possible cases that this app was already running when it received the
     * intent or it was started fresh with the intent meaning we have to handle
     * the opening asynchronously.
     * 
     * @param listId
     */
    private void openListFromIntent(long listId, Intent intent) {
        if (beforeBoot) {
            // Set the variable to be selected after the loader has
            // finished its query
            listIdToSelect = listId;
            noteIntentToSelect = intent;
            Log.d(TAG, "beforeBoot setting future id");
        } else {
            // Select the list directly since the loader is done
            int pos = getPosOfId(listId);
            Log.d("FragmentLayout", "pos: " + pos);
            if (pos > -1) {
                // select it
                ActionBar ab = getActionBar();
                if (ab != null && ab.getSelectedNavigationIndex() != pos) {
                    ab.setSelectedNavigationItem(pos);
                }
                NotesListFragment list = getLeftFragment();
                if (list != null) {
                    list.handleNoteIntent(intent);
                }
            }
        }
    }

    @Override
    protected void onResume() {
        if (shouldRestart) {
            restartAndRefresh();
        }
        super.onResume();
        // Show changelog if it is new
        ChangeLog cl = new ChangeLog(this);
        if (cl.firstRun())
            cl.getLogDialog().show();
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
        case DELETE_LIST:
            final Dialog deleteDialog = new Dialog(this);
            deleteDialog.setContentView(R.layout.delete_list_dialog);
            deleteDialog.setTitle(R.string.menu_deletelist);

            Button dYesButton = (Button) deleteDialog.findViewById(R.id.d_dialog_yes);
            dYesButton.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    deleteCurrentList();
                    deleteDialog.dismiss();
                }
            });

            Button dNoButton = (Button) deleteDialog.findViewById(R.id.d_dialog_no);
            dNoButton.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    deleteDialog.cancel();
                }
            });
            return deleteDialog;
        case CREATE_LIST:
            final Dialog dialog = new Dialog(this);
            dialog.setContentView(R.layout.create_list_dialog);
            dialog.setTitle(R.string.menu_createlist);

            EditText title = (EditText) dialog.findViewById(R.id.editTitle);
            title.setText("");

            Button yesButton = (Button) dialog.findViewById(R.id.dialog_yes);
            yesButton.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    EditText title = (EditText) dialog.findViewById(R.id.editTitle);
                    createList(title.getText().toString());
                    title.setText("");
                    dialog.dismiss();
                }
            });

            Button noButton = (Button) dialog.findViewById(R.id.dialog_no);
            noButton.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    getActionBar().setSelectedNavigationItem(currentListPos);
                    dialog.cancel();
                }
            });
            return dialog;
        case RENAME_LIST:
            final Dialog renameDialog = new Dialog(this);
            renameDialog.setContentView(R.layout.rename_list_dialog);
            renameDialog.setTitle(R.string.menu_renamelist);

            CharSequence currentTitle = "";
            if (mSectionsPagerAdapter != null)
                currentTitle = mSectionsPagerAdapter.getPageTitle(currentListPos);

            EditText renameTitle = (EditText) renameDialog.findViewById(R.id.renameTitle);
            renameTitle.setText(currentTitle);

            Button rYesButton = (Button) renameDialog.findViewById(R.id.r_dialog_yes);
            rYesButton.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    EditText renameTitle = (EditText) renameDialog.findViewById(R.id.renameTitle);
                    renameList(renameTitle.getText().toString());
                    renameTitle.setText("");
                    renameDialog.dismiss();
                }
            });

            Button rNoButton = (Button) renameDialog.findViewById(R.id.r_dialog_no);
            rNoButton.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    renameDialog.cancel();
                }
            });
            return renameDialog;

        default:
            return null;
        }
    }

    protected void createList(String title) {
        // I will not allow empty names for lists
        if (!title.equals("")) {
            ContentValues values = new ContentValues();
            values.put(NotePad.Lists.COLUMN_NAME_TITLE, title);
            // Add list
            Uri listUri = getContentResolver().insert(NotePad.Lists.CONTENT_URI, values);
            listIdToSelect = Long.parseLong(listUri.getPathSegments().get(NotePad.Lists.ID_PATH_POSITION));
            UpdateNotifier.notifyChangeList(getApplicationContext());
        }
    }

    private int getPosOfId(long id) {
        int length = mSectionAdapter.getCount();
        int position;
        boolean found = false;
        for (position = 0; position < length; position++) {
            if (id == mSpinnerAdapter.getItemId(position)) {
                found = true;
                break;
            }
        }
        if (!found) {
            // Happens both if list is empty
            // and if id is -1
            position = -1;
        }
        return position;
    }

    protected void renameList(String title) {
        // I will not allow empty names for lists
        // Also must have a valid id
        if (!title.equals("") && currentListId > -1) {
            ContentValues values = new ContentValues();
            values.put(NotePad.Lists.COLUMN_NAME_TITLE, title);
            // Update list
            getContentResolver().update(
                    Uri.withAppendedPath(NotePad.Lists.CONTENT_ID_URI_BASE, Long.toString(currentListId)), values,
                    null, null);
            UpdateNotifier.notifyChangeList(getApplicationContext(),
                    Uri.withAppendedPath(NotePad.Lists.CONTENT_ID_URI_BASE, Long.toString(currentListId)));
        }
    }

    /**
     * Returns true if user has activated sync and there is a valid account name
     * selected (not "")
     * 
     * @return
     */
    public static boolean shouldMarkAsDeleted(Context context) {
        SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
        if (settings == null)
            return false;
        else
            return (!settings.getString(SyncPrefs.KEY_ACCOUNT, "").isEmpty());
    }

    /**
     * Marks the current list and all the tasks contained in it as deleted in
     * the database. Will be deleted on next sync.
     */
    protected void deleteCurrentList() {
        Log.d("deletebug", "currentlistid: " + currentListId);
        if (currentListId > -1) {
            // Only mark as deleted so it is synced
            if (shouldMarkAsDeleted(this)) {
                ContentValues values = new ContentValues();
                values.put(NotePad.Lists.COLUMN_NAME_DELETED, 1);
                // Mark list as deleted
                getContentResolver().update(
                        Uri.withAppendedPath(NotePad.Lists.CONTENT_ID_URI_BASE, Long.toString(currentListId)),
                        values, null, null);
                // Mark tasks as hidden locally. They are deleted with the list
                // in
                // the sync
                values = new ContentValues();
                values.put(NotePad.Notes.COLUMN_NAME_DELETED, 1);
                values.put(NotePad.Notes.COLUMN_NAME_MODIFIED, 0); // Yes zero,
                // we
                // don't
                // want to
                // sync
                // tasks in
                // deleted
                // lists
                Log.d("deletebug", "marking as deleted");
                getContentResolver().update(NotePad.Notes.CONTENT_URI, values,
                        NotePad.Notes.COLUMN_NAME_LIST + " IS " + currentListId, null);
            } else {
                // Delete for real
                Log.d("deletebug", "actually deleting");
                getContentResolver().delete(
                        Uri.withAppendedPath(NotePad.Lists.CONTENT_ID_URI_BASE, Long.toString(currentListId)), null,
                        null);
            }
            Log.d("deletebug", "notify!");
            UpdateNotifier.notifyChangeList(this,
                    Uri.withAppendedPath(NotePad.Lists.CONTENT_ID_URI_BASE, Long.toString(currentListId)));
            UpdateNotifier.notifyChangeNote(this);

            // Remove default setting if this is the default list
            long defaultListId = Long.parseLong(PreferenceManager.getDefaultSharedPreferences(this)
                    .getString(MainPrefs.KEY_DEFAULT_LIST, "-1"));
            if (currentListId == defaultListId) {
                // Remove knowledge of default list
                SharedPreferences.Editor prefEditor = PreferenceManager.getDefaultSharedPreferences(this).edit();
                prefEditor.remove(MainPrefs.KEY_DEFAULT_LIST);
                prefEditor.commit();
            }
        }
    }

    public void restartAndRefresh() {
        shouldRestart = false;
        Intent intent = getIntent();
        overridePendingTransition(0, 0);
        intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
        finish();
        overridePendingTransition(0, 0);
        startActivity(intent);
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        // Need to restart to allow themes and such to go into effect
        if (key.equals(MainPrefs.KEY_THEME) || key.equals(MainPrefs.KEY_HIDDENCHECKBOX)
                || key.equals(MainPrefs.KEY_HIDDENDATE) || key.equals(MainPrefs.KEY_HIDDENNOTE)
                || key.equals(MainPrefs.KEY_TITLEROWS) || key.equals(MainPrefs.KEY_SORT_ORDER)
                || key.equals(MainPrefs.KEY_SORT_TYPE) || key.equals(getString(R.string.pref_locale))
                || key.equals(MainPrefs.KEY_LISTHEADERS)) {
            shouldRestart = true;
        }
    }

    private void readAndSetSettings() {
        // Read settings and set
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);

        currentTheme = prefs.getString(MainPrefs.KEY_THEME, currentTheme);

        setTypeOfTheme();

        // Set language
        Configuration config = getResources().getConfiguration();

        String lang = prefs.getString(getString(R.string.pref_locale), "");
        if (!config.locale.toString().equals(lang)) {
            Locale locale;
            if ("".equals(lang))
                locale = Locale.getDefault();
            else if (lang.length() == 5) {
                locale = new Locale(lang.substring(0, 2), lang.substring(3, 5));
            } else {
                locale = new Locale(lang.substring(0, 2));
            }
            // Locale.setDefault(locale);
            config.locale = locale;
            getResources().updateConfiguration(config, getResources().getDisplayMetrics());
        }

        String sortType = prefs.getString(MainPrefs.KEY_SORT_TYPE, NotePad.Notes.DEFAULT_SORT_TYPE);
        String sortOrder = prefs.getString(MainPrefs.KEY_SORT_ORDER, NotePad.Notes.DEFAULT_SORT_ORDERING);

        NotePad.Notes.SORT_ORDER = sortType + " " + sortOrder;

        // We want to be notified of future changes
        prefs.registerOnSharedPreferenceChangeListener(this);
    }

    private void setTypeOfTheme() {
        if (MainPrefs.THEME_LIGHT_ICS_AB.equals(currentTheme)) {
            setTheme(R.style.ThemeHoloLightDarkActonBar);
        } else if (MainPrefs.THEME_LIGHT.equals(currentTheme)) {
            setTheme(R.style.ThemeHoloLight);
        } else if (MainPrefs.THEME_BLACK.equals(currentTheme)) {
            setTheme(R.style.ThemeHoloBlack);
        } else {
            setTheme(R.style.ThemeHolo);
        }
    }

    @Override
    public void PasswordVerified(ActionResult result) {
        NotesEditorFragment editor = (NotesEditorFragment) getRightFragment();
        if (editor != null) {
            editor.OnPasswordVerified(result);
        }
    }

    @TargetApi(14)
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.menu_delete:
            onDeleteAction();
            break;
        case R.id.menu_preferences:
            showPrefs();
            return true;
        case R.id.menu_setdefaultlist:
            long currentId = -1;
            if (mSectionsPagerAdapter != null)
                currentId = mSectionsPagerAdapter.getItemId(currentListPos);

            if (currentId != -1) {
                PreferenceManager.getDefaultSharedPreferences(this).edit()
                        .putString(MainPrefs.KEY_DEFAULT_LIST, Long.toString(currentId)).commit();

                Toast.makeText(this, getString(R.string.default_list_set), Toast.LENGTH_SHORT).show();
            }

            break;
        case R.id.menu_createlist:
            showDialog(CREATE_LIST);
            return true;
        case R.id.menu_renamelist:
            // Create dialog
            showDialog(RENAME_LIST);
            return true;
        case R.id.menu_deletelist:
            // Create dialog
            showDialog(DELETE_LIST);
            return true;
        case R.id.menu_search:
            // Cant do this in HC, because it will crash.
            // Ignore search button in HC
            if (getResources().getBoolean(R.bool.atLeast14)) {
                NotesListFragment list = getLeftFragment();
                if (list != null && list.mSearchItem != null) {
                    list.mSearchItem.expandActionView();
                } else if (list != null) {
                    // Launches the search window
                    onSearchRequested();
                }
            }
            return true;
        case R.id.menu_revert:
            if (currentContent.equals(CONTENTVIEW.RIGHT)) {
                goUp();
            }
            break;
        case R.id.menu_sync:

            SyncHelper.requestSyncIf(this, SyncHelper.MANUAL);

            String accountName = PreferenceManager.getDefaultSharedPreferences(this)
                    .getString(SyncPrefs.KEY_ACCOUNT, "");
            boolean syncEnabled = PreferenceManager.getDefaultSharedPreferences(this)
                    .getBoolean(SyncPrefs.KEY_SYNC_ENABLE, false);
            if (accountName != null && !accountName.equals("") && syncEnabled) {
                requestSync(accountName);
            } else {
                // Enable syncing
                enableSync();
            }
            return false; // Editor will listen for this also and saves when it
                          // receives it
        }
        return super.onOptionsItemSelected(item);
    }

    private void enableSync() {
        final Activity activity = this;
        // Get the first Google account on the device
        final Account[] accounts = AccountManager.get(activity).getAccountsByType("com.google");
        if (accounts.length > 0) {
            final Account account = accounts[0];

            // Request access
            AccountManager.get(activity).getAuthToken(account, SyncAdapter.AUTH_TOKEN_TYPE, null, activity,
                    new AccountManagerCallback<Bundle>() {

                        @Override
                        public void run(AccountManagerFuture<Bundle> future) {
                            // This is the callback class, it handles all the
                            // steps
                            // after requesting access
                            try {
                                String token = future.getResult().getString(AccountManager.KEY_AUTHTOKEN);
                                if (token != null && !token.equals("") && account != null) {
                                    // Get preference editor
                                    Editor editor = PreferenceManager.getDefaultSharedPreferences(activity).edit();

                                    // Write account name to prefs
                                    editor.putString(SyncPrefs.KEY_ACCOUNT, account.name);

                                    // Set it syncable
                                    ContentResolver.setIsSyncable(account, NotePad.AUTHORITY, 1);

                                    // Write to pref
                                    editor.putBoolean(SyncPrefs.KEY_SYNC_ENABLE, true);

                                    // Commit prefs
                                    editor.commit();

                                    // Then request sync
                                    requestSync(account.name);
                                }
                            } catch (OperationCanceledException e) {
                                Log.e("SyncFix", "Error1");
                                // if the request was canceled for any reason
                            } catch (AuthenticatorException e) {
                                Log.e("SyncFix", "Error2");
                                // if there was an error communicating with the
                                // authenticator or
                                // if the authenticator returned an invalid
                                // response
                            } catch (IOException e) {
                                Log.e("SyncFix", "Error3");
                                // if the authenticator returned an error
                                // response that
                                // indicates that it encountered an IOException
                                // while
                                // communicating with the authentication server
                            }
                        }
                    }, null);

        }
    }

    private void requestSync(String accountName) {
        if (accountName != null && !"".equals(accountName)) {
            Account account = SyncPrefs.getAccount(AccountManager.get(this), accountName);
            // Don't start a new sync if one is already going
            if (!ContentResolver.isSyncActive(account, NotePad.AUTHORITY)) {
                Bundle options = new Bundle();
                // This will force a sync regardless of what the setting is
                // in accounts manager. Only use it here where the user has
                // manually desired a sync to happen NOW.
                options.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
                ContentResolver.requestSync(account, NotePad.AUTHORITY, options);
            }
        }
    }

    private void showPrefs() {
        // launch a new activity to display the dialog
        Intent intent = new Intent();
        intent.setClass(this, PrefsActivity.class);
        startActivity(intent);
    }

    /**
     * Calls deleteNotes wrapped in ArrayList
     * 
     * @param id
     */
    public static void deleteNote(Context context, long id) {
        Log.d(TAG, "deleteNote: " + id);
        // Only do this for valid id
        if (id > -1) {
            ArrayList<Long> idList = new ArrayList<Long>();
            idList.add(id);
            deleteNotes(context, idList);
        }
    }

    /**
     * Delete all notes given from database Only marks them as deleted if sync
     * is enabled
     * 
     * @param ids
     */
    public static void deleteNotes(Context context, Iterable<Long> ids) {
        ContentResolver resolver = context.getContentResolver();
        boolean shouldMark = shouldMarkAsDeleted(context);
        for (long id : ids) {
            Log.d(TAG, "deleteNotes: " + id);
            if (shouldMark) {
                ContentValues values = new ContentValues();
                values.put(NotePad.Notes.COLUMN_NAME_DELETED, "1");
                resolver.update(NotesEditorFragment.getUriFrom(id), values, null, null);
            } else {
                resolver.delete(NotesEditorFragment.getUriFrom(id), null, null);
            }
            UpdateNotifier.notifyChangeNote(context, NotesEditorFragment.getUriFrom(id));
        }
    }

    /**
     * Inserts a new note in the designated list
     * 
     * @param resolver
     * @param listId
     * @return
     */
    public static Uri createNote(Context context, long listId, String noteText) {
        if (listId > -1) {
            ContentValues values = new ContentValues();
            // Must always include list
            values.put(NotePad.Notes.COLUMN_NAME_LIST, listId);
            values.put(NotePad.Notes.COLUMN_NAME_NOTE, noteText);
            try {
                ContentResolver resolver = context.getContentResolver();
                Uri uri = resolver.insert(NotePad.Notes.CONTENT_URI, values);

                UpdateNotifier.notifyChangeNote(context, uri);
                return uri;
            } catch (SQLException e) {
                return null;
            }
        } else {
            return null;
        }
    }

    public void onMultiDelete(Collection<Long> ids, long curId) {
        if (ids.contains(curId)) {
            NotesEditorFragment editor = (NotesEditorFragment) getFragmentManager()
                    .findFragmentById(R.id.rightFragment);
            if (editor != null) {
                editor.clearNoSave();
            }
        }
        deleteNotes(this, ids);
    }

    @Override
    public NotesListFragment getLeftFragment() {
        NotesListFragment retval = null;
        if (mSectionsPagerAdapter != null) {
            retval = (NotesListFragment) mSectionsPagerAdapter.getCurrentPrimaryItem();
        }
        return retval;
    }

    public void onDeleteAction() {
        // both list and editor should be notified
        NotesListFragment list = (NotesListFragment) getLeftFragment();
        NotesEditorFragment editor = (NotesEditorFragment) getRightFragment();
        Log.d(TAG, "onDeleteAction, list: " + list + ", editor: " + editor);
        // tell list to do what it should
        // if (list != null)
        // list.onDelete();

        if (editor != null) {
            deleteNote(this, editor.getCurrentNoteId());
            editor.clearNoSave();
        }
        if (list == null) {
            // this is an editor view displaying inactive data. kill it
            finish();
        }

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        getLoaderManager().destroyLoader(0);
    }

    @Override
    public boolean onNavigationItemSelected(int itemPosition, long itemId) {
        // Change the active list
        Log.d(TAG, "onNavigationItemSelected: " + itemId);

        Log.d(TAG, "show list pos: " + itemPosition);
        // Display list
        if (itemId != currentListId) {
            Log.d(TAG, "set current item");
            mViewPager.setCurrentItem(itemPosition);
            currentListId = itemId;
        }
        return true;
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        Log.d(TAG, "onCreateLoader: " + id);

        // This is called when a new Loader needs to be created. This
        // sample only has one Loader, so we don't care about the ID.
        Uri baseUri = NotePad.Lists.CONTENT_VISIBLE_URI;
        // Now create and return a CursorLoader that will take care of
        // creating a Cursor for the data being displayed.

        return new CursorLoader(this, baseUri, new String[] { NotePad.Lists._ID, NotePad.Lists.COLUMN_NAME_TITLE,
                NotePad.Lists.COLUMN_NAME_DELETED }, null, null, NotePad.Lists.SORT_ORDER // Use the default sort order.
        );
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        Log.d(TAG, "onLoadFinished");
        mSpinnerAdapter.swapCursor(data);
        mSectionAdapter.swapCursor(data);
        int position = -1;
        if (listIdToSelect > -1) {
            position = getPosOfId(listIdToSelect);
        }

        if (position < 0 && currentListId < 0) {
            position = 0;
            currentListId = mSectionAdapter.getItemId(0);
        }

        if (position > -1) {
            mViewPager.setCurrentItem(position);
        }
        listIdToSelect = -1;

        beforeBoot = false; // Need to do it here

        if (noteIntentToSelect != null) {
            NotesListFragment list = getLeftFragment();

            if (list != null) {
                list.handleNoteIntent(noteIntentToSelect);
            }

            noteIntentToSelect = null;
        }
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        Log.d(TAG, "onLoaderReset");
        mSpinnerAdapter.swapCursor(null);
        mSectionAdapter.swapCursor(null);
    }

    @Override
    public void onItemSelected(long id) {
        Log.d(TAG, "onItemSelected: " + id);
        // Open a note
        if (id > -1) {
            if (getCurrentContent().equals(DualLayoutActivity.CONTENTVIEW.DUAL)) {
                Bundle arguments = new Bundle();
                arguments.putLong(NotesEditorFragment.KEYID, id);
                NotesEditorFragment fragment = new NotesEditorFragment();
                fragment.setArguments(arguments);
                getFragmentManager().beginTransaction().replace(R.id.rightFragment, fragment)
                        .commitAllowingStateLoss();
            } else {
                Intent intent = new Intent();
                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                intent.setClass(this, RightActivity.class)
                        .setData(Uri.withAppendedPath(NotePad.Notes.CONTENT_VISIBLE_ID_URI_BASE, Long.toString(id)))
                        .setAction(Intent.ACTION_EDIT);

                startActivity(intent);
            }
        }
    }
}