1afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project/*
2afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *
4afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * you may not use this file except in compliance with the License.
6afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * You may obtain a copy of the License at
7afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *
8afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *
10afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * See the License for the specific language governing permissions and
14afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * limitations under the License.
15afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */
16afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
17afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectpackage com.android.settings.quicklaunch;
18afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
19263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglioimport android.app.Activity;
20afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.app.AlertDialog;
21afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.app.Dialog;
22afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.content.DialogInterface;
23afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.content.Intent;
24ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischerimport android.content.pm.PackageManager;
25ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischerimport android.content.pm.ResolveInfo;
26afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.database.ContentObserver;
27afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.database.Cursor;
28afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.os.Bundle;
29afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.os.Handler;
30afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.preference.Preference;
31afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.preference.PreferenceGroup;
32afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.preference.PreferenceScreen;
33afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.provider.Settings.Bookmarks;
34afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.util.Log;
35afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.util.SparseArray;
36afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.util.SparseBooleanArray;
37afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.view.KeyCharacterMap;
38afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.view.KeyEvent;
39afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.view.View;
40afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.widget.AdapterView;
41afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
42afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport com.android.settings.R;
43263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglioimport com.android.settings.SettingsPreferenceFragment;
44afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
45ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischerimport java.net.URISyntaxException;
46ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischer
47afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project/**
48afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Settings activity for quick launch.
49afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * <p>
50afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Shows a list of possible shortcuts, the current application each is bound to,
51afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * and allows choosing a new bookmark for a shortcut.
52afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */
53263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Megliopublic class QuickLaunchSettings extends SettingsPreferenceFragment implements
54afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        AdapterView.OnItemLongClickListener, DialogInterface.OnClickListener {
55afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
56afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final String TAG = "QuickLaunchSettings";
57afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
58afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final String KEY_SHORTCUT_CATEGORY = "shortcut_category";
59afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
60afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final int DIALOG_CLEAR_SHORTCUT = 0;
61afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
62afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final int REQUEST_PICK_BOOKMARK = 1;
63afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
64afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final int COLUMN_SHORTCUT = 0;
65afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final int COLUMN_TITLE = 1;
66afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final int COLUMN_INTENT = 2;
67afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final String[] sProjection = new String[] {
68afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            Bookmarks.SHORTCUT, Bookmarks.TITLE, Bookmarks.INTENT
69afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    };
70afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final String sShortcutSelection = Bookmarks.SHORTCUT + "=?";
71afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
72afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private Handler mUiHandler = new Handler();
73afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
74afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final String DEFAULT_BOOKMARK_FOLDER = "@quicklaunch";
75afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /** Cursor for Bookmarks provider. */
76afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private Cursor mBookmarksCursor;
77afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /** Listens for changes to Bookmarks provider. */
78afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private BookmarksObserver mBookmarksObserver;
79afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /** Used to keep track of which shortcuts have bookmarks. */
80afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private SparseBooleanArray mBookmarkedShortcuts;
81afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
82afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /** Preference category to hold the shortcut preferences. */
83afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private PreferenceGroup mShortcutGroup;
84afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /** Mapping of a shortcut to its preference. */
85afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private SparseArray<ShortcutPreference> mShortcutToPreference;
86afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
87afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /** The bookmark title of the shortcut that is being cleared. */
88afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private CharSequence mClearDialogBookmarkTitle;
89afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final String CLEAR_DIALOG_BOOKMARK_TITLE = "CLEAR_DIALOG_BOOKMARK_TITLE";
90afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /** The shortcut that is being cleared. */
91afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private char mClearDialogShortcut;
92afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final String CLEAR_DIALOG_SHORTCUT = "CLEAR_DIALOG_SHORTCUT";
93afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
94afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
95263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio    public void onCreate(Bundle savedInstanceState) {
96afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        super.onCreate(savedInstanceState);
97afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
98afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        addPreferencesFromResource(R.xml.quick_launch_settings);
99afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
100afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mShortcutGroup = (PreferenceGroup) findPreference(KEY_SHORTCUT_CATEGORY);
101afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mShortcutToPreference = new SparseArray<ShortcutPreference>();
102afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mBookmarksObserver = new BookmarksObserver(mUiHandler);
103afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        initShortcutPreferences();
104263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio        mBookmarksCursor = getActivity().getContentResolver().query(Bookmarks.CONTENT_URI,
105263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio                sProjection, null, null, null);
106afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
107afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
108afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
109263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio    public void onResume() {
110afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        super.onResume();
111263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio        mBookmarksCursor = getActivity().getContentResolver().query(Bookmarks.CONTENT_URI,
112263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio                sProjection, null, null, null);
113afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        getContentResolver().registerContentObserver(Bookmarks.CONTENT_URI, true,
114afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                mBookmarksObserver);
115afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        refreshShortcuts();
116afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
117afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
118afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
119263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio    public void onPause() {
120afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        super.onPause();
121afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        getContentResolver().unregisterContentObserver(mBookmarksObserver);
122afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
123afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
124afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
125263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio    public void onStop() {
126e3ff4d8e92a19473c622c1d46b30c63bf2d001d0Fabrice Di Meglio        super.onStop();
127263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio        mBookmarksCursor.close();
128263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio    }
129263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio
130263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio    @Override
131263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio    public void onActivityCreated(Bundle state) {
132263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio        super.onActivityCreated(state);
133e3ff4d8e92a19473c622c1d46b30c63bf2d001d0Fabrice Di Meglio
134e3ff4d8e92a19473c622c1d46b30c63bf2d001d0Fabrice Di Meglio        getListView().setOnItemLongClickListener(this);
135e3ff4d8e92a19473c622c1d46b30c63bf2d001d0Fabrice Di Meglio
136e3ff4d8e92a19473c622c1d46b30c63bf2d001d0Fabrice Di Meglio        if (state != null) {
137e3ff4d8e92a19473c622c1d46b30c63bf2d001d0Fabrice Di Meglio            // Restore the clear dialog's info
138e3ff4d8e92a19473c622c1d46b30c63bf2d001d0Fabrice Di Meglio            mClearDialogBookmarkTitle = state.getString(CLEAR_DIALOG_BOOKMARK_TITLE);
139e3ff4d8e92a19473c622c1d46b30c63bf2d001d0Fabrice Di Meglio            mClearDialogShortcut = (char) state.getInt(CLEAR_DIALOG_SHORTCUT, 0);
140e3ff4d8e92a19473c622c1d46b30c63bf2d001d0Fabrice Di Meglio        }
141afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
142afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
143afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
144263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio    public void onSaveInstanceState(Bundle outState) {
145afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        super.onSaveInstanceState(outState);
146afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
147afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // Save the clear dialog's info
148afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        outState.putCharSequence(CLEAR_DIALOG_BOOKMARK_TITLE, mClearDialogBookmarkTitle);
149afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        outState.putInt(CLEAR_DIALOG_SHORTCUT, mClearDialogShortcut);
150afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
151afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
152afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
153263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio    public Dialog onCreateDialog(int id) {
154afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        switch (id) {
155afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
156afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            case DIALOG_CLEAR_SHORTCUT: {
157afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                // Create the dialog for clearing a shortcut
158263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio                return new AlertDialog.Builder(getActivity())
159afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                        .setTitle(getString(R.string.quick_launch_clear_dialog_title))
160afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                        .setMessage(getString(R.string.quick_launch_clear_dialog_message,
161afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                                mClearDialogShortcut, mClearDialogBookmarkTitle))
162afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                        .setPositiveButton(R.string.quick_launch_clear_ok_button, this)
163afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                        .setNegativeButton(R.string.quick_launch_clear_cancel_button, this)
164afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                        .create();
165afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            }
166afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
167afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
168afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        return super.onCreateDialog(id);
169afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
170afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
171afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private void showClearDialog(ShortcutPreference pref) {
172afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
173afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (!pref.hasBookmark()) return;
174afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
175afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mClearDialogBookmarkTitle = pref.getTitle();
176afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mClearDialogShortcut = pref.getShortcut();
177afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        showDialog(DIALOG_CLEAR_SHORTCUT);
178afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
179afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
180afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public void onClick(DialogInterface dialog, int which) {
1810193bf8b3de6debd6f799f6d453b8b8535769da9Christian Mehlmauer        if (mClearDialogShortcut > 0 && which == AlertDialog.BUTTON_POSITIVE) {
182afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            // Clear the shortcut
183afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            clearShortcut(mClearDialogShortcut);
184afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
185afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mClearDialogBookmarkTitle = null;
186afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mClearDialogShortcut = 0;
187afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
188afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
189afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private void clearShortcut(char shortcut) {
190afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        getContentResolver().delete(Bookmarks.CONTENT_URI, sShortcutSelection,
191afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                new String[] { String.valueOf((int) shortcut) });
192afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
193afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
194afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
195afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
196afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (!(preference instanceof ShortcutPreference)) return false;
197afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
198afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // Open the screen to pick a bookmark for this shortcut
199afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        ShortcutPreference pref = (ShortcutPreference) preference;
200263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio        Intent intent = new Intent(getActivity(), BookmarkPicker.class);
201afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        intent.putExtra(BookmarkPicker.EXTRA_SHORTCUT, pref.getShortcut());
202afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        startActivityForResult(intent, REQUEST_PICK_BOOKMARK);
203afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
204afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        return true;
205afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
206afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
20782163dec1806a63084a436bb28683fc668219d02Christian Mehlmauer    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
208afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
209afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // Open the clear shortcut dialog
210afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        Preference pref = (Preference) getPreferenceScreen().getRootAdapter().getItem(position);
211afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (!(pref instanceof ShortcutPreference)) return false;
212afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        showClearDialog((ShortcutPreference) pref);
213afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        return true;
214afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
215afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
216afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
217263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio    public void onActivityResult(int requestCode, int resultCode, Intent data) {
218263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio        if (resultCode != Activity.RESULT_OK) {
219afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            return;
220afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
221afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
222afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (requestCode == REQUEST_PICK_BOOKMARK) {
223afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
224afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            // Returned from the 'pick bookmark for this shortcut' screen
225afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            if (data == null) {
226afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                Log.w(TAG, "Result from bookmark picker does not have an intent.");
227afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                return;
228afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            }
2298762093e0094e09493fa6cbac8e8fbf265f18165Michael Chan
230afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            char shortcut = data.getCharExtra(BookmarkPicker.EXTRA_SHORTCUT, (char) 0);
231afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            updateShortcut(shortcut, data);
232afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
233afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        } else {
234afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            super.onActivityResult(requestCode, resultCode, data);
235afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
236afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
237afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
238afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private void updateShortcut(char shortcut, Intent intent) {
239afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // Update the bookmark for a shortcut
240afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // Pass an empty title so it gets resolved each time this bookmark is
241afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // displayed (since the locale could change after we insert into the provider).
242afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        Bookmarks.add(getContentResolver(), intent, "", DEFAULT_BOOKMARK_FOLDER, shortcut, 0);
243afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
244afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
245afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private ShortcutPreference getOrCreatePreference(char shortcut) {
246afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        ShortcutPreference pref = mShortcutToPreference.get(shortcut);
247afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (pref != null) {
248afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            return pref;
249afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        } else {
250afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            Log.w(TAG, "Unknown shortcut '" + shortcut + "', creating preference anyway");
251afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            return createPreference(shortcut);
252afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
253afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
254afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
255afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private ShortcutPreference createPreference(char shortcut) {
256263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio        ShortcutPreference pref = new ShortcutPreference(getActivity(), shortcut);
257afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mShortcutGroup.addPreference(pref);
258afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mShortcutToPreference.put(shortcut, pref);
259afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        return pref;
260afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
261afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
262afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private void initShortcutPreferences() {
263afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
264afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        /** Whether the shortcut has been seen already.  The array index is the shortcut. */
265afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        SparseBooleanArray shortcutSeen = new SparseBooleanArray();
266819dff1c18d3e83a277a8e461ad3397e8b3ded52Jeff Brown        KeyCharacterMap keyMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
267afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
268afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // Go through all the key codes and create a preference for the appropriate keys
269afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        for (int keyCode = KeyEvent.getMaxKeyCode() - 1; keyCode >= 0; keyCode--) {
270afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            // Get the label for the primary char on the key that produces this key code
271afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            char shortcut = (char) Character.toLowerCase(keyMap.getDisplayLabel(keyCode));
272afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            if (shortcut == 0 || shortcutSeen.get(shortcut, false)) continue;
273afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            // TODO: need a to tell if the current keyboard can produce this key code, for now
274afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            // only allow the letter or digits
275afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            if (!Character.isLetterOrDigit(shortcut)) continue;
276afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            shortcutSeen.put(shortcut, true);
277afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
278afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            createPreference(shortcut);
279afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
280afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
281afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
282afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private synchronized void refreshShortcuts() {
283afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        Cursor c = mBookmarksCursor;
284afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (c == null) {
285afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            // Haven't finished querying yet
286afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            return;
287afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
288afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
289afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (!c.requery()) {
290afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            Log.e(TAG, "Could not requery cursor when refreshing shortcuts.");
291afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            return;
292afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
293afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
294afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        /**
295afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project         * We use the previous bookmarked shortcuts array to filter out those
296afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project         * shortcuts that had bookmarks before this method call, and don't after
297afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project         * (so we can set the preferences to be without bookmarks).
298afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project         */
299afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        SparseBooleanArray noLongerBookmarkedShortcuts = mBookmarkedShortcuts;
300afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        SparseBooleanArray newBookmarkedShortcuts = new SparseBooleanArray();
301afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        while (c.moveToNext()) {
302afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            char shortcut = Character.toLowerCase((char) c.getInt(COLUMN_SHORTCUT));
303afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            if (shortcut == 0) continue;
304afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
305afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            ShortcutPreference pref = getOrCreatePreference(shortcut);
306263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio            CharSequence title = Bookmarks.getTitle(getActivity(), c);
307ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischer
308ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischer            /*
309ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischer             * The title retrieved from Bookmarks.getTitle() will be in
310ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischer             * the original boot locale, not the current locale.
311ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischer             * Try to look up a localized title from the PackageManager.
312ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischer             */
313ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischer            int intentColumn = c.getColumnIndex(Bookmarks.INTENT);
314ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischer            String intentUri = c.getString(intentColumn);
315ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischer            PackageManager packageManager = getPackageManager();
316ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischer            try {
31782163dec1806a63084a436bb28683fc668219d02Christian Mehlmauer                Intent intent = Intent.parseUri(intentUri, 0);
318ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischer                ResolveInfo info = packageManager.resolveActivity(intent, 0);
319ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischer                if (info != null) {
320ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischer                    title = info.loadLabel(packageManager);
321ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischer                }
322ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischer            } catch (URISyntaxException e) {
323ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischer                // Just use the non-localized title, then.
324ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischer            }
325ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischer
326ec598cb91c02c035d19ccd8a9f17e2bf8da9da5aEric Fischer            pref.setTitle(title);
327afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            pref.setSummary(getString(R.string.quick_launch_shortcut,
328afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    String.valueOf(shortcut)));
329afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            pref.setHasBookmark(true);
330afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
331afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            newBookmarkedShortcuts.put(shortcut, true);
332afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            if (noLongerBookmarkedShortcuts != null) {
333afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                // After this loop, the shortcuts with value true in this array
334afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                // will no longer have bookmarks
335afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                noLongerBookmarkedShortcuts.put(shortcut, false);
336afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            }
337afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
338afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
339afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (noLongerBookmarkedShortcuts != null) {
340afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            for (int i = noLongerBookmarkedShortcuts.size() - 1; i >= 0; i--) {
341afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                if (noLongerBookmarkedShortcuts.valueAt(i)) {
342afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    // True, so there is no longer a bookmark for this shortcut
343afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    char shortcut = (char) noLongerBookmarkedShortcuts.keyAt(i);
344afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    ShortcutPreference pref = mShortcutToPreference.get(shortcut);
345afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    if (pref != null) {
346afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                        pref.setHasBookmark(false);
347afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    }
348afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                }
349afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            }
350afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
351afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
352afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mBookmarkedShortcuts = newBookmarkedShortcuts;
353afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
354afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        c.deactivate();
355afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
356afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
357afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private class BookmarksObserver extends ContentObserver {
358afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
359afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        public BookmarksObserver(Handler handler) {
360afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            super(handler);
361afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
362afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
363afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        @Override
364afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        public void onChange(boolean selfChange) {
365afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            super.onChange(selfChange);
366afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
367afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            refreshShortcuts();
368afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
369afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
370afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project}
371