1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.inputmethod.latin.userdictionary;
18
19import android.app.Activity;
20import android.content.Context;
21import android.content.Intent;
22import android.database.Cursor;
23import android.os.Bundle;
24import android.preference.Preference;
25import android.preference.PreferenceFragment;
26import android.preference.PreferenceGroup;
27import android.provider.UserDictionary;
28import android.text.TextUtils;
29import android.view.inputmethod.InputMethodInfo;
30import android.view.inputmethod.InputMethodManager;
31import android.view.inputmethod.InputMethodSubtype;
32
33import com.android.inputmethod.latin.R;
34import com.android.inputmethod.latin.common.LocaleUtils;
35
36import java.util.List;
37import java.util.Locale;
38import java.util.TreeSet;
39
40import javax.annotation.Nullable;
41
42// Caveat: This class is basically taken from
43// packages/apps/Settings/src/com/android/settings/inputmethod/UserDictionaryList.java
44// in order to deal with some devices that have issues with the user dictionary handling
45
46public class UserDictionaryList extends PreferenceFragment {
47
48    public static final String USER_DICTIONARY_SETTINGS_INTENT_ACTION =
49            "android.settings.USER_DICTIONARY_SETTINGS";
50
51    @Override
52    public void onCreate(final Bundle icicle) {
53        super.onCreate(icicle);
54        setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getActivity()));
55    }
56
57    public static TreeSet<String> getUserDictionaryLocalesSet(final Activity activity) {
58        final Cursor cursor = activity.getContentResolver().query(UserDictionary.Words.CONTENT_URI,
59                new String[] { UserDictionary.Words.LOCALE },
60                null, null, null);
61        final TreeSet<String> localeSet = new TreeSet<>();
62        if (null == cursor) {
63            // The user dictionary service is not present or disabled. Return null.
64            return null;
65        }
66        try {
67            if (cursor.moveToFirst()) {
68                final int columnIndex = cursor.getColumnIndex(UserDictionary.Words.LOCALE);
69                do {
70                    final String locale = cursor.getString(columnIndex);
71                    localeSet.add(null != locale ? locale : "");
72                } while (cursor.moveToNext());
73            }
74        } finally {
75            cursor.close();
76        }
77        if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) {
78            // For ICS, we need to show "For all languages" in case that the keyboard locale
79            // is different from the system locale
80            localeSet.add("");
81        }
82
83        final InputMethodManager imm =
84                (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE);
85        final List<InputMethodInfo> imis = imm.getEnabledInputMethodList();
86        for (final InputMethodInfo imi : imis) {
87            final List<InputMethodSubtype> subtypes =
88                    imm.getEnabledInputMethodSubtypeList(
89                            imi, true /* allowsImplicitlySelectedSubtypes */);
90            for (InputMethodSubtype subtype : subtypes) {
91                final String locale = subtype.getLocale();
92                if (!TextUtils.isEmpty(locale)) {
93                    localeSet.add(locale);
94                }
95            }
96        }
97
98        // We come here after we have collected locales from existing user dictionary entries and
99        // enabled subtypes. If we already have the locale-without-country version of the system
100        // locale, we don't add the system locale to avoid confusion even though it's technically
101        // correct to add it.
102        if (!localeSet.contains(Locale.getDefault().getLanguage().toString())) {
103            localeSet.add(Locale.getDefault().toString());
104        }
105
106        return localeSet;
107    }
108
109    /**
110     * Creates the entries that allow the user to go into the user dictionary for each locale.
111     * @param userDictGroup The group to put the settings in.
112     */
113    protected void createUserDictSettings(final PreferenceGroup userDictGroup) {
114        final Activity activity = getActivity();
115        userDictGroup.removeAll();
116        final TreeSet<String> localeSet =
117                UserDictionaryList.getUserDictionaryLocalesSet(activity);
118
119        if (localeSet.size() > 1) {
120            // Have an "All languages" entry in the languages list if there are two or more active
121            // languages
122            localeSet.add("");
123        }
124
125        if (localeSet.isEmpty()) {
126            userDictGroup.addPreference(createUserDictionaryPreference(null));
127        } else {
128            for (String locale : localeSet) {
129                userDictGroup.addPreference(createUserDictionaryPreference(locale));
130            }
131        }
132    }
133
134    /**
135     * Create a single User Dictionary Preference object, with its parameters set.
136     * @param localeString The locale for which this user dictionary is for.
137     * @return The corresponding preference.
138     */
139    protected Preference createUserDictionaryPreference(@Nullable final String localeString) {
140        final Preference newPref = new Preference(getActivity());
141        final Intent intent = new Intent(USER_DICTIONARY_SETTINGS_INTENT_ACTION);
142        if (null == localeString) {
143            newPref.setTitle(Locale.getDefault().getDisplayName());
144        } else {
145            if (localeString.isEmpty()) {
146                newPref.setTitle(getString(R.string.user_dict_settings_all_languages));
147            } else {
148                newPref.setTitle(
149                        LocaleUtils.constructLocaleFromString(localeString).getDisplayName());
150            }
151            intent.putExtra("locale", localeString);
152            newPref.getExtras().putString("locale", localeString);
153        }
154        newPref.setIntent(intent);
155        newPref.setFragment(UserDictionarySettings.class.getName());
156        return newPref;
157    }
158
159    @Override
160    public void onResume() {
161        super.onResume();
162        createUserDictSettings(getPreferenceScreen());
163    }
164}
165
166