grim/guifications3

moved gflib-gtk to the new cmake module
cmake
2010-12-15, Gary Kramlich
b6418db658c1
moved gflib-gtk to the new cmake module
/*
* Guifications - The end-all, be-all notification framework
* Copyright (C) 2003-2009 Gary Kramlich <grim@reaperworld.com>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#if HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <gflib/gf_intl.h>
#include <gflib/gf_preferences_proxy.h>
#include <gflib/gf_preferences_proxy_entry.h>
#include <string.h>
#define GF_PREFERENCES_PROXY_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE((obj), GF_TYPE_PREFERENCES_PROXY, GfPreferencesProxyPrivate))
/******************************************************************************
* Structs
*****************************************************************************/
typedef struct {
GHashTable *engines;
} GfPreferencesProxyPrivate;
/******************************************************************************
* Globals
*****************************************************************************/
static GfPreferenceEngineClass *parent_class = NULL;
/******************************************************************************
* Helpers
*****************************************************************************/
static GfPreferenceEngine *
gf_preferences_proxy_find_engine(GfPreferencesProxy *proxy,
const gchar *path, gchar **mntpnt)
{
GfPreferencesProxyPrivate *priv = GF_PREFERENCES_PROXY_GET_PRIVATE(proxy);
GfPreferenceEngine *engine = NULL;
GfPreferencesProxyEntry *entry = NULL;
gchar *mnt = NULL, *tmp = NULL;
tmp = mnt = g_strdup(path);
while(tmp) {
entry = GF_PREFERENCES_PROXY_ENTRY(
g_hash_table_lookup(priv->engines, tmp));
if(entry)
break;
*tmp = '\0';
tmp = g_strrstr(mnt, "/");
}
if(mntpnt)
*mntpnt = (entry) ? g_strdup(mnt) : NULL;
engine = (entry) ? gf_preferences_proxy_entry_get_engine(entry) : NULL;
g_free(mnt);
return engine;
}
typedef struct {
GList *nests;
gchar *root;
} NestedData;
static void
gf_preferences_proxy_get_nested_mounts_cb(gpointer k, gpointer v, gpointer d) {
NestedData *nd = (NestedData *)d;
GfPreferencesProxyEntry *entry = GF_PREFERENCES_PROXY_ENTRY(v);
gchar *key = (gchar *)k;
if(g_str_has_prefix(key, nd->root)) {
nd->nests = g_list_prepend(nd->nests, entry);
}
}
static gchar **
gf_preferences_proxy_get_nested_mounts(GfPreferencesProxy *proxy,
const gchar *path)
{
GfPreferencesProxyPrivate *priv = GF_PREFERENCES_PROXY_GET_PRIVATE(proxy);
GList *mounts = NULL;
gchar **ret = NULL;
g_hash_table_foreach(priv->engines,
gf_preferences_proxy_get_nested_mounts_cb,
mounts);
if(!mounts)
return NULL;
mounts = g_list_sort(mounts, (GCompareFunc)g_utf8_collate);
if(mounts) {
GList *l;
gint i;
ret = g_new0(gchar *, g_list_length(mounts) + 1);
for(l = mounts, i = 0; l; l = l->next, i++)
ret[i] = l->data;
}
g_list_free(mounts);
return ret;
}
static gboolean
gf_preferences_proxy_has_nested_mounts(GfPreferencesProxy *proxy,
const gchar *path)
{
gchar **nests = gf_preferences_proxy_get_nested_mounts(proxy, path);
gboolean ret = FALSE;
if(nests) {
ret = TRUE;
g_strfreev(nests);
}
return ret;
}
static gchar *
gf_preferences_proxy_mangle_name(const gchar *path, const gchar *mntpnt) {
if(!mntpnt)
return g_strdup(path);
return g_strdup(path + strlen(mntpnt));
}
/* callbacks for normal preference engine stuff */
static void
gf_preferences_proxy_reload_cb(gpointer k, gpointer v, gpointer d) {
GfPreferenceEngine *engine = GF_PREFERENCE_ENGINE(v);
gf_preference_engine_reload(engine);
}
static void
gf_preferences_proxy_save_cb(gpointer k, gpointer v, gpointer d) {
GfPreferenceEngine *engine = GF_PREFERENCE_ENGINE(v);
gf_preference_engine_save(engine);
}
/******************************************************************************
* PreferenceEngine API
*****************************************************************************/
static void
gf_preferences_proxy_reload(GfPreferenceEngine *engine) {
GfPreferencesProxyPrivate *priv = GF_PREFERENCES_PROXY_GET_PRIVATE(engine);
g_hash_table_foreach(priv->engines,
gf_preferences_proxy_reload_cb,
engine);
}
static void
gf_preferences_proxy_save(const GfPreferenceEngine *engine) {
GfPreferencesProxyPrivate *priv = GF_PREFERENCES_PROXY_GET_PRIVATE(engine);
g_hash_table_foreach(priv->engines,
gf_preferences_proxy_save_cb,
(gpointer)engine);
}
static void
gf_preferences_proxy_add_section(GfPreferenceEngine *engine,
const gchar *path)
{
GfPreferenceEngine *rengine;
gchar *mnt = NULL;
rengine = gf_preferences_proxy_find_engine(GF_PREFERENCES_PROXY(engine),
path, &mnt);
if(GF_IS_PREFERENCE_ENGINE(rengine)) {
gchar *rp = gf_preferences_proxy_mangle_name(path, mnt);
g_free(mnt);
gf_preference_engine_add_section(rengine, rp);
g_free(rp);
}
}
static void
gf_preferences_proxy_add_string(GfPreferenceEngine *engine, const gchar *name,
const gchar *def)
{
GfPreferenceEngine *rengine;
gchar *mnt = NULL;
rengine = gf_preferences_proxy_find_engine(GF_PREFERENCES_PROXY(engine),
name, &mnt);
if(GF_IS_PREFERENCE_ENGINE(rengine)) {
gchar *rp = gf_preferences_proxy_mangle_name(name, mnt);
g_free(mnt);
gf_preference_engine_add_string(rengine, rp, def);
g_free(rp);
}
}
static void
gf_preferences_proxy_set_string(GfPreferenceEngine *engine, const gchar *name,
const gchar *value)
{
GfPreferenceEngine *rengine;
gchar *mnt = NULL;
rengine = gf_preferences_proxy_find_engine(GF_PREFERENCES_PROXY(engine),
name, &mnt);
if(GF_IS_PREFERENCE_ENGINE(rengine)) {
gchar *rp = gf_preferences_proxy_mangle_name(name, mnt);
g_free(mnt);
gf_preference_engine_set_string(rengine, rp, value);
g_free(rp);
}
}
static gchar *
gf_preferences_proxy_get_string(const GfPreferenceEngine *engine,
const gchar *name)
{
GfPreferenceEngine *rengine;
gchar *mnt = NULL, *ret = NULL;
rengine = gf_preferences_proxy_find_engine(GF_PREFERENCES_PROXY(engine),
name, &mnt);
if(GF_IS_PREFERENCE_ENGINE(rengine)) {
gchar *rp = gf_preferences_proxy_mangle_name(name, mnt);
g_free(mnt);
ret = gf_preference_engine_get_string(rengine, rp);
g_free(rp);
}
return ret;
}
static void
gf_preferences_proxy_add_int(GfPreferenceEngine *engine, const gchar *name,
gint def)
{
GfPreferenceEngine *rengine;
gchar *mnt = NULL;
rengine = gf_preferences_proxy_find_engine(GF_PREFERENCES_PROXY(engine),
name, &mnt);
if(GF_IS_PREFERENCE_ENGINE(rengine)) {
gchar *rp = gf_preferences_proxy_mangle_name(name, mnt);
g_free(mnt);
gf_preference_engine_add_int(rengine, rp, def);
g_free(rp);
}
}
static void
gf_preferences_proxy_set_int(GfPreferenceEngine *engine, const gchar *name,
gint value)
{
GfPreferenceEngine *rengine;
gchar *mnt = NULL;
rengine = gf_preferences_proxy_find_engine(GF_PREFERENCES_PROXY(engine),
name, &mnt);
if(GF_IS_PREFERENCE_ENGINE(rengine)) {
gchar *rp = gf_preferences_proxy_mangle_name(name, mnt);
g_free(mnt);
gf_preference_engine_set_int(rengine, rp, value);
g_free(rp);
}
}
static gint
gf_preferences_proxy_get_int(const GfPreferenceEngine *engine,
const gchar *name)
{
GfPreferenceEngine *rengine;
gchar *mnt = NULL;
gint ret = 0;
rengine = gf_preferences_proxy_find_engine(GF_PREFERENCES_PROXY(engine),
name, &mnt);
if(GF_IS_PREFERENCE_ENGINE(rengine)) {
gchar *rp = gf_preferences_proxy_mangle_name(name, mnt);
g_free(mnt);
ret = gf_preference_engine_get_int(rengine, rp);
g_free(rp);
}
return ret;
}
static void
gf_preferences_proxy_add_bool(GfPreferenceEngine *engine, const gchar *name,
gboolean def)
{
GfPreferenceEngine *rengine;
gchar *mnt = NULL;
rengine = gf_preferences_proxy_find_engine(GF_PREFERENCES_PROXY(engine),
name, &mnt);
if(GF_IS_PREFERENCE_ENGINE(rengine)) {
gchar *rp = gf_preferences_proxy_mangle_name(name, mnt);
g_free(mnt);
gf_preference_engine_add_bool(rengine, rp, def);
g_free(rp);
}
}
static void
gf_preferences_proxy_set_bool(GfPreferenceEngine *engine, const gchar *name,
gboolean value)
{
GfPreferenceEngine *rengine;
gchar *mnt = NULL;
rengine = gf_preferences_proxy_find_engine(GF_PREFERENCES_PROXY(engine),
name, &mnt);
if(GF_IS_PREFERENCE_ENGINE(rengine)) {
gchar *rp = gf_preferences_proxy_mangle_name(name, mnt);
g_free(mnt);
gf_preference_engine_set_bool(rengine, rp, value);
g_free(rp);
}
}
static gboolean
gf_preferences_proxy_get_bool(const GfPreferenceEngine *engine,
const gchar *name)
{
GfPreferenceEngine *rengine;
gchar *mnt = NULL;
gboolean ret = FALSE;
rengine = gf_preferences_proxy_find_engine(GF_PREFERENCES_PROXY(engine),
name, &mnt);
if(GF_IS_PREFERENCE_ENGINE(rengine)) {
gchar *rp = gf_preferences_proxy_mangle_name(name, mnt);
g_free(mnt);
ret = gf_preference_engine_get_bool(rengine, rp);
g_free(rp);
}
return ret;
}
static gboolean
gf_preferences_proxy_exists(const GfPreferenceEngine *engine,
const gchar *name)
{
GfPreferenceEngine *rengine;
gchar *mnt = NULL;
gboolean ret = FALSE;
rengine = gf_preferences_proxy_find_engine(GF_PREFERENCES_PROXY(engine),
name, &mnt);
if(GF_IS_PREFERENCE_ENGINE(rengine)) {
gchar *rp = gf_preferences_proxy_mangle_name(name, mnt);
g_free(mnt);
ret = gf_preference_engine_exists(rengine, rp);
g_free(rp);
}
return ret;
}
static GfPreferenceType
gf_preferences_proxy_get_pref_type(const GfPreferenceEngine *engine,
const gchar *path)
{
GfPreferenceEngine *rengine;
gchar *mnt = NULL;
gboolean ret = FALSE;
rengine = gf_preferences_proxy_find_engine(GF_PREFERENCES_PROXY(engine),
path, &mnt);
if(GF_IS_PREFERENCE_ENGINE(rengine)) {
gchar *rp = gf_preferences_proxy_mangle_name(path, mnt);
g_free(mnt);
ret = gf_preference_engine_get_type(rengine, rp);
g_free(rp);
}
return ret;
}
static gboolean
gf_preferences_proxy_rename(GfPreferenceEngine *engine, const gchar *oldname,
const gchar *newname)
{
return FALSE;
}
static gint
gf_preferences_proxy_remove(GfPreferenceEngine *engine, const gchar *path) {
return 0;
}
static GfPreference **
gf_preferences_proxy_query(const GfPreferenceEngine *engine, const gchar *path,
guint *num_prefs)
{
if(num_prefs)
*num_prefs = 0;
return NULL;
}
/******************************************************************************
* Real PreferencesProxy API
*****************************************************************************/
static gboolean
gf_preferences_proxy_real_add_engine(GfPreferencesProxy *proxy,
GfPreferenceEngine *engine,
const gchar *mntpnt)
{
GfPreferencesProxyPrivate *priv = GF_PREFERENCES_PROXY_GET_PRIVATE(proxy);
GfPreferencesProxyEntry *entry = NULL;
g_return_val_if_fail(GF_IS_PREFERENCES_PROXY(proxy), FALSE);
g_return_val_if_fail(GF_IS_PREFERENCE_ENGINE(engine), FALSE);
g_return_val_if_fail(mntpnt, FALSE);
#warning We should probably give a reason for this failure--I am open to suggestions...
if(g_hash_table_lookup(priv->engines, mntpnt))
return FALSE;
entry = gf_preferences_proxy_entry_new(mntpnt, engine);
g_hash_table_insert(priv->engines, g_strdup(mntpnt), entry);
return TRUE;
}
static gboolean
gf_preferences_proxy_real_remove_engine(GfPreferencesProxy *proxy,
const gchar *mntpnt)
{
GfPreferencesProxyPrivate *priv = GF_PREFERENCES_PROXY_GET_PRIVATE(proxy);
g_return_val_if_fail(GF_IS_PREFERENCES_PROXY(proxy), FALSE);
g_return_val_if_fail(mntpnt, FALSE);
# warning we need to show the failure reason here too...
if(gf_preferences_proxy_has_nested_mounts(proxy, mntpnt)) {
return FALSE;
}
return g_hash_table_remove(priv->engines, mntpnt);
}
/******************************************************************************
* Object stuff
*****************************************************************************/
static void
gf_preferences_proxy_finalize(GObject *obj) {
GfPreferencesProxyPrivate *priv = GF_PREFERENCES_PROXY_GET_PRIVATE(obj);
g_hash_table_destroy(priv->engines);
G_OBJECT_CLASS(parent_class)->finalize(obj);
}
static void
gf_preferences_proxy_class_init(GfPreferencesProxyClass *klass) {
GfPreferenceEngineClass *engine_class = GF_PREFERENCE_ENGINE_CLASS(klass);
GObjectClass *obj_class = G_OBJECT_CLASS(klass);
parent_class = g_type_class_peek_parent(klass);
g_type_class_add_private(klass, sizeof(GfPreferencesProxyPrivate));
obj_class->finalize = gf_preferences_proxy_finalize;
engine_class->reload = gf_preferences_proxy_reload;
engine_class->save = gf_preferences_proxy_save;
engine_class->add_section = gf_preferences_proxy_add_section;
engine_class->add_string = gf_preferences_proxy_add_string;
engine_class->set_string = gf_preferences_proxy_set_string;
engine_class->get_string = gf_preferences_proxy_get_string;
engine_class->add_int = gf_preferences_proxy_add_int;
engine_class->set_int = gf_preferences_proxy_set_int;
engine_class->get_int = gf_preferences_proxy_get_int;
engine_class->add_bool = gf_preferences_proxy_add_bool;
engine_class->set_bool = gf_preferences_proxy_set_bool;
engine_class->get_bool = gf_preferences_proxy_get_bool;
engine_class->exists = gf_preferences_proxy_exists;
engine_class->rename = gf_preferences_proxy_rename;
engine_class->remove = gf_preferences_proxy_remove;
engine_class->query = gf_preferences_proxy_query;
engine_class->get_type = gf_preferences_proxy_get_pref_type;
klass->add_engine = gf_preferences_proxy_real_add_engine;
klass->remove_engine = gf_preferences_proxy_real_remove_engine;
}
static void
gf_preferences_proxy_init(GTypeInstance *instance, gpointer g_class) {
GfPreferencesProxyPrivate *priv =
GF_PREFERENCES_PROXY_GET_PRIVATE(instance);
priv->engines =
g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_object_unref);
}
/******************************************************************************
* GfPreferencesProxy API
*****************************************************************************/
GType
gf_preferences_proxy_get_type(void) {
static GType type = 0;
if(type == 0) {
static const GTypeInfo info = {
sizeof(GfPreferencesProxyClass),
NULL,
NULL,
(GClassInitFunc)gf_preferences_proxy_class_init,
NULL,
NULL,
sizeof(GfPreferencesProxy),
0,
gf_preferences_proxy_init,
};
type = g_type_register_static(GF_TYPE_PREFERENCE_ENGINE,
"GfPreferencesProxy",
&info, 0);
}
return type;
}
/**
* gf_preferences_proxy_new:
*
* Creates a new #GfPreferencesProxy instance.
*
* Return Value: The new #GfPreferencesProxy instance.
*/
GfPreferenceEngine *
gf_preferences_proxy_new(void) {
return g_object_new(GF_TYPE_PREFERENCES_PROXY, NULL);
}
/**
* gf_preferences_proxy_add_engine:
* @proxy: The #GfPreferencesProxy instance.
* @engine: The #GfPreferenceEngine instance.
* @mount_point: The path to make @engine accessible on.
*
* "Mounts" @engine in @proxy at @mount_path.
*
* Return Value: TRUE on success, FALSE otherwise.
*/
gboolean
gf_preferences_proxy_add_engine(GfPreferencesProxy *proxy,
GfPreferenceEngine *engine,
const gchar *mount_point)
{
GfPreferencesProxyClass *klass = NULL;
g_return_val_if_fail(GF_IS_PREFERENCES_PROXY(proxy), FALSE);
g_return_val_if_fail(GF_IS_PREFERENCE_ENGINE(engine), FALSE);
g_return_val_if_fail(mount_point, FALSE);
klass = GF_PREFERENCES_PROXY_GET_CLASS(proxy);
if(klass && klass->add_engine)
return klass->add_engine(proxy, engine, mount_point);
return FALSE;
}
/**
* gf_preferences_proxy_remove_engine:
* @proxy: The #GfPreferencesProxy instance.
* @mount_point: The path of the engine to remove.
*
* Removes a #GfPreferenceEngine from @proxy that's currently accessible on
* @mount_point.
*
* Return Value: TRUE on success, FALSE otherwise.
*/
gboolean
gf_preferences_proxy_remove_engine(GfPreferencesProxy *proxy,
const gchar *mount_point)
{
GfPreferencesProxyClass *klass = NULL;
g_return_val_if_fail(GF_IS_PREFERENCES_PROXY(proxy), FALSE);
g_return_val_if_fail(mount_point, FALSE);
klass = GF_PREFERENCES_PROXY_GET_CLASS(proxy);
if(klass && klass->remove_engine)
return klass->remove_engine(proxy, mount_point);
return FALSE;
}