--- a/gflib/gflib/gf_preferences.c Wed Dec 09 17:48:51 2009 -0600
+++ b/gflib/gflib/gf_preferences.c Wed Dec 09 20:23:28 2009 -0600
@@ -18,38 +18,213 @@
#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>
+#define PREFS_URI_REGEX \ + "^([A-Za-z][A-Z-a-z0-9]*):((([A-Za-z].*)=(.*))(,([A-Za-z].*)=(.*)))*$" /******************************************************************************
*****************************************************************************/
static GfPreferenceEngine *root = NULL;
/******************************************************************************
+ *****************************************************************************/ +static GfPreferenceEngine * +gf_preferences_create_default_engine(const gchar *appname) { + GfPreferenceEngine *engine = NULL; + 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); + engine = gf_preference_engine_xml_new(filename); + engine = gf_preference_engine_null_new(); +/* 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; + GList *gc = NULL, *l = NULL; + GMatchInfo *match_info = NULL; + GParameter *params = NULL; + GType type = G_TYPE_INVALID; + gchar *type_name = NULL; + regex = g_regex_new(PREFS_URI_REGEX, 0, 0, &error); + if(!g_regex_match(regex, uri, 0, &match_info)) { + gf_log_warning("GfPreferences", + "Could not parse preference uri: '%s'\n" + "Falling back to the default preference engine.\n", + /* we have the match_info now, so kill the regex */ + /* the type name is in position 1, so grab it and see if the type even + 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 " + "Falling back to the default preference engine.\n", + /* 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); + /* 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; + /* we multiple by 3 to get to the group, and add two to actually + /* 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 + name = g_match_info_fetch(match_info, index + 1); + pspec = g_object_class_find_property(klass, name); + gf_log_warning("GfPreferences", + "Preference engine %s does not have a property " + switch(pspec->value_type) { + 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), + /* we know the property exists now, so set it in the GParameter and + 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(¶ms[cur].value, G_TYPE_STRING); + g_value_take_string(¶ms[cur].value, value); + g_type_class_unref(klass); + engine = g_object_newv(type, n_params, params); + for(l = gc; l; l = l->next) + 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. +/****************************************************************************** *****************************************************************************/
gf_preferences_init(const gchar *appname, const gchar *uri) {
- gchar *gf_dir = NULL, *base = NULL, *filename = NULL;
+ GfPreferenceEngine *engine = NULL; + const gchar *real_uri = NULL; - gf_dir = gf_fs_user_settings_dir();
- base = g_path_get_basename(appname);
- filename = g_build_filename(gf_dir, base, "prefs.xml", 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");
+ engine = gf_preferences_create_engine_from_uri(real_uri); - root = gf_preference_engine_xml_new(filename);
- root = gf_preference_engine_null_new();
+ engine = gf_preferences_create_default_engine(appname);