mirror of
https://gitlab.gnome.org/GNOME/nautilus
synced 2024-08-25 10:45:41 +00:00
![Alexander Larsson](/assets/img/avatar_default.png)
2008-12-15 Alexander Larsson <alexl@redhat.com> * Makefile.am: * acconfig.h: * configure.in: * eel/ * libnautilus-private/Makefile.am: Import eel into nautilus. svn path=/trunk/; revision=14815
1702 lines
41 KiB
C
1702 lines
41 KiB
C
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
|
|
|
|
/* eel-preferences.c - Preference peek/poke/notify implementation.
|
|
|
|
Copyright (C) 1999, 2000 Eazel, Inc.
|
|
|
|
The Gnome Library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public License as
|
|
published by the Free Software Foundation; either version 2 of the
|
|
License, or (at your option) any later version.
|
|
|
|
The Gnome Library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
License along with the Gnome Library; see the file COPYING.LIB. If not,
|
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
Boston, MA 02111-1307, USA.
|
|
|
|
Authors: Ramiro Estrugo <ramiro@eazel.com>
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include "eel-preferences.h"
|
|
|
|
#include "eel-debug.h"
|
|
#include "eel-gconf-extensions.h"
|
|
#include "eel-lib-self-check-functions.h"
|
|
#include "eel-enumeration.h"
|
|
#include "eel-glib-extensions.h"
|
|
#include "eel-string.h"
|
|
#include <gconf/gconf-client.h>
|
|
#include <gconf/gconf.h>
|
|
#include <gtk/gtk.h>
|
|
|
|
/* An enumeration used for updating auto-storage variables in a type-specific way.
|
|
* FIXME: there is another enumeration like this in eel-global-preferences.c,
|
|
* used for different purposes but in a related way. Should we combine them?
|
|
*/
|
|
typedef enum {
|
|
PREFERENCE_BOOLEAN = 1,
|
|
PREFERENCE_INTEGER,
|
|
PREFERENCE_STRING,
|
|
PREFERENCE_STRING_ARRAY,
|
|
PREFERENCE_STRING_ARRAY_AS_QUARKS
|
|
} PreferenceType;
|
|
|
|
/*
|
|
* PreferencesEntry:
|
|
*
|
|
* A structure to manage preference hash table nodes.
|
|
* Preferences are hash tables. The hash key is the preference name
|
|
* (a string). The hash value is a pointer of the following struct:
|
|
*/
|
|
typedef struct {
|
|
char *name;
|
|
char *description;
|
|
PreferenceType type;
|
|
gboolean invisible;
|
|
GList *callback_list;
|
|
GList *auto_storage_list;
|
|
int gconf_connection_id;
|
|
char *enumeration_id;
|
|
GConfValue *fallback;
|
|
} PreferencesEntry;
|
|
|
|
/*
|
|
* PreferencesCallbackEntry:
|
|
*
|
|
* A structure to manage callback lists. A callback list is a GList.
|
|
* The callback_data in each list node is a pointer to the following
|
|
* struct:
|
|
*/
|
|
typedef struct {
|
|
EelPreferencesCallback callback;
|
|
gpointer callback_data;
|
|
} PreferencesCallbackEntry;
|
|
|
|
static GHashTable *global_table = NULL;
|
|
static char *storage_path = NULL;
|
|
static gboolean initialized = FALSE;
|
|
|
|
static void preferences_global_table_free (void);
|
|
static char * preferences_key_make (const char *name);
|
|
static void preferences_callback_entry_free (PreferencesCallbackEntry *callback_entry);
|
|
static void preferences_entry_update_auto_storage (PreferencesEntry *entry);
|
|
static PreferencesEntry *preferences_global_table_lookup_or_insert (const char *name);
|
|
|
|
static int
|
|
preferences_gconf_value_get_int (const GConfValue *value)
|
|
{
|
|
if (value == NULL) {
|
|
return 0;
|
|
}
|
|
g_assert (value->type == GCONF_VALUE_INT);
|
|
return gconf_value_get_int (value);
|
|
}
|
|
|
|
static gboolean
|
|
preferences_gconf_value_get_bool (const GConfValue *value)
|
|
{
|
|
if (value == NULL) {
|
|
return FALSE;
|
|
}
|
|
g_assert (value->type == GCONF_VALUE_BOOL);
|
|
return gconf_value_get_bool (value);
|
|
}
|
|
|
|
static char *
|
|
preferences_gconf_value_get_string (const GConfValue *value)
|
|
{
|
|
if (value == NULL) {
|
|
return g_strdup ("");
|
|
}
|
|
g_assert (value->type == GCONF_VALUE_STRING);
|
|
return g_strdup (gconf_value_get_string (value));
|
|
}
|
|
|
|
static char **
|
|
preferences_gconf_value_get_string_array (const GConfValue *value)
|
|
{
|
|
GSList *slist, *l;
|
|
GPtrArray *result;
|
|
|
|
if (value == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
g_assert (value->type == GCONF_VALUE_LIST);
|
|
g_assert (gconf_value_get_list_type (value) == GCONF_VALUE_STRING);
|
|
|
|
slist = eel_gconf_value_get_string_list (value);
|
|
|
|
result = g_ptr_array_new ();
|
|
for (l = slist; l != NULL; l = l->next) {
|
|
g_ptr_array_add (result, l->data);
|
|
}
|
|
g_slist_free (slist);
|
|
g_ptr_array_add (result, NULL);
|
|
|
|
return (char **) g_ptr_array_free (result, FALSE);
|
|
}
|
|
|
|
static const char *
|
|
preferences_peek_storage_path (void)
|
|
{
|
|
g_assert (storage_path != NULL);
|
|
|
|
return storage_path;
|
|
}
|
|
|
|
static void
|
|
preferences_set_storage_path (const char *new_storage_path)
|
|
{
|
|
g_assert (eel_strlen (new_storage_path) > 0);
|
|
|
|
/* Make sure the path is indeed different */
|
|
if (eel_str_is_equal (new_storage_path, storage_path)) {
|
|
return;
|
|
}
|
|
|
|
/* Free the preference hash table */
|
|
preferences_global_table_free ();
|
|
|
|
/* Stop monitoring the old path */
|
|
eel_gconf_monitor_remove (storage_path);
|
|
|
|
g_free (storage_path);
|
|
storage_path = g_strdup (new_storage_path);
|
|
|
|
/* Start monitoring the new path */
|
|
eel_gconf_monitor_add (storage_path);
|
|
}
|
|
|
|
static gboolean
|
|
preferences_is_initialized (void)
|
|
{
|
|
return initialized;
|
|
}
|
|
|
|
static GConfValue *
|
|
preferences_get_value (const char *name)
|
|
{
|
|
GConfValue *result;
|
|
char *key;
|
|
PreferencesEntry *entry;
|
|
|
|
g_assert (name != NULL);
|
|
g_assert (preferences_is_initialized ());
|
|
|
|
key = preferences_key_make (name);
|
|
result = eel_gconf_get_value (key);
|
|
g_free (key);
|
|
|
|
if (result == NULL) {
|
|
entry = preferences_global_table_lookup_or_insert (name);
|
|
|
|
if (entry->fallback)
|
|
result = gconf_value_copy (entry->fallback);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/* If the preference name begind with a "/", we interpret
|
|
* it as a straight gconf key. */
|
|
static gboolean
|
|
preferences_preference_is_gconf_key (const char *name)
|
|
{
|
|
g_assert (name != NULL);
|
|
|
|
if (eel_str_has_prefix (name, "/")) {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static char *
|
|
preferences_key_make (const char *name)
|
|
{
|
|
g_assert (name != NULL);
|
|
|
|
if (!preferences_preference_is_gconf_key (name)) {
|
|
return g_strdup (name);
|
|
}
|
|
|
|
/* Otherwise, we prefix it with the path */
|
|
return g_strconcat (preferences_peek_storage_path (), "/",
|
|
name, NULL);
|
|
}
|
|
|
|
/* Get default from schema or emergency fallback */
|
|
static GConfValue *
|
|
preferences_get_default_value (const char *name)
|
|
{
|
|
GConfValue *result;
|
|
PreferencesEntry *entry;
|
|
char *key;
|
|
|
|
g_assert (name != NULL);
|
|
|
|
key = preferences_key_make (name);
|
|
|
|
result = eel_gconf_get_default_value (key);
|
|
|
|
g_free (key);
|
|
|
|
if (result == NULL) {
|
|
entry = preferences_global_table_lookup_or_insert (name);
|
|
if (entry && entry->fallback)
|
|
result = gconf_value_copy (entry->fallback);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static int
|
|
preferences_callback_entry_compare (gconstpointer a,
|
|
gconstpointer b)
|
|
{
|
|
const PreferencesCallbackEntry *a_entry = a;
|
|
const PreferencesCallbackEntry *b_entry = b;
|
|
|
|
if (a_entry->callback < b_entry->callback) {
|
|
return -1;
|
|
}
|
|
|
|
if (a_entry->callback > b_entry->callback) {
|
|
return +1;
|
|
}
|
|
|
|
if (a_entry->callback_data < b_entry->callback_data) {
|
|
return -1;
|
|
}
|
|
|
|
if (a_entry->callback_data > b_entry->callback_data) {
|
|
return +1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Public preferences functions */
|
|
|
|
gboolean
|
|
eel_preferences_get_is_invisible (const char *name)
|
|
{
|
|
g_assert (name != NULL);
|
|
g_assert (preferences_is_initialized ());
|
|
|
|
return preferences_global_table_lookup_or_insert (name)->invisible;
|
|
}
|
|
|
|
void
|
|
eel_preferences_set_is_invisible (const char *name,
|
|
gboolean is_invisible)
|
|
{
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (preferences_is_initialized ());
|
|
|
|
preferences_global_table_lookup_or_insert (name)->invisible = is_invisible;
|
|
}
|
|
|
|
void
|
|
eel_preferences_set_boolean (const char *name,
|
|
gboolean boolean_value)
|
|
{
|
|
char *key;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (preferences_is_initialized ());
|
|
|
|
key = preferences_key_make (name);
|
|
eel_gconf_set_boolean (key, boolean_value);
|
|
g_free (key);
|
|
|
|
eel_gconf_suggest_sync ();
|
|
}
|
|
|
|
gboolean
|
|
eel_preferences_get_boolean (const char *name)
|
|
{
|
|
gboolean result;
|
|
GConfValue *value;
|
|
|
|
g_return_val_if_fail (name != NULL, 0);
|
|
g_return_val_if_fail (preferences_is_initialized (), 0);
|
|
|
|
value = preferences_get_value (name);
|
|
result = preferences_gconf_value_get_bool (value);
|
|
eel_gconf_value_free (value);
|
|
|
|
return result;
|
|
}
|
|
|
|
void
|
|
eel_preferences_set_integer (const char *name,
|
|
int int_value)
|
|
{
|
|
char *key;
|
|
int old_value;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (preferences_is_initialized ());
|
|
|
|
key = preferences_key_make (name);
|
|
old_value = eel_preferences_get_integer (name);
|
|
|
|
if (int_value != old_value) {
|
|
eel_gconf_set_integer (key, int_value);
|
|
}
|
|
g_free (key);
|
|
}
|
|
|
|
int
|
|
eel_preferences_get_integer (const char *name)
|
|
{
|
|
int result;
|
|
GConfValue *value;
|
|
|
|
g_return_val_if_fail (name != NULL, 0);
|
|
g_return_val_if_fail (preferences_is_initialized (), 0);
|
|
|
|
value = preferences_get_value (name);
|
|
result = preferences_gconf_value_get_int (value);
|
|
eel_gconf_value_free (value);
|
|
|
|
return result;
|
|
}
|
|
|
|
/* GConf has no unsigned store, save as signed and cast */
|
|
guint
|
|
eel_preferences_get_uint (const char *name)
|
|
{
|
|
return (guint)eel_preferences_get_integer (name);
|
|
}
|
|
void
|
|
eel_preferences_set_uint (const char *name,
|
|
guint uint_value)
|
|
{
|
|
eel_preferences_set_integer (name, (int)uint_value);
|
|
}
|
|
|
|
guint
|
|
eel_preferences_get_enum (const char *name)
|
|
{
|
|
guint ret_val;
|
|
char *str_value;
|
|
GConfValue *value;
|
|
const EelEnumeration *enumeration;
|
|
PreferencesEntry *entry;
|
|
|
|
g_return_val_if_fail (name != NULL, 0);
|
|
g_return_val_if_fail (preferences_is_initialized (), 0);
|
|
|
|
entry = preferences_global_table_lookup_or_insert (name);
|
|
g_return_val_if_fail (entry != NULL, 0);
|
|
|
|
enumeration = eel_enumeration_lookup (entry->enumeration_id);
|
|
|
|
if (!enumeration) {
|
|
g_warning ("No enum entry for '%s' (%s)",
|
|
name, entry->enumeration_id);
|
|
return 0;
|
|
}
|
|
|
|
value = preferences_get_value (name);
|
|
if (value->type == GCONF_VALUE_INT) { /* compatibility path */
|
|
ret_val = (guint)preferences_gconf_value_get_int (value);
|
|
eel_gconf_value_free (value);
|
|
return ret_val;
|
|
}
|
|
|
|
str_value = preferences_gconf_value_get_string (value);
|
|
eel_gconf_value_free (value);
|
|
|
|
if (str_value == NULL) {
|
|
g_warning ("No key for '%s' at %s", str_value, name);
|
|
return 0;
|
|
}
|
|
|
|
ret_val = eel_enumeration_get_value_for_name (enumeration, str_value);
|
|
|
|
g_free (str_value);
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
void
|
|
eel_preferences_set_enum (const char *name,
|
|
guint int_value)
|
|
{
|
|
const char *str_value;
|
|
const EelEnumeration *enumeration;
|
|
PreferencesEntry *entry;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (preferences_is_initialized ());
|
|
|
|
entry = preferences_global_table_lookup_or_insert (name);
|
|
g_return_if_fail (entry != NULL);
|
|
|
|
enumeration = eel_enumeration_lookup (entry->enumeration_id);
|
|
|
|
if (!enumeration) {
|
|
g_warning ("No enum entry for '%s' (%s)",
|
|
name, entry->enumeration_id);
|
|
return;
|
|
}
|
|
|
|
str_value = eel_enumeration_get_name_for_value (enumeration, int_value);
|
|
|
|
if (str_value == NULL) {
|
|
g_warning ("No enum match for '%d'", int_value);
|
|
return;
|
|
}
|
|
|
|
eel_preferences_set (name, str_value);
|
|
}
|
|
|
|
void
|
|
eel_preferences_set (const char *name,
|
|
const char *string_value)
|
|
{
|
|
char *key;
|
|
char *old_value;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (preferences_is_initialized ());
|
|
|
|
key = preferences_key_make (name);
|
|
old_value = eel_preferences_get (name);
|
|
|
|
if (strcmp (string_value, old_value) != 0) {
|
|
eel_gconf_set_string (key, string_value);
|
|
}
|
|
g_free (key);
|
|
g_free (old_value);
|
|
}
|
|
|
|
char *
|
|
eel_preferences_get (const char *name)
|
|
{
|
|
char *result;
|
|
GConfValue *value;
|
|
|
|
g_return_val_if_fail (name != NULL, NULL);
|
|
g_return_val_if_fail (preferences_is_initialized (), NULL);
|
|
|
|
value = preferences_get_value (name);
|
|
result = preferences_gconf_value_get_string (value);
|
|
eel_gconf_value_free (value);
|
|
|
|
return result;
|
|
}
|
|
|
|
void
|
|
eel_preferences_set_string_array (const char *name,
|
|
char **strv_value)
|
|
{
|
|
GSList *slist;
|
|
int i;
|
|
char *key;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (preferences_is_initialized ());
|
|
|
|
slist = NULL;
|
|
if (strv_value != NULL) {
|
|
for (i = 0; strv_value[i] != NULL; i++) {
|
|
slist = g_slist_prepend (slist, strv_value[i]);
|
|
}
|
|
slist = g_slist_reverse (slist);
|
|
}
|
|
|
|
key = preferences_key_make (name);
|
|
eel_gconf_set_string_list (key, slist);
|
|
g_free (key);
|
|
|
|
g_slist_free (slist);
|
|
}
|
|
|
|
static gboolean
|
|
string_array_is_valid (char **strv, const char *enumeration_id)
|
|
{
|
|
guint i;
|
|
gboolean res;
|
|
|
|
g_assert (strv != NULL);
|
|
g_assert (enumeration_id != NULL);
|
|
|
|
res = TRUE;
|
|
for (i = 0; strv[i] != NULL; i++) {
|
|
const EelEnumeration *enumeration;
|
|
|
|
enumeration = eel_enumeration_lookup (enumeration_id);
|
|
if (!enumeration) {
|
|
res = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (!eel_enumeration_contains_name (enumeration, strv[i])) {
|
|
res = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
char **
|
|
eel_preferences_get_string_array (const char *name)
|
|
{
|
|
char **result;
|
|
GConfValue *value;
|
|
PreferencesEntry *entry;
|
|
GConfValue *default_value;
|
|
|
|
g_return_val_if_fail (name != NULL, NULL);
|
|
g_return_val_if_fail (preferences_is_initialized (), NULL);
|
|
|
|
value = preferences_get_value (name);
|
|
result = preferences_gconf_value_get_string_array (value);
|
|
eel_gconf_value_free (value);
|
|
|
|
entry = preferences_global_table_lookup_or_insert (name);
|
|
g_assert (entry != NULL);
|
|
|
|
/* No enumeration_id so we're done */
|
|
if (entry->enumeration_id == NULL) {
|
|
return result;
|
|
}
|
|
|
|
/* Do a sanity check on the validity of the values */
|
|
if (string_array_is_valid (result, entry->enumeration_id)) {
|
|
return result;
|
|
}
|
|
|
|
/* Forget the bad value and use the default instead */
|
|
g_strfreev (result);
|
|
|
|
default_value = preferences_get_default_value (name);
|
|
if (default_value) {
|
|
result = preferences_gconf_value_get_string_array (default_value);
|
|
gconf_value_free (default_value);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void
|
|
eel_preferences_unset (const char *name)
|
|
{
|
|
char *key;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (preferences_is_initialized ());
|
|
|
|
key = preferences_key_make (name);
|
|
|
|
eel_gconf_unset (key);
|
|
|
|
g_free (key);
|
|
}
|
|
|
|
gboolean
|
|
eel_preferences_key_is_writable (const char *name)
|
|
{
|
|
gboolean result;
|
|
char *key;
|
|
|
|
g_return_val_if_fail (name != NULL, 0);
|
|
g_return_val_if_fail (preferences_is_initialized (), 0);
|
|
|
|
key = preferences_key_make (name);
|
|
result = eel_gconf_key_is_writable (key);
|
|
g_free (key);
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* preferences_callback_entry_invoke_function
|
|
*
|
|
* A function that invokes a callback from the given struct. It is meant to be fed to
|
|
* g_list_foreach ()
|
|
* @data: The list data privately maintained by the GList.
|
|
* @callback_data: The callback_data privately maintained by the GList.
|
|
**/
|
|
static void
|
|
preferences_callback_entry_invoke_function (gpointer data,
|
|
gpointer callback_data)
|
|
{
|
|
PreferencesCallbackEntry *callback_entry;
|
|
|
|
g_assert (data != NULL);
|
|
|
|
callback_entry = data;
|
|
|
|
(* callback_entry->callback) (callback_entry->callback_data);
|
|
}
|
|
|
|
static void
|
|
preferences_entry_invoke_callbacks (PreferencesEntry *entry)
|
|
{
|
|
g_assert (entry != NULL);
|
|
|
|
/* Update the auto storage preferences */
|
|
if (entry->auto_storage_list != NULL) {
|
|
preferences_entry_update_auto_storage (entry);
|
|
}
|
|
|
|
/* Invoke callbacks for this entry if any */
|
|
if (entry->callback_list != NULL) {
|
|
g_list_foreach (entry->callback_list,
|
|
preferences_callback_entry_invoke_function,
|
|
NULL);
|
|
}
|
|
}
|
|
|
|
static void
|
|
update_auto_string (gpointer data, gpointer callback_data)
|
|
{
|
|
char **storage;
|
|
const char *value;
|
|
|
|
g_assert (data != NULL);
|
|
g_assert (callback_data != NULL);
|
|
|
|
storage = (char **)data;
|
|
value = (const char *)callback_data;
|
|
|
|
g_free (*storage);
|
|
*(char **)storage = g_strdup (value);
|
|
}
|
|
|
|
static void
|
|
update_auto_string_array (gpointer data, gpointer callback_data)
|
|
{
|
|
char ***storage;
|
|
char **value;
|
|
|
|
g_assert (data != NULL);
|
|
g_assert (callback_data != NULL);
|
|
|
|
storage = (char ***)data;
|
|
value = (char **)callback_data;
|
|
|
|
g_strfreev (*storage);
|
|
*(char ***)storage = value ? g_strdupv (value) : NULL;
|
|
}
|
|
|
|
static void
|
|
update_auto_string_array_as_quarks (gpointer data, gpointer callback_data)
|
|
{
|
|
GQuark **storage;
|
|
char **value;
|
|
int i = 0;
|
|
|
|
g_assert (data != NULL);
|
|
g_assert (callback_data != NULL);
|
|
|
|
storage = (GQuark **)data;
|
|
value = (char **)callback_data;
|
|
|
|
g_free (*storage);
|
|
*storage = g_new (GQuark, g_strv_length (value) + 1);
|
|
|
|
if (value != NULL) {
|
|
for (i = 0; value[i] != NULL; ++i) {
|
|
(*storage)[i] = g_quark_from_string (value[i]);
|
|
}
|
|
}
|
|
(*storage)[i] = 0;
|
|
}
|
|
|
|
static void
|
|
update_auto_integer_or_boolean (gpointer data, gpointer callback_data)
|
|
{
|
|
g_assert (data != NULL);
|
|
|
|
*(int *)data = GPOINTER_TO_INT (callback_data);
|
|
}
|
|
|
|
static void
|
|
preferences_entry_update_auto_storage (PreferencesEntry *entry)
|
|
{
|
|
char *new_string_value;
|
|
char **new_string_array_value;
|
|
int new_int_value;
|
|
guint new_uint_value;
|
|
gboolean new_boolean_value;
|
|
|
|
switch (entry->type) {
|
|
case PREFERENCE_STRING:
|
|
if (entry->enumeration_id != NULL) {
|
|
new_uint_value = eel_preferences_get_enum (entry->name);
|
|
g_list_foreach (entry->auto_storage_list,
|
|
update_auto_integer_or_boolean,
|
|
GINT_TO_POINTER (new_uint_value));
|
|
} else {
|
|
new_string_value = eel_preferences_get (entry->name);
|
|
g_list_foreach (entry->auto_storage_list,
|
|
update_auto_string,
|
|
new_string_value);
|
|
g_free (new_string_value);
|
|
}
|
|
break;
|
|
case PREFERENCE_STRING_ARRAY:
|
|
new_string_array_value = eel_preferences_get_string_array (entry->name);
|
|
g_list_foreach (entry->auto_storage_list,
|
|
update_auto_string_array,
|
|
new_string_array_value);
|
|
g_strfreev (new_string_array_value);
|
|
break;
|
|
case PREFERENCE_STRING_ARRAY_AS_QUARKS:
|
|
new_string_array_value = eel_preferences_get_string_array (entry->name);
|
|
g_list_foreach (entry->auto_storage_list,
|
|
update_auto_string_array_as_quarks,
|
|
new_string_array_value);
|
|
g_strfreev (new_string_array_value);
|
|
break;
|
|
case PREFERENCE_INTEGER:
|
|
new_int_value = eel_preferences_get_integer (entry->name);
|
|
g_list_foreach (entry->auto_storage_list,
|
|
update_auto_integer_or_boolean,
|
|
GINT_TO_POINTER (new_int_value));
|
|
break;
|
|
case PREFERENCE_BOOLEAN:
|
|
new_boolean_value = eel_preferences_get_boolean (entry->name);
|
|
g_list_foreach (entry->auto_storage_list,
|
|
update_auto_integer_or_boolean,
|
|
GINT_TO_POINTER (new_boolean_value));
|
|
break;
|
|
default:
|
|
g_warning ("unexpected preferences type %d in preferences_entry_update_auto_storage", entry->type);
|
|
}
|
|
}
|
|
|
|
static void
|
|
preferences_something_changed_notice (GConfClient *client,
|
|
guint connection_id,
|
|
GConfEntry *entry,
|
|
gpointer notice_data)
|
|
{
|
|
g_assert (entry != NULL);
|
|
g_assert (entry->key != NULL);
|
|
g_assert (notice_data != NULL);
|
|
|
|
preferences_entry_invoke_callbacks (notice_data);
|
|
}
|
|
|
|
static void
|
|
preferences_entry_ensure_gconf_connection (PreferencesEntry *entry)
|
|
{
|
|
char *key;
|
|
|
|
/*
|
|
* We install only one gconf notification for each preference entry.
|
|
* Otherwise, we would invoke the installed callbacks more than once
|
|
* per registered callback.
|
|
*/
|
|
if (entry->gconf_connection_id != EEL_GCONF_UNDEFINED_CONNECTION) {
|
|
return;
|
|
}
|
|
|
|
g_assert (entry->name != NULL);
|
|
|
|
key = preferences_key_make (entry->name);
|
|
|
|
entry->gconf_connection_id = eel_gconf_notification_add (key,
|
|
preferences_something_changed_notice,
|
|
entry);
|
|
g_free (key);
|
|
|
|
g_assert (entry->gconf_connection_id != EEL_GCONF_UNDEFINED_CONNECTION);
|
|
}
|
|
|
|
/**
|
|
* preferences_entry_add_callback
|
|
*
|
|
* Add a callback to a pref node. Callbacks are fired whenever
|
|
* the pref value changes.
|
|
* @preferences_entry: The hash node.
|
|
* @callback: The user-supplied callback.
|
|
* @callback_data: The user-supplied closure.
|
|
**/
|
|
static void
|
|
preferences_entry_add_callback (PreferencesEntry *entry,
|
|
EelPreferencesCallback callback,
|
|
gpointer callback_data)
|
|
{
|
|
PreferencesCallbackEntry *callback_entry;
|
|
GList *l;
|
|
|
|
g_assert (entry != NULL);
|
|
g_assert (callback != NULL);
|
|
|
|
callback_entry = g_new0 (PreferencesCallbackEntry, 1);
|
|
callback_entry->callback = callback;
|
|
callback_entry->callback_data = callback_data;
|
|
|
|
l = g_list_find_custom (entry->callback_list, callback_entry, preferences_callback_entry_compare);
|
|
if (l == NULL) {
|
|
entry->callback_list = g_list_append (entry->callback_list, callback_entry);
|
|
preferences_entry_ensure_gconf_connection (entry);
|
|
} else {
|
|
g_warning ("Trying to add a callback for %s that already exists.", entry->name);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* preferences_entry_add_auto_storage
|
|
*
|
|
* Add an auto-storage variable to a pref node. The variable will
|
|
* be updated to match the pref value whenever the pref
|
|
* the pref value changes.
|
|
* @preferences_entry: The hash node.
|
|
* @storage: The user-supplied location at which to store the value.
|
|
* @type: Which type of variable this is.
|
|
**/
|
|
static void
|
|
preferences_entry_add_auto_storage (PreferencesEntry *entry,
|
|
gpointer storage,
|
|
PreferenceType type)
|
|
{
|
|
g_assert (entry != NULL);
|
|
g_assert (storage != NULL);
|
|
g_assert (entry->type == 0 || entry->type == type);
|
|
if (g_list_find (entry->auto_storage_list, storage) != NULL) {
|
|
g_warning ("Trying to add an auto storage for %s that already exists.", entry->name);
|
|
return;
|
|
}
|
|
|
|
entry->type = type;
|
|
|
|
entry->auto_storage_list = g_list_append (entry->auto_storage_list, storage);
|
|
|
|
preferences_entry_ensure_gconf_connection (entry);
|
|
}
|
|
|
|
static void
|
|
preferences_entry_check_remove_connection (PreferencesEntry *entry)
|
|
{
|
|
/*
|
|
* If there are no callbacks or auto-storage variables left in the entry,
|
|
* remove the gconf notification.
|
|
*/
|
|
if (entry->callback_list != NULL || entry->auto_storage_list != NULL) {
|
|
return;
|
|
}
|
|
|
|
eel_gconf_notification_remove (entry->gconf_connection_id);
|
|
entry->gconf_connection_id = EEL_GCONF_UNDEFINED_CONNECTION;
|
|
}
|
|
|
|
/**
|
|
* preferences_entry_remove_callback
|
|
*
|
|
* remove a callback from a pref entry. Both the callback and the callback_data must
|
|
* match in order for a callback to be removed from the entry.
|
|
* @preferences_entry: The hash entry.
|
|
* @callback: The user-supplied callback.
|
|
* @callback_data: The user-supplied closure.
|
|
**/
|
|
static void
|
|
preferences_entry_remove_callback (PreferencesEntry *entry,
|
|
EelPreferencesCallback callback,
|
|
gpointer callback_data)
|
|
{
|
|
PreferencesCallbackEntry cb_entry;
|
|
GList *l;
|
|
|
|
g_assert (entry != NULL);
|
|
g_assert (callback != NULL);
|
|
|
|
cb_entry.callback = callback;
|
|
cb_entry.callback_data = callback_data;
|
|
|
|
l = g_list_find_custom (entry->callback_list, &cb_entry, preferences_callback_entry_compare);
|
|
if (l != NULL) {
|
|
preferences_callback_entry_free (l->data);
|
|
entry->callback_list = g_list_delete_link (entry->callback_list, l);
|
|
preferences_entry_check_remove_connection (entry);
|
|
} else {
|
|
g_warning ("Trying to remove a callback for %s without adding it first.", entry->name);
|
|
}
|
|
|
|
g_assert (g_list_find_custom (entry->callback_list, &cb_entry, preferences_callback_entry_compare) == NULL);
|
|
}
|
|
|
|
/**
|
|
* preferences_entry_remove_auto_storage
|
|
*
|
|
* remove an auto-storage variable from a pref entry.
|
|
* @preferences_entry: The hash entry.
|
|
* @storage: The user-supplied location.
|
|
**/
|
|
static void
|
|
preferences_entry_remove_auto_storage (PreferencesEntry *entry,
|
|
gpointer storage)
|
|
{
|
|
GList *new_list;
|
|
const GList *node;
|
|
gpointer storage_in_entry;
|
|
|
|
g_assert (entry != NULL);
|
|
g_assert (storage != NULL);
|
|
g_assert (entry->auto_storage_list != NULL);
|
|
|
|
new_list = g_list_copy (entry->auto_storage_list);
|
|
|
|
for (node = new_list; node != NULL; node = node->next) {
|
|
storage_in_entry = node->data;
|
|
|
|
g_assert (storage_in_entry != NULL);
|
|
|
|
if (storage_in_entry == storage) {
|
|
entry->auto_storage_list = g_list_remove (entry->auto_storage_list,
|
|
storage);
|
|
|
|
switch (entry->type) {
|
|
case PREFERENCE_STRING:
|
|
update_auto_string (storage, NULL);
|
|
break;
|
|
case PREFERENCE_STRING_ARRAY:
|
|
update_auto_string_array (storage, NULL);
|
|
break;
|
|
case PREFERENCE_STRING_ARRAY_AS_QUARKS:
|
|
update_auto_string_array_as_quarks (storage, NULL);
|
|
break;
|
|
case PREFERENCE_BOOLEAN:
|
|
case PREFERENCE_INTEGER:
|
|
update_auto_integer_or_boolean (storage, NULL);
|
|
break;
|
|
default:
|
|
g_warning ("unexpected preference type %d in preferences_entry_remove_auto_storage", entry->type);
|
|
}
|
|
}
|
|
}
|
|
|
|
g_list_free (new_list);
|
|
|
|
preferences_entry_check_remove_connection (entry);
|
|
}
|
|
|
|
/**
|
|
* preferences_callback_entry_free
|
|
*
|
|
* Free a callback info struct.
|
|
* @preferences_callback_entry: The struct to free.
|
|
**/
|
|
static void
|
|
preferences_callback_entry_free (PreferencesCallbackEntry *callback_entry)
|
|
{
|
|
g_assert (callback_entry != NULL);
|
|
|
|
callback_entry->callback = NULL;
|
|
callback_entry->callback_data = NULL;
|
|
|
|
g_free (callback_entry);
|
|
}
|
|
|
|
/**
|
|
* preferences_callback_entry_free_func
|
|
*
|
|
* A function that frees a callback info struct. It is meant to be fed to
|
|
* g_list_foreach ()
|
|
* @data: The list data privately maintained by the GList.
|
|
* @callback_data: The callback_data privately maintained by the GList.
|
|
**/
|
|
static void
|
|
preferences_callback_entry_free_func (gpointer data,
|
|
gpointer callback_data)
|
|
{
|
|
g_assert (data != NULL);
|
|
|
|
preferences_callback_entry_free (data);
|
|
}
|
|
|
|
/**
|
|
* preferences_entry_free
|
|
*
|
|
* Free a preference hash node's members along with the node itself.
|
|
* @preferences_hash_node: The node to free.
|
|
**/
|
|
static void
|
|
preferences_entry_free (PreferencesEntry *entry)
|
|
{
|
|
g_assert (entry != NULL);
|
|
|
|
eel_gconf_notification_remove (entry->gconf_connection_id);
|
|
entry->gconf_connection_id = EEL_GCONF_UNDEFINED_CONNECTION;
|
|
|
|
g_list_free (entry->auto_storage_list);
|
|
eel_g_list_free_deep_custom (entry->callback_list,
|
|
preferences_callback_entry_free_func,
|
|
NULL);
|
|
|
|
entry->auto_storage_list = NULL;
|
|
entry->callback_list = NULL;
|
|
|
|
g_free (entry->name);
|
|
g_free (entry->description);
|
|
g_free (entry->enumeration_id);
|
|
|
|
eel_gconf_value_free (entry->fallback);
|
|
|
|
g_free (entry);
|
|
}
|
|
|
|
/**
|
|
* preferences_entry_free_func
|
|
*
|
|
* A function that frees a pref hash node. It is meant to be fed to
|
|
* g_hash_table_foreach ()
|
|
* @key: The hash key privately maintained by the GHashTable.
|
|
* @value: The hash value privately maintained by the GHashTable.
|
|
* @callback_data: The callback_data privately maintained by the GHashTable.
|
|
**/
|
|
static void
|
|
preferences_entry_free_func (gpointer key,
|
|
gpointer value,
|
|
gpointer callback_data)
|
|
{
|
|
g_assert (value != NULL);
|
|
|
|
preferences_entry_free (value);
|
|
}
|
|
|
|
static void
|
|
preferences_global_table_free (void)
|
|
{
|
|
if (global_table == NULL) {
|
|
return;
|
|
}
|
|
|
|
g_hash_table_foreach (global_table, preferences_entry_free_func, NULL);
|
|
g_hash_table_destroy (global_table);
|
|
global_table = NULL;
|
|
|
|
g_free (storage_path);
|
|
storage_path = NULL;
|
|
}
|
|
|
|
static void
|
|
preferences_uninitialize (void)
|
|
{
|
|
initialized = FALSE;
|
|
}
|
|
|
|
static GHashTable *
|
|
preferences_global_table_get_global (void)
|
|
{
|
|
static gboolean at_exit_handler_added = FALSE;
|
|
|
|
if (global_table == NULL) {
|
|
global_table = g_hash_table_new (g_str_hash, g_str_equal);
|
|
|
|
if (!at_exit_handler_added) {
|
|
at_exit_handler_added = TRUE;
|
|
eel_debug_call_at_shutdown (preferences_global_table_free);
|
|
/* ensure that we catch calls to preferences functions after eel shutdown */
|
|
eel_debug_call_at_shutdown (preferences_uninitialize);
|
|
}
|
|
}
|
|
|
|
return global_table;
|
|
}
|
|
|
|
static PreferencesEntry *
|
|
preferences_global_table_lookup (const char *name)
|
|
{
|
|
g_assert (name != NULL);
|
|
g_assert (preferences_global_table_get_global () != NULL);
|
|
|
|
return g_hash_table_lookup (preferences_global_table_get_global (), name);
|
|
}
|
|
|
|
static PreferencesEntry *
|
|
preferences_global_table_insert (const char *name)
|
|
{
|
|
PreferencesEntry *entry;
|
|
|
|
g_assert (name != NULL);
|
|
g_assert (preferences_global_table_get_global () != NULL);
|
|
g_assert (preferences_global_table_lookup (name) == NULL);
|
|
|
|
entry = g_new0 (PreferencesEntry, 1);
|
|
entry->name = g_strdup (name);
|
|
|
|
g_hash_table_insert (preferences_global_table_get_global (), entry->name, entry);
|
|
|
|
g_assert (entry == preferences_global_table_lookup (name));
|
|
|
|
return entry;
|
|
}
|
|
|
|
static PreferencesEntry *
|
|
preferences_global_table_lookup_or_insert (const char *name)
|
|
{
|
|
PreferencesEntry *entry;
|
|
|
|
g_assert (name != NULL);
|
|
|
|
entry = preferences_global_table_lookup (name);
|
|
|
|
if (entry != NULL) {
|
|
return entry;
|
|
}
|
|
|
|
entry = preferences_global_table_insert (name);
|
|
g_assert (entry != NULL);
|
|
|
|
return entry;
|
|
}
|
|
|
|
void
|
|
eel_preferences_add_callback (const char *name,
|
|
EelPreferencesCallback callback,
|
|
gpointer callback_data)
|
|
{
|
|
PreferencesEntry *entry;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (callback != NULL);
|
|
g_return_if_fail (preferences_is_initialized ());
|
|
|
|
entry = preferences_global_table_lookup_or_insert (name);
|
|
g_assert (entry != NULL);
|
|
|
|
preferences_entry_add_callback (entry, callback, callback_data);
|
|
}
|
|
|
|
void
|
|
eel_preferences_add_auto_string (const char *name,
|
|
const char **storage)
|
|
{
|
|
PreferencesEntry *entry;
|
|
char *value;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (storage != NULL);
|
|
g_return_if_fail (preferences_is_initialized ());
|
|
|
|
entry = preferences_global_table_lookup_or_insert (name);
|
|
g_assert (entry != NULL);
|
|
|
|
preferences_entry_add_auto_storage (entry, storage, PREFERENCE_STRING);
|
|
|
|
value = eel_preferences_get (entry->name);
|
|
update_auto_string (storage, value);
|
|
g_free (value);
|
|
}
|
|
|
|
void
|
|
eel_preferences_add_auto_string_array (const char *name,
|
|
char ***storage)
|
|
{
|
|
PreferencesEntry *entry;
|
|
char **value;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (storage != NULL);
|
|
g_return_if_fail (preferences_is_initialized ());
|
|
|
|
entry = preferences_global_table_lookup_or_insert (name);
|
|
g_assert (entry != NULL);
|
|
|
|
preferences_entry_add_auto_storage (entry, storage, PREFERENCE_STRING_ARRAY);
|
|
|
|
value = eel_preferences_get_string_array (entry->name);
|
|
update_auto_string_array (storage, value);
|
|
g_strfreev (value);
|
|
}
|
|
|
|
void
|
|
eel_preferences_add_auto_string_array_as_quarks (const char *name,
|
|
GQuark **storage)
|
|
{
|
|
PreferencesEntry *entry;
|
|
char **value;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (storage != NULL);
|
|
g_return_if_fail (preferences_is_initialized ());
|
|
|
|
entry = preferences_global_table_lookup_or_insert (name);
|
|
g_assert (entry != NULL);
|
|
|
|
preferences_entry_add_auto_storage (entry, storage, PREFERENCE_STRING_ARRAY_AS_QUARKS);
|
|
|
|
value = eel_preferences_get_string_array (entry->name);
|
|
update_auto_string_array_as_quarks (storage, value);
|
|
g_strfreev (value);
|
|
}
|
|
|
|
void
|
|
eel_preferences_add_auto_integer (const char *name,
|
|
int *storage)
|
|
{
|
|
PreferencesEntry *entry;
|
|
int value;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (storage != NULL);
|
|
g_return_if_fail (preferences_is_initialized ());
|
|
|
|
entry = preferences_global_table_lookup_or_insert (name);
|
|
g_assert (entry != NULL);
|
|
|
|
preferences_entry_add_auto_storage (entry, storage, PREFERENCE_INTEGER);
|
|
|
|
value = eel_preferences_get_integer (entry->name);
|
|
update_auto_integer_or_boolean (storage, GINT_TO_POINTER (value));
|
|
}
|
|
|
|
|
|
void
|
|
eel_preferences_add_auto_enum (const char *name,
|
|
guint *storage)
|
|
{
|
|
PreferencesEntry *entry;
|
|
guint value;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (storage != NULL);
|
|
g_return_if_fail (preferences_is_initialized ());
|
|
|
|
entry = preferences_global_table_lookup_or_insert (name);
|
|
g_assert (entry != NULL);
|
|
g_assert (entry->enumeration_id != NULL);
|
|
|
|
preferences_entry_add_auto_storage (entry, storage, PREFERENCE_STRING);
|
|
|
|
value = eel_preferences_get_enum (entry->name);
|
|
update_auto_integer_or_boolean (storage, GINT_TO_POINTER (value));
|
|
}
|
|
|
|
void
|
|
eel_preferences_add_auto_boolean (const char *name,
|
|
gboolean *storage)
|
|
{
|
|
PreferencesEntry *entry;
|
|
gboolean value;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (storage != NULL);
|
|
g_return_if_fail (preferences_is_initialized ());
|
|
|
|
entry = preferences_global_table_lookup_or_insert (name);
|
|
g_assert (entry != NULL);
|
|
|
|
preferences_entry_add_auto_storage (entry, storage, PREFERENCE_BOOLEAN);
|
|
|
|
value = eel_preferences_get_boolean (entry->name);
|
|
update_auto_integer_or_boolean (storage, GINT_TO_POINTER (value));
|
|
}
|
|
|
|
void
|
|
eel_preferences_remove_auto_string (const char *name,
|
|
const char **storage)
|
|
{
|
|
PreferencesEntry *entry;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (storage != NULL);
|
|
g_return_if_fail (preferences_is_initialized ());
|
|
|
|
entry = preferences_global_table_lookup (name);
|
|
if (entry == NULL) {
|
|
g_warning ("Trying to remove auto-string for %s without adding it first.", name);
|
|
return;
|
|
}
|
|
|
|
preferences_entry_remove_auto_storage (entry, storage);
|
|
}
|
|
|
|
void
|
|
eel_preferences_remove_auto_string_array (const char *name,
|
|
char ***storage)
|
|
{
|
|
PreferencesEntry *entry;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (storage != NULL);
|
|
g_return_if_fail (preferences_is_initialized ());
|
|
|
|
entry = preferences_global_table_lookup (name);
|
|
if (entry == NULL) {
|
|
g_warning ("Trying to remove auto-string for %s without adding it first.", name);
|
|
return;
|
|
}
|
|
|
|
preferences_entry_remove_auto_storage (entry, storage);
|
|
}
|
|
|
|
void
|
|
eel_preferences_remove_auto_integer (const char *name,
|
|
int *storage)
|
|
{
|
|
PreferencesEntry *entry;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (storage != NULL);
|
|
g_return_if_fail (preferences_is_initialized ());
|
|
|
|
entry = preferences_global_table_lookup (name);
|
|
if (entry == NULL) {
|
|
g_warning ("Trying to remove auto-integer for %s without adding it first.", name);
|
|
return;
|
|
}
|
|
|
|
preferences_entry_remove_auto_storage (entry, storage);
|
|
}
|
|
|
|
void
|
|
eel_preferences_remove_auto_boolean (const char *name,
|
|
gboolean *storage)
|
|
{
|
|
PreferencesEntry *entry;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (storage != NULL);
|
|
g_return_if_fail (preferences_is_initialized ());
|
|
|
|
entry = preferences_global_table_lookup (name);
|
|
if (entry == NULL) {
|
|
g_warning ("Trying to remove auto-boolean for %s without adding it first.", name);
|
|
return;
|
|
}
|
|
|
|
preferences_entry_remove_auto_storage (entry, storage);
|
|
}
|
|
|
|
typedef struct
|
|
{
|
|
char *name;
|
|
EelPreferencesCallback callback;
|
|
gpointer callback_data;
|
|
} WhileAliveData;
|
|
|
|
static void
|
|
preferences_while_alive_disconnector (gpointer callback_data, GObject *where_object_was)
|
|
{
|
|
WhileAliveData *data;
|
|
|
|
g_assert (callback_data != NULL);
|
|
|
|
data = callback_data;
|
|
|
|
/* we might have survived an eel shutdown, which
|
|
* already cleared all the callbacks */
|
|
if (preferences_is_initialized ()) {
|
|
eel_preferences_remove_callback (data->name,
|
|
data->callback,
|
|
data->callback_data);
|
|
}
|
|
|
|
g_free (data->name);
|
|
g_free (data);
|
|
}
|
|
|
|
void
|
|
eel_preferences_add_callback_while_alive (const char *name,
|
|
EelPreferencesCallback callback,
|
|
gpointer callback_data,
|
|
GObject *alive_object)
|
|
{
|
|
WhileAliveData *data;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (callback != NULL);
|
|
g_return_if_fail (G_IS_OBJECT (alive_object));
|
|
g_return_if_fail (preferences_is_initialized ());
|
|
|
|
data = g_new (WhileAliveData, 1);
|
|
data->name = g_strdup (name);
|
|
data->callback = callback;
|
|
data->callback_data = callback_data;
|
|
|
|
eel_preferences_add_callback (name, callback, callback_data);
|
|
|
|
g_object_weak_ref (alive_object,
|
|
preferences_while_alive_disconnector,
|
|
data);
|
|
}
|
|
|
|
void
|
|
eel_preferences_remove_callback (const char *name,
|
|
EelPreferencesCallback callback,
|
|
gpointer callback_data)
|
|
{
|
|
PreferencesEntry *entry;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (callback != NULL);
|
|
g_return_if_fail (preferences_is_initialized ());
|
|
|
|
entry = preferences_global_table_lookup (name);
|
|
|
|
if (entry == NULL) {
|
|
g_warning ("Trying to remove a callback for %s without adding it first.", name);
|
|
return;
|
|
}
|
|
|
|
preferences_entry_remove_callback (entry, callback, callback_data);
|
|
}
|
|
|
|
void
|
|
eel_preferences_set_description (const char *name,
|
|
const char *description)
|
|
{
|
|
PreferencesEntry *entry;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (description != NULL);
|
|
g_return_if_fail (preferences_is_initialized ());
|
|
|
|
entry = preferences_global_table_lookup_or_insert (name);
|
|
g_assert (entry != NULL);
|
|
|
|
g_free (entry->description);
|
|
entry->description = g_strdup (description);
|
|
}
|
|
|
|
char *
|
|
eel_preferences_get_description (const char *name)
|
|
{
|
|
PreferencesEntry *entry;
|
|
|
|
g_return_val_if_fail (name != NULL, NULL);
|
|
g_return_val_if_fail (preferences_is_initialized (), NULL);
|
|
|
|
entry = preferences_global_table_lookup_or_insert (name);
|
|
|
|
return g_strdup (entry->description ? entry->description : "");
|
|
}
|
|
|
|
void
|
|
eel_preferences_set_enumeration_id (const char *name,
|
|
const char *enumeration_id)
|
|
{
|
|
PreferencesEntry *entry;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (enumeration_id != NULL);
|
|
g_return_if_fail (preferences_is_initialized ());
|
|
|
|
entry = preferences_global_table_lookup_or_insert (name);
|
|
g_assert (entry != NULL);
|
|
|
|
g_free (entry->enumeration_id);
|
|
entry->enumeration_id = g_strdup (enumeration_id);
|
|
}
|
|
|
|
char *
|
|
eel_preferences_get_enumeration_id (const char *name)
|
|
{
|
|
PreferencesEntry *entry;
|
|
|
|
g_return_val_if_fail (name != NULL, NULL);
|
|
g_return_val_if_fail (preferences_is_initialized (), NULL);
|
|
|
|
entry = preferences_global_table_lookup_or_insert (name);
|
|
|
|
return g_strdup (entry->enumeration_id);
|
|
}
|
|
|
|
static void
|
|
preferences_set_emergency_fallback_stealing_value (const char *name,
|
|
GConfValue *value)
|
|
{
|
|
PreferencesEntry *entry;
|
|
|
|
g_assert (name != NULL);
|
|
g_assert (preferences_is_initialized ());
|
|
|
|
entry = preferences_global_table_lookup_or_insert (name);
|
|
g_assert (entry != NULL);
|
|
|
|
if (entry->fallback)
|
|
gconf_value_free (entry->fallback);
|
|
entry->fallback = value; /* steal ownership of value */
|
|
}
|
|
|
|
void
|
|
eel_preferences_set_emergency_fallback_string (const char *name,
|
|
const char *value)
|
|
{
|
|
GConfValue *gconf_value;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (value != NULL);
|
|
|
|
gconf_value = gconf_value_new (GCONF_VALUE_STRING);
|
|
|
|
gconf_value_set_string (gconf_value, value);
|
|
|
|
preferences_set_emergency_fallback_stealing_value (name, gconf_value);
|
|
}
|
|
|
|
void
|
|
eel_preferences_set_emergency_fallback_integer (const char *name,
|
|
int value)
|
|
{
|
|
GConfValue *gconf_value;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
|
|
gconf_value = gconf_value_new (GCONF_VALUE_INT);
|
|
|
|
gconf_value_set_int (gconf_value, value);
|
|
|
|
preferences_set_emergency_fallback_stealing_value (name, gconf_value);
|
|
}
|
|
|
|
void
|
|
eel_preferences_set_emergency_fallback_boolean (const char *name,
|
|
gboolean value)
|
|
{
|
|
GConfValue *gconf_value;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
|
|
gconf_value = gconf_value_new (GCONF_VALUE_BOOL);
|
|
|
|
gconf_value_set_bool (gconf_value, value);
|
|
|
|
preferences_set_emergency_fallback_stealing_value (name, gconf_value);
|
|
}
|
|
|
|
|
|
void
|
|
eel_preferences_set_emergency_fallback_string_array (const char *name,
|
|
char **value)
|
|
{
|
|
GConfValue *gconf_value;
|
|
GSList *list;
|
|
int i;
|
|
|
|
g_return_if_fail (name != NULL);
|
|
g_return_if_fail (value != NULL);
|
|
|
|
gconf_value = gconf_value_new (GCONF_VALUE_LIST);
|
|
gconf_value_set_list_type (gconf_value, GCONF_VALUE_STRING);
|
|
|
|
list = NULL;
|
|
for (i = 0; value[i] != NULL; ++i)
|
|
{
|
|
GConfValue *v;
|
|
|
|
v = gconf_value_new (GCONF_VALUE_STRING);
|
|
gconf_value_set_string (v, value[i]);
|
|
|
|
list = g_slist_prepend (list, v);
|
|
}
|
|
|
|
gconf_value_set_list_nocopy (gconf_value, g_slist_reverse (list));
|
|
|
|
preferences_set_emergency_fallback_stealing_value (name, gconf_value);
|
|
}
|
|
|
|
GConfValue*
|
|
eel_preferences_get_emergency_fallback (const char *name)
|
|
{
|
|
PreferencesEntry *entry;
|
|
|
|
g_return_val_if_fail (name != NULL, NULL);
|
|
g_return_val_if_fail (preferences_is_initialized (), NULL);
|
|
|
|
entry = preferences_global_table_lookup_or_insert (name);
|
|
|
|
return entry->fallback ? gconf_value_copy (entry->fallback) : NULL;
|
|
}
|
|
|
|
gboolean
|
|
eel_preferences_monitor_directory (const char *directory)
|
|
{
|
|
g_return_val_if_fail (preferences_is_initialized (), FALSE);
|
|
|
|
return eel_gconf_monitor_add (directory);
|
|
}
|
|
|
|
gboolean
|
|
eel_preferences_is_visible (const char *name)
|
|
{
|
|
g_return_val_if_fail (name != NULL, FALSE);
|
|
g_return_val_if_fail (preferences_is_initialized (), FALSE);
|
|
|
|
return !preferences_global_table_lookup_or_insert (name)->invisible;
|
|
}
|
|
|
|
void
|
|
eel_preferences_init (const char *path)
|
|
{
|
|
g_return_if_fail (eel_strlen (path) > 0);
|
|
|
|
if (initialized) {
|
|
return;
|
|
}
|
|
|
|
initialized = TRUE;
|
|
|
|
preferences_set_storage_path (path);
|
|
}
|
|
|
|
#if !defined (EEL_OMIT_SELF_CHECK)
|
|
|
|
#define CHECK_BOOLEAN(name__, value__) \
|
|
G_STMT_START { \
|
|
eel_preferences_set_boolean ((name__), (value__)); \
|
|
EEL_CHECK_BOOLEAN_RESULT (eel_preferences_get_boolean (name__), (value__)); \
|
|
} G_STMT_END
|
|
|
|
#define CHECK_INTEGER(name__, value__) \
|
|
G_STMT_START { \
|
|
eel_preferences_set_integer ((name__), (value__)); \
|
|
EEL_CHECK_INTEGER_RESULT (eel_preferences_get_integer (name__), (value__)); \
|
|
} G_STMT_END
|
|
|
|
#define CHECK_STRING(name__, value__) \
|
|
G_STMT_START { \
|
|
eel_preferences_set ((name__), (value__)); \
|
|
EEL_CHECK_STRING_RESULT (eel_preferences_get (name__), (value__)); \
|
|
} G_STMT_END
|
|
|
|
void
|
|
eel_self_check_preferences (void)
|
|
{
|
|
/* Disabled until I can debug why these seemingly harmless tests
|
|
* dont work. -re
|
|
*/
|
|
#if 0
|
|
int original_user_level;
|
|
|
|
original_user_level = eel_preferences_get_user_level ();
|
|
|
|
EEL_CHECK_INTEGER_RESULT (eel_preferences_get_integer ("self-check/neverset/i"), 0);
|
|
EEL_CHECK_STRING_RESULT (eel_preferences_get ("self-check/neverset/s"), "");
|
|
EEL_CHECK_BOOLEAN_RESULT (eel_preferences_get_boolean ("self-check/neverset/b"), FALSE);
|
|
|
|
eel_preferences_set_user_level (0);
|
|
|
|
/* FIXME: Fails if you add the commented-out lines. */
|
|
/* CHECK_INTEGER ("self-check/i", 0); */
|
|
CHECK_INTEGER ("self-check/i", 666);
|
|
/* CHECK_BOOLEAN ("self-check/b", FALSE); */
|
|
CHECK_BOOLEAN ("self-check/b", TRUE);
|
|
/* CHECK_STRING ("self-check/s", ""); */
|
|
CHECK_STRING ("self-check/s", "foo");
|
|
|
|
/* Restore the original user level */
|
|
eel_preferences_set_user_level (original_user_level);
|
|
#endif
|
|
}
|
|
|
|
#endif /* !EEL_OMIT_SELF_CHECK */
|