2 * Copyright (c) 2008 Jiri Benc <jbenc@upir.cz>
3 * Copyright (c) 2009 Roman Moravcik <roman.moravcik@gmail.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <hildon/hildon-caption.h>
26 #include <hildon/hildon-banner.h>
27 #include <hildon/hildon.h>
29 #include <gconf/gconf.h>
30 #include <gconf/gconf-client.h>
35 #define GETTEXT_PACKAGE "ukeyboard"
36 #include <glib/gi18n-lib.h>
38 char *ignore_autocapitalisation
[] = {"ar_AR", "fa_IR", "he_IL", "ka_GE", "km_KH", "pa_IN", "th_TH", NULL
};
51 HildonCheckButton
*word_compl
;
52 HildonCheckButton
*auto_cap
;
53 HildonCheckButton
*sp_after
;
54 HildonPickerButton
*sec_dictsel
;
55 HildonTouchSelector
*langsel
[2];
56 HildonTouchSelector
*dictsel
[2];
57 HildonCheckButton
*dual
;
61 static gchar
*get_lang(GConfClient
*client
, int n
)
63 char *tmp
= g_strdup_printf("/apps/osso/inputmethod/hildon-im-languages/language-%d", n
);
66 res
= gconf_client_get_string(client
, tmp
, NULL
);
71 static void set_lang(GConfClient
*client
, int n
, gchar
*val
)
73 char *tmp
= g_strdup_printf("/apps/osso/inputmethod/hildon-im-languages/language-%d", n
);
75 gconf_client_set_string(client
, tmp
, val
, NULL
);
79 static gchar
*read_vkb_str(FILE *f
)
84 if (!fread(&len
, 1, 1, f
) || !len
)
86 res
= g_malloc(len
+ 1);
87 if (fread(res
, 1, len
, f
) != len
) {
95 static struct lang
*read_vkb(gchar
*path
)
98 struct lang
*res
= NULL
;
102 f
= fopen(path
, "r");
106 if (!fread(&ver
, 1, 1, f
) || ver
!= 1)
108 /* number of sections */
109 if (!fread(&ver
, 1, 1, f
))
111 /* descriptive name */
112 desc
= read_vkb_str(f
);
116 code
= read_vkb_str(f
);
122 res
= g_malloc(sizeof(struct lang
));
130 static GList
*add_lang_link(gchar
*path
, gchar
*dest
, GList
*list
)
131 /* 'dest' has to be allocated; it's eaten by this function! */
133 struct langlink
*langlink
;
136 link
= g_file_read_link(path
, NULL
);
138 langlink
= g_malloc(sizeof(struct langlink
));
139 langlink
->dest
= dest
;
140 tmp
= strrchr(link
, '/');
141 langlink
->src
= tmp
? tmp
+ 1 : link
;
142 tmp
= strrchr(link
, '.');
145 langlink
->src
= g_strdup(langlink
->src
);
147 list
= g_list_append(list
, langlink
);
152 static GList
*get_langs(gchar
*path
, GList
**langlinks
, GList
*list
)
156 gchar
*fullpath
, *shortpath
, *tmp
;
159 d
= g_dir_open(path
, 0, NULL
);
162 while ((fname
= g_dir_read_name(d
))) {
163 if (!g_str_has_suffix(fname
, ".vkb"))
165 fullpath
= g_strjoin("/", path
, fname
, NULL
);
166 shortpath
= g_strdup(fname
);
167 tmp
= strrchr(shortpath
, '.');
170 if (langlinks
&& g_file_test(fullpath
, G_FILE_TEST_IS_SYMLINK
)) {
171 *langlinks
= add_lang_link(fullpath
, shortpath
, *langlinks
);
175 lang
= read_vkb(fullpath
);
177 lang
->fname
= shortpath
;
178 lang
->ext
= !langlinks
;
179 list
= g_list_append(list
, lang
);
188 static struct lang
*get_def_lang(gchar
*code
, GList
*langs
, GList
*langlinks
)
192 struct langlink
*langlink
;
196 for (item
= langs
; item
; item
= g_list_next(item
)) {
198 if (!strcmp(lang
->fname
, code
))
202 for (item
= langlinks
; item
; item
= g_list_next(item
)) {
203 langlink
= item
->data
;
204 if (!strcmp(langlink
->dest
, code
))
205 return get_def_lang(langlink
->src
, langs
, NULL
);
210 static gboolean
check_ukbd_layout(gchar
*code
, GList
*langlinks
)
213 struct langlink
*langlink
;
218 for (item
= langlinks
; item
; item
= g_list_next(item
)) {
219 langlink
= item
->data
;
220 if (!strcmp(langlink
->dest
, code
)) {
221 if (!strncmp(langlink
->src
, "ukbd", 4)) {
229 static void free_langs(GList
*list
)
234 for (item
= list
; item
; item
= g_list_next(item
)) {
244 static void free_langlinks(GList
*list
)
247 struct langlink
*langlink
;
249 for (item
= list
; item
; item
= g_list_next(item
)) {
250 langlink
= item
->data
;
251 g_free(langlink
->src
);
252 g_free(langlink
->dest
);
258 static void fill_langsel(HildonTouchSelector
*combo
, GList
*langs
, struct lang
*deflang
, gboolean empty
)
264 for (item
= langs
, i
= 0; item
; item
= g_list_next(item
), i
++) {
266 hildon_touch_selector_append_text(combo
, lang
->desc
);
268 hildon_touch_selector_set_active(combo
, 0, i
);
271 hildon_touch_selector_append_text(combo
, _TI("tein_fi_not_in_use"));
273 hildon_touch_selector_set_active(combo
, 0, i
);
277 static void sensitivity_langsel(struct data
*d
)
281 sens
= (hildon_touch_selector_get_active(d
->langsel
[1], 0) < d
->num_langs
);
282 gtk_widget_set_sensitive(GTK_WIDGET(d
->dual
), sens
);
285 gtk_widget_show(GTK_WIDGET(d
->sec_dictsel
));
287 gtk_widget_hide(GTK_WIDGET(d
->sec_dictsel
));
290 static void verify_langsel(HildonTouchSelector
*combo
, gint column
, struct data
*d
)
292 struct lang
*lang
[2];
297 for (i
= 0; i
< 2; i
++) {
298 res
= hildon_touch_selector_get_active(d
->langsel
[i
], column
);
299 lang
[i
] = (res
>= 0) ? g_list_nth_data(d
->langs
, res
) : NULL
;
301 if (lang
[0] && lang
[1] && !strcmp(lang
[0]->code
, lang
[1]->code
)) {
302 hildon_banner_show_information(d
->win
, "gtk-dialog-error",
303 "Impossible combination of languages");
304 hildon_touch_selector_set_active(d
->langsel
[1], column
, d
->num_langs
);
306 sensitivity_langsel(d
);
309 static gint
langs_compare_func(gconstpointer a
, gconstpointer b
)
311 struct lang
*lang_a
= (struct lang
*) a
;
312 struct lang
*lang_b
= (struct lang
*) b
;
314 return g_utf8_collate (lang_a
->desc
, lang_b
->desc
);
317 static GtkWidget
*start(GConfClient
*client
, GtkWidget
*win
, void **data
)
321 GtkWidget
*vbox
, *table
;
325 d
= g_new0(struct data
, 1);
329 d
->langs
= get_langs("/usr/share/keyboards", &d
->langlinks
, NULL
);
330 d
->langs
= get_langs("/usr/share/ukeyboard", NULL
, d
->langs
);
331 d
->langs
= g_list_sort(d
->langs
, langs_compare_func
);
332 d
->num_langs
= g_list_length(d
->langs
);
334 d
->dicts
= get_dicts(d
->langs
);
336 vbox
= gtk_vbox_new(FALSE
, 0);
338 d
->word_compl
= HILDON_CHECK_BUTTON(hildon_check_button_new(HILDON_SIZE_FINGER_HEIGHT
));
339 gtk_button_set_label (GTK_BUTTON (d
->word_compl
), _TI("tein_fi_settings_word_completion"));
340 gtk_box_pack_start(GTK_BOX(vbox
), GTK_WIDGET(d
->word_compl
), TRUE
, TRUE
, 0);
342 d
->auto_cap
= HILDON_CHECK_BUTTON(hildon_check_button_new(HILDON_SIZE_FINGER_HEIGHT
));
343 gtk_button_set_label (GTK_BUTTON (d
->auto_cap
), _TI("tein_fi_settings_auto_capitalization"));
344 gtk_box_pack_start(GTK_BOX(vbox
), GTK_WIDGET(d
->auto_cap
), TRUE
, TRUE
, 0);
346 d
->sp_after
= HILDON_CHECK_BUTTON(hildon_check_button_new(HILDON_SIZE_FINGER_HEIGHT
));
347 gtk_button_set_label (GTK_BUTTON (d
->sp_after
), _TI("tein_fi_settings_space_after_word"));
348 gtk_box_pack_start(GTK_BOX(vbox
), GTK_WIDGET(d
->sp_after
), TRUE
, TRUE
, 0);
350 table
= gtk_table_new(2, 2, TRUE
);
351 gtk_box_pack_start(GTK_BOX(vbox
), table
, TRUE
, TRUE
, 0);
353 for (i
= 0; i
< 2; i
++) {
357 d
->langsel
[i
] = HILDON_TOUCH_SELECTOR(hildon_touch_selector_new_text());
358 code
= get_lang(client
, i
);
359 fill_langsel(d
->langsel
[i
], d
->langs
, get_def_lang(code
, d
->langs
, d
->langlinks
), i
== 1);
360 g_signal_connect(G_OBJECT(d
->langsel
[i
]), "changed", G_CALLBACK(verify_langsel
), d
);
362 button
= hildon_picker_button_new(HILDON_SIZE_FINGER_HEIGHT
, HILDON_BUTTON_ARRANGEMENT_VERTICAL
);
363 hildon_picker_button_set_selector(HILDON_PICKER_BUTTON (button
), d
->langsel
[i
]);
364 hildon_button_set_title(HILDON_BUTTON(button
), i
== 0 ? _TI("tein_fi_primary_language") : _TI("tein_fi_secondary_language"));
366 /* if nothing was selected, try set selector button value text */
367 if (hildon_touch_selector_get_active(d
->langsel
[i
], 0) < 0) {
368 if (check_ukbd_layout(code
, d
->langlinks
))
369 hildon_button_set_value(HILDON_BUTTON(button
), "UKeyboard Creator Layout");
371 hildon_button_set_value(HILDON_BUTTON(button
), _TI("tein_fi_not_in_use"));
374 hildon_button_set_alignment (HILDON_BUTTON (button
), 0.0, 0.5, 1.0, 0.0);
375 hildon_button_set_title_alignment(HILDON_BUTTON(button
), 0.0, 0.5);
376 hildon_button_set_value_alignment (HILDON_BUTTON (button
), 0.0, 0.5);
377 gtk_table_attach_defaults(GTK_TABLE(table
), button
, 0, 1, i
, i
+ 1);
379 d
->dictsel
[i
] = HILDON_TOUCH_SELECTOR(hildon_touch_selector_new_text());
380 tmp
= get_l_str(client
, code
, "dictionary");
381 lang
= get_def_lang(code
, d
->langs
, d
->langlinks
);
383 /* If tmp is NULL (i.e. the gconf key is unset), try to use the same
384 * dictionary as the keyboard. But don't do this if the keyboard is
385 * from our package. */
386 fill_dict(d
->dictsel
[i
], d
->dicts
, (tmp
|| (lang
&& lang
->ext
)) ? tmp
: code
);
390 button
= hildon_picker_button_new(HILDON_SIZE_FINGER_HEIGHT
, HILDON_BUTTON_ARRANGEMENT_VERTICAL
);
391 hildon_button_set_title(HILDON_BUTTON(button
), _TI("tein_fi_settings_dictionary"));
392 hildon_picker_button_set_selector(HILDON_PICKER_BUTTON (button
), d
->dictsel
[i
]);
393 hildon_button_set_alignment (HILDON_BUTTON (button
), 0.0, 0.5, 1.0, 0.0);
394 hildon_button_set_title_alignment(HILDON_BUTTON(button
), 0.0, 0.5);
395 hildon_button_set_value_alignment (HILDON_BUTTON (button
), 0.0, 0.5);
396 gtk_table_attach_defaults(GTK_TABLE(table
), button
, 1, 2, i
, i
+ 1);
399 /* secondary language */
400 d
->sec_dictsel
= HILDON_PICKER_BUTTON(button
);
402 /* check if auto-capitalization for the second language isn't enabled */
403 if (get_l_bool(client
, code
, "auto-capitalisation")) {
404 if (!hildon_check_button_get_active(d
->auto_cap
))
405 hildon_check_button_set_active(d
->auto_cap
, TRUE
);
408 /* primary language */
409 hildon_check_button_set_active(d
->word_compl
, get_l_bool(client
, code
, "word-completion"));
410 hildon_check_button_set_active(d
->auto_cap
, get_l_bool(client
, code
, "auto-capitalisation"));
411 hildon_check_button_set_active(d
->sp_after
, get_l_bool(client
, code
, "insert-space-after-word"));
418 d
->dual
= HILDON_CHECK_BUTTON(hildon_check_button_new(HILDON_SIZE_FINGER_HEIGHT
));
419 hildon_check_button_set_active(d
->dual
, get_bool(client
, "dual-dictionary"));
420 gtk_button_set_label (GTK_BUTTON (d
->dual
), _TI("tein_fi_dual_dictionary_use"));
421 gtk_box_pack_start(GTK_BOX(vbox
), GTK_WIDGET(d
->dual
), TRUE
, TRUE
, 0);
423 gtk_widget_show_all(vbox
);
425 sensitivity_langsel(d
);
432 static void action(GConfClient
*client
, void *data
)
434 struct data
*d
= data
;
440 for (i
= 0; i
< 2; i
++) {
443 res
= hildon_touch_selector_get_active(d
->langsel
[i
], 0);
446 lang
= g_list_nth_data(d
->langs
, res
);
449 if (inside_scratchbox
)
450 tmp
= g_strdup_printf("fakeroot /usr/libexec/ukeyboard-set %s %s", lang
->fname
, lang
->code
);
452 tmp
= g_strdup_printf("sudo /usr/libexec/ukeyboard-set %s %s", lang
->fname
, lang
->code
);
455 hildon_banner_show_information(d
->win
, "gtk-dialog-warning",
459 /* When the newly set layout has the same lang code as the
460 * previous one (but the underlaying file changed), setting
461 * the same value won't trigger layout reload. Workaround
462 * that by setting "en_GB" lang code first. */
463 set_lang(client
, i
, "en_GB");
464 set_lang(client
, i
, lang
->code
);
466 set_l_bool(client
, lang
->code
, "auto-capitalisation", hildon_check_button_get_active(d
->auto_cap
));
467 set_l_bool(client
, lang
->code
, "word-completion", hildon_check_button_get_active(d
->word_compl
));
468 set_l_bool(client
, lang
->code
, "insert-space-after-word", hildon_check_button_get_active(d
->sp_after
));
470 /* forced disabling of autocapitalization for selected language codes,
471 that doesn't support autocapitalization */
472 for (j
= 0; ignore_autocapitalisation
[j
] != NULL
; j
++) {
473 if (!strcmp(lang
->code
, ignore_autocapitalisation
[j
])) {
474 set_l_bool(client
, lang
->code
, "auto-capitalisation", FALSE
);
478 res
= hildon_touch_selector_get_active(d
->dictsel
[i
], 0);
480 dict
= g_list_nth_data(d
->dicts
, res
);
483 set_l_str(client
, lang
->code
, "dictionary", dict
->code
);
485 set_l_str(client
, lang
->code
, "dictionary", "");
487 set_lang(client
, i
, "");
489 set_bool(client
, "dual-dictionary", hildon_check_button_get_active(d
->dual
));
492 static void stop(GConfClient
*client
, void *data
)
494 struct data
*d
= data
;
498 free_langs(d
->langs
);
499 free_langs(d
->dicts
);
500 free_langlinks(d
->langlinks
);
504 void prefs_lang_init(struct prefs
*prefs
)
506 prefs
->start
= start
;
507 prefs
->action
= action
;
509 prefs
->name
= "Languages";