Add language filter in dictionary list
CHANGELOG.md
1 | 1 | Changelog | |
2 | 2 | ========= | |
3 | 3 | ||
4 | + | Changes in next version | |
5 | + | ----------------------- | |
6 | + | ||
7 | + | Here is a list of changes that are not yet part of a release, but that will | |
8 | + | appear in next release. | |
9 | + | ||
10 | + | ### Features | |
11 | + | ||
12 | + | * It is now possible to filter the list of dictionaries by target language. | |
13 | + | ||
4 | 14 | Changes in 0.3.2.1 | |
5 | 15 | ------------------ | |
6 | 16 |
app/src/main/java/eu/lepiller/nani/DictionaryActivity.java
12 | 12 | import android.util.Log; | |
13 | 13 | import android.view.View; | |
14 | 14 | import android.widget.AdapterView; | |
15 | + | import android.widget.ArrayAdapter; | |
15 | 16 | import android.widget.ListView; | |
17 | + | import android.widget.ScrollView; | |
18 | + | import android.widget.Spinner; | |
16 | 19 | ||
17 | 20 | import com.google.android.material.snackbar.Snackbar; | |
18 | 21 | ||
… | |||
24 | 27 | import java.net.MalformedURLException; | |
25 | 28 | import java.net.URL; | |
26 | 29 | import java.util.ArrayList; | |
30 | + | import java.util.List; | |
27 | 31 | ||
28 | 32 | import eu.lepiller.nani.dictionary.DictionariesAdapter; | |
29 | 33 | import eu.lepiller.nani.dictionary.DictionaryFactory; | |
… | |||
33 | 37 | static final int DICO_REQUEST = 1; | |
34 | 38 | static final String TAG = "DICO_LIST"; | |
35 | 39 | DictionariesAdapter adapter; | |
40 | + | ArrayAdapter<String> langAdapter; | |
36 | 41 | ArrayList<Dictionary> dictionaries; | |
42 | + | List<String> langs; | |
43 | + | String selectedLanguage = ""; | |
37 | 44 | private SwipeRefreshLayout refresher; | |
38 | 45 | ||
39 | 46 | @Override | |
… | |||
41 | 48 | super.onCreate(savedInstanceState); | |
42 | 49 | setContentView(R.layout.activity_dictionary); | |
43 | 50 | ||
51 | + | final Spinner lang_view = findViewById(R.id.lang_view); | |
44 | 52 | final ListView list_view = findViewById(R.id.dictionary_view); | |
45 | 53 | refresher = findViewById(R.id.dictionary_refresh_layout); | |
46 | 54 | ||
47 | - | dictionaries = DictionaryFactory.getDictionaries(getApplicationContext()); | |
55 | + | dictionaries = new ArrayList<>(); | |
56 | + | dictionaries.addAll(DictionaryFactory.getDictionaries(getApplicationContext())); | |
57 | + | ||
58 | + | langs = new ArrayList<>(); | |
59 | + | langs.add(getString(R.string.all_langs)); | |
60 | + | langs.addAll(DictionaryFactory.getLangs(getApplicationContext())); | |
61 | + | ||
48 | 62 | adapter = new DictionariesAdapter(this, dictionaries); | |
49 | 63 | list_view.setAdapter(adapter); | |
50 | 64 | ||
65 | + | langAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, langs); | |
66 | + | langAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); | |
67 | + | lang_view.setAdapter(langAdapter); | |
68 | + | ||
51 | 69 | if(dictionaries.size() == 0) { | |
52 | 70 | Snackbar.make(findViewById(R.id.dictionary_view), getString(R.string.no_dico_list), | |
53 | 71 | Snackbar.LENGTH_LONG).show(); | |
… | |||
62 | 80 | startActivityForResult(intent, DICO_REQUEST); | |
63 | 81 | } | |
64 | 82 | }); | |
83 | + | ||
84 | + | lang_view.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { | |
85 | + | @Override | |
86 | + | public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { | |
87 | + | if(position == 0) | |
88 | + | selectedLanguage = ""; | |
89 | + | else | |
90 | + | selectedLanguage = parent.getItemAtPosition(position).toString(); | |
91 | + | updateDataSet(); | |
92 | + | } | |
93 | + | ||
94 | + | @Override | |
95 | + | public void onNothingSelected(AdapterView<?> parent) { | |
96 | + | selectedLanguage = ""; | |
97 | + | updateDataSet(); | |
98 | + | } | |
99 | + | }); | |
65 | 100 | } | |
66 | 101 | ||
67 | 102 | @Override | |
… | |||
158 | 193 | private void updateDataSet() { | |
159 | 194 | DictionaryFactory.updatePackageList(); | |
160 | 195 | dictionaries.clear(); | |
161 | - | dictionaries.addAll(DictionaryFactory.getDictionaries(getApplicationContext())); | |
196 | + | dictionaries.addAll(DictionaryFactory.getDictionaries(getApplicationContext(), selectedLanguage)); | |
197 | + | langs.clear(); | |
198 | + | langs.add(getString(R.string.all_langs)); | |
199 | + | langs.addAll(DictionaryFactory.getLangs(getApplicationContext())); | |
162 | 200 | adapter.notifyDataSetChanged(); | |
201 | + | langAdapter.notifyDataSetChanged(); | |
163 | 202 | } | |
164 | 203 | ||
165 | 204 | @Override |
app/src/main/java/eu/lepiller/nani/dictionary/Dictionary.java
22 | 22 | ||
23 | 23 | abstract public class Dictionary { | |
24 | 24 | private String name; | |
25 | - | private String description, fullDescription; | |
25 | + | private String description, fullDescription, lang; | |
26 | 26 | private int expectedFileSize; | |
27 | 27 | private int expectedEntries; | |
28 | 28 | private String sha256; | |
… | |||
30 | 30 | ||
31 | 31 | private Drawable drawable=null, newDrawable=null; | |
32 | 32 | ||
33 | - | Dictionary(String name, String description, String fullDescription, File cacheDir, int fileSize, int entries, String hash) { | |
33 | + | Dictionary(String name, String description, String fullDescription, File cacheDir, int fileSize, int entries, String hash, String lang) { | |
34 | 34 | this.name = name; | |
35 | 35 | this.description = description; | |
36 | 36 | this.fullDescription = fullDescription; | |
37 | 37 | expectedEntries = entries; | |
38 | 38 | expectedFileSize = fileSize; | |
39 | 39 | sha256 = hash; | |
40 | + | this.lang = lang; | |
40 | 41 | this.file = new File(cacheDir, "/dico/" + name); | |
41 | 42 | this.temporaryFile = new File(cacheDir, "/tmp/" + name); | |
42 | 43 | } | |
… | |||
59 | 60 | String getSha256() { | |
60 | 61 | return sha256; | |
61 | 62 | } | |
63 | + | String getLang() { | |
64 | + | return lang; | |
65 | + | } | |
62 | 66 | abstract public boolean canUpdate(); | |
63 | 67 | ||
64 | 68 | File getFile() { |
app/src/main/java/eu/lepiller/nani/dictionary/DictionaryFactory.java
13 | 13 | import java.net.MalformedURLException; | |
14 | 14 | import java.net.URL; | |
15 | 15 | import java.util.ArrayList; | |
16 | + | import java.util.Collections; | |
16 | 17 | import java.util.HashMap; | |
17 | 18 | import java.util.List; | |
18 | 19 | import java.util.Locale; | |
… | |||
66 | 67 | return null; | |
67 | 68 | } | |
68 | 69 | ||
70 | + | public static List<String> getLangs(Context context) { | |
71 | + | List<String> langs = new ArrayList<>(); | |
72 | + | for(Dictionary d: getDictionaries(context)) { | |
73 | + | if(d.getLang().compareTo("") == 0) | |
74 | + | continue; | |
75 | + | if(langs.contains(d.getLang())) | |
76 | + | continue; | |
77 | + | langs.add(d.getLang()); | |
78 | + | } | |
79 | + | Collections.sort(langs); | |
80 | + | return langs; | |
81 | + | } | |
82 | + | ||
69 | 83 | public static void updatePackageList() { | |
70 | 84 | dictionaries = new ArrayList<>(); | |
71 | 85 | if(listFile.exists()) { | |
… | |||
83 | 97 | String name = ""; | |
84 | 98 | int current = LIST_PARSER_NONE; | |
85 | 99 | String currentLanguage = ""; | |
100 | + | String lang = ""; | |
86 | 101 | ||
87 | 102 | Dictionary d; | |
88 | 103 | while((line = br.readLine()) != null) { | |
… | |||
92 | 107 | d = new RadicalDict(name, | |
93 | 108 | chooseLanguage(synopsis), | |
94 | 109 | chooseLanguage(description), | |
95 | - | cacheDir, url, size, entries, sha256); | |
110 | + | cacheDir, url, size, entries, sha256, lang); | |
96 | 111 | Log.d("FACTORY", "radk: " + (d.isDownloaded()? "downloaded": "not downloaded")); | |
97 | 112 | } else if (type.compareTo("jmdict") == 0) { | |
98 | 113 | d = new JMDict(name, | |
99 | 114 | chooseLanguage(synopsis), | |
100 | 115 | chooseLanguage(description), | |
101 | - | cacheDir, url, size, entries, sha256); | |
116 | + | cacheDir, url, size, entries, sha256, lang); | |
102 | 117 | } else if (type.compareTo("wadoku") == 0) { | |
103 | 118 | d = new WadokuResultDictionary(name, | |
104 | 119 | chooseLanguage(synopsis), | |
105 | 120 | chooseLanguage(description), | |
106 | - | cacheDir, url, size, entries, sha256); | |
121 | + | cacheDir, url, size, entries, sha256, lang); | |
107 | 122 | } else if (type.compareTo("jibiki") == 0) { | |
108 | 123 | d = new Jibiki(name, | |
109 | 124 | chooseLanguage(synopsis), | |
110 | 125 | chooseLanguage(description), | |
111 | - | cacheDir, url, size, entries, sha256); | |
126 | + | cacheDir, url, size, entries, sha256, lang); | |
112 | 127 | } else if (type.compareTo("wadoku_pitch") == 0) { | |
113 | 128 | d = new WadokuPitchDictionary(name, | |
114 | 129 | chooseLanguage(synopsis), | |
115 | 130 | chooseLanguage(description), | |
116 | - | cacheDir, url, size, entries, sha256); | |
131 | + | cacheDir, url, size, entries, sha256, lang); | |
117 | 132 | } else { | |
118 | 133 | continue; | |
119 | 134 | } | |
… | |||
169 | 184 | url = line.substring(4); | |
170 | 185 | } else if(line.startsWith("size=")) { | |
171 | 186 | size = Integer.parseInt(line.substring(5)); | |
187 | + | } else if(line.startsWith("lang=")) { | |
188 | + | lang = line.substring(5); | |
172 | 189 | } else if(line.startsWith("entries=")) { | |
173 | 190 | entries = Integer.parseInt(line.substring(8)); | |
174 | 191 | } | |
… | |||
255 | 272 | return dictionaries; | |
256 | 273 | } | |
257 | 274 | ||
275 | + | public static ArrayList<Dictionary> getDictionaries(Context context, String langFilter) { | |
276 | + | if(instance == null) | |
277 | + | instance = new DictionaryFactory(context); | |
278 | + | ||
279 | + | if(langFilter.compareTo("") == 0) | |
280 | + | return dictionaries; | |
281 | + | ||
282 | + | ArrayList<Dictionary> dicos = new ArrayList<>(); | |
283 | + | for(Dictionary d: dictionaries) { | |
284 | + | if(d.getLang().compareTo("") == 0 || d.getLang().compareTo(langFilter) == 0) | |
285 | + | dicos.add(d); | |
286 | + | } | |
287 | + | return dicos; | |
288 | + | } | |
289 | + | ||
258 | 290 | public static RadicalDict getRadicalDictionary(Context context) throws NoDictionaryException { | |
259 | 291 | if(instance == null) | |
260 | 292 | instance = new DictionaryFactory(context); |
app/src/main/java/eu/lepiller/nani/dictionary/FileDictionary.java
40 | 40 | private final static String TAG = "FileDictionary"; | |
41 | 41 | ||
42 | 42 | FileDictionary(String name, String description, String fullDescription, File cacheDir, String url, | |
43 | - | int fileSize, int entries, String hash) { | |
44 | - | super(name, description, fullDescription, cacheDir, fileSize, entries, hash); | |
43 | + | int fileSize, int entries, String hash, String lang) { | |
44 | + | super(name, description, fullDescription, cacheDir, fileSize, entries, hash, lang); | |
45 | 45 | mUrl = url; | |
46 | 46 | } | |
47 | 47 |
app/src/main/java/eu/lepiller/nani/dictionary/JMDict.java
5 | 5 | import eu.lepiller.nani.R; | |
6 | 6 | ||
7 | 7 | public class JMDict extends ResultDictionary { | |
8 | - | JMDict(String name, String description, String fullDescription, File cacheDir, String url, int fileSize, int entries, String hash) { | |
9 | - | super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash); | |
8 | + | JMDict(String name, String description, String fullDescription, File cacheDir, String url, int fileSize, int entries, String hash, String lang) { | |
9 | + | super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash, lang); | |
10 | 10 | } | |
11 | 11 | ||
12 | 12 | @Override |
app/src/main/java/eu/lepiller/nani/dictionary/Jibiki.java
5 | 5 | import eu.lepiller.nani.R; | |
6 | 6 | ||
7 | 7 | public class Jibiki extends ResultDictionary { | |
8 | - | Jibiki(String name, String description, String fullDescription, File cacheDir, String url, int fileSize, int entries, String hash) { | |
9 | - | super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash); | |
8 | + | Jibiki(String name, String description, String fullDescription, File cacheDir, String url, int fileSize, int entries, String hash, String lang) { | |
9 | + | super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash, lang); | |
10 | 10 | } | |
11 | 11 | ||
12 | 12 | @Override |
app/src/main/java/eu/lepiller/nani/dictionary/RadicalDict.java
95 | 95 | } | |
96 | 96 | ||
97 | 97 | RadicalDict(String name, String description, String fullDescription, File cacheDir, String url, | |
98 | - | int fileSize, int entries, String hash) { | |
99 | - | super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash); | |
98 | + | int fileSize, int entries, String hash, String lang) { | |
99 | + | super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash, lang); | |
100 | 100 | } | |
101 | 101 | ||
102 | 102 | private static boolean contains(List<String> lst, String s) { |
app/src/main/java/eu/lepiller/nani/dictionary/ResultAugmenterDictionary.java
5 | 5 | import eu.lepiller.nani.result.Result; | |
6 | 6 | ||
7 | 7 | public abstract class ResultAugmenterDictionary extends FileDictionary { | |
8 | - | ResultAugmenterDictionary(String name, String description, String fullDescription, File cacheDir, String url, int fileSize, int entries, String hash) { | |
9 | - | super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash); | |
8 | + | ResultAugmenterDictionary(String name, String description, String fullDescription, File cacheDir, String url, int fileSize, int entries, String hash, String lang) { | |
9 | + | super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash, lang); | |
10 | 10 | } | |
11 | 11 | ||
12 | 12 | void augment(Result r) throws IncompatibleFormatException { |
app/src/main/java/eu/lepiller/nani/dictionary/ResultDictionary.java
16 | 16 | private Huffman kanjiHuffman, readingHuffman, meaningHuffman; | |
17 | 17 | ||
18 | 18 | ResultDictionary(String name, String description, String fullDescription, File cacheDir, String url, | |
19 | - | int fileSize, int entries, String hash) { | |
20 | - | super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash); | |
19 | + | int fileSize, int entries, String hash, String lang) { | |
20 | + | super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash, lang); | |
21 | 21 | } | |
22 | 22 | ||
23 | 23 | @Override |
app/src/main/java/eu/lepiller/nani/dictionary/WadokuPitchDictionary.java
18 | 18 | private Huffman huffman = null; | |
19 | 19 | private long triePos; | |
20 | 20 | ||
21 | - | WadokuPitchDictionary(String name, String description, String fullDescription, File cacheDir, String url, int fileSize, int entries, String hash) { | |
22 | - | super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash); | |
21 | + | WadokuPitchDictionary(String name, String description, String fullDescription, File cacheDir, String url, int fileSize, int entries, String hash, String lang) { | |
22 | + | super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash, lang); | |
23 | 23 | } | |
24 | 24 | ||
25 | 25 | @Override |
app/src/main/java/eu/lepiller/nani/dictionary/WadokuResultDictionary.java
5 | 5 | import eu.lepiller.nani.R; | |
6 | 6 | ||
7 | 7 | public class WadokuResultDictionary extends ResultDictionary { | |
8 | - | WadokuResultDictionary(String name, String description, String fullDescription, File cacheDir, String url, int fileSize, int entries, String hash) { | |
9 | - | super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash); | |
8 | + | WadokuResultDictionary(String name, String description, String fullDescription, File cacheDir, String url, int fileSize, int entries, String hash, String lang) { | |
9 | + | super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash, lang); | |
10 | 10 | } | |
11 | 11 | ||
12 | 12 | @Override |
app/src/main/res/layout/activity_dictionary.xml
9 | 9 | tools:showIn="@layout/activity_dictionary" | |
10 | 10 | android:id="@+id/dictionary_refresh_layout"> | |
11 | 11 | ||
12 | - | <ListView | |
13 | - | android:id="@+id/dictionary_view" | |
14 | - | android:layout_width="match_parent" | |
12 | + | <LinearLayout | |
13 | + | android:layout_width="wrap_content" | |
15 | 14 | android:layout_height="wrap_content" | |
16 | - | android:layout_marginStart="8dp" | |
17 | - | android:layout_marginLeft="8dp" | |
18 | - | android:layout_marginTop="32dp" | |
19 | - | android:layout_marginEnd="8dp" | |
20 | - | android:layout_marginRight="8dp" | |
21 | - | android:layout_marginBottom="8dp" /> | |
15 | + | android:orientation="vertical"> | |
16 | + | ||
17 | + | <Spinner | |
18 | + | android:layout_width="match_parent" | |
19 | + | android:layout_height="wrap_content" | |
20 | + | android:id="@+id/lang_view" | |
21 | + | android:layout_margin="8dp" /> | |
22 | + | ||
23 | + | <ListView | |
24 | + | android:id="@+id/dictionary_view" | |
25 | + | android:layout_width="match_parent" | |
26 | + | android:layout_height="wrap_content" | |
27 | + | android:layout_marginStart="8dp" | |
28 | + | android:layout_marginLeft="8dp" | |
29 | + | android:layout_marginTop="32dp" | |
30 | + | android:layout_marginEnd="8dp" | |
31 | + | android:layout_marginRight="8dp" | |
32 | + | android:layout_marginBottom="8dp" /> | |
33 | + | </LinearLayout> | |
22 | 34 | ||
23 | 35 | </androidx.swiperefreshlayout.widget.SwipeRefreshLayout> | |
23 | 35 | = | |
24 | 36 | = | \ No newline at end of file |
app/src/main/res/values/strings.xml
76 | 76 | <string name="dictionary_expected_size_b">File size: %sB</string> | |
77 | 77 | <string name="dictionary_expected_size_kb">File size: %sKB</string> | |
78 | 78 | <string name="dictionary_expected_size_mb">File size: %sMB</string> | |
79 | + | <string name="all_langs">All languages</string> | |
79 | 80 | ||
80 | 81 | <!-- Result view --> | |
81 | 82 | <string name="sense_number">%d.</string> |