[Gnucash-changes] Add central notification dispatcher for the "general" set of gconf keys.

David Hampton hampton at cvs.gnucash.org
Fri Jul 22 14:51:10 EDT 2005


Log Message:
-----------
Add central notification dispatcher for the "general" set of gconf
keys.  This is needed because lots of file need callbacks for just one
or two keys from this section.  Add routines to get/set float values
in gconf.  Miscellaneous tweaks.

Tags:
----
gnucash-gnome2-dev

Modified Files:
--------------
    gnucash/src/core-utils:
        gnc-gconf-utils.c
        gnc-gconf-utils.h

Revision Data
-------------
Index: gnc-gconf-utils.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/core-utils/Attic/gnc-gconf-utils.h,v
retrieving revision 1.1.2.8
retrieving revision 1.1.2.9
diff -Lsrc/core-utils/gnc-gconf-utils.h -Lsrc/core-utils/gnc-gconf-utils.h -u -r1.1.2.8 -r1.1.2.9
--- src/core-utils/gnc-gconf-utils.h
+++ src/core-utils/gnc-gconf-utils.h
@@ -56,8 +56,15 @@
 #define GCONF_WARNINGS_PERM	"general/warnings/permanent"
 
 /* Keys used across multiple modules */
-#define KEY_LAST_PATH "last_path"
-#define KEY_USE_NEW   "use_new_window"
+#define KEY_LAST_PATH		"last_path"
+#define KEY_USE_NEW   		"use_new_window"
+#define KEY_ACCOUNTING_LABELS	"use_accounting_labels"
+#define KEY_ACCOUNT_SEPARATOR	"account_separator"
+#define KEY_NEGATIVE_IN_RED	"negative_in_red"
+#define KEY_NUMBER_OF_ROWS	"number_of_rows"
+
+typedef void (*GncGconfGeneralCb)    (GConfEntry *entry, gpointer user_data);
+typedef void (*GncGconfGeneralAnyCb) (gpointer user_data);
 
 
 /** @name GConf Miscellaneous Functions
@@ -147,6 +154,85 @@
 
 
 
+/** @name GConf "General" Section Convenience Functions 
+ @{ 
+*/
+
+
+/** Register a callback for when a specific key in the general section
+ *  of Gnucash's gconf data is changed.  Any time the key's value
+ *  chagnes, the routine will be invoked and will be passed both the
+ *  changes gconf entry and the user data passed to this function.
+ *
+ *  @param key This value contains the name of the key within the
+ *  "general" section to watch.
+ *
+ *  @param func This is a pointer to the function to call when the key
+ *  changes.
+ *
+ *  @param user_data This pointer will be passed to the callback
+ *  function.
+ */
+void gnc_gconf_general_register_cb (const gchar *key,
+				    GncGconfGeneralCb func,
+				    gpointer user_data);
+
+
+/** Remove a function that was registered for a callback when a
+ *  specific key in the general section of Gnucash's gconf data
+ *  changed.  Both the func and user_data arguments are used to match
+ *  up the callback to remove.
+ *
+ *  @param key This value contains the name of the key within the
+ *  "general" section to watch.
+ *
+ *  @param func This is a pointer to the function to call when the key
+ *  changes.
+ *
+ *  @param user_data This pointer will be passed to the callback
+ *  function.
+ */
+void gnc_gconf_general_remove_cb (const gchar *key,
+				  GncGconfGeneralCb func,
+				  gpointer user_data);
+
+
+/** Register a callback for when any key in the general section of
+ *  Gnucash's gconf data is changed.  Any time the value of a key in
+ *  this section chagnes, the routine will be invoked and will be
+ *  passed the specified user data.
+ *
+ *  @param func This is a pointer to the function to call when the key
+ *  changes.
+ *
+ *  @param user_data This pointer will be passed to the callback
+ *  function.
+ */
+void gnc_gconf_general_register_any_cb (GncGconfGeneralAnyCb func,
+					gpointer user_data);
+
+
+/** Remove a function that was registered for a callback when any key
+ *  in the general section of Gnucash's gconf data changed.  Both the
+ *  func and user_data arguments are used to match up the callback to
+ *  remove.
+ *
+ *  @param key This value contains the name of the key within the
+ *  "general" section to watch.
+ *
+ *  @param func This is a pointer to the function to call when the key
+ *  changes.
+ *
+ *  @param user_data This pointer will be passed to the callback
+ *  function.
+ */
+void gnc_gconf_general_remove_any_cb (GncGconfGeneralAnyCb func,
+				      gpointer user_data);
+
+/** @} */
+
+
+
 /** @name GConf Get Functions 
  @{ 
 */
@@ -245,7 +331,7 @@
  *  display an error message via stdout.  If present, this function
  *  will pass any error back to the calling function for it to handle.
  *
- *  @return This function returns the integer value stored at the
+ *  @return This function returns the float value stored at the
  *  requested key in the gconf database.  If the key has never been
  *  set, this function passes on the default value returned by GConf
  *  as specified in the schema for this key.  If there is an error in
@@ -256,6 +342,42 @@
 			const gchar *name,
 			GError **error);
 
+/** Get an float value from GConf.
+ *
+ *  Retrieve an float value from GConf.  The section and key names
+ *  provided as arguments are combined with the standard gnucash key
+ *  prefix to produce a fully qualified key name.  Either name (but
+ *  not both) may be a fully qualified key path name, in which case it
+ *  is used as is, without the standard gnucash prefix.  This allows
+ *  the program to access keys like standard desktop settings.  Either
+ *  name (but not both) may be NULL.
+ *
+ *  @param section This string provides a grouping of keys within the
+ *  GnuCash section of the gconf database.  It can be a simple string
+ *  as in "history" for settings that are common to many areas of
+ *  gnucash, or it can be a partial path name as in
+ *  "dialogs/business/invoice" for setting that only apply to one
+ *  specific area of the program.
+ *
+ *  @param name This string is the name of the particular key within
+ *  the named section of gconf.
+ *
+ *  @param error An optional pointer to a GError structure.  If NULL,
+ *  this function will check for any errors returned by GConf and will
+ *  display an error message via stdout.  If present, this function
+ *  will pass any error back to the calling function for it to handle.
+ *
+ *  @return This function returns the integer value stored at the
+ *  requested key in the gconf database.  If the key has never been
+ *  set, this function passes on the default value returned by GConf
+ *  as specified in the schema for this key.  If there is an error in
+ *  processing, this function passed on the value of zero as returned
+ *  by GConf.
+ */
+gdouble gnc_gconf_get_float (const gchar *section,
+			     const gchar *name,
+			     GError **error);
+
 /** Get a string value from GConf.
  *
  *  Retrieve an string value from GConf.  The section and key names
@@ -401,7 +523,7 @@
  *  @param name This string is the name of the particular key within
  *  the named section of gconf.
  *
- *  @value The TRUE/FALSE value to be stored.
+ *  @param value The TRUE/FALSE value to be stored.
  *
  *  @param error An optional pointer to a GError structure.  If NULL,
  *  this function will check for any errors returned by GConf and will
@@ -433,7 +555,7 @@
  *  @param name This string is the name of the particular key within
  *  the named section of gconf.
  *
- *  @value The number to be stored.
+ *  @param value The number to be stored.
  *
  *  @param error An optional pointer to a GError structure.  If NULL,
  *  this function will check for any errors returned by GConf and will
@@ -445,6 +567,38 @@
 			const gint value,
 			GError **error);
 
+/** Store an float value into GConf.
+ *
+ *  Store an float into GConf.  The section and key names provided
+ *  as arguments are combined with the standard gnucash key prefix to
+ *  produce a fully qualified key name.  Either name (but not both)
+ *  may be a fully qualified key path name, in which case it is used
+ *  as is, without the standard gnucash prefix.  This allows the
+ *  program to access keys like standard desktop settings.  Either
+ *  name (but not both) may be NULL.
+ *
+ *  @param section This string provides a grouping of keys within the
+ *  GnuCash section of the gconf database.  It can be a simple string
+ *  as in "history" for settings that are common to many areas of
+ *  gnucash, or it can be a partial path name as in
+ *  "dialogs/business/invoice" for setting that only apply to one
+ *  specific area of the program.
+ *
+ *  @param name This string is the name of the particular key within
+ *  the named section of gconf.
+ *
+ *  @param value The number to be stored.
+ *
+ *  @param error An optional pointer to a GError structure.  If NULL,
+ *  this function will check for any errors returned by GConf and will
+ *  display an error message via stdout.  If present, this function
+ *  will pass any error back to the calling function for it to handle.
+ */
+void gnc_gconf_set_float (const gchar *section,
+			  const gchar *name,
+			  const gdouble value,
+			  GError **error);
+
 /** Store a string into GConf.
  *
  *  Store a single string into GConf.  The section and key names
@@ -465,7 +619,7 @@
  *  @param name This string is the name of the particular key within
  *  the named section of gconf.
  *
- *  @value The string to be stored.  GConf will make a copy of this
+ *  @param value The string to be stored.  GConf will make a copy of this
  *  string, so it is the callers responsibility to free the space used
  *  by this string (if necessary).
  *
@@ -504,7 +658,7 @@
  *  @param list_type This enum indicates the type of each item in the
  *  list to be stored.
  *
- *  @value The list of items to be stored.  Each item in the list must
+ *  @param value The list of items to be stored.  Each item in the list must
  *  be of the type specified.  E.G. If the list_type is
  *  GCONF_VALUE_STRING, then the data field of each element in the
  *  list must be a string pointer.
Index: gnc-gconf-utils.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/core-utils/Attic/gnc-gconf-utils.c,v
retrieving revision 1.1.2.7
retrieving revision 1.1.2.8
diff -Lsrc/core-utils/gnc-gconf-utils.c -Lsrc/core-utils/gnc-gconf-utils.c -u -r1.1.2.7 -r1.1.2.8
--- src/core-utils/gnc-gconf-utils.c
+++ src/core-utils/gnc-gconf-utils.c
@@ -28,11 +28,12 @@
 #include <string.h>
 #include "gnc-gconf-utils.h"
 
-#define APP_GNUCASH "/apps/gnucash/%s"
+#define APP_GNUCASH "/apps/gnucash"
 #define CLIENT_TAG  "%s-client"
 #define NOTIFY_TAG  "%s-notify_id"
 
 static GConfClient *our_client = NULL;
+static guint gconf_general_cb_id = 0;
 
 /************************************************************/
 /*                      Enum Utilities                      */
@@ -105,12 +106,154 @@
 }
 
 /************************************************************/
+/*        Notification of "General" Section Changes         */
+/************************************************************/
+
+static GOnce gcb_init_once = G_ONCE_INIT;
+static GHashTable *gcb_callback_hash = NULL;
+static GHookList *gcb_final_hook_list = NULL;
+
+static gpointer
+gcb_init (gpointer unused)
+{
+  gcb_callback_hash = g_hash_table_new(g_str_hash, g_str_equal);
+
+  gcb_final_hook_list = g_malloc(sizeof(GHookList));
+  g_hook_list_init(gcb_final_hook_list, sizeof(GHook));
+  return NULL;
+}
+
+static void
+gcb_call_hook (GHook *hook, gpointer data)
+{
+  ((GFunc)hook->func)(data, hook->data);
+}
+
+static void
+gnc_gconf_general_changed (GConfClient *client,
+			   guint cnxn_id,
+			   GConfEntry *entry,
+			   gpointer data)
+{
+  const gchar *key, *key_tail;
+  GHookList *hook_list;
+
+  g_once(&gcb_init_once, gcb_init, NULL);
+
+  key = gconf_entry_get_key(entry);
+  key_tail = rindex(key, '/');
+  if (key_tail != NULL) {
+    key_tail++;
+  }
+  if (key_tail == NULL) {
+    /* Should never happen. */
+    g_warning("Malformed key %s:",key);
+    return;
+  }
+
+  hook_list = g_hash_table_lookup(gcb_callback_hash, key_tail);
+  if (hook_list != NULL)
+    g_hook_list_marshal(hook_list, TRUE, gcb_call_hook, entry);
+  g_hook_list_invoke(gcb_final_hook_list, TRUE);
+}
+
+
+void
+gnc_gconf_general_register_cb (const gchar *key,
+			       GncGconfGeneralCb func,
+			       gpointer user_data)
+{
+  GHookList *hook_list;
+  GHook *hook;
+
+  g_once(&gcb_init_once, gcb_init, NULL);
+  hook_list = g_hash_table_lookup(gcb_callback_hash, key);
+  if (hook_list == NULL) {
+    hook_list = g_malloc(sizeof(GHookList));
+    g_hook_list_init(hook_list, sizeof(GHook));
+    g_hash_table_insert(gcb_callback_hash, (gpointer)key, hook_list);
+  }
+
+  hook = g_hook_find_func_data(hook_list, TRUE, func, user_data);
+  if (hook != NULL) {
+    return;
+  }
+
+  hook = g_hook_alloc(hook_list);
+  hook->func = func;
+  hook->data = user_data;
+  g_hook_append(hook_list, hook);
+}
+
+
+void
+gnc_gconf_general_remove_cb (const gchar *key,
+			     GncGconfGeneralCb func,
+			     gpointer user_data)
+{
+  GHookList *hook_list;
+  GHook *hook;
+
+  g_once(&gcb_init_once, gcb_init, NULL);
+  hook_list = g_hash_table_lookup(gcb_callback_hash, key);
+  if (hook_list == NULL)
+    return;
+  hook = g_hook_find_func_data(hook_list, TRUE, func, user_data);
+  if (hook == NULL)
+    return;
+
+  g_hook_destroy_link(hook_list, hook);
+  if (hook_list->hooks == NULL) {
+    g_hash_table_remove(gcb_callback_hash, key);
+    g_free(hook_list);
+  }
+}
+
+
+void
+gnc_gconf_general_register_any_cb (GncGconfGeneralAnyCb func,
+				   gpointer user_data)
+{
+  GHook *hook;
+
+  g_once(&gcb_init_once, gcb_init, NULL);
+  hook = g_hook_find_func_data(gcb_final_hook_list, TRUE, func, user_data);
+  if (hook != NULL)
+    return;
+
+  hook = g_hook_alloc(gcb_final_hook_list);
+  hook->func = func;
+  hook->data = user_data;
+  g_hook_append(gcb_final_hook_list, hook);
+}
+
+
+void
+gnc_gconf_general_remove_any_cb (GncGconfGeneralAnyCb func,
+				 gpointer user_data)
+{
+  GHook *hook;
+
+  g_once(&gcb_init_once, gcb_init, NULL);
+  hook = g_hook_find_func_data(gcb_final_hook_list, TRUE, func, user_data);
+  if (hook == NULL)
+    return;
+
+  g_hook_unref(gcb_final_hook_list, hook);
+}
+
+
+/************************************************************/
 /*                      Gconf Utilities                     */
 /************************************************************/
 
 char *
 gnc_gconf_section_name (const char *name)
 {
+  if (name == NULL) {
+    /* Need to return a newly allocated string */
+    return g_strdup(APP_GNUCASH);
+  }
   if (*name == '/') {
     /* Need to return a newly allocated string */
     return g_strdup(name);
@@ -122,7 +265,7 @@
    * order to keep this file completely "gnome-free" this approach was
    * used.
    */
-  return g_strdup_printf(APP_GNUCASH, name);
+  return g_strjoin("/", APP_GNUCASH, name, NULL);
 }
 
 char *
@@ -139,7 +282,7 @@
    * order to keep this file completely "gnome-free" this approach was
    * used.
    */
-  return g_strdup_printf("/schemas" APP_GNUCASH, name);
+  return g_strconcat("/schemas", APP_GNUCASH, "/", name, NULL);
 }
 
 static gchar *
@@ -297,6 +440,57 @@
   g_free(key);
 }
 
+gdouble
+gnc_gconf_get_float (const gchar *section,
+		     const gchar *name,
+		     GError **caller_error)
+{
+  GError *error = NULL;
+  gint value;
+  gchar *key;
+
+  if (our_client == NULL)
+    our_client = gconf_client_get_default();
+
+  key = gnc_gconf_make_key(section, name);
+  value = gconf_client_get_float(our_client, key, &error);
+  if (error) {
+    if (caller_error) {
+      g_propagate_error(caller_error, error);
+    } else {
+      printf("Failed to load key %s: %s", key, error->message);
+      g_error_free(error);
+    }
+  }
+  g_free(key);
+  return value;
+}
+
+void
+gnc_gconf_set_float (const gchar *section,
+		     const gchar *name,
+		     const gdouble value,
+		     GError **caller_error)
+{
+  GError *error = NULL;
+  gchar *key;
+
+  if (our_client == NULL)
+    our_client = gconf_client_get_default();
+
+  /* Remember whether the column width */
+  key = gnc_gconf_make_key(section, name);
+  if (!gconf_client_set_float(our_client, key, value, &error)) {
+    if (caller_error) {
+      g_propagate_error(caller_error, error);
+    } else {
+      printf("Failed to save key %s: %s", key, error->message);
+      g_error_free(error);
+    }
+  }
+  g_free(key);
+}
+
 gchar *
 gnc_gconf_get_string (const gchar *section,
 		      const gchar *name,
@@ -540,7 +734,6 @@
 	guint id;
 
 	g_return_if_fail(G_IS_OBJECT(object));
-	g_return_if_fail(section != NULL);
 	g_return_if_fail(callback != NULL);
 
 	client = gconf_client_get_default();
@@ -595,7 +788,6 @@
 	gchar *path;
 	guint id;
 
-	g_return_val_if_fail(section != NULL, 0);
 	g_return_val_if_fail(callback != NULL, 0);
 
 	client = gconf_client_get_default();
@@ -641,7 +833,6 @@
 	guint id;
 
 	g_return_if_fail(G_IS_OBJECT(object));
-	g_return_if_fail(section != NULL);
 
 	/*
 	 * Remove any gconf notifications
@@ -669,8 +860,6 @@
 	GConfClient *client;
 	gchar *path;
 
-	g_return_if_fail(section != NULL);
-
 	/*
 	 * Remove any gconf notifications
 	 */
@@ -684,12 +873,13 @@
 	g_free(path);
 }
 
+/* ============================================================== */
+
 gboolean
 gnc_gconf_schemas_found (void)
 {
   GConfSchema* schema;
   GError *err = NULL;
-  gboolean found = FALSE;
   gchar *key;
 
   if (our_client == NULL)
@@ -697,10 +887,16 @@
 
   key = gnc_gconf_make_schema_key(GCONF_GENERAL_REGISTER, "use_theme_colors");
   schema = gconf_client_get_schema(our_client, key, &err);
-  if (schema != NULL) {
-    gconf_schema_free(schema);
-    found = TRUE;
-  }
-  g_free(key);
-  return found;
+  if (schema == NULL) {
+    g_free(key);
+    return FALSE;
+  }
+  gconf_schema_free(schema);
+
+  /* Set up convenience callback for general section */
+  
+  gconf_general_cb_id =
+    gnc_gconf_add_anon_notification(GCONF_GENERAL, gnc_gconf_general_changed,
+				    NULL);
+    return TRUE;
 }


More information about the gnucash-changes mailing list