/* * Copyright (C) 2003 Benjamin Otte * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * $Id$ */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include "gnome-gconf-state.h" #define GAME_GCONF_DIR "/apps/libgame" static GameGnomeStateClass *parent_class = NULL; static void game_gnome_gconf_state_get_property (GObject *object, guint param_id, GValue *value, GParamSpec *pspec) { //GameGnomeGconfState *state = GAME_GNOME_GCONF_STATE (object); switch (param_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; } } static void game_gnome_gconf_state_set_property (GObject *object, guint param_id, const GValue *value, GParamSpec *pspec) { //GameGnomeGconfState *state = GAME_GNOME_GCONF_STATE (object); switch (param_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; } } static void game_gnome_gconf_state_handle_error (GameGnomeGconfState *state, GError *error) { if (!error) return; g_printerr ("error from GConf: %s\n", error->message); g_error_free (error); } static void game_gnome_gconf_state_finalize (GObject *object) { GameGnomeGconfState *state = GAME_GNOME_GCONF_STATE (object); char *str; GError *error = NULL; if (g_signal_handlers_disconnect_matched (state->gconf, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, state) != 1) { g_assert_not_reached (); } str = g_strconcat (GAME_GCONF_DIR, "/", GAME_GNOME_STATE (state)->name, NULL); gconf_client_remove_dir (state->gconf, str, &error); g_free (str); game_gnome_gconf_state_handle_error (state, error); g_object_unref (state->gconf); G_OBJECT_CLASS (parent_class)->finalize (object); } static char * game_gnome_gconf_key_from_path (GameGnomeState *state, const char *path) { return g_strconcat (GAME_GCONF_DIR "/", state->name, path, NULL); } static const char * game_gnome_gconf_path_from_key (GameGnomeState *state, const char *key) { return key + strlen (GAME_GCONF_DIR) + 1 + strlen (state->name); } static GConfValue * gconf_value_from_value (const GValue *from) { GConfValue *to; if (G_VALUE_TYPE (from) == G_TYPE_STRING) { return gconf_value_new_from_string (GCONF_VALUE_STRING, g_value_get_string (from), NULL); } else if (G_VALUE_TYPE (from) == G_TYPE_STRV) { char **strv = g_value_get_boxed (from); GSList *list = NULL; while (*strv) { GConfValue *tmp = gconf_value_new (GCONF_VALUE_STRING); gconf_value_set_string (tmp, *strv); list = g_slist_prepend (list, tmp); strv++; } list = g_slist_reverse (list); to = gconf_value_new (GCONF_VALUE_LIST); gconf_value_set_list_type (to, GCONF_VALUE_STRING); gconf_value_set_list_nocopy (to, list); return to; } else if (G_VALUE_TYPE (from) == GAME_TYPE_COLOR) { char *s = game_color_to_string (g_value_get_boxed (from)); to = gconf_value_new_from_string (GCONF_VALUE_STRING, s, NULL); g_free (s); return to; } else { g_return_val_if_reached (NULL); } return NULL; } static gboolean value_from_gconf_value (GValue *to, const GConfValue *from) { if (G_VALUE_TYPE (to) == G_TYPE_STRING) { if (from->type != GCONF_VALUE_STRING) return FALSE; g_value_set_string (to, gconf_value_get_string (from)); } else if (G_VALUE_TYPE (to) == G_TYPE_STRV) { GSList *list; char **strv, **walk; if (from->type != GCONF_VALUE_LIST || gconf_value_get_list_type (from) != GCONF_VALUE_STRING) return FALSE; list = gconf_value_get_list (from); walk = strv = g_new (char *, g_slist_length (list) + 1); for (; list; list = list->next) { *walk = g_strdup (gconf_value_get_string (list->data)); walk++; } *walk = NULL; g_value_set_boxed (to, strv); } else if (G_VALUE_TYPE (to) == GAME_TYPE_COLOR) { GameColor color; if (from->type != GCONF_VALUE_STRING) return FALSE; if (!game_color_from_string (&color, gconf_value_get_string (from))) return FALSE; g_value_set_boxed (to, &color); } else { g_return_val_if_reached (FALSE); } return TRUE; } static void game_gnome_gconf_state_foreach_read (gpointer path, gpointer value, gpointer state) { GConfValue *val; GValue new = { 0, }; GError *error = NULL; char *key = game_gnome_gconf_key_from_path (state, path); val = gconf_client_get (GAME_GNOME_GCONF_STATE (state)->gconf, key, &error); game_gnome_gconf_state_handle_error (state, error); g_free (key); if (!val) return; g_value_init (&new, G_VALUE_TYPE (value)); if (!value_from_gconf_value (&new, val)) { gconf_value_free (val); return; } game_gnome_state_set_value (state, path, &new); gconf_value_free (val); g_value_unset (&new); } static void game_gnome_gconf_state_gconf_value_changed_cb (GConfClient* client, const gchar* key, GConfValue* val, GameGnomeState *state) { const char *path = game_gnome_gconf_path_from_key (state, key); GValue value = { 0, }; if (!game_gnome_state_get_value (state, path, &value)) return; if (!value_from_gconf_value (&value, val)) { g_value_unset (&value); return; } game_gnome_state_set_value (state, path, &value); g_value_unset (&value); } static void game_gnome_gconf_state_do_init (GameGnomeState *state) { char *str; GError *error = NULL; GameGnomeGconfState *gstate = GAME_GNOME_GCONF_STATE (state); /* setup GConf */ gstate->gconf = gconf_client_get_default (); g_signal_connect (gstate->gconf, "value-changed", G_CALLBACK (game_gnome_gconf_state_gconf_value_changed_cb), state); str = g_strconcat (GAME_GCONF_DIR, "/", state->name, NULL); gconf_client_add_dir (gstate->gconf, str, GCONF_CLIENT_PRELOAD_RECURSIVE, &error); g_free (str); game_gnome_gconf_state_handle_error (gstate, error); /* copy values from GConf */ g_hash_table_foreach (state->values, game_gnome_gconf_state_foreach_read, state); } static void game_gnome_gconf_state_value_changed (GameGnomeState *state, const char *path, GValue *value) { char *key; GError *error = NULL; GConfValue *val; GAME_GNOME_STATE_CLASS (parent_class)->value_changed (state, path, value); val = gconf_value_from_value (value); if (val == NULL) return; key = game_gnome_gconf_key_from_path (state, path); gconf_client_set (GAME_GNOME_GCONF_STATE (state)->gconf, key, val, &error); game_gnome_gconf_state_handle_error (GAME_GNOME_GCONF_STATE (state), error); g_free (key); gconf_value_free (val); } static void game_gnome_gconf_state_class_init (gpointer g_class, gpointer class_data) { GObjectClass *object_class = G_OBJECT_CLASS (g_class); GameGnomeStateClass *state_class = GAME_GNOME_STATE_CLASS (g_class); parent_class = g_type_class_peek_parent (g_class); object_class->finalize = game_gnome_gconf_state_finalize; object_class->get_property = game_gnome_gconf_state_get_property; object_class->set_property = game_gnome_gconf_state_set_property; state_class->init = game_gnome_gconf_state_do_init; state_class->value_changed = game_gnome_gconf_state_value_changed; } static void game_gnome_gconf_state_init (GTypeInstance *instance, gpointer g_class) { } GType game_gnome_gconf_state_get_type () { static GType type = 0; if (!type) { static const GTypeInfo gnome_gconf_state_info = { sizeof (GameGnomeGconfStateClass), NULL, NULL, game_gnome_gconf_state_class_init, NULL, NULL, sizeof (GameGnomeGconfState), 0, game_gnome_gconf_state_init, }; type = g_type_register_static (GAME_TYPE_GNOME_STATE, "GameGnomeGconfState", &gnome_gconf_state_info, 0); } return type; }