OSDN Git Service

clear btn, about btn, dicts info ...
[eb123/eb123.git] / src / prefs.c
1
2 #include "defs.h"
3
4 #include "builder.h"
5 #include "dicts.h"
6 #include "history.h"
7 #include "mainwnd.h"
8 #include "popupwnd.h"
9 #include "prefs.h"
10 #include "selection.h"
11 #include "hotkeys.h"
12 #include "textview.h"
13
14 G_DEFINE_TYPE(Prefs, prefs, G_TYPE_OBJECT);
15
16 typedef struct
17 {
18     int type;
19     char *name;
20     union
21     {
22         int i;
23         char *s;
24     } val;
25 } pref1;
26
27 static Prefs *_prefs = NULL;
28
29 static const pref1 prefs_list[] =
30 {
31     {G_TYPE_INT, "headword.maxhits", {50}},
32     {G_TYPE_INT, "dictbar.word_hist", {30}},
33     {G_TYPE_INT, "selection.maxchar", {32}},
34     {G_TYPE_INT, "selection.lookup_started", {0}},
35     {G_TYPE_INT, "hotkeys.ignore_locks", {1}},
36     {G_TYPE_INT, "popupwnd.w", {350}},
37     {G_TYPE_INT, "popupwnd.h", {450}},
38     {G_TYPE_INT, "popupwnd.x", {300}},
39     {G_TYPE_INT, "popupwnd.y", {300}},
40     {G_TYPE_INT, "popupwnd.remember_pos", {0}},
41     {G_TYPE_INT, "popupwnd.lock", {0}},
42     {G_TYPE_INT, "popupwnd.jap_only", {0}},
43     {G_TYPE_INT, "popupwnd.timeout", {2000}},
44     {G_TYPE_INT, "popupwnd.maxhits", {5}},
45     {G_TYPE_INT, "popupwnd.search_method", {0}},
46     {G_TYPE_INT, "mainwnd.x", {300}},
47     {G_TYPE_INT, "mainwnd.y", {300}},
48     {G_TYPE_INT, "mainwnd.w", {500}},
49     {G_TYPE_INT, "mainwnd.h", {400}},
50     {G_TYPE_INT, "mainwnd.remember_pos", {1}},
51     {G_TYPE_INT, "mainwnd.search", {0}},
52     {G_TYPE_INT, "mainwnd.custom_font", {0}},
53     {G_TYPE_INT, "paned.tree_width", {185}},
54     {G_TYPE_INT, "paned.tree_height", {210}},
55     {G_TYPE_STRING, "color.link", {.s = "#0000c0"}},
56     {G_TYPE_STRING, "color.keyword", {.s = "#c00000"}},
57     {G_TYPE_STRING, "color.title", {.s = "#306090"}}
58 };
59
60 //static GParamSpec *obj_properties[SZ(prefs_list) + 2] = { NULL, };
61
62 static void prefs_class_init(PrefsClass *klass)
63 {
64 }
65
66 static void prefs_init(Prefs *self)
67 {
68     if(!_prefs)
69         _prefs = self;
70     else
71         g_assert(1);
72     //GstElementClass *gstelement_class = GST_ELEMENT_CLASS(klass);
73     //gst_element_class_add_pad_template(gstelement_class, gst_static_pad_template_get(&prefs_template));
74
75     g_datalist_init(&(self->data));
76
77     hotkeys_list_init();
78
79     gchar *home_dir = getenv("HOME");
80     gchar *userdir = g_strdup_printf("%s%s.%s", home_dir, G_DIR_SEPARATOR_S, PACKAGE_NAME);
81     prefs_set_str(self, "userdir", userdir);
82
83     GDir *dir;
84     if((dir = g_dir_open(userdir, 0, NULL)) == NULL)
85     {
86         if(g_mkdir_with_parents(userdir, 493))
87         {
88             LOG(LOG_CRITICAL, "Failed to create directory: %s\n", userdir);
89             exit(1);
90         }
91     }
92     else
93         g_dir_close(dir);
94
95     prefs_load(self);
96 }
97
98 enum
99 {
100     PREF_TITLE,
101     PREF_NUMBER,
102     PREF_N
103 };
104
105 extern Builder *_builder;
106
107 static void prefs_selection_changed_cb(GtkTreeSelection *selection, gpointer data)
108 {
109     GtkTreeIter iter;
110     GtkTreeModel *model;
111     if(!gtk_tree_selection_get_selected(selection, &model, &iter)) return;
112
113     GtkNotebook *notebook = GTK_NOTEBOOK(data);
114     gint n;
115     gtk_tree_model_get(model, &iter, 1, &n, -1);
116     if(n >= 0)
117         gtk_notebook_set_current_page(notebook, n);
118 }
119
120 static const pref1* prefs_get1(Prefs *p, const gchar *str)
121 {
122     gint i;
123     for(i = 0; i < SZ(prefs_list); i++)
124     {
125         const pref1 *p1 = &(prefs_list[i]);
126         if(!g_strcmp0(p1->name, str))
127             return p1;
128     }
129     return 0;
130 }
131
132 static void prefs_set_widget_data(Prefs *p, Builder *b, const gchar *str)
133 {
134     const pref1 *p1 = prefs_get1(p, str);
135     if(p1->type == G_TYPE_INT)
136     {
137         gint value = prefs_get_int(p, str);
138         builder_set_int(b, str, value);
139     }
140     if(p1->type == G_TYPE_STRING)
141     {
142         gchar *value = prefs_get_str(p, str);
143         builder_set_str(b, str, value);
144     }
145 }
146
147 static void prefs_get_widget_data(Prefs *p, Builder *b, const gchar *str)
148 {
149     pref1 *p1 = prefs_get1(p, str);
150     if(p1->type == G_TYPE_INT)
151     {
152         gint value = builder_get_int(b, str);
153         prefs_set_int(p, str, value);
154     }
155     if(p1->type == G_TYPE_STRING)
156     {
157         gchar *value = builder_get_str(b, str);
158         prefs_set_str(p, str, value);
159     }
160 }
161
162 gboolean on_preferences_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
163 {
164     gtk_widget_hide(widget);
165     return TRUE;
166 }
167
168 void prefs_ok_btn_clicked_cb(GtkWidget *widget, gpointer data)
169 {
170     Mainwnd *mainwnd = MAINWND(data);
171     GtkWidget *wnd = gtk_widget_get_toplevel(widget);
172     gtk_widget_hide(wnd);
173     gint i;
174     for(i = 0; i < SZ(prefs_list); i++)
175     {
176         pref1 *p1 = &(prefs_list[i]);
177         prefs_get_widget_data(mainwnd->prefs, mainwnd->builder, p1->name);
178     }
179     prefs_save(mainwnd->prefs);
180 }
181
182 void prefs_cancel_btn_clicked_cb(GtkWidget *widget, gpointer data)
183 {
184     GtkWidget *wnd = gtk_widget_get_toplevel(widget);
185     gtk_widget_hide(wnd);
186 }
187
188 void prefs_close_wnd()
189 {
190     GtkWidget *w = GTK_WIDGET(gtk_builder_get_object(GTK_BUILDER(_builder), "btn_prefs_cancel"));
191     prefs_cancel_btn_clicked_cb(w, NULL);
192 }
193
194 void on_btn_prefs_clicked(GtkWidget *widget, gpointer data)
195 {
196     Mainwnd *mainwnd = MAINWND(data);
197     Prefs *prefs = mainwnd->prefs;
198
199     GtkWidget *wnd = GTK_WIDGET(gtk_builder_get_object(GTK_BUILDER(mainwnd->builder), "preferences"));
200     gtk_widget_hide_on_delete(wnd);
201
202     GtkTreeView *prefs_tree = GTK_TREE_VIEW(gtk_builder_get_object(GTK_BUILDER(mainwnd->builder), "prefs_tree"));
203     GtkTreeStore *prefs_store = GTK_TREE_STORE(gtk_builder_get_object(GTK_BUILDER(mainwnd->builder), "prefs_store"));
204     GtkTreeSelection *select = gtk_tree_view_get_selection(prefs_tree);
205     GtkTreeIter iter1, iter2;
206     static gboolean preparewnd = True;
207     if(preparewnd)
208     {
209         GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
210         GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(_("Items"), renderer, "text", 0, NULL);
211         gtk_tree_view_append_column(prefs_tree, column);
212
213         GtkNotebook *notebook = GTK_NOTEBOOK(gtk_builder_get_object(GTK_BUILDER(mainwnd->builder), "notebook1"));
214         gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
215         g_signal_connect(G_OBJECT(select), "changed", G_CALLBACK(prefs_selection_changed_cb), notebook);
216
217         gint n = gtk_notebook_get_n_pages(notebook);
218         gint i;
219         for(i = 0; i < n; i++)
220         {
221             GtkWidget *p = gtk_notebook_get_nth_page(notebook, i);
222             GtkWidget *l = gtk_notebook_get_tab_label(notebook, p);
223             const gchar *text = gtk_label_get_text(GTK_LABEL(l));
224             if(text[0] != '_')
225             {
226                 gtk_tree_store_append(prefs_store, &iter1, NULL);
227                 gtk_tree_store_set(prefs_store, &iter1, 0, _(text), 1, 0, -1);
228             }
229             else
230             {
231                 gtk_tree_store_append(prefs_store, &iter2, &iter1);
232                 gtk_tree_store_set(prefs_store, &iter2, 0, _(&(text[1])), 1, i, -1);
233             }
234         }
235         for(i = 0; i < SZ(prefs_list); i++)
236         {
237             pref1 *p1 = &(prefs_list[i]);
238             prefs_set_widget_data(prefs, mainwnd->builder, p1->name);
239         }
240         preparewnd = False;
241     }
242     if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(prefs_store), &iter1))
243     {
244         gtk_tree_selection_select_iter(select, &iter1);
245     }
246     gtk_tree_view_expand_all(prefs_tree);
247     gtk_widget_show_all(wnd);
248 }
249
250 void prefs_save(Prefs *self)
251 {
252     gint i, j;
253     gchar filename[PATH_MAX], buff[128], *str;
254     xmlDocPtr doc = xmlNewDoc((xmlChar*)"1.0");
255     doc->children = xmlNewDocRawNode(doc, NULL, (xmlChar*)"Prefs", NULL);
256
257     gchar *userdir = prefs_get_str(self, "userdir");
258     sprintf(filename, "%s%s%s", userdir, G_DIR_SEPARATOR_S, FILENAME_PREFS);
259     
260     for(i = 0 ; i < SZ(prefs_list); i++)
261     {
262         const pref1 *p = &(prefs_list[i]);
263         switch(prefs_list[i].type)
264         {
265         case G_TYPE_INT:
266         case G_TYPE_BOOLEAN:
267             j = prefs_get_int(self, p->name);
268             sprintf(buff, "%d", j);
269             break;
270         case G_TYPE_FLOAT:
271             break;
272         case G_TYPE_STRING:
273             str = prefs_get_str(self, p->name);
274             sprintf(buff, "%s", str);
275             break;
276         }
277         xmlNodePtr node = xmlAddChild(doc->children, xmlNewNode(NULL, (xmlChar*)prefs_list[i].name));
278         xmlNewProp(node, (xmlChar*)"value", (xmlChar*)buff);
279     }
280     xmlSaveFormatFileEnc(filename, doc, "utf8", 0);
281     xmlFreeDoc(doc);
282 }
283
284 void prefs_load_elem(void *ctx, const xmlChar *name, const xmlChar **atts)
285 {
286     gint i;
287     xmlParserCtxt *ctxt = (xmlParserCtxt*)ctx;
288     xmlSAXHandler *cb = ctxt->sax;
289     Prefs *prefs = PREFS(cb->_private);
290     for(i = 0; i < SZ(prefs_list); i++)
291     {
292         if(!g_strcmp0((gchar*)name, prefs_list[i].name))
293         {
294             switch(prefs_list[i].type){
295             case G_TYPE_INT:
296             case G_TYPE_BOOLEAN:
297                 prefs_set_int(prefs, (const gchar*)name, atoi((gchar*)atts[1]));
298                 break;
299             case G_TYPE_STRING:
300                 g_printf("%s, %s\n", (const gchar*)name, (gchar*)atts[1]);
301                 prefs_set_str(prefs, (const gchar*)name, strdup((gchar*)atts[1]));
302                 g_printf("%s\n", prefs_get_str(prefs, (const gchar*)name));
303                 break;
304             case G_TYPE_FLOAT:
305                 break;
306             }
307         }
308     }
309 }
310
311 void prefs_load(Prefs *self)
312 {
313     gchar filename[PATH_MAX];
314     xmlSAXHandler cb;
315     gchar *userdir = prefs_get_str(self, "userdir");
316     sprintf(filename, "%s%s%s", userdir, G_DIR_SEPARATOR_S, FILENAME_PREFS);
317     if(!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
318         return;
319     memset(&cb, 0, sizeof(xmlSAXHandler));
320     cb.startElement = &prefs_load_elem;
321     cb._private = self;
322     xmlDocPtr doc = xmlSAXParseFile(&cb, filename, 0);
323     xmlFreeDoc(doc);
324 }
325
326 gint prefs_get_int(Prefs *self, const gchar *name)
327 {
328     gpointer ptr = g_datalist_get_data(&self->data, name);
329     return (gint)ptr;
330 }
331
332 void prefs_set_int(Prefs *self, const gchar *name, gint value)
333 {
334     g_datalist_set_data(&self->data, name, (gpointer)value);
335 }
336
337 gchar* prefs_get_str(Prefs *self, const gchar *name)
338 {
339     gpointer ptr = g_datalist_get_data(&self->data, name);
340     return (gchar*)ptr;
341 }
342
343 void prefs_set_str(Prefs *self, const gchar *name, gchar *value)
344 {
345     g_datalist_set_data(&self->data, name, (gpointer)value);
346 }
347
348 gchar* prefs_get_userdir()
349 {
350     return prefs_get_str(_prefs, "userdir");
351 }
352