diff options
author | Brian Tarricone <brian@tarricone.org> | 2007-09-06 09:27:05 +0000 |
---|---|---|
committer | Brian Tarricone <brian@tarricone.org> | 2007-09-06 09:27:05 +0000 |
commit | 63affd4acd1d4aca358999235d83303c76826d2f (patch) | |
tree | 88a3b5377d68a20120a9669bff354cafdfe04522 | |
parent | f1b43fa69c1b83fd89f60bbeb6f1dc7819120545 (diff) | |
download | xfconf-63affd4acd1d4aca358999235d83303c76826d2f.tar.gz |
implement most of the perchannel-xml backend. reading stuff from
the xml files isn't implemented yet, but writing values is done and
appears to work
(Old svn revision: 26728)
-rw-r--r-- | xfconfd/Makefile.am | 27 | ||||
-rw-r--r-- | xfconfd/xfconf-backend-perchannel-xml.c | 470 | ||||
-rw-r--r-- | xfconfd/xfconf-backend.c | 85 | ||||
-rw-r--r-- | xfconfd/xfconf-backend.h | 30 | ||||
-rw-r--r-- | xfconfd/xfconf-daemon.c | 10 |
5 files changed, 586 insertions, 36 deletions
diff --git a/xfconfd/Makefile.am b/xfconfd/Makefile.am index bfd012e..80a55bb 100644 --- a/xfconfd/Makefile.am +++ b/xfconfd/Makefile.am @@ -44,18 +44,27 @@ service_DATA = $(service_in_files:.service.in=.service) %.service: %.service.in sed -e "s,\@bindir\@,$(bindir),g" < $< > $@ -if MAINTAINER_MODE - -xfconf-dbus-server.h: $(top_srcdir)/common/xfconf-dbus.xml - dbus-binding-tool --mode=glib-server --prefix=xfconf $< > $@ - -endif - +DISTCLEANFILES = \ + $(service_DATA) EXTRA_DIST = \ xfconf-backend-perchannel-xml.c \ xfconf-backend-perchannel-xml.h \ $(service_in_files) -DISTCLEANFILES = \ - $(service_DATA) + +if MAINTAINER_MODE + +xfconf_built_sources = \ + xfconf-dbus-server.h + +DISTCLEANFILES += \ + $(xfconf_built_sources) + +BUILT_SOURCES = \ + $(xfconf_built_sources) + +xfconf-dbus-server.h: $(top_srcdir)/common/xfconf-dbus.xml + dbus-binding-tool --mode=glib-server --prefix=xfconf $< > $@ + +endif diff --git a/xfconfd/xfconf-backend-perchannel-xml.c b/xfconfd/xfconf-backend-perchannel-xml.c index 6f0a0ec..1eb80cf 100644 --- a/xfconfd/xfconf-backend-perchannel-xml.c +++ b/xfconfd/xfconf-backend-perchannel-xml.c @@ -21,16 +21,38 @@ #include <config.h> #endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif + +#ifdef HAVE_STRING_H +#include <string.h> +#endif + #include <libxfce4util/libxfce4util.h> +#include <dbus/dbus-glib.h> #include "xfconf-backend-perchannel-xml.h" #include "xfconf-backend.h" +#include "xfconf-util.h" + +#define CACHE_TIMEOUT (20*60*1000) /* 20 minutes */ +#define WRITE_TIMEOUT (5*1000) /* 5 secionds */ struct _XfconfBackendPerchannelXml { GObject parent; gchar *config_path; + + GTree *channels; + + guint save_id; + GList *dirty_channels; }; typedef struct _XfconfBackendPerchannelXmlClass @@ -76,6 +98,18 @@ static gboolean xfconf_backend_perchannel_xml_remove_channel(XfconfBackend *back static gboolean xfconf_backend_perchannel_xml_flush(XfconfBackend *backend, GError **error); +static void xfconf_backend_perchannel_xml_schedule_save(XfconfBackendPerchannelXml *xbpx, + const gchar *channel); + +static GTree *xfconf_backend_perchannel_xml_create_channel(XfconfBackendPerchannelXml *xbpx, + const gchar *channel); +static GTree *xfconf_backend_perchannel_xml_load_channel(XfconfBackendPerchannelXml *xbpx, + const gchar *channel, + GError **error); +static gboolean xfconf_backend_perchannel_xml_flush_channel(XfconfBackendPerchannelXml *xbpx, + const gchar *channel, + GError **error); + G_DEFINE_TYPE_WITH_CODE(XfconfBackendPerchannelXml, xfconf_backend_perchannel_xml, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(XFCONF_TYPE_BACKEND, @@ -93,12 +127,28 @@ xfconf_backend_perchannel_xml_class_init(XfconfBackendPerchannelXmlClass *klass) static void xfconf_backend_perchannel_xml_init(XfconfBackendPerchannelXml *instance) { - + instance->channels = g_tree_new_full((GCompareDataFunc)g_ascii_strcasecmp, + NULL, + (GDestroyNotify)g_free, + (GDestroyNotify)g_tree_destroy); } static void xfconf_backend_perchannel_xml_finalize(GObject *obj) { + XfconfBackendPerchannelXml *xbpx = XFCONF_BACKEND_PERCHANNEL_XML(obj); + + if(xbpx->save_id) { + g_source_remove(xbpx->save_id); + xbpx->save_id = 0; + } + + if(xbpx->dirty_channels) + xfconf_backend_perchannel_xml_flush(XFCONF_BACKEND(xbpx), NULL); + + g_tree_destroy(xbpx->channels); + g_free(xbpx->config_path); + G_OBJECT_CLASS(xfconf_backend_perchannel_xml_parent_class)->finalize(obj); } @@ -126,7 +176,8 @@ xfconf_backend_perchannel_xml_initialize(XfconfBackend *backend, if(!path || !g_file_test(path, G_FILE_TEST_IS_DIR)) { if(error) { - g_set_error(error, G_FILE_ERROR, 0, + g_set_error(error, XFCONF_BACKEND_ERROR, + XFCONF_BACKEND_ERROR_WRITE_FAILURE, _("Unable to create configuration directory")); } g_free(path); @@ -145,7 +196,31 @@ xfconf_backend_perchannel_xml_set(XfconfBackend *backend, const GValue *value, GError **error) { - return FALSE; + XfconfBackendPerchannelXml *xbpx = XFCONF_BACKEND_PERCHANNEL_XML(backend); + GTree *properties = g_tree_lookup(xbpx->channels, channel); + GValue *cur_val; + + if(!properties) { + properties = xfconf_backend_perchannel_xml_load_channel(xbpx, channel, + NULL); + if(!properties) { + properties = xfconf_backend_perchannel_xml_create_channel(xbpx, + channel); + } + } + + cur_val = g_tree_lookup(properties, property); + if(cur_val) + g_value_unset(cur_val); + else { + cur_val = g_new0(GValue, 1); + g_tree_insert(properties, g_strdup(property), cur_val); + } + + g_value_copy(value, g_value_init(cur_val, G_VALUE_TYPE(value))); + xfconf_backend_perchannel_xml_schedule_save(xbpx, channel); + + return TRUE; } static gboolean @@ -155,6 +230,43 @@ xfconf_backend_perchannel_xml_get(XfconfBackend *backend, GValue *value, GError **error) { + XfconfBackendPerchannelXml *xbpx = XFCONF_BACKEND_PERCHANNEL_XML(backend); + GTree *properties = g_tree_lookup(xbpx->channels, channel); + GValue *cur_val; + + if(!properties) { + properties = xfconf_backend_perchannel_xml_load_channel(xbpx, channel, + error); + if(!properties) + return FALSE; + } + + cur_val = g_tree_lookup(properties, property); + if(!cur_val) { + if(error) { + g_set_error(error, XFCONF_BACKEND_ERROR, + XFCONF_BACKEND_ERROR_PROPERTY_NOT_FOUND, + _("Property \"%s\" does not exist on channel \"%s\""), + property, channel); + } + return FALSE; + } + + g_value_copy(cur_val, g_value_init(value, G_VALUE_TYPE(cur_val))); + + return TRUE; +} + +static gboolean +tree_to_hash_table(gpointer key, + gpointer value, + gpointer data) +{ + GValue *value1 = g_new0(GValue, 1); + + g_value_copy(value, g_value_init(value1, G_VALUE_TYPE(value))); + g_hash_table_insert((GHashTable *)data, g_strdup(key), value1); + return FALSE; } @@ -164,7 +276,19 @@ xfconf_backend_perchannel_xml_get_all(XfconfBackend *backend, GHashTable *properties, GError **error) { - return FALSE; + XfconfBackendPerchannelXml *xbpx = XFCONF_BACKEND_PERCHANNEL_XML(backend); + GTree *properties1 = g_tree_lookup(xbpx->channels, channel); + + if(!properties1) { + properties1 = xfconf_backend_perchannel_xml_load_channel(xbpx, channel, + error); + if(!properties1) + return FALSE; + } + + g_tree_foreach(properties1, tree_to_hash_table, properties); + + return TRUE; } static gboolean @@ -174,7 +298,24 @@ xfconf_backend_perchannel_xml_exists(XfconfBackend *backend, gboolean *exists, GError **error) { - return FALSE; + XfconfBackendPerchannelXml *xbpx = XFCONF_BACKEND_PERCHANNEL_XML(backend); + GTree *properties = g_tree_lookup(xbpx->channels, channel); + + if(!properties) { + properties = xfconf_backend_perchannel_xml_load_channel(xbpx, channel, + NULL); + if(!properties) { + *exists = FALSE; + return TRUE; + } + } + + if(g_tree_lookup(properties, property)) + *exists = TRUE; + else + *exists = FALSE; + + return TRUE; } static gboolean @@ -183,7 +324,30 @@ xfconf_backend_perchannel_xml_remove(XfconfBackend *backend, const gchar *property, GError **error) { - return FALSE; + XfconfBackendPerchannelXml *xbpx = XFCONF_BACKEND_PERCHANNEL_XML(backend); + GTree *properties = g_tree_lookup(xbpx->channels, channel); + + if(!properties) { + properties = xfconf_backend_perchannel_xml_load_channel(xbpx, channel, + error); + if(!properties) + return FALSE; + } + + if(!g_tree_lookup(properties, property)) { + if(error) { + g_set_error(error, XFCONF_BACKEND_ERROR, + XFCONF_BACKEND_ERROR_PROPERTY_NOT_FOUND, + _("Property \"%s\" does not exist on channel \"%s\""), + property, channel); + } + return FALSE; + } + + g_tree_remove(properties, property); + xfconf_backend_perchannel_xml_schedule_save(xbpx, channel); + + return TRUE; } static gboolean @@ -191,12 +355,304 @@ xfconf_backend_perchannel_xml_remove_channel(XfconfBackend *backend, const gchar *channel, GError **error) { - return FALSE; + XfconfBackendPerchannelXml *xbpx = XFCONF_BACKEND_PERCHANNEL_XML(backend); + gchar *filename; + GList *dirty; + + if((dirty = g_list_find_custom(xbpx->dirty_channels, channel, + (GCompareFunc)g_ascii_strcasecmp))) + { + xbpx->dirty_channels = g_list_remove(xbpx->dirty_channels, dirty); + if(!xbpx->dirty_channels && xbpx->save_id) { + g_source_remove(xbpx->save_id); + xbpx->save_id = 0; + } + } + + g_tree_remove(xbpx->channels, channel); + + filename = g_strdup_printf("%s/%s.xml", xbpx->config_path, channel); + if(unlink(filename)) { + if(error) { + g_set_error(error, XFCONF_BACKEND_ERROR, + XFCONF_BACKEND_ERROR_WRITE_FAILURE, + _("Unable to remove channel \"%s\": %s"), + channel, strerror(errno)); + } + g_free(filename); + return FALSE; + } + g_free(filename); + + return TRUE; } static gboolean xfconf_backend_perchannel_xml_flush(XfconfBackend *backend, GError **error) { + XfconfBackendPerchannelXml *xbpx = XFCONF_BACKEND_PERCHANNEL_XML(backend); + GList *l; + + for(l = xbpx->dirty_channels; l; l = l->next) + xfconf_backend_perchannel_xml_flush_channel(xbpx, l->data, error); + return TRUE; } + + + +static gboolean +xfconf_backend_perchannel_xml_save_timeout(gpointer data) +{ + XFCONF_BACKEND_PERCHANNEL_XML(data)->save_id = 0; + xfconf_backend_perchannel_xml_flush(XFCONF_BACKEND(data), NULL); + + return FALSE; +} + +static void +xfconf_backend_perchannel_xml_schedule_save(XfconfBackendPerchannelXml *xbpx, + const gchar *channel) +{ + if(!g_list_find_custom(xbpx->dirty_channels, channel, + (GCompareFunc)g_ascii_strcasecmp)) + { + gpointer orig_key = NULL, val = NULL; + + if(!g_tree_lookup_extended(xbpx->channels, channel, &orig_key, &val)) { + g_warning("Attempt to schedule save for a nonexistent channel."); + return; + } + + xbpx->dirty_channels = g_list_prepend(xbpx->dirty_channels, orig_key); + } + + if(xbpx->save_id) + g_source_remove(xbpx->save_id); + + xbpx->save_id = g_timeout_add(WRITE_TIMEOUT, + xfconf_backend_perchannel_xml_save_timeout, + xbpx); +} + +static GTree * +xfconf_backend_perchannel_xml_create_channel(XfconfBackendPerchannelXml *xbpx, + const gchar *channel) +{ + GTree *properties; + + if((properties = g_tree_lookup(xbpx->channels, channel))) { + g_warning("Attempt to create channel when one already exists."); + return properties; + } + + properties = g_tree_new_full((GCompareDataFunc)strcmp, NULL, + (GDestroyNotify)g_free, + (GDestroyNotify)xfconf_g_value_free); + g_tree_insert(xbpx->channels, g_strdup(channel), properties); + + return properties; +} + +static GTree * +xfconf_backend_perchannel_xml_load_channel(XfconfBackendPerchannelXml *xbpx, + const gchar *channel, + GError **error) +{ + GTree *properties = NULL; + gchar *filename; + + filename = g_strdup_printf("%s/%s.xml", xbpx->config_path, channel); + if(!g_file_test(filename, G_FILE_TEST_IS_REGULAR)) { + if(error) { + g_set_error(error, XFCONF_BACKEND_ERROR, + XFCONF_BACKEND_ERROR_CHANNEL_NOT_FOUND, + _("Channel \"%s\" does not exist"), channel); + } + g_free(filename); + return NULL; + } + +//out: + g_free(filename); + + return properties; +} + +typedef struct +{ + FILE *fp; + gboolean error_occurred; +} NodeWriterData; + +static gboolean +tree_write_nodes(gpointer key, + gpointer value_p, + gpointer data) +{ + NodeWriterData *ndata = data; + const gchar *property = key, *type_str = NULL; + const GValue *value = value_p; + gchar *value_str = NULL; + + /* + * I know the suggested config value scheme implies some kind of hierarchical + * list of properties, but I'm lazy, so we're just going to store them flat. + */ + + switch(G_VALUE_TYPE(value)) { + case G_TYPE_STRING: + value_str = g_markup_escape_text(g_value_get_string(value), -1); + type_str = "string"; + break; + + case G_TYPE_INT: + value_str = g_strdup_printf("%d", g_value_get_int(value)); + type_str = "int"; + break; + + case G_TYPE_INT64: + value_str = g_strdup_printf("%" G_GINT64_FORMAT, + g_value_get_int64(value)); + type_str = "int64"; + break; + + case G_TYPE_DOUBLE: + value_str = g_strdup_printf("%f", g_value_get_double(value)); + type_str = "double"; + break; + + case G_TYPE_BOOLEAN: + value_str = g_strdup(g_value_get_boolean(value) ? "true" : "false"); + type_str = "bool"; + break; + + default: + if(G_VALUE_TYPE(value) == dbus_g_type_get_collection("GPtrArray", + G_TYPE_STRING)) + { + type_str = "strlist"; + } else { + g_warning("Unknown value type %d (\"%s\"), skipping", + (int)G_VALUE_TYPE(value), G_VALUE_TYPE_NAME(value)); + ndata->error_occurred = TRUE; + return TRUE; + } + break; + } + + if(fprintf(ndata->fp, " <property name=\"%s\" type=\"%s\"", + property, type_str) < 0) + { + ndata->error_occurred = TRUE; + goto out; + } + + if(value_str) { + if(fprintf(ndata->fp, " value=\"%s\"/>\n", value_str) < 0) { + ndata->error_occurred = TRUE; + goto out; + } + } else { + GPtrArray *arr; + gint i; + + if(fputs(">\n", ndata->fp) == EOF) { + ndata->error_occurred = TRUE; + goto out; + } + + arr = g_value_get_boxed(value); + for(i = 0; i < arr->len; ++i) { + value_str = g_markup_escape_text(arr->pdata[i], -1); + if(fprintf(ndata->fp, " <string>%s</string\n", value_str) < 0) { + ndata->error_occurred = TRUE; + goto out; + } + g_free(value_str); + } + value_str = NULL; + + if(fputs(" </property>\n", ndata->fp) == EOF) { + ndata->error_occurred = TRUE; + goto out; + } + } + +out: + g_free(value_str); + + return ndata->error_occurred; +} + + +static gboolean +xfconf_backend_perchannel_xml_flush_channel(XfconfBackendPerchannelXml *xbpx, + const gchar *channel, + GError **error) +{ + gboolean ret = FALSE; + GTree *properties = g_tree_lookup(xbpx->channels, channel); + gchar *filename = NULL, *filename_tmp = NULL; + FILE *fp = NULL; + NodeWriterData ndata; + + if(!properties) { + if(error) { + g_set_error(error, XFCONF_BACKEND_ERROR, + XFCONF_BACKEND_ERROR_CHANNEL_NOT_FOUND, + _("Channel \"%s\" does not exist"), channel); + } + return FALSE; + } + + filename = g_strdup_printf("%s/%s.xml", xbpx->config_path, channel); + filename_tmp = g_strconcat(filename, ".new", NULL); + + fp = fopen(filename_tmp, "w"); + if(!fp) + goto out; + + if(fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n", fp) == EOF + || fprintf(fp, "<channel name=\"%s\" version=\"1\">\n", channel) < 0) + { + goto out; + } + + ndata.fp = fp; + ndata.error_occurred = FALSE; + g_tree_foreach(properties, tree_write_nodes, &ndata); + if(ndata.error_occurred) + goto out; + + if(fputs("</channel>\n", fp) == EOF) + goto out; + + if(fclose(fp)) { + fp = NULL; + goto out; + } + fp = NULL; + + if(rename(filename_tmp, filename)) + goto out; + + ret = TRUE; + +out: + if(!ret && error && !*error) { + g_set_error(error, XFCONF_BACKEND_ERROR, + XFCONF_BACKEND_ERROR_WRITE_FAILURE, + _("Unable to write channel \"%s\": %s"), + channel, strerror(errno)); + } + + if(fp) + fclose(fp); + + g_free(filename); + g_free(filename_tmp); + + return ret; +} diff --git a/xfconfd/xfconf-backend.c b/xfconfd/xfconf-backend.c index 7778c07..96153d2 100644 --- a/xfconfd/xfconf-backend.c +++ b/xfconfd/xfconf-backend.c @@ -21,10 +21,14 @@ #include <config.h> #endif +#include <dbus/dbus-glib.h> + #include "xfconf-backend.h" static GQuark error_quark = 0; +static void xfconf_backend_base_init(gpointer g_class); + /** * XfconfBackendInterface: @@ -58,6 +62,32 @@ xfconf_backend_get_error_quark() return error_quark; } +/* unfortunately glib-mkenums can't generate types that are compatible with + * dbus error names -- the 'nick' value is used, which can have dashes in it, + * which dbus doesn't like. */ +GType +xfconf_backend_error_get_type() +{ + static GType type = 0; + + if(!type) { + static const GEnumValue values[] = { + { XFCONF_BACKEND_ERROR_UNKNOWN, "XFCONF_BACKEND_ERROR_UNKNOWN", "Unknown" }, + { XFCONF_BACKEND_ERROR_CHANNEL_NOT_FOUND, "XFCONF_BACKEND_ERROR_CHANNEL_NOT_FOUND", "ChannelNotFound" }, + { XFCONF_BACKEND_ERROR_PROPERTY_NOT_FOUND, "XFCONF_BACKEND_ERROR_PROPERTY_NOT_FOUND", "PropertyNotFound" }, + { XFCONF_BACKEND_ERROR_READ_FAILURE, "XFCONF_BACKEND_ERROR_READ_FAILURE", "ReadFailure" }, + { XFCONF_BACKEND_ERROR_WRITE_FAILURE, "XFCONF_BACKEND_ERROR_WRITE_FAILURE", "WriteFailure" }, + { XFCONF_BACKEND_ERROR_INTERNAL_ERROR, "XFCONF_BACKEND_ERROR_INTERNAL_ERROR", "InternalError" }, + { 0, NULL, NULL } + }; + + type = g_enum_register_static("XfconfBackendError", values); + } + + return type; +} + + GType xfconf_backend_get_type() { @@ -66,7 +96,7 @@ xfconf_backend_get_type() if(!backend_type) { static const GTypeInfo backend_info = { sizeof(XfconfBackendInterface), - NULL, + xfconf_backend_base_init, NULL, NULL, NULL, @@ -86,6 +116,22 @@ xfconf_backend_get_type() +static void +xfconf_backend_base_init(gpointer g_class) +{ + static gboolean _inited = FALSE; + + if(!_inited) { + dbus_g_error_domain_register(XFCONF_BACKEND_ERROR, + "org.xfce.Xfconf.BackendError", + XFCONF_TYPE_BACKEND_ERROR); + + _inited = TRUE; + } +} + + + /** * xfconf_backend_initialize: * @backend: The #XfconfBackend. @@ -103,7 +149,8 @@ xfconf_backend_initialize(XfconfBackend *backend, { XfconfBackendInterface *iface = XFCONF_BACKEND_GET_INTERFACE(backend); - g_return_val_if_fail(iface && iface->initialize, FALSE); + xfconf_backend_return_val_if_fail(iface && iface->initialize + && (!error || !*error), FALSE); return iface->initialize(backend, error); } @@ -131,8 +178,9 @@ xfconf_backend_set(XfconfBackend *backend, { XfconfBackendInterface *iface = XFCONF_BACKEND_GET_INTERFACE(backend); - g_return_val_if_fail(iface && iface->set && channel && property && value - && (!error || *error), FALSE); + xfconf_backend_return_val_if_fail(iface && iface->set && channel && *channel + && property && *property + && value && (!error || !*error), FALSE); return iface->set(backend, channel, property, value, error); } @@ -160,8 +208,9 @@ xfconf_backend_get(XfconfBackend *backend, { XfconfBackendInterface *iface = XFCONF_BACKEND_GET_INTERFACE(backend); - g_return_val_if_fail(iface && iface->get && channel && property && value - && (!error || *error), FALSE); + xfconf_backend_return_val_if_fail(iface && iface->get && channel && *channel + && property && *property + && value && (!error || !*error), FALSE); return iface->get(backend, channel, property, value, error); } @@ -189,8 +238,9 @@ xfconf_backend_get_all(XfconfBackend *backend, { XfconfBackendInterface *iface = XFCONF_BACKEND_GET_INTERFACE(backend); - g_return_val_if_fail(iface && iface->get_all && channel && properties - && (!error || *error), FALSE); + xfconf_backend_return_val_if_fail(iface && iface->get_all && channel + && *channel && properties + && (!error || !*error), FALSE); return iface->get_all(backend, channel, properties, error); } @@ -219,8 +269,10 @@ xfconf_backend_exists(XfconfBackend *backend, { XfconfBackendInterface *iface = XFCONF_BACKEND_GET_INTERFACE(backend); - g_return_val_if_fail(iface && iface->exists && channel && property && exists - && (!error || *error), FALSE); + xfconf_backend_return_val_if_fail(iface && iface->exists && channel + && *channel && property && *property + && exists + && (!error || !*error), FALSE); return iface->exists(backend, channel, property, exists, error); } @@ -246,8 +298,9 @@ xfconf_backend_remove(XfconfBackend *backend, { XfconfBackendInterface *iface = XFCONF_BACKEND_GET_INTERFACE(backend); - g_return_val_if_fail(iface && iface->remove && channel && property - && (!error || *error), FALSE); + xfconf_backend_return_val_if_fail(iface && iface->remove && channel + && *channel && property && *property + && (!error || !*error), FALSE); return iface->remove(backend, channel, property, error); } @@ -271,8 +324,9 @@ xfconf_backend_remove_channel(XfconfBackend *backend, { XfconfBackendInterface *iface = XFCONF_BACKEND_GET_INTERFACE(backend); - g_return_val_if_fail(iface && iface->remove_channel && channel - && (!error || *error), FALSE); + xfconf_backend_return_val_if_fail(iface && iface->remove_channel && channel + && *channel + && (!error || !*error), FALSE); return iface->remove_channel(backend, channel, error); } @@ -295,7 +349,8 @@ xfconf_backend_flush(XfconfBackend *backend, { XfconfBackendInterface *iface = XFCONF_BACKEND_GET_INTERFACE(backend); - g_return_val_if_fail(iface && iface->flush && (!error || *error), FALSE); + xfconf_backend_return_val_if_fail(iface && iface->flush + && (!error || !*error), FALSE); return iface->flush(backend, error); } diff --git a/xfconfd/xfconf-backend.h b/xfconfd/xfconf-backend.h index b53017b..03d7816 100644 --- a/xfconfd/xfconf-backend.h +++ b/xfconfd/xfconf-backend.h @@ -22,15 +22,44 @@ #include <glib-object.h> +#if defined(GETTEXT_PACKAGE) +#include <glib/gi18n-lib.h> +#else +#include <glib/gi18n.h> +#endif + #define XFCONF_TYPE_BACKEND (xfconf_backend_get_type()) #define XFCONF_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XFCONF_TYPE_BACKEND, XfconfBackend)) #define XFCONF_IS_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XFCONF_TYPE_BACKEND)) #define XFCONF_BACKEND_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE((obj), XFCONF_TYPE_BACKEND, XfconfBackendInterface)) +#define XFCONF_TYPE_BACKEND_ERROR (xfconf_backend_error_get_type()) #define XFCONF_BACKEND_ERROR (xfconf_backend_get_error_quark()) +#define xfconf_backend_return_val_if_fail(cond, val) G_STMT_START{ \ + if(!(cond)) { \ + if(error) { \ + g_set_error(error, XFCONF_BACKEND_ERROR, \ + XFCONF_BACKEND_ERROR_INTERNAL_ERROR, \ + _("An internal error occurred; this is probably a bug")); \ + } \ + g_return_val_if_fail((cond), (val)); \ + return (val); /* ensure return even if G_DISABLE_CHECKS */ \ + } \ +}G_STMT_END + G_BEGIN_DECLS +typedef enum +{ + XFCONF_BACKEND_ERROR_UNKNOWN = 0, + XFCONF_BACKEND_ERROR_CHANNEL_NOT_FOUND, + XFCONF_BACKEND_ERROR_PROPERTY_NOT_FOUND, + XFCONF_BACKEND_ERROR_READ_FAILURE, + XFCONF_BACKEND_ERROR_WRITE_FAILURE, + XFCONF_BACKEND_ERROR_INTERNAL_ERROR, +} XfconfBackendError; + typedef struct _XfconfBackend XfconfBackend; typedef struct _XfconfBackendInterface XfconfBackendInterface; @@ -83,6 +112,7 @@ struct _XfconfBackendInterface void (*_xb_reserved3)(); }; +GType xfconf_backend_error_get_type() G_GNUC_CONST; GQuark xfconf_backend_get_error_quark(); GType xfconf_backend_get_type() G_GNUC_CONST; diff --git a/xfconfd/xfconf-daemon.c b/xfconfd/xfconf-daemon.c index 3a42e62..c3c8059 100644 --- a/xfconfd/xfconf-daemon.c +++ b/xfconfd/xfconf-daemon.c @@ -28,7 +28,7 @@ #include "xfconf-backend-factory.h" #include "xfconf-backend.h" #include "xfconf-marshal.h" - +#include "xfconf-util.h" static gboolean xfconf_set_property(XfconfDaemon *xfconfd, const gchar *channel, @@ -96,9 +96,9 @@ xfconf_daemon_class_init(XfconfDaemonClass *klass) object_class->finalize = xfconf_daemon_finalize; - g_signal_new("changed", XFCONF_TYPE_DAEMON, G_SIGNAL_RUN_LAST, 0, NULL, - NULL, xfconf_marshal_VOID__STRING_STRING, G_TYPE_NONE, 2, - G_TYPE_STRING, G_TYPE_STRING); + g_signal_new("property-changed", XFCONF_TYPE_DAEMON, G_SIGNAL_RUN_LAST, 0, + NULL, NULL, xfconf_marshal_VOID__STRING_STRING, G_TYPE_NONE, + 2, G_TYPE_STRING, G_TYPE_STRING); dbus_g_object_type_install_info(G_TYPE_FROM_CLASS(klass), &dbus_glib_xfconf_object_info); @@ -162,7 +162,7 @@ xfconf_get_all_properties(XfconfDaemon *xfconfd, *properties = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify)g_free, - (GDestroyNotify)g_value_unset); + (GDestroyNotify)xfconf_g_value_free); ret = xfconf_backend_get_all(xfconfd->backend, channel, *properties, error); if(!ret) { |