]> gitweb.fperrin.net Git - Dictionary.git/commitdiff
Major refactor of down dictionary list is stored by app.
authorThad Hughes <thad.hughes@gmail.com>
Tue, 24 Jan 2012 05:32:38 +0000 (21:32 -0800)
committerThad Hughes <thad.hughes@gmail.com>
Tue, 24 Jan 2012 05:32:38 +0000 (21:32 -0800)
19 files changed:
images/michael_vogel_icon_48x48.png [new file with mode: 0644]
images/q114x114.png [new file with mode: 0644]
images/q128x128.png [new file with mode: 0644]
images/q512x512.png [new file with mode: 0644]
res/layout/download_activity.xml
res/values/languages.xml
res/values/strings.xml
src/com/hughes/android/dictionary/DictionaryActivity.java
src/com/hughes/android/dictionary/DictionaryApplication.java
src/com/hughes/android/dictionary/DictionaryEditActivity.java [deleted file]
src/com/hughes/android/dictionary/DictionaryInfo.java
src/com/hughes/android/dictionary/DictionaryManagerActivity.java
src/com/hughes/android/dictionary/DownloadActivity.java
src/com/hughes/android/dictionary/QuickDicConfig.java
src/com/hughes/android/dictionary/engine/Dictionary.java
src/com/hughes/android/dictionary/engine/EntrySource.java
src/com/hughes/android/dictionary/engine/Language.java
src/com/hughes/android/dictionary/engine/TransliteratorManager.java
src/com/hughes/android/util/IntentLauncher.java [new file with mode: 0644]

diff --git a/images/michael_vogel_icon_48x48.png b/images/michael_vogel_icon_48x48.png
new file mode 100644 (file)
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 (file)
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 (file)
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 (file)
index 0000000..767ad26
Binary files /dev/null and b/images/q512x512.png differ
index 2ed5a649ae23d2c456aa48ce0125b85345744c02..13457b81c0f7c4cc23cd87858a2390db46c37e63 100755 (executable)
@@ -27,6 +27,9 @@
     android:max="100" android:progress="50"
                android:layout_width="fill_parent" android:layout_height="wrap_content" android:indeterminate="false"/>
 
+  <TextView android:id="@+id/downloadMessage" android:layout_width="wrap_content"
+    android:layout_height="wrap_content" android:visibility="visible" android:text="Download message."/>
        <TextView android:id="@+id/downloadStatus" android:layout_width="wrap_content"
                android:layout_height="wrap_content" android:visibility="visible" android:text="Download status."/>
 
index 80b2fcb144d8c3d85b34292ed1a02daeed0e6a6d..28bc91b3722d7a8212dc19fc69f85791ee295e32 100644 (file)
@@ -59,6 +59,7 @@
   <string name="BO">Tibetan</string>
   <string name="TR">Turkish</string>
   <string name="UK">Ukrainian</string>
+  <string name="UR">Urdu</string>
   <string name="VI">Vietnamese</string>
   <string name="CI">Welsh</string>
   <string name="YI">Yiddish</string>
index bd3925583e85ea74a0a7c68d0cb88c0b131dfc64..4ccaafa16b1b804f20058ae7b6eeb0b3f7882865 100644 (file)
   <string name="downloadButton">Download</string>
   <string name="openButton">Open</string>
   <string name="dictionaryInfo">Dictionary info:</string>
+  <string name="indexInfo">Index %1$s, %2$d words</string>
   <string name="localFile">Dictionary file</string>
   <string name="wordListFile">Word list file</string>
   <string name="fileNotFound">File not found: \'%s\'</string>
   <string name="invalidDictionary">Invalid dictionary: file=%1$s, error=%2$s</string>
   <string name="numPairEntries">Entries: %,d</string>
-  <string name="numTokens">Tokens: %,d</string>
-  <string name="numRows">Rows: %,d</string>
 
  
        <!-- Main -->
index d6ec791fc9a214e9c85caa608d26147dce285e2a..6c69e9b5be350ebd98a2e182e1aee69a20b1af71 100644 (file)
@@ -20,7 +20,6 @@ import java.io.IOException;
 import java.io.PrintWriter;\r
 import java.io.RandomAccessFile;\r
 import java.text.SimpleDateFormat;\r
-import java.util.ArrayList;\r
 import java.util.Date;\r
 import java.util.List;\r
 import java.util.concurrent.Executor;\r
@@ -81,7 +80,6 @@ import com.hughes.android.dictionary.engine.PairEntry.Pair;
 import com.hughes.android.dictionary.engine.RowBase;\r
 import com.hughes.android.dictionary.engine.TokenRow;\r
 import com.hughes.android.dictionary.engine.TransliteratorManager;\r
-import com.hughes.android.util.PersistentObjectCache;\r
 \r
 public class DictionaryActivity extends ListActivity {\r
 \r
@@ -132,16 +130,25 @@ public class DictionaryActivity extends ListActivity {
     return intent;\r
   }\r
   \r
-  // TODO: fix these...\r
-\r
   @Override\r
   protected void onSaveInstanceState(final Bundle outState) {\r
     super.onSaveInstanceState(outState);\r
     outState.putString(C.SEARCH_TOKEN, searchText.getText().toString());\r
   }\r
+\r
+  @Override\r
+  protected void onRestoreInstanceState(final Bundle outState) {\r
+    super.onRestoreInstanceState(outState);\r
+    setSearchText(outState.getString(C.SEARCH_TOKEN));\r
+  }\r
+\r
+  public DictionaryApplication getDictionaryApplication() {\r
+    return (DictionaryApplication) super.getApplication();\r
+  }\r
   \r
   @Override\r
   public void onCreate(Bundle savedInstanceState) {\r
+    // Clear them so that if something goes wrong, we won't relaunch.\r
     clearDictionaryPrefs(this);\r
     \r
     Log.d(LOG, "onCreate:" + this);\r
@@ -152,12 +159,9 @@ public class DictionaryActivity extends ListActivity {
     dictFile = intent.getStringExtra(C.DICT_FILE);\r
 \r
     try {\r
-      PersistentObjectCache.init(this);\r
-      QuickDicConfig quickDicConfig = PersistentObjectCache.init(\r
-          this).read(C.DICTIONARY_CONFIGS, QuickDicConfig.class);\r
-      final DictionaryInfo dictionaryConfig = quickDicConfig.getDictionaryInfoByFile(dictFile);\r
-      this.setTitle("QuickDic: " + dictionaryConfig.name);\r
-      dictRaf = new RandomAccessFile(dictionaryConfig.localFile, "r");\r
+      final String name = getDictionaryApplication().getDictionaryName(dictFile);\r
+      this.setTitle("QuickDic: " + name);\r
+      dictRaf = new RandomAccessFile(dictFile, "r");\r
       dictionary = new Dictionary(dictRaf); \r
     } catch (Exception e) {\r
       Log.e(LOG, "Unable to load dictionary.", e);\r
@@ -170,7 +174,7 @@ public class DictionaryActivity extends ListActivity {
         dictRaf = null;\r
       }\r
       Toast.makeText(this, getString(R.string.invalidDictionary, "", e.getMessage()), Toast.LENGTH_LONG);\r
-      startActivity(DictionaryEditActivity.getLaunchIntent(dictFile));\r
+      startActivity(DictionaryManagerActivity.getLaunchIntent());\r
       finish();\r
       return;\r
     }\r
@@ -427,21 +431,16 @@ public class DictionaryActivity extends ListActivity {
     dialog.setTitle(R.string.selectADictionary);\r
 \r
     ListView listView = (ListView) dialog.findViewById(android.R.id.list);\r
+    \r
+    final List<DictionaryInfo> installedDicts = ((DictionaryApplication)getApplication()).getUsableDicts();\r
 \r
-    QuickDicConfig quickDicConfig = PersistentObjectCache.init(\r
-        this).read(C.DICTIONARY_CONFIGS, QuickDicConfig.class);\r
-    final List<DictionaryInfo> dictionaryInfos = new ArrayList<DictionaryInfo>();\r
-    for (final DictionaryInfo dictionaryInfo : quickDicConfig.dictionaryInfos) {\r
-      if (new File(dictionaryInfo.localFile).canRead()) {\r
-        dictionaryInfos.add(dictionaryInfo);\r
-      }\r
-    }\r
     listView.setAdapter(new BaseAdapter() {\r
       \r
       @Override\r
       public View getView(int position, View convertView, ViewGroup parent) {\r
         final LinearLayout result = new LinearLayout(parent.getContext());\r
         //result.addView(new Butt)\r
+        // TODO: me\r
         return result;\r
       }\r
       \r
@@ -451,13 +450,13 @@ public class DictionaryActivity extends ListActivity {
       }\r
       \r
       @Override\r
-      public Object getItem(int position) {\r
-        return dictionaryInfos.get(position);\r
+      public DictionaryInfo getItem(int position) {\r
+        return installedDicts.get(position);\r
       }\r
       \r
       @Override\r
       public int getCount() {\r
-        return dictionaryInfos.size();\r
+        return installedDicts.size();\r
       }\r
     });\r
   }\r
index d7109a062cc39d8376c155ce939e9f8439ecd839..a16ad0e163dafa3112ce9c8740af40a97f373461 100644 (file)
 
 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<String,DictionaryInfo> 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<String> dictionaryFiles = new ArrayList<String>();
+  }
+  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<String,DictionaryInfo>();
+    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<DictionaryInfo> getUsableDicts() {
+    final List<DictionaryInfo> result = new ArrayList<DictionaryInfo>(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<String, String> fileToNameCache = new LinkedHashMap<String, String>();
+  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<DictionaryInfo> getAllDictionaries() {
+    final List<DictionaryInfo> result = getUsableDicts();
+    
+    // The ones we knew about...
+    final Set<String> known = new LinkedHashSet<String>();
+    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<String,DictionaryInfo> remaining = new LinkedHashMap<String, DictionaryInfo>(DOWNLOADABLE_NAME_TO_INFO);
+    remaining.keySet().removeAll(known);
+    final List<DictionaryInfo> remainingSorted = new ArrayList<DictionaryInfo>(remaining.values());
+    final Collator collator = Collator.getInstance();
+    Collections.sort(remainingSorted, new Comparator<DictionaryInfo>() {
+      @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 (file)
index 499feb2..0000000
+++ /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);
-  }
-  
-}
index 6759e32e4809b043498da3bf28b14db4d041642d..a291dc092824f2a29898460e22b39a738127a668 100644 (file)
@@ -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<IndexInfo> indexInfos = new ArrayList<DictionaryInfo.IndexInfo>();
   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;
   }
 
 
index bd41943ef12d086018b37e3ecba0095226290633..d5ac87eb18f16d07054bb9022f934b87520cb5c3 100644 (file)
@@ -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<DictionaryInfo> 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();
index 0ed845417a8c4f180785327d356568f2b159d03a..1e7a083e2b1fb3b7a2950457fe9c486f4f16af57 100644 (file)
@@ -39,9 +39,11 @@ public class DownloadActivity extends Activity {
 \r
   public static final String SOURCE = "source";\r
   public static final String DEST = "dest";\r
+  public static final String MESSAGE = "message";\r
 \r
   String source;\r
   String dest;\r
+  String message;\r
   long bytesProcessed = 0;\r
   long contentLength = -1;\r
 \r
@@ -49,6 +51,15 @@ public class DownloadActivity extends Activity {
   private final Handler uiHandler = new Handler();\r
 \r
   final AtomicBoolean stop = new AtomicBoolean(false);\r
+  \r
+  public static Intent getLaunchIntent(final String dictFile, final String source, final String dest, final String message) {\r
+    final Intent intent = new Intent();\r
+    intent.setClassName(DownloadActivity.class.getPackage().getName(), DownloadActivity.class.getName());\r
+    intent.putExtra(SOURCE, source);\r
+    intent.putExtra(DEST, dest);\r
+    intent.putExtra(MESSAGE, message);\r
+    return intent;\r
+  }\r
 \r
   /** Called when the activity is first created. */\r
   @Override\r
@@ -59,6 +70,7 @@ public class DownloadActivity extends Activity {
     final Intent intent = getIntent();\r
     source = intent.getStringExtra(SOURCE);\r
     dest = intent.getStringExtra(DEST);\r
+    message = intent.getStringExtra(MESSAGE);\r
     if (source == null || dest == null) {\r
       throw new RuntimeException("null source or dest.");\r
     }\r
index 4cdcbd38ae2f9ddbc7c43cbea4f9df08a5e0a5a2..e98f0152ba2f721e303b8c3946ea3cc97ded0903 100644 (file)
 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<DictionaryInfo> dictionaryInfos = new ArrayList<DictionaryInfo>();
-  
-  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<String,DictionaryInfo> defaultDictionaries = null;
-  public synchronized static Map<String,DictionaryInfo> getDefaultDictionaries(final Context context) {
-    if (defaultDictionaries != null) {
-      return defaultDictionaries;
-    }
-    
-    defaultDictionaries = new LinkedHashMap<String, DictionaryInfo>();
-    
-    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<String, DictionaryInfo>();
-    }
-    
-    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);
-  }
 
 }
index b00868ecb8c1d43c95626ccbc4c31b70fdf88ad6..245f138a6f5a7c60645d1be2ec0b9dc4049c7bf5 100644 (file)
@@ -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<Dictionary> {
   
   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<Dictionary> {
     dictInfo = raf.readUTF();
     
     // Load the sources, then seek past them, because reading them later disrupts the offset.
-    final RAFList<EntrySource> rafSources = RAFList.create(raf, EntrySource.SERIALIZER, raf.getFilePointer());
+    final RAFList<EntrySource> rafSources = RAFList.create(raf, new EntrySource.Serializer(this), raf.getFilePointer());
     sources = new ArrayList<EntrySource>(rafSources);
     raf.seek(rafSources.getEndOffset());
     
@@ -88,7 +89,7 @@ public class Dictionary implements RAFSerializable<Dictionary> {
     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<Dictionary> {
     
     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<Dictionary> {
       }
       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
index 80c4ebf8fe290d8b04871fa827259114e4da4e4f..091138088ebfe27db0fc4b2c338597236da4d20b 100644 (file)
@@ -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<EntrySource> SERIALIZER = new RAFListSerializer<EntrySource>() {
+  public static final class Serializer implements RAFListSerializer<EntrySource> {
+    
+    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);
     }    
   };
   
index fe24d1f77940d7556be5102d85fd35273029971f..90bc3b947ab57197fa4aadb23f59aeeb49f97cbe 100644 (file)
@@ -85,6 +85,7 @@ public class Language {
     isoCodeToResourceId.put("BO", R.string.BO);\r
     isoCodeToResourceId.put("TR", R.string.TR);\r
     isoCodeToResourceId.put("UK", R.string.UK);\r
+    isoCodeToResourceId.put("UR", R.string.UR);\r
     isoCodeToResourceId.put("VI", R.string.VI);\r
     isoCodeToResourceId.put("CI", R.string.CI);\r
     isoCodeToResourceId.put("YI", R.string.YI);\r
index 4024c681ab7df2c57208e82539b373fbf187c99a..5bfe674e438a1c6c4e27db0ee2c9573f0554723b 100644 (file)
@@ -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<Callback> callbacks = new ArrayList<TransliteratorManager.Callback>();
   
   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 (file)
index 0000000..46e66a4
--- /dev/null
@@ -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);
+  }
+  
+  
+
+}