* Create signal on gconf key change and propagate event to account manager.
[modest] / src / modest-conf-gconf.c
1 /* modest-conf-gconf.c */
2 /* GConf implementation of ModestConf */
3
4 /* insert (c)/licensing information) */
5
6 #include "modest-conf.h"
7 #include <gconf/gconf-client.h>
8
9
10 /* 'private'/'protected' functions */
11 static void   modest_conf_class_init     (ModestConfClass *klass);
12 static void   modest_conf_init           (ModestConf *obj);
13 static void   modest_conf_finalize       (GObject *obj);
14
15 static void   modest_conf_on_change      (GConfClient *client, guint conn_id,
16                                           GConfEntry *entry, gpointer data);
17 /* list my signals */
18 enum {
19         KEY_CHANGED_SIGNAL,
20         LAST_SIGNAL
21 };
22
23 typedef struct _ModestConfPrivate ModestConfPrivate;
24 struct _ModestConfPrivate {
25         GConfClient *gconf_client;
26 };
27 #define MODEST_CONF_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
28                                          MODEST_TYPE_CONF, \
29                                          ModestConfPrivate))
30 /* globals */
31 static GObjectClass *parent_class = NULL;
32
33 static guint signals[LAST_SIGNAL] = {0};
34
35 typedef void (*MarshalFunc_VOID__POINTER_POINTER) (gpointer data1, 
36         gpointer arg_1, gpointer arg_2, gpointer data2);
37                                                     
38   
39 static void
40 modest_marshal_VOID__POINTER_POINTER (GClosure     *closure,
41                                       GValue       *return_value,
42                                       guint         n_param_values,
43                                       const GValue *param_values,
44                                       gpointer      invocation_hint,
45                                       gpointer      marshal_data)
46 {
47         MarshalFunc_VOID__POINTER_POINTER callback;
48         GCClosure *cc = (GCClosure*) closure;
49         gpointer data1, data2;
50
51         g_return_if_fail (n_param_values == 3);
52
53         if (G_CCLOSURE_SWAP_DATA (closure)) {
54                 data1 = closure->data;
55                 data2 = g_value_peek_pointer (param_values + 0);
56         } else {
57                 data1 = g_value_peek_pointer (param_values + 0);
58                 data2 = closure->data;
59         }
60         
61         callback = (MarshalFunc_VOID__POINTER_POINTER) (marshal_data ? marshal_data : cc->callback);
62
63         callback (data1, g_value_get_pointer (param_values + 1),
64                   g_value_get_pointer (param_values + 2), data2);
65 }
66
67 void 
68 modest_conf_key_changed (ModestConf* self, const gchar *key, const gchar *new_value)
69 {
70
71 }
72
73
74 GType
75 modest_conf_get_type (void)
76 {
77         static GType my_type = 0;
78         if (!my_type) {
79                 static const GTypeInfo my_info = {
80                         sizeof(ModestConfClass),
81                         NULL,           /* base init */
82                         NULL,           /* base finalize */
83                         (GClassInitFunc) modest_conf_class_init,
84                         NULL,           /* class finalize */
85                         NULL,           /* class data */
86                         sizeof(ModestConf),
87                         1,              /* n_preallocs */
88                         (GInstanceInitFunc) modest_conf_init,
89                 };
90                 my_type = g_type_register_static (G_TYPE_OBJECT,
91                                                   "ModestConf",
92                                                   &my_info, 0);
93         }
94         return my_type;
95 }
96
97 static void
98 modest_conf_class_init (ModestConfClass *klass)
99 {
100         GObjectClass *gobject_class;
101         gobject_class = (GObjectClass*) klass;
102
103         parent_class            = g_type_class_peek_parent (klass);
104         gobject_class->finalize = modest_conf_finalize;
105
106         g_type_class_add_private (gobject_class, sizeof(ModestConfPrivate));
107         
108         klass->key_changed = modest_conf_key_changed;
109
110         signals[KEY_CHANGED_SIGNAL] = 
111                 g_signal_new ("key-changed", 
112                               G_TYPE_FROM_CLASS (gobject_class), G_SIGNAL_RUN_LAST,
113                               G_STRUCT_OFFSET(ModestConfClass, key_changed),
114                               NULL, NULL,
115                               modest_marshal_VOID__POINTER_POINTER,
116                               G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER);
117 }
118
119 static void
120 modest_conf_init (ModestConf *obj)
121 {
122         GConfClient *conf = NULL;
123         ModestConfPrivate *priv = MODEST_CONF_GET_PRIVATE(obj);
124         GError *err      = NULL;
125         
126         priv->gconf_client = NULL;
127         
128         conf = gconf_client_get_default ();
129         if (!conf) {
130                 g_warning ("could not get gconf client");
131                 return;
132         }
133
134         /* FIXME: is PRELOAD_NONE the most efficient? */
135         gconf_client_add_dir (conf, MODEST_CONF_NAMESPACE,
136                               GCONF_CLIENT_PRELOAD_NONE, &err);
137         if (err) {
138                 g_warning ("error with gconf_client_add_dir: %d:%s",
139                            err->code, err->message);
140                 g_object_unref (conf);
141                 g_error_free (err);
142                 return;
143         }
144
145         gconf_client_notify_add (conf, MODEST_CONF_NAMESPACE,
146                                  modest_conf_on_change,
147                                  obj, NULL, &err);
148         if (err) {
149                 g_warning ("error with gconf_client_notify_add: %d:%s",
150                            err->code, err->message);
151                 g_object_unref (conf);
152                 g_error_free (err);
153                 return;
154         }
155
156         /* all went well! */
157         priv->gconf_client = conf;
158         return;
159 }
160
161 static void
162 modest_conf_finalize (GObject *obj)
163 {
164         ModestConfPrivate *priv = MODEST_CONF_GET_PRIVATE(obj);
165         if (priv->gconf_client) {
166                 gconf_client_suggest_sync (priv->gconf_client, NULL);
167                 g_object_unref (priv->gconf_client);
168         }       
169 }
170
171 GObject*
172 modest_conf_new (void)
173 {
174         ModestConf *conf = MODEST_CONF(g_object_new(MODEST_TYPE_CONF, NULL));
175         if (!conf) {
176                 g_warning ("failed to init ModestConf (GConf)");
177                 return NULL;
178         }
179
180         ModestConfPrivate *priv = MODEST_CONF_GET_PRIVATE(conf);
181         if (!priv->gconf_client) {
182                 g_warning ("failed to init gconf");
183                 g_object_unref (conf);
184                 return NULL;
185         }
186         
187         return G_OBJECT(conf);
188 }
189
190
191 gchar*
192 modest_conf_get_string (ModestConf* self, const gchar* key, GError **err)
193 {
194         ModestConfPrivate *priv;
195         
196         g_return_val_if_fail (self, NULL);
197         g_return_val_if_fail (key,  NULL);
198
199         priv = MODEST_CONF_GET_PRIVATE(self);
200         return gconf_client_get_string (priv->gconf_client, key, err);
201 }
202
203
204 gint
205 modest_conf_get_int (ModestConf* self, const gchar* key, GError **err)
206 {
207         ModestConfPrivate *priv;
208
209         g_return_val_if_fail (self, -1);
210         g_return_val_if_fail (key, -1);
211
212         priv = MODEST_CONF_GET_PRIVATE(self);
213         
214         return gconf_client_get_int (priv->gconf_client, key, err);
215 }
216
217
218 gboolean
219 modest_conf_get_bool (ModestConf* self, const gchar* key, GError **err)
220 {
221         ModestConfPrivate *priv;
222
223         g_return_val_if_fail (self, FALSE);
224         g_return_val_if_fail (key, FALSE);
225
226         priv = MODEST_CONF_GET_PRIVATE(self);
227         
228         return gconf_client_get_bool (priv->gconf_client, key, err);
229 }
230
231
232 gboolean
233 modest_conf_set_string (ModestConf* self, const gchar* key, const gchar* val,
234                         GError **err)
235 {
236         ModestConfPrivate *priv;
237                 
238         g_return_val_if_fail (self,FALSE);
239         g_return_val_if_fail (key, FALSE);
240         
241         priv = MODEST_CONF_GET_PRIVATE(self);
242
243         if (!gconf_client_key_is_writable(priv->gconf_client,key,err)) {
244                 g_warning ("'%s' is not writable", key);
245                 return FALSE;
246         }
247                         
248         return gconf_client_set_string (priv->gconf_client, key, val, err);     
249 }
250
251
252 gboolean
253 modest_conf_set_int  (ModestConf* self, const gchar* key, gint val,
254                       GError **err)
255 {
256         ModestConfPrivate *priv;
257                 
258         g_return_val_if_fail (self,FALSE);
259         g_return_val_if_fail (key, FALSE);
260         
261         priv = MODEST_CONF_GET_PRIVATE(self);
262
263         if (!gconf_client_key_is_writable(priv->gconf_client,key,err)) {
264                 g_warning ("'%s' is not writable", key);
265                 return FALSE;
266         }
267                         
268         return gconf_client_set_int (priv->gconf_client, key, val, err);        
269 }
270
271
272 gboolean
273 modest_conf_set_bool (ModestConf* self, const gchar* key, gboolean val,
274                       GError **err)
275 {
276         ModestConfPrivate *priv;
277                 
278         g_return_val_if_fail (self,FALSE);
279         g_return_val_if_fail (key, FALSE);
280         
281         priv = MODEST_CONF_GET_PRIVATE(self);
282
283         if (!gconf_client_key_is_writable(priv->gconf_client,key, err)) {
284                 g_warning ("'%s' is not writable", key);
285                 return FALSE;
286         }
287                         
288         return gconf_client_set_bool (priv->gconf_client,key,val, err);
289 }
290
291
292
293
294 GSList*
295 modest_conf_list_subkeys (ModestConf* self, const gchar* key, GError **err)
296 {
297         ModestConfPrivate *priv;
298                 
299         g_return_val_if_fail (self,FALSE);
300         g_return_val_if_fail (key, FALSE);
301         
302         priv = MODEST_CONF_GET_PRIVATE(self);
303                         
304         return gconf_client_all_dirs (priv->gconf_client,key,err);
305 }
306
307
308 gboolean
309 modest_conf_remove_key (ModestConf* self, const gchar* key, GError **err)
310 {
311         ModestConfPrivate *priv;
312                 
313         g_return_val_if_fail (self,FALSE);
314         g_return_val_if_fail (key, FALSE);
315         
316         priv = MODEST_CONF_GET_PRIVATE(self);
317                         
318         return gconf_client_recursive_unset (priv->gconf_client,key,0,err);
319 }
320
321
322
323
324 gboolean
325 modest_conf_key_exists (ModestConf* self, const gchar* key, GError **err)
326 {
327         ModestConfPrivate *priv;
328         
329         g_return_val_if_fail (self,FALSE);
330         g_return_val_if_fail (key, FALSE);
331         
332         priv = MODEST_CONF_GET_PRIVATE(self);
333                         
334         return gconf_client_dir_exists (priv->gconf_client,key,err);
335 }
336
337
338
339
340
341 static void
342 modest_conf_on_change (GConfClient *client, guint conn_id, GConfEntry *entry,
343                         gpointer data)
344 {
345         ModestConf *modest_conf = data;
346         
347         if (!entry->value) {
348                 g_print ("modest: key '%s' unset\n",
349                          gconf_entry_get_key (entry));
350                 g_signal_emit (modest_conf, signals[KEY_CHANGED_SIGNAL], 0, 
351                                gconf_entry_get_key (entry), NULL);
352         } else {
353                 gchar *val = gconf_value_to_string (gconf_entry_get_value(entry));
354                 g_print ("modest: key '%s' set to '%s'\n",
355                          gconf_entry_get_key (entry), val);
356                 g_signal_emit (modest_conf, signals[KEY_CHANGED_SIGNAL], 0, 
357                                gconf_entry_get_key (entry), val);
358                 g_free (val);
359         }
360 }