From 809fdd0e3e313c1143cdc32ead6649afbc5bc7f6 Mon Sep 17 00:00:00 2001 From: Rodrigo Moya Date: Tue, 20 Aug 2002 14:04:03 +0000 Subject: new class for config database access and monitoring. 2002-08-16 Rodrigo Moya * e-config-listener.[ch]: new class for config database access and monitoring. * Makefile.am: added new files. svn path=/trunk/; revision=17816 --- e-util/ChangeLog | 7 + e-util/Makefile.am | 2 + e-util/e-config-listener.c | 313 +++++++++++++++++++++++++++++++++++++++++++++ e-util/e-config-listener.h | 53 ++++++++ 4 files changed, 375 insertions(+) create mode 100644 e-util/e-config-listener.c create mode 100644 e-util/e-config-listener.h diff --git a/e-util/ChangeLog b/e-util/ChangeLog index bac53db150..26e78fb47f 100644 --- a/e-util/ChangeLog +++ b/e-util/ChangeLog @@ -1,3 +1,10 @@ +2002-08-16 Rodrigo Moya + + * e-config-listener.[ch]: new class for config database access and + monitoring. + + * Makefile.am: added new files. + 2002-08-14 Rodrigo Moya * e-component-listener.[ch]: new class for controlling a component, diff --git a/e-util/Makefile.am b/e-util/Makefile.am index f2283b3a0f..75481cdfcf 100644 --- a/e-util/Makefile.am +++ b/e-util/Makefile.am @@ -23,6 +23,7 @@ eutilinclude_HEADERS = \ e-categories-master-list-wombat.h \ e-categories-config.h \ e-component-listener.h \ + e-config-listener.h \ e-corba-utils.h \ e-dialog-utils.h \ e-dialog-widgets.h \ @@ -51,6 +52,7 @@ libeutil_la_SOURCES = \ e-categories-master-list-wombat.c \ e-categories-config.c \ e-component-listener.c \ + e-config-listener.c \ e-corba-utils.c \ e-dialog-utils.c \ e-dialog-widgets.c \ diff --git a/e-util/e-config-listener.c b/e-util/e-config-listener.c new file mode 100644 index 0000000000..e6fd8dbb9c --- /dev/null +++ b/e-util/e-config-listener.c @@ -0,0 +1,313 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Configuration component listener + * + * Author: + * Rodrigo Moya + * + * Copyright 2002, Ximian, Inc. + */ + +#include +#include +#include +#include +#include +#include "e-config-listener.h" + +#define PARENT_TYPE GTK_TYPE_OBJECT + +typedef struct { + EConfigListener *cl; + char *key; + GtkFundamentalType type; + union { + char *v_str; + gboolean v_bool; + } value; + gboolean used_default; +} KeyData; + +struct _EConfigListenerPrivate { + Bonobo_ConfigDatabase db; + GHashTable *keys; +}; + +static void e_config_listener_class_init (EConfigListenerClass *klass); +static void e_config_listener_init (EConfigListener *cl); +static void e_config_listener_destroy (GtkObject *object); + +static GtkObjectClass *parent_class = NULL; + +static void +e_config_listener_class_init (EConfigListenerClass *klass) +{ + GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass); + + parent_class = gtk_type_class (PARENT_TYPE); + + object_class->destroy = e_config_listener_destroy; +} + +static void +e_config_listener_init (EConfigListener *cl) +{ + CORBA_Environment ev; + + /* allocate internal structure */ + cl->priv = g_new0 (EConfigListenerPrivate, 1); + + cl->priv->keys = g_hash_table_new (g_str_hash, g_str_equal); + + /* activate the configuration database */ + CORBA_exception_init (&ev); + cl->priv->db = bonobo_get_object ("wombat:", "Bonobo/ConfigDatabase", &ev); + + if (BONOBO_EX (&ev) || cl->priv->db == CORBA_OBJECT_NIL) { + CORBA_exception_free (&ev); + cl->priv->db = CORBA_OBJECT_NIL; + } +} + +static void +free_key_hash (gpointer key, gpointer value, gpointer user_data) +{ + KeyData *kd = (KeyData *) value; + + g_return_if_fail (kd != NULL); + + g_free (kd->key); + switch (kd->type) { + case GTK_TYPE_STRING : + g_free (kd->value.v_str); + break; + default : + } + + g_free (kd); +} + +static void +e_config_listener_destroy (GtkObject *object) +{ + EConfigListener *cl = (EConfigListener *) object; + + g_return_if_fail (E_IS_CONFIG_LISTENER (cl)); + + if (cl->priv->db != CORBA_OBJECT_NIL) { + bonobo_object_release_unref (cl->priv->db, NULL); + cl->priv->db = CORBA_OBJECT_NIL; + } + + g_hash_table_foreach (cl->priv->keys, (GHFunc) free_key_hash, NULL); + g_hash_table_destroy (cl->priv->keys); + cl->priv->keys = NULL; + + g_free (cl->priv); + cl->priv = NULL; + + if (GTK_OBJECT_CLASS (parent_class)->destroy) + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + +GtkType +e_config_listener_get_type (void) +{ + static GtkType type = 0; + + if (!type) { + static const GtkTypeInfo info = { + "EConfigListener", + sizeof (EConfigListener), + sizeof (EConfigListenerClass), + (GtkClassInitFunc) e_config_listener_class_init, + (GtkObjectInitFunc) e_config_listener_init, + NULL, /* reserved_1 */ + NULL, /* reserved_2 */ + (GtkClassInitFunc) NULL + }; + + type = gtk_type_unique (PARENT_TYPE, &info); + } + + return type; +} + +/** + * e_config_listener_new + * + * Create a new configuration listener, which is an object which + * allows to listen for changes in the configuration database. It keeps + * an updated copy of all requested configuration entries, so that + * access is much quicker and instantaneous. + * + * Returns: the newly created listener. + */ +EConfigListener * +e_config_listener_new (void) +{ + EConfigListener *cl; + + cl = gtk_type_new (E_CONFIG_LISTENER_TYPE); + return cl; +} + +static void +property_change_cb (BonoboListener *listener, + char *event_name, + CORBA_any *any, + CORBA_Environment *ev, + gpointer user_data) +{ + KeyData *kd = (KeyData *) user_data; + + g_return_if_fail (any != NULL); + g_return_if_fail (kd != NULL); + + /* free previous value */ + if (kd->type == GTK_TYPE_STRING) + g_free (kd->value.v_str); + + /* set new value */ + if (bonobo_arg_type_is_equal (any->_type, BONOBO_ARG_BOOLEAN, NULL)) { + kd->type = GTK_TYPE_BOOL; + kd->value.v_bool = BONOBO_ARG_GET_BOOLEAN (any); + } else if (bonobo_arg_type_is_equal (any->_type, BONOBO_ARG_STRING, NULL)) { + kd->type = GTK_TYPE_STRING; + kd->value.v_str = g_strdup (BONOBO_ARG_GET_STRING (any)); + } else + return; +} + +static KeyData * +add_key (EConfigListener *cl, const char *key, GtkFundamentalType type, + gpointer value, gboolean used_default) +{ + KeyData *kd; + char *event_name; + CORBA_Environment ev; + + /* add the key to our hash table */ + kd = g_new0 (KeyData, 1); + kd->cl = cl; + kd->key = g_strdup (key); + kd->type = type; + switch (type) { + case GTK_TYPE_BOOL : + memcpy (&kd->value.v_bool, value, sizeof (gboolean)); + break; + case GTK_TYPE_STRING : + kd->value.v_str = (char *) value; + break; + default : + } + + kd->used_default = used_default; + + /* add the listener for changes */ + event_name = g_strdup_printf ("=Bonobo/ConfigDatabase:change%s", + kd->key); + + CORBA_exception_init (&ev); + bonobo_event_source_client_add_listener ( + cl->priv->db, + property_change_cb, + event_name, + &ev, kd); + if (BONOBO_EX (&ev)) { + CORBA_exception_free (&ev); + free_key_hash (kd->key, kd, NULL); + return NULL; + } + + g_hash_table_insert (cl->priv->keys, kd->key, kd); + + CORBA_exception_free (&ev); + g_free (event_name); + + return kd; +} + +char * +e_config_listener_get_string_with_default (EConfigListener *cl, + const char *key, + const char *def, + gboolean *used_default) +{ + char *str; + KeyData *kd; + gboolean d; + gpointer orig_key, orig_value; + + g_return_val_if_fail (E_IS_CONFIG_LISTENER (cl), NULL); + g_return_val_if_fail (key != NULL, NULL); + + /* search for the key in our hash table */ + if (!g_hash_table_lookup_extended (cl->priv->keys, key, &orig_key, &orig_value)) { + /* not found, so retrieve it from the configuration database */ + str = bonobo_config_get_string_with_default (cl->priv->db, key, (char *) def, &d); + if (str) { + kd = add_key (cl, key, GTK_TYPE_STRING, (gpointer) str, d); + + if (used_default != NULL) + *used_default = d; + } else + return NULL; + } else { + kd = (KeyData *) orig_value; + g_assert (kd != NULL); + + if (kd->type == GTK_TYPE_STRING) { + str = g_strdup (kd->value.v_str); + if (used_default != NULL) + *used_default = kd->used_default; + } else + return NULL; + } + + return str; +} + +gboolean +e_config_listener_get_boolean_with_default (EConfigListener *cl, + const char *key, + gboolean def, + gboolean *used_default) +{ + gboolean value; + KeyData *kd; + gboolean d; + gpointer orig_key, orig_value; + + g_return_val_if_fail (E_IS_CONFIG_LISTENER (cl), FALSE); + g_return_val_if_fail (key != NULL, FALSE); + + /* search for the key in our hash table */ + if (!g_hash_table_lookup_extended (cl->priv->keys, key, &orig_key, &orig_value)) { + /* not found, so retrieve it from the configuration database */ + value = bonobo_config_get_boolean_with_default (cl->priv->db, key, def, &d); + kd = add_key (cl, key, GTK_TYPE_BOOL, &value, d); + + if (used_default != NULL) + *used_default = d; + } else { + kd = (KeyData *) orig_value; + g_assert (kd != NULL); + + if (kd->type == GTK_TYPE_BOOL) { + value = kd->value.v_bool; + if (used_default != NULL) + *used_default = kd->used_default; + } else + return FALSE; + } + + return value; +} + +Bonobo_ConfigDatabase +e_config_listener_get_db (EConfigListener *cl) +{ + g_return_val_if_fail (E_IS_CONFIG_LISTENER (cl), CORBA_OBJECT_NIL); + return cl->priv->db; +} diff --git a/e-util/e-config-listener.h b/e-util/e-config-listener.h new file mode 100644 index 0000000000..b83565d85f --- /dev/null +++ b/e-util/e-config-listener.h @@ -0,0 +1,53 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Configuration component listener + * + * Author: + * Rodrigo Moya + * + * Copyright 2002, Ximian, Inc. + */ + +#ifndef __E_CONFIG_LISTENER_H__ +#define __E_CONFIG_LISTENER_H__ + +#include +#include +#include + +BEGIN_GNOME_DECLS + +#define E_CONFIG_LISTENER_TYPE (e_config_listener_get_type ()) +#define E_CONFIG_LISTENER(o) (GTK_CHECK_CAST ((o), E_CONFIG_LISTENER_TYPE, EConfigListener)) +#define E_CONFIG_LISTENER_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_CONFIG_LISTENER_TYPE, EConfigListenerClass)) +#define E_IS_CONFIG_LISTENER(o) (GTK_CHECK_TYPE ((o), E_CONFIG_LISTENER_TYPE)) +#define E_IS_CONFIG_LISTENER_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_CONFIG_LISTENER_TYPE)) + +typedef struct _EConfigListenerPrivate EConfigListenerPrivate; + +typedef struct { + GtkObject object; + EConfigListenerPrivate *priv; +} EConfigListener; + +typedef struct { + GtkObjectClass parent_class; +} EConfigListenerClass; + +GtkType e_config_listener_get_type (void); +EConfigListener *e_config_listener_new (void); + +char *e_config_listener_get_string_with_default (EConfigListener *cl, + const char *key, + const char *def, + gboolean *used_default); +gboolean e_config_listener_get_boolean_with_default (EConfigListener *cl, + const char *key, + gboolean def, + gboolean *used_default); + +Bonobo_ConfigDatabase e_config_listener_get_db (EConfigListener *cl); + +END_GNOME_DECLS + +#endif -- cgit