grim/guifications3
Clone
Summary
Browse
Changes
Graph
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
;
}