diff --git a/README.md b/README.md index e71d6ef0..757fe944 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,6 @@ To support a new language one needs to: - Add translations for arrays.xml and strings.xml in to new files in the appropriate locale folder (e.g. res/values-de/arrays.xml.) AndroidStudio has a cute/nice Translation Editor which might be handy. - Edit the base arrays.xml file to add the new language. (pref_lang_titles, pref_lang_values) - Exclude translatable="false" items from the new locale arrays.xml file. - - Also make sure the new language is added to pref_loaduserdictdesc (base non-locale strings.xml) - Find a suitable dictionary and add it to assets That should be it? I hope. diff --git a/build.gradle b/build.gradle index 7080f8bc..d82327c6 100644 --- a/build.gradle +++ b/build.gradle @@ -11,6 +11,7 @@ apply plugin: 'com.android.application' dependencies { implementation "androidx.core:core:1.6.0" + implementation 'androidx.preference:preference:1.1.1' } repositories { diff --git a/docs/user-manual.md b/docs/user-manual.md index 3fe70f66..a71ec2a3 100644 --- a/docs/user-manual.md +++ b/docs/user-manual.md @@ -41,9 +41,6 @@ Insert symbol or Add word depending on state and context. Add word only availabl ## Configuration Options TODO... -### Key Remapping -See [the original manual](https://github.com/Clam-/TraditionalT9/wiki/Key-remapping). - ## License - The source code, the logo image and the icons are licensed under [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0). - The word lists / dictionaries are licensed under the licenses provided in the respective readme files found in the source code, where applicable. diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml index 2d50f4d4..fd65e91c 100644 --- a/res/values-bg/strings.xml +++ b/res/values-bg/strings.xml @@ -27,7 +27,6 @@ Добавяне на дума Настройки Базата данни е недостъпна. - Базата данни е недостъпна. Зареждане на стандартни настройки. Обновяване на речника… Речникът се обновява, моля изчакайте… @@ -38,35 +37,10 @@ Помощ Зареди заводски речник Зареди собствен речник - Изтрий собствен речник - Резервно копие на речник - Възстанови копие - Query test - Test func Зареждане на речник… Зареждане на вашия речник… Зареди речник - Възстановяване на речник… - Създаване на резервно копие… - Изтриване на речник… Няма речник за %1$s. Не може да се зареди такъв. - Внимание! Вече съществува резервно копие на речника. Моля потвърдете презаписването му - Създаване на резервно копие - Грешка! Няма външна памет, за да се запише резервното копие. - Ако имате думи в речника на телефона, те ще бъдат заменени със същите от резервното копие. Ако не желаете това, моля изберете \"%1$s\" преди възстановяването.. - Възстановяване на резервно копие - Грешка! Няма външна памет, от която да се възстанови резервното копие на речника. - Грешка! Не е открито резервно копие. - Внимание! Всички думи от Вашия речник ще бъдат изтрити. Потвърждавате ли? - Изтрий собствения речник - Зареди keymap.txt - Зарежда повторно файла с разменени клавиши - Упешно зареждане. - Имаше грешки при зареждане (виж logcat.) - Няма файл keymap.txt. - - Работи! - diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 18bb495a..20ff3031 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -27,7 +27,6 @@ Wort hinzufügen Einstellungen Datenbank nicht verfügbar. - Database unavailable. Using default settings. Wörterbuch-Datenbank wird aktualisiert… Aktualisiere Wörterbuch-Datenbank. Das könnte einen Moment dauern. @@ -38,31 +37,10 @@ "Hilfe anzeigen Wörterbuch laden Benutzerwörterbuch laden - Wörterbuch löschen - Wörterbuch sichern - Wörterbuch wiederherstellen - Query test - Test func Lade Wörterbuch… Lade Benutzerwörterbuch… IME-Wörterbuch laden - Stelle Wörterbuch wiederher… - Sichere Wörterbuch… - Lösche Wörterbuch… Bitte warten… Wörterbuch für %1$s nicht gefunden. Wird nicht geladen. - Warnung: Es existiert bereits ein Datenbank-Backup. Soll es überschrieben werden? - IME-Datenbank sichern - Fehler: Für das Backup ist kein externer Speicher verfügbar. Sicherung kann nicht fortfahren. - Einträge aus der Sicherungsdatenbank werden existierende Datenbankeinträge überschreiben. Einträge, die nicht in der Sicherung sind, bleiben erhalten. Falls dies nicht gewünscht ist, bitte \"%1$s\" wählen, bevor diese Option gewählt wird. - IME-Datenbank wiederherstellen - Fehler: Für die Wiederherstellung ist kein externer Speicher verfügbar. Wiederherstellung kann nicht fortfahren. - Fehler: Sicherungsdatei nicht gefunden. - Warnung: Dies wird das gesamte Wörterbuch löschen. Fortfahren? - IME-Wörterbuch löschen - Force reload of key overrides - - Hallo Welt! - diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index 016f9a2d..7b452a00 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -27,7 +27,6 @@ Aj. mot Paramètres Base de données indisponible - Base de données indisponible. Options par défaut utilisées. Mise à jour de la base de données du dictionnaire… Mise à jour de la base de données du dictionnaire, cela peut prendre un certain temps. @@ -38,31 +37,10 @@ "Afficher l\'aide Charger le dictionnaire Charger le dictionnaire utilisateur - Détruire le dictionnaire - Sauvegarder le dictionnaire - Restaurer le dictionnaire - Tester le clavier - Teste fonc Chargement du dictionnaire… Chargement du dictionnaire utilisateur… Charger le dictionnaire IME - Restauration du dictionnaire… - Sauvegarde du dictionnaire… - Destruction du dictionary… Attendez s\'il vous plaît… Dictionnaire %1$s introuvable. Chargement annulé. - Attention: Une sauvegarde de la base de données est déjà présente. Souhaitez-vous la réécrire ? - Sauvegarde de la base de données IME - Erreur: Pas de stockage externe disponible pour la sauvegarde. Sauvegarde annulée. - Les entrée de la sauvegarde vont réécrire les entrées existantes. Les entrées qui ne sont pas présentes dans la sauvegarde seront conservées. Si ce n\'est pas ce que vous souhaitez, selectionnez \"%1$s\" avant de selectionner cette option. - Restaurer la base de données IME - Erreur: Pas de stockage externe pour la restauration. Restauration annulée - Erreur: Fichier de sauvegarde introuvable. - Attention: Votre ditionnaire sera entièrement effacé. Voulez-vous continuer ? - Détruire le dictionnaire IME - Forcer le rechargement de la surcharge des touches - - Bonjour monde ! - diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml index 23469d9c..de5e5d2f 100644 --- a/res/values-it/strings.xml +++ b/res/values-it/strings.xml @@ -27,7 +27,6 @@ Aggiungi parola Impostazioni Database non disponibile. - Database non disponibile. Utilizzo impostazioni di base. Aggiornamento database dizionario… Aggiornamento database dizionario, potrebbe volerci un po\'. @@ -38,32 +37,11 @@ "Mostra aiuto Carica dizionario Carica dizionario utente - Elimina dizionario - Salvataggio dizionario - Ripristina dizionario - Test ricerca - Test func Caricamento dizionario… Caricamento dizionario utente… Caricamento dizionario IME - Ripristino dizionario… - Salvataggio dizionario… - Eliminazione dizionario… Attendere prego… Dizionario per %1$s non trovato. Impossibile caricare. - Attenzione: salvataggio già esistente. Sovrascrivere ? - Salvataggio database IME - Errore: Nessuna unità esterna disponibile per il salvataggio. Il salvataggio verrà interrotto. - I dati presenti nel salvataggio sostituiranno i dati esistenti. I dati non presenti nel salvataggio verranno mantenuti. In alternativa utilizzare \"%1$s\" prima di effettuare il ripristino. - Ripristino database IME - Errore: Nessuna unità esterna disponibile per il ripristino. Il ripristino verrà interrotto. - Errore: File di salvataggio non trovato. - Attenzione: L\'intero dizionario sarà cancellato. Continuare ? - Elimina dizionario IME - Ricaricamento KeyMap - - Ciao mondo! - diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index 89116559..68779f0f 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -7,7 +7,6 @@ Слово (%1$s) уже есть в словаре. Слово (%1$s) уже есть в словаре %2$s. Traditional T9 - Hello world! Клавиатура T9 Цифры Добавить слово @@ -15,31 +14,14 @@ Добавить слово? Изменить IME Режим ввода - Ошибка: Внешняя память недоступна. Резервное копирование невозможно невозможно. - Резервное копирование базы данных IME - Предупреждение: Существующая копия базы данных будет перезаписана. Продолжить? - Бэкап словаря Режим ввода по умолчанию Режим ввода по умолчанию Загрузить словарь IME Загрузить словарь - Восстановление словаря… Загрузка словаря Загрузка пользовательского словаря… Загрузить свой словарь Мультиязычная поддержка - Очистить IME словарь - Предупреждение: Будет выполнена очстка словаря. Продолжить? - Очистить словарь - Очистка словаря… Пожалуйста, подождите… - Query test - Ошибка: Внешняя память недоступна. Восстановление невозможно. - Ошибка: Файл встановления не найден. - Восстановить базу данных IME - При восстановлении существующая база данных будет очищена. Если это нежелательно, то сначала выберите \"%1$s\" перед использованием этой опции. - Сохранить словарь - Сохранение словаря… - Test func Hold Icon О программе Следущая страница @@ -56,8 +38,6 @@ Обновление базы данных словаря выполнено успешно. Обновление базы данных словаря недоступно. Ошибка. \n Словарь %1$s не найден. - База данных недоступна. Используем значения по умолчанию. - >Перезагрузить кеймап Добавить слово Traditional T9 настройки diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml index cfca77e2..dc09dd5f 100644 --- a/res/values-uk/strings.xml +++ b/res/values-uk/strings.xml @@ -7,7 +7,6 @@ Слово (%1$s) вже є в словнику. Слово (%1$s) вже є в словнику %2$s. Traditional T9 - Hello world! Клавіатура T9 Цифри Додати слово @@ -15,31 +14,14 @@ Додати слово? Змінити IME Режим введення - Помилка: Зовнішня пам\'ять недоступна. Резервне копіювання неможливе. - Резервне копіювання бази даних IME - Попередження: Існуюча копія бази даних буде перезаписана. Продовжити? - Бекап словника Режим введення за замовчуванням Режим введення за замовчуванням Завантажити словник IME Завантажити словник - Відновлення словника… Завантаження словника Завантаження словника користувача… Завантажити свій словник Багатомовна підтримка - Очистити IME словник - Попередження: Буде виконана очистка словника. Продовжити? - Очистка словника - Очистка словника… Будь-ласка, зачекайте… - Тестовий запит - Помилка: Зовнішня память недоступна. Відновлення неможливе. - Помилка: Файл відновлення не знайдений. - Відновити базу даних IME - При відновленні існуюча база даних буде витерта. Если это нежелательно, то сначала выберите \"%1$s\" перед использованием этой опции. - Зберегти словник - Збереження словника… - Test func Hold Icon Про програму Наступне @@ -56,8 +38,6 @@ Оновлення бази даних словника виконано успішно. Оновлення бізи даних словника недоступне. Помилка. \n Словник %1$s не знайдено. - База даних недоступна. Використовуюься значення за замовчуванням. - Перезавантажити значення клавіш Додати слово Налаштування Traditional T9 diff --git a/res/values/strings.xml b/res/values/strings.xml index ac623f69..64532995 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -29,7 +29,6 @@ Add Word Settings Database unavailable. - Database unavailable. Using default settings. Updating dictionary database… Updating dictionary database, this might take a while. @@ -41,35 +40,10 @@ Load dictionary Load user dictionary SDcard/traditionalt9/user.lang.dict (lang: en/ru/de/fr) - Nuke dictionary - Backup dictionary - Restore dictionary - Query test - Test func Loading dictionary… Loading user dictionary… Load IME dictionary - Restoring dictionary… - Backing up dictionary… - Nuking dictionary… Please wait… Dictionary for %1$s not found. Not loading. - Warning: An existing database backup exists. Do you wish to overwrite? - Backup IME database - Error: No external storage available for backup. Backup will not continue. - Backup database entries will overwrite existing database entries. Entries not in the backup will be retained. If that is not desired behaviour select \"%1$s\" before selecting this option. - Restore IME database - Error: No external storage available for restoring. Restore will not continue. - Error: Backup file not found. - Warning: This will delete your entire dictionary. Do you wish to continue? - Nuke IME dictionary - Reload KeyMap - Force reload of key mapping overrides - Reload complete. - Reload complete with errors (check logcat.) - No keymap.txt file found. - - Hello world! - diff --git a/res/xml/prefs.xml b/res/xml/prefs.xml index 4d573da4..e3eb1e51 100644 --- a/res/xml/prefs.xml +++ b/res/xml/prefs.xml @@ -15,9 +15,6 @@ entryValues="@array/pref_lang_values" title="@string/pref_lang_title" /> - - - - - + + diff --git a/src/io/github/sspanak/tt9/AddWordAct.java b/src/io/github/sspanak/tt9/AddWordAct.java index c86f7ec2..ae182052 100644 --- a/src/io/github/sspanak/tt9/AddWordAct.java +++ b/src/io/github/sspanak/tt9/AddWordAct.java @@ -10,7 +10,9 @@ import android.view.Menu; import android.view.View; import android.widget.EditText; -import io.github.sspanak.tt9.T9DB.DBSettings.SETTING; +import io.github.sspanak.tt9.db.DBException; +import io.github.sspanak.tt9.db.T9DB; +import io.github.sspanak.tt9.preferences.T9Preferences; public class AddWordAct extends Activity { @@ -45,9 +47,8 @@ public class AddWordAct extends Activity { } public void doAddWord(String text) { - T9DB db = T9DB.getInstance(this); try { - db.addWord(text, LangHelper.LANGUAGE.get(lang)); + T9DB.getInstance(this).addWord(text, LangHelper.LANGUAGE.get(lang)); } catch (DBException e) { AlertDialog.Builder builder = new AlertDialog.Builder(this); String msg = e.getMessage(); @@ -62,7 +63,7 @@ public class AddWordAct extends Activity { AlertDialog dialog = builder.create(); dialog.show(); } - db.storeSettingString(SETTING.LAST_WORD, text); + T9Preferences.getInstance(this).setLastWord(text); } diff --git a/src/io/github/sspanak/tt9/CharMap.java b/src/io/github/sspanak/tt9/CharMap.java index 586bcb5e..1a015d99 100644 --- a/src/io/github/sspanak/tt9/CharMap.java +++ b/src/io/github/sspanak/tt9/CharMap.java @@ -163,7 +163,7 @@ public class CharMap { protected static final int[] BGT9CAPSTART = { 0, 0, 4, 4, 4, 4, 4, 4, 3, 3, 0, 0, 0 }; protected static final int[][] T9CAPSTART = {ENT9CAPSTART, RUT9CAPSTART, DET9CAPSTART, FRT9CAPSTART, ITT9CAPSTART, UKT9CAPSTART, BGT9CAPSTART}; - protected static String getStringSequence(String word, LANGUAGE lang) { + public static String getStringSequence(String word, LANGUAGE lang) { StringBuilder seq = new StringBuilder(); String tword = word.toLowerCase(LangHelper.LOCALES[lang.index]); for (int i = 0; i < word.length(); i++) { diff --git a/src/io/github/sspanak/tt9/KeyMap.java b/src/io/github/sspanak/tt9/KeyMap.java deleted file mode 100644 index 35efcac2..00000000 --- a/src/io/github/sspanak/tt9/KeyMap.java +++ /dev/null @@ -1,60 +0,0 @@ -package io.github.sspanak.tt9; - -import android.os.Environment; -import android.util.Log; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -public class KeyMap { - public static final String keymapfname = "keymap.txt"; - public static Map keyMapping = new HashMap(); - - static { - setKeys(); - } - - public static int setKeys() { - int msg = 0; - keyMapping = new HashMap(); - // check storage - if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(Environment.getExternalStorageState()) - || Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { - // check for file - if ((new File(new File(Environment.getExternalStorageDirectory(), TraditionalT9Settings.sddir), - keymapfname)).exists()) { - BufferedReader br = null; - Log.d("T9.KeyMap", "Attemping to load keys"); - try { - br = new BufferedReader(new FileReader(new File( - new File(Environment.getExternalStorageDirectory(), TraditionalT9Settings.sddir), keymapfname))); - String line; - try { - while ((line = br.readLine()) != null) { - String[] ws = line.split(" "); - if (ws.length != 2) {continue;} - else if (line.startsWith("#")) {continue;} - try { - keyMapping.put(Integer.parseInt(ws[0]), Integer.parseInt(ws[1])); - } catch (NumberFormatException _ignore) { - Log.w("T9.KeyMap", "Invalid number found"); - msg = R.string.pref_reloadKeysDoneWE; - } - } - Log.d("T9.KeyMap", "Done."); - } catch (IOException _ignore) { - Log.e("T9.KeyMap", "Error while reading line."); - try { br.close(); } - catch (IOException ignored) {} - } - } catch (FileNotFoundException ignored) { msg = R.string.pref_reloadKeysDone; } - } else { msg = R.string.pref_reloadKeysNoFile; } - } else { msg = R.string.pref_reloadKeysNoFile; } - return msg; - } -} diff --git a/src/io/github/sspanak/tt9/LangHelper.java b/src/io/github/sspanak/tt9/LangHelper.java index c8e67cdb..fc9e3d4b 100644 --- a/src/io/github/sspanak/tt9/LangHelper.java +++ b/src/io/github/sspanak/tt9/LangHelper.java @@ -29,7 +29,7 @@ public class LangHelper { public static LANGUAGE get(int i) { return lookup.get(i);} } - protected static final Locale[] LOCALES = {Locale.ENGLISH, RUSSIAN, Locale.GERMAN, Locale.FRENCH, Locale.ITALIAN, UKRAINIAN, BULGARIAN}; + public static final Locale[] LOCALES = {Locale.ENGLISH, RUSSIAN, Locale.GERMAN, Locale.FRENCH, Locale.ITALIAN, UKRAINIAN, BULGARIAN}; public static final int LANG_DEFAULT = LANGUAGE.EN.id; diff --git a/src/io/github/sspanak/tt9/T9DB.java b/src/io/github/sspanak/tt9/T9DB.java deleted file mode 100644 index 3aebbac4..00000000 --- a/src/io/github/sspanak/tt9/T9DB.java +++ /dev/null @@ -1,561 +0,0 @@ -package io.github.sspanak.tt9; - -import android.content.ContentValues; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.database.Cursor; -import android.database.sqlite.SQLiteConstraintException; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteException; -import android.database.sqlite.SQLiteOpenHelper; -import android.provider.BaseColumns; -import android.text.TextUtils; -import android.util.Log; -import android.widget.Toast; - -import io.github.sspanak.tt9.LangHelper.LANGUAGE; - -import java.util.AbstractList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -public class T9DB { - - private static volatile T9DB instance = null; - protected boolean ready = true; - - protected static final String DATABASE_NAME = "t9dict.db"; - protected static final int DATABASE_VERSION = 4; - protected static final String WORD_TABLE_NAME = "word"; - protected static final String SETTING_TABLE_NAME = "setting"; - protected static final String FREQ_TRIGGER_NAME = "freqtrigger"; - // 50k, 10k - private static final int FREQ_MAX = 50000; - private static final int FREQ_DIV = 10000; - // This seems to be pretty fast on my phone. 10 is pretty slow (Might be because > MAX_RESULTS (8).) - private static final int MINHITS = 4; - - protected static final String COLUMN_ID = BaseColumns._ID; - protected static final String COLUMN_LANG = "lang"; - protected static final String COLUMN_SEQ = "seq"; - protected static final String COLUMN_WORD = "word"; - protected static final String COLUMN_FREQUENCY = "freq"; - - private static final String QUERY1 = "SELECT " + COLUMN_ID + ", " + COLUMN_WORD + " FROM " + WORD_TABLE_NAME + - " WHERE " + COLUMN_LANG + "=? AND " + COLUMN_SEQ + "=?" + - " ORDER BY " + COLUMN_FREQUENCY + " DESC"; - - private static final String UPDATEQ = "UPDATE " + WORD_TABLE_NAME + - " SET " + COLUMN_FREQUENCY + " = " + COLUMN_FREQUENCY + "+1" + - " WHERE " + COLUMN_ID + "="; - - private static final int MAX_RESULTS = 8; - private static final int MAX_MAX_RESULTS = 30; // to make sure we don't exceed candidate view array. - - private static final int CAPS_OFF = 0; - private static final int CAPS_SINGLE = 1; - private static final int CAPS_ALL = 2; - - private DatabaseHelper mOpenHelper; - private SQLiteDatabase db; - - private Context mContext; - - public static class DBSettings { - public enum SETTING { - INPUT_MODE("pref_inputmode", 0, 0), - LANG_SUPPORT("pref_lang_support", 1, 1), - MODE_NOTIFY("pref_mode_notify", 0, 2), // no longer in use; delete in #7 - LAST_LANG("set_last_lang", 1, 5), - LAST_WORD("set_last_word", null, 6), - SPACE_ZERO("pref_spaceOnZero", 0, 4), // no longer in use; delete in #7 - KEY_REMAP("pref_keyMap", 0, 3); // no longer in use; delete in #7 - - public final String id; - public final Integer defvalue; - public final int sqOrder; // used for building SettingsUI - - // lookup map - private static final Map lookup = new HashMap(); - private static final SETTING[] settings = SETTING.values(); - static { for (SETTING l : settings) lookup.put(l.id, l); } - - private SETTING(String id, Integer defval, int sqOrder) { - this.id = id; this.defvalue = defval; this.sqOrder = sqOrder; - } - - public static SETTING get(String i) { return lookup.get(i);} - public static StringBuilder join(SETTING[] settings, StringBuilder sb) { - for (int x=0; x stringList, List intList, - int capsMode, LANGUAGE lang) { - stringList.clear(); - intList.clear(); - // String[] sa = packInts(stringToInts(is), true); - int islen = is.length(); - - if (!checkReady()) { - Log.e("T9DB.updateWords", "not ready"); - Toast.makeText(mContext, R.string.database_notready, Toast.LENGTH_SHORT).show(); - return; - } - Cursor cur = db.rawQuery(QUERY1, new String[] { String.valueOf(lang.id), is }); - - int hits = 0; - for (cur.moveToFirst(); !cur.isAfterLast(); cur.moveToNext()) { - intList.add(cur.getInt(0)); - stringList.add(cur.getString(1)); - if (hits >= MAX_MAX_RESULTS) { break; } // to stop index error in candidate view - hits++; - } - cur.close(); - - if ((hits < MINHITS) && (islen >= 2)) { - char c = is.charAt(islen - 1); - c++; - String q = "SELECT " + COLUMN_ID + ", " + COLUMN_WORD + - " FROM " + WORD_TABLE_NAME + - " WHERE " + COLUMN_LANG + "=? AND " + COLUMN_SEQ + " >= '" + is + "1" + - "' AND " + COLUMN_SEQ + " < '" + is.substring(0, islen - 1) + c + "'" + - " ORDER BY " + COLUMN_FREQUENCY + " DESC, " + COLUMN_SEQ + " ASC" + - " LIMIT " + (MAX_RESULTS - hits); - cur = db.rawQuery(q, new String[] { String.valueOf(lang.id) }); - - for (cur.moveToFirst(); !cur.isAfterLast(); cur.moveToNext()) { - intList.add(cur.getInt(0)); - stringList.add(cur.getString(1)); - if (hits >= MAX_MAX_RESULTS) { - break; - } - hits++; - } - cur.close(); - } - // Log.d("T9DB.updateWords", "pre: " + stringList); - if (capsMode == CAPS_OFF) { - return; - } - // Log.d("T9DB.updateWords", "filtering..."); - // filter list - Iterator iter = stringList.iterator(); - String word; - String wordtemp; - int index = 0; - boolean removed = false; - while (iter.hasNext()) { - word = iter.next(); - switch (capsMode) { - case CAPS_ALL: - wordtemp = word.toUpperCase(LangHelper.LOCALES[lang.index]); - if (wordtemp.equals(word)) { - index++; - continue; - } else if (stringList.contains(wordtemp)) { - // remove this entry - iter.remove(); - removed = true; - } else { - stringList.set(index, wordtemp); - } - break; - case CAPS_SINGLE: - if (word.length() > 1) { - wordtemp = word.substring(0, 1).toUpperCase(LangHelper.LOCALES[lang.index]) + word.substring(1); - } else { - wordtemp = word.toUpperCase(LangHelper.LOCALES[lang.index]); - } - if (wordtemp.equals(word)) { - index++; - continue; - } else if (stringList.contains(wordtemp)) { - // remove this entry - iter.remove(); - removed = true; - } else { - stringList.set(index, wordtemp); - } - break; - } - if (removed) { - intList.remove(index); - removed = false; - } else { - index++; - } - } - //Log.d("T9DB.updateWords", "i:" + is + " words:" + Arrays.toString(stringList.toArray())); - } - - private static class DatabaseHelper extends SQLiteOpenHelper { - - Context mContext = null; - - DatabaseHelper(Context context) { - super(context, DATABASE_NAME, null, DATABASE_VERSION); - mContext = context; - } - - // partial code from parent class SQLiteOpenHelper - protected boolean needsUpgrading() { - //quick and dirty check to see if an existing database exists. - if (mContext.databaseList().length > 0) { - SQLiteDatabase db = mContext.openOrCreateDatabase(DATABASE_NAME, 0, null); - int version = db.getVersion(); - db.close(); - return version < DATABASE_VERSION; - } else { - return false; - } - } - @Override - public void onCreate(SQLiteDatabase db) { - db.execSQL("CREATE TABLE IF NOT EXISTS " + WORD_TABLE_NAME + " (" + - COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + - COLUMN_LANG + " INTEGER, " + - COLUMN_SEQ + " TEXT, " + - COLUMN_WORD + " TEXT, " + - COLUMN_FREQUENCY + " INTEGER, " + - "UNIQUE(" + COLUMN_LANG + ", " + COLUMN_WORD + ") )"); - db.execSQL("CREATE INDEX IF NOT EXISTS idx ON " + WORD_TABLE_NAME + "(" - + COLUMN_LANG + ", " + COLUMN_SEQ + " ASC, " + COLUMN_FREQUENCY + " DESC )"); - db.execSQL("CREATE TRIGGER IF NOT EXISTS " + FREQ_TRIGGER_NAME + - " AFTER UPDATE ON " + WORD_TABLE_NAME + - " WHEN NEW." + COLUMN_FREQUENCY + " > " + FREQ_MAX + - " BEGIN" + - " UPDATE " + WORD_TABLE_NAME + " SET " + COLUMN_FREQUENCY + " = " - + COLUMN_FREQUENCY + " / " + FREQ_DIV + - " WHERE " + COLUMN_SEQ + " = NEW." + COLUMN_SEQ + ";" + - " END;"); - - createSettingsTable(db); - - StringBuilder sb = new StringBuilder("INSERT OR IGNORE INTO "); sb.append(SETTING_TABLE_NAME); - sb.append(" ("); sb.append(COLUMN_ID); sb.append(", "); - sb = DBSettings.SETTING.join(DBSettings.SETTING.settings, sb); - sb.append(") VALUES (1,"); - for (int x=0;x 0 || mComposingI.length() > 0) @@ -477,17 +464,13 @@ public class TraditionalT9 extends InputMethodService implements // ?????????????? } - private KeyEvent TranslateKey(int keyCode, KeyEvent event) { - KeyEvent key = event; - if (KeyMap.keyMapping.containsKey(keyCode)) { - key = new KeyEvent(event.getDownTime(), event.getEventTime(), event.getAction(), - KeyMap.keyMapping.get(keyCode), event.getRepeatCount(), event.getMetaState(), - event.getDeviceId(), 0, event.getFlags()); - } - return key; - } - - private boolean onKeyDown_(int keyCode, KeyEvent event) { + /** + * Use this to monitor key events being delivered to the application. We get + * first crack at them, and can either resume them or let them continue to + * the app. + */ + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { // Log.d("onKeyDown", "Key: " + event + " repeat?: " + // event.getRepeatCount() + " long-time: " + event.isLongPress()); if (mEditing == NON_EDIT) { @@ -516,7 +499,7 @@ public class TraditionalT9 extends InputMethodService implements return super.onKeyDown(keyCode, event); } - } else if (keyCode == KeyEvent.KEYCODE_DEL) {// Special handling of the delete key: if we currently are + } else if (keyCode == prefs.getKeyBackspace()) {// Special handling of the delete key: if we currently are // composing text for the user, we want to modify that instead // of let the application do the delete itself. // if (mComposing.length() > 0) { @@ -530,7 +513,7 @@ public class TraditionalT9 extends InputMethodService implements if (event.getRepeatCount() != 0) { return true; } - if (mKeyMode == MODE_TEXT) { + if (mKeyMode == T9Preferences.MODE_ABC) { t9releasehandler.removeCallbacks(mt9release); } if (keyCode == KeyEvent.KEYCODE_BACK) { @@ -564,20 +547,6 @@ public class TraditionalT9 extends InputMethodService implements commitReset(); return super.onKeyDown(keyCode, event); } - /** - * Use this to monitor key events being delivered to the application. We get - * first crack at them, and can either resume them or let them continue to - * the app. - */ - @Override - public boolean onKeyDown(int inputKeyCode, KeyEvent inputEvent) { - KeyEvent event = TranslateKey(inputKeyCode, inputEvent); - if (event != null) { - return onKeyDown_(event.getKeyCode(), event); - } - - return onKeyDown_(inputKeyCode, inputEvent); - } protected void launchOptions() { Intent awintent = new Intent(this, TraditionalT9Settings.class); @@ -607,7 +576,7 @@ public class TraditionalT9 extends InputMethodService implements } return true; } else if (keyCode == KeyEvent.KEYCODE_STAR) { - if (mKeyMode != MODE_NUM) { + if (mKeyMode != T9Preferences.MODE_123) { if (mLangsAvailable.length > 1) { nextLang(); } else { @@ -620,7 +589,7 @@ public class TraditionalT9 extends InputMethodService implements if (interfacehandler != null) { interfacehandler.setPressed(keyCode, false); } - if (mKeyMode == MODE_LANG) { + if (mKeyMode == T9Preferences.MODE_PREDICTIVE) { if (mWordFound) { showAddWord(); } else { @@ -637,13 +606,13 @@ public class TraditionalT9 extends InputMethodService implements return true; } if (keyCode >= KeyEvent.KEYCODE_0 && keyCode <= KeyEvent.KEYCODE_9) { - if (mKeyMode == MODE_LANG) { + if (mKeyMode == T9Preferences.MODE_PREDICTIVE) { commitTyped(); onText(String.valueOf(keyCode - KeyEvent.KEYCODE_0)); - } else if (mKeyMode == MODE_TEXT) { + } else if (mKeyMode == T9Preferences.MODE_ABC) { commitReset(); onText(String.valueOf(keyCode - KeyEvent.KEYCODE_0)); - } else if (mKeyMode == MODE_NUM) { + } else if (mKeyMode == T9Preferences.MODE_123) { if (keyCode == KeyEvent.KEYCODE_0) { onText("+"); } @@ -651,8 +620,13 @@ public class TraditionalT9 extends InputMethodService implements } return true; } - - private boolean onKeyUp_(int keyCode, KeyEvent event) { + /** + * Use this to monitor key events being delivered to the application. We get + * first crack at them, and can either resume them or let them continue to + * the app. + */ + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { // Log.d("onKeyUp", "Key: " + keyCode + " repeat?: " + // event.getRepeatCount()); if (mEditing == NON_EDIT) { @@ -700,7 +674,7 @@ public class TraditionalT9 extends InputMethodService implements } return false; - } else if (keyCode == KeyEvent.KEYCODE_DEL) { + } else if (keyCode == prefs.getKeyBackspace()) { return true; } else if (keyCode == KeyEvent.KEYCODE_ENTER) { return false; @@ -743,20 +717,6 @@ public class TraditionalT9 extends InputMethodService implements commitReset(); return super.onKeyUp(keyCode, event); } - /** - * Use this to monitor key events being delivered to the application. We get - * first crack at them, and can either resume them or let them continue to - * the app. - */ - @Override - public boolean onKeyUp(int inputKeyCode, KeyEvent inputEvent) { - KeyEvent event = TranslateKey(inputKeyCode, inputEvent); - if (event != null) { - return onKeyUp_(event.getKeyCode(), event); - } - - return onKeyUp_(inputKeyCode, inputEvent); - } /** * Helper function to commit any text being composed in to the editor. @@ -780,7 +740,7 @@ public class TraditionalT9 extends InputMethodService implements */ private void updateShiftKeyState(EditorInfo attr) { // Log.d("updateShift", "CM start: " + mCapsMode); - if (attr != null && mCapsMode != CAPS_ALL) { + if (attr != null && mCapsMode != T9Preferences.CASE_UPPER) { int caps = 0; if (attr.inputType != InputType.TYPE_NULL) { caps = currentInputConnection.getCursorCapsMode(attr.inputType); @@ -788,13 +748,13 @@ public class TraditionalT9 extends InputMethodService implements // mInputView.setShifted(mCapsLock || caps != 0); // Log.d("updateShift", "caps: " + caps); if ((caps & TextUtils.CAP_MODE_CHARACTERS) == TextUtils.CAP_MODE_CHARACTERS) { - mCapsMode = CAPS_ALL; + mCapsMode = T9Preferences.CASE_UPPER; } else if ((caps & TextUtils.CAP_MODE_SENTENCES) == TextUtils.CAP_MODE_SENTENCES) { - mCapsMode = CAPS_SINGLE; + mCapsMode = T9Preferences.CASE_CAPITALIZE; } else if ((caps & TextUtils.CAP_MODE_WORDS) == TextUtils.CAP_MODE_WORDS) { - mCapsMode = CAPS_SINGLE; + mCapsMode = T9Preferences.CASE_CAPITALIZE; } else { - mCapsMode = CAPS_OFF; + mCapsMode = T9Preferences.CASE_LOWER; } updateKeyMode(); } @@ -820,11 +780,11 @@ public class TraditionalT9 extends InputMethodService implements // Log.d("OnKey", "pri: " + keyCode); // Log.d("onKey", "START Cm: " + mCapsMode); // HANDLE SPECIAL KEYS - if (keyCode == KeyEvent.KEYCODE_DEL) { + if (keyCode == prefs.getKeyBackspace()) { handleBackspace(); } else if (keyCode == KeyEvent.KEYCODE_STAR) { // change case - if (mKeyMode == MODE_NUM) { + if (mKeyMode == T9Preferences.MODE_123) { handleCharacter(KeyEvent.KEYCODE_STAR); } else { handleShift(); @@ -878,14 +838,14 @@ public class TraditionalT9 extends InputMethodService implements } if (mComposing.length() > 0) { switch (mKeyMode) { - case MODE_LANG: + case T9Preferences.MODE_PREDICTIVE: commitTyped(); break; - case MODE_TEXT: + case T9Preferences.MODE_ABC: commitTyped(); charReset(); break; - case MODE_NUM: + case T9Preferences.MODE_123: // shouldn't happen break; } @@ -902,7 +862,7 @@ public class TraditionalT9 extends InputMethodService implements updateCandidates(false); } private void updateCandidates(boolean backspace) { - if (mKeyMode == MODE_LANG) { + if (mKeyMode == T9Preferences.MODE_PREDICTIVE) { int len = mComposingI.length(); if (len > 0) { if (mComposingI.charAt(len - 1) == '1') { @@ -964,7 +924,7 @@ public class TraditionalT9 extends InputMethodService implements interfacehandler.showNotFound(false); } } - } else if (mKeyMode == MODE_TEXT) { + } else if (mKeyMode == T9Preferences.MODE_ABC) { if (mComposing.length() > 0) { //Log.d("updateCandidates", "Previous: " + mComposing.toString()); mSuggestionStrings.clear(); @@ -993,7 +953,7 @@ public class TraditionalT9 extends InputMethodService implements private void handleBackspace() { final int length = mComposing.length(); final int length2 = mComposingI.length(); - if (mKeyMode == MODE_TEXT) { + if (mKeyMode == T9Preferences.MODE_ABC) { charReset(); setCandidatesViewShown(false); } @@ -1028,7 +988,7 @@ public class TraditionalT9 extends InputMethodService implements updateCandidates(); } else { mPreviousWord = ""; - keyDownUp(KeyEvent.KEYCODE_DEL); + keyDownUp(prefs.getKeyBackspace()); } updateShiftKeyState(getCurrentInputEditorInfo()); // Log.d("handleBS", "Cm: " + mCapsMode); @@ -1044,7 +1004,7 @@ public class TraditionalT9 extends InputMethodService implements mCapsMode++; } - if (mKeyMode == MODE_LANG && mComposing.length() > 0) { + if (mKeyMode == T9Preferences.MODE_PREDICTIVE && mComposing.length() > 0) { updateCandidates(); currentInputConnection.setComposingText(mComposing, 1); } @@ -1058,7 +1018,7 @@ public class TraditionalT9 extends InputMethodService implements */ private void handleCharacter(int keyCode) { switch (mKeyMode) { - case MODE_LANG: + case T9Preferences.MODE_PREDICTIVE: // it begins if (keyCode == KeyEvent.KEYCODE_POUND || keyCode == KeyEvent.KEYCODE_0) { if (mComposing.length() > 0) { @@ -1074,7 +1034,7 @@ public class TraditionalT9 extends InputMethodService implements } break; - case MODE_TEXT: + case T9Preferences.MODE_ABC: t9releasehandler.removeCallbacks(mt9release); if (keyCode == KeyEvent.KEYCODE_POUND) { keyCode = 10; @@ -1102,7 +1062,7 @@ public class TraditionalT9 extends InputMethodService implements // start at caps if CapMode // Log.d("handleChar", "Cm: " + mCapsMode); - if (mCharIndex == 0 && mCapsMode != CAPS_OFF) { + if (mCharIndex == 0 && mCapsMode != T9Preferences.CASE_LOWER) { mCharIndex = CharMap.T9CAPSTART[mLang.index][keyCode]; } @@ -1120,15 +1080,15 @@ public class TraditionalT9 extends InputMethodService implements t9releasehandler.postDelayed(mt9release, T9DELAY); if (newChar) { // consume single caps - if (mCapsMode == CAPS_SINGLE) { - mCapsMode = CAPS_OFF; + if (mCapsMode == T9Preferences.CASE_CAPITALIZE) { + mCapsMode = T9Preferences.CASE_LOWER; } } updateCandidates(); updateShiftKeyState(getCurrentInputEditorInfo()); break; - case MODE_NUM: + case T9Preferences.MODE_123: if (keyCode == KeyEvent.KEYCODE_POUND) { onText("#"); } else if (keyCode == KeyEvent.KEYCODE_STAR) { @@ -1173,7 +1133,7 @@ public class TraditionalT9 extends InputMethodService implements mIgnoreDPADKeyUp = false; return super.onKeyUp(keyCode, event); } else { - if (mKeyMode != MODE_NUM && mComposing.length() > 0) { + if (mKeyMode != T9Preferences.MODE_123 && mComposing.length() > 0) { if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { mCandidateView.scrollToSuggestion(1); if (mSuggestionStrings.size() > mCandidateView.mSelectedIndex) @@ -1185,9 +1145,9 @@ public class TraditionalT9 extends InputMethodService implements currentInputConnection.setComposingText(mSuggestionStrings.get(mCandidateView.mSelectedIndex), 1); return true; } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) { - if (mKeyMode == MODE_LANG) { + if (mKeyMode == T9Preferences.MODE_PREDICTIVE) { commitTyped(); - } else if (mKeyMode == MODE_TEXT) { + } else if (mKeyMode == T9Preferences.MODE_ABC) { commitReset(); } // getCurrentInputConnection().sendKeyEvent(mDPADkeyEvent); @@ -1219,8 +1179,8 @@ public class TraditionalT9 extends InputMethodService implements private void commitReset() { commitTyped(); charReset(); - if (mCapsMode == CAPS_SINGLE) { - mCapsMode = CAPS_OFF; + if (mCapsMode == T9Preferences.CASE_CAPITALIZE) { + mCapsMode = T9Preferences.CASE_LOWER; } // Log.d("commitReset", "CM pre: " + mCapsMode); updateShiftKeyState(getCurrentInputEditorInfo()); @@ -1260,7 +1220,7 @@ public class TraditionalT9 extends InputMethodService implements private void resetKeyMode() { charReset(); - if (mKeyMode != MODE_NUM) { + if (mKeyMode != T9Preferences.MODE_123) { commitTyped(); } mComposing.setLength(0); @@ -1276,12 +1236,12 @@ public class TraditionalT9 extends InputMethodService implements int icon = 0; switch (mKeyMode) { - case MODE_TEXT: + case T9Preferences.MODE_ABC: interfacehandler.showHold(false); icon = LangHelper.ICONMAP[mLang.index][mKeyMode][mCapsMode]; break; - case MODE_LANG: - if (!db.ready) { + case T9Preferences.MODE_PREDICTIVE: + if (!db.isReady()) { if (!mGaveUpdateWarn) { Toast.makeText(this, getText(R.string.updating_database_unavailable), Toast.LENGTH_LONG).show(); mGaveUpdateWarn = true; @@ -1302,7 +1262,7 @@ public class TraditionalT9 extends InputMethodService implements // + mCapsMode); icon = LangHelper.ICONMAP[mLang.index][mKeyMode][mCapsMode]; break; - case MODE_NUM: + case T9Preferences.MODE_123: interfacehandler.showHold(false); icon = R.drawable.ime_number; break; @@ -1329,14 +1289,14 @@ public class TraditionalT9 extends InputMethodService implements // mSuggestionStrings.get(mCandidateView.mSelectedIndex)); // get and commit selected suggestion ic.commitText(mSuggestionStrings.get(mCandidateView.mSelectedIndex), 1); - if (mKeyMode == MODE_LANG) { + if (mKeyMode == T9Preferences.MODE_PREDICTIVE) { // update freq db.incrementWord(mSuggestionInts.get(mCandidateView.mSelectedIndex)); } } else { // commit suggestion index ic.commitText(mSuggestionStrings.get(index), 1); - if (mKeyMode == MODE_LANG) { + if (mKeyMode == T9Preferences.MODE_PREDICTIVE) { db.incrementWord(mSuggestionInts.get(index)); } } diff --git a/src/io/github/sspanak/tt9/TraditionalT9Settings.java b/src/io/github/sspanak/tt9/TraditionalT9Settings.java index 0ee89bfe..1e42cc64 100644 --- a/src/io/github/sspanak/tt9/TraditionalT9Settings.java +++ b/src/io/github/sspanak/tt9/TraditionalT9Settings.java @@ -7,15 +7,12 @@ import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.content.res.Resources; -import android.database.Cursor; import android.database.DatabaseUtils.InsertHelper; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; -import android.os.Handler; import android.os.SystemClock; import android.text.TextUtils; import android.util.Log; @@ -27,39 +24,32 @@ import android.widget.Toast; import com.stackoverflow.answer.UnicodeBOMInputStream; import io.github.sspanak.tt9.LangHelper.LANGUAGE; -import io.github.sspanak.tt9.T9DB.DBSettings.SETTING; +import io.github.sspanak.tt9.db.T9DB; +import io.github.sspanak.tt9.preferences.T9Preferences; import io.github.sspanak.tt9.settings.CustomInflater; import io.github.sspanak.tt9.settings.Setting; import io.github.sspanak.tt9.settings.SettingAdapter; import java.io.BufferedReader; -import java.io.BufferedWriter; import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; -import java.util.AbstractList; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Properties; -public class TraditionalT9Settings extends ListActivity implements - DialogInterface.OnCancelListener { +public class TraditionalT9Settings extends ListActivity implements DialogInterface.OnCancelListener { AsyncTask task = null; final static String dictname = "%s-utf8.txt"; final static String userdictname = "user.%s.dict"; - final static String backupname = "t9backup.txt"; final static String sddir = "tt9"; final int BACKUP_Q_LIMIT = 1000; @@ -136,13 +126,11 @@ public class TraditionalT9Settings extends ListActivity implements long size; long pos; boolean internal; - boolean restore; String[] dicts; LANGUAGE[] mSupportedLanguages; - LoadDictTask(int msgid, boolean intern, boolean restorebackup, LANGUAGE[] supportedLanguages) { + LoadDictTask(int msgid, boolean intern, LANGUAGE[] supportedLanguages) { internal = intern; - restore = restorebackup; int suplanglen = supportedLanguages.length; dicts = new String[suplanglen]; @@ -160,7 +148,7 @@ public class TraditionalT9Settings extends ListActivity implements pd.setOnCancelListener(TraditionalT9Settings.this); } - private long getDictSizes(boolean internal, boolean restore, String[] dicts) { + private long getDictSizes(boolean internal, String[] dicts) { if (internal) { InputStream input; Properties props = new Properties(); @@ -183,32 +171,22 @@ public class TraditionalT9Settings extends ListActivity implements } } else { File backupfile = new File(Environment.getExternalStorageDirectory(), sddir); - if (restore) { - // using external backup - backupfile = new File(backupfile, backupname); - if (backupfile.exists() && backupfile.isFile()) { - return backupfile.length(); + long total = 0; + File f; + for (String dict : dicts) { + f = new File(backupfile, dict); + if (f.exists() && f.isFile()) { + total = total + f.length(); } else { - return -1; + total = total + 0; } - } else { - long total = 0; - File f; - for (String dict : dicts) { - f = new File(backupfile, dict); - if (f.exists() && f.isFile()) { - total = total + f.length(); - } else { - total = total + 0; - } - } - return total; } + return total; } } @Override protected void onPreExecute() { - size = getDictSizes(internal, restore, dicts); + size = getDictSizes(internal, dicts); pos = 0; if ( size >= 0 ) { pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); @@ -247,64 +225,45 @@ public class TraditionalT9Settings extends ListActivity implements InputStream dictstream = null; try { - if (restore) { - try { - dictstream = new FileInputStream(new File( - new File(Environment.getExternalStorageDirectory(), sddir), backupname)); - reply = processFile(dictstream, reply, db, LANGUAGE.NONE, backupname); - } catch (FileNotFoundException e) { - reply.status = false; - reply.forceMsg("Backup file not found: " + e.getMessage()); - closeStream(dictstream, reply); // this is silly but it - return reply; // stops IDE nagging at me. - } catch (IOException e) { - reply.status = false; - reply.forceMsg("IO Error: " + e.getMessage()); - closeStream(dictstream, reply); // this is silly but it - return reply; // stops IDE nagging at me. + for (int x=0; x { - - ProgressDialog pd; - - DumpDictTask(int msgid) { - pd = new ProgressDialog(TraditionalT9Settings.this); - pd.setMessage(getResources().getString(msgid)); - pd.setOnCancelListener(TraditionalT9Settings.this); - } - - @Override protected void onPreExecute() { - pd.show(); - } - - @Override - protected Reply doInBackground(String... ignore) { - Reply reply = new Reply(); - SQLiteDatabase db; - db = T9DB.getSQLDB(mContext); - if (db == null) { - reply.forceMsg("Database unavailable at this time. (May be updating)"); - reply.status = false; - return reply; - } - long entries; - int current = 0; - int pos = 0; - int last = 0; - File backupfile = new File(new File(Environment.getExternalStorageDirectory(), - sddir), backupname); - - db.setLockingEnabled(false); - - Log.d("doInBackground", "Dumping dict..."); - BufferedWriter bw; - OutputStream dictstream = null; - - try { - dictstream = new FileOutputStream(backupfile); - } catch (FileNotFoundException e) { - reply.status = false; - reply.forceMsg("Backup file error: " + e.getMessage()); - return reply; - } - - try { - bw = new BufferedWriter(new OutputStreamWriter(dictstream, "UTF-8")); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - reply.status = false; - reply.forceMsg("Encoding Error (backupfile): " + e.getMessage()); - closeStream(dictstream, reply); - return reply; - } - long startnow, endnow; - startnow = SystemClock.uptimeMillis(); - - String q = "SELECT count(*) FROM " + T9DB.WORD_TABLE_NAME; - Cursor cur = db.rawQuery(q, null); - cur.moveToFirst(); - entries = cur.getInt(0); - // pd.setMax((int)entries); - cur.close(); - try { - while (pos < entries) { - q = "SELECT " + T9DB.COLUMN_ID + ", " + T9DB.COLUMN_LANG + ", " + - T9DB.COLUMN_WORD + ", " + T9DB.COLUMN_FREQUENCY + - " FROM " + T9DB.WORD_TABLE_NAME + - " WHERE " + T9DB.COLUMN_ID + ">" + current + - " ORDER BY " + T9DB.COLUMN_ID + " LIMIT " + BACKUP_Q_LIMIT; - cur = db.rawQuery(q, null); - for (cur.moveToFirst(); !cur.isAfterLast(); cur.moveToNext()) { - if (isCancelled()) { - reply.status = false; - reply.forceMsg("User cancelled."); - break; - } - current = cur.getInt(0); - pos++; - try { - bw.write(cur.getString(2)); // write word - bw.write(" "); - bw.write(Integer.toString(cur.getInt(3))); // then freq - bw.write(" "); - bw.write(Integer.toString(cur.getInt(1))); // then lang - bw.newLine(); - } catch (Exception e) { - e.printStackTrace(); - reply.status = false; - reply.forceMsg("Error: " + e.getMessage()); - closeStream(dictstream, reply); - } - if ((pos - last) > 80) { - publishProgress((int) ((float) pos / entries * 10000)); - last = pos; - } - } - cur.close(); - } - } finally { - cur.close(); - } - publishProgress(10000); - - endnow = SystemClock.uptimeMillis(); - Log.d("TIMING", "Execution time: " + (endnow - startnow) + " ms"); - Log.d("doInBackground", "entries: " + entries + " last: " + pos); - try { - bw.flush(); - bw.close(); - } catch (IOException e) { - e.printStackTrace(); - } - closeStream(dictstream, reply); - return reply; - } - - @Override - protected void onProgressUpdate(Integer... progress) { - if (pd.isShowing()) { - pd.setProgress(progress[0]); - } - } - - /** - * The system calls this to perform work in the UI thread and delivers - * the result from doInBackground() - */ - @Override - protected void onPostExecute(Reply result) { - finishAndShowError(pd, result, R.string.pref_backup_title); - } - } - - private class NukeDictTask extends AsyncTask { - - ProgressDialog pd; - - NukeDictTask(int msgid) { - pd = new ProgressDialog(TraditionalT9Settings.this); - pd.setMessage(getResources().getString(msgid)); - pd.setCancelable(false); - pd.setProgressStyle(ProgressDialog.STYLE_SPINNER); - - } - - @Override protected void onPreExecute() { - pd.show(); - } - - @Override - protected Reply doInBackground(String... ignore) { - Reply reply = new Reply(); - Log.d("doInBackground", "Nuking dict..."); - long startnow, endnow; - startnow = SystemClock.uptimeMillis(); - T9DB t9db = T9DB.getInstance(mContext); - t9db.nuke(); - - endnow = SystemClock.uptimeMillis(); - Log.d("TIMING", "Execution time: " + (endnow - startnow) + " ms"); - return reply; - } - - @Override - protected void onCancelled() { - // Pointless callback. Thanks android. - } - - /** - * The system calls this to perform work in the UI thread and delivers - * the result from doInBackground() - */ - @Override - protected void onPostExecute(Reply result) { - finishAndShowError(pd, result, R.string.pref_nuke_title); + finishAndShowError(pd, result, R.string.pref_load_title); } } @@ -684,10 +460,14 @@ public class TraditionalT9Settings extends ListActivity implements // http://stackoverflow.com/questions/7645880/listview-with-onitemclicklistener-android // get settings - Object[] settings = T9DB.getInstance(this).getSettings(new SETTING[] - // Order should be based on SETTING.sqOrder - // "MODE_NOTIFY", "SPACE_ZERO" and "KEY_REMAP" are no longer in use; delete in #7 - {SETTING.INPUT_MODE, SETTING.LANG_SUPPORT, SETTING.MODE_NOTIFY, SETTING.KEY_REMAP, SETTING.SPACE_ZERO}); + T9Preferences prefs = new T9Preferences(this); + Object[] settings = { + prefs.getInputMode(), + prefs.getEnabledLanguages(), + null, // MODE_NOTIFY; not used, remove in #29 + false, // KEY_REMAP; not used, remove in #29 + true, // SPACE_ZERO; not used, remove in #29 + }; ListAdapter settingitems; try { settingitems = new SettingAdapter(this, CustomInflater.inflate(this, R.xml.prefs, settings)); @@ -707,21 +487,9 @@ public class TraditionalT9Settings extends ListActivity implements if (s.id.equals("help")) openHelp(); else if (s.id.equals("loaddict")) - preloader(R.string.pref_loadingdict, true, false); + preloader(R.string.pref_loadingdict, true); else if (s.id.equals("loaduserdict")) - preloader(R.string.pref_loadinguserdict, false, false); - else if (s.id.equals("nukedict")) - nukeDict(); - else if (s.id.equals("backupdict")) - backupDict(); - else if (s.id.equals("restoredict")) - restoreDict(); - else if (s.id.equals("reloadKeys")) { - int msg = KeyMap.setKeys(); - if (msg != 0) { - Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); - } - } + preloader(R.string.pref_loadinguserdict, false); else s.clicked(mContext); } @@ -732,81 +500,17 @@ public class TraditionalT9Settings extends ListActivity implements startActivity(i); } - // LoadDictTask(int msgid, boolean intern, boolean restorebackup, CheckBoxPreference setting) - private void preloader(int msgid, boolean internal, boolean restorebackup) { + private void preloader(int msgid, boolean internal) { - task = new LoadDictTask(msgid, internal, restorebackup, - LangHelper.buildLangs(T9DB.getInstance(mContext).getSettingInt(SETTING.LANG_SUPPORT))); + + task = new LoadDictTask( + msgid, + internal, + LangHelper.buildLangs(T9Preferences.getInstance(mContext).getEnabledLanguages()) + ); task.execute(); } - private void predumper(int msgid) { - task = new DumpDictTask(msgid); - task.execute(); - } - - private void nukeDict() { - - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setMessage(R.string.pref_nuke_warn).setTitle(R.string.pref_nuke_title) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - task = new NukeDictTask(R.string.pref_nukingdict); - task.execute(); - // restart settings to get fresh settings. - TraditionalT9Settings.this.finish(); - new Handler().postDelayed(new Runnable() { - @Override - public void run() { - startActivity(new Intent(TraditionalT9Settings.this, TraditionalT9Settings.class)); - }}, 1000); - } - }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - dialog.dismiss(); - } - }); - AlertDialog dialog = builder.create(); - dialog.show(); - } - - private void backupDict() { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { - - File saveloc = new File(Environment.getExternalStorageDirectory(), sddir); - saveloc.mkdirs(); - if (!saveloc.canWrite()) { - Log.e("backupDict", "can't write : " + saveloc.getAbsolutePath()); - showErrorDialogID(builder, R.string.pref_backup_title, R.string.pref_backup_noext); - return; - } - - saveloc = new File(saveloc, backupname); - if (saveloc.exists()) { - builder.setMessage(R.string.pref_backup_warn).setTitle(R.string.pref_backup_title) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - predumper(R.string.pref_savingbackup); - } - }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - dialog.dismiss(); - } - }); - AlertDialog dialog = builder.create(); - dialog.show(); - } else { - predumper(R.string.pref_savingbackup); - } - } else { - showErrorDialogID(builder, R.string.pref_backup_title, R.string.pref_backup_noext); - } - } private void showErrorDialog(CharSequence title, CharSequence msg) { showErrorDialog(new AlertDialog.Builder(this), title, msg); @@ -836,125 +540,6 @@ public class TraditionalT9Settings extends ListActivity implements dialog.show(); } - private void restoreDict() { - // Environment.MEDIA_MOUNTED_READ_ONLY; - // Environment.MEDIA_MOUNTED; - AlertDialog.Builder builder = new AlertDialog.Builder(this); - if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(Environment.getExternalStorageState()) - || Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { - if ((new File(new File(Environment.getExternalStorageDirectory(), sddir), - backupname)).exists()) { - Resources res = getResources(); - builder - .setMessage( - res.getString(R.string.pref_restore_warn, - res.getString(R.string.pref_nukedict))) - .setTitle(R.string.pref_restore_title) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - preloader(R.string.pref_loadingbackup, false, true); - } - }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - dialog.dismiss(); - } - }); - AlertDialog dialog = builder.create(); - dialog.show(); - } else { - showErrorDialogID(builder, R.string.pref_restore_title, - R.string.pref_restore_nofile); - } - } else { - showErrorDialogID(builder, R.string.pref_restore_title, R.string.pref_restore_noext); - } - } - - @SuppressWarnings("unused") - private void queryTestDebug() { - long startnow, endnow; - AbstractList words = new ArrayList(); - List ids = new ArrayList(); - - startnow = SystemClock.uptimeMillis(); - - T9DB tdb = T9DB.getInstance(this); - Log.d("queryTestDebug", "Testing..."); - tdb.updateWords("123", words, ids, 0, LangHelper.LANGUAGE.EN); - Log.d("queryTestDebug", "123->" + words.toString()); - Log.d("queryTestDebug", "269->"); - tdb.updateWords("269", words, ids, 0, LangHelper.LANGUAGE.EN); - Iterator i = words.iterator(); - while (i.hasNext()) { - Log.d("queryTestDebug", "word: " + i.next()); - } - - Log.d("queryTestDebug", "228->"); - tdb.updateWords("228", words, ids, 0, LangHelper.LANGUAGE.EN); - i = words.iterator(); - while (i.hasNext()) { - Log.d("queryTestDebug", "word: " + i.next()); - } - endnow = SystemClock.uptimeMillis(); - Log.d("TIMING", "Execution time: " + (endnow - startnow) + " ms"); - } - - @SuppressWarnings("unused") - private void queryTest() { - long startnow, endnow; - startnow = SystemClock.uptimeMillis(); - - T9DB tdb = T9DB.getInstance(this); - - // tdb.getWords("123").iterator(); - // tdb.getWords("269").iterator(); - // tdb.getWords("228").iterator(); - // tdb.getWords("24371").iterator(); - // tdb.getWords("22376284").iterator(); - // tdb.getWords("68372667367283").iterator(); - // tdb.getWords("22637").iterator(); - - endnow = SystemClock.uptimeMillis(); - Log.d("TIMING", "Execution time: " + (endnow - startnow) + " ms"); - } - - @SuppressWarnings("unused") - private void queryTestSingle() { - long startnow, endnow; - int size; - AbstractList words = new ArrayList(8); - ArrayList ids = new ArrayList(8); - startnow = SystemClock.uptimeMillis(); - - T9DB tdb = T9DB.getInstance(this); - - tdb.updateWords("222", words, ids, 0, LangHelper.LANGUAGE.EN); - size = ids.size(); - if (size > 0) { - tdb.incrementWord(ids.get(0)); - tdb.incrementWord(ids.get(0)); - tdb.incrementWord(ids.get(0)); - } - - for (int x = 0; x < size; x++) { - tdb.incrementWord(ids.get(x)); - } - - endnow = SystemClock.uptimeMillis(); - Log.d("TIMING", "Execution time: " + (endnow - startnow) + " ms"); - - List freqs = new ArrayList(8); - //tdb.updateWordsW("222", words, ids, freqs, LangHelper.EN); - Log.d("VALUES", "..."); - size = freqs.size(); - for (int x = 0; x < size; x++) { - Log.d("VALUES", - "Word: " + words.get(x) + " id: " + ids.get(x) + " freq: " + freqs.get(x)); - } - Log.d("queryTestSingle", "done."); - } @Override public void onCancel(DialogInterface dint) { diff --git a/src/io/github/sspanak/tt9/DBException.java b/src/io/github/sspanak/tt9/db/DBException.java similarity index 84% rename from src/io/github/sspanak/tt9/DBException.java rename to src/io/github/sspanak/tt9/db/DBException.java index fb389b94..d2985e23 100644 --- a/src/io/github/sspanak/tt9/DBException.java +++ b/src/io/github/sspanak/tt9/db/DBException.java @@ -1,4 +1,4 @@ -package io.github.sspanak.tt9; +package io.github.sspanak.tt9.db; public class DBException extends Exception { private static final long serialVersionUID = 376752656441823823L; diff --git a/src/io/github/sspanak/tt9/DBUpdateService.java b/src/io/github/sspanak/tt9/db/DBUpdateService.java similarity index 97% rename from src/io/github/sspanak/tt9/DBUpdateService.java rename to src/io/github/sspanak/tt9/db/DBUpdateService.java index dffc2f26..2d339150 100644 --- a/src/io/github/sspanak/tt9/DBUpdateService.java +++ b/src/io/github/sspanak/tt9/db/DBUpdateService.java @@ -1,4 +1,4 @@ -package io.github.sspanak.tt9; +package io.github.sspanak.tt9.db; import android.app.IntentService; import android.app.Notification; @@ -11,6 +11,8 @@ import android.os.Handler; import android.util.Log; import android.widget.Toast; +import io.github.sspanak.tt9.R; + public class DBUpdateService extends IntentService { private static final int UPDATING_NOTIFICATION_ID = 9640142; diff --git a/src/io/github/sspanak/tt9/db/DatabaseHelper.java b/src/io/github/sspanak/tt9/db/DatabaseHelper.java new file mode 100644 index 00000000..fe01e1b9 --- /dev/null +++ b/src/io/github/sspanak/tt9/db/DatabaseHelper.java @@ -0,0 +1,56 @@ +package io.github.sspanak.tt9.db; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.util.Log; + +public class DatabaseHelper extends SQLiteOpenHelper { + Context mContext = null; + + DatabaseHelper(Context context) { + super(context, T9DB.DATABASE_NAME, null, T9DB.DATABASE_VERSION); + mContext = context; + } + + // partial code from parent class SQLiteOpenHelper + protected boolean needsUpgrading() { + //quick and dirty check to see if an existing database exists. + if (mContext.databaseList().length > 0) { + SQLiteDatabase db = mContext.openOrCreateDatabase(T9DB.DATABASE_NAME, 0, null); + int version = db.getVersion(); + db.close(); + return version < T9DB.DATABASE_VERSION; + } else { + return false; + } + } + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL("CREATE TABLE IF NOT EXISTS " + T9DB.WORD_TABLE_NAME + " (" + + T9DB.COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + + T9DB.COLUMN_LANG + " INTEGER, " + + T9DB.COLUMN_SEQ + " TEXT, " + + T9DB.COLUMN_WORD + " TEXT, " + + T9DB.COLUMN_FREQUENCY + " INTEGER, " + + "UNIQUE(" + T9DB.COLUMN_LANG + ", " + T9DB.COLUMN_WORD + ") )"); + db.execSQL("CREATE INDEX IF NOT EXISTS idx ON " + T9DB.WORD_TABLE_NAME + "(" + + T9DB.COLUMN_LANG + ", " + T9DB.COLUMN_SEQ + " ASC, " + T9DB.COLUMN_FREQUENCY + " DESC )"); + db.execSQL("CREATE TRIGGER IF NOT EXISTS " + T9DB.FREQ_TRIGGER_NAME + + " AFTER UPDATE ON " + T9DB.WORD_TABLE_NAME + + " WHEN NEW." + T9DB.COLUMN_FREQUENCY + " > " + T9DB.FREQ_MAX + + " BEGIN" + + " UPDATE " + T9DB.WORD_TABLE_NAME + " SET " + T9DB.COLUMN_FREQUENCY + " = " + + T9DB.COLUMN_FREQUENCY + " / " + T9DB.FREQ_DIV + + " WHERE " + T9DB.COLUMN_SEQ + " = NEW." + T9DB.COLUMN_SEQ + ";" + + " END;"); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + Log.i("T9DB.onUpgrade", "Upgrading database from version " + oldVersion + " to " + newVersion); + onCreate(db); + // subsequent database migrations go here + Log.i("T9DB.onUpgrade", "Done."); + } +} diff --git a/src/io/github/sspanak/tt9/db/T9DB.java b/src/io/github/sspanak/tt9/db/T9DB.java new file mode 100644 index 00000000..ec09505b --- /dev/null +++ b/src/io/github/sspanak/tt9/db/T9DB.java @@ -0,0 +1,299 @@ +package io.github.sspanak.tt9.db; + +import android.content.ContentValues; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.database.Cursor; +import android.database.sqlite.SQLiteConstraintException; +import android.database.sqlite.SQLiteDatabase; +import android.provider.BaseColumns; +import android.util.Log; +import android.widget.Toast; + +import io.github.sspanak.tt9.CharMap; +import io.github.sspanak.tt9.LangHelper; +import io.github.sspanak.tt9.LangHelper.LANGUAGE; +import io.github.sspanak.tt9.R; +import io.github.sspanak.tt9.preferences.T9Preferences; + +import java.util.AbstractList; +import java.util.Iterator; +import java.util.List; + +public class T9DB { + + private static volatile T9DB instance = null; + protected boolean ready = true; + + public static final String DATABASE_NAME = "t9dict.db"; + public static final int DATABASE_VERSION = 5; // Versions < 5 belong to the original project. We don't care about + // them and we don't migrate them, because the APP ID used to be + // different. This means the TT9 must be installed as a new application + // since version 5, which eliminates the possibility of reusing any + // legacy data. + public static final String WORD_TABLE_NAME = "word"; + public static final String FREQ_TRIGGER_NAME = "freqtrigger"; + // 50k, 10k + public static final int FREQ_MAX = 50000; + public static final int FREQ_DIV = 10000; + // This seems to be pretty fast on my phone. 10 is pretty slow (Might be because > MAX_RESULTS (8).) + private static final int MINHITS = 4; + + public static final String COLUMN_ID = BaseColumns._ID; + public static final String COLUMN_LANG = "lang"; + public static final String COLUMN_SEQ = "seq"; + public static final String COLUMN_WORD = "word"; + public static final String COLUMN_FREQUENCY = "freq"; + + private static final String QUERY1 = + "SELECT " + COLUMN_ID + ", " + COLUMN_WORD + + " FROM " + WORD_TABLE_NAME + + " WHERE " + COLUMN_LANG + "=? AND " + COLUMN_SEQ + "=?" + + " ORDER BY " + COLUMN_FREQUENCY + " DESC"; + + private static final String UPDATEQ = + "UPDATE " + WORD_TABLE_NAME + + " SET " + COLUMN_FREQUENCY + " = " + COLUMN_FREQUENCY + "+1" + + " WHERE " + COLUMN_ID + "="; + + private static final int MAX_RESULTS = 8; + private static final int MAX_MAX_RESULTS = 30; // to make sure we don't exceed candidate view array. + + private DatabaseHelper mOpenHelper; + private SQLiteDatabase db; + + private Context mContext; + + public T9DB(Context caller) { + // create db + mContext = caller; + mOpenHelper = new DatabaseHelper(caller); + } + + public static T9DB getInstance(Context caller) { + if (instance == null) { + synchronized (T9DB.class){ + if (instance == null) { + instance = new T9DB (caller); + instance.init(); + } + } + } + return instance; + } + + public static SQLiteDatabase getSQLDB(Context caller) { + T9DB t9dbhelper = getInstance(caller); + //Log.d("T9DB.getSQLDB", "db:" + t9dbhelper.db.isOpen()); + return t9dbhelper.db; + } + + private void init() { + if (mOpenHelper.needsUpgrading() ) { + ready = false; + Log.i("T9.init", "needsUpgrading"); + // start updating service + if (db != null) { + try { + db.close(); + } catch (NullPointerException ignored) { } + db = null; + } + Intent intent = new Intent(mContext, DBUpdateService.class); + Log.i("T9.init", "Invoking update service..."); + mContext.startService(intent); + } else { + db = mOpenHelper.getWritableDatabase(); + } + } + + private boolean ensureDb() { + if (ready) { + if (db == null) { + db = getWritableDatabase(); + } + return true; + } else { + return false; + } + } + + protected SQLiteDatabase getWritableDatabase() { + return mOpenHelper.getWritableDatabase(); + } + + protected void setSQLDB(SQLiteDatabase tdb) { + synchronized (T9DB.class){ + db = tdb; + ready = true; + } + } + + public boolean isReady() { + return this.ready; + } + + public void close() { + try { db.close(); } + catch (NullPointerException ignored) { } + db = null; + } + + public void truncate() { + Log.i("T9DB.truncate", "Truncating words table..."); + synchronized (T9DB.class) { + ready = false; + db = getWritableDatabase(); + db.delete(WORD_TABLE_NAME, null, null); + ready = true; + } + Log.i("T9DB.truncate", "Done..."); + } + + public void showDBaccessError() { + Toast.makeText(mContext, R.string.database_notready, Toast.LENGTH_SHORT).show(); + } + + public void addWord(String iword, LANGUAGE lang) throws DBException { + Resources r = mContext.getResources(); + if (iword.equals("")) { + throw new DBException(r.getString(R.string.add_word_blank)); + } + // get int sequence + String seq; + try { + seq = CharMap.getStringSequence(iword, lang); + } catch (NullPointerException e) { + throw new DBException(r.getString(R.string.add_word_badchar, lang.name(), iword)); + } + // add int sequence into num table + ContentValues values = new ContentValues(); + values.put(COLUMN_SEQ, seq); + values.put(COLUMN_LANG, lang.id); + // add word into word + values.put(COLUMN_WORD, iword); + values.put(COLUMN_FREQUENCY, 1); + if (!ensureDb()) { + Log.e("T9DB.addWord", "not ready"); + this.showDBaccessError(); + return; + } + try { + db.insertOrThrow(WORD_TABLE_NAME, null, values); + } catch (SQLiteConstraintException e) { + String msg = r.getString(R.string.add_word_exist2, iword, lang.name()); + Log.w("T9DB.addWord", msg); + throw new DBException(msg); + } + } + + public void incrementWord(int id) { + if (!ensureDb()) { + Log.e("T9DB.incrementWord", "not ready"); + this.showDBaccessError(); + return; + } + db.execSQL(UPDATEQ + id); + // if id's freq is greater than FREQ_MAX, it gets normalized with trigger + } + + public void updateWords(String is, AbstractList stringList, List intList, + int capsMode, LANGUAGE lang) { + stringList.clear(); + intList.clear(); + // String[] sa = packInts(stringToInts(is), true); + int islen = is.length(); + + if (!ensureDb()) { + Log.e("T9DB.updateWords", "not ready"); + this.showDBaccessError(); + return; + } + Cursor cur = db.rawQuery(QUERY1, new String[] { String.valueOf(lang.id), is }); + + int hits = 0; + for (cur.moveToFirst(); !cur.isAfterLast(); cur.moveToNext()) { + intList.add(cur.getInt(0)); + stringList.add(cur.getString(1)); + if (hits >= MAX_MAX_RESULTS) { break; } // to stop index error in candidate view + hits++; + } + cur.close(); + + if ((hits < MINHITS) && (islen >= 2)) { + char c = is.charAt(islen - 1); + c++; + String q = "SELECT " + COLUMN_ID + ", " + COLUMN_WORD + + " FROM " + WORD_TABLE_NAME + + " WHERE " + COLUMN_LANG + "=? AND " + COLUMN_SEQ + " >= '" + is + "1" + + "' AND " + COLUMN_SEQ + " < '" + is.substring(0, islen - 1) + c + "'" + + " ORDER BY " + COLUMN_FREQUENCY + " DESC, " + COLUMN_SEQ + " ASC" + + " LIMIT " + (MAX_RESULTS - hits); + cur = db.rawQuery(q, new String[] { String.valueOf(lang.id) }); + + for (cur.moveToFirst(); !cur.isAfterLast(); cur.moveToNext()) { + intList.add(cur.getInt(0)); + stringList.add(cur.getString(1)); + if (hits >= MAX_MAX_RESULTS) { + break; + } + hits++; + } + cur.close(); + } + // Log.d("T9DB.updateWords", "pre: " + stringList); + if (capsMode == T9Preferences.CASE_LOWER) { + return; + } + // Log.d("T9DB.updateWords", "filtering..."); + // filter list + Iterator iter = stringList.iterator(); + String word; + String wordtemp; + int index = 0; + boolean removed = false; + while (iter.hasNext()) { + word = iter.next(); + switch (capsMode) { + case T9Preferences.CASE_UPPER: + wordtemp = word.toUpperCase(LangHelper.LOCALES[lang.index]); + if (wordtemp.equals(word)) { + index++; + continue; + } else if (stringList.contains(wordtemp)) { + // remove this entry + iter.remove(); + removed = true; + } else { + stringList.set(index, wordtemp); + } + break; + case T9Preferences.CASE_CAPITALIZE: + if (word.length() > 1) { + wordtemp = word.substring(0, 1).toUpperCase(LangHelper.LOCALES[lang.index]) + word.substring(1); + } else { + wordtemp = word.toUpperCase(LangHelper.LOCALES[lang.index]); + } + if (wordtemp.equals(word)) { + index++; + continue; + } else if (stringList.contains(wordtemp)) { + // remove this entry + iter.remove(); + removed = true; + } else { + stringList.set(index, wordtemp); + } + break; + } + if (removed) { + intList.remove(index); + removed = false; + } else { + index++; + } + } + //Log.d("T9DB.updateWords", "i:" + is + " words:" + Arrays.toString(stringList.toArray())); + } +} diff --git a/src/io/github/sspanak/tt9/preferences/T9Preferences.java b/src/io/github/sspanak/tt9/preferences/T9Preferences.java new file mode 100644 index 00000000..73e1add7 --- /dev/null +++ b/src/io/github/sspanak/tt9/preferences/T9Preferences.java @@ -0,0 +1,109 @@ +package io.github.sspanak.tt9.preferences; + +import android.content.Context; +import android.content.SharedPreferences; +import androidx.preference.PreferenceManager; + +import android.view.KeyEvent; + +public class T9Preferences { + private static T9Preferences self; + + private SharedPreferences prefs; + private SharedPreferences.Editor prefsEditor; + + public static final int CASE_LOWER = 0; + public static final int CASE_CAPITALIZE = 1; + public static final int CASE_UPPER = 2; + + public static final int MODE_PREDICTIVE = 0; + public static final int MODE_ABC = 1; + public static final int MODE_123 = 2; + + public T9Preferences (Context context) { + prefs = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()); + prefsEditor = prefs.edit(); + } + + public static T9Preferences getInstance(Context context) { + if (self == null) { + self = new T9Preferences(context); + } + + return self; + } + + public int getEnabledLanguages() { + return prefs.getInt("pref_enabled_languages", 1); + } + + public T9Preferences setEnabledLanguages(int languageMask) { + prefsEditor.putInt("pref_enabled_languages", languageMask); + prefsEditor.apply(); + + return this; + } + + // public int getInputCase() { + // return prefs.getInt("pref_input_case", CASE_CAPITALIZE); + // } + + public int getInputLanguage() { + return prefs.getInt("pref_input_language", 1); + } + + public T9Preferences setInputLanguage(int language) { + prefsEditor.putInt("pref_input_language", language); + prefsEditor.apply(); + + return this; + } + + public int getInputMode() { + return prefs.getInt("pref_input_mode", MODE_PREDICTIVE); + } + + public T9Preferences setInputMode(int mode) throws Exception { + if (mode != MODE_PREDICTIVE && mode != MODE_ABC && mode != MODE_123) { + throw new Exception("Invalid input mode: '" + mode + "'"); + } + + prefsEditor.putInt("pref_input_mode", mode); + prefsEditor.apply(); + + return this; + } + + public int getKeyBackspace() { + return prefs.getInt("pref_key_backspace", KeyEvent.KEYCODE_DEL); + } + + // public int getKeyInputMode() { + // return prefs.getInt("pref_key_inputmode", KeyEvent.KEYCODE_POUND); + // } + + // public int getKeyOtherActions() { + // return prefs.getInt("pref_key_other_actions", KeyEvent.KEYCODE_CALL); + // } + + // public boolean getSoftBackspaceEnabled() { + // return prefs.getBoolean("pref_softkey_backspace", true); + // } + + // public boolean getSoftPrefsEnabled() { + // return prefs.getBoolean("pref_softkey_prefs", true); + // } + + public String getLastWord() { + return prefs.getString("last_word", ""); + } + + public T9Preferences setLastWord(String lastWord) { + // "last_word" was part of the original Preferences implementation. + // It is weird, but it is simple and it works, so I decided to keep it. + prefsEditor.putString("last_word", lastWord); + prefsEditor.apply(); + + return this; + } +} diff --git a/src/io/github/sspanak/tt9/settings/SettingCheck.java b/src/io/github/sspanak/tt9/settings/SettingCheck.java deleted file mode 100644 index 4d4e96a0..00000000 --- a/src/io/github/sspanak/tt9/settings/SettingCheck.java +++ /dev/null @@ -1,49 +0,0 @@ -package io.github.sspanak.tt9.settings; - - -import android.content.Context; -import android.util.AttributeSet; -import android.widget.CheckBox; - -import io.github.sspanak.tt9.R; -import io.github.sspanak.tt9.T9DB; -import io.github.sspanak.tt9.T9DB.DBSettings.SETTING; - -public class SettingCheck extends Setting { - boolean value; - boolean defaultValue; - - public SettingCheck (Context context, AttributeSet attrs, Object[] isettings) { - super(context, attrs, isettings); - // http://stackoverflow.com/a/8488691 - for (int i = 0; i < attrs.getAttributeCount(); i++) { - String attr = attrs.getAttributeName(i); - if ("defaultValue".equals(attr)) { - defaultValue = attrs.getAttributeBooleanValue(i, false); - } - } - - SETTING s = SETTING.get(id); - if (s != null) { - Object o = isettings[s.sqOrder]; - if (o == null) - value = defaultValue; - else - value = o.equals(1); - } - widgetID = R.layout.checkbox; - layout = R.layout.setting_widget; - } - - @Override - public void clicked(Context context) { - value = !value; - T9DB.getInstance(context).storeSettingInt(SETTING.get(id), value ? 1 : 0); - ((CheckBox)view.findViewById(R.id.checkbox)).setChecked(value); - } - - @Override - public void init(){ - ((CheckBox)view.findViewById(R.id.checkbox)).setChecked(value); - } -} diff --git a/src/io/github/sspanak/tt9/settings/SettingList.java b/src/io/github/sspanak/tt9/settings/SettingList.java index d8554279..43efb009 100644 --- a/src/io/github/sspanak/tt9/settings/SettingList.java +++ b/src/io/github/sspanak/tt9/settings/SettingList.java @@ -4,10 +4,10 @@ import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.util.AttributeSet; +import android.util.Log; import io.github.sspanak.tt9.R; -import io.github.sspanak.tt9.T9DB; -import io.github.sspanak.tt9.T9DB.DBSettings.SETTING; +import io.github.sspanak.tt9.preferences.T9Preferences; public class SettingList extends Setting { String[] entries; @@ -56,7 +56,13 @@ public class SettingList extends Setting { @Override public void onClick(DialogInterface dialog, int which) { - T9DB.getInstance(context).storeSettingInt(SETTING.get(id), entryValues[which]); + if (id.equals("pref_inputmode")) { + try { + T9Preferences.getInstance(context).setInputMode(entryValues[which]); + } catch (Exception e) { + Log.e("SettingsList", e.getMessage()); + } + } value = entryValues[which]; dialog.dismiss(); } diff --git a/src/io/github/sspanak/tt9/settings/SettingMultiList.java b/src/io/github/sspanak/tt9/settings/SettingMultiList.java index 31ef3ee8..501a871e 100644 --- a/src/io/github/sspanak/tt9/settings/SettingMultiList.java +++ b/src/io/github/sspanak/tt9/settings/SettingMultiList.java @@ -8,8 +8,7 @@ import android.widget.TextView; import io.github.sspanak.tt9.LangHelper; import io.github.sspanak.tt9.R; -import io.github.sspanak.tt9.T9DB; -import io.github.sspanak.tt9.T9DB.DBSettings.SETTING; +import io.github.sspanak.tt9.preferences.T9Preferences; public class SettingMultiList extends SettingList { boolean[] selectedEntries = new boolean[0]; @@ -38,7 +37,9 @@ public class SettingMultiList extends SettingList { new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - T9DB.getInstance(context).storeSettingInt(SETTING.get(id), LangHelper.shrinkLangs(buildSelection())); + if (id.equals("pref_lang_support")) { + T9Preferences.getInstance(context).setEnabledLanguages(LangHelper.shrinkLangs(buildSelection())); + } summary = buildItems(); dialog.dismiss(); ((TextView)view.findViewById(R.id.summary)).setText(summary);