* added the 6 bug fixes for week 27 release for diablo pe2
[modest] / src / modest-conf.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <gconf/gconf-client.h>
31 #include <config.h>
32 #include <string.h>
33 #include <glib/gi18n.h>
34 #include "modest-conf.h"
35 #include "modest-marshal.h"
36 #include <stdio.h>
37
38 static void   modest_conf_class_init     (ModestConfClass *klass);
39
40 static void   modest_conf_init           (ModestConf *obj);
41
42 static void   modest_conf_finalize       (GObject *obj);
43
44 static void   modest_conf_on_change      (GConfClient *client, guint conn_id,
45                                           GConfEntry *entry, gpointer data);
46
47 static GConfValueType modest_conf_type_to_gconf_type (ModestConfValueType value_type, 
48                                                       GError **err);
49
50 /* list my signals */
51 enum {
52         KEY_CHANGED_SIGNAL,
53         LAST_SIGNAL
54 };
55 static guint signals[LAST_SIGNAL] = {0}; 
56
57
58 typedef struct _ModestConfPrivate ModestConfPrivate;
59 struct _ModestConfPrivate {
60         GConfClient *gconf_client;
61 };
62 #define MODEST_CONF_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
63                                                                      MODEST_TYPE_CONF, \
64                                                                      ModestConfPrivate))
65 /* globals */
66 static GObjectClass *parent_class = NULL;
67
68 GType
69 modest_conf_get_type (void)
70 {
71         static GType my_type = 0;
72         if (!my_type) {
73                 static const GTypeInfo my_info = {
74                         sizeof(ModestConfClass),
75                         NULL,           /* base init */
76                         NULL,           /* base finalize */
77                         (GClassInitFunc) modest_conf_class_init,
78                         NULL,           /* class finalize */
79                         NULL,           /* class data */
80                         sizeof(ModestConf),
81                         1,              /* n_preallocs */
82                         (GInstanceInitFunc) modest_conf_init,
83                         NULL
84                 };
85                 my_type = g_type_register_static (G_TYPE_OBJECT,
86                                                   "ModestConf",
87                                                   &my_info, 0);
88         }
89         return my_type;
90 }
91
92 static void
93 modest_conf_class_init (ModestConfClass *klass)
94 {
95         GObjectClass *gobject_class;
96         gobject_class = (GObjectClass*) klass;
97
98         parent_class            = g_type_class_peek_parent (klass);
99         gobject_class->finalize = modest_conf_finalize;
100
101         g_type_class_add_private (gobject_class, sizeof(ModestConfPrivate));
102         
103         signals[KEY_CHANGED_SIGNAL] =
104                 g_signal_new ("key_changed",
105                               G_TYPE_FROM_CLASS (gobject_class),
106                               G_SIGNAL_RUN_FIRST,
107                               G_STRUCT_OFFSET (ModestConfClass,key_changed),
108                               NULL, NULL,
109                               modest_marshal_VOID__STRING_INT_INT,
110                               G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT); 
111 }
112
113 static void
114 modest_conf_init (ModestConf *obj)
115 {
116         GConfClient *conf = NULL;
117         GError *error = NULL;
118         ModestConfPrivate *priv = MODEST_CONF_GET_PRIVATE(obj);
119
120         priv->gconf_client = NULL;
121         
122         conf = gconf_client_get_default ();
123         if (!conf) {
124                 g_printerr ("modest: could not get gconf client\n");
125                 return;
126         }
127
128         priv->gconf_client = conf;
129
130         /* All the tree will be listened */
131         gconf_client_add_dir (priv->gconf_client,
132                               "/apps/modest",
133                               GCONF_CLIENT_PRELOAD_NONE,
134                               &error);
135
136         /* Notify every change under namespace */
137         if (!error)
138                 gconf_client_notify_add (priv->gconf_client,
139                                          "/apps/modest",
140                                          modest_conf_on_change,
141                                          obj,
142                                          NULL,
143                                          &error);
144 }
145
146 static void
147 modest_conf_finalize (GObject *obj)
148 {
149         ModestConfPrivate *priv = MODEST_CONF_GET_PRIVATE(obj);
150         if (priv->gconf_client) {
151
152                 gconf_client_suggest_sync (priv->gconf_client, NULL);
153
154                 g_object_unref (priv->gconf_client);
155                 priv->gconf_client = NULL;
156         }       
157
158         G_OBJECT_CLASS(parent_class)->finalize (obj);
159 }
160
161 ModestConf*
162 modest_conf_new (void)
163 {
164         ModestConf *conf;
165         ModestConfPrivate *priv;
166         
167         conf = MODEST_CONF(g_object_new(MODEST_TYPE_CONF, NULL));
168         if (!conf) {
169                 g_printerr ("modest: failed to init ModestConf (GConf)\n");
170                 return NULL;
171         }
172
173         priv = MODEST_CONF_GET_PRIVATE(conf);
174         if (!priv->gconf_client) {
175                 g_printerr ("modest: failed to init gconf\n");
176                 g_object_unref (conf);
177                 return NULL;
178         }
179         
180         return conf;
181 }
182
183
184 gchar*
185 modest_conf_get_string (ModestConf* self, const gchar* key, GError **err)
186 {
187         ModestConfPrivate *priv;
188         
189         g_return_val_if_fail (self, NULL);
190         g_return_val_if_fail (key,  NULL);
191
192         priv = MODEST_CONF_GET_PRIVATE(self);
193         return gconf_client_get_string (priv->gconf_client, key, err);
194 }
195
196
197 gint
198 modest_conf_get_int (ModestConf* self, const gchar* key, GError **err)
199 {
200         ModestConfPrivate *priv;
201
202         g_return_val_if_fail (self, -1);
203         g_return_val_if_fail (key, -1);
204
205         priv = MODEST_CONF_GET_PRIVATE(self);
206         
207         return gconf_client_get_int (priv->gconf_client, key, err);
208 }
209
210 gdouble
211 modest_conf_get_float (ModestConf* self, const gchar* key, GError **err)
212 {
213         ModestConfPrivate *priv;
214
215         g_return_val_if_fail (self, -1);
216         g_return_val_if_fail (key, -1);
217
218         priv = MODEST_CONF_GET_PRIVATE(self);
219         
220         return gconf_client_get_float (priv->gconf_client, key, err);
221 }
222
223 gboolean
224 modest_conf_get_bool (ModestConf* self, const gchar* key, GError **err)
225 {
226         ModestConfPrivate *priv;
227
228         g_return_val_if_fail (self, FALSE);
229         g_return_val_if_fail (key, FALSE);
230
231         priv = MODEST_CONF_GET_PRIVATE(self);
232         
233         return gconf_client_get_bool (priv->gconf_client, key, err);
234 }
235
236
237 GSList * 
238 modest_conf_get_list (ModestConf* self, const gchar* key, ModestConfValueType list_type,
239                       GError **err)
240 {
241         ModestConfPrivate *priv;
242         GConfValueType gconf_type;
243        
244         g_return_val_if_fail (self, NULL);
245         g_return_val_if_fail (key,  NULL);
246
247         priv = MODEST_CONF_GET_PRIVATE(self);
248
249         gconf_type = modest_conf_type_to_gconf_type (list_type, err);
250
251         return gconf_client_get_list (priv->gconf_client, key, gconf_type, err);
252 }
253
254
255
256
257 gboolean
258 modest_conf_set_string (ModestConf* self, const gchar* key, const gchar* val,
259                         GError **err)
260 {
261         ModestConfPrivate *priv;
262                 
263         g_return_val_if_fail (self,FALSE);
264         g_return_val_if_fail (key, FALSE);
265         g_return_val_if_fail (val, FALSE);
266         
267         priv = MODEST_CONF_GET_PRIVATE(self);
268
269         if (!gconf_client_key_is_writable(priv->gconf_client,key,err)) {
270                 g_printerr ("modest: '%s' is not writable\n", key);
271                 return FALSE;
272         }
273                         
274         return gconf_client_set_string (priv->gconf_client, key, val, err);
275 }
276
277 gboolean
278 modest_conf_set_int  (ModestConf* self, const gchar* key, gint val,
279                       GError **err)
280 {
281         ModestConfPrivate *priv;
282                 
283         g_return_val_if_fail (self,FALSE);
284         g_return_val_if_fail (key, FALSE);
285         
286         priv = MODEST_CONF_GET_PRIVATE(self);
287
288         if (!gconf_client_key_is_writable(priv->gconf_client,key,err)) {
289                 g_printerr ("modest: '%s' is not writable\n", key);
290                 return FALSE;
291         }
292                         
293         return gconf_client_set_int (priv->gconf_client, key, val, err);
294 }
295
296 gboolean
297 modest_conf_set_float (ModestConf* self, 
298                        const gchar* key, 
299                        gdouble val,
300                        GError **err)
301 {
302         ModestConfPrivate *priv;
303                 
304         g_return_val_if_fail (self,FALSE);
305         g_return_val_if_fail (key, FALSE);
306         
307         priv = MODEST_CONF_GET_PRIVATE(self);
308
309         if (!gconf_client_key_is_writable(priv->gconf_client,key,err)) {
310                 g_printerr ("modest: '%s' is not writable\n", key);
311                 return FALSE;
312         }
313                         
314         return gconf_client_set_float (priv->gconf_client, key, val, err);
315 }
316
317
318 gboolean
319 modest_conf_set_bool (ModestConf* self, const gchar* key, gboolean val,
320                       GError **err)
321 {
322         ModestConfPrivate *priv;
323                 
324         g_return_val_if_fail (self,FALSE);
325         g_return_val_if_fail (key, FALSE);
326         
327         priv = MODEST_CONF_GET_PRIVATE(self);
328
329         if (!gconf_client_key_is_writable(priv->gconf_client,key, err)) {
330                 g_warning ("modest: '%s' is not writable\n", key);
331                 return FALSE;
332         }
333
334         return gconf_client_set_bool (priv->gconf_client, key, val, err);
335 }
336
337
338 gboolean
339 modest_conf_set_list (ModestConf* self, const gchar* key, 
340                       GSList *val, ModestConfValueType list_type, 
341                       GError **err)
342 {
343         ModestConfPrivate *priv;
344         GConfValueType gconf_type;
345        
346         g_return_val_if_fail (self, FALSE);
347         g_return_val_if_fail (key, FALSE);
348
349         priv = MODEST_CONF_GET_PRIVATE(self);
350
351         gconf_type = modest_conf_type_to_gconf_type (list_type, err);
352
353         return gconf_client_set_list (priv->gconf_client, key, gconf_type, val, err);
354 }
355
356
357 GSList*
358 modest_conf_list_subkeys (ModestConf* self, const gchar* key, GError **err)
359 {
360         ModestConfPrivate *priv;
361                 
362         g_return_val_if_fail (self,FALSE);
363         g_return_val_if_fail (key, FALSE);
364         
365         priv = MODEST_CONF_GET_PRIVATE(self);
366                         
367         return gconf_client_all_dirs (priv->gconf_client,key,err);
368 }
369
370
371 gboolean
372 modest_conf_remove_key (ModestConf* self, const gchar* key, GError **err)
373 {
374         ModestConfPrivate *priv;
375         gboolean retval;
376         
377         g_return_val_if_fail (self,FALSE);
378         g_return_val_if_fail (key, FALSE);
379         
380         priv = MODEST_CONF_GET_PRIVATE(self);
381                         
382         retval = gconf_client_recursive_unset (priv->gconf_client,key,0,err);
383         gconf_client_suggest_sync (priv->gconf_client, NULL);
384
385         return retval;
386 }
387
388
389 gboolean
390 modest_conf_key_exists (ModestConf* self, const gchar* key, GError **err)
391 {
392         ModestConfPrivate *priv;
393         GConfValue *val;
394
395         g_return_val_if_fail (self,FALSE);
396         g_return_val_if_fail (key, FALSE);
397         
398         priv = MODEST_CONF_GET_PRIVATE(self);
399
400         /* the fast way... */
401         if (gconf_client_dir_exists (priv->gconf_client,key,err))
402                 return TRUE;
403         
404         val = gconf_client_get (priv->gconf_client, key, NULL);
405         if (!val)
406                 return FALSE;
407         else {
408                 gconf_value_free (val);
409                 return TRUE;
410         }       
411 }
412
413
414 gchar*
415 modest_conf_key_escape (const gchar* key)
416 {
417         g_return_val_if_fail (key, NULL);
418         g_return_val_if_fail (strlen (key) > 0, g_strdup (key));
419         
420         return gconf_escape_key (key, strlen(key));
421 }
422
423
424 gchar*
425 modest_conf_key_unescape (const gchar* key)
426 {
427         g_return_val_if_fail (key, NULL);
428
429         return gconf_unescape_key (key, strlen(key));
430 }
431
432 gboolean
433 modest_conf_key_is_valid (const gchar* key)
434 {
435         return gconf_valid_key (key, NULL);
436 }
437
438 static void
439 modest_conf_on_change (GConfClient *client,
440                        guint conn_id,
441                        GConfEntry *entry,
442                        gpointer data)
443 {
444         ModestConfEvent event;
445         const gchar* key;
446
447         event = (entry->value) ? MODEST_CONF_EVENT_KEY_CHANGED : MODEST_CONF_EVENT_KEY_UNSET;
448         key    = gconf_entry_get_key (entry);
449
450         g_signal_emit (G_OBJECT(data),
451                        signals[KEY_CHANGED_SIGNAL], 0,
452                        key, event, conn_id);
453 }
454
455 static GConfValueType
456 modest_conf_type_to_gconf_type (ModestConfValueType value_type, GError **err)
457 {
458         GConfValueType gconf_type;
459
460         switch (value_type) {
461         case MODEST_CONF_VALUE_INT:
462                 gconf_type = GCONF_VALUE_INT;
463                 break;
464         case MODEST_CONF_VALUE_BOOL:
465                 gconf_type = GCONF_VALUE_BOOL;
466                 break;
467         case MODEST_CONF_VALUE_FLOAT:
468                 gconf_type = GCONF_VALUE_FLOAT;
469                 break;
470         case MODEST_CONF_VALUE_STRING:
471                 gconf_type = GCONF_VALUE_STRING;
472                 break;
473         default:
474                 /* FIXME: use MODEST_ERROR, and error code */
475                 gconf_type = GCONF_VALUE_INVALID;
476                 g_printerr ("modest: invalid list value type %d\n", value_type);
477                 *err = g_error_new_literal (0, 0, "invalid list value type");
478         }       
479         return gconf_type;
480 }
481
482 void
483 modest_conf_listen_to_namespace (ModestConf *self,
484                                  const gchar *namespace)
485 {
486         ModestConfPrivate *priv;
487         GError *error = NULL;
488
489         g_return_if_fail (MODEST_IS_CONF (self));
490         g_return_if_fail (namespace);
491         
492         priv = MODEST_CONF_GET_PRIVATE(self);
493
494         /* Add the namespace to the list of the namespaces that will
495            be observed */
496         gconf_client_add_dir (priv->gconf_client,
497                               namespace,
498                               GCONF_CLIENT_PRELOAD_NONE,
499                               &error);
500 }
501
502 void 
503 modest_conf_forget_namespace (ModestConf *self,
504                               const gchar *namespace)
505 {
506         ModestConfPrivate *priv;
507
508         g_return_if_fail (MODEST_IS_CONF (self));
509         g_return_if_fail (namespace);
510         
511         priv = MODEST_CONF_GET_PRIVATE(self);
512
513         /* Remove the namespace to the list of the namespaces that will
514            be observed */
515         gconf_client_remove_dir (priv->gconf_client, namespace, NULL);
516 }