/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/* eel-gconf-extensions.c - Stuff to make GConf easier to use.
Copyright (C) 2000, 2001 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>
$Id$
*/
#include "config.h"
#include "eel-gconf-extensions.h"
#include <glib/gi18n.h>
#include <gconf/gconf-client.h>
#include <gconf/gconf.h>
#include <string.h>
static GConfClient *global_gconf_client = NULL;
static void
global_client_free (void)
{
if (global_gconf_client == NULL) {
return;
}
g_object_unref (global_gconf_client);
global_gconf_client = NULL;
}
/* Public */
GConfClient *
eel_gconf_client_get_global (void)
{
if (global_gconf_client == NULL) {
global_gconf_client = gconf_client_get_default ();
g_atexit (global_client_free);
}
return global_gconf_client;
}
gboolean
eel_gconf_handle_error (GError **error)
{
g_return_val_if_fail (error != NULL, FALSE);
if (*error != NULL) {
g_warning (_("GConf error:\n %s"), (*error)->message);
g_error_free (*error);
*error = NULL;
return TRUE;
}
return FALSE;
}
void
eel_gconf_set_boolean (const char *key,
gboolean boolean_value)
{
GConfClient *client;
GError *error = NULL;
g_return_if_fail (key != NULL);
client = eel_gconf_client_get_global ();
g_return_if_fail (client != NULL);
gconf_client_set_bool (client, key, boolean_value, &error);
eel_gconf_handle_error (&error);
}
gboolean
eel_gconf_get_boolean (const char *key)
{
gboolean result;
GConfClient *client;
GError *error = NULL;
g_return_val_if_fail (key != NULL, FALSE);
client = eel_gconf_client_get_global ();
g_return_val_if_fail (client != NULL, FALSE);
result = gconf_client_get_bool (client, key, &error);
if (eel_gconf_handle_error (&error)) {
result = FALSE;
}
return result;
}
void
eel_gconf_set_integer (const char *key,
int int_value)
{
GConfClient *client;
GError *error = NULL;
g_return_if_fail (key != NULL);
client = eel_gconf_client_get_global ();
g_return_if_fail (client != NULL);
gconf_client_set_int (client, key, int_value, &error);
eel_gconf_handle_error (&error);
}
int
eel_gconf_get_integer (const char *key)
{
int result;
GConfClient *client;
GError *error = NULL;
g_return_val_if_fail (key != NULL, 0);
client = eel_gconf_client_get_global ();
g_return_val_if_fail (client != NULL, 0);
result = gconf_client_get_int (client, key, &error);
if (eel_gconf_handle_error (&error)) {
result = 0;
}
return result;
}
void
eel_gconf_set_string (const char *key,
const char *string_value)
{
GConfClient *client;
GError *error = NULL;
g_return_if_fail (key != NULL);
client = eel_gconf_client_get_global ();
g_return_if_fail (client != NULL);
gconf_client_set_string (client, key, string_value, &error);
eel_gconf_handle_error (&error);
}
char *
eel_gconf_get_string (const char *key)
{
char *result;
GConfClient *client;
GError *error = NULL;
g_return_val_if_fail (key != NULL, NULL);
client = eel_gconf_client_get_global ();
g_return_val_if_fail (client != NULL, NULL);
result = gconf_client_get_string (client, key, &error);
if (eel_gconf_handle_error (&error)) {
result = g_strdup ("");
}
return result;
}
void
eel_gconf_set_string_list (const char *key,
const GSList *slist)
{
GConfClient *client;
GError *error;
g_return_if_fail (key != NULL);
client = eel_gconf_client_get_global ();
g_return_if_fail (client != NULL);
error = NULL;
gconf_client_set_list (client, key, GCONF_VALUE_STRING,
/* Need cast cause of GConf api bug */
(GSList *) slist,
&error);
eel_gconf_handle_error (&error);
}
GSList *
eel_gconf_get_string_list (const char *key)
{
GSList *slist;
GConfClient *client;
GError *error;
g_return_val_if_fail (key != NULL, NULL);
client = eel_gconf_client_get_global ();
g_return_val_if_fail (client != NULL, NULL);
error = NULL;
slist = gconf_client_get_list (client, key, GCONF_VALUE_STRING, &error);
if (eel_gconf_handle_error (&error)) {
slist = NULL;
}
return slist;
}
gboolean
eel_gconf_is_default (const char *key)
{
gboolean result;
GConfValue *value;
GError *error = NULL;
g_return_val_if_fail (key != NULL, FALSE);
value = gconf_client_get_without_default (eel_gconf_client_get_global (), key, &error);
if (eel_gconf_handle_error (&error)) {
if (value != NULL) {
gconf_value_free (value);
}
return FALSE;
}
result = (value == NULL);
eel_gconf_value_free (value);
return result;
}
gboolean
eel_gconf_key_is_writable (const char *key)
{
gboolean result;
GError *error = NULL;
g_return_val_if_fail (key != NULL, FALSE);
result = gconf_client_key_is_writable (eel_gconf_client_get_global (), key, &error);
if (eel_gconf_handle_error (&error)) {
return result;
}
return result;
}
gboolean
eel_gconf_monitor_add (const char *directory)
{
GError *error = NULL;
GConfClient *client;
g_return_val_if_fail (directory != NULL, FALSE);
client = gconf_client_get_default ();
g_return_val_if_fail (client != NULL, FALSE);
gconf_client_add_dir (client,
directory,
GCONF_CLIENT_PRELOAD_NONE,
&error);
if (eel_gconf_handle_error (&error)) {
return FALSE;
}
return TRUE;
}
gboolean
eel_gconf_monitor_remove (const char *directory)
{
GError *error = NULL;
GConfClient *client;
if (directory == NULL) {
return FALSE;
}
client = gconf_client_get_default ();
g_return_val_if_fail (client != NULL, FALSE);
gconf_client_remove_dir (client,
directory,
&error);
if (eel_gconf_handle_error (&error)) {
return FALSE;
}
return TRUE;
}
void
eel_gconf_preload_cache (const char *directory,
GConfClientPreloadType preload_type)
{
GError *error = NULL;
GConfClient *client;
if (directory == NULL) {
return;
}
client = gconf_client_get_default ();
g_return_if_fail (client != NULL);
gconf_client_preload (client,
directory,
preload_type,
&error);
eel_gconf_handle_error (&error);
}
void
eel_gconf_suggest_sync (void)
{
GConfClient *client;
GError *error = NULL;
client = eel_gconf_client_get_global ();
g_return_if_fail (client != NULL);
gconf_client_suggest_sync (client, &error);
eel_gconf_handle_error (&error);
}
GConfValue*
eel_gconf_get_value (const char *key)
{
GConfValue *value = NULL;
GConfClient *client;
GError *error = NULL;
g_return_val_if_fail (key != NULL, NULL);
client = eel_gconf_client_get_global ();
g_return_val_if_fail (client != NULL, NULL);
value = gconf_client_get (client, key, &error);
if (eel_gconf_handle_error (&error)) {
if (value != NULL) {
gconf_value_free (value);
value = NULL;
}
}
return value;
}
GConfValue*
eel_gconf_get_default_value (const char *key)
{
GConfValue *value = NULL;
GConfClient *client;
GError *error = NULL;
g_return_val_if_fail (key != NULL, NULL);
client = eel_gconf_client_get_global ();
g_return_val_if_fail (client != NULL, NULL);
value = gconf_client_get_default_from_schema (client, key, &error);
if (eel_gconf_handle_error (&error)) {
if (value != NULL) {
gconf_value_free (value);
value = NULL;
}
}
return value;
}
static int
eel_strcmp (const char *string_a, const char *string_b)
{
/* FIXME bugzilla.eazel.com 5450: Maybe we need to make this
* treat 'NULL < ""', or have a flavor that does that. If we
* didn't have code that already relies on 'NULL == ""', I
* would change it right now.
*/
return strcmp (string_a == NULL ? "" : string_a,
string_b == NULL ? "" : string_b);
}
static gboolean
eel_str_is_equal (const char *string_a, const char *string_b)
{
/* FIXME bugzilla.eazel.com 5450: Maybe we need to make this
* treat 'NULL != ""', or have a flavor that does that. If we
* didn't have code that already relies on 'NULL == ""', I
* would change it right now.
*/
return eel_strcmp (string_a, string_b) == 0;
}
static gboolean
simple_value_is_equal (const GConfValue *a,
const GConfValue *b)
{
g_return_val_if_fail (a != NULL, FALSE);
g_return_val_if_fail (b != NULL, FALSE);
switch (a->type) {
case GCONF_VALUE_STRING:
return eel_str_is_equal (gconf_value_get_string (a),
gconf_value_get_string (b));
break;
case GCONF_VALUE_INT:
return gconf_value_get_int (a) ==
gconf_value_get_int (b);
break;
case GCONF_VALUE_FLOAT:
return gconf_value_get_float (a) ==
gconf_value_get_float (b);
break;
case GCONF_VALUE_BOOL:
return gconf_value_get_bool (a) ==
gconf_value_get_bool (b);
break;
default:
g_assert_not_reached ();
}
return FALSE;
}
gboolean
eel_gconf_value_is_equal (const GConfValue *a,
const GConfValue *b)
{
GSList *node_a;
GSList *node_b;
if (a == NULL && b == NULL) {
return TRUE;
}
if (a == NULL || b == NULL) {
return FALSE;
}
if (a->type != b->type) {
return FALSE;
}
switch (a->type) {
case GCONF_VALUE_STRING:
case GCONF_VALUE_INT:
case GCONF_VALUE_FLOAT:
case GCONF_VALUE_BOOL:
return simple_value_is_equal (a, b);
break;
case GCONF_VALUE_LIST:
if (gconf_value_get_list_type (a) !=
gconf_value_get_list_type (b)) {
return FALSE;
}
node_a = gconf_value_get_list (a);
node_b = gconf_value_get_list (b);
if (node_a == NULL && node_b == NULL) {
return TRUE;
}
if (g_slist_length (node_a) !=
g_slist_length (node_b)) {
return FALSE;
}
for (;
node_a != NULL && node_b != NULL;
node_a = node_a->next, node_b = node_b->next) {
g_assert (node_a->data != NULL);
g_assert (node_b->data != NULL);
if (!simple_value_is_equal (node_a->data, node_b->data)) {
return FALSE;
}
}
return TRUE;
default:
/* FIXME: pair ? */
g_assert (0);
}
g_assert_not_reached ();
return FALSE;
}
void
eel_gconf_value_free (GConfValue *value)
{
if (value == NULL) {
return;
}
gconf_value_free (value);
}
guint
eel_gconf_notification_add (const char *key,
GConfClientNotifyFunc notification_callback,
gpointer callback_data)
{
guint notification_id;
GConfClient *client;
GError *error = NULL;
g_return_val_if_fail (key != NULL, EEL_GCONF_UNDEFINED_CONNECTION);
g_return_val_if_fail (notification_callback != NULL, EEL_GCONF_UNDEFINED_CONNECTION);
client = eel_gconf_client_get_global ();
g_return_val_if_fail (client != NULL, EEL_GCONF_UNDEFINED_CONNECTION);
notification_id = gconf_client_notify_add (client,
key,
notification_callback,
callback_data,
NULL,
&error);
if (eel_gconf_handle_error (&error)) {
if (notification_id != EEL_GCONF_UNDEFINED_CONNECTION) {
gconf_client_notify_remove (client, notification_id);
notification_id = EEL_GCONF_UNDEFINED_CONNECTION;
}
}
return notification_id;
}
void
eel_gconf_notification_remove (guint notification_id)
{
GConfClient *client;
if (notification_id == EEL_GCONF_UNDEFINED_CONNECTION) {
return;
}
client = eel_gconf_client_get_global ();
g_return_if_fail (client != NULL);
gconf_client_notify_remove (client, notification_id);
}
GSList *
eel_gconf_value_get_string_list (const GConfValue *value)
{
GSList *result;
const GSList *slist;
const GSList *node;
const char *string;
const GConfValue *next_value;
if (value == NULL) {
return NULL;
}
g_return_val_if_fail (value->type == GCONF_VALUE_LIST, NULL);
g_return_val_if_fail (gconf_value_get_list_type (value) == GCONF_VALUE_STRING, NULL);
slist = gconf_value_get_list (value);
result = NULL;
for (node = slist; node != NULL; node = node->next) {
next_value = node->data;
g_return_val_if_fail (next_value != NULL, NULL);
g_return_val_if_fail (next_value->type == GCONF_VALUE_STRING, NULL);
string = gconf_value_get_string (next_value);
result = g_slist_append (result, g_strdup (string));
}
return result;
}
void
eel_gconf_value_set_string_list (GConfValue *value,
const GSList *string_list)
{
const GSList *node;
GConfValue *next_value;
GSList *value_list;
g_return_if_fail (value->type == GCONF_VALUE_LIST);
g_return_if_fail (gconf_value_get_list_type (value) == GCONF_VALUE_STRING);
value_list = NULL;
for (node = string_list; node != NULL; node = node->next) {
next_value = gconf_value_new (GCONF_VALUE_STRING);
gconf_value_set_string (next_value, node->data);
value_list = g_slist_append (value_list, next_value);
}
gconf_value_set_list (value, value_list);
for (node = value_list; node != NULL; node = node->next) {
gconf_value_free (node->data);
}
g_slist_free (value_list);
}
void
eel_gconf_set_float (const char *key,
gfloat float_value)
{
GConfClient *client;
GError *error = NULL;
g_return_if_fail (key != NULL);
client = eel_gconf_client_get_global ();
g_return_if_fail (client != NULL);
gconf_client_set_float (client, key, float_value, &error);
eel_gconf_handle_error (&error);
}
gfloat
eel_gconf_get_float (const char *key)
{
gfloat result;
GConfClient *client;
GError *error = NULL;
g_return_val_if_fail (key != NULL, 0);
client = eel_gconf_client_get_global ();
g_return_val_if_fail (client != NULL, 0);
result = gconf_client_get_float (client, key, &error);
if (eel_gconf_handle_error (&error)) {
result = 0;
}
return result;
}
static char *
tilde_compress (const char *path)
{
const char *home_dir = g_get_home_dir();
int home_dir_l = strlen (home_dir);
int ntilde = 0;
const char *scan;
int path_l, result_l;
char *result, *scan2;
if (path == NULL)
return NULL;
path_l = strlen (path);
for (scan = path; scan != NULL; scan++) {
if (path_l - (scan - path) < home_dir_l)
break;
if (strncmp (scan, home_dir, home_dir_l) == 0)
ntilde++;
}
if (ntilde == 0)
return g_strdup (path);
result_l = strlen (path) + ntilde - (ntilde * home_dir_l);
result = g_new (char, result_l + 1);
for (scan = path, scan2 = result; scan != NULL; scan2++) {
if (path_l - (scan - path) < home_dir_l) {
strcpy (scan2, scan);
scan2 += strlen (scan);
break;
}
if (strncmp (scan, home_dir, home_dir_l) == 0) {
*scan2 = '~';
scan += home_dir_l;
} else {
*scan2 = *scan;
scan++;
}
}
*scan2 = 0;
return result;
}
void
eel_gconf_set_path (const char *key,
const char *value)
{
char *tilde_path;
char *converted;
tilde_path = tilde_compress (value);
converted = g_filename_to_utf8 (tilde_path, -1, NULL, NULL, NULL);
eel_gconf_set_string (key, converted);
g_free (tilde_path);
g_free (converted);
}