From: Thad Hughes Date: Tue, 24 Jan 2012 05:32:38 +0000 (-0800) Subject: Major refactor of down dictionary list is stored by app. X-Git-Url: http://gitweb.fperrin.net/?p=Dictionary.git;a=commitdiff_plain;h=6d31b7b124787ac07ba682879fd47229765b6ee0 Major refactor of down dictionary list is stored by app. --- diff --git a/images/michael_vogel_icon_48x48.png b/images/michael_vogel_icon_48x48.png new file mode 100644 index 0000000..c2fe5ff Binary files /dev/null and b/images/michael_vogel_icon_48x48.png differ diff --git a/images/q114x114.png b/images/q114x114.png new file mode 100644 index 0000000..8e8621b Binary files /dev/null and b/images/q114x114.png differ diff --git a/images/q128x128.png b/images/q128x128.png new file mode 100644 index 0000000..ceb7466 Binary files /dev/null and b/images/q128x128.png differ diff --git a/images/q512x512.png b/images/q512x512.png new file mode 100644 index 0000000..767ad26 Binary files /dev/null and b/images/q512x512.png differ diff --git a/res/layout/download_activity.xml b/res/layout/download_activity.xml index 2ed5a64..13457b8 100755 --- a/res/layout/download_activity.xml +++ b/res/layout/download_activity.xml @@ -27,6 +27,9 @@ android:max="100" android:progress="50" android:layout_width="fill_parent" android:layout_height="wrap_content" android:indeterminate="false"/> + + diff --git a/res/values/languages.xml b/res/values/languages.xml index 80b2fcb..28bc91b 100644 --- a/res/values/languages.xml +++ b/res/values/languages.xml @@ -59,6 +59,7 @@ Tibetan Turkish Ukrainian + Urdu Vietnamese Welsh Yiddish diff --git a/res/values/strings.xml b/res/values/strings.xml index bd39255..4ccaafa 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -40,13 +40,12 @@ Download Open Dictionary info: + Index %1$s, %2$d words Dictionary file Word list file File not found: \'%s\' Invalid dictionary: file=%1$s, error=%2$s Entries: %,d - Tokens: %,d - Rows: %,d diff --git a/src/com/hughes/android/dictionary/DictionaryActivity.java b/src/com/hughes/android/dictionary/DictionaryActivity.java index d6ec791..6c69e9b 100644 --- a/src/com/hughes/android/dictionary/DictionaryActivity.java +++ b/src/com/hughes/android/dictionary/DictionaryActivity.java @@ -20,7 +20,6 @@ import java.io.IOException; import java.io.PrintWriter; import java.io.RandomAccessFile; import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.Executor; @@ -81,7 +80,6 @@ import com.hughes.android.dictionary.engine.PairEntry.Pair; import com.hughes.android.dictionary.engine.RowBase; import com.hughes.android.dictionary.engine.TokenRow; import com.hughes.android.dictionary.engine.TransliteratorManager; -import com.hughes.android.util.PersistentObjectCache; public class DictionaryActivity extends ListActivity { @@ -132,16 +130,25 @@ public class DictionaryActivity extends ListActivity { return intent; } - // TODO: fix these... - @Override protected void onSaveInstanceState(final Bundle outState) { super.onSaveInstanceState(outState); outState.putString(C.SEARCH_TOKEN, searchText.getText().toString()); } + + @Override + protected void onRestoreInstanceState(final Bundle outState) { + super.onRestoreInstanceState(outState); + setSearchText(outState.getString(C.SEARCH_TOKEN)); + } + + public DictionaryApplication getDictionaryApplication() { + return (DictionaryApplication) super.getApplication(); + } @Override public void onCreate(Bundle savedInstanceState) { + // Clear them so that if something goes wrong, we won't relaunch. clearDictionaryPrefs(this); Log.d(LOG, "onCreate:" + this); @@ -152,12 +159,9 @@ public class DictionaryActivity extends ListActivity { dictFile = intent.getStringExtra(C.DICT_FILE); try { - PersistentObjectCache.init(this); - QuickDicConfig quickDicConfig = PersistentObjectCache.init( - this).read(C.DICTIONARY_CONFIGS, QuickDicConfig.class); - final DictionaryInfo dictionaryConfig = quickDicConfig.getDictionaryInfoByFile(dictFile); - this.setTitle("QuickDic: " + dictionaryConfig.name); - dictRaf = new RandomAccessFile(dictionaryConfig.localFile, "r"); + final String name = getDictionaryApplication().getDictionaryName(dictFile); + this.setTitle("QuickDic: " + name); + dictRaf = new RandomAccessFile(dictFile, "r"); dictionary = new Dictionary(dictRaf); } catch (Exception e) { Log.e(LOG, "Unable to load dictionary.", e); @@ -170,7 +174,7 @@ public class DictionaryActivity extends ListActivity { dictRaf = null; } Toast.makeText(this, getString(R.string.invalidDictionary, "", e.getMessage()), Toast.LENGTH_LONG); - startActivity(DictionaryEditActivity.getLaunchIntent(dictFile)); + startActivity(DictionaryManagerActivity.getLaunchIntent()); finish(); return; } @@ -427,21 +431,16 @@ public class DictionaryActivity extends ListActivity { dialog.setTitle(R.string.selectADictionary); ListView listView = (ListView) dialog.findViewById(android.R.id.list); + + final List installedDicts = ((DictionaryApplication)getApplication()).getUsableDicts(); - QuickDicConfig quickDicConfig = PersistentObjectCache.init( - this).read(C.DICTIONARY_CONFIGS, QuickDicConfig.class); - final List dictionaryInfos = new ArrayList(); - for (final DictionaryInfo dictionaryInfo : quickDicConfig.dictionaryInfos) { - if (new File(dictionaryInfo.localFile).canRead()) { - dictionaryInfos.add(dictionaryInfo); - } - } listView.setAdapter(new BaseAdapter() { @Override public View getView(int position, View convertView, ViewGroup parent) { final LinearLayout result = new LinearLayout(parent.getContext()); //result.addView(new Butt) + // TODO: me return result; } @@ -451,13 +450,13 @@ public class DictionaryActivity extends ListActivity { } @Override - public Object getItem(int position) { - return dictionaryInfos.get(position); + public DictionaryInfo getItem(int position) { + return installedDicts.get(position); } @Override public int getCount() { - return dictionaryInfos.size(); + return installedDicts.size(); } }); } diff --git a/src/com/hughes/android/dictionary/DictionaryApplication.java b/src/com/hughes/android/dictionary/DictionaryApplication.java index d7109a0..a16ad0e 100644 --- a/src/com/hughes/android/dictionary/DictionaryApplication.java +++ b/src/com/hughes/android/dictionary/DictionaryApplication.java @@ -14,32 +14,73 @@ package com.hughes.android.dictionary; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + import android.app.Application; +import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.os.Environment; import android.preference.PreferenceManager; import android.util.Log; +import com.hughes.android.dictionary.engine.Dictionary; +import com.hughes.android.dictionary.engine.Language; import com.hughes.android.dictionary.engine.TransliteratorManager; +import com.hughes.android.util.PersistentObjectCache; +import com.ibm.icu.text.Collator; public class DictionaryApplication extends Application { + static final String LOG = "QuickDicApp"; + + private static final File DICT_DIR = new File(Environment.getExternalStorageDirectory().getName(), "quickdic"); + + // Static, determined by resources (and locale). + // Unordered. + static Map DOWNLOADABLE_NAME_TO_INFO = null; + + static final class DictionaryConfig implements Serializable { + private static final long serialVersionUID = -1444177164708201260L; + // User-ordered list, persisted, just the ones that are/have been present. + final List dictionaryFiles = new ArrayList(); + } + DictionaryConfig dictionaryConfig = null; + @Override public void onCreate() { super.onCreate(); Log.d("QuickDic", "Application: onCreate"); TransliteratorManager.init(null); + staticInit(getApplicationContext()); - setTheme(getSelectedTheme().themeId); - + // Load the dictionaries we know about. + dictionaryConfig = PersistentObjectCache.init(getApplicationContext()).read(C.DICTIONARY_CONFIGS, DictionaryConfig.class); + if (dictionaryConfig == null) { + dictionaryConfig = new DictionaryConfig(); + } + + // Theme stuff. + setTheme(getSelectedTheme().themeId); final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); prefs.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener() { @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { Log.d("THAD", "prefs changed: " + key); - if (key.equals(getString(R.string.themeKey))) { setTheme(getSelectedTheme().themeId); } @@ -56,4 +97,136 @@ public class DictionaryApplication extends Application { return C.Theme.DEFAULT; } } + + static synchronized void staticInit(final Context context) { + if (DOWNLOADABLE_NAME_TO_INFO != null) { + return; + } + DOWNLOADABLE_NAME_TO_INFO = new LinkedHashMap(); + final BufferedReader reader = new BufferedReader(new InputStreamReader(context.getResources().openRawResource(R.raw.dictionary_info))); + try { + String line; + while ((line = reader.readLine()) != null) { + if (line.startsWith("#") || line.length() == 0) { + continue; + } + final DictionaryInfo dictionaryInfo = new DictionaryInfo(line); + DOWNLOADABLE_NAME_TO_INFO.put(dictionaryInfo.uncompressedFilename, dictionaryInfo); + } + reader.close(); + } catch (IOException e) { + Log.e(LOG, "Failed to load downloadable dictionary lists.", e); + } + } + + private File getPath(String uncompressedFilename) { + return new File(DICT_DIR, uncompressedFilename); + } + + + public List getUsableDicts() { + final List result = new ArrayList(dictionaryConfig.dictionaryFiles.size()); + for (final String uncompressedFilename : dictionaryConfig.dictionaryFiles) { + final DictionaryInfo dictionaryInfo = Dictionary.getDictionaryInfo(getPath(uncompressedFilename)); + if (dictionaryInfo != null) { + result.add(dictionaryInfo); + } + } + return result; + } + + final Map fileToNameCache = new LinkedHashMap(); + public synchronized String getDictionaryName(final String uncompressedFilename) { + String name = fileToNameCache.get(uncompressedFilename); + if (name != null) { + return name; + } + + final DictionaryInfo dictionaryInfo = DOWNLOADABLE_NAME_TO_INFO.get(uncompressedFilename); + final Context context = getApplicationContext(); + if (dictionaryInfo != null) { + final StringBuilder nameBuilder = new StringBuilder(); + for (int i = 0; i < dictionaryInfo.indexInfos.size(); ++i) { + final Integer langCode = Language.isoCodeToResourceId.get(dictionaryInfo.indexInfos.get(i).shortName); + final String lang = langCode != null ? context.getString(langCode) : dictionaryInfo.indexInfos.get(i).shortName; + if (i > 0) { + nameBuilder.append("-"); + } + nameBuilder.append(lang); + } + name = nameBuilder.toString(); + } else { + name = uncompressedFilename.replace(".quickdic", ""); + } + fileToNameCache.put(uncompressedFilename, name); + return name; + } + + public void moveDictionaryToTop(final String canonicalPath) { + dictionaryConfig.dictionaryFiles.remove(canonicalPath); + dictionaryConfig.dictionaryFiles.add(0, canonicalPath); + PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS, dictionaryConfig); + } + + public void deleteDictionary(String canonicalPath) { + while (dictionaryConfig.dictionaryFiles.remove(canonicalPath)) {}; + PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS, dictionaryConfig); + } + + public List getAllDictionaries() { + final List result = getUsableDicts(); + + // The ones we knew about... + final Set known = new LinkedHashSet(); + for (final DictionaryInfo usable : result) { + known.add(usable.uncompressedFilename); + } + + // Are there dictionaries on the device that we didn't know about already? + // Pick them up and put them at the end of the list. + boolean foundNew = false; + final File[] dictDirFiles = DICT_DIR.listFiles(); + for (final File file : dictDirFiles) { + if (!file.getName().endsWith(".quickdic")) { + continue; + } + if (known.contains(file.getName())) { + // We have it in our list already. + continue; + } + final DictionaryInfo dictionaryInfo = Dictionary.getDictionaryInfo(file); + if (dictionaryInfo == null) { + Log.e(LOG, "Unable to parse dictionary: " + file.getPath()); + continue; + } + known.add(file.getName()); + foundNew = true; + dictionaryConfig.dictionaryFiles.add(file.getName()); + result.add(dictionaryInfo); + } + if (foundNew) { + PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS, dictionaryConfig); + } + + // The downloadable ones. + final Map remaining = new LinkedHashMap(DOWNLOADABLE_NAME_TO_INFO); + remaining.keySet().removeAll(known); + final List remainingSorted = new ArrayList(remaining.values()); + final Collator collator = Collator.getInstance(); + Collections.sort(remainingSorted, new Comparator() { + @Override + public int compare(DictionaryInfo object1, DictionaryInfo object2) { + return collator.compare(getDictionaryName(object1.uncompressedFilename), getDictionaryName(object2.uncompressedFilename)); + } + }); + + result.addAll(remainingSorted); + return result; + } + + public boolean isDictionaryOnDevice(String uncompressedFilename) { + return getPath(uncompressedFilename).canRead(); + } + + } diff --git a/src/com/hughes/android/dictionary/DictionaryEditActivity.java b/src/com/hughes/android/dictionary/DictionaryEditActivity.java deleted file mode 100644 index 499feb2..0000000 --- a/src/com/hughes/android/dictionary/DictionaryEditActivity.java +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright 2011 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.hughes.android.dictionary; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.os.Handler; -import android.text.Editable; -import android.text.TextWatcher; -import android.util.Log; -import android.view.Menu; -import android.view.MenuItem; -import android.view.MenuItem.OnMenuItemClickListener; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.WindowManager; -import android.widget.Button; -import android.widget.EditText; -import android.widget.TextView; - -import com.hughes.android.dictionary.engine.Dictionary; -import com.hughes.android.dictionary.engine.Index; -import com.hughes.android.util.PersistentObjectCache; - -public class DictionaryEditActivity extends Activity { - - static final String LOG = "QuickDic"; - - QuickDicConfig quickDicConfig; - private DictionaryInfo dictionaryInfo; - - final Handler uiHandler = new Handler(); - - public static Intent getLaunchIntent(final String dictFile) { - final Intent intent = new Intent(); - intent.setClassName(DictionaryEditActivity.class.getPackage().getName(), - DictionaryEditActivity.class.getName()); - intent.putExtra(C.DICT_FILE, dictFile); - return intent; - } - - /** Called when the activity is first created. */ - @Override - public void onCreate(final Bundle savedInstanceState) { - //((DictionaryApplication)getApplication()).applyTheme(this); - - super.onCreate(savedInstanceState); - setContentView(R.layout.edit_activity); - - final Intent intent = getIntent(); - final String dictFile = intent.getStringExtra(C.DICT_FILE); - - PersistentObjectCache.init(this); - try { - quickDicConfig = PersistentObjectCache.init(this).read( - C.DICTIONARY_CONFIGS, QuickDicConfig.class); - dictionaryInfo = quickDicConfig.getDictionaryInfoByFile(dictFile); - } catch (Exception e) { - Log.e(LOG, "Failed to read QuickDicConfig.", e); - finish(); - startActivity(DictionaryManagerActivity.getLaunchIntent()); - return; - } - - // Write stuff from object into fields. - - ((EditText) findViewById(R.id.dictionaryName)) - .setText(dictionaryInfo.name); - ((EditText) findViewById(R.id.localFile)) - .setText(dictionaryInfo.localFile); - - final TextWatcher textWatcher = new TextWatcher() { - @Override - public void onTextChanged(CharSequence s, int start, int before, - int count) { - } - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, - int after) { - } - - @Override - public void afterTextChanged(Editable s) { - updateDictInfo(); - } - }; - - ((EditText) findViewById(R.id.localFile)).addTextChangedListener(textWatcher); - - final EditText downloadUrl = (EditText) findViewById(R.id.downloadUrl); - downloadUrl.setText(dictionaryInfo.downloadUrl); - downloadUrl.addTextChangedListener(textWatcher); - - final Button downloadButton = (Button) findViewById(R.id.downloadButton); - downloadButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - startDownloadDictActivity(DictionaryEditActivity.this, - dictionaryInfo); - } - }); - - final Button openButton = (Button) findViewById(R.id.openButton); - openButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - final Intent intent = DictionaryActivity.getLaunchIntent(dictFile, 0, ""); - startActivity(intent); - } - }); - - // Don't show the keyboard when this opens up: - getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); - - } - - protected void onResume() { - super.onResume(); - - updateDictInfo(); - - // Focus the download button so the keyboard doesn't pop up. - final Button downloadButton = (Button) findViewById(R.id.downloadButton); - downloadButton.requestFocus(); - } - - @Override - protected void onPause() { - super.onPause(); - - // Read stuff from fields into object. - dictionaryInfo.name = ((EditText) findViewById(R.id.dictionaryName)) - .getText().toString(); - dictionaryInfo.localFile = ((EditText) findViewById(R.id.localFile)) - .getText().toString(); - dictionaryInfo.downloadUrl = ((EditText) findViewById(R.id.downloadUrl)) - .getText().toString(); - - PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS, - quickDicConfig); - } - - public boolean onCreateOptionsMenu(final Menu menu) { - final MenuItem newDictionaryMenuItem = menu - .add(R.string.downloadDictionary); - newDictionaryMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(final MenuItem menuItem) { - startDownloadDictActivity(DictionaryEditActivity.this, - dictionaryInfo); - return false; - } - }); - - final MenuItem dictionaryList = menu.add(getString(R.string.dictionaryManager)); - dictionaryList.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(final MenuItem menuItem) { - startActivity(DictionaryManagerActivity.getLaunchIntent()); - return false; - } - }); - - - return true; - } - - void updateDictInfo() { - final String downloadUrl = ((EditText) findViewById(R.id.downloadUrl)) - .getText().toString(); - final String localFile = ((EditText) findViewById(R.id.localFile)) - .getText().toString(); - - final Button downloadButton = (Button) findViewById(R.id.downloadButton); - downloadButton.setEnabled(downloadUrl.length() > 0 && localFile.length() > 0); - - final Button openButton = (Button) findViewById(R.id.openButton); - openButton.setEnabled(false); - - final TextView dictInfo = (TextView) findViewById(R.id.dictionaryInfo); - if (!new File(localFile).canRead()) { - dictInfo.setText(getString(R.string.fileNotFound, localFile)); - return; - } - - try { - final RandomAccessFile raf = new RandomAccessFile(localFile, "r"); - final Dictionary dict = new Dictionary(raf); - final StringBuilder builder = new StringBuilder(); - builder.append(dict.dictInfo).append("\n"); - builder.append( - getString(R.string.numPairEntries, dict.pairEntries.size())).append( - "\n"); - for (final Index index : dict.indices) { - builder.append("\n"); - builder.append(index.longName).append("\n"); - builder.append(" ").append( - getString(R.string.numTokens, index.sortedIndexEntries.size())) - .append("\n"); - builder.append(" ").append( - getString(R.string.numRows, index.rows.size())).append("\n"); - } - raf.close(); - dictInfo.setText(builder.toString()); - openButton.setEnabled(true); - - } catch (IOException e) { - dictInfo.setText(getString(R.string.invalidDictionary, localFile, e - .toString())); - } - } - - static void startDownloadDictActivity(final Context context, - final DictionaryInfo dictionaryConfig) { - final Intent intent = new Intent(context, DownloadActivity.class); - intent.putExtra(DownloadActivity.SOURCE, dictionaryConfig.downloadUrl); - intent.putExtra(DownloadActivity.DEST, dictionaryConfig.localFile + ".zip"); - context.startActivity(intent); - } - -} diff --git a/src/com/hughes/android/dictionary/DictionaryInfo.java b/src/com/hughes/android/dictionary/DictionaryInfo.java index 6759e32..a291dc0 100644 --- a/src/com/hughes/android/dictionary/DictionaryInfo.java +++ b/src/com/hughes/android/dictionary/DictionaryInfo.java @@ -25,26 +25,26 @@ public class DictionaryInfo implements Serializable { public static final class IndexInfo implements Serializable { private static final long serialVersionUID = 6524751236198309438L; - public IndexInfo(String langIso, int allTokenCount, int mainTokenCount) { - this.langIso = langIso; + public IndexInfo(String shortName, int allTokenCount, int mainTokenCount) { + this.shortName = shortName; this.allTokenCount = allTokenCount; this.mainTokenCount = mainTokenCount; } - public final String langIso; + public final String shortName; // Often LangISO. public final int allTokenCount; public final int mainTokenCount; public static final int SIZE = 3; public StringBuilder append(StringBuilder result) { - result.append(langIso); + result.append(shortName); result.append("\t").append(allTokenCount); result.append("\t").append(mainTokenCount); return result; } public IndexInfo(final String[] fields, int i) { - langIso = fields[i++]; + shortName = fields[i++]; allTokenCount = Integer.parseInt(fields[i++]); mainTokenCount = Integer.parseInt(fields[i++]); } @@ -52,15 +52,12 @@ public class DictionaryInfo implements Serializable { } // Stuff populated from the text file. - public String uncompressedFilename; + public String uncompressedFilename; // used as a key throughout the program. public String downloadUrl; public long uncompressedSize; public long creationMillis; public final List indexInfos = new ArrayList(); public String dictInfo; - - String name; // Determined at runtime based on locale on device--user editable? - String localFile; // Determined based on device's Environment. public StringBuilder append(final StringBuilder result) { result.append(uncompressedFilename); @@ -96,7 +93,7 @@ public class DictionaryInfo implements Serializable { @Override public String toString() { - return name; + return uncompressedFilename; } diff --git a/src/com/hughes/android/dictionary/DictionaryManagerActivity.java b/src/com/hughes/android/dictionary/DictionaryManagerActivity.java index bd41943..d5ac87e 100644 --- a/src/com/hughes/android/dictionary/DictionaryManagerActivity.java +++ b/src/com/hughes/android/dictionary/DictionaryManagerActivity.java @@ -14,7 +14,7 @@ package com.hughes.android.dictionary; -import java.io.File; +import java.util.List; import android.app.AlertDialog; import android.app.ListActivity; @@ -41,8 +41,6 @@ import android.widget.BaseAdapter; import android.widget.TableLayout; import android.widget.TextView; -import com.hughes.android.util.PersistentObjectCache; - public class DictionaryManagerActivity extends ListActivity { static final String LOG = "QuickDic"; @@ -50,6 +48,7 @@ public class DictionaryManagerActivity extends ListActivity { static boolean canAutoLaunch = true; + final DictionaryApplication application = (DictionaryApplication) getApplication(); public void onCreate(Bundle savedInstanceState) { //((DictionaryApplication)getApplication()).applyTheme(this); @@ -100,9 +99,9 @@ public class DictionaryManagerActivity extends ListActivity { } } - private void onClick(int dictIndex) { - final DictionaryInfo dictionaryInfo = quickDicConfig.dictionaryInfos.get(dictIndex); - final Intent intent = DictionaryActivity.getLaunchIntent(dictionaryInfo.localFile, 0, ""); + private void onClick(int index) { + final DictionaryInfo dictionaryInfo = adapter.getItem(index); + final Intent intent = DictionaryActivity.getLaunchIntent(dictionaryInfo.uncompressedFilename, 0, ""); startActivity(intent); } @@ -126,16 +125,7 @@ public class DictionaryManagerActivity extends ListActivity { return; } - quickDicConfig = PersistentObjectCache.init(this).read(C.DICTIONARY_CONFIGS, QuickDicConfig.class); - if (quickDicConfig == null) { - quickDicConfig = new QuickDicConfig(this); - } else { - quickDicConfig.addDefaultDictionaries(this); - } - PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS, quickDicConfig); - - Log.d(LOG, "DictionaryList: " + quickDicConfig.dictionaryInfos); - setListAdapter(new Adapter()); + setListAdapter(adapter); } public boolean onCreateOptionsMenu(final Menu menu) { @@ -169,15 +159,16 @@ public class DictionaryManagerActivity extends ListActivity { super.onCreateContextMenu(menu, view, menuInfo); final AdapterContextMenuInfo adapterContextMenuInfo = (AdapterContextMenuInfo) menuInfo; + final int position = adapterContextMenuInfo.position; + final DictionaryInfo dictionaryInfo = adapter.getItem(position); - if (adapterContextMenuInfo.position > 0) { + if (position > 0) { final MenuItem moveToTopMenuItem = menu.add(R.string.moveToTop); moveToTopMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { - final DictionaryInfo dictionaryConfig = quickDicConfig.dictionaryInfos.remove(adapterContextMenuInfo.position); - quickDicConfig.dictionaryInfos.add(0, dictionaryConfig); - dictionaryConfigsChanged(); + application.moveDictionaryToTop(dictionaryInfo.uncompressedFilename); + setListAdapter(adapter = new Adapter()); return true; } }); @@ -187,29 +178,26 @@ public class DictionaryManagerActivity extends ListActivity { deleteMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { - quickDicConfig.dictionaryInfos.remove(adapterContextMenuInfo.position); - dictionaryConfigsChanged(); + application.deleteDictionary(dictionaryInfo.uncompressedFilename); + setListAdapter(adapter = new Adapter()); return true; } }); } - private void dictionaryConfigsChanged() { - PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS, quickDicConfig); - setListAdapter(getListAdapter()); - } - class Adapter extends BaseAdapter { + + final List dictionaryInfos = application.getAllDictionaries(); @Override public int getCount() { - return quickDicConfig.dictionaryInfos.size(); + return dictionaryInfos.size(); } @Override public DictionaryInfo getItem(int position) { - return quickDicConfig.dictionaryInfos.get(position); + return dictionaryInfos.get(position); } @Override @@ -219,13 +207,13 @@ public class DictionaryManagerActivity extends ListActivity { @Override public View getView(int position, View convertView, ViewGroup parent) { - final DictionaryInfo dictionaryConfig = getItem(position); + final DictionaryInfo dictionaryInfo = getItem(position); final TableLayout tableLayout = new TableLayout(parent.getContext()); final TextView view = new TextView(parent.getContext()); - String name = dictionaryConfig.name; - if (!new File(dictionaryConfig.localFile).canRead()) { - name = getString(R.string.notOnDevice, dictionaryConfig.name); + String name = application.getDictionaryName(dictionaryInfo.uncompressedFilename); + if (!application.isDictionaryOnDevice(dictionaryInfo.uncompressedFilename)) { + name = getString(R.string.notOnDevice, name); } view.setText(name); @@ -234,8 +222,8 @@ public class DictionaryManagerActivity extends ListActivity { return tableLayout; } - } + Adapter adapter = new Adapter(); public static Intent getLaunchIntent() { final Intent intent = new Intent(); diff --git a/src/com/hughes/android/dictionary/DownloadActivity.java b/src/com/hughes/android/dictionary/DownloadActivity.java index 0ed8454..1e7a083 100644 --- a/src/com/hughes/android/dictionary/DownloadActivity.java +++ b/src/com/hughes/android/dictionary/DownloadActivity.java @@ -39,9 +39,11 @@ public class DownloadActivity extends Activity { public static final String SOURCE = "source"; public static final String DEST = "dest"; + public static final String MESSAGE = "message"; String source; String dest; + String message; long bytesProcessed = 0; long contentLength = -1; @@ -49,6 +51,15 @@ public class DownloadActivity extends Activity { private final Handler uiHandler = new Handler(); final AtomicBoolean stop = new AtomicBoolean(false); + + public static Intent getLaunchIntent(final String dictFile, final String source, final String dest, final String message) { + final Intent intent = new Intent(); + intent.setClassName(DownloadActivity.class.getPackage().getName(), DownloadActivity.class.getName()); + intent.putExtra(SOURCE, source); + intent.putExtra(DEST, dest); + intent.putExtra(MESSAGE, message); + return intent; + } /** Called when the activity is first created. */ @Override @@ -59,6 +70,7 @@ public class DownloadActivity extends Activity { final Intent intent = getIntent(); source = intent.getStringExtra(SOURCE); dest = intent.getStringExtra(DEST); + message = intent.getStringExtra(MESSAGE); if (source == null || dest == null) { throw new RuntimeException("null source or dest."); } diff --git a/src/com/hughes/android/dictionary/QuickDicConfig.java b/src/com/hughes/android/dictionary/QuickDicConfig.java index 4cdcbd3..e98f015 100644 --- a/src/com/hughes/android/dictionary/QuickDicConfig.java +++ b/src/com/hughes/android/dictionary/QuickDicConfig.java @@ -15,89 +15,31 @@ package com.hughes.android.dictionary; import java.io.BufferedReader; +import java.io.File; import java.io.IOException; import java.io.InputStreamReader; +import java.io.RandomAccessFile; import java.io.Serializable; import java.util.ArrayList; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; import android.content.Context; import android.os.Environment; +import android.util.Log; +import com.hughes.android.dictionary.engine.Dictionary; import com.hughes.android.dictionary.engine.Language; public final class QuickDicConfig implements Serializable { - private static final long serialVersionUID = 6711617368780900979L; + private static final String LOG = "QuickDicConfig"; - final List dictionaryInfos = new ArrayList(); - - public QuickDicConfig(final Context context) { - addDefaultDictionaries(context); - } - - public void addDefaultDictionaries(final Context context) { - for (final DictionaryInfo dictionaryInfo : getDefaultDictionaries(context).values()) { - addOrReplace(dictionaryInfo); - } - } + private static final long serialVersionUID = 6711617368780900979L; - private static Map defaultDictionaries = null; - public synchronized static Map getDefaultDictionaries(final Context context) { - if (defaultDictionaries != null) { - return defaultDictionaries; - } - - defaultDictionaries = new LinkedHashMap(); - - final BufferedReader reader = new BufferedReader(new InputStreamReader(context.getResources().openRawResource(R.raw.dictionary_info))); - String line; - try { - while ((line = reader.readLine()) != null) { - if (line.startsWith("#") || line.length() == 0) { - continue; - } - final DictionaryInfo dictionaryInfo = new DictionaryInfo(line); - String name = ""; - for (int i = 0; i < dictionaryInfo.indexInfos.size(); ++i) { - final Integer langCode = Language.isoCodeToResourceId.get(dictionaryInfo.indexInfos.get(i).langIso); - final String lang = langCode != null ? context.getString(langCode) : dictionaryInfo.indexInfos.get(i).langIso; - if (i > 0) { - name += "-"; - } - name += lang; - } - dictionaryInfo.name = name; - dictionaryInfo.localFile = Environment.getExternalStorageDirectory().getName() + "/quickdic/" + dictionaryInfo.uncompressedFilename; - defaultDictionaries.put(dictionaryInfo.localFile, dictionaryInfo); - } - } catch (IOException e) { - defaultDictionaries = null; - return new LinkedHashMap(); - } - - return defaultDictionaries; - } - - private void addOrReplace(final DictionaryInfo dictionaryConfig) { - for (int i = 0; i < dictionaryInfos.size(); ++i) { - if (dictionaryInfos.get(i).uncompressedFilename.equals(dictionaryConfig.uncompressedFilename)) { - dictionaryInfos.set(i, dictionaryConfig); - return; - } - } - dictionaryInfos.add(dictionaryConfig); - } - DictionaryInfo getDictionaryInfoByFile(final String dictFile) throws Exception { - for (int i = 0; i < dictionaryInfos.size(); ++i) { - if (dictionaryInfos.get(i).localFile.equals(dictFile)) { - return dictionaryInfos.get(i); - } - } - throw new Exception("Not found: " + dictFile); - } } diff --git a/src/com/hughes/android/dictionary/engine/Dictionary.java b/src/com/hughes/android/dictionary/engine/Dictionary.java index b00868e..245f138 100644 --- a/src/com/hughes/android/dictionary/engine/Dictionary.java +++ b/src/com/hughes/android/dictionary/engine/Dictionary.java @@ -14,6 +14,7 @@ package com.hughes.android.dictionary.engine; +import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.io.RandomAccessFile; @@ -31,7 +32,7 @@ public class Dictionary implements RAFSerializable { static final int CACHE_SIZE = 5000; - static final int CURRENT_DICT_VERSION = 2; + static final int CURRENT_DICT_VERSION = 3; static final String END_OF_DICTIONARY = "END OF DICTIONARY"; // persisted @@ -70,7 +71,7 @@ public class Dictionary implements RAFSerializable { dictInfo = raf.readUTF(); // Load the sources, then seek past them, because reading them later disrupts the offset. - final RAFList rafSources = RAFList.create(raf, EntrySource.SERIALIZER, raf.getFilePointer()); + final RAFList rafSources = RAFList.create(raf, new EntrySource.Serializer(this), raf.getFilePointer()); sources = new ArrayList(rafSources); raf.seek(rafSources.getEndOffset()); @@ -88,7 +89,7 @@ public class Dictionary implements RAFSerializable { raf.writeInt(dictFileVersion); raf.writeLong(creationMillis); raf.writeUTF(dictInfo); - RAFList.write(raf, sources, EntrySource.SERIALIZER); + RAFList.write(raf, sources, new EntrySource.Serializer(this)); RAFList.write(raf, pairEntries, new PairEntry.Serializer(this)); RAFList.write(raf, textEntries, new TextEntry.Serializer(this)); RAFList.write(raf, indices, indexSerializer); @@ -107,6 +108,10 @@ public class Dictionary implements RAFSerializable { public void print(final PrintStream out) { out.println("dictInfo=" + dictInfo); + for (final EntrySource entrySource : sources) { + out.printf("EntrySource: %s %d\n", entrySource.name, entrySource.numEntries); + } + out.println(); for (final Index index : indices) { out.printf("Index: %s %s\n", index.shortName, index.longName); index.print(out); @@ -123,6 +128,26 @@ public class Dictionary implements RAFSerializable { } return result; } - + + public static DictionaryInfo getDictionaryInfo(final File file) { + RandomAccessFile raf = null; + try { + raf = new RandomAccessFile(file, "r"); + final Dictionary dict = new Dictionary(raf); + final DictionaryInfo dictionaryInfo = dict.getDictionaryInfo(); + raf.close(); + return dictionaryInfo; + } catch (IOException e) { + return null; + } finally { + if (raf != null) { + try { + raf.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } } \ No newline at end of file diff --git a/src/com/hughes/android/dictionary/engine/EntrySource.java b/src/com/hughes/android/dictionary/engine/EntrySource.java index 80c4ebf..0911380 100644 --- a/src/com/hughes/android/dictionary/engine/EntrySource.java +++ b/src/com/hughes/android/dictionary/engine/EntrySource.java @@ -26,10 +26,12 @@ public class EntrySource extends IndexedObject implements Serializable { private static final long serialVersionUID = -1323165134846120269L; final String name; + int numEntries; - public EntrySource(final int index, final String name) { + public EntrySource(final int index, final String name, int numEntries) { super(index); this.name = name; + this.numEntries = numEntries; } @Override @@ -38,18 +40,26 @@ public class EntrySource extends IndexedObject implements Serializable { } - public static RAFListSerializer SERIALIZER = new RAFListSerializer() { + public static final class Serializer implements RAFListSerializer { + + final Dictionary dictionary; + + Serializer(Dictionary dictionary) { + this.dictionary = dictionary; + } @Override public EntrySource read(RandomAccessFile raf, int readIndex) throws IOException { final String name = raf.readUTF(); - return new EntrySource(readIndex, name); + final int numEntries = dictionary.dictFileVersion >= 3 ? raf.readInt() : 0; + return new EntrySource(readIndex, name, numEntries); } @Override public void write(RandomAccessFile raf, EntrySource t) throws IOException { raf.writeUTF(t.name); + raf.writeInt(t.numEntries); } }; diff --git a/src/com/hughes/android/dictionary/engine/Language.java b/src/com/hughes/android/dictionary/engine/Language.java index fe24d1f..90bc3b9 100644 --- a/src/com/hughes/android/dictionary/engine/Language.java +++ b/src/com/hughes/android/dictionary/engine/Language.java @@ -85,6 +85,7 @@ public class Language { isoCodeToResourceId.put("BO", R.string.BO); isoCodeToResourceId.put("TR", R.string.TR); isoCodeToResourceId.put("UK", R.string.UK); + isoCodeToResourceId.put("UR", R.string.UR); isoCodeToResourceId.put("VI", R.string.VI); isoCodeToResourceId.put("CI", R.string.CI); isoCodeToResourceId.put("YI", R.string.YI); diff --git a/src/com/hughes/android/dictionary/engine/TransliteratorManager.java b/src/com/hughes/android/dictionary/engine/TransliteratorManager.java index 4024c68..5bfe674 100644 --- a/src/com/hughes/android/dictionary/engine/TransliteratorManager.java +++ b/src/com/hughes/android/dictionary/engine/TransliteratorManager.java @@ -24,6 +24,7 @@ public class TransliteratorManager { private static boolean starting = false; private static boolean ready = false; + // Whom to notify when we're all set up and ready to go. private static List callbacks = new ArrayList(); public static synchronized boolean init(final Callback callback) { diff --git a/src/com/hughes/android/util/IntentLauncher.java b/src/com/hughes/android/util/IntentLauncher.java new file mode 100644 index 0000000..46e66a4 --- /dev/null +++ b/src/com/hughes/android/util/IntentLauncher.java @@ -0,0 +1,25 @@ +package com.hughes.android.util; + +import android.app.Activity; +import android.content.Intent; + +public class IntentLauncher { + + final Intent intent; + final Activity activity; + + private IntentLauncher(final Intent intent, final Activity activity) { + this.intent = intent; + this.activity = activity; + } + + private void go() { + if (activity != null) { + activity.finish(); + } + activity.startActivity(intent); + } + + + +}