3 Website: http://www.vultaire.net/software/jben/
4 License: GNU General Public License (GPL) version 2
5 (http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt)
7 File: dialog_config.cpp
9 Contributors: Alain Bertrand
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>
25 #include "dialog_config.h"
26 #include "preferences.h"
28 #include "file_utils.h"
29 #include "jben_defines.h"
30 #include <glibmm/i18n.h>
31 #include <gtkmm/notebook.h>
32 #include <gtkmm/scrolledwindow.h>
33 #include <gtkmm/buttonbox.h>
34 #include <gtkmm/stock.h>
35 #include <gtkmm/fontselection.h>
36 #include <gtkmm/messagedialog.h>
37 #include <boost/format.hpp>
39 #define CHOOSE_FONT _("Change...")
41 DialogConfig::DialogConfig(Gtk::Window
& parent
)
42 : StoredDialog(_("Preferences Editor"), parent
, "gui.dlg.preferences.size"),
43 chkReadings(_("Include on-yomi, kun-yomi and nanori (name) readings")),
44 chkMeanings(_("Include English meanings")),
45 chkHighImp(_("Include stroke count, Jouyou grade "
46 "and newspaper frequency rank")),
47 chkMultiRad(_("Include radical component list")),
48 chkDict(_("Include dictionary reference codes")),
49 chkVocabCrossRef(_("Show vocab from your study list "
50 "which use the kanji")),
51 chkLowImp(_("Other information (Radical #'s, "
52 "Korean and Pinyin romanization)")),
53 chkSodStatic(_("Use stroke order diagrams if present")),
54 chkSodAnim(_("Use animated stroke order diagrams if present (tests only)")),
56 lblJaNormal(_("Japanese Font, Normal")),
57 lblJaLarge (_("Japanese Font, Large")),
58 lblEnNormal(_("English Font, Normal")),
59 lblEnSmall (_("English Font, Small")),
60 btnJaNormal(CHOOSE_FONT
),
61 btnJaLarge (CHOOSE_FONT
),
62 btnEnNormal(CHOOSE_FONT
),
63 btnEnSmall (CHOOSE_FONT
),
64 chkMobile(_("Mobile mode (settings saved to current directory)")),
65 btnCancel(Gtk::Stock::CANCEL
),
68 std::vector
<Gtk::CheckButton
*>::iterator it
;
70 /* Create list of dictionary checkbuttons */
73 new Gtk::CheckButton(_("\"New Japanese-English Character Dictionary\" "
74 "by Jack Halpern.")));
75 vChkDict
.push_back(pc
);
77 new Gtk::CheckButton(_("\"Modern Reader's Japanese-English "
78 "Character Dictionary\" by Andrew Nelson")));
79 vChkDict
.push_back(pc
);
81 new Gtk::CheckButton(_("\"The New Nelson Japanese-English "
82 "Character Dictionary\" by John Haig")));
83 vChkDict
.push_back(pc
);
85 new Gtk::CheckButton(_("\"Japanese for Busy People\" by AJLT")));
86 vChkDict
.push_back(pc
);
88 new Gtk::CheckButton(_("\"The Kanji Way to Japanese Language Power\" "
90 vChkDict
.push_back(pc
);
91 pc
= manage(new Gtk::CheckButton(_("\"Kodansha Compact Kanji Guide\"")));
92 vChkDict
.push_back(pc
);
94 new Gtk::CheckButton(_("\"A Guide To Reading and Writing Japanese\" "
95 "by Ken Hensall et al.")));
96 vChkDict
.push_back(pc
);
98 new Gtk::CheckButton(_("\"Kanji in Context\" by Nishiguchi and Kono")));
99 vChkDict
.push_back(pc
);
101 new Gtk::CheckButton(_("\"Kanji Learner's Dictionary\" "
102 "by Jack Halpern")));
103 vChkDict
.push_back(pc
);
105 new Gtk::CheckButton(_("\"Essential Kanji\" by P.G. O'Neill")));
106 vChkDict
.push_back(pc
);
108 new Gtk::CheckButton(_("\"2001 Kanji\" by Father Joseph De Roo")));
109 vChkDict
.push_back(pc
);
111 new Gtk::CheckButton(_("\"A Guide To Reading and Writing Japanese\" "
112 "by Florence Sakade")));
113 vChkDict
.push_back(pc
);
115 new Gtk::CheckButton(_("\"Tuttle Kanji Cards\" by Alexander Kask")));
116 vChkDict
.push_back(pc
);
118 new Gtk::CheckButton(_("\"Japanese Kanji Flashcards\" "
119 "by White Rabbit Press")));
120 vChkDict
.push_back(pc
);
122 new Gtk::CheckButton(_("SKIP codes used by Halpern dictionaries")));
123 vChkDict
.push_back(pc
);
125 new Gtk::CheckButton(_("\"Kanji Dictionary\" by Spahn & Hadamitzky")));
126 vChkDict
.push_back(pc
);
128 new Gtk::CheckButton(_("\"Kanji & Kana\" by Spahn & Hadamitzky")));
129 vChkDict
.push_back(pc
);
131 new Gtk::CheckButton(_("Four Corner code (various dictionaries)")));
132 vChkDict
.push_back(pc
);
133 pc
= manage(new Gtk::CheckButton(_("\"Morohashi Daikanwajiten\"")));
134 vChkDict
.push_back(pc
);
136 new Gtk::CheckButton(_("\"A Guide to Remembering Japanese Characters\" "
137 "by Kenneth G. Henshal")));
138 vChkDict
.push_back(pc
);
140 new Gtk::CheckButton(_("Gakken Kanji Dictionary "
141 "(\"A New Dictionary of Kanji Usage\")")));
142 vChkDict
.push_back(pc
);
144 new Gtk::CheckButton(_("\"Remembering The Kanji\" by James Heisig")));
145 vChkDict
.push_back(pc
);
146 pc
= manage(new Gtk::CheckButton(_("\"Japanese Names\" by P.G. O'Neill")));
148 /* Connect signals */
149 chkDict
.signal_toggled()
150 .connect(sigc::mem_fun(*this, &DialogConfig::OnDictionaryToggle
));
151 btnCancel
.signal_clicked()
152 .connect(sigc::mem_fun(*this, &DialogConfig::OnCancel
));
153 btnOK
.signal_clicked()
154 .connect(sigc::mem_fun(*this, &DialogConfig::OnOK
));
156 /* Layout and display */
157 Gtk::Notebook
*pnb
= manage(new Gtk::Notebook
);
158 Gtk::VBox
*pvbKanjiConfig
, *pvbFontConfig
;
159 Gtk::VBox
*pvbKanjiMainOpts
, *pvbKanjiDictsOuter
, *pvbKanjiOtherOpts
;
160 pvbKanjiConfig
= manage(new Gtk::VBox
);
161 pvbKanjiMainOpts
= manage(new Gtk::VBox
);
162 pvbKanjiDictsOuter
= manage(new Gtk::VBox
);
163 pvbKanjiOtherOpts
= manage(new Gtk::VBox
);
164 pvbFontConfig
= manage(new Gtk::VBox
);
165 Gtk::HButtonBox
*phbbButtons
= manage(new Gtk::HButtonBox
);
166 Gtk::ScrolledWindow
*pswDicts
= manage(new Gtk::ScrolledWindow
);
167 pswDicts
->set_policy(Gtk::POLICY_AUTOMATIC
, Gtk::POLICY_AUTOMATIC
);
169 pvbKanjiConfig
->pack_start(*pvbKanjiMainOpts
, Gtk::PACK_SHRINK
);
170 pvbKanjiConfig
->pack_start(*pvbKanjiDictsOuter
, Gtk::PACK_EXPAND_WIDGET
);
171 pvbKanjiConfig
->pack_start(*pvbKanjiOtherOpts
, Gtk::PACK_SHRINK
);
172 pvbKanjiConfig
->pack_start(*phbbButtons
, Gtk::PACK_SHRINK
);
174 pvbKanjiMainOpts
->pack_start(chkReadings
, Gtk::PACK_SHRINK
);
175 pvbKanjiMainOpts
->pack_start(chkMeanings
, Gtk::PACK_SHRINK
);
176 pvbKanjiMainOpts
->pack_start(chkHighImp
, Gtk::PACK_SHRINK
);
177 pvbKanjiMainOpts
->pack_start(chkMultiRad
, Gtk::PACK_SHRINK
);
179 pvbKanjiDictsOuter
->pack_start(chkDict
, Gtk::PACK_SHRINK
);
180 pvbKanjiDictsOuter
->pack_start(*pswDicts
, Gtk::PACK_EXPAND_WIDGET
);
182 pswDicts
->add(vbDicts
);
183 for(it
= vChkDict
.begin(); it
!= vChkDict
.end(); it
++) {
184 vbDicts
.pack_start(**it
, Gtk::PACK_SHRINK
);
186 vbDicts
.set_sensitive(false);
188 pvbKanjiOtherOpts
->pack_start(chkVocabCrossRef
, Gtk::PACK_SHRINK
);
189 pvbKanjiOtherOpts
->pack_start(chkLowImp
, Gtk::PACK_SHRINK
);
190 pvbKanjiOtherOpts
->pack_start(chkSodStatic
, Gtk::PACK_SHRINK
);
191 pvbKanjiOtherOpts
->pack_start(chkSodAnim
, Gtk::PACK_SHRINK
);
193 pvbFontConfig
->set_spacing(5);
194 pvbFontConfig
->pack_start(tblFonts
, Gtk::PACK_SHRINK
);
196 frJaNormal
.add(tvJaNormal
);
197 frJaNormal
.set_shadow_type(Gtk::SHADOW_IN
);
198 frJaLarge
.add(tvJaLarge
);
199 frJaLarge
.set_shadow_type(Gtk::SHADOW_IN
);
200 frEnNormal
.add(tvEnNormal
);
201 frEnNormal
.set_shadow_type(Gtk::SHADOW_IN
);
202 frEnSmall
.add(tvEnSmall
);
203 frEnSmall
.set_shadow_type(Gtk::SHADOW_IN
);
204 tvJaNormal
.set_accepts_tab(false);
205 tvJaLarge
.set_accepts_tab(false);
206 tvEnNormal
.set_accepts_tab(false);
207 tvEnSmall
.set_accepts_tab(false);
208 tvJaNormal
.set_editable(false);
209 tvJaLarge
.set_editable(false);
210 tvEnNormal
.set_editable(false);
211 tvEnSmall
.set_editable(false);
213 Gtk::HButtonBox
*fntBtnBox1
= manage(new Gtk::HButtonBox
);
214 fntBtnBox1
->pack_start(btnJaNormal
, Gtk::PACK_SHRINK
);
215 Gtk::HButtonBox
*fntBtnBox2
= manage(new Gtk::HButtonBox
);
216 fntBtnBox2
->pack_start(btnJaLarge
, Gtk::PACK_SHRINK
);
217 Gtk::HButtonBox
*fntBtnBox3
= manage(new Gtk::HButtonBox
);
218 fntBtnBox3
->pack_start(btnEnNormal
, Gtk::PACK_SHRINK
);
219 Gtk::HButtonBox
*fntBtnBox4
= manage(new Gtk::HButtonBox
);
220 fntBtnBox4
->pack_start(btnEnSmall
, Gtk::PACK_SHRINK
);
222 tblFonts
.attach(lblJaNormal
, 0, 1, 0, 1, Gtk::SHRINK
,
224 tblFonts
.attach(frJaNormal
, 1, 2, 0, 1, Gtk::FILL
| Gtk::EXPAND
,
226 tblFonts
.attach(*fntBtnBox1
, 2, 3, 0, 1, Gtk::SHRINK
,
228 tblFonts
.attach(lblJaLarge
, 0, 1, 1, 2, Gtk::SHRINK
,
230 tblFonts
.attach(frJaLarge
, 1, 2, 1, 2, Gtk::FILL
| Gtk::EXPAND
,
232 tblFonts
.attach(*fntBtnBox2
, 2, 3, 1, 2, Gtk::SHRINK
,
234 tblFonts
.attach(lblEnNormal
, 0, 1, 2, 3, Gtk::SHRINK
,
236 tblFonts
.attach(frEnNormal
, 1, 2, 2, 3, Gtk::FILL
| Gtk::EXPAND
,
238 tblFonts
.attach(*fntBtnBox3
, 2, 3, 2, 3, Gtk::SHRINK
,
240 tblFonts
.attach(lblEnSmall
, 0, 1, 3, 4, Gtk::SHRINK
,
242 tblFonts
.attach(frEnSmall
, 1, 2, 3, 4, Gtk::FILL
| Gtk::EXPAND
,
244 tblFonts
.attach(*fntBtnBox4
, 2, 3, 3, 4, Gtk::SHRINK
,
247 btnJaNormal
.signal_clicked().connect(sigc::bind
<Gtk::Button
*>(
248 sigc::mem_fun(*this, &DialogConfig::OnFontChange
), &btnJaNormal
));
249 btnJaLarge
.signal_clicked() .connect(sigc::bind
<Gtk::Button
*>(
250 sigc::mem_fun(*this, &DialogConfig::OnFontChange
), &btnJaLarge
));
251 btnEnNormal
.signal_clicked().connect(sigc::bind
<Gtk::Button
*>(
252 sigc::mem_fun(*this, &DialogConfig::OnFontChange
), &btnEnNormal
));
253 btnEnSmall
.signal_clicked() .connect(sigc::bind
<Gtk::Button
*>(
254 sigc::mem_fun(*this, &DialogConfig::OnFontChange
), &btnEnSmall
));
256 pnb
->append_page(*pvbKanjiConfig
, _("Kanji Dictionary"));
257 pnb
->append_page(ckt
,_("Kanji test"));
258 pnb
->append_page(*pvbFontConfig
, _("Fonts"));
260 /* Windows only: "mobile mode" */
262 chkMobile
.signal_toggled()
263 .connect(sigc::mem_fun(*this, &DialogConfig::OnMobileToggle
));
264 Gtk::VBox
*pvbOtherConfig
= manage(new Gtk::VBox
);
265 pvbOtherConfig
->pack_start(chkMobile
, Gtk::PACK_SHRINK
);
266 pnb
->append_page(*pvbOtherConfig
, _("Other"));
270 Gtk::VBox
* pvb
= get_vbox();
272 pvb
->pack_start(*pnb
);
274 Gtk::HButtonBox
* phbb
= get_action_area();
275 phbb
->pack_start(btnCancel
);
276 phbb
->pack_start(btnOK
);
282 void DialogConfig::OnDictionaryToggle() {
283 vbDicts
.set_sensitive(chkDict
.get_active());
286 void DialogConfig::OnCancel() {
288 response(Gtk::RESPONSE_CANCEL
);
291 void DialogConfig::OnOK() {
292 unsigned long options
=0, dictionaries
=0;
293 if(chkReadings
.get_active()) options
|= KDO_READINGS
;
294 if(chkMeanings
.get_active()) options
|= KDO_MEANINGS
;
295 if(chkHighImp
.get_active()) options
|= KDO_HIGHIMPORTANCE
;
296 if(chkMultiRad
.get_active()) options
|= KDO_MULTIRAD
;
297 if(chkDict
.get_active()) options
|= KDO_DICTIONARIES
;
298 if(chkVocabCrossRef
.get_active()) options
|= KDO_VOCABCROSSREF
;
299 if(chkLowImp
.get_active()) options
|= KDO_LOWIMPORTANCE
;
300 if(chkSodStatic
.get_active()) options
|= KDO_SOD_STATIC
;
301 if(chkSodAnim
.get_active()) options
|= KDO_SOD_ANIM
;
303 for(size_t i
=0; i
<vChkDict
.size(); i
++) {
304 if(vChkDict
[i
]->get_active()) dictionaries
|= (1ul << i
);
306 Preferences
*prefs
= Preferences::Get();
307 prefs
->kanjidicOptions
= options
;
308 prefs
->kanjidicDictionaries
= dictionaries
;
309 ckt
.validate(); /* Validate kanji test settings */
310 prefs
->GetSetting("font.ja") = sFontJaNormal
;
311 prefs
->GetSetting("font.ja.large") = sFontJaLarge
;
312 prefs
->GetSetting("font.en") = sFontEnNormal
;
313 prefs
->GetSetting("font.en.small") = sFontEnSmall
;
315 if(chkMobile
.get_active())
316 prefs
->GetSetting("config_save_target") = "mobile";
318 prefs
->GetSetting("config_save_target") = "home";
320 Update(); /* Probably unnecessary, but let's be safe. */
321 response(Gtk::RESPONSE_OK
);
324 void DialogConfig::Update() {
325 Preferences
*prefs
= Preferences::Get();
326 int options
= prefs
->kanjidicOptions
;
327 int dictionaries
= prefs
->kanjidicDictionaries
;
329 /* Set appropriate checkboxes */
330 chkReadings
.set_active(options
& KDO_READINGS
);
331 chkMeanings
.set_active(options
& KDO_MEANINGS
);
332 chkHighImp
.set_active(options
& KDO_HIGHIMPORTANCE
);
333 chkMultiRad
.set_active(options
& KDO_MULTIRAD
);
334 chkDict
.set_active(options
& KDO_DICTIONARIES
);
335 chkVocabCrossRef
.set_active(options
& KDO_VOCABCROSSREF
);
336 chkLowImp
.set_active(options
& KDO_LOWIMPORTANCE
);
337 chkSodStatic
.set_active(options
& KDO_SOD_STATIC
);
338 chkSodAnim
.set_active(options
& KDO_SOD_ANIM
);
341 /* Enable/disable SOD/SODA checkboxes based on existance of directory */
342 /* (DISABLED for now; J-Ben should auto-disable the flag if dicts
343 are not found, but obviously that needs to be done in the prefs
344 loader. I'll add that later.) */
345 string sodDir
= Preferences::Get()->GetSetting("sod_dir");
346 chkSodStatic
.set_sensitive(
350 .append("sod-utf8-hex")
352 .append("README-License").c_str()));
353 chkSodAnim
.set_sensitive(
357 .append("soda-utf8-hex")
359 .append("README-License").c_str()));
362 for(size_t i
=0;i
<vChkDict
.size();i
++) {
363 vChkDict
[i
]->set_active(dictionaries
& (1ul << i
));
366 /* Init font display */
367 sFontJaNormal
= prefs
->GetSetting("font.ja");
368 sFontJaLarge
= prefs
->GetSetting("font.ja.large");
369 sFontEnNormal
= prefs
->GetSetting("font.en");
370 sFontEnSmall
= prefs
->GetSetting("font.en.small");
371 UpdateFontControl(tvJaNormal
, sFontJaNormal
);
372 UpdateFontControl(tvJaLarge
, sFontJaLarge
);
373 UpdateFontControl(tvEnNormal
, sFontEnNormal
);
374 UpdateFontControl(tvEnSmall
, sFontEnSmall
);
377 chkMobile
.set_active(prefs
->GetSetting("config_save_target") == "mobile");
380 void DialogConfig::UpdateFontControl(Gtk::TextView
& tv
, const string
& font
) {
381 Glib::RefPtr
<Gtk::TextBuffer
> pBuf
= tv
.get_buffer();
382 Glib::RefPtr
<Gtk::TextTagTable
> pTable
= pBuf
->get_tag_table();
383 Glib::RefPtr
<Gtk::TextTag
> pTag
;
384 pTag
= pTable
->lookup("font");
386 pTable
->remove(pTag
);
389 pTag
= Gtk::TextTag::create("font");
390 pTag
->property_font() = font
;
393 if(&tv
== &tvJaNormal
|| &tv
== &tvJaLarge
) {
394 pBuf
->insert_with_tag(pBuf
->begin(), "日本語", pTag
);
396 pBuf
->insert_with_tag(pBuf
->begin(), "English", pTag
);
400 void DialogConfig::OnFontChange(Gtk::Button
* src
) {
401 Gtk::FontSelectionDialog
fd(_("Choose Font"));
404 if(src
==&btnJaNormal
) {
407 fd
.set_preview_text("ENGLISH english 日本語 にほんご ニホンゴ");
408 } else if(src
==&btnJaLarge
) {
411 fd
.set_preview_text("ENGLISH english 日本語 にほんご ニホンゴ");
412 } else if(src
==&btnEnNormal
) {
415 } else if(src
==&btnEnSmall
) {
418 } else return; /* Should not happen */
420 fd
.set_font_name(*ps
);
421 int result
= fd
.run();
422 if(result
== Gtk::RESPONSE_OK
) {
423 (*ps
) = fd
.get_font_name();
424 UpdateFontControl(*ptv
, *ps
);
428 void DialogConfig::OnMobileToggle() {
429 if(chkMobile
.get_active()==false) {
430 Preferences
*p
= Preferences::Get();
431 if(p
->GetSetting("config_save_target")=="mobile") {
432 /* The user is attempting a change from a mobile to standard
433 install. We need to check whether a standard install config
434 file is already present, and if it is, we need to warn the
435 user before they accidentally overwrite it. */
437 char *sz
= getenv(HOMEENV
);
440 sCfgPath
.append(1, DSCHAR
);
441 sCfgPath
.append(CFGFILE
);
442 } else return; /* No home dir is a problem of its own, but at least
443 the user won't lose data over the problem. */
444 if(FileExists(sCfgPath
.c_str())) {
445 Gtk::MessageDialog
md(
447 "A config file was found in this system's home folder: "
448 "%s. Turning mobile mode off will cause J-Ben to "
449 "OVERWRITE the existing file when it closes, "
450 "destroying whatever is already there. Is this okay?"))
452 false, Gtk::MESSAGE_WARNING
, Gtk::BUTTONS_YES_NO
);
453 int result
= md
.run();
454 if(result
== Gtk::RESPONSE_NO
) {
455 chkMobile
.set_active(true);