~ubuntu-branches/ubuntu/precise/gnome-control-center/precise-updates

« back to all changes in this revision

Viewing changes to panels/region/gnome-region-panel-xkbltadd.c

Tags: upstream-3.0.1.1
ImportĀ upstreamĀ versionĀ 3.0.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* gnome-region-panel-xkbltadd.c
 
2
 * Copyright (C) 2007 Sergey V. Udaltsov
 
3
 *
 
4
 * Written by: Sergey V. Udaltsov <svu@gnome.org>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2, or (at your option)
 
9
 * any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
19
 * 02111-1307, USA.
 
20
 */
 
21
 
 
22
#ifdef HAVE_CONFIG_H
 
23
#  include <config.h>
 
24
#endif
 
25
 
 
26
#include <string.h>
 
27
 
 
28
#include <libgnomekbd/gkbd-keyboard-drawing.h>
 
29
#include <libgnomekbd/gkbd-util.h>
 
30
 
 
31
#include "gnome-region-panel-xkb.h"
 
32
 
 
33
enum {
 
34
        COMBO_BOX_MODEL_COL_SORT,
 
35
        COMBO_BOX_MODEL_COL_VISIBLE,
 
36
        COMBO_BOX_MODEL_COL_XKB_ID,
 
37
        COMBO_BOX_MODEL_COL_COUNTRY_DESC,
 
38
        COMBO_BOX_MODEL_COL_LANGUAGE_DESC
 
39
};
 
40
 
 
41
static gchar **search_pattern_list = NULL;
 
42
 
 
43
static GtkWidget *preview_dialog = NULL;
 
44
 
 
45
#define RESPONSE_PREVIEW 1
 
46
 
 
47
static void
 
48
xkb_preview_destroy_callback (GtkWidget * widget)
 
49
{
 
50
        preview_dialog = NULL;
 
51
}
 
52
 
 
53
static gboolean
 
54
xkb_layout_chooser_selection_dupe (GtkDialog *dialog)
 
55
{
 
56
        gchar *selected_id =
 
57
            (gchar *) xkb_layout_chooser_get_selected_id (dialog);
 
58
        gchar **layouts_list, **pl;
 
59
        gboolean rv = FALSE;
 
60
        if (selected_id == NULL)
 
61
                return rv;
 
62
        layouts_list = pl = xkb_layouts_get_selected_list ();
 
63
        while (pl && *pl) {
 
64
                if (!g_ascii_strcasecmp (*pl++, selected_id)) {
 
65
                        rv = TRUE;
 
66
                        break;
 
67
                }
 
68
        }
 
69
        g_strfreev (layouts_list);
 
70
        return rv;
 
71
}
 
72
 
 
73
void
 
74
xkb_layout_chooser_response (GtkDialog  *dialog,
 
75
                             gint        response)
 
76
{
 
77
        switch (response)
 
78
        case GTK_RESPONSE_OK:{
 
79
                        /* Handled by the main code */
 
80
                        break;
 
81
        case RESPONSE_PREVIEW:{
 
82
                                gchar *selected_id = (gchar *)
 
83
                                    xkb_layout_chooser_get_selected_id
 
84
                                    (dialog);
 
85
 
 
86
                                if (selected_id != NULL) {
 
87
                                        if (preview_dialog == NULL) {
 
88
                                                preview_dialog =
 
89
                                                    gkbd_keyboard_drawing_dialog_new
 
90
                                                    ();
 
91
                                                g_signal_connect (G_OBJECT
 
92
                                                                  (preview_dialog),
 
93
                                                                  "destroy",
 
94
                                                                  G_CALLBACK
 
95
                                                                  (xkb_preview_destroy_callback),
 
96
                                                                  NULL);
 
97
                                                /* Put into the separate group to avoid conflict
 
98
                                                   with modal parent */
 
99
                                                gtk_window_group_add_window
 
100
                                                    (gtk_window_group_new
 
101
                                                     (),
 
102
                                                     GTK_WINDOW
 
103
                                                     (preview_dialog));
 
104
                                        };
 
105
                                        gkbd_keyboard_drawing_dialog_set_layout
 
106
                                            (preview_dialog,
 
107
                                             config_registry, selected_id);
 
108
 
 
109
                                        gtk_widget_show_all
 
110
                                            (preview_dialog);
 
111
                                }
 
112
                        }
 
113
 
 
114
                        return;
 
115
                }
 
116
        if (preview_dialog != NULL) {
 
117
                gtk_widget_destroy (preview_dialog);
 
118
        }
 
119
        if (search_pattern_list != NULL) {
 
120
                g_strfreev (search_pattern_list);
 
121
                search_pattern_list = NULL;
 
122
        }
 
123
        gtk_widget_destroy (GTK_WIDGET (dialog));
 
124
}
 
125
 
 
126
static gchar *
 
127
xkl_create_description_from_list (const XklConfigItem * item,
 
128
                                  const XklConfigItem * subitem,
 
129
                                  const gchar * prop_name,
 
130
                                  const gchar *
 
131
                                  (*desc_getter) (const gchar * code))
 
132
{
 
133
        gchar *rv = NULL, *code = NULL;
 
134
        gchar **list = NULL;
 
135
        const gchar *desc;
 
136
 
 
137
        if (subitem != NULL)
 
138
                list =
 
139
                    (gchar
 
140
                     **) (g_object_get_data (G_OBJECT (subitem),
 
141
                                             prop_name));
 
142
        if (list == NULL || *list == 0)
 
143
                list =
 
144
                    (gchar
 
145
                     **) (g_object_get_data (G_OBJECT (item), prop_name));
 
146
 
 
147
        /* First try the parent id as such */
 
148
        desc = desc_getter (item->name);
 
149
        if (desc != NULL) {
 
150
                rv = g_utf8_strup (desc, -1);
 
151
        } else {
 
152
                code = g_utf8_strup (item->name, -1);
 
153
                desc = desc_getter (code);
 
154
                if (desc != NULL) {
 
155
                        rv = g_utf8_strup (desc, -1);
 
156
                }
 
157
                g_free (code);
 
158
        }
 
159
 
 
160
        if (list == NULL || *list == 0)
 
161
                return rv;
 
162
 
 
163
        while (*list != 0) {
 
164
                code = *list++;
 
165
                desc = desc_getter (code);
 
166
                if (desc != NULL) {
 
167
                        gchar *udesc = g_utf8_strup (desc, -1);
 
168
                        if (rv == NULL) {
 
169
                                rv = udesc;
 
170
                        } else {
 
171
                                gchar *orv = rv;
 
172
                                rv = g_strdup_printf ("%s %s", rv, udesc);
 
173
                                g_free (orv);
 
174
                                g_free (udesc);
 
175
                        }
 
176
                }
 
177
        }
 
178
        return rv;
 
179
}
 
180
 
 
181
static void
 
182
xkl_layout_add_to_list (XklConfigRegistry * config,
 
183
                        const XklConfigItem * item,
 
184
                        const XklConfigItem * subitem,
 
185
                        GtkBuilder * chooser_dialog)
 
186
{
 
187
        GtkListStore *list_store =
 
188
            GTK_LIST_STORE (gtk_builder_get_object (chooser_dialog,
 
189
                                                    "layout_list_model"));
 
190
        GtkTreeIter iter;
 
191
        gchar *utf_variant_name =
 
192
            subitem ?
 
193
            xkb_layout_description_utf8 (gkbd_keyboard_config_merge_items
 
194
                                         (item->name,
 
195
                                          subitem->name)) :
 
196
            xci_desc_to_utf8 (item);
 
197
        const gchar *xkb_id =
 
198
            subitem ? gkbd_keyboard_config_merge_items (item->name,
 
199
                                                        subitem->name) :
 
200
            item->name;
 
201
 
 
202
        gchar *country_desc =
 
203
            xkl_create_description_from_list (item, subitem,
 
204
                                              XCI_PROP_COUNTRY_LIST,
 
205
                                              xkl_get_country_name);
 
206
        gchar *language_desc =
 
207
            xkl_create_description_from_list (item, subitem,
 
208
                                              XCI_PROP_LANGUAGE_LIST,
 
209
                                              xkl_get_language_name);
 
210
 
 
211
        if (subitem
 
212
            && g_object_get_data (G_OBJECT (subitem),
 
213
                                  XCI_PROP_EXTRA_ITEM)) {
 
214
                gchar *buf =
 
215
                    g_strdup_printf ("<i>%s</i>", utf_variant_name);
 
216
                gtk_list_store_insert_with_values (list_store, &iter, -1,
 
217
                                                   COMBO_BOX_MODEL_COL_SORT,
 
218
                                                   utf_variant_name,
 
219
                                                   COMBO_BOX_MODEL_COL_VISIBLE,
 
220
                                                   buf,
 
221
                                                   COMBO_BOX_MODEL_COL_XKB_ID,
 
222
                                                   xkb_id,
 
223
                                                   COMBO_BOX_MODEL_COL_COUNTRY_DESC,
 
224
                                                   country_desc,
 
225
                                                   COMBO_BOX_MODEL_COL_LANGUAGE_DESC,
 
226
                                                   language_desc, -1);
 
227
                g_free (buf);
 
228
        } else
 
229
                gtk_list_store_insert_with_values (list_store, &iter,
 
230
                                                   -1,
 
231
                                                   COMBO_BOX_MODEL_COL_SORT,
 
232
                                                   utf_variant_name,
 
233
                                                   COMBO_BOX_MODEL_COL_VISIBLE,
 
234
                                                   utf_variant_name,
 
235
                                                   COMBO_BOX_MODEL_COL_XKB_ID,
 
236
                                                   xkb_id,
 
237
                                                   COMBO_BOX_MODEL_COL_COUNTRY_DESC,
 
238
                                                   country_desc,
 
239
                                                   COMBO_BOX_MODEL_COL_LANGUAGE_DESC,
 
240
                                                   language_desc, -1);
 
241
        g_free (utf_variant_name);
 
242
        g_free (country_desc);
 
243
        g_free (language_desc);
 
244
}
 
245
 
 
246
static void
 
247
xkb_layout_filter_clear (GtkEntry            *entry,
 
248
                         GtkEntryIconPosition icon_pos,
 
249
                         GdkEvent            *event,
 
250
                         gpointer             user_data)
 
251
{
 
252
        gtk_entry_set_text (entry, "");
 
253
}
 
254
 
 
255
static void
 
256
xkb_layout_filter_changed (GtkBuilder * chooser_dialog)
 
257
{
 
258
        GtkTreeModelFilter *filtered_model =
 
259
            GTK_TREE_MODEL_FILTER (gtk_builder_get_object (chooser_dialog,
 
260
                                                           "filtered_layout_list_model"));
 
261
        GtkWidget *xkb_layout_filter = CWID ("xkb_layout_filter");
 
262
        const gchar *pattern =
 
263
            gtk_entry_get_text (GTK_ENTRY (xkb_layout_filter));
 
264
        gchar *upattern = g_utf8_strup (pattern, -1);
 
265
 
 
266
        if (!g_strcmp0 (pattern, "")) {
 
267
                g_object_set (G_OBJECT (xkb_layout_filter),
 
268
                              "secondary-icon-name", "edit-find-symbolic",
 
269
                              "secondary-icon-activatable", FALSE,
 
270
                              "secondary-icon-sensitive", FALSE,
 
271
                              NULL);
 
272
        } else {
 
273
                g_object_set (G_OBJECT (xkb_layout_filter),
 
274
                              "secondary-icon-name", "edit-clear-symbolic",
 
275
                              "secondary-icon-activatable", TRUE,
 
276
                              "secondary-icon-sensitive", TRUE,
 
277
                              NULL);
 
278
        }
 
279
 
 
280
        if (search_pattern_list != NULL)
 
281
                g_strfreev (search_pattern_list);
 
282
 
 
283
        search_pattern_list = g_strsplit (upattern, " ", -1);
 
284
        g_free (upattern);
 
285
 
 
286
        gtk_tree_model_filter_refilter (filtered_model);
 
287
}
 
288
 
 
289
static void
 
290
xkb_layout_chooser_selection_changed (GtkTreeSelection * selection,
 
291
                                      GtkBuilder * chooser_dialog)
 
292
{
 
293
        GList *selected_layouts =
 
294
            gtk_tree_selection_get_selected_rows (selection, NULL);
 
295
        GtkWidget *add_button = CWID ("btnOk");
 
296
        GtkWidget *preview_button = CWID ("btnPreview");
 
297
        gboolean anything_selected = g_list_length (selected_layouts) == 1;
 
298
        gboolean dupe = xkb_layout_chooser_selection_dupe (GTK_DIALOG (CWID("xkb_layout_chooser")));
 
299
 
 
300
        gtk_widget_set_sensitive (add_button, anything_selected && !dupe);
 
301
        gtk_widget_set_sensitive (preview_button, anything_selected);
 
302
}
 
303
 
 
304
static gboolean
 
305
xkb_filter_layouts (GtkTreeModel * model,
 
306
                    GtkTreeIter * iter, gpointer data)
 
307
{
 
308
        gchar *desc = NULL, *country_desc = NULL, *language_desc =
 
309
            NULL, **pattern;
 
310
        gboolean rv = TRUE;
 
311
 
 
312
        if (search_pattern_list == NULL || search_pattern_list[0] == NULL)
 
313
                return TRUE;
 
314
 
 
315
        gtk_tree_model_get (model, iter,
 
316
                            COMBO_BOX_MODEL_COL_SORT, &desc,
 
317
                            COMBO_BOX_MODEL_COL_COUNTRY_DESC,
 
318
                            &country_desc,
 
319
                            COMBO_BOX_MODEL_COL_LANGUAGE_DESC,
 
320
                            &language_desc, -1);
 
321
 
 
322
        pattern = search_pattern_list;
 
323
        do {
 
324
                gboolean is_pattern_found = FALSE;
 
325
                gchar *udesc = g_utf8_strup (desc, -1);
 
326
                if (udesc != NULL && g_strstr_len (udesc, -1, *pattern)) {
 
327
                        is_pattern_found = TRUE;
 
328
                } else if (country_desc != NULL
 
329
                           && g_strstr_len (country_desc, -1, *pattern)) {
 
330
                        is_pattern_found = TRUE;
 
331
                } else if (language_desc != NULL
 
332
                           && g_strstr_len (language_desc, -1, *pattern)) {
 
333
                        is_pattern_found = TRUE;
 
334
                }
 
335
                g_free (udesc);
 
336
 
 
337
                if (!is_pattern_found) {
 
338
                        rv = FALSE;
 
339
                        break;
 
340
                }
 
341
 
 
342
        } while (*++pattern != NULL);
 
343
 
 
344
        g_free (desc);
 
345
        g_free (country_desc);
 
346
        g_free (language_desc);
 
347
        return rv;
 
348
}
 
349
 
 
350
GtkWidget *
 
351
xkb_layout_choose (GtkBuilder * dialog)
 
352
{
 
353
        GtkBuilder *chooser_dialog = gtk_builder_new ();
 
354
        GtkWidget *chooser, *xkb_filtered_layouts_list, *xkb_layout_filter;
 
355
        GtkTreeViewColumn *visible_column;
 
356
        GtkTreeSelection *selection;
 
357
        GtkListStore *model;
 
358
        GtkTreeModelFilter *filtered_model;
 
359
 
 
360
        gtk_builder_add_from_file (chooser_dialog, GNOMECC_UI_DIR
 
361
                                   "/gnome-region-panel-layout-chooser.ui",
 
362
                                   NULL);
 
363
        chooser = CWID ("xkb_layout_chooser");
 
364
        xkb_filtered_layouts_list = CWID ("xkb_filtered_layouts_list");
 
365
        xkb_layout_filter = CWID ("xkb_layout_filter");
 
366
 
 
367
        g_object_set_data (G_OBJECT (chooser), "xkb_filtered_layouts_list", xkb_filtered_layouts_list);
 
368
        visible_column =
 
369
            gtk_tree_view_column_new_with_attributes ("Layout",
 
370
                                                      gtk_cell_renderer_text_new
 
371
                                                      (), "text",
 
372
                                                      COMBO_BOX_MODEL_COL_VISIBLE,
 
373
                                                      NULL);
 
374
 
 
375
        gtk_window_set_transient_for (GTK_WINDOW (chooser),
 
376
                                      GTK_WINDOW
 
377
                                      (gtk_widget_get_toplevel
 
378
                                       (WID ("region_notebook"))));
 
379
 
 
380
        gtk_tree_view_append_column (GTK_TREE_VIEW
 
381
                                     (xkb_filtered_layouts_list),
 
382
                                     visible_column);
 
383
        g_signal_connect_swapped (G_OBJECT (xkb_layout_filter),
 
384
                                  "notify::text",
 
385
                                  G_CALLBACK
 
386
                                  (xkb_layout_filter_changed),
 
387
                                  chooser_dialog);
 
388
 
 
389
        g_signal_connect (G_OBJECT (xkb_layout_filter), "icon-release",
 
390
                          G_CALLBACK (xkb_layout_filter_clear), NULL);
 
391
 
 
392
        selection =
 
393
            gtk_tree_view_get_selection (GTK_TREE_VIEW
 
394
                                         (xkb_filtered_layouts_list));
 
395
 
 
396
        g_signal_connect (G_OBJECT (selection),
 
397
                          "changed",
 
398
                          G_CALLBACK
 
399
                          (xkb_layout_chooser_selection_changed),
 
400
                          chooser_dialog);
 
401
 
 
402
        xkb_layout_chooser_selection_changed (selection, chooser_dialog);
 
403
 
 
404
        filtered_model =
 
405
            GTK_TREE_MODEL_FILTER (gtk_builder_get_object
 
406
                                   (chooser_dialog,
 
407
                                    "filtered_layout_list_model"));
 
408
        model =
 
409
            GTK_LIST_STORE (gtk_builder_get_object
 
410
                            (chooser_dialog, "layout_list_model"));
 
411
 
 
412
        xkl_config_registry_search_by_pattern (config_registry,
 
413
                                               NULL,
 
414
                                               (TwoConfigItemsProcessFunc)
 
415
                                               (xkl_layout_add_to_list),
 
416
                                               chooser_dialog);
 
417
        gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
 
418
                                              COMBO_BOX_MODEL_COL_SORT,
 
419
                                              GTK_SORT_ASCENDING);
 
420
 
 
421
        gtk_tree_model_filter_set_visible_func (filtered_model,
 
422
                                                xkb_filter_layouts,
 
423
                                                NULL, NULL);
 
424
 
 
425
        gtk_widget_grab_focus (xkb_layout_filter);
 
426
 
 
427
        gtk_widget_show (chooser);
 
428
 
 
429
        return chooser;
 
430
}
 
431
 
 
432
gchar *
 
433
xkb_layout_chooser_get_selected_id (GtkDialog *dialog)
 
434
{
 
435
        GtkTreeModel *filtered_list_model;
 
436
        GtkWidget *xkb_filtered_layouts_list =
 
437
                g_object_get_data (G_OBJECT (dialog), "xkb_filtered_layouts_list");
 
438
        GtkTreeIter viter;
 
439
        gchar *v_id;
 
440
        GtkTreeSelection *selection =
 
441
            gtk_tree_view_get_selection (GTK_TREE_VIEW
 
442
                                         (xkb_filtered_layouts_list));
 
443
        GList *selected_layouts =
 
444
            gtk_tree_selection_get_selected_rows (selection,
 
445
                                                  &filtered_list_model);
 
446
 
 
447
        if (g_list_length (selected_layouts) != 1)
 
448
                return NULL;
 
449
 
 
450
        gtk_tree_model_get_iter (filtered_list_model,
 
451
                                 &viter,
 
452
                                 (GtkTreePath *) (selected_layouts->data));
 
453
        g_list_foreach (selected_layouts,
 
454
                        (GFunc) gtk_tree_path_free, NULL);
 
455
        g_list_free (selected_layouts);
 
456
 
 
457
        gtk_tree_model_get (filtered_list_model, &viter,
 
458
                            COMBO_BOX_MODEL_COL_XKB_ID, &v_id, -1);
 
459
 
 
460
        return v_id;
 
461
}