gcc6: narrowing conversion from char to unsigned char
[platform/core/uifw/ise-engine-unikey.git] / setup / dlg_macro_table.cpp
1 #include <gtk/gtk.h>
2 #include <string.h>
3
4 #include <libintl.h>
5 #include "keycons.h"
6 #include "mactab.h"
7 #include "dlg_macro_table.h"
8
9 #define _(str) gettext(str)
10
11
12 #define STR_NULL_ITEM "..."
13 #define MACRO_DEFAULT_VALUE _("(replace text)")
14
15 enum {COL_KEY = 0, COL_VALUE, NUM_COLS};
16
17
18 void check_last_macro_in_list(GtkListStore* list);
19 void key_edited_cb (GtkCellRendererText *celltext,
20                     const gchar *string_path,
21                     const gchar *newkey,
22                     gpointer user_data);
23 void value_edited_cb(GtkCellRendererText *celltext,
24                      const gchar *string_path,
25                      const gchar *newvalue,
26                      gpointer data);
27 void remove_macro_clicked_cb(GtkButton *button, gpointer user_data);
28 void removeall_macro_clicked_cb(GtkButton *button, gpointer user_data);
29 void import_macro_clicked_cb(GtkButton *button, gpointer user_data);
30 void export_macro_clicked_cb(GtkButton *button, gpointer user_data);
31
32 GtkWidget* unikey_macro_dialog_new()
33 {
34     GtkBuilder* builder = gtk_builder_new();
35
36     gtk_builder_add_from_file(builder, GLADE_DATA_DIR "/setup-macro.glade", NULL);
37
38     GtkWidget* dialog = GTK_WIDGET(gtk_builder_get_object(builder, "dlg_macro_table"));
39
40     // init macro list
41     GtkListStore* list = GTK_LIST_STORE(gtk_builder_get_object(builder, "list_macro"));
42     check_last_macro_in_list(list);
43
44     GtkTreeView* tree = GTK_TREE_VIEW(gtk_builder_get_object(builder, "tree_macro"));
45     g_object_set_data(G_OBJECT(dialog), "tree_macro", tree);
46
47     GtkTreeViewColumn* col;
48     GtkCellRenderer* render;
49
50 // create key column
51     render = gtk_cell_renderer_text_new();
52     g_object_set(render,
53                  "editable", TRUE,
54                  "width-chars", MAX_MACRO_KEY_LEN+8,
55                  NULL);
56     g_signal_connect(render, "edited", G_CALLBACK(key_edited_cb), tree);
57     col = gtk_tree_view_column_new_with_attributes(_("Word"),
58                                                    render,
59                                                    "text",
60                                                    COL_KEY,
61                                                    NULL);
62     gtk_tree_view_column_set_resizable(col, TRUE);
63     gtk_tree_view_append_column(tree, col);
64
65 // create value column
66     render = gtk_cell_renderer_text_new();
67     g_object_set(render,
68                  "editable", TRUE,
69                  NULL);
70     g_signal_connect(render, "edited", G_CALLBACK(value_edited_cb), tree);
71     col = gtk_tree_view_column_new_with_attributes(_("Replace with"),
72                                                    render,
73                                                    "text",
74                                                    COL_VALUE,
75                                                    NULL);
76     gtk_tree_view_column_set_resizable(col, TRUE);
77     gtk_tree_view_append_column(tree, col);
78
79     GtkWidget* btn;
80
81     // connect signal
82     btn = GTK_WIDGET(gtk_builder_get_object(builder, "btn_remove"));
83     g_signal_connect(btn, "clicked", G_CALLBACK(remove_macro_clicked_cb), tree);
84
85     // connect signal
86     btn = GTK_WIDGET(gtk_builder_get_object(builder, "btn_removeall"));
87     g_signal_connect(btn, "clicked", G_CALLBACK(removeall_macro_clicked_cb), tree);
88     // connect signal
89     btn = GTK_WIDGET(gtk_builder_get_object(builder, "btn_import"));
90     g_signal_connect(btn, "clicked", G_CALLBACK(import_macro_clicked_cb), dialog);
91     // connect signal
92     btn = GTK_WIDGET(gtk_builder_get_object(builder, "btn_export"));
93     g_signal_connect(btn, "clicked", G_CALLBACK(export_macro_clicked_cb), dialog);
94
95     g_object_unref(builder);
96
97     return dialog;
98 }
99
100 void append_macro_to_list_store(GtkListStore* list, CMacroTable macro)
101 {
102     GtkTreeIter iter;
103     gchar key[MAX_MACRO_KEY_LEN*3];
104     gchar value[MAX_MACRO_TEXT_LEN*3];
105     gchar* oldkey;
106     UKBYTE* p;
107     int inLen, maxOutLen;
108     int i, ret;
109
110     for (i = 0 ; i < macro.getCount(); i++)
111     {
112         // get key and convert to XUTF charset
113         p = (UKBYTE*)macro.getKey(i);
114         inLen = -1;
115         maxOutLen = sizeof(key);
116         ret = VnConvert(CONV_CHARSET_VNSTANDARD, CONV_CHARSET_XUTF8,
117                         p, (UKBYTE*)key,
118                         &inLen, &maxOutLen);
119         if (ret != 0)
120             continue;
121
122         // check if any key same as newkey
123         gboolean b = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(list), &iter);
124         while (b)
125         {
126             gtk_tree_model_get(GTK_TREE_MODEL(list), &iter, COL_KEY, &oldkey, -1);
127
128             if (strcasecmp(oldkey, key) == 0)
129             {
130                 break;
131             }
132
133             b = gtk_tree_model_iter_next(GTK_TREE_MODEL(list), &iter);
134         }
135         if (b)
136         {
137             continue;
138         }
139         // end check
140
141         // get value and convert to XUTF charset
142         p = (UKBYTE*)macro.getText(i);
143         inLen = -1;
144         maxOutLen = sizeof(value);
145         ret = VnConvert(CONV_CHARSET_VNSTANDARD, CONV_CHARSET_XUTF8,
146                         p, (UKBYTE*)value,
147                         &inLen, &maxOutLen);
148         if (ret != 0)
149             continue;
150
151         // append to liststore
152         gtk_list_store_append(list, &iter);
153         gtk_list_store_set(list, &iter, COL_KEY, key, COL_VALUE, value, -1);
154     }
155 }
156
157 void unikey_macro_dialog_load_macro(GtkDialog* dialog, CMacroTable macro)
158 {
159     GtkTreeView* tree;
160     GtkListStore* list;
161     GtkTreeIter iter;
162
163     tree = GTK_TREE_VIEW(g_object_get_data(G_OBJECT(dialog), "tree_macro"));
164     list = GTK_LIST_STORE(gtk_tree_view_get_model(tree));
165     
166     gtk_list_store_clear(list);
167
168     append_macro_to_list_store(list, macro);
169     check_last_macro_in_list(list);
170
171     // select first iter
172     GtkTreeSelection* select = gtk_tree_view_get_selection(tree);
173     gtk_tree_model_get_iter_first(GTK_TREE_MODEL(list), &iter);
174     gtk_tree_selection_select_iter(select, &iter);
175 }
176
177 void unikey_macro_dialog_save_macro(GtkDialog* dialog, CMacroTable* macro)
178 {
179     GtkTreeView* tree;
180     GtkTreeModel* model;
181     GtkTreeIter iter;
182     gboolean b;
183     gchar *key, *value;
184
185     macro->resetContent();
186
187     tree = GTK_TREE_VIEW(g_object_get_data(G_OBJECT(dialog), "tree_macro"));
188     model = GTK_TREE_MODEL(gtk_tree_view_get_model(tree));
189
190     b = gtk_tree_model_get_iter_first(model, &iter);
191     while (b == TRUE)
192     {
193         gtk_tree_model_get(model, &iter, COL_KEY, &key, COL_VALUE, &value, -1);
194
195         if (strcasecmp(key, STR_NULL_ITEM) != 0)
196         {
197             macro->addItem(key, value, CONV_CHARSET_XUTF8);
198         }
199
200         b = gtk_tree_model_iter_next(model, &iter);
201     }
202 }
203
204 void check_last_macro_in_list(GtkListStore* list)
205 {
206     GtkTreeIter iter;
207     gchar *key;
208     gint n;
209
210     // get number item in list
211     n = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(list), NULL);
212
213     if (n > 0)
214     {
215         // get last item
216         gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list), &iter, NULL, n-1);
217
218         // get key of item
219         gtk_tree_model_get(GTK_TREE_MODEL(list), &iter, COL_KEY, &key, -1);
220
221         // if key is value used for NULL item
222         if (strcmp(key, STR_NULL_ITEM) == 0)
223         {
224             return;
225         }
226     }
227
228     // if last item is valid item or no item in list, add new NULL item
229     gtk_list_store_append(list, &iter);
230     gtk_list_store_set(list, &iter,
231                        COL_KEY, STR_NULL_ITEM,
232                        COL_VALUE, STR_NULL_ITEM,
233                        -1);
234 }
235
236 void key_edited_cb (GtkCellRendererText *celltext,
237                     const gchar *string_path,
238                     const gchar *newkey,
239                     gpointer data)
240 {
241     GtkTreeView *tree;
242     GtkTreeModel *model;
243     GtkTreeIter iter;
244     gchar *key, *oldkey, *oldvalue;
245     gchar nkey[MAX_MACRO_KEY_LEN];
246     gboolean b;
247
248     tree = GTK_TREE_VIEW(data);
249     model = gtk_tree_view_get_model(tree);
250
251     strncpy(nkey, newkey, MAX_MACRO_KEY_LEN-1);
252     nkey[MAX_MACRO_KEY_LEN-1] = '\0';
253
254     if (strcmp(nkey, STR_NULL_ITEM) == 0
255         || (strlen(STR_NULL_ITEM) != 0 && strlen(nkey) == 0))
256     {
257         return;
258     }
259
260     // check if any key same as newkey
261     b = gtk_tree_model_get_iter_first(model, &iter);
262     while (b)
263     {
264         gtk_tree_model_get(model, &iter, COL_KEY, &key, -1);
265         if (strcasecmp(key, nkey) == 0)
266         {
267             return;
268         }
269
270         b = gtk_tree_model_iter_next(model, &iter);
271     }
272     // end check
273
274     // get iter of newkey
275     gtk_tree_model_get_iter_from_string(model, &iter, string_path);
276     // get old value of that iter
277     gtk_tree_model_get(model, &iter, COL_KEY, &oldkey, COL_VALUE, &oldvalue, -1);
278
279     gtk_list_store_set(GTK_LIST_STORE(model), &iter, COL_KEY, nkey, -1);
280
281     if (strcmp(oldkey, STR_NULL_ITEM) == 0)
282     {
283         gtk_list_store_set(GTK_LIST_STORE(model), &iter, COL_VALUE, MACRO_DEFAULT_VALUE);
284     }
285
286     check_last_macro_in_list(GTK_LIST_STORE(model));
287 }
288
289 void value_edited_cb(GtkCellRendererText *celltext,
290                      const gchar *string_path,
291                      const gchar *newvalue,
292                      gpointer data)
293 {
294     GtkTreeView *tree;
295     GtkTreeModel *model;
296     GtkTreeIter iter;
297     gchar *key;
298     gchar value[MAX_MACRO_TEXT_LEN];
299
300     tree = GTK_TREE_VIEW(data);
301     model = gtk_tree_view_get_model(tree);
302
303     gtk_tree_model_get_iter_from_string(model, &iter, string_path);
304
305     gtk_tree_model_get(model, &iter, COL_KEY, &key, -1);
306
307     strncpy(value, newvalue, MAX_MACRO_TEXT_LEN-1);
308     value[MAX_MACRO_TEXT_LEN-1] = '\0';
309
310     if (strcmp(key, STR_NULL_ITEM) != 0)
311     {
312         gtk_list_store_set(GTK_LIST_STORE(model), &iter, COL_VALUE, value, -1);
313     }
314 }
315
316 void remove_macro_clicked_cb(GtkButton *button, gpointer user_data)
317 {
318     GtkTreeView     *treeview;
319     GtkListStore    *list;
320     GtkTreeSelection*select;
321     GtkTreeIter     iter;
322     gchar           *key;
323
324     treeview = GTK_TREE_VIEW(user_data);
325
326     select = gtk_tree_view_get_selection(treeview);
327
328     list = GTK_LIST_STORE(gtk_tree_view_get_model(treeview));
329
330     if (gtk_tree_selection_get_selected(select, NULL, &iter) == TRUE)
331     {
332         gtk_tree_model_get(GTK_TREE_MODEL(list), &iter, COL_KEY, &key, -1);
333
334         if (strcmp(key, STR_NULL_ITEM) != 0)
335         {
336             gtk_list_store_remove(list, &iter);
337         }
338
339         gtk_tree_selection_select_iter(select, &iter); // select current index
340     }
341 }
342
343 void removeall_macro_clicked_cb(GtkButton *button, gpointer data)
344 {
345     GtkTreeView* tree;
346     GtkListStore* list;
347     GtkTreeIter iter;
348     GtkTreeSelection* select;
349
350     tree = GTK_TREE_VIEW(data);
351     list = GTK_LIST_STORE(gtk_tree_view_get_model(tree));
352
353     gtk_list_store_clear(list);
354
355     check_last_macro_in_list(list);
356
357     select = gtk_tree_view_get_selection(tree);
358
359     gtk_tree_model_get_iter_first(GTK_TREE_MODEL(list), &iter);
360
361     gtk_tree_selection_select_iter(select, &iter);
362 }
363
364 void import_macro_clicked_cb(GtkButton *button, gpointer data)
365 {
366     GtkWidget* file;
367     GtkTreeView* tree;
368     GtkListStore* list;
369     GtkTreeIter iter;
370     CMacroTable macro;
371     gchar* fn;
372     int r, n;
373
374     file = gtk_file_chooser_dialog_new(_("Choose file to import"),
375                                        GTK_WINDOW(data),
376                                        GTK_FILE_CHOOSER_ACTION_OPEN,
377                                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
378                                        GTK_STOCK_OPEN, GTK_RESPONSE_OK,
379                                        NULL);
380
381     gtk_widget_set_sensitive(GTK_WIDGET(data), FALSE);
382
383     r = gtk_dialog_run(GTK_DIALOG(file));
384     if (r == GTK_RESPONSE_OK)
385     {
386         fn = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file));
387         macro.init();
388         macro.loadFromFile(fn);
389         g_free(fn);
390
391         tree = GTK_TREE_VIEW(g_object_get_data(G_OBJECT(data), "tree_macro"));
392         list = GTK_LIST_STORE(gtk_tree_view_get_model(tree));
393
394         n = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(list), NULL);     // get number of iter
395         gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list), &iter, NULL, n-1); // get last iter
396         gtk_list_store_remove(list, &iter); // remove last iter (...)
397
398         append_macro_to_list_store(list, macro);
399
400         check_last_macro_in_list(list); // add iter (...)
401
402         // select first iter
403         GtkTreeSelection* select = gtk_tree_view_get_selection(tree);
404         gtk_tree_model_get_iter_first(GTK_TREE_MODEL(list), &iter);
405         gtk_tree_selection_select_iter(select, &iter);
406     }
407
408     gtk_widget_destroy(file);
409
410     gtk_widget_set_sensitive(GTK_WIDGET(data), TRUE);
411 }
412
413 void export_macro_clicked_cb(GtkButton *button, gpointer data)
414 {
415     GtkWidget* file;
416     GtkTreeView* tree;
417     GtkTreeModel* model;
418     GtkTreeIter iter;
419     CMacroTable macro;
420     gchar* key, *value;
421     gchar* fn;
422     int r;
423
424     file = gtk_file_chooser_dialog_new(_("Choose file to export"),
425                                        GTK_WINDOW(data),
426                                        GTK_FILE_CHOOSER_ACTION_SAVE,
427                                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
428                                        GTK_STOCK_SAVE, GTK_RESPONSE_OK,
429                                        NULL);
430
431     gtk_widget_set_sensitive(GTK_WIDGET(data), FALSE);
432
433     r = gtk_dialog_run(GTK_DIALOG(file));
434     if (r == GTK_RESPONSE_OK)
435     {
436         macro.init();
437
438         tree = GTK_TREE_VIEW(g_object_get_data(G_OBJECT(data), "tree_macro"));
439         model = GTK_TREE_MODEL(gtk_tree_view_get_model(tree));
440
441         gboolean b = gtk_tree_model_get_iter_first(model, &iter);
442         while (b == TRUE)
443         {
444             gtk_tree_model_get(model, &iter, COL_KEY, &key, COL_VALUE, &value, -1);
445
446             if (strcasecmp(key, STR_NULL_ITEM) != 0)
447             {
448                 macro.addItem(key, value, CONV_CHARSET_XUTF8);
449             }
450             b = gtk_tree_model_iter_next(model, &iter);
451         }
452
453         fn = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file));
454         macro.writeToFile(fn);
455         g_free(fn);
456     }
457
458     gtk_widget_destroy(file);
459
460     gtk_widget_set_sensitive(GTK_WIDGET(data), TRUE);
461 }
462