1 /*
2  * Copyright © 2014  Red Hat, Inc. All rights reserved.
3  * Copyright © 2014  Ding-Yi Chen <dchen@redhat.com>
4  *
5  * This file is part of the ibus-chewing Project.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20  */
21 
22 #include <ibus.h>
23 #include <glib.h>
24 #include <gconf/gconf.h>
25 #include <gconf/gconf-client.h>
26 #include "MakerDialogUtil.h"
27 #include "GConf2Backend.h"
28 
29 static GHashTable *camalCasedKeyTable = NULL;
30 
31 gchar *gconf2_backend_get_key(MkdgBackend * backend,
32 			      const gchar * section, const gchar * key,
33 			      gpointer userData);
34 
gconf_value_to_g_value(GConfValue * confValue,GValue * value)35 static GValue *gconf_value_to_g_value(GConfValue * confValue,
36 				      GValue * value)
37 {
38     GType gType = G_VALUE_TYPE(value);
39     switch (confValue->type) {
40     case GCONF_VALUE_BOOL:
41 	if (gType != G_TYPE_BOOLEAN) {
42 	    return NULL;
43 	}
44 	g_value_set_boolean(value, gconf_value_get_bool(confValue));
45 	break;
46     case GCONF_VALUE_INT:
47 	if (gType != G_TYPE_INT && gType != G_TYPE_UINT) {
48 	    return NULL;
49 	} else if (gType == G_TYPE_INT) {
50 	    g_value_set_int(value, gconf_value_get_int(confValue));
51 	} else {
52 	    g_value_set_uint(value, gconf_value_get_int(confValue));
53 	}
54 	break;
55     case GCONF_VALUE_STRING:
56 	if (gType != G_TYPE_STRING) {
57 	    return NULL;
58 	}
59 	g_value_set_string(value, gconf_value_get_string(confValue));
60 	break;
61     default:
62 	return NULL;
63     }
64     return value;
65 }
66 
gconf_value_new_g_value(GValue * value)67 static GConfValue *gconf_value_new_g_value(GValue * value)
68 {
69     GConfValue *confValue;
70     GType gType = G_VALUE_TYPE(value);
71     switch (gType) {
72     case G_TYPE_BOOLEAN:
73 	confValue = gconf_value_new(GCONF_VALUE_BOOL);
74 	gconf_value_set_bool(confValue, g_value_get_boolean(value));
75 	break;
76     case G_TYPE_INT:
77 	confValue = gconf_value_new(GCONF_VALUE_INT);
78 	gconf_value_set_int(confValue, g_value_get_int(value));
79 	break;
80     case G_TYPE_UINT:
81 	confValue = gconf_value_new(GCONF_VALUE_INT);
82 	gconf_value_set_int(confValue, g_value_get_uint(value));
83 	break;
84     case G_TYPE_STRING:
85 	confValue = gconf_value_new(GCONF_VALUE_STRING);
86 	gconf_value_set_string(confValue, g_value_get_string(value));
87 	break;
88     default:
89 	return NULL;
90     }
91     return confValue;
92 }
93 
94 #define KEY_BUFFER_SIZE 100
to_real_key(gchar * confKey,MkdgBackend * backend,const gchar * section,const gchar * key)95 static gchar *to_real_key(gchar * confKey, MkdgBackend * backend,
96 			  const gchar * section, const gchar * key)
97 {
98     gchar *camalCasedKey =
99 	gconf2_backend_get_key(backend, section, key, NULL);
100 
101     if (!STRING_IS_EMPTY(backend->basePath)) {
102 	g_strlcpy(confKey, backend->basePath, KEY_BUFFER_SIZE);
103 	g_strlcat(confKey, "/", KEY_BUFFER_SIZE);
104     } else {
105 	g_strlcpy(confKey, "/", KEY_BUFFER_SIZE);
106     }
107 
108     if (!STRING_IS_EMPTY(section)) {
109 	g_strlcat(confKey, section, KEY_BUFFER_SIZE);
110 	g_strlcat(confKey, "/", KEY_BUFFER_SIZE);
111     }
112     g_strlcat(confKey, camalCasedKey, KEY_BUFFER_SIZE);
113     return confKey;
114 }
115 
116 /*============================================
117  * Interface routines
118  */
gconf2_backend_get_key(MkdgBackend * backend,const gchar * section,const gchar * key,gpointer userData)119 gchar *gconf2_backend_get_key(MkdgBackend * backend,
120 			      const gchar * section, const gchar * key,
121 			      gpointer userData)
122 {
123     gchar *camalCasedKey =
124 	(gchar *) g_hash_table_lookup(camalCasedKeyTable, key);
125     if (camalCasedKey == NULL) {
126 	camalCasedKey = mkdg_str_dash_to_camel(key);
127 	g_hash_table_insert(camalCasedKeyTable, (gpointer) key,
128 			    camalCasedKey);
129     }
130     return camalCasedKey;
131 }
132 
gconf2_backend_read_value(MkdgBackend * backend,GValue * value,const gchar * section,const gchar * key,gpointer userData)133 GValue *gconf2_backend_read_value(MkdgBackend * backend,
134 				  GValue * value,
135 				  const gchar * section,
136 				  const gchar * key, gpointer userData)
137 {
138     mkdg_log(DEBUG, "gconf2_backend_read_value(-,-,%s,%s,-):", section,
139 	     key);
140     GConfClient *config = (GConfClient *) backend->config;
141     GError *err = NULL;
142     gchar confKey[KEY_BUFFER_SIZE];
143     to_real_key(confKey, backend, section, key);
144     GConfValue *confValue = gconf_client_get(config, confKey, &err);
145 
146     if (confValue == NULL) {
147 	mkdg_log(ERROR,
148 		 "gconf2_backend_read_value(-,-,%s,%s,-): Failed to retrieve confValue",
149 		 section, key);
150 	return NULL;
151     }
152     if (err != NULL) {
153 	mkdg_log(ERROR, "gconf2_backend_read_value(-,-,%s,%s,-): %s",
154 		 section, key, err->message);
155 	return NULL;
156     }
157     return gconf_value_to_g_value(confValue, value);
158 }
159 
gconf2_backend_write_value(MkdgBackend * backend,GValue * value,const gchar * section,const gchar * key,gpointer userData)160 gboolean gconf2_backend_write_value(MkdgBackend * backend,
161 				    GValue * value,
162 				    const gchar * section,
163 				    const gchar * key, gpointer userData)
164 {
165     GConfClient *config = (GConfClient *) backend->config;
166     GError *err = NULL;
167     gchar confKey[KEY_BUFFER_SIZE];
168     to_real_key(confKey, backend, section, key);
169     GConfValue *confValue = gconf_value_new_g_value(value);
170     gconf_client_set(config, confKey, confValue, &err);
171     gconf_value_free(confValue);
172     if (err != NULL) {
173 	mkdg_log(ERROR, "gconf2_backend_write_value(-,-,%s,%s,-): %s",
174 		 section, key, err->message);
175 	return FALSE;
176     }
177     return TRUE;
178 }
179 
gconf2_backend_new(const gchar * basePath,gpointer auxData)180 MkdgBackend *gconf2_backend_new(const gchar * basePath, gpointer auxData)
181 {
182     GConfClient *client = gconf_client_get_default();
183     MkdgBackend *result = mkdg_backend_new(GCONF2_BACKEND_ID,
184 					   (gpointer) client, basePath,
185 					   auxData);
186     camalCasedKeyTable = g_hash_table_new(g_str_hash, g_str_equal);
187     result->getKeyFunc = gconf2_backend_get_key;
188     result->readFunc = gconf2_backend_read_value;
189     result->writeFunc = gconf2_backend_write_value;
190     return result;
191 }
192