Added indexing to JMdict parser. Small changes to unit tests.
[jben2_gui.git] / preferences.py
blobeecfa54af705ddbbf7ce9ea1036d4722b229d001
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
4 # Project: J-Ben, Python front-end
5 # File: preferences.py
6 # Author: Paul Goins
7 # Created on: 20 December 2008
9 from jben_global import *
10 import re
12 options = {}
13 """Maps preference key strings to stored option values."""
15 original_save_target = None
16 """This variable will be set to the contents of options["config_save_target"]
17 when a config file is loaded, in order to track runtime changes.
18 """
20 __CURRENT_CONFIG_VERSION = "2.0"
21 """The current version of the config file."""
23 def load(filename=None):
24 """Load preferences from a config file.
26 If filename is None (default), then J-Ben will search for a config
27 file in the program's parent directory (important for self-contained
28 "mobile" installs), followed by the user's home directory.
30 """
31 global original_save_target
32 loaded = False
34 if filename:
35 try:
36 f = open(filename)
37 print "Reading from file:", filename
38 lines = f.readlines()
39 f.close()
41 for line in lines:
42 line = line.strip()
43 # Treat # and ; as comment markers, and ignore empty lines.
44 if len(line) == 0 or line[0] == "#" or line[0] == ";":
45 continue
47 try:
48 k, v = re.split("[ \t=:]+", line, 1)
49 if k and v:
50 v2 = v.lower().strip()
51 if v2 in ("true", "false"):
52 options[k] = (v2 == "true")
53 else:
54 options[k] = v
55 except ValueError:
56 print _("Warning: unable to split line: %s" % line)
57 original_save_target = options["config_save_target"]
58 except IOError, e:
59 if e.args[0] == 2: # Error 2 == File not found
60 print "Could not find file:", filename
61 else:
62 raise
63 else:
64 loaded = load("../%s/jben.cfg" % CFG_FOLDER)
65 if not loaded or options["config_save_target"] == "home":
66 env_path = os.getenv(HOME_ENV)
67 if env_path:
68 loaded2 = load("%s/%s/jben.cfg" % (env_path, CFG_FOLDER))
69 if loaded2:
70 loaded = True
72 return loaded
74 def save(filename=None):
75 """Save preferences to a config file.
77 If filename is None (default), then J-Ben will save the file based
78 on the current install type (standard or mobile).
80 Important: If filename is None, and the installation type was
81 changed during runtime, then this function will save to both files.
82 This is necessary in case two config files are located on a
83 system (both standard and mobile), in which case J-Ben will look at
84 both files and decide which one to use.
86 """
87 save_data = __create_config_file_string()
88 #print "save_data = [%s]" % save_data
90 files = set()
91 if filename is None:
92 env_path = os.getenv(HOME_ENV)
93 if env_path: home_path = "%s/%s/jben.cfg" % (env_path, CFG_FOLDER)
94 else: home_path = None
95 mobile_path = "../%s/jben.cfg" % CFG_FOLDER
97 targets = (options["config_save_target"], original_save_target)
98 for target in targets:
99 if target == "unset": target = "home"
100 if target == "mobile" or not home_path:
101 files.add(mobile_path)
102 else:
103 files.add(home_path)
104 else:
105 files.append(filename)
107 for f in files:
108 if f:
109 try:
110 dirname = os.path.dirname(f)
111 if not os.path.exists(dirname):
112 os.mkdir(dirname)
113 fo = open(f, "w")
114 print "Writing to file:", f
115 fo.write(save_data)
116 fo.close()
117 except:
118 # We can add error handlers later...
119 raise
121 def set_default_prefs():
122 """Default preferences are defined here.
124 These settings are loaded prior to loading any config file. Any
125 new default settings should be defined here.
128 # Changes in Python version
129 # 1. JB_DATADIR is now configured in jben_global.py.
130 # 2. DSSTR is removed; we will now simply specify "/" as a
131 # directory separator.
132 # 3. kanjidicOptions and kanjidicDictionaries have been obsoleted and
133 # replaced with explicit "kdict.render" values.
135 options.clear()
136 options["config_version"] = __CURRENT_CONFIG_VERSION
137 options["config_save_target"] = "unset"
139 # Obsoleted options
140 # kanjidicOptions = KDO_READINGS | KDO_MEANINGS
141 # | KDO_HIGHIMPORTANCE | KDO_VOCABCROSSREF;
142 # kanjidicDictionaries = 0;
144 # Replaced by the following, more explicit options:
146 # KDO_READINGS:
147 options["kdict.render.onyomi"] = True
148 options["kdict.render.kunyomi"] = True
149 options["kdict.render.nanori"] = True
150 options["kdict.render.radical_name"] = True
152 # KDO_MEANINGS:
153 options["kdict.render.meaning"] = True # ENGLISH
154 #options["kdict.render.meaning.fr"] = True # Example for French
156 # KDO_HIGHIMPORTANCE:
157 options["kdict.render.stroke_count"] = True
158 options["kdict.render.jouyou_grade"] = True
159 options["kdict.render.jlpt_level"] = True
160 options["kdict.render.frequency"] = True
162 # KDO_MULTIRAD:
163 options["kdict.render.radical_list"] = False
165 # KDO_VOCABCROSSREF:
166 options["kdict.render.vocab_cross_ref"] = True
168 # KDO_DICTIONARIES:
169 options["kdict.render.dictionaries"] = False
170 # Additional keys for specific dictionaries are boolean flags tagged onto
171 # the end of the above key.
172 # Example: kdict.render.dictionaries.kld = True
173 # (kld = Kanji Learners' Dictionary)
175 # KDO_LOWIMPORTANCE:
176 options["kdict.render.jis-208"] = False
177 options["kdict.render.jis-212"] = False
178 options["kdict.render.jis-213"] = False
179 options["kdict.render.unicode"] = False
180 options["kdict.render.kangxi_radical"] = False
181 options["kdict.render.nelson_radical"] = False
182 options["kdict.render.pinyin_roman"] = False
183 options["kdict.render.korean"] = False
184 options["kdict.render.korean_roman"] = False
185 options["kdict.render.cross_ref"] = False
187 # KDO_SOD_*:
188 options["kdict.render.kanjicafe_sods"] = True
189 options["kdict.render.kanjicafe_sodas"] = True
191 # Define default paths to supported (and future supported) dicts.
192 # J-Ben will automatically append ".gz" and load compressed dictionaries
193 # if found.
194 # Identifiers are of the form "jben_obj.dict_type.file[#]". Dicts with the
195 # same format should share the same dict_type and add a file number.
197 options["kdict.kanjidic2.file"] = JB_DATADIR + "/dicts/kanjidic2.xml"
198 options["kdict.kanjidic.file"] = JB_DATADIR + "/dicts/kanjidic"
199 options["kdict.kanjidic.file2"] = JB_DATADIR + "/dicts/kanjd212"
200 options["kdict.kradfile.file"] = JB_DATADIR + "/dicts/kradfile"
201 options["kdict.radkfile.file"] = JB_DATADIR + "/dicts/radkfile"
202 options["wdict.edict.file"] = JB_DATADIR + "/dicts/edict"
203 options["wdict.edict2.file"] = JB_DATADIR + "/dicts/edict2"
205 # J-Ben's internal encoding is UTF-8, however most of Jim Breen's non-XML
206 # dict files are in EUC-JP. We should allow the program to support
207 # these files.
208 options["wdict.edict.file.encoding"] = "euc-jp"
209 options["wdict.edict2.file.encoding"] = "euc-jp"
210 options["kdict.kanjidic.file.encoding"] = "euc-jp"
211 options["kdict.kanjidic.file2.encoding"] = "euc-jp"
212 options["kdict.kradfile.file.encoding"] = "euc-jp"
213 options["kdict.radkfile.file.encoding"] = "euc-jp"
214 # Specify JIS encoding for kanjidic files (jis-208 or jis-212)
215 # jis-208 is assumed, so this just means to set it only for kanjd212.
216 options["kdict.kanjidic.file2.jispage"] = "jis212"
218 options["sod_dir"] = JB_DATADIR + "/sods"
220 options["kanjitest.writing.showonyomi"]=True
221 options["kanjitest.writing.showkunyomi"]=True
222 options["kanjitest.writing.showenglish"]=True
223 options["kanjitest.reading.showonyomi"]=False
224 options["kanjitest.reading.showkunyomi"]=False
225 options["kanjitest.reading.showenglish"]=False
226 options["kanjitest.showanswer"]="1"
227 options["kanjitest.correctanswer"]="2"
228 options["kanjitest.wronganswer"]="3"
229 options["kanjitest.stopdrill"]="4"
231 def upgrade_config_file():
232 """Brings settings loaded from previous config file versions up-to-date.
234 Generally speaking, this should not need to be edited. Only when
235 an option string has been renamed, or the config file itself changed,
236 should this really need to be touched.
239 version = options["config_version"]
241 # Iterate through the version-wise changes
243 if version == "1":
244 el.Push(EL_Silent, "Upgrading config file from version 1 to 1.1.")
245 # 1 to 1.1:
246 # - Add config_save_target setting
247 # - Add KANJIDIC2 and KANJD212 default settings
248 options["config_save_target"] = "home"
249 options["kdict_kanjidic2"] = JB_DATADIR + "/dicts/kanjidic2.xml"
250 options["kdict_kanjd212"] = JB_DATADIR + "/dicts/kanjd212"
251 version = "1.1"
253 if version == "1.1":
254 # 1.1 to 1.2:
255 # - Convert xdict_filename to xdict.dicttype_file# format */
256 map = {"kdict_kanjidic": "kdict.kanjidic.file",
257 "kdict_kanjd212": "kdict.kanjidic.file2",
258 "kdict_kanjidic2": "kdict.kanjidic2.file",
259 "kdict_kradfile": "kdict.kradfile.file",
260 "kdict_radkfile": "kdict.radkfile.file",
261 "wdict_edict2": "wdict.edict2.file"}
262 for old_key, new_key in map.items():
263 val = options.get(old_key)
264 if val:
265 options[new_key] = val
266 del val[old_key]
267 if "kdict.kanjidic.file2" in options.keys():
268 options["kdict.kanjidic.file2.jispage"] = "jis212"
269 version = "1.2"
271 if version == "1.2":
272 # This version change doesn't really change anything, but is left in
273 # so we don't break anything.
274 version = "1.2.1"
276 if version == "1.2.1":
277 # Updates for J-Ben 2.0
278 # 1. Convert kanjidic options/dictionaries int values to normal
279 # options.
280 # 2. Rename KanjiList and VocabList to list.kanji and list.vocab
281 # respectively.
282 pass
283 version = "2.0"
285 version = __CURRENT_CONFIG_VERSION
287 def __create_config_file_string():
288 """Creates a complete config file data string for saving to disk."""
290 # Format: tab-delimited
291 # Example: key value
292 # Notes: First key MUST be "config_version".
294 header = "config_version\t%s" % options["config_version"]
295 config_strs = []
297 # These values are handled specially, so we don't auto-include them.
298 excludes = ["config_version", "kanji_list", "vocab_list"]
299 other_opts = [(k, v) for k, v in options.items() if k not in excludes]
300 for k, v in other_opts:
301 if v != '':
302 config_strs.append("%s\t%s" % (k, str(v)))
303 else:
304 print _('Warning: dropping empty setting "%s"!' % k)
306 # Append kanji and vocab lists
307 # ...
309 config_strs.sort()
310 config_strs.insert(0, header)
311 return "\n".join(config_strs) + "\n"