grim/guifications3

added the install prefix to gflib-genheader
cmake
2010-12-13, Gary Kramlich
999ee3e165df
added the install prefix to gflib-genheader
/*
* 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/>.
*/
#include <gflib/gf_preferences.h>
#include <gflib/gf_filesystem.h>
#include <gflib/gf_log.h>
#include <gflib/gf_preference_engine_null.h>
#include <gflib/gf_preference_engine_xml.h>
#include <string.h>
#define PREFS_URI_REGEX \
"^([A-Za-z][A-Z-a-z0-9]*):((([A-Za-z].*)=(.*))(,([A-Za-z].*)=(.*)))*$"
/******************************************************************************
* Globals
*****************************************************************************/
static GfPreferenceEngine *root = NULL;
/******************************************************************************
* Helpers
*****************************************************************************/
static GfPreferenceEngine *
gf_preferences_create_default_engine(const gchar *appname) {
GfPreferenceEngine *engine = NULL;
if(appname) {
gchar *gf_dir = NULL, *base = NULL, *filename = NULL;
gf_dir = gf_fs_user_settings_dir();
base = g_path_get_basename(appname);
filename = g_build_filename(gf_dir, base, "prefs.xml", NULL);
g_free(gf_dir);
g_free(base);
engine = gf_preference_engine_xml_new(filename);
} else {
engine = gf_preference_engine_null_new();
}
return engine;
}
/* This big ass basturd takes a uri in the form of:
*
* GTypeName:GParamName=Value,GParamName,Value
*
* and creates an object out of it. This might be worth splitting out at some
* point. But until then, it's fine where it is. But if it were to be split
* out, it should go into gf_object.[ch] and have it's log messages cleaned up.
*/
static GfPreferenceEngine *
gf_preferences_create_engine_from_uri(const gchar *uri) {
GfPreferenceEngine *engine = NULL;
GError *error = NULL;
GList *gc = NULL, *l = NULL;
GMatchInfo *match_info = NULL;
GParameter *params = NULL;
GRegex *regex = NULL;
GType type = G_TYPE_INVALID;
gchar *type_name = NULL;
guint n_params = 0;
gint matches = 0;
regex = g_regex_new(PREFS_URI_REGEX, 0, 0, &error);
if(!g_regex_match(regex, uri, 0, &match_info)) {
g_regex_unref(regex);
gf_log_warning("GfPreferences",
"Could not parse preference uri: '%s'\n"
"Falling back to the default preference engine.\n",
uri);
return NULL;
}
/* we have the match_info now, so kill the regex */
g_regex_unref(regex);
/* the type name is in position 1, so grab it and see if the type even
* exists.
*/
type_name = g_match_info_fetch(match_info, 1);
type = g_type_from_name(type_name);
if(type == G_TYPE_INVALID) {
g_match_info_free(match_info);
gf_log_warning("GfPreferences",
"Could not find the type information for preference "
"engine '%s'\n"
"Falling back to the default preference engine.\n",
type_name);
g_free(type_name);
return NULL;
}
/* now dig through the given params and build the GParameterArray */
if((matches = g_match_info_get_match_count(match_info)) > 1) {
GObjectClass *klass = g_type_class_ref(type);
guint cur = 0;
/* we ignore the first two matches (the engine and the full param
* string. Then our params are grouped in threes: name=value, name,
* and value. So our number of params is (matches - 2) / 3
*/
n_params = (guint)((matches - 2) / 3);
/* now allocate params */
params = g_new0(GParameter, n_params + 1);
for(cur = 0; cur < n_params; cur++) {
GParamSpec *pspec = NULL;
gchar *name = NULL, *value = NULL;
gint index = 0;
/* we multiple by 3 to get to the group, and add two to actually
* get to the data.
*/
index = (cur * 3) + 2;
/* grab the name and see if the parameter exists and that we can
* handle it's type. If we can't do either, log a warning and
* continue on.
*/
name = g_match_info_fetch(match_info, index + 1);
pspec = g_object_class_find_property(klass, name);
if(!pspec) {
gf_log_warning("GfPreferences",
"Preference engine %s does not have a property "
"named '%s'.\n",
type_name, name);
g_free(name);
continue;
}
switch(pspec->value_type) {
case G_TYPE_STRING:
break;
default:
gf_log_warning("GfPreference",
"Don't know how to handle property '%s' "
"with type '%s' for engine '%s'.\n",
name, g_type_name(pspec->value_type),
type_name);
g_free(name);
continue;
}
/* we know the property exists now, so set it in the GParameter and
* add the name to gc
*/
params[cur].name = name;
gc = g_list_prepend(gc, name);
/* set the GValue in the GParameter */
value = g_match_info_fetch(match_info, index + 2);
g_value_init(&params[cur].value, G_TYPE_STRING);
g_value_take_string(&params[cur].value, value);
/* add the value to gc, this is ugly, but the best idea i have at
* the moment.
*/
gc = g_list_prepend(gc, &params[cur].value);
}
g_type_class_unref(klass);
}
engine = g_object_newv(type, n_params, params);
/* cleanup time! */
for(l = gc; l; l = l->next->next) {
/* we prepended everything onto the list, so the first item is a
* GValue, followed by a gchar *.
*/
g_value_unset(l->data);
g_free(l->next->data);
}
g_list_free(gc);
g_free(params);
g_match_info_free(match_info);
/* we free the type_name down here so we can use it in the error messages
* during all the fun above.
*/
g_free(type_name);
return engine;
}
/******************************************************************************
* Private API
*****************************************************************************/
void
gf_preferences_init(const gchar *appname, const gchar *uri) {
GfPreferenceEngine *engine = NULL;
const gchar *real_uri = NULL;
/* if the uri was given on the command line, use it. Otherwise, try the
* environment variable.
*/
real_uri = (uri) ? uri : g_getenv("GF_PREFS_URI");
if(real_uri)
engine = gf_preferences_create_engine_from_uri(real_uri);
if(!engine)
engine = gf_preferences_create_default_engine(appname);
root = engine;
}
void
gf_preferences_uninit(void) {
g_object_unref(G_OBJECT(root));
}
/******************************************************************************
* Public API
*****************************************************************************/
/**
* gf_preferences_reload:
*
* Reloads all preferences.
*/
void
gf_preferences_reload(void) {
gf_preference_engine_reload(root);
}
/**
* gf_preferences_save:
*
* Saves all preferences.
*/
void
gf_preferences_save(void) {
gf_preference_engine_save(root);
}
/**
* gf_preferences_add_section:
* @path : The path of the section to add.
*
* Adds a section to the preferences.
*/
void
gf_preferences_add_section(const gchar *path) {
gf_preference_engine_add_section(root, path);
}
/**
* gf_preferences_add_string:
* @name : The name of the preferences.
* @def : The default value of the preference.
*
* Adds a string preference to the preferences with a value of @def if it
* does not already exist.
*/
void
gf_preferences_add_string(const gchar *name, const gchar *def) {
gf_preference_engine_add_string(root, name, def);
}
/**
* gf_preferences_set_string:
* @name : The name of the preference.
* @value : The new value for the preference.
*
* Sets the string value for the preference named @name.
*/
void
gf_preferences_set_string(const gchar *name, const gchar *value) {
gf_preference_engine_set_string(root, name, value);
}
/**
* gf_preferences_get_string:
* @name : The name of the string preference.
*
* Gets the value of the string preference named @name.
*
* Return Value: The value of the string preference named @name.
*/
const gchar *
gf_preferences_get_string(const gchar *name) {
return gf_preference_engine_get_string(root, name);
}
/**
* gf_preferences_add_int:
* @name : The name of the preference.
* @def : The default value of the preference.
*
* Adds an integer preference named @name with a value of @def if it does not
* already exist.
*/
void
gf_preferences_add_int(const gchar *name, gint def) {
gf_preference_engine_add_int(root, name, def);
}
/**
* gf_preferences_set_int:
* @name : The name of the preference.
* @value : The new value of the preference.
*
* Sets the value of the integer preference named @named to @value.
*/
void
gf_preferences_set_int(const gchar *name, gint value) {
gf_preference_engine_set_int(root, name, value);
}
/**
* gf_preferences_get_int:
* @name : The name of the preference.
*
* Gets the value of the integer preference named @name.
*
* Return Value: The value of the integer preference named @name.
*/
gint
gf_preferences_get_int(const gchar *name) {
return gf_preference_engine_get_int(root, name);
}
/**
* gf_preferences_add_bool:
* @name : The name of the preference.
* @def : The default value of the preference.
*
* Adds a new boolean preference named @name. If it does not already exist
* sets it's value to @def.
*/
void
gf_preferences_add_bool(const gchar *name, gboolean def) {
gf_preference_engine_add_bool(root, name, def);
}
/**
* gf_preferences_set_bool:
* @name : The name of the preference.
* @value : The new value.
*
* Sets the value of the boolean preference named @name to @value.
*/
void
gf_preferences_set_bool(const gchar *name, gboolean value) {
gf_preference_engine_set_bool(root, name, value);
}
/**
* gf_preferences_get_bool:
* @name : The name of the preference.
*
* Gets the value of the boolean preference named @name.
*
* Return Value: The value of the boolean preference named @name.
*/
gboolean
gf_preferences_get_bool(const gchar *name) {
return gf_preference_engine_get_bool(root, name);
}
/**
* gf_preferences_exist:
* @name : The name of the preference.
*
* Determines if the preference named @name exists.
*
* Return Value: @TRUE if the preference exists, @FALSE otherwise.
*/
gboolean
gf_preferences_exist(const gchar *name) {
return gf_preference_engine_exists(root, name);
}
/**
* gf_preferences_rename:
* @oldname : The oldname of the preference.
* @newname : The newname for the preference.
*
* Renames @oldname to @newname.
*
* Return Value: @TRUE on success, @FALSE otherwise.
*/
gboolean
gf_preferences_rename(const gchar *oldname, const gchar *newname) {
return gf_preference_engine_rename(root, oldname, newname);
}
/**
* gf_preferences_remove:
* @path : The path to remove.
*
* Removes @path and all children.
*
* Return Value: The number of preferences removed.
*/
gint
gf_preferences_remove(const gchar *path) {
return gf_preference_engine_remove(root, path);
}
/**
* gf_preferences_query:
* @path : The path to query.
* @num_prefs : Return address for the number of preferences returned.
*
* Queries @path for all preferences.
*
* Return Value: A newly allocated array of #GfPreference's.
*/
GfPreference **
gf_preferences_query(const gchar *path, guint *num_prefs) {
return gf_preference_engine_query(root, path, num_prefs);
}
/**
* gf_preferences_get_type:
* @path : The path of the preference.
*
* Gets the #GfPreferenceType of the preference @path.
*
* Return Value: The #GfPreferenceType of the preference @path.
*/
GfPreferenceType
gf_preferences_get_type(const gchar *path) {
return gf_preference_engine_get_type(root, path);
}
/**
* gf_preferences_add_engine:
* @engine : The #GfPreferenceEngine to add.
* @mntpnt : The path to add the engine at.
*
* This works basically like a Unix filesystem. You mount your
* #GfPreferenceEngine, @engine in this case (the filesystem), at an arbitrary
* path, @mntpnt (a mount point).
*
* All preferences for @engine will be accessible trough their normal paths
* with @mntpnt prepended to them.
*
* Return Value: @TRUE if the add was successful, @FALSE otherwise.
*/
gboolean
gf_preferences_add_engine(GfPreferenceEngine *engine, const gchar *mntpnt) {
g_return_val_if_fail(GF_IS_PREFERENCE_ENGINE(engine), FALSE);
g_return_val_if_fail(mntpnt, FALSE);
#warning rewrite me
return FALSE;
}
/**
* gf_preferences_remove_engine:
* @mntpnt : The mount point of the engine.
*
* Unmounts a preference engine.
*
* Return Value: @TRUE on success, @FALSE otherwise.
*/
gboolean
gf_preferences_remove_engine(const gchar *mntpnt) {
g_return_val_if_fail(mntpnt, FALSE);
# warning rewrite me
return FALSE;
}