/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
 *
 * Copyright (C) 2004-2006 William Jon McCann <mccann@jhu.edu>
 *
 * 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 of the License, 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.
 *
 * Authors: William Jon McCann <mccann@jhu.edu>
 *
 */

#include "config.h"

#include <string.h>

#include <glib.h>
#include <glib-object.h>
#include <mateconf/mateconf-client.h>

#include "gs-prefs.h"

static void gs_prefs_class_init (GSPrefsClass *klass);
static void gs_prefs_init       (GSPrefs      *prefs);
static void gs_prefs_finalize   (GObject      *object);

#define MATE_LOCKDOWN_DIR "/desktop/mate/lockdown"
#define KEY_LOCK_DISABLE          MATE_LOCKDOWN_DIR "/disable_lock_screen"
#define KEY_USER_SWITCH_DISABLE   MATE_LOCKDOWN_DIR "/disable_user_switching"

#define KEY_DIR            "/apps/mate-screensaver"
#define MATE_SESSION_DIR  "/desktop/mate/session"
#define KEY_IDLE_ACTIVATION_ENABLED         KEY_DIR "/idle_activation_enabled"
#define KEY_LOCK_ENABLED   KEY_DIR "/lock_enabled"
#define KEY_MODE           KEY_DIR "/mode"
#define KEY_ACTIVATE_DELAY MATE_SESSION_DIR "/idle_delay"
#define KEY_POWER_DELAY    KEY_DIR "/power_management_delay"
#define KEY_LOCK_DELAY     KEY_DIR "/lock_delay"
#define KEY_CYCLE_DELAY    KEY_DIR "/cycle_delay"
#define KEY_THEMES         KEY_DIR "/themes"
#define KEY_USER_SWITCH_ENABLED KEY_DIR "/user_switch_enabled"
#define KEY_LOGOUT_ENABLED KEY_DIR "/logout_enabled"
#define KEY_LOGOUT_DELAY   KEY_DIR "/logout_delay"
#define KEY_LOGOUT_COMMAND KEY_DIR "/logout_command"
#define KEY_KEYBOARD_ENABLED KEY_DIR "/embedded_keyboard_enabled"
#define KEY_KEYBOARD_COMMAND KEY_DIR "/embedded_keyboard_command"
#define KEY_STATUS_MESSAGE_ENABLED   KEY_DIR "/status_message_enabled"

#define GS_PREFS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GS_TYPE_PREFS, GSPrefsPrivate))

struct GSPrefsPrivate
{
	MateConfClient *mateconf_client;
};

enum
{
    CHANGED,
    LAST_SIGNAL
};

enum
{
    PROP_0
};

static MateConfEnumStringPair mode_enum_map [] =
{
	{ GS_MODE_BLANK_ONLY,       "blank-only" },
	{ GS_MODE_RANDOM,           "random"     },
	{ GS_MODE_SINGLE,           "single"     },
	{ 0, NULL }
};

static guint         signals [LAST_SIGNAL] = { 0, };

G_DEFINE_TYPE (GSPrefs, gs_prefs, G_TYPE_OBJECT)

static void
gs_prefs_set_property (GObject            *object,
                       guint               prop_id,
                       const GValue       *value,
                       GParamSpec         *pspec)
{
	switch (prop_id)
	{
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}

static void
gs_prefs_get_property (GObject            *object,
                       guint               prop_id,
                       GValue             *value,
                       GParamSpec         *pspec)
{
	switch (prop_id)
	{
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}

static void
gs_prefs_class_init (GSPrefsClass *klass)
{
	GObjectClass   *object_class = G_OBJECT_CLASS (klass);

	object_class->finalize     = gs_prefs_finalize;
	object_class->get_property = gs_prefs_get_property;
	object_class->set_property = gs_prefs_set_property;


	signals [CHANGED] =
	    g_signal_new ("changed",
	                  G_TYPE_FROM_CLASS (object_class),
	                  G_SIGNAL_RUN_LAST,
	                  G_STRUCT_OFFSET (GSPrefsClass, changed),
	                  NULL,
	                  NULL,
	                  g_cclosure_marshal_VOID__VOID,
	                  G_TYPE_NONE,
	                  0);

	g_type_class_add_private (klass, sizeof (GSPrefsPrivate));

}

static void
_gs_prefs_set_timeout (GSPrefs *prefs,
                       int      value)
{
	if (value < 1)
		value = 10;

	/* pick a reasonable large number for the
	   upper bound */
	if (value > 480)
		value = 480;

	prefs->timeout = value * 60000;
}

static void
_gs_prefs_set_power_timeout (GSPrefs *prefs,
                             int      value)
{
	if (value < 1)
		value = 60;

	/* pick a reasonable large number for the
	   upper bound */
	if (value > 480)
		value = 480;

	/* this value is in seconds - others are in minutes */
	prefs->power_timeout = value * 1000;
}

static void
_gs_prefs_set_lock_timeout (GSPrefs *prefs,
                            int      value)
{
	if (value < 0)
		value = 0;

	/* pick a reasonable large number for the
	   upper bound */
	if (value > 480)
		value = 480;

	prefs->lock_timeout = value * 60000;
}

static void
_gs_prefs_set_cycle_timeout (GSPrefs *prefs,
                             int      value)
{
	if (value < 1)
		value = 1;

	/* pick a reasonable large number for the
	   upper bound */
	if (value > 480)
		value = 480;

	prefs->cycle = value * 60000;
}

static void
_gs_prefs_set_mode (GSPrefs    *prefs,
                    const char *value)
{
	int mode;

	if (value && mateconf_string_to_enum (mode_enum_map, value, &mode))
		prefs->mode = mode;
	else
		prefs->mode = GS_MODE_BLANK_ONLY;
}

static void
_gs_prefs_set_themes (GSPrefs *prefs,
                      GSList  *list)
{
	if (prefs->themes)
	{
		g_slist_foreach (prefs->themes, (GFunc)g_free, NULL);
		g_slist_free (prefs->themes);
	}

	/* take ownership of the list */
	prefs->themes = list;
}

static void
_gs_prefs_set_idle_activation_enabled (GSPrefs *prefs,
                                       gboolean value)
{
	prefs->idle_activation_enabled = value;
}

static void
_gs_prefs_set_lock_enabled (GSPrefs *prefs,
                            gboolean value)
{
	prefs->lock_enabled = value;
}

static void
_gs_prefs_set_lock_disabled (GSPrefs *prefs,
                             gboolean value)
{
	prefs->lock_disabled = value;
}

static void
_gs_prefs_set_user_switch_disabled (GSPrefs *prefs,
                                    gboolean value)
{
	prefs->user_switch_disabled = value;
}

static void
_gs_prefs_set_keyboard_enabled (GSPrefs *prefs,
                                gboolean value)
{
	prefs->keyboard_enabled = value;
}

static void
_gs_prefs_set_keyboard_command (GSPrefs    *prefs,
                                const char *value)
{
	g_free (prefs->keyboard_command);
	prefs->keyboard_command = NULL;

	if (value)
	{
		/* FIXME: check command */

		prefs->keyboard_command = g_strdup (value);
	}
}

static void
_gs_prefs_set_status_message_enabled (GSPrefs  *prefs,
                                      gboolean  enabled)
{
	prefs->status_message_enabled = enabled;
}

static void
_gs_prefs_set_logout_enabled (GSPrefs *prefs,
                              gboolean value)
{
	prefs->logout_enabled = value;
}

static void
_gs_prefs_set_logout_command (GSPrefs    *prefs,
                              const char *value)
{
	g_free (prefs->logout_command);
	prefs->logout_command = NULL;

	if (value)
	{
		/* FIXME: check command */

		prefs->logout_command = g_strdup (value);
	}
}

static void
_gs_prefs_set_logout_timeout (GSPrefs *prefs,
                              int      value)
{
	if (value < 0)
		value = 0;

	/* pick a reasonable large number for the
	   upper bound */
	if (value > 480)
		value = 480;

	prefs->logout_timeout = value * 60000;
}

static void
_gs_prefs_set_user_switch_enabled (GSPrefs *prefs,
                                   gboolean value)
{
	prefs->user_switch_enabled = value;
}

static void
key_error_and_free (const char *key,
                    GError     *error)
{
	g_warning ("Error retrieving configuration key '%s': %s", key, error->message);
	g_error_free (error);
	error = NULL;
}

static void
gs_prefs_load_from_mateconf (GSPrefs *prefs)
{
	glong    value;
	gboolean bvalue;
	char    *string;
	GSList  *list;
	GError  *error;

	error = NULL;
	bvalue = mateconf_client_get_bool (prefs->priv->mateconf_client, KEY_IDLE_ACTIVATION_ENABLED, &error);
	if (! error)
	{
		_gs_prefs_set_idle_activation_enabled (prefs, bvalue);
	}
	else
	{
		key_error_and_free (KEY_IDLE_ACTIVATION_ENABLED, error);
	}

	error = NULL;
	bvalue = mateconf_client_get_bool (prefs->priv->mateconf_client, KEY_LOCK_ENABLED, &error);
	if (! error)
	{
		_gs_prefs_set_lock_enabled (prefs, bvalue);
	}
	else
	{
		key_error_and_free (KEY_LOCK_ENABLED, error);
	}

	error = NULL;
	bvalue = mateconf_client_get_bool (prefs->priv->mateconf_client, KEY_LOCK_DISABLE, &error);
	if (! error)
	{
		_gs_prefs_set_lock_disabled (prefs, bvalue);
	}
	else
	{
		key_error_and_free (KEY_LOCK_DISABLE, error);
	}

	error = NULL;
	bvalue = mateconf_client_get_bool (prefs->priv->mateconf_client, KEY_USER_SWITCH_DISABLE, &error);
	if (! error)
	{
		_gs_prefs_set_user_switch_disabled (prefs, bvalue);
	}
	else
	{
		key_error_and_free (KEY_USER_SWITCH_DISABLE, error);
	}

	error = NULL;
	value = mateconf_client_get_int (prefs->priv->mateconf_client, KEY_ACTIVATE_DELAY, &error);
	if (! error)
	{
		_gs_prefs_set_timeout (prefs, value);
	}
	else
	{
		key_error_and_free (KEY_ACTIVATE_DELAY, error);
	}

	error = NULL;
	value = mateconf_client_get_int (prefs->priv->mateconf_client, KEY_POWER_DELAY, &error);
	if (! error)
	{
		_gs_prefs_set_power_timeout (prefs, value);
	}
	else
	{
		key_error_and_free (KEY_POWER_DELAY, error);
	}

	error = NULL;
	value = mateconf_client_get_int (prefs->priv->mateconf_client, KEY_LOCK_DELAY, &error);
	if (! error)
	{
		_gs_prefs_set_lock_timeout (prefs, value);
	}
	else
	{
		key_error_and_free (KEY_LOCK_DELAY, error);
	}

	error = NULL;
	value = mateconf_client_get_int (prefs->priv->mateconf_client, KEY_CYCLE_DELAY, &error);
	if (! error)
	{
		_gs_prefs_set_cycle_timeout (prefs, value);
	}
	else
	{
		key_error_and_free (KEY_CYCLE_DELAY, error);
	}

	error = NULL;
	string = mateconf_client_get_string (prefs->priv->mateconf_client, KEY_MODE, &error);
	if (! error)
	{
		_gs_prefs_set_mode (prefs, string);
	}
	else
	{
		key_error_and_free (KEY_MODE, error);
	}
	g_free (string);

	error = NULL;
	list = mateconf_client_get_list (prefs->priv->mateconf_client,
	                                 KEY_THEMES,
	                                 MATECONF_VALUE_STRING,
	                                 &error);
	if (! error)
	{
		_gs_prefs_set_themes (prefs, list);
	}
	else
	{
		key_error_and_free (KEY_THEMES, error);
	}

	/* Embedded keyboard options */

	error = NULL;
	bvalue = mateconf_client_get_bool (prefs->priv->mateconf_client, KEY_KEYBOARD_ENABLED, &error);
	if (! error)
	{
		_gs_prefs_set_keyboard_enabled (prefs, bvalue);
	}
	else
	{
		key_error_and_free (KEY_KEYBOARD_ENABLED, error);
	}

	error = NULL;
	string = mateconf_client_get_string (prefs->priv->mateconf_client, KEY_KEYBOARD_COMMAND, &error);
	if (! error)
	{
		_gs_prefs_set_keyboard_command (prefs, string);
	}
	else
	{
		key_error_and_free (KEY_KEYBOARD_COMMAND, error);
	}
	g_free (string);

	error = NULL;
	bvalue = mateconf_client_get_bool (prefs->priv->mateconf_client, KEY_STATUS_MESSAGE_ENABLED, &error);
	if (! error)
	{
		_gs_prefs_set_status_message_enabled (prefs, bvalue);
	}
	else
	{
		key_error_and_free (KEY_STATUS_MESSAGE_ENABLED, error);
	}

	/* Logout options */

	error = NULL;
	bvalue = mateconf_client_get_bool (prefs->priv->mateconf_client, KEY_LOGOUT_ENABLED, &error);
	if (! error)
	{
		_gs_prefs_set_logout_enabled (prefs, bvalue);
	}
	else
	{
		key_error_and_free (KEY_LOGOUT_ENABLED, error);
	}

	error = NULL;
	string = mateconf_client_get_string (prefs->priv->mateconf_client, KEY_LOGOUT_COMMAND, &error);
	if (! error)
	{
		_gs_prefs_set_logout_command (prefs, string);
	}
	else
	{
		key_error_and_free (KEY_LOGOUT_COMMAND, error);
	}
	g_free (string);

	error = NULL;
	value = mateconf_client_get_int (prefs->priv->mateconf_client, KEY_LOGOUT_DELAY, &error);
	if (! error)
	{
		_gs_prefs_set_logout_timeout (prefs, value);
	}
	else
	{
		key_error_and_free (KEY_LOGOUT_DELAY, error);
	}

	/* User switching options */

	error = NULL;
	bvalue = mateconf_client_get_bool (prefs->priv->mateconf_client, KEY_USER_SWITCH_ENABLED, &error);
	if (! error)
	{
		_gs_prefs_set_user_switch_enabled (prefs, bvalue);
	}
	else
	{
		key_error_and_free (KEY_USER_SWITCH_ENABLED, error);
	}
}

static void
invalid_type_warning (const char *type)
{
	g_warning ("Error retrieving configuration key '%s': Invalid type",
	           type);
}

static void
key_changed_cb (MateConfClient *client,
                guint        cnxn_id,
                MateConfEntry  *entry,
                GSPrefs     *prefs)
{
	gboolean    changed = FALSE;
	const char *key;
	MateConfValue *value;

	key = mateconf_entry_get_key (entry);

	if (! g_str_has_prefix (key, KEY_DIR) && ! g_str_has_prefix (key, MATE_LOCKDOWN_DIR))
		return;

	value = mateconf_entry_get_value (entry);

	if (strcmp (key, KEY_MODE) == 0)
	{

		if (value->type == MATECONF_VALUE_STRING)
		{
			const char *str;

			str = mateconf_value_get_string (value);
			_gs_prefs_set_mode (prefs, str);

			changed = TRUE;
		}
		else
		{
			invalid_type_warning (key);
		}

	}
	else if (strcmp (key, KEY_THEMES) == 0)
	{
		GSList *list = NULL;

		if (value == NULL
		        || value->type != MATECONF_VALUE_LIST)
		{
			return;
		}

		list = mateconf_value_get_list (value);

		if (list
		        && mateconf_value_get_list_type (value) == MATECONF_VALUE_STRING)
		{
			GSList *l;
			GSList *new_list;

			changed = TRUE;

			new_list = NULL;
			for (l = list; l; l = l->next)
			{
				char *s;

				s = mateconf_value_to_string (l->data);

				new_list = g_slist_prepend (new_list, g_strdup (s));

				g_free (s);
			}

			new_list = g_slist_reverse (new_list);

			_gs_prefs_set_themes (prefs, new_list);

		}

	}
	else if (strcmp (key, KEY_ACTIVATE_DELAY) == 0)
	{

		if (value->type == MATECONF_VALUE_INT)
		{
			int delay;

			delay = mateconf_value_get_int (value);
			_gs_prefs_set_timeout (prefs, delay);

			changed = TRUE;
		}
		else
		{
			invalid_type_warning (key);
		}

	}
	else if (strcmp (key, KEY_POWER_DELAY) == 0)
	{

		if (value->type == MATECONF_VALUE_INT)
		{
			int delay;

			delay = mateconf_value_get_int (value);
			_gs_prefs_set_power_timeout (prefs, delay);

			changed = TRUE;
		}
		else
		{
			invalid_type_warning (key);
		}

	}
	else if (strcmp (key, KEY_LOCK_DELAY) == 0)
	{

		if (value->type == MATECONF_VALUE_INT)
		{
			int delay;

			delay = mateconf_value_get_int (value);
			_gs_prefs_set_lock_timeout (prefs, delay);

			changed = TRUE;
		}
		else
		{
			invalid_type_warning (key);
		}

	}
	else if (strcmp (key, KEY_IDLE_ACTIVATION_ENABLED) == 0)
	{

		if (value->type == MATECONF_VALUE_BOOL)
		{
			gboolean enabled;

			enabled = mateconf_value_get_bool (value);
			_gs_prefs_set_idle_activation_enabled (prefs, enabled);

			changed = TRUE;
		}
		else
		{
			invalid_type_warning (key);
		}

	}
	else if (strcmp (key, KEY_LOCK_ENABLED) == 0)
	{

		if (value->type == MATECONF_VALUE_BOOL)
		{
			gboolean enabled;

			enabled = mateconf_value_get_bool (value);
			_gs_prefs_set_lock_enabled (prefs, enabled);

			changed = TRUE;
		}
		else
		{
			invalid_type_warning (key);
		}

	}
	else if (strcmp (key, KEY_LOCK_DISABLE) == 0)
	{

		if (value->type == MATECONF_VALUE_BOOL)
		{
			gboolean disabled;

			disabled = mateconf_value_get_bool (value);
			_gs_prefs_set_lock_disabled (prefs, disabled);

			changed = TRUE;
		}
		else
		{
			invalid_type_warning (key);
		}

	}
	else if (strcmp (key, KEY_USER_SWITCH_DISABLE) == 0)
	{

		if (value->type == MATECONF_VALUE_BOOL)
		{
			gboolean disabled;

			disabled = mateconf_value_get_bool (value);
			_gs_prefs_set_user_switch_disabled (prefs, disabled);

			changed = TRUE;
		}
		else
		{
			invalid_type_warning (key);
		}

	}
	else if (strcmp (key, KEY_CYCLE_DELAY) == 0)
	{

		if (value->type == MATECONF_VALUE_INT)
		{
			int delay;

			delay = mateconf_value_get_int (value);
			_gs_prefs_set_cycle_timeout (prefs, delay);

			changed = TRUE;
		}
		else
		{
			invalid_type_warning (key);
		}

	}
	else if (strcmp (key, KEY_KEYBOARD_ENABLED) == 0)
	{

		if (value->type == MATECONF_VALUE_BOOL)
		{
			gboolean enabled;

			enabled = mateconf_value_get_bool (value);
			_gs_prefs_set_keyboard_enabled (prefs, enabled);

			changed = TRUE;
		}
		else
		{
			invalid_type_warning (key);
		}

	}
	else if (strcmp (key, KEY_KEYBOARD_COMMAND) == 0)
	{

		if (value->type == MATECONF_VALUE_STRING)
		{
			const char *command;

			command = mateconf_value_get_string (value);
			_gs_prefs_set_keyboard_command (prefs, command);

			changed = TRUE;
		}
		else
		{
			invalid_type_warning (key);
		}

	}
	else if (strcmp (key, KEY_STATUS_MESSAGE_ENABLED) == 0)
	{

		if (value->type == MATECONF_VALUE_BOOL)
		{
			gboolean enabled;

			enabled = mateconf_value_get_bool (value);
			_gs_prefs_set_status_message_enabled (prefs, enabled);

			changed = TRUE;
		}
		else
		{
			invalid_type_warning (key);
		}

	}
	else if (strcmp (key, KEY_LOGOUT_ENABLED) == 0)
	{

		if (value->type == MATECONF_VALUE_BOOL)
		{
			gboolean enabled;

			enabled = mateconf_value_get_bool (value);
			_gs_prefs_set_logout_enabled (prefs, enabled);

			changed = TRUE;
		}
		else
		{
			invalid_type_warning (key);
		}

	}
	else if (strcmp (key, KEY_LOGOUT_DELAY) == 0)
	{

		if (value->type == MATECONF_VALUE_INT)
		{
			int delay;

			delay = mateconf_value_get_int (value);
			_gs_prefs_set_logout_timeout (prefs, delay);

			changed = TRUE;
		}
		else
		{
			invalid_type_warning (key);
		}

	}
	else if (strcmp (key, KEY_LOGOUT_COMMAND) == 0)
	{

		if (value->type == MATECONF_VALUE_STRING)
		{
			const char *command;

			command = mateconf_value_get_string (value);
			_gs_prefs_set_logout_command (prefs, command);

			changed = TRUE;
		}
		else
		{
			invalid_type_warning (key);
		}

	}
	else if (strcmp (key, KEY_USER_SWITCH_ENABLED) == 0)
	{

		if (value->type == MATECONF_VALUE_BOOL)
		{
			gboolean enabled;

			enabled = mateconf_value_get_bool (value);
			_gs_prefs_set_user_switch_enabled (prefs, enabled);

			changed = TRUE;
		}
		else
		{
			invalid_type_warning (key);
		}

	}
	else
	{
		g_warning ("Config key not handled: %s", key);
	}

	if (changed && prefs)
	{
		g_signal_emit (prefs, signals [CHANGED], 0);
	}
}

static void
gs_prefs_init (GSPrefs *prefs)
{
	prefs->priv = GS_PREFS_GET_PRIVATE (prefs);

	prefs->priv->mateconf_client      = mateconf_client_get_default ();

	prefs->idle_activation_enabled = TRUE;
	prefs->lock_enabled            = TRUE;
	prefs->lock_disabled           = FALSE;
	prefs->logout_enabled          = FALSE;
	prefs->user_switch_enabled     = FALSE;

	prefs->timeout                 = 600000;
	prefs->power_timeout           = 60000;
	prefs->lock_timeout            = 0;
	prefs->logout_timeout          = 14400000;
	prefs->cycle                   = 600000;

	prefs->mode                    = GS_MODE_SINGLE;

	/* MateConf setup */
	mateconf_client_add_dir (prefs->priv->mateconf_client,
	                         KEY_DIR,
	                         MATECONF_CLIENT_PRELOAD_NONE, NULL);
	mateconf_client_add_dir (prefs->priv->mateconf_client,
	                         MATE_LOCKDOWN_DIR,
	                         MATECONF_CLIENT_PRELOAD_NONE, NULL);
	mateconf_client_add_dir (prefs->priv->mateconf_client,
	                         MATE_SESSION_DIR,
	                         MATECONF_CLIENT_PRELOAD_NONE, NULL);


	mateconf_client_notify_add (prefs->priv->mateconf_client,
	                            KEY_DIR,
	                            (MateConfClientNotifyFunc)key_changed_cb,
	                            prefs,
	                            NULL, NULL);
	mateconf_client_notify_add (prefs->priv->mateconf_client,
	                            MATE_LOCKDOWN_DIR,
	                            (MateConfClientNotifyFunc)key_changed_cb,
	                            prefs,
	                            NULL, NULL);

	gs_prefs_load_from_mateconf (prefs);
}

static void
gs_prefs_finalize (GObject *object)
{
	GSPrefs *prefs;

	g_return_if_fail (object != NULL);
	g_return_if_fail (GS_IS_PREFS (object));

	prefs = GS_PREFS (object);

	g_return_if_fail (prefs->priv != NULL);

	if (prefs->priv->mateconf_client)
	{
		g_object_unref (prefs->priv->mateconf_client);
		prefs->priv->mateconf_client = NULL;
	}

	if (prefs->themes)
	{
		g_slist_foreach (prefs->themes, (GFunc)g_free, NULL);
		g_slist_free (prefs->themes);
	}

	g_free (prefs->logout_command);
	g_free (prefs->keyboard_command);

	G_OBJECT_CLASS (gs_prefs_parent_class)->finalize (object);
}

GSPrefs *
gs_prefs_new (void)
{
	GObject *prefs;

	prefs = g_object_new (GS_TYPE_PREFS, NULL);

	return GS_PREFS (prefs);
}
