X-Git-Url: http://gitweb.fperrin.net/?a=blobdiff_plain;f=src%2Fcom%2Fhughes%2Fandroid%2Fdictionary%2FDictionaryApplication.java;h=d36e99d718cdbfe77f7438b622668b6d89384132;hb=cbcff0e7ca442adc1064f60b56ff2e551243576f;hp=fc80df6d854a5d6d74f51003ded40933906bb2ad;hpb=2035f432745e7f1ba271a107c387664b307ca6cf;p=Dictionary.git diff --git a/src/com/hughes/android/dictionary/DictionaryApplication.java b/src/com/hughes/android/dictionary/DictionaryApplication.java index fc80df6..d36e99d 100644 --- a/src/com/hughes/android/dictionary/DictionaryApplication.java +++ b/src/com/hughes/android/dictionary/DictionaryApplication.java @@ -23,17 +23,14 @@ 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.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; -import android.os.Environment; import android.preference.PreferenceManager; import android.util.Log; import android.view.Menu; @@ -50,17 +47,15 @@ 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 = -1444177164708201262L; + private static final long serialVersionUID = -1444177164708201263L; // User-ordered list, persisted, just the ones that are/have been present. - final List dictionaryFilesOrdered = new ArrayList(); - final Set invalidatedFilenames = new LinkedHashSet(); + final List dictionaryFilesOrdered = new ArrayList(); + final Map dictionaryInfoCache = new LinkedHashMap(); } DictionaryConfig dictionaryConfig = null; @@ -70,6 +65,29 @@ public class DictionaryApplication extends Application { final List dictionaryLinks = new ArrayList(); } DictionaryHistory dictionaryHistory = null; + + private File dictDir; + + 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); + } + } @Override @@ -85,7 +103,6 @@ public class DictionaryApplication extends Application { dictionaryConfig = new DictionaryConfig(); } - // Theme stuff. setTheme(getSelectedTheme().themeId); final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); @@ -101,6 +118,49 @@ public class DictionaryApplication extends Application { }); } + public void onCreateGlobalOptionsMenu( + final Context context, final Menu menu) { + final MenuItem about = menu.add(getString(R.string.about)); + about.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(final MenuItem menuItem) { + final Intent intent = new Intent().setClassName(AboutActivity.class + .getPackage().getName(), AboutActivity.class.getCanonicalName()); + context.startActivity(intent); + return false; + } + }); + + final MenuItem help = menu.add(getString(R.string.help)); + help.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(final MenuItem menuItem) { + context.startActivity(HelpActivity.getLaunchIntent()); + return false; + } + }); + + final MenuItem preferences = menu.add(getString(R.string.preferences)); + preferences.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(final MenuItem menuItem) { + PreferenceActivity.prefsMightHaveChanged = true; + final Intent intent = new Intent().setClassName(PreferenceActivity.class + .getPackage().getName(), PreferenceActivity.class.getCanonicalName()); + context.startActivity(intent); + return false; + } + }); + } + + public synchronized File getDictDir() { + // This metaphore doesn't work, because we've already reset prefsMightHaveChanged. +// if (dictDir == null || PreferenceActivity.prefsMightHaveChanged) { + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + final String dir = prefs.getString(getString(R.string.quickdicDirectoryKey), getString(R.string.quickdicDirectoryDefault)); + dictDir = new File(dir); + dictDir.mkdirs(); +// } + return dictDir; + } + public C.Theme getSelectedTheme() { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); final String theme = prefs.getString(getString(R.string.themeKey), "themeLight"); @@ -111,60 +171,19 @@ public class DictionaryApplication extends Application { } } - 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); - } - } - public File getPath(String uncompressedFilename) { - return new File(DICT_DIR, uncompressedFilename); - } - - - public List getUsableDicts() { - final List result = new ArrayList(dictionaryConfig.dictionaryFilesOrdered.size()); - for (int i = 0; i < dictionaryConfig.dictionaryFilesOrdered.size(); ++i) { - DictionaryInfo dictionaryInfo = dictionaryConfig.dictionaryFilesOrdered.get(i); - if (dictionaryConfig.invalidatedFilenames.contains(dictionaryInfo.uncompressedFilename)) { - dictionaryInfo = Dictionary.getDictionaryInfo(getPath(dictionaryInfo.uncompressedFilename)); - if (dictionaryInfo != null) { - dictionaryConfig.dictionaryFilesOrdered.set(i, dictionaryInfo); - } - } - if (dictionaryInfo != null) { - result.add(dictionaryInfo); - } - } - if (!dictionaryConfig.invalidatedFilenames.isEmpty()) { - dictionaryConfig.invalidatedFilenames.clear(); - PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS, dictionaryConfig); - } - return result; + return new File(getDictDir(), uncompressedFilename); } + + final Map fileToNameCache = new LinkedHashMap(); + public String getLanguageName(final String isoCode) { final Language.LanguageResources languageResources = Language.isoCodeToResources.get(isoCode); final String lang = languageResources != null ? getApplicationContext().getString(languageResources.nameId) : isoCode; return lang; } - final Map fileToNameCache = new LinkedHashMap(); public synchronized String getDictionaryName(final String uncompressedFilename) { String name = fileToNameCache.get(uncompressedFilename); if (name != null) { @@ -188,81 +207,121 @@ public class DictionaryApplication extends Application { return name; } - public void moveDictionaryToTop(final DictionaryInfo dictionaryInfo) { - dictionaryConfig.dictionaryFilesOrdered.remove(dictionaryInfo); - dictionaryConfig.dictionaryFilesOrdered.add(0, dictionaryInfo); + public synchronized void moveDictionaryToTop(final DictionaryInfo dictionaryInfo) { + dictionaryConfig.dictionaryFilesOrdered.remove(dictionaryInfo.uncompressedFilename); + dictionaryConfig.dictionaryFilesOrdered.add(0, dictionaryInfo.uncompressedFilename); PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS, dictionaryConfig); } - public void deleteDictionary(final DictionaryInfo dictionaryInfo) { - while (dictionaryConfig.dictionaryFilesOrdered.remove(dictionaryInfo)) {}; + public synchronized void deleteDictionary(final DictionaryInfo dictionaryInfo) { + while (dictionaryConfig.dictionaryFilesOrdered.remove(dictionaryInfo.uncompressedFilename)) {}; + dictionaryConfig.dictionaryInfoCache.remove(dictionaryInfo.uncompressedFilename); getPath(dictionaryInfo.uncompressedFilename).delete(); PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS, dictionaryConfig); } final Collator collator = Collator.getInstance(); - final Comparator comparator = new Comparator() { + final Comparator uncompressedFilenameComparator = new Comparator() { @Override - public int compare(DictionaryInfo object1, DictionaryInfo object2) { - return collator.compare(getDictionaryName(object1.uncompressedFilename), getDictionaryName(object2.uncompressedFilename)); + public int compare(String uncompressedFilename1, String uncompressedFilename2) { + return collator.compare(getDictionaryName(uncompressedFilename1), getDictionaryName(uncompressedFilename2)); } }; - - 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); - } - if (!dictionaryConfig.invalidatedFilenames.isEmpty()) { - dictionaryConfig.invalidatedFilenames.clear(); + final Comparator dictionaryInfoComparator = new Comparator() { + @Override + public int compare(DictionaryInfo d1, DictionaryInfo d2) { + return uncompressedFilenameComparator.compare(d1.uncompressedFilename, d2.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. - final List toAddSorted = new ArrayList(); - final File[] dictDirFiles = DICT_DIR.listFiles(); - for (final File file : dictDirFiles) { - // TODO: delete zip files here. - 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; + }; + + public void backgroundUpdateDictionaries(final Runnable onUpdateFinished) { + new Thread(new Runnable() { + @Override + public void run() { + final DictionaryConfig oldDictionaryConfig = new DictionaryConfig(); + synchronized(this) { + oldDictionaryConfig.dictionaryFilesOrdered.addAll(dictionaryConfig.dictionaryFilesOrdered); + } + final DictionaryConfig newDictionaryConfig = new DictionaryConfig(); + for (final String uncompressedFilename : oldDictionaryConfig.dictionaryFilesOrdered) { + final File dictFile = getPath(uncompressedFilename); + final DictionaryInfo dictionaryInfo = Dictionary.getDictionaryInfo(dictFile); + if (dictionaryInfo != null) { + newDictionaryConfig.dictionaryFilesOrdered.add(uncompressedFilename); + newDictionaryConfig.dictionaryInfoCache.put(uncompressedFilename, dictionaryInfo); + } + } + + // 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. + final List toAddSorted = new ArrayList(); + final File[] dictDirFiles = getDictDir().listFiles(); + for (final File file : dictDirFiles) { + if (file.getName().endsWith(".zip")) { + if (DOWNLOADABLE_NAME_TO_INFO.containsKey(file.getName().replace(".zip", ""))) { + file.delete(); + } + } + if (!file.getName().endsWith(".quickdic")) { + continue; + } + if (newDictionaryConfig.dictionaryInfoCache.containsKey(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; + } + + toAddSorted.add(file.getName()); + newDictionaryConfig.dictionaryInfoCache.put(file.getName(), dictionaryInfo); + } + if (!toAddSorted.isEmpty()) { + Collections.sort(toAddSorted, uncompressedFilenameComparator); + newDictionaryConfig.dictionaryFilesOrdered.addAll(toAddSorted); + } + + PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS, newDictionaryConfig); + synchronized (this) { + dictionaryConfig = newDictionaryConfig; + } + + try { + onUpdateFinished.run(); + } catch (Exception e) { + Log.e(LOG, "Exception running callback.", e); + } + }}).start(); + } + + public synchronized List getUsableDicts() { + final List result = new ArrayList(dictionaryConfig.dictionaryFilesOrdered.size()); + for (final String uncompressedFilename : dictionaryConfig.dictionaryFilesOrdered) { + final DictionaryInfo dictionaryInfo = dictionaryConfig.dictionaryInfoCache.get(uncompressedFilename); + if (dictionaryInfo != null) { + result.add(dictionaryInfo); } - known.add(file.getName()); - toAddSorted.add(dictionaryInfo); - } - if (!toAddSorted.isEmpty()) { - Collections.sort(toAddSorted, comparator); - result.addAll(toAddSorted); -// for (final DictionaryInfo dictionaryInfo : toAddSorted) { -// dictionaryConfig.dictionaryFilesOrdered.add(dictionaryInfo.uncompressedFilename); -// } - dictionaryConfig.dictionaryFilesOrdered.addAll(toAddSorted); - PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS, dictionaryConfig); } + return result; + } + public synchronized List getAllDictionaries() { + final List result = getUsableDicts(); + // The downloadable ones. final Map remaining = new LinkedHashMap(DOWNLOADABLE_NAME_TO_INFO); - remaining.keySet().removeAll(known); - toAddSorted.clear(); - toAddSorted.addAll(remaining.values()); - Collections.sort(toAddSorted, comparator); + remaining.keySet().removeAll(dictionaryConfig.dictionaryFilesOrdered); + final List toAddSorted = new ArrayList(remaining.values()); + Collections.sort(toAddSorted, dictionaryInfoComparator); result.addAll(toAddSorted); + return result; } - public boolean isDictionaryOnDevice(String uncompressedFilename) { - return getPath(uncompressedFilename).canRead(); + public synchronized boolean isDictionaryOnDevice(String uncompressedFilename) { + return dictionaryConfig.dictionaryInfoCache.get(uncompressedFilename) != null; } public boolean updateAvailable(final DictionaryInfo dictionaryInfo) { @@ -275,41 +334,4 @@ public class DictionaryApplication extends Application { return downloadable; } - public void invalidateDictionaryInfo(final String uncompressedFilename) { - dictionaryConfig.invalidatedFilenames.add(uncompressedFilename); - PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS, dictionaryConfig); - } - - public void onCreateGlobalOptionsMenu( - final Context context, final Menu menu) { - final MenuItem about = menu.add(getString(R.string.about)); - about.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(final MenuItem menuItem) { - final Intent intent = new Intent().setClassName(AboutActivity.class - .getPackage().getName(), AboutActivity.class.getCanonicalName()); - context.startActivity(intent); - return false; - } - }); - - final MenuItem help = menu.add(getString(R.string.help)); - help.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(final MenuItem menuItem) { - context.startActivity(HelpActivity.getLaunchIntent()); - return false; - } - }); - - final MenuItem preferences = menu.add(getString(R.string.preferences)); - preferences.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(final MenuItem menuItem) { - PreferenceActivity.prefsMightHaveChanged = true; - final Intent intent = new Intent().setClassName(PreferenceActivity.class - .getPackage().getName(), PreferenceActivity.class.getCanonicalName()); - context.startActivity(intent); - return false; - } - }); - } - }