Mercurial > pidgin
changeset 25097:60d3ba8c9047
propagate from branch 'im.pidgin.pidgin' (head 1d533cebad7c0dbda8ec8ebee1334d27dcae5f9c)
to branch 'im.pidgin.soc.2008.themes' (head 6108b8f480f1589e219641d557022940902871cf)
author | Gary Kramlich <grim@reaperworld.com> |
---|---|
date | Mon, 30 Jun 2008 23:12:54 +0000 |
parents | 47b709962aab (current diff) fbf72bbd1084 (diff) |
children | 331a7a69d955 |
files | finch/libgnt/gntkeys.c libpurple/Makefile.am libpurple/protocols/qq/qq_proxy.c libpurple/protocols/qq/qq_proxy.h libpurple/protocols/qq/recv_core.c libpurple/protocols/qq/recv_core.h libpurple/protocols/qq/send_core.c libpurple/protocols/qq/send_core.h libpurple/protocols/qq/sendqueue.c libpurple/protocols/qq/sendqueue.h libpurple/protocols/qq/udp_proxy_s5.c libpurple/protocols/qq/udp_proxy_s5.h libpurple/util.c |
diffstat | 18 files changed, 2011 insertions(+), 68 deletions(-) [+] |
line wrap: on
line diff
--- a/libpurple/Makefile.am Mon Jun 30 22:58:18 2008 +0000 +++ b/libpurple/Makefile.am Mon Jun 30 23:12:54 2008 +0000 @@ -75,8 +75,13 @@ stringref.c \ stun.c \ sound.c \ + sound-loader.c \ + sound-theme.c \ sslconn.c \ upnp.c \ + theme.c \ + theme-loader.c \ + theme-manager.c \ util.c \ value.c \ version.c \ @@ -128,8 +133,13 @@ stringref.h \ stun.h \ sound.h \ + sound-loader.h \ + sound-theme.h \ sslconn.h \ upnp.h \ + theme.h \ + theme-loader.h \ + theme-manager.h \ util.h \ value.h \ xmlnode.h \
--- a/libpurple/core.c Mon Jun 30 22:58:18 2008 +0000 +++ b/libpurple/core.c Mon Jun 30 23:12:54 2008 +0000 @@ -45,10 +45,12 @@ #include "signals.h" #include "smiley.h" #include "sound.h" +#include "sound-loader.h" #include "sslconn.h" #include "status.h" #include "stun.h" #include "util.h" +#include "theme-manager.h" #ifdef HAVE_DBUS # ifndef DBUS_API_SUBJECT_TO_CHANGE @@ -147,6 +149,7 @@ /* Accounts use status, buddy icons and connection signals, so * initialize these before accounts */ + purple_theme_manager_init(g_object_new(PURPLE_TYPE_SOUND_THEME_LOADER, "type", "sound", NULL), NULL); purple_status_init(); purple_buddy_icons_init(); purple_connections_init(); @@ -169,7 +172,7 @@ purple_xfers_init(); purple_idle_init(); purple_smileys_init(); - + /* * Call this early on to try to auto-detect our IP address and * hopefully save some time later. @@ -178,6 +181,7 @@ if (ops != NULL && ops->ui_init != NULL) ops->ui_init(); + return TRUE; } @@ -213,6 +217,7 @@ purple_status_uninit(); purple_prefs_uninit(); purple_sound_uninit(); + purple_theme_manager_uninit(); purple_xfers_uninit(); purple_proxy_uninit(); purple_dnsquery_uninit();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/sound-loader.c Mon Jun 30 23:12:54 2008 +0000 @@ -0,0 +1,124 @@ +/* + * SoundThemeLoader for LibPurple + * + * Pidgin is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * + */ + +#include "sound-loader.h" +#include "sound-theme.h" +#include "util.h" +#include "xmlnode.h" + +/****************************************************************************** + * Globals + *****************************************************************************/ +/***************************************************************************** + * Sound Theme Builder + *****************************************************************************/ + +static gpointer +purple_sound_loader_build(const gchar *dir) +{ + xmlnode *root_node, *sub_node; + gchar *filename, *filename_full, *data; + GDir *gdir; + PurpleSoundTheme *theme; + + /* Find the theme file */ + gdir = g_dir_open(dir, 0, NULL); + g_return_val_if_fail(gdir != NULL, NULL); + + while ((filename = g_strdup(g_dir_read_name(gdir))) != NULL && ! g_str_has_suffix(filename, ".xml")) + g_free(filename); + + g_return_val_if_fail(filename != NULL, NULL); + + /* Build the xml tree */ + filename_full = g_build_filename(dir, filename, NULL); + + root_node = xmlnode_from_file(dir, filename, "sound themes", "sound-loader"); + g_return_val_if_fail(root_node != NULL, NULL); + + /* Parse the tree */ + sub_node = xmlnode_get_child(root_node, "description"); + data = xmlnode_get_data(sub_node); + + theme = g_object_new(PURPLE_TYPE_SOUND_THEME, + "type", "sound", + "name", xmlnode_get_attrib(root_node, "name"), + "author", xmlnode_get_attrib(root_node, "author"), + "image", xmlnode_get_attrib(root_node, "image"), + "directory", dir, + "description", data, NULL); + + xmlnode_free(sub_node); + + while ((sub_node = xmlnode_get_child(root_node, "event")) != NULL){ + purple_sound_theme_set_file(theme, + xmlnode_get_attrib(sub_node, "name"), + xmlnode_get_attrib(sub_node, "file")); + xmlnode_free(sub_node); + } + + xmlnode_free(root_node); + g_dir_close(gdir); + g_free(filename_full); + g_free(data); + return theme; +} + +/****************************************************************************** + * GObject Stuff + *****************************************************************************/ + +static void +purple_sound_theme_loader_class_init (PurpleSoundThemeLoaderClass *klass) +{ + PurpleThemeLoaderClass *loader_klass = PURPLE_THEME_LOADER_CLASS(klass); + + loader_klass->purple_theme_loader_build = purple_sound_loader_build; +} + + +GType +purple_sound_theme_loader_get_type (void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (PurpleSoundThemeLoaderClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)purple_sound_theme_loader_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (PurpleSoundThemeLoader), + 0, /* n_preallocs */ + NULL, /* instance_init */ + NULL, /* value table */ + }; + type = g_type_register_static (PURPLE_TYPE_THEME_LOADER, + "PurpleSoundThemeLoader", + &info, 0); + } + return type; +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/sound-loader.h Mon Jun 30 23:12:54 2008 +0000 @@ -0,0 +1,71 @@ +/** + * @file sound-loader.h Purple Sound Theme Loader Class API + */ + +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#ifndef _PURPLE_SOUND_THEME_LOADER_H_ +#define _PURPLE_SOUND_THEME_LOADER_H_ + +#include <glib.h> +#include <glib-object.h> +#include "theme-loader.h" + +/** + * A purple sound theme loader. extends PurpleThemeLoader (theme-loader.h) + * This is a class designed to build sound themes + * + * PurpleSoundThemeLoader is a GObject. + */ +typedef struct _PurpleSoundThemeLoader PurpleSoundThemeLoader; +typedef struct _PurpleSoundThemeLoaderClass PurpleSoundThemeLoaderClass; + +#define PURPLE_TYPE_SOUND_THEME_LOADER (purple_sound_theme_loader_get_type ()) +#define PURPLE_SOUND_THEME_LOADER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PURPLE_TYPE_SOUND_THEME_LOADER, PurpleSoundThemeLoader)) +#define PURPLE_SOUND_THEME_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PURPLE_TYPE_SOUND_THEME_LOADER, PurpleSoundThemeLoaderClass)) +#define PURPLE_IS_SOUND_THEME_LOADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PURPLE_TYPE_SOUND_THEME_LOADER)) +#define PURPLE_IS_SOUND_THEME_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PURPLE_TYPE_SOUND_THEME_LOADER)) +#define PURPLE_SOUND_THEME_LOADER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PURPLE_TYPE_SOUND_THEME_LOADER, PurpleSoundThemeLoaderClass)) + +struct _PurpleSoundThemeLoader +{ + PurpleThemeLoader parent; +}; + +struct _PurpleSoundThemeLoaderClass +{ + PurpleThemeLoaderClass parent_class; +}; + +/**************************************************************************/ +/** @name Purple Theme-Loader API */ +/**************************************************************************/ +G_BEGIN_DECLS + +/** + * GObject foo. + * @internal. + */ +GType purple_sound_theme_loader_get_type(void); + +G_END_DECLS +#endif /* _PURPLE_SOUND_THEME_LOADER_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/sound-theme.c Mon Jun 30 23:12:54 2008 +0000 @@ -0,0 +1,163 @@ +/* + * Sound Themes for LibPurple + * + * Pidgin is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * + */ + +#include "sound-theme.h" + +#define PURPLE_SOUND_THEME_GET_PRIVATE(Gobject) \ + ((PurpleSoundThemePrivate *) ((PURPLE_SOUND_THEME(Gobject))->priv)) + + +/****************************************************************************** + * Structs + *****************************************************************************/ +typedef struct { + /* used to store filenames of diffrent sounds */ + GHashTable *sound_files; +} PurpleSoundThemePrivate; + +/****************************************************************************** + * Globals + *****************************************************************************/ + +static GObjectClass *parent_class = NULL; + +/****************************************************************************** + * Enums + *****************************************************************************/ + +/****************************************************************************** + * GObject Stuff + *****************************************************************************/ + +static void +purple_sound_theme_init(GTypeInstance *instance, + gpointer klass) +{ + PurpleSoundThemePrivate *priv; + + (PURPLE_SOUND_THEME(instance))->priv = g_new0(PurpleSoundThemePrivate, 1); + + priv = PURPLE_SOUND_THEME_GET_PRIVATE(instance); + + priv->sound_files = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + g_free); +} + +static void +purple_sound_theme_finalize (GObject *obj) +{ + PurpleSoundThemePrivate *priv; + + priv = PURPLE_SOUND_THEME_GET_PRIVATE(obj); + + g_hash_table_destroy(priv->sound_files); + + parent_class->finalize (obj); +} + +static void +purple_sound_theme_class_init (PurpleSoundThemeClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + parent_class = g_type_class_peek_parent (klass); + + obj_class->finalize = purple_sound_theme_finalize; +} + +GType +purple_sound_theme_get_type (void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (PurpleSoundThemeClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)purple_sound_theme_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (PurpleSoundTheme), + 0, /* n_preallocs */ + purple_sound_theme_init, /* instance_init */ + NULL, /* value table */ + }; + type = g_type_register_static (PURPLE_TYPE_THEME, + "PurpleSoundTheme", + &info, 0); + } + return type; +} + + +/***************************************************************************** + * Public API functions + *****************************************************************************/ + +const gchar * +purple_sound_theme_get_file(PurpleSoundTheme *theme, + const gchar *event) +{ + PurpleSoundThemePrivate *priv; + + g_return_val_if_fail(PURPLE_IS_SOUND_THEME(theme), NULL); + + priv = PURPLE_SOUND_THEME_GET_PRIVATE(theme); + + return g_hash_table_lookup(priv->sound_files, event); +} + +gchar * +purple_sound_theme_get_file_full(PurpleSoundTheme *theme, + const gchar *event) +{ + gchar *filename; + + g_return_val_if_fail(PURPLE_IS_SOUND_THEME(theme), NULL); + + filename = purple_sound_theme_get_file(theme, event); + + g_return_val_if_fail(filename, NULL); + + return g_build_filename(purple_theme_get_dir(PURPLE_THEME(theme)), filename, NULL); +} + +void +purple_sound_theme_set_file(PurpleSoundTheme *theme, + const gchar *event, + const gchar *filename) +{ + PurpleSoundThemePrivate *priv; + g_return_if_fail(PURPLE_IS_SOUND_THEME(theme)); + + priv = PURPLE_SOUND_THEME_GET_PRIVATE(theme); + + if (filename != NULL)g_hash_table_replace(priv->sound_files, + g_strdup(event), + g_strdup(filename)); + else g_hash_table_remove(priv->sound_files, event); +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/sound-theme.h Mon Jun 30 23:12:54 2008 +0000 @@ -0,0 +1,102 @@ +/** + * @file sound-theme.h Purple Sound Theme Abstact Class API + */ + +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#ifndef _PURPLE_SOUND_THEME_H_ +#define _PURPLE_SOUND_THEME_H_ + +#include <glib.h> +#include <glib-object.h> +#include "theme.h" +#include "sound.h" + +/** + * extends PurpleTheme (theme.h) + * A purple sound theme. + * This is an object for Purple to represent a sound theme. + * + * PurpleSoundTheme is a PurpleTheme Object. + */ +typedef struct _PurpleSoundTheme PurpleSoundTheme; +typedef struct _PurpleSoundThemeClass PurpleSoundThemeClass; + +#define PURPLE_TYPE_SOUND_THEME (purple_sound_theme_get_type ()) +#define PURPLE_SOUND_THEME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PURPLE_TYPE_SOUND_THEME, PurpleSoundTheme)) +#define PURPLE_SOUND_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PURPLE_TYPE_SOUND_THEME, PurpleSoundThemeClass)) +#define PURPLE_IS_SOUND_THEME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PURPLE_TYPE_SOUND_THEME)) +#define PURPLE_IS_SOUND_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PURPLE_TYPE_SOUND_THEME)) +#define PURPLE_SOUND_THEME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PURPLE_TYPE_SOUND_THEME, PurpleSoundThemeClass)) + +struct _PurpleSoundTheme +{ + PurpleTheme parent; + gpointer priv; +}; + +struct _PurpleSoundThemeClass +{ + PurpleThemeClass parent_class; +}; + +/**************************************************************************/ +/** @name Purple Sound Theme API */ +/**************************************************************************/ +G_BEGIN_DECLS + +/** + * GObject foo. + * @internal. + */ +GType purple_sound_theme_get_type(void); + +/** + * Returns a copy of the filename for the sound event + * + * @param event the purple sound event to look up + * + * @returns the filename of the sound event + */ +const gchar *purple_sound_theme_get_file(PurpleSoundTheme *theme, + const gchar *event); +/** + * Returns a copy of the directory and filename for the sound event + * + * @param event the purple sound event to look up + * + * @returns the directory + '/' + filename of the sound event + */ +gchar *purple_sound_theme_get_file_full(PurpleSoundTheme *theme, + const gchar *event); +/** + * Sets the filename for a given sound event + * + * @param event the purple sound event to look up + * @param filename the name of the file to be used for the event + */ +void purple_sound_theme_set_file(PurpleSoundTheme *theme, + const gchar *event, + const gchar *filename); + +G_END_DECLS +#endif /* _PURPLE_SOUND_THEME_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/theme-loader.c Mon Jun 30 23:12:54 2008 +0000 @@ -0,0 +1,186 @@ +/* + * ThemeLoaders for LibPurple + * + * Pidgin is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * + */ + +#include "theme-loader.h" + +#define PURPLE_THEME_LOADER_GET_PRIVATE(PurpleThemeLoader) \ + ((PurpleThemeLoaderPrivate *) ((PurpleThemeLoader)->priv)) + +void purple_theme_loader_set_type_string(PurpleThemeLoader *loader, const gchar *type); +/****************************************************************************** + * Structs + *****************************************************************************/ +typedef struct { + gchar *type; +} PurpleThemeLoaderPrivate; + +/****************************************************************************** + * Globals + *****************************************************************************/ + +static GObjectClass *parent_class = NULL; + +/****************************************************************************** + * Enums + *****************************************************************************/ + +enum { + PROP_ZERO = 0, + PROP_TYPE, +}; + +/****************************************************************************** + * GObject Stuff * + *****************************************************************************/ + +static void +purple_theme_loader_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *psec) +{ + PurpleThemeLoader *theme_loader = PURPLE_THEME_LOADER(obj); + + switch(param_id) { + case PROP_TYPE: + g_value_set_string(value, purple_theme_loader_get_type_string(theme_loader)); + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, psec); + break; + } +} + +static void +purple_theme_loader_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *psec) +{ + PurpleThemeLoader *loader = PURPLE_THEME_LOADER(obj); + + switch(param_id) { + case PROP_TYPE: + purple_theme_loader_set_type_string(loader, g_value_get_string(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, psec); + break; + } +} + +static void +purple_theme_loader_init(GTypeInstance *instance, + gpointer klass) +{ + PurpleThemeLoader *loader = PURPLE_THEME_LOADER(instance); + loader->priv = g_new0(PurpleThemeLoaderPrivate, 1); +} + +static void +purple_theme_loader_finalize(GObject *obj) +{ + PurpleThemeLoader *loader = PURPLE_THEME_LOADER(obj); + PurpleThemeLoaderPrivate *priv = PURPLE_THEME_LOADER_GET_PRIVATE(loader); + + g_free(priv->type); + + parent_class->finalize (obj); +} + +static void +purple_theme_loader_class_init (PurpleThemeLoaderClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + GParamSpec *pspec; + + parent_class = g_type_class_peek_parent (klass); + + obj_class->get_property = purple_theme_loader_get_property; + obj_class->set_property = purple_theme_loader_set_property; + obj_class->finalize = purple_theme_loader_finalize; + + /* TYPE STRING (read only) */ + pspec = g_param_spec_string("type", "Type", + "The string represtenting the type of the theme", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property(obj_class, PROP_TYPE, pspec); +} + + +GType +purple_theme_loader_get_type (void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (PurpleThemeLoaderClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)purple_theme_loader_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (PurpleThemeLoader), + 0, /* n_preallocs */ + purple_theme_loader_init, /* instance_init */ + NULL, /* value table */ + }; + type = g_type_register_static (G_TYPE_OBJECT, + "PurpleThemeLoader", + &info, G_TYPE_FLAG_ABSTRACT); + } + return type; +} + + +/***************************************************************************** + * Public API functions + *****************************************************************************/ + + +const gchar * +purple_theme_loader_get_type_string (PurpleThemeLoader *theme_loader) +{ + PurpleThemeLoaderPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_THEME_LOADER(theme_loader), NULL); + + priv = PURPLE_THEME_LOADER_GET_PRIVATE(theme_loader); + return priv->type; +} + +/* < private > */ +void +purple_theme_loader_set_type_string(PurpleThemeLoader *loader, const gchar *type) +{ + PurpleThemeLoaderPrivate *priv; + + g_return_if_fail(PURPLE_IS_THEME_LOADER(loader)); + + priv = PURPLE_THEME_LOADER_GET_PRIVATE(loader); + + g_free(priv->type); + priv->type = g_strdup(type); +} + +gpointer +purple_theme_loader_build (PurpleThemeLoader *loader, const gchar *dir) +{ + return PURPLE_THEME_LOADER_GET_CLASS(loader)->purple_theme_loader_build(dir); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/theme-loader.h Mon Jun 30 23:12:54 2008 +0000 @@ -0,0 +1,92 @@ +/** + * @file theme-loader.h Purple Theme Loader Abstact Class API + */ + +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#ifndef _PURPLE_THEME_LOADER_H_ +#define _PURPLE_THEME_LOADER_H_ + +#include <glib.h> +#include <glib-object.h> +#include "theme.h" + +/** + * A purple theme loader. + * This is an abstract class for Purple to use with the Purple theme manager. + * The loader is responsible for building each type of theme + * + * PurpleThemeLoader is a GObject. + */ +typedef struct _PurpleThemeLoader PurpleThemeLoader; +typedef struct _PurpleThemeLoaderClass PurpleThemeLoaderClass; + +#define PURPLE_TYPE_THEME_LOADER (purple_theme_loader_get_type ()) +#define PURPLE_THEME_LOADER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PURPLE_TYPE_THEME_LOADER, PurpleThemeLoader)) +#define PURPLE_THEME_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PURPLE_TYPE_THEME_LOADER, PurpleThemeLoaderClass)) +#define PURPLE_IS_THEME_LOADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PURPLE_TYPE_THEME_LOADER)) +#define PURPLE_IS_THEME_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PURPLE_TYPE_THEME_LOADER)) +#define PURPLE_THEME_LOADER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PURPLE_TYPE_THEME_LOADER, PurpleThemeLoaderClass)) + +struct _PurpleThemeLoader +{ + GObject parent; + gpointer priv; +}; + +struct _PurpleThemeLoaderClass +{ + GObjectClass parent_class; + gpointer (*purple_theme_loader_build)(const gchar*); +}; + +/**************************************************************************/ +/** @name Purple Theme-Loader API */ +/**************************************************************************/ +G_BEGIN_DECLS + +/** + * GObject foo. + * @internal. + */ +GType purple_theme_loader_get_type(void); + +/** + * Returns the string represtenting the type of the theme loader + * + * @param self the theme loader + * + * @returns the string represting this type + */ +const gchar *purple_theme_loader_get_type_string(PurpleThemeLoader *self); + +/** + * Creates a new PurpleTheme + * + * @param dir the directory containing the theme + * + * @returns PurpleTheme containing the information from the directory + */ +gpointer purple_theme_loader_build(PurpleThemeLoader *loader, const gchar *dir); + +G_END_DECLS +#endif /* _PURPLE_THEME_LOADER_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/theme-manager.c Mon Jun 30 23:12:54 2008 +0000 @@ -0,0 +1,284 @@ +/* + * Themes for LibPurple + * + * Pidgin is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * + */ + +#include <stdarg.h> +#include "theme-manager.h" + +/****************************************************************************** + * Globals + *****************************************************************************/ + +static GHashTable *theme_table = NULL; + +/***************************************************************************** + * GObject Stuff + ****************************************************************************/ + +GType +purple_theme_manager_get_type (void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (PurpleThemeManagerClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + NULL, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (PurpleThemeManager), + 0, /* n_preallocs */ + NULL, /* instance_init */ + NULL, /* Value Table */ + }; + type = g_type_register_static (G_TYPE_OBJECT, + "PurpleThemeManager", + &info, 0); + } + return type; +} + +/****************************************************************************** + * Helpers + *****************************************************************************/ +/* makes a key of <type> + '/' + <name> */ +static gchar * +purple_theme_manager_make_key(const gchar *name, const gchar *type) +{ + g_return_val_if_fail(name, NULL); + g_return_val_if_fail(type, NULL); + return g_strconcat(type, "/", name, NULL); +} + +/* returns TRUE if theme is of type "user_data" */ +static gboolean +purple_theme_manager_is_theme_type(gchar *key, + gpointer value, + gchar *user_data) +{ + return g_str_has_prefix(key, g_strconcat(user_data, "/", NULL)); +} + +static gboolean +purple_theme_manager_is_theme(gchar *key, + gpointer value, + gchar *user_data) +{ + return PURPLE_IS_THEME(value); +} + +static void +purple_theme_manager_function_wrapper(gchar *key, + gpointer value, + PTFunc user_data) +{ + if (PURPLE_IS_THEME(value)) + (* user_data) (value); +} + +static void +purple_theme_manager_build_dir(const gchar *root) +{ + + GDir *rdir; + gchar *name, *type, *purple_dir, *theme_dir; + GDir *dir; + PurpleThemeLoader *loader; + + rdir = g_dir_open(root, 0, NULL); + + g_return_if_fail(rdir); + + /* Parses directory by root/name/purple/type */ + while ((name = g_strdup(g_dir_read_name (rdir)))){ + + purple_dir = g_build_filename(root, name, "purple", NULL); + dir = g_dir_open(purple_dir, 0, NULL); + + if (dir) { + while ((type = g_strdup(g_dir_read_name (dir)))) { + if ((loader = g_hash_table_lookup (theme_table, type))){ + + theme_dir = g_build_filename(purple_dir, type, NULL); + purple_theme_manager_add_theme(purple_theme_loader_build(loader, theme_dir)); + + } + g_free(type); + + } + g_dir_close(dir); + + } + g_free(purple_dir); + g_free(name); + + } + g_dir_close(rdir); + +} + +/***************************************************************************** + * Public API functions * + *****************************************************************************/ + +void +purple_theme_manager_init (PurpleThemeLoader *loader1, ...) +{ + va_list args; + PurpleThemeLoader *loader; + + /*g_return_if_fail(theme_table != NULL);*/ + + theme_table = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + g_object_unref); + + va_start(args, loader1); + for (loader = loader1; loader != NULL; loader = va_arg(args, PurpleThemeLoader *)) + purple_theme_manager_register_type(loader); + va_end(args); + + /* TODO: add themes properly */ + purple_theme_manager_build_dir("/usr/share/themes"); +} + +void +purple_theme_manager_refresh() +{ + g_hash_table_foreach_remove (theme_table, + (GHRFunc) purple_theme_manager_is_theme, + NULL); + + /* TODO: this also needs to be fixed the same as new */ + purple_theme_manager_build_dir("/usr/share/themes"); + +} + +void +purple_theme_manager_uninit () +{ + g_hash_table_destroy(theme_table); +} + + +void +purple_theme_manager_register_type(PurpleThemeLoader *loader) +{ + gchar *type; + + g_return_if_fail(PURPLE_IS_THEME_LOADER(loader)); + + type = g_strdup(purple_theme_loader_get_type_string(loader)); + g_return_if_fail(type); + + /* if something is already there do nothing */ + if (! g_hash_table_lookup (theme_table, type)) + g_hash_table_insert(theme_table, type, loader); +} + +void +purple_theme_manager_unregister_type(PurpleThemeLoader *loader) +{ + gchar *type; + + g_return_if_fail(PURPLE_IS_THEME_LOADER(loader)); + + type = purple_theme_loader_get_type_string(loader); + g_return_if_fail(type); + + if (g_hash_table_lookup (theme_table, type) == loader){ + + g_hash_table_remove (theme_table, type); + + g_hash_table_foreach_remove (theme_table, + (GHRFunc) purple_theme_manager_is_theme_type, + type); + }/* only free if given registered loader */ + + g_free(type); +} + +PurpleTheme * +purple_theme_manager_find_theme(const gchar *name, + const gchar *type) +{ + gchar *key; + PurpleTheme *theme; + + key = purple_theme_manager_make_key(name, type); + + g_return_val_if_fail(key, NULL); + + theme = g_hash_table_lookup(theme_table, key); + + g_free(key); + + return theme; +} + + +void +purple_theme_manager_add_theme(PurpleTheme *theme) +{ + gchar *key; + + g_return_if_fail(PURPLE_IS_THEME(theme)); + + key = purple_theme_manager_make_key(purple_theme_get_name(theme), + purple_theme_get_type_string(theme)); + + g_return_if_fail(key); + + /* if something is already there do nothing */ + if (g_hash_table_lookup(theme_table, key) == NULL) + g_hash_table_insert(theme_table, key, theme); +} + +void +purple_theme_manager_remove_theme(PurpleTheme *theme) +{ + gchar *key; + + g_return_if_fail(PURPLE_IS_THEME(theme)); + + key = purple_theme_manager_make_key(purple_theme_get_name(theme), + purple_theme_get_type_string(theme)); + + g_return_if_fail(key); + + g_hash_table_remove(theme_table, key); + + g_free(key); +} + +void +purple_theme_manager_for_each_theme(PTFunc func) +{ + g_return_if_fail(func); + + g_hash_table_foreach(theme_table, + (GHFunc) purple_theme_manager_function_wrapper, + func); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/theme-manager.h Mon Jun 30 23:12:54 2008 +0000 @@ -0,0 +1,127 @@ +/** + * @file thememanager.h Theme Manager API + */ + +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#ifndef __PURPLE_THEME_MANAGER_H__ +#define __PURPLE_THEME_MANAGER_H__ + +#include <glib-object.h> +#include <glib.h> +#include "theme.h" +#include "theme-loader.h" + +typedef void (*PTFunc) (PurpleTheme *); + +typedef struct _PurpleThemeManager PurpleThemeManager; +typedef struct _PurpleThemeManagerClass PurpleThemeManagerClass; + +#define PURPLE_TYPE_THEME_MANAGER (purple_theme_manager_get_type ()) +#define PURPLE_THEME_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_THEME_MANAGER, PurpleThemeManager)) +#define PURPLE_THEME_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PURPLE_TYPE_THEME_MANAGER, PurpleThemeManagerClass)) +#define PURPLE_IS_THEME_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PURPLE_TYPE_THEME_MANAGER)) +#define PURPLE_IS_THEME_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PURPLE_TYPE_THEME_MANAGER)) +#define PURPLE_GET_THEME_MANAGER_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PURPLE_TYPE_THEME_MANAGER, PurpleThemeManagerClass)) + +struct _PurpleThemeManager { + GObject parent; +}; + +struct _PurpleThemeManagerClass { + GObjectClass parent_class; +}; + +/**************************************************************************/ +/** @name Purple Theme Manager API */ +/**************************************************************************/ +G_BEGIN_DECLS + +/** + * GObject foo. + * @internal. + */ +GType purple_theme_manager_get_type (void); + +/** + * Initalizes the manager then add the loaders to the theme manager + * and builds with the given loaders + * @param the loaders to build with + */ +void purple_theme_manager_init (PurpleThemeLoader *loader1, ...); + +/** + * Rebuilds all the themes in the theme manager + * (removes all current themes but keeps the added loaders) + */ +void purple_theme_manager_refresh(void); + +/** + * Uninitalizes the manager then frees all the themes an loaders it is responsible for + */ +void purple_theme_manager_uninit (void); + +/** + * Finds the PurpleTheme object stored by the theme manager + * + * @param name the name of the PurpleTheme + * @param type the type of the PurpleTheme + * + * @returns The PurpleTheme or NULL if it wasn't found + */ +PurpleTheme *purple_theme_manager_find_theme(const gchar *name, const gchar *type); + +/** + * Adds a PurpleTheme to the theme manager, if the theme already exits it does nothing + * + * @param theme the PurpleTheme to add to the manager + */ +void purple_theme_manager_add_theme(PurpleTheme *theme); + +/** + * Removes a PurpleTheme from the theme manager, and frees the theme + * @param theme the PurpleTheme to remove from the manager + */ +void purple_theme_manager_remove_theme(PurpleTheme *theme); + +/** + * Addes a Loader to the theme manager so it knows how to build themes + * @param loader the PurpleThemeLoader to add + */ +void purple_theme_manager_register_type(PurpleThemeLoader *loader); + +/** + * Removes the loader and all themes of the same type from the loader + * @param loader the PurpleThemeLoader to be removed + */ +void purple_theme_manager_unregister_type(PurpleThemeLoader *loader); + +/** + * Calles the given function on each purple theme + * + * @param func the PTFunc to be applied to each theme + */ +void purple_theme_manager_for_each_theme(PTFunc func); + +G_END_DECLS +#endif /* __PURPLE_THEME_MANAGER_H__ */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/theme.c Mon Jun 30 23:12:54 2008 +0000 @@ -0,0 +1,387 @@ +/* + * Themes for LibPurple + * + * Pidgin is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * + */ + +#include "theme.h" + +#define PURPLE_THEME_GET_PRIVATE(PurpleTheme) \ + ((PurpleThemePrivate *) ((PurpleTheme)->priv)) + +void purple_theme_set_type_string(PurpleTheme *theme, const gchar *type); + +/****************************************************************************** + * Structs + *****************************************************************************/ +typedef struct { + gchar *name; + gchar *description; + gchar *author; + gchar *type; + gchar *dir; + gchar *img; +} PurpleThemePrivate; + +/****************************************************************************** + * Globals + *****************************************************************************/ + +static GObjectClass *parent_class = NULL; + +/****************************************************************************** + * Enums + *****************************************************************************/ + +enum { + PROP_ZERO = 0, + PROP_NAME, + PROP_DESCRIPION, + PROP_AUTHOR, + PROP_TYPE, + PROP_DIR, + PROP_IMAGE +}; + +/****************************************************************************** + * GObject Stuff * + *****************************************************************************/ + +static void +purple_theme_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *psec) +{ + PurpleTheme *theme = PURPLE_THEME(obj); + + switch(param_id) { + case PROP_NAME: + g_value_set_string(value, purple_theme_get_name(theme)); + break; + case PROP_DESCRIPION: + g_value_set_string(value, purple_theme_get_description(theme)); + break; + case PROP_AUTHOR: + g_value_set_string(value, purple_theme_get_author(theme)); + break; + case PROP_TYPE: + g_value_set_string(value, purple_theme_get_type_string(theme)); + break; + case PROP_DIR: + g_value_set_string(value, purple_theme_get_dir(theme)); + break; + case PROP_IMAGE: + g_value_set_string(value, purple_theme_get_image(theme)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, psec); + break; + } +} + +static void +purple_theme_set_property(GObject *obj, guint param_id, const GValue *value, + GParamSpec *psec) +{ + PurpleTheme *theme = PURPLE_THEME(obj); + + switch(param_id) { + case PROP_NAME: + purple_theme_set_name(theme, g_value_get_string(value)); + break; + case PROP_DESCRIPION: + purple_theme_set_description(theme, g_value_get_string(value)); + break; + case PROP_AUTHOR: + purple_theme_set_author(theme, g_value_get_string(value)); + break; + case PROP_TYPE: + purple_theme_set_type_string(theme, g_value_get_string(value)); + break; + case PROP_DIR: + purple_theme_set_dir(theme, g_value_get_string(value)); + break; + case PROP_IMAGE: + purple_theme_set_image(theme, g_value_get_string(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, psec); + break; + } +} + +static void +purple_theme_init(GTypeInstance *instance, + gpointer klass) +{ + PurpleTheme *theme = PURPLE_THEME(instance); + theme->priv = g_new0(PurpleThemePrivate, 1); +} + +static void +purple_theme_finalize(GObject *obj) +{ + PurpleTheme *theme = PURPLE_THEME(obj); + PurpleThemePrivate *priv = PURPLE_THEME_GET_PRIVATE(theme); + + g_free(priv->name); + g_free(priv->description); + g_free(priv->author); + g_free(priv->type); + g_free(priv->dir); + g_free(priv->img); + + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +static void +purple_theme_class_init (PurpleThemeClass *klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + GParamSpec *pspec; + + parent_class = g_type_class_peek_parent(klass); + + obj_class->get_property = purple_theme_get_property; + obj_class->set_property = purple_theme_set_property; + obj_class->finalize = purple_theme_finalize; + + /* NAME */ + pspec = g_param_spec_string("name", "Name", + "The name of the theme", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + g_object_class_install_property(obj_class, PROP_NAME, pspec); + /* DESCRIPION */ + pspec = g_param_spec_string("description", "Description", + "The description of the theme", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + g_object_class_install_property(obj_class, PROP_DESCRIPION, pspec); + /* AUTHOR */ + pspec = g_param_spec_string("author", "Author", + "The author of the theme", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + g_object_class_install_property(obj_class, PROP_AUTHOR, pspec); + /* TYPE STRING (read only) */ + pspec = g_param_spec_string("type", "Type", + "The string represtenting the type of the theme", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property(obj_class, PROP_TYPE, pspec); + /* DIRECTORY */ + pspec = g_param_spec_string("directory", "Directory", + "The directory that contains the theme and all its files", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + g_object_class_install_property(obj_class, PROP_DIR, pspec); + /* PREVIEW IMAGE */ + pspec = g_param_spec_string("image", "Image", + "A preview image of the theme", + NULL, + G_PARAM_READWRITE); + g_object_class_install_property(obj_class, PROP_IMAGE, pspec); +} + + +GType +purple_theme_get_type (void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (PurpleThemeClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)purple_theme_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (PurpleTheme), + 0, /* n_preallocs */ + purple_theme_init, /* instance_init */ + NULL, /* value table */ + }; + type = g_type_register_static (G_TYPE_OBJECT, + "PurpleTheme", + &info, G_TYPE_FLAG_ABSTRACT); + } + return type; +} + + +/***************************************************************************** + * Public API functions * + *****************************************************************************/ + +const gchar * +purple_theme_get_name(PurpleTheme *theme) +{ + PurpleThemePrivate *priv; + + g_return_val_if_fail(PURPLE_IS_THEME(theme), NULL); + + priv = PURPLE_THEME_GET_PRIVATE(theme); + return priv->name; +} + +void +purple_theme_set_name(PurpleTheme *theme, const gchar *name) +{ + PurpleThemePrivate *priv; + + g_return_if_fail(PURPLE_IS_THEME(theme)); + + priv = PURPLE_THEME_GET_PRIVATE(theme); + + g_free(priv->name); + priv->name = g_strdup(name); +} + +const gchar * +purple_theme_get_description(PurpleTheme *theme) +{ + PurpleThemePrivate *priv; + + g_return_val_if_fail(PURPLE_IS_THEME(theme), NULL); + + priv = PURPLE_THEME_GET_PRIVATE(theme); + return priv->description; +} + +void +purple_theme_set_description(PurpleTheme *theme, const gchar *description) +{ + PurpleThemePrivate *priv; + + g_return_if_fail(PURPLE_IS_THEME(theme)); + + priv = PURPLE_THEME_GET_PRIVATE(theme); + + g_free(priv->description); + priv->description = g_strdup(description); +} + +const gchar * +purple_theme_get_author(PurpleTheme *theme) +{ + PurpleThemePrivate *priv; + + g_return_val_if_fail(PURPLE_IS_THEME(theme), NULL); + + priv = PURPLE_THEME_GET_PRIVATE(theme); + return priv->author; +} + +void +purple_theme_set_author(PurpleTheme *theme, const gchar *author) +{ + PurpleThemePrivate *priv; + + g_return_if_fail(PURPLE_IS_THEME(theme)); + + priv = PURPLE_THEME_GET_PRIVATE(theme); + + g_free(priv->author); + priv->author = g_strdup(author); +} + +const gchar * +purple_theme_get_type_string(PurpleTheme *theme) +{ + PurpleThemePrivate *priv; + + g_return_val_if_fail(PURPLE_IS_THEME(theme), NULL); + + priv = PURPLE_THEME_GET_PRIVATE(theme); + return priv->type; +} + +/* < private > */ +void +purple_theme_set_type_string(PurpleTheme *theme, const gchar *type) +{ + PurpleThemePrivate *priv; + + g_return_if_fail(PURPLE_IS_THEME(theme)); + + priv = PURPLE_THEME_GET_PRIVATE(theme); + + g_free(priv->type); + priv->type = g_strdup(type); +} + +const gchar * +purple_theme_get_dir(PurpleTheme *theme) +{ + PurpleThemePrivate *priv; + + g_return_val_if_fail(PURPLE_IS_THEME(theme), NULL); + + priv = PURPLE_THEME_GET_PRIVATE(theme); + return priv->dir; +} + +void +purple_theme_set_dir(PurpleTheme *theme, const gchar *dir) +{ + PurpleThemePrivate *priv; + + g_return_if_fail(PURPLE_IS_THEME(theme)); + + priv = PURPLE_THEME_GET_PRIVATE(theme); + + g_free(priv->dir); + priv->dir = g_strdup(dir); +} + +const gchar * +purple_theme_get_image(PurpleTheme *theme) +{ + PurpleThemePrivate *priv; + + g_return_val_if_fail(PURPLE_IS_THEME(theme), NULL); + + priv = PURPLE_THEME_GET_PRIVATE(theme); + + return priv->img; +} + +gchar * +purple_theme_get_image_full(PurpleTheme *theme) +{ + const gchar *filename = purple_theme_get_image(theme); + + g_return_val_if_fail(filename, NULL); + + return g_build_filename(purple_theme_get_dir(PURPLE_THEME(theme)), filename, NULL); +} + +void +purple_theme_set_image(PurpleTheme *theme, const gchar *img) +{ + PurpleThemePrivate *priv; + + g_return_if_fail(PURPLE_IS_THEME(theme)); + + priv = PURPLE_THEME_GET_PRIVATE(theme); + + g_free(priv->img); + priv->img = g_strdup(img); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/theme.h Mon Jun 30 23:12:54 2008 +0000 @@ -0,0 +1,175 @@ +/** + * @file theme.h Purple Theme Abstact Class API + */ + +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#ifndef _PURPLE_THEME_H_ +#define _PURPLE_THEME_H_ + +#include <glib.h> +#include <glib-object.h> +#include "imgstore.h" + +/** + * A purple theme. + * This is an abstract class for Purple to use with the Purple theme manager. + * + * PurpleTheme is a GObject. + */ +typedef struct _PurpleTheme PurpleTheme; +typedef struct _PurpleThemeClass PurpleThemeClass; + +#define PURPLE_TYPE_THEME (purple_theme_get_type ()) +#define PURPLE_THEME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PURPLE_TYPE_THEME, PurpleTheme)) +#define PURPLE_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PURPLE_TYPE_THEME, PurpleThemeClass)) +#define PURPLE_IS_THEME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PURPLE_TYPE_THEME)) +#define PURPLE_IS_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PURPLE_TYPE_THEME)) +#define PURPLE_THEME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PURPLE_TYPE_THEME, PurpleThemeClass)) + +struct _PurpleTheme +{ + GObject parent; + gpointer priv; +}; + +struct _PurpleThemeClass +{ + GObjectClass parent_class; +}; + +/**************************************************************************/ +/** @name Purple Theme API */ +/**************************************************************************/ +G_BEGIN_DECLS + +/** + * GObject foo. + * @internal. + */ +GType purple_theme_get_type(void); + +/** + * Returns the name of the PurpleTheme object + * + * @param theme the purple theme + * + * @return The string representating the name of the theme + */ +const gchar *purple_theme_get_name(PurpleTheme *theme); + +/** + * Sets the name of the PurpleTheme object + * + * @param theme the purple theme + * @param name the name of the PurpleTheme object + */ +void purple_theme_set_name(PurpleTheme *theme, const gchar *name); + +/** + * Returns the description of the PurpleTheme object + * + * @param theme the purple theme + * + * @return A short description of the theme + */ +const gchar *purple_theme_get_description(PurpleTheme *theme); + +/** + * Sets the description of the PurpleTheme object + * + * @param theme the purple theme + * @param description the description of the PurpleTheme object + */ +void purple_theme_set_description(PurpleTheme *theme, const gchar *description); + +/** + * Returns the author of the PurpleTheme object + * + * @param theme the purple theme + * + * @return The author of the theme + */ +const gchar *purple_theme_get_author(PurpleTheme *theme); + +/** + * Sets the author of the PurpleTheme object + * + * @param theme the purple theme + * @param author the author of the PurpleTheme object + */ +void purple_theme_set_author(PurpleTheme *theme, const gchar *author); + +/** + * Returns the type (string) of the PurpleTheme object + * + * @param theme the purple theme + * + * @return The string represtenting the type + */ +const gchar *purple_theme_get_type_string(PurpleTheme *theme); + +/** + * Returns the directory of the PurpleTheme object + * + * @param theme the purple theme + * + * @return The string represtenting the theme directory + */ +const gchar *purple_theme_get_dir(PurpleTheme *theme); + +/** + * Sets the directory of the PurpleTheme object + * + * @param theme the purple theme + * @param dir the directory of the PurpleTheme object + */ +void purple_theme_set_dir(PurpleTheme *theme, const gchar *dir); + +/** + * Returns the image preview of the PurpleTheme object + * + * @param theme the purple theme + * + * @return The image preview of the PurpleTheme object + */ +const gchar *purple_theme_get_image(PurpleTheme *theme); + +/** + * Returns the image preview and directory of the PurpleTheme object + * + * @param theme the purple theme + * + * @return The image preview of the PurpleTheme object + */ +gchar *purple_theme_get_image_full(PurpleTheme *theme); + +/** + * Sets the directory of the PurpleTheme object + * + * @param theme the purple theme + * @param img the image preview of the PurpleTheme object + */ +void purple_theme_set_image(PurpleTheme *theme, const gchar *img); + +G_END_DECLS +#endif /* _PURPLE_THEME_H_ */
--- a/libpurple/util.c Mon Jun 30 22:58:18 2008 +0000 +++ b/libpurple/util.c Mon Jun 30 23:12:54 2008 +0000 @@ -2757,70 +2757,7 @@ xmlnode * purple_util_read_xml_from_file(const char *filename, const char *description) { - const char *user_dir = purple_user_dir(); - gchar *filename_full; - GError *error = NULL; - gchar *contents = NULL; - gsize length; - xmlnode *node = NULL; - - g_return_val_if_fail(user_dir != NULL, NULL); - - purple_debug_info("util", "Reading file %s from directory %s\n", - filename, user_dir); - - filename_full = g_build_filename(user_dir, filename, NULL); - - if (!g_file_test(filename_full, G_FILE_TEST_EXISTS)) - { - purple_debug_info("util", "File %s does not exist (this is not " - "necessarily an error)\n", filename_full); - g_free(filename_full); - return NULL; - } - - if (!g_file_get_contents(filename_full, &contents, &length, &error)) - { - purple_debug_error("util", "Error reading file %s: %s\n", - filename_full, error->message); - g_error_free(error); - } - - if ((contents != NULL) && (length > 0)) - { - node = xmlnode_from_str(contents, length); - - /* If we were unable to parse the file then save its contents to a backup file */ - if (node == NULL) - { - gchar *filename_temp; - - filename_temp = g_strdup_printf("%s~", filename); - purple_debug_error("util", "Error parsing file %s. Renaming old " - "file to %s\n", filename_full, filename_temp); - purple_util_write_data_to_file(filename_temp, contents, length); - g_free(filename_temp); - } - - g_free(contents); - } - - /* If we could not parse the file then show the user an error message */ - if (node == NULL) - { - gchar *title, *msg; - title = g_strdup_printf(_("Error Reading %s"), filename); - msg = g_strdup_printf(_("An error was encountered reading your " - "%s. They have not been loaded, and the old file " - "has been renamed to %s~."), description, filename_full); - purple_notify_error(NULL, NULL, title, msg); - g_free(title); - g_free(msg); - } - - g_free(filename_full); - - return node; + return xmlnode_from_file(purple_user_dir(), filename, description, "util"); } /*
--- a/libpurple/xmlnode.c Mon Jun 30 22:58:18 2008 +0000 +++ b/libpurple/xmlnode.c Mon Jun 30 23:12:54 2008 +0000 @@ -729,6 +729,78 @@ } xmlnode * +xmlnode_from_file(const char *dir, const char *filename, const char *description, const char *process) +{ + gchar *filename_full; + GError *error = NULL; + gchar *contents = NULL; + gsize length; + xmlnode *node = NULL; + + g_return_val_if_fail(dir != NULL, NULL); + + purple_debug_info(process, "Reading file %s from directory %s\n", + filename, dir); + + filename_full = g_build_filename(dir, filename, NULL); + + if (!g_file_test(filename_full, G_FILE_TEST_EXISTS)) + { + purple_debug_info(process, "File %s does not exist (this is not " + "necessarily an error)\n", filename_full); + g_free(filename_full); + return NULL; + } + + if (!g_file_get_contents(filename_full, &contents, &length, &error)) + { + purple_debug_error(process, "Error reading file %s: %s\n", + filename_full, error->message); + g_error_free(error); + } + + if ((contents != NULL) && (length > 0)) + { + node = xmlnode_from_str(contents, length); + + /* If we were unable to parse the file then save its contents to a backup file */ + if (node == NULL) + { + gchar *filename_temp, *filename_temp_full; + + filename_temp = g_strdup_printf("%s~", filename); + filename_temp_full = g_build_filename(dir, filename_temp, NULL); + + purple_debug_error("util", "Error parsing file %s. Renaming old " + "file to %s\n", filename_full, filename_temp); + purple_util_write_data_to_file_absolute(filename_temp_full, contents, length); + + g_free(filename_temp_full); + g_free(filename_temp); + } + + g_free(contents); + } + + /* If we could not parse the file then show the user an error message */ + if (node == NULL) + { + gchar *title, *msg; + title = g_strdup_printf(_("Error Reading %s"), filename); + msg = g_strdup_printf(_("An error was encountered reading your " + "%s. The file has not been loaded, and the old file " + "has been renamed to %s~."), description, filename_full); + purple_notify_error(NULL, NULL, title, msg); + g_free(title); + g_free(msg); + } + + g_free(filename_full); + + return node; +} + +xmlnode * xmlnode_copy(const xmlnode *src) { xmlnode *ret;
--- a/libpurple/xmlnode.h Mon Jun 30 22:58:18 2008 +0000 +++ b/libpurple/xmlnode.h Mon Jun 30 23:12:54 2008 +0000 @@ -297,6 +297,20 @@ */ void xmlnode_free(xmlnode *node); +/** + * Creates a node from a XML File. Calling this on the + * root node of an XML document will parse the entire document + * into a tree of nodes, and return the xmlnode of the root. + * + * @param str The string of xml. + * @param description The description of the file being parsed + * @process The utility that is calling xmlnode_from_file + * + * @return The new node. + */ +xmlnode *xmlnode_from_file(const char *dir, const char *filename, + const char *description, const char *process); + #ifdef __cplusplus } #endif
--- a/pidgin/gtkprefs.c Mon Jun 30 22:58:18 2008 +0000 +++ b/pidgin/gtkprefs.c Mon Jun 30 23:12:54 2008 +0000 @@ -35,6 +35,8 @@ #include "request.h" #include "savedstatuses.h" #include "sound.h" +#include "sound-theme.h" +#include "theme-manager.h" #include "util.h" #include "network.h" @@ -69,6 +71,10 @@ static int notebook_page = 0; static GtkTreeRowReference *previous_smiley_row = NULL; +static gboolean prefs_themes_unsorted = TRUE; +static GtkListStore *prefs_sound_themes; +static GtkTreeIter prefs_sound_iter; + /* * PROTOTYPES */ @@ -546,6 +552,101 @@ gtk_drag_finish(dc, FALSE, FALSE, t); } +/* sets the current sound theme to customized or NULL */ +static void +pref_set_sound_customized() +{ + if (pidgin_sound_is_customized()) + gtk_list_store_set(prefs_sound_themes, &prefs_sound_iter, 2, "(Custom)", -1); + else gtk_list_store_set(prefs_sound_themes, &prefs_sound_iter, 2, NULL, -1); +} + +/* adds the themes to the theme list from the manager so they can be sisplayed in prefs */ +static void +prefs_themes_sort(PurpleTheme *theme) +{ + GdkPixbuf *pixbuf = NULL; + GtkTreeIter iter; + gchar *image_full; + + if (PURPLE_IS_SOUND_THEME(theme)){ + /* TODO: string leaks? */ + const gchar *pref = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/theme"); + + image_full = purple_theme_get_image_full(theme); + if (image_full != NULL){ + pixbuf = gdk_pixbuf_new_from_file(image_full, NULL); + g_free(image_full); + } + else pixbuf = NULL; + + gtk_list_store_append (prefs_sound_themes, &iter); + gtk_list_store_set (prefs_sound_themes, &iter, 0, pixbuf, 1, purple_theme_get_name(theme), 2, NULL, -1); + + if (pixbuf != NULL) + gdk_pixbuf_unref(pixbuf); + + if (pref && strlen(pref) && !strcmp(purple_theme_get_name(theme), pref)) + prefs_sound_iter = iter; + + } +} + +/* init all the theme variables so that the themes can be sorted later and used by pref pages */ +static void +prefs_themes_init(void) +{ + GdkPixbuf *pixbuf = NULL; + gchar *filename; + + /* sound themes */ + prefs_sound_themes = gtk_list_store_new (3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING); + + filename = g_build_filename(DATADIR, "icons", "hicolor", "16x16", "apps", "pidgin.png", NULL); + pixbuf= gdk_pixbuf_new_from_file(filename, NULL); + g_free(filename); + + gtk_list_store_append (prefs_sound_themes, &prefs_sound_iter); + + gtk_list_store_set (prefs_sound_themes, &prefs_sound_iter, 0, pixbuf, 1, _("(Default)"), 2, NULL, -1); + + gdk_pixbuf_unref (pixbuf); +} + +/* sets the current sound theme */ +static void +prefs_set_sound_theme(GtkComboBox *combo_box, gpointer user_data) +{ + gint i; + gchar *pref; + gchar *theme_name; + + /* remove "(custom)" */ + gtk_list_store_set(prefs_sound_themes, &prefs_sound_iter, 2, NULL, -1); + + g_return_if_fail(gtk_combo_box_get_active_iter(combo_box, &prefs_sound_iter)); + + gtk_tree_model_get(GTK_TREE_MODEL(prefs_sound_themes), &prefs_sound_iter, 1, &theme_name, -1); + + if (strcmp(theme_name, "(Default)") == 0){ + g_free(theme_name); + theme_name = g_strdup(""); + } + + purple_prefs_set_string(PIDGIN_PREFS_ROOT "/sound/theme", theme_name); + + for(i=0; i < PURPLE_NUM_SOUNDS; i++){ + pref = g_strdup_printf(PIDGIN_PREFS_ROOT "/sound/file/%s", + pidgin_sound_get_event_option(i)); + purple_prefs_set_path(pref, ""); + g_free(pref); + } + + gtk_entry_set_text(GTK_ENTRY(sound_entry), _("(default)")); + + g_free(theme_name); +} + /* Does same as normal sort, except "none" is sorted first */ static gint pidgin_sort_smileys (GtkTreeModel *model, GtkTreeIter *a, @@ -1736,6 +1837,8 @@ g_free(pref); gtk_entry_set_text(GTK_ENTRY(sound_entry), _("(default)")); + + pref_set_sound_customized(); } static void @@ -1758,6 +1861,8 @@ */ if (sound == sound_row_sel) gtk_entry_set_text(GTK_ENTRY(sound_entry), filename); + + pref_set_sound_customized(); } static void select_sound(GtkWidget *button, gpointer being_NULL_is_fun) @@ -1826,13 +1931,15 @@ if (sound_entry) gtk_entry_set_text(GTK_ENTRY(sound_entry), (file && *file != '\0') ? file : _("(default)")); g_value_unset (&val); + + pref_set_sound_customized(); } static GtkWidget * sound_page(void) { GtkWidget *ret; - GtkWidget *vbox, *sw, *button; + GtkWidget *vbox, *sw, *button, *combo_box; GtkSizeGroup *sg; GtkTreeIter iter; GtkWidget *event_view; @@ -1845,6 +1952,7 @@ int j; const char *file; char *pref; + GtkCellRenderer *cell_rend; #ifndef _WIN32 GtkWidget *dd; GtkWidget *entry; @@ -1922,7 +2030,6 @@ purple_prefs_connect_callback(prefs, PIDGIN_PREFS_ROOT "/sound/method", sound_changed2_cb, vbox); #endif - vbox = pidgin_make_frame(ret, _("Sound Events")); /* The following is an ugly hack to make the frame expand so the @@ -1934,6 +2041,28 @@ gtk_box_set_child_packing(GTK_BOX(vbox->parent->parent->parent), vbox->parent->parent, TRUE, TRUE, 0, GTK_PACK_START); + /* SOUND THEMES */ + combo_box = gtk_combo_box_new_with_model(GTK_TREE_MODEL (prefs_sound_themes)); + gtk_box_pack_start (GTK_BOX (vbox), combo_box, FALSE, FALSE, 0); + + cell_rend = gtk_cell_renderer_pixbuf_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), cell_rend, FALSE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), cell_rend, "pixbuf", 0, NULL); + + cell_rend = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), cell_rend, FALSE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), cell_rend, "text", 1, NULL); + + cell_rend = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), cell_rend, FALSE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), cell_rend, "text", 2, NULL); + + gtk_combo_box_set_active_iter(GTK_COMBO_BOX(combo_box), &prefs_sound_iter); + g_signal_connect(G_OBJECT(combo_box), "changed", (GCallback)prefs_set_sound_theme, NULL); + + pref_set_sound_customized(); + + /* SOUND SELECTION */ sw = gtk_scrolled_window_new(NULL,NULL); gtk_widget_set_size_request(sw, -1, 100); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); @@ -2166,6 +2295,12 @@ gtk_window_present(GTK_WINDOW(prefs)); return; } + + /* add everthing in the thmeme manager before the window is loaded */ + if (prefs_themes_unsorted){ + purple_theme_manager_for_each_theme(prefs_themes_sort); + prefs_themes_unsorted = FALSE; + } /* copy the preferences to tmp values... * I liked "take affect immediately" Oh well :-( */ @@ -2261,6 +2396,9 @@ purple_prefs_add_path(PIDGIN_PREFS_ROOT "/filelocations/last_open_folder", ""); purple_prefs_add_path(PIDGIN_PREFS_ROOT "/filelocations/last_icon_folder", ""); + /* Themes */ + prefs_themes_init(); + /* Smiley Themes */ purple_prefs_add_none(PIDGIN_PREFS_ROOT "/smileys"); purple_prefs_add_string(PIDGIN_PREFS_ROOT "/smileys/theme", "Default");
--- a/pidgin/gtksound.c Mon Jun 30 22:58:18 2008 +0000 +++ b/pidgin/gtksound.c Mon Jun 30 23:12:54 2008 +0000 @@ -40,6 +40,8 @@ #include "notify.h" #include "prefs.h" #include "sound.h" +#include "sound-theme.h" +#include "theme-manager.h" #include "util.h" #include "gtkconv.h" @@ -294,6 +296,7 @@ purple_prefs_add_path(PIDGIN_PREFS_ROOT "/sound/file/nick_said", ""); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/sound/enabled/pounce_default", TRUE); purple_prefs_add_path(PIDGIN_PREFS_ROOT "/sound/file/pounce_default", ""); + purple_prefs_add_string(PIDGIN_PREFS_ROOT "/sound/theme", ""); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/sound/conv_focus", TRUE); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/sound/mute", FALSE); purple_prefs_add_path(PIDGIN_PREFS_ROOT "/sound/command", ""); @@ -557,6 +560,8 @@ { char *enable_pref; char *file_pref; + char *theme_name; + PurpleSoundTheme *theme; if ((event == PURPLE_SOUND_BUDDY_ARRIVE) && mute_login_sounds) return; @@ -570,23 +575,67 @@ sounds[event].pref); file_pref = g_strdup_printf(PIDGIN_PREFS_ROOT "/sound/file/%s", sounds[event].pref); + + /* check NULL for sounds that don't have an option, ie buddy pounce */ if (purple_prefs_get_bool(enable_pref)) { char *filename = g_strdup(purple_prefs_get_path(file_pref)); - if(!filename || !strlen(filename)) { + theme_name = g_strdup(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/theme")); + + if (theme_name && strlen(theme_name) && (!filename || !strlen(filename))){ /* Use theme */ g_free(filename); + + theme = PURPLE_SOUND_THEME(purple_theme_manager_find_theme(theme_name, "sound")); + filename = purple_sound_theme_get_file_full(theme, sounds[event].pref); + + if(!g_file_test(filename, G_FILE_TEST_IS_REGULAR)){ /* Use Default sound in this case */ + purple_debug_error("sound", "The file: (%s) %s\n from theme: %s, was not found or wasn't readable\n", + sounds[event].pref, filename, theme_name); + g_free(filename); + } + } + + if (!filename || !strlen(filename)) { /* Use Default sounds */ + g_free(filename); + /* XXX Consider creating a constant for "sounds/purple" to be shared with Finch */ filename = g_build_filename(DATADIR, "sounds", "purple", sounds[event].def, NULL); } purple_sound_play_file(filename, NULL); + + g_free(theme_name); g_free(filename); } + g_free(enable_pref); g_free(file_pref); } +gboolean +pidgin_sound_is_customized(void) +{ + gint i; + gchar *path, *file; + + for (i=0; i < PURPLE_NUM_SOUNDS; i++){ + path = g_strdup_printf(PIDGIN_PREFS_ROOT "/sound/file/%s", sounds[i].pref); + file = g_strdup(purple_prefs_get_path(path)); + g_free(path); + + if (file && strlen(file)){ + g_free(file); + return TRUE; + } + + g_free(file); + } + + return FALSE; + +} + static PurpleSoundUiOps sound_ui_ops = { pidgin_sound_init,
--- a/pidgin/gtksound.h Mon Jun 30 22:58:18 2008 +0000 +++ b/pidgin/gtksound.h Mon Jun 30 23:12:54 2008 +0000 @@ -63,6 +63,13 @@ */ void *pidgin_sound_get_handle(void); +/** + * Returns true Pidgin is using customized sounds + * + * @return TRUE if non default sounds are used + */ +gboolean pidgin_sound_is_customized(void); + /*@}*/ #endif /* _PIDGINSOUND_H_ */