[nautilus-actions] Have smaller sources for NagpGConfProvider



commit c826957087a878b315c6a5eddd9f77294b49cb86
Author: Pierre Wieser <pwieser trychlos org>
Date:   Tue Nov 24 23:49:05 2009 +0100

    Have smaller sources for NagpGConfProvider

 ChangeLog                                          |   10 +
 nautilus-actions/io-provider-gconf/Makefile.am     |    4 +
 .../io-provider-gconf/nagp-gconf-provider.c        |  889 +-------------------
 .../io-provider-gconf/nagp-gconf-provider.h        |   13 +-
 nautilus-actions/io-provider-gconf/nagp-read.c     |  580 +++++++++++++
 nautilus-actions/io-provider-gconf/nagp-read.h     |   55 ++
 nautilus-actions/io-provider-gconf/nagp-write.c    |  419 +++++++++
 nautilus-actions/io-provider-gconf/nagp-write.h    |   66 ++
 8 files changed, 1153 insertions(+), 883 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index eccf04b..f1f83db 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
 2009-11-24 Pierre Wieser <pwieser trychlos org>
 
+	Have smaller sources in NagpGConfProvider.
+	Remove na-utils dependancy.
+
+	* nautilus-actions/io-provider-gconf/nagp-read.c:
+	* nautilus-actions/io-provider-gconf/nagp-read.h:
+	* nautilus-actions/io-provider-gconf/nagp-write.c:
+	* nautilus-actions/io-provider-gconf/nagp-write.h: New files.
+
+	* nautilus-actions/io-provider-gconf/Makefile.am: Updated accordingly.
+
 	* configure.ac: Remove useless gthread dependancy.
 
 	* nautilus-actions/io-provider-gconf/Makefile.am:
diff --git a/nautilus-actions/io-provider-gconf/Makefile.am b/nautilus-actions/io-provider-gconf/Makefile.am
index b793330..dbb5a06 100644
--- a/nautilus-actions/io-provider-gconf/Makefile.am
+++ b/nautilus-actions/io-provider-gconf/Makefile.am
@@ -42,6 +42,10 @@ libna_io_provider_gconf_la_SOURCES = \
 	nagp-gconf-provider.h										\
 	nagp-keys.h													\
 	nagp-module.c												\
+	nagp-read.c													\
+	nagp-read.h													\
+	nagp-write.c												\
+	nagp-write.h												\
 	$(NULL)
 
 libna_io_provider_gconf_la_LIBADD = \
diff --git a/nautilus-actions/io-provider-gconf/nagp-gconf-provider.c b/nautilus-actions/io-provider-gconf/nagp-gconf-provider.c
index 535c2e9..d651b58 100644
--- a/nautilus-actions/io-provider-gconf/nagp-gconf-provider.c
+++ b/nautilus-actions/io-provider-gconf/nagp-gconf-provider.c
@@ -35,14 +35,11 @@
 #include <string.h>
 
 #include <nautilus-actions/api/na-iio-provider.h>
-#include <nautilus-actions/api/na-object-api.h>
 #include <nautilus-actions/api/na-gconf-monitor.h>
 
-/* only possible because we are an internal plugin */
-#include <runtime/na-gconf-utils.h>
-#include <runtime/na-utils.h>
-
 #include "nagp-gconf-provider.h"
+#include "nagp-read.h"
+#include "nagp-write.h"
 #include "nagp-keys.h"
 
 /* private class data
@@ -51,17 +48,6 @@ struct NagpGConfProviderClassPrivate {
 	void *empty;						/* so that gcc -pedantic is happy */
 };
 
-/* private instance data
- */
-struct NagpGConfProviderPrivate {
-	gboolean     dispose_has_run;
-	GConfClient *gconf;
-	GList       *monitors;
-	GTimeVal     last_event;
-	guint        event_source_id;
-	gchar       *last_triggered_id;
-};
-
 static GType         st_module_type = 0;
 static GObjectClass *st_parent_class = NULL;
 static gint          st_timeout_msec = 100;
@@ -81,39 +67,6 @@ static gboolean       config_path_changed_trigger_interface( NagpGConfProvider *
 static gulong         time_val_diff( const GTimeVal *recent, const GTimeVal *old );
 static gchar         *entry2uuid( GConfEntry *entry );
 
-static GList         *iio_provider_read_items( const NAIIOProvider *provider, GSList **messages );
-static NAObjectItem  *read_item( NagpGConfProvider *provider, const gchar *path );
-static void           read_item_action( NagpGConfProvider *provider, const gchar *path, NAObjectAction *action );
-static void           read_item_action_properties( NagpGConfProvider *provider, GSList *entries, NAObjectAction *action );
-static void           read_item_action_properties_v1( NagpGConfProvider *gconf, GSList *entries, NAObjectAction *action );
-static void           read_item_action_profile( NagpGConfProvider *provider, NAObjectAction *action, const gchar *path );
-static void           read_item_action_profile_properties( NagpGConfProvider *provider, GSList *entries, NAObjectProfile *profile );
-static void           read_item_menu( NagpGConfProvider *provider, const gchar *path, NAObjectMenu *menu );
-static void           read_item_menu_properties( NagpGConfProvider *provider, GSList *entries, NAObjectMenu *menu );
-static void           read_object_item_properties( NagpGConfProvider *provider, GSList *entries, NAObjectItem *item );
-
-static gboolean       iio_provider_is_willing_to_write( const NAIIOProvider *provider );
-
-static gboolean       iio_provider_is_writable( const NAIIOProvider *provider, const NAObjectItem *item );
-
-static guint          iio_provider_write_item( const NAIIOProvider *provider, const NAObjectItem *item, GSList **message );
-static gboolean       write_item_action( NagpGConfProvider *gconf, const NAObjectAction *action, GSList **message );
-static gboolean       write_item_menu( NagpGConfProvider *gconf, const NAObjectMenu *menu, GSList **message );
-static gboolean       write_object_item( NagpGConfProvider *gconf, const NAObjectItem *item, GSList **message );
-
-static guint          iio_provider_delete_item( const NAIIOProvider *provider, const NAObjectItem *item, GSList **message );
-
-static gboolean       key_is_writable( NagpGConfProvider *gconf, const gchar *path );
-
-static gboolean       write_str( NagpGConfProvider *gconf, const gchar *uuid, const gchar *name, const gchar *key, gchar *value, GSList **message );
-static gboolean       write_bool( NagpGConfProvider *gconf, const gchar *uuid, const gchar *name, const gchar *key, gboolean value, GSList **message );
-static gboolean       write_list( NagpGConfProvider *gconf, const gchar *uuid, const gchar *name, const gchar *key, GSList *value, GSList **message );
-
-static GSList  *na_gconf_utils_get_subdirs( GConfClient *gconf, const gchar *path );
-static void     na_gconf_utils_free_subdirs( GSList *subdirs );
-/*static gboolean na_gconf_utils_have_subdir( GConfClient *gconf, const gchar *path );*/
-static gboolean na_gconf_utils_have_entry( GConfClient *gconf, const gchar *path, const gchar *entry );
-
 GType
 nagp_gconf_provider_get_type( void )
 {
@@ -174,11 +127,11 @@ iio_provider_iface_init( NAIIOProviderInterface *iface )
 
 	g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
 
-	iface->read_items = iio_provider_read_items;
-	iface->is_willing_to_write = iio_provider_is_willing_to_write;
-	iface->is_writable = iio_provider_is_writable;
-	iface->write_item = iio_provider_write_item;
-	iface->delete_item = iio_provider_delete_item;
+	iface->read_items = nagp_iio_provider_read_items;
+	iface->is_willing_to_write = nagp_iio_provider_is_willing_to_write;
+	iface->is_writable = nagp_iio_provider_is_writable;
+	iface->write_item = nagp_iio_provider_write_item;
+	iface->delete_item = nagp_iio_provider_delete_item;
 }
 
 static void
@@ -420,831 +373,3 @@ entry2uuid( GConfEntry *entry )
 
 	return( uuid );
 }
-
-/**
- * iio_provider_read_items:
- *
- * Note that whatever be the version of the readen action, it will be
- * stored as a #NAObjectAction and its set of #NAObjectProfile of the same,
- * latest, version of these classes.
- */
-static GList *
-iio_provider_read_items( const NAIIOProvider *provider, GSList **messages )
-{
-	static const gchar *thisfn = "nagp_gconf_provider_iio_provider_read_items";
-	NagpGConfProvider *self;
-	GList *items_list = NULL;
-	GSList *listpath, *ip;
-	NAObjectItem *item;
-
-	g_debug( "%s: provider=%p, messages=%p", thisfn, ( void * ) provider, ( void * ) messages );
-
-	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), NULL );
-	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), NULL );
-	self = NAGP_GCONF_PROVIDER( provider );
-
-	if( !self->private->dispose_has_run ){
-
-		listpath = na_gconf_utils_get_subdirs( self->private->gconf, NA_GCONF_CONFIG_PATH );
-
-		for( ip = listpath ; ip ; ip = ip->next ){
-
-			const gchar *path = ( const gchar * ) ip->data;
-			g_debug( "path=%s", path );
-			item = read_item( self, path );
-			if( item ){
-				items_list = g_list_prepend( items_list, item );
-			}
-		}
-
-		na_gconf_utils_free_subdirs( listpath );
-	}
-
-	return( items_list );
-}
-
-static NAObjectItem *
-read_item( NagpGConfProvider *provider, const gchar *path )
-{
-	static const gchar *thisfn = "nagp_gconf_provider_read_item";
-	NAObjectItem *item;
-	gboolean have_type;
-	gchar *full_path;
-	gchar *type;
-
-	g_debug( "%s: provider=%p, path=%s", thisfn, ( void * ) provider, path );
-	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), NULL );
-	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), NULL );
-	g_return_val_if_fail( !provider->private->dispose_has_run, NULL );
-
-	have_type = na_gconf_utils_have_entry( provider->private->gconf, path, OBJECT_ITEM_TYPE_ENTRY );
-	full_path = gconf_concat_dir_and_key( path, OBJECT_ITEM_TYPE_ENTRY );
-	type = na_gconf_utils_read_string( provider->private->gconf, full_path, TRUE, OBJECT_ITEM_TYPE_ACTION );
-	g_free( full_path );
-	item = NULL;
-
-	/* a menu has a type='Menu'
-	 */
-	if( have_type && !strcmp( type, OBJECT_ITEM_TYPE_MENU )){
-		item = NA_OBJECT_ITEM( na_object_menu_new());
-		read_item_menu( provider, path, NA_OBJECT_MENU( item ));
-
-	/* else this should be an action (no type, or type='Action')
-	 */
-	} else if( !have_type || !strcmp( type, OBJECT_ITEM_TYPE_ACTION )){
-		item = NA_OBJECT_ITEM( na_object_action_new());
-		read_item_action( provider, path, NA_OBJECT_ACTION( item ));
-
-	} else {
-		g_warning( "%s: unknown type '%s' at %s", thisfn, type, path );
-	}
-
-	g_free( type );
-
-	return( item );
-}
-
-/*
- * load and set the properties of the specified action
- * at least we must have a label, as all other entries can have
- * suitable default values
- *
- * we have to deal with successive versions of action schema :
- *
- * - version = '1.0'
- *   action+= uuid+label+tooltip+icon
- *   action+= path+parameters+basenames+isdir+isfile+multiple+schemes
- *
- * - version > '1.0'
- *   action+= matchcase+mimetypes
- *
- * - version = '2.0' which introduces the 'profile' notion
- *   profile += name+label
- *
- * Profiles are kept in the order specified in 'items' entry if it exists.
- */
-static void
-read_item_action( NagpGConfProvider *provider, const gchar *path, NAObjectAction *action )
-{
-	static const gchar *thisfn = "nagp_gconf_provider_read_item_action";
-	gchar *uuid;
-	GSList *entries, *list_profiles, *ip;
-	GSList *order;
-	gchar *profile_path;
-
-	g_debug( "%s: provider=%p, path=%s, action=%p",
-			thisfn, ( void * ) provider, path, ( void * ) action );
-	g_return_if_fail( NA_IS_OBJECT_ACTION( action ));
-
-	uuid = na_gconf_utils_path_to_key( path );
-	na_object_set_id( action, uuid );
-	g_free( uuid );
-
-	entries = na_gconf_utils_get_entries( provider->private->gconf, path );
-	read_item_action_properties( provider, entries, action  );
-
-	order = na_object_item_get_items_string_list( NA_OBJECT_ITEM( action ));
-	list_profiles = na_gconf_utils_get_subdirs( provider->private->gconf, path );
-
-	if( list_profiles ){
-
-		/* read profiles in the specified order
-		 */
-		for( ip = order ; ip ; ip = ip->next ){
-			profile_path = gconf_concat_dir_and_key( path, ( gchar * ) ip->data );
-			read_item_action_profile( provider, action, profile_path );
-			list_profiles = na_utils_remove_from_string_list( list_profiles, profile_path );
-			g_free( profile_path );
-		}
-
-		/* read other profiles
-		 */
-		for( ip = list_profiles ; ip ; ip = ip->next ){
-			profile_path = g_strdup(( gchar * ) ip->data );
-			read_item_action_profile( provider, action, profile_path );
-			g_free( profile_path );
-		}
-
-	/* if there is no subdir, this may be a valid v1 or an invalid v2
-	 * at least try to read some properties
-	 */
-	} else {
-		read_item_action_properties_v1( provider, entries, action );
-	}
-
-	na_utils_free_string_list( order );
-	na_gconf_utils_free_subdirs( list_profiles );
-	na_gconf_utils_free_entries( entries );
-
-	na_object_action_set_readonly( action, !key_is_writable( provider, path ));
-}
-
-/*
- * set the item properties into the action, dealing with successive
- * versions
- */
-static void
-read_item_action_properties( NagpGConfProvider *provider, GSList *entries, NAObjectAction *action )
-{
-	gchar *version;
-	gboolean target_selection, target_background, target_toolbar;
-	gboolean toolbar_same_label;
-	gchar *toolbar_label;
-
-	read_object_item_properties( provider, entries, NA_OBJECT_ITEM( action ) );
-
-	if( na_gconf_utils_get_string_from_entries( entries, ACTION_VERSION_ENTRY, &version )){
-		na_object_action_set_version( action, version );
-		g_free( version );
-	}
-
-	if( na_gconf_utils_get_bool_from_entries( entries, OBJECT_ITEM_TARGET_SELECTION_ENTRY, &target_selection )){
-		na_object_action_set_target_selection( action, target_selection );
-	}
-
-	if( na_gconf_utils_get_bool_from_entries( entries, OBJECT_ITEM_TARGET_BACKGROUND_ENTRY, &target_background )){
-		na_object_action_set_target_background( action, target_background );
-	}
-
-	if( na_gconf_utils_get_bool_from_entries( entries, OBJECT_ITEM_TARGET_TOOLBAR_ENTRY, &target_toolbar )){
-		na_object_action_set_target_toolbar( action, target_toolbar );
-	}
-
-	if( na_gconf_utils_get_bool_from_entries( entries, OBJECT_ITEM_TOOLBAR_SAME_LABEL_ENTRY, &toolbar_same_label )){
-		na_object_action_toolbar_set_same_label( action, toolbar_same_label );
-
-	} else {
-		toolbar_same_label = na_object_action_toolbar_use_same_label( action );
-	}
-
-	if( na_gconf_utils_get_string_from_entries( entries, OBJECT_ITEM_TOOLBAR_LABEL_ENTRY, &toolbar_label )){
-		na_object_action_toolbar_set_label( action, toolbar_label );
-		g_free( toolbar_label );
-
-	} else if( toolbar_same_label ){
-		toolbar_label = na_object_get_label( action );
-		na_object_action_toolbar_set_label( action, toolbar_label );
-		g_free( toolbar_label );
-	}
-}
-
-/*
- * version is marked as less than "2.0"
- * we handle so only one profile, which is already loaded
- * action+= path+parameters+basenames+isdir+isfile+multiple+schemes
- * if version greater than "1.0", we have also matchcase+mimetypes
- */
-static void
-read_item_action_properties_v1( NagpGConfProvider *provider, GSList *entries, NAObjectAction *action )
-{
-	NAObjectProfile *profile = na_object_profile_new();
-
-	na_object_action_attach_profile( action, profile );
-
-	read_item_action_profile_properties( provider, entries, profile );
-}
-
-static void
-read_item_action_profile( NagpGConfProvider *provider, NAObjectAction *action, const gchar *path )
-{
-	NAObjectProfile *profile;
-	gchar *name;
-	GSList *entries;
-
-	g_return_if_fail( NA_IS_OBJECT_ACTION( action ));
-
-	profile = na_object_profile_new();
-
-	name = na_gconf_utils_path_to_key( path );
-	na_object_set_id( profile, name );
-	g_free( name );
-
-	entries = na_gconf_utils_get_entries( provider->private->gconf, path );
-	read_item_action_profile_properties( provider, entries, profile );
-	na_gconf_utils_free_entries( entries );
-
-	na_object_action_attach_profile( action, profile );
-}
-
-static void
-read_item_action_profile_properties( NagpGConfProvider *provider, GSList *entries, NAObjectProfile *profile )
-{
-	/*static const gchar *thisfn = "nagp_gconf_provider_read_item_action_profile_properties";*/
-	gchar *label, *path, *parameters;
-	GSList *basenames, *schemes, *mimetypes;
-	gboolean isfile, isdir, multiple, matchcase;
-	GSList *folders;
-
-	if( na_gconf_utils_get_string_from_entries( entries, ACTION_PROFILE_LABEL_ENTRY, &label )){
-		na_object_set_label( profile, label );
-		g_free( label );
-	}
-
-	if( na_gconf_utils_get_string_from_entries( entries, ACTION_PATH_ENTRY, &path )){
-		na_object_profile_set_path( profile, path );
-		g_free( path );
-	}
-
-	if( na_gconf_utils_get_string_from_entries( entries, ACTION_PARAMETERS_ENTRY, &parameters )){
-		na_object_profile_set_parameters( profile, parameters );
-		g_free( parameters );
-	}
-
-	if( na_gconf_utils_get_string_list_from_entries( entries, ACTION_BASENAMES_ENTRY, &basenames )){
-		na_object_profile_set_basenames( profile, basenames );
-		na_utils_free_string_list( basenames );
-	}
-
-	if( na_gconf_utils_get_bool_from_entries( entries, ACTION_ISFILE_ENTRY, &isfile )){
-		na_object_profile_set_isfile( profile, isfile );
-	}
-
-	if( na_gconf_utils_get_bool_from_entries( entries, ACTION_ISDIR_ENTRY, &isdir )){
-		na_object_profile_set_isdir( profile, isdir );
-	}
-
-	if( na_gconf_utils_get_bool_from_entries( entries, ACTION_MULTIPLE_ENTRY, &multiple )){
-		na_object_profile_set_multiple( profile, multiple );
-	}
-
-	if( na_gconf_utils_get_string_list_from_entries( entries, ACTION_SCHEMES_ENTRY, &schemes )){
-		na_object_profile_set_schemes( profile, schemes );
-		na_utils_free_string_list( schemes );
-	}
-
-	/* handle matchcase+mimetypes
-	 * note that default values for 1.0 version have been set
-	 * in na_object_profile_instance_init
-	 */
-	if( na_gconf_utils_get_bool_from_entries( entries, ACTION_MATCHCASE_ENTRY, &matchcase )){
-		na_object_profile_set_matchcase( profile, matchcase );
-	}
-
-	if( na_gconf_utils_get_string_list_from_entries( entries, ACTION_MIMETYPES_ENTRY, &mimetypes )){
-		na_object_profile_set_mimetypes( profile, mimetypes );
-		na_utils_free_string_list( mimetypes );
-	}
-
-	if( na_gconf_utils_get_string_list_from_entries( entries, ACTION_FOLDERS_ENTRY, &folders )){
-		na_object_profile_set_folders( profile, folders );
-		na_utils_free_string_list( folders );
-	}
-}
-
-static void
-read_item_menu( NagpGConfProvider *provider, const gchar *path, NAObjectMenu *menu )
-{
-	static const gchar *thisfn = "nagp_gconf_provider_read_item_menu";
-	gchar *uuid;
-	GSList *entries;
-
-	g_debug( "%s: provider=%p, path=%s, menu=%p",
-			thisfn, ( void * ) provider, path, ( void * ) menu );
-	g_return_if_fail( NA_IS_OBJECT_MENU( menu ));
-
-	uuid = na_gconf_utils_path_to_key( path );
-	na_object_set_id( menu, uuid );
-	g_free( uuid );
-
-	entries = na_gconf_utils_get_entries( provider->private->gconf, path );
-	read_item_menu_properties( provider, entries, menu  );
-	na_gconf_utils_free_entries( entries );
-}
-
-static void
-read_item_menu_properties( NagpGConfProvider *provider, GSList *entries, NAObjectMenu *menu )
-{
-	read_object_item_properties( provider, entries, NA_OBJECT_ITEM( menu ) );
-}
-
-/*
- * set the properties into the NAObjectItem
- */
-static void
-read_object_item_properties( NagpGConfProvider *provider, GSList *entries, NAObjectItem *item )
-{
-	static const gchar *thisfn = "nagp_gconf_provider_read_object_item_properties";
-	gchar *id, *label, *tooltip, *icon;
-	gboolean enabled;
-	GSList *subitems;
-
-	if( !na_gconf_utils_get_string_from_entries( entries, OBJECT_ITEM_LABEL_ENTRY, &label )){
-		id = na_object_get_id( item );
-		g_warning( "%s: no label found for NAObjectItem %s", thisfn, id );
-		g_free( id );
-		label = g_strdup( "" );
-	}
-	na_object_set_label( item, label );
-	g_free( label );
-
-	if( na_gconf_utils_get_string_from_entries( entries, OBJECT_ITEM_TOOLTIP_ENTRY, &tooltip )){
-		na_object_set_tooltip( item, tooltip );
-		g_free( tooltip );
-	}
-
-	if( na_gconf_utils_get_string_from_entries( entries, OBJECT_ITEM_ICON_ENTRY, &icon )){
-		na_object_set_icon( item, icon );
-		g_free( icon );
-	}
-
-	if( na_gconf_utils_get_bool_from_entries( entries, OBJECT_ITEM_ENABLED_ENTRY, &enabled )){
-		na_object_set_enabled( item, enabled );
-	}
-
-	if( na_gconf_utils_get_string_list_from_entries( entries, OBJECT_ITEM_LIST_ENTRY, &subitems )){
-		na_object_item_set_items_string_list( item, subitems );
-		na_utils_free_string_list( subitems );
-	}
-}
-
-static gboolean
-iio_provider_is_willing_to_write( const NAIIOProvider *provider )
-{
-	NagpGConfProvider *self;
-	gboolean willing_to = FALSE;
-
-	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), FALSE );
-	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), FALSE );
-	self = NAGP_GCONF_PROVIDER( provider );
-
-	/* TODO: nagp_gconf_provider_iio_provider_is_willing_to_write */
-	if( !self->private->dispose_has_run ){
-		willing_to = TRUE;
-	}
-
-	return( willing_to );
-}
-
-static gboolean
-iio_provider_is_writable( const NAIIOProvider *provider, const NAObjectItem *item )
-{
-	NagpGConfProvider *self;
-	gboolean willing_to = FALSE;
-
-	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), FALSE );
-	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), FALSE );
-	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), FALSE );
-	self = NAGP_GCONF_PROVIDER( provider );
-
-	/* TODO: nagp_gconf_provider_iio_provider_is_writable */
-	if( !self->private->dispose_has_run ){
-		willing_to = TRUE;
-	}
-
-	return( willing_to );
-}
-
-static guint
-iio_provider_write_item( const NAIIOProvider *provider, const NAObjectItem *item, GSList **messages )
-{
-	static const gchar *thisfn = "nagp_gconf_provider_iio_provider_write_item";
-	NagpGConfProvider *self;
-
-	g_debug( "%s: provider=%p, item=%p (%s), messages=%p",
-			thisfn, ( void * ) provider,
-			( void * ) item, G_OBJECT_TYPE_NAME( item ), ( void * ) messages );
-	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), NA_IIO_PROVIDER_PROGRAM_ERROR );
-	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), NA_IIO_PROVIDER_PROGRAM_ERROR );
-	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NA_IIO_PROVIDER_PROGRAM_ERROR );
-
-	self = NAGP_GCONF_PROVIDER( provider );
-
-	if( self->private->dispose_has_run ){
-		return( NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE );
-	}
-
-	if( NA_IS_OBJECT_ACTION( item )){
-		if( !write_item_action( self, NA_OBJECT_ACTION( item ), messages )){
-			return( NA_IIO_PROVIDER_WRITE_ERROR );
-		}
-	}
-
-	if( NA_IS_OBJECT_MENU( item )){
-		if( !write_item_menu( self, NA_OBJECT_MENU( item ), messages )){
-			return( NA_IIO_PROVIDER_WRITE_ERROR );
-		}
-	}
-
-	gconf_client_suggest_sync( self->private->gconf, NULL );
-
-	return( NA_IIO_PROVIDER_WRITE_OK );
-}
-
-static gboolean
-write_item_action( NagpGConfProvider *provider, const NAObjectAction *action, GSList **messages )
-{
-	gchar *uuid, *name;
-	gboolean ret;
-	GList *profiles, *ip;
-	NAObjectProfile *profile;
-
-	uuid = na_object_get_id( action );
-
-	ret =
-		write_object_item( provider, NA_OBJECT_ITEM( action ), messages ) &&
-		write_str( provider, uuid, NULL, ACTION_VERSION_ENTRY, na_object_action_get_version( action ), messages ) &&
-		write_bool( provider, uuid, NULL, OBJECT_ITEM_TARGET_SELECTION_ENTRY, na_object_action_is_target_selection( action ), messages ) &&
-		write_bool( provider, uuid, NULL, OBJECT_ITEM_TARGET_BACKGROUND_ENTRY, na_object_action_is_target_background( action ), messages ) &&
-		write_bool( provider, uuid, NULL, OBJECT_ITEM_TARGET_TOOLBAR_ENTRY, na_object_action_is_target_toolbar( action ), messages ) &&
-		write_bool( provider, uuid, NULL, OBJECT_ITEM_TOOLBAR_SAME_LABEL_ENTRY, na_object_action_toolbar_use_same_label( action ), messages ) &&
-		write_str( provider, uuid, NULL, OBJECT_ITEM_TOOLBAR_LABEL_ENTRY, na_object_action_toolbar_get_label( action ), messages ) &&
-		write_str( provider, uuid, NULL, OBJECT_ITEM_TYPE_ENTRY, g_strdup( OBJECT_ITEM_TYPE_ACTION ), messages );
-
-	profiles = na_object_get_items_list( action );
-
-	for( ip = profiles ; ip && ret ; ip = ip->next ){
-
-		profile = NA_OBJECT_PROFILE( ip->data );
-		name = na_object_get_id( profile );
-
-		ret =
-			write_str( provider, uuid, name, ACTION_PROFILE_LABEL_ENTRY, na_object_get_label( profile ), messages ) &&
-			write_str( provider, uuid, name, ACTION_PATH_ENTRY, na_object_profile_get_path( profile ), messages ) &&
-			write_str( provider, uuid, name, ACTION_PARAMETERS_ENTRY, na_object_profile_get_parameters( profile ), messages ) &&
-			write_list( provider, uuid, name, ACTION_BASENAMES_ENTRY, na_object_profile_get_basenames( profile ), messages ) &&
-			write_bool( provider, uuid, name, ACTION_MATCHCASE_ENTRY, na_object_profile_get_matchcase( profile ), messages ) &&
-			write_list( provider, uuid, name, ACTION_MIMETYPES_ENTRY, na_object_profile_get_mimetypes( profile ), messages ) &&
-			write_bool( provider, uuid, name, ACTION_ISFILE_ENTRY, na_object_profile_get_is_file( profile ), messages ) &&
-			write_bool( provider, uuid, name, ACTION_ISDIR_ENTRY, na_object_profile_get_is_dir( profile ), messages ) &&
-			write_bool( provider, uuid, name, ACTION_MULTIPLE_ENTRY, na_object_profile_get_multiple( profile ), messages ) &&
-			write_list( provider, uuid, name, ACTION_SCHEMES_ENTRY, na_object_profile_get_schemes( profile ), messages ) &&
-			write_list( provider, uuid, name, ACTION_FOLDERS_ENTRY, na_object_profile_get_folders( profile ), messages );
-
-		g_free( name );
-	}
-
-	g_free( uuid );
-
-	return( ret );
-}
-
-static gboolean
-write_item_menu( NagpGConfProvider *provider, const NAObjectMenu *menu, GSList **messages )
-{
-	gboolean ret;
-	gchar *uuid;
-
-	uuid = na_object_get_id( menu );
-
-	ret =
-		write_object_item( provider, NA_OBJECT_ITEM( menu ), messages ) &&
-		write_str( provider, uuid, NULL, OBJECT_ITEM_TYPE_ENTRY, g_strdup( OBJECT_ITEM_TYPE_MENU ), messages );
-
-	g_free( uuid );
-
-	return( ret );
-}
-
-static gboolean
-write_object_item( NagpGConfProvider *provider, const NAObjectItem *item, GSList **messages )
-{
-	gchar *uuid;
-	gboolean ret;
-
-	uuid = na_object_get_id( NA_OBJECT( item ));
-
-	ret =
-		write_str( provider, uuid, NULL, OBJECT_ITEM_LABEL_ENTRY, na_object_get_label( NA_OBJECT( item )), messages ) &&
-		write_str( provider, uuid, NULL, OBJECT_ITEM_TOOLTIP_ENTRY, na_object_get_tooltip( item ), messages ) &&
-		write_str( provider, uuid, NULL, OBJECT_ITEM_ICON_ENTRY, na_object_get_icon( item ), messages ) &&
-		write_bool( provider, uuid, NULL, OBJECT_ITEM_ENABLED_ENTRY, na_object_is_enabled( item ), messages ) &&
-		write_list( provider, uuid, NULL, OBJECT_ITEM_LIST_ENTRY, na_object_item_rebuild_items_list( item ), messages );
-
-	g_free( uuid );
-	return( ret );
-}
-
-/*
- * also delete the schema which may be directly attached to this action
- * cf. http://bugzilla.gnome.org/show_bug.cgi?id=325585
- */
-static guint
-iio_provider_delete_item( const NAIIOProvider *provider, const NAObjectItem *item, GSList **messages )
-{
-	static const gchar *thisfn = "nagp_gconf_provider_iio_provider_delete_item";
-	NagpGConfProvider *self;
-	guint ret;
-	gchar *uuid, *path;
-	GError *error = NULL;
-
-	g_debug( "%s: provider=%p, item=%p (%s), messages=%p",
-			thisfn, ( void * ) provider,
-			( void * ) item, G_OBJECT_TYPE_NAME( item ), ( void * ) messages );
-
-	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), NA_IIO_PROVIDER_PROGRAM_ERROR );
-	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), NA_IIO_PROVIDER_PROGRAM_ERROR );
-	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NA_IIO_PROVIDER_PROGRAM_ERROR );
-
-	self = NAGP_GCONF_PROVIDER( provider );
-
-	if( self->private->dispose_has_run ){
-		return( NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE );
-	}
-
-	ret = NA_IIO_PROVIDER_WRITE_OK;
-	uuid = na_object_get_id( NA_OBJECT( item ));
-
-	path = g_strdup_printf( "%s%s/%s", NAUTILUS_ACTIONS_GCONF_SCHEMASDIR, NA_GCONF_CONFIG_PATH, uuid );
-	gconf_client_recursive_unset( self->private->gconf, path, 0, &error );
-	if( error ){
-		g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
-		*messages = g_slist_append( *messages, g_strdup( error->message ));
-		g_error_free( error );
-		error = NULL;
-	}
-	g_free( path );
-
-
-	path = g_strdup_printf( "%s/%s", NA_GCONF_CONFIG_PATH, uuid );
-	if( !gconf_client_recursive_unset( self->private->gconf, path, 0, &error )){
-		g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
-		*messages = g_slist_append( *messages, g_strdup( error->message ));
-		g_error_free( error );
-		error = NULL;
-		ret = NA_IIO_PROVIDER_WRITE_ERROR;
-
-	} else {
-		gconf_client_suggest_sync( self->private->gconf, NULL );
-	}
-	g_free( path );
-
-	g_free( uuid );
-
-	return( ret );
-}
-
-/*
- * gconf_client_key_is_writable doesn't work as I expect: it returns
- * FALSE without error for our keys !
- * So I have to actually try a fake write to the key to get the real
- * writability status...
- *
- * TODO: having a NAPivot as Nautilus extension and another NAPivot in
- * the UI leads to a sort of notification loop: extension's pivot is
- * not aware of UI's one, and so get notifications from GConf, reloads
- * the list of actions, retrying to test the writability.
- * In the meanwhile, UI's pivot has reauthorized notifications, and is
- * notified of extension's pivot tests, and so on......
- *
- * -> Nautilus extension's pivot should not test for writability, as it
- *    uses actions as read-only, reloading the whole list when one
- *    action is modified ; this can break the loop
- *
- * -> the UI may use the pivot inside of Nautilus extension via a sort
- *    of API, falling back to its own pivot, when the extension is not
- *    present.
- */
-static gboolean
-key_is_writable( NagpGConfProvider *gconf, const gchar *path )
-{
-	/*static const gchar *thisfn = "nagp_gconf_provider_key_is_writable";
-	GError *error = NULL;
-
-	remove_gconf_watched_dir( gconf );
-
-	gboolean ret_gconf = gconf_client_key_is_writable( gconf->private->gconf, path, &error );
-	if( error ){
-		g_warning( "%s: gconf_client_key_is_writable: %s", thisfn, error->message );
-		g_error_free( error );
-		error = NULL;
-	}
-	gboolean ret_try = FALSE;
-	gchar *path_try = g_strdup_printf( "%s/%s", path, "fake_key" );
-	ret_try = gconf_client_set_string( gconf->private->gconf, path_try, "fake_value", &error );
-	if( error ){
-		g_warning( "%s: gconf_client_set_string: %s", thisfn, error->message );
-		g_error_free( error );
-		error = NULL;
-	}
-	if( ret_try ){
-		gconf_client_unset( gconf->private->gconf, path_try, NULL );
-	}
-	g_free( path_try );
-	g_debug( "%s: ret_gconf=%s, ret_try=%s", thisfn, ret_gconf ? "True":"False", ret_try ? "True":"False" );
-
-	install_gconf_watched_dir( gconf );
-	return( ret_try );*/
-
-	return( TRUE );
-}
-
-static gboolean
-write_str( NagpGConfProvider *provider, const gchar *uuid, const gchar *name, const gchar *key, gchar *value, GSList **messages )
-{
-	gchar *path;
-	gboolean ret;
-	gchar *msg;
-
-	if( name && strlen( name )){
-		path = g_strdup_printf( "%s/%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, name, key );
-	} else {
-		path = g_strdup_printf( "%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, key );
-	}
-
-	msg = NULL;
-	ret = na_gconf_utils_write_string( provider->private->gconf, path, value, &msg );
-	if( msg ){
-		*messages = g_slist_append( *messages, g_strdup( msg ));
-		g_free( msg );
-	}
-
-	g_free( value );
-	g_free( path );
-
-	return( ret );
-}
-
-static gboolean
-write_bool( NagpGConfProvider *provider, const gchar *uuid, const gchar *name, const gchar *key, gboolean value, GSList **messages )
-{
-	gboolean ret;
-	gchar *path;
-	gchar *msg;
-
-	if( name && strlen( name )){
-		path = g_strdup_printf( "%s/%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, name, key );
-	} else {
-		path = g_strdup_printf( "%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, key );
-	}
-
-	msg = NULL;
-	ret = na_gconf_utils_write_bool( provider->private->gconf, path, value, &msg );
-	if( msg ){
-		*messages = g_slist_append( *messages, g_strdup( msg ));
-		g_free( msg );
-	}
-
-	g_free( path );
-
-	return( ret );
-}
-
-static gboolean
-write_list( NagpGConfProvider *provider, const gchar *uuid, const gchar *name, const gchar *key, GSList *value, GSList **messages )
-{
-	gboolean ret;
-	gchar *path;
-	gchar *msg;
-
-	if( name && strlen( name )){
-		path = g_strdup_printf( "%s/%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, name, key );
-	} else {
-		path = g_strdup_printf( "%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, key );
-	}
-
-	msg = NULL;
-	ret = na_gconf_utils_write_string_list( provider->private->gconf, path, value, &msg );
-	if( msg ){
-		*messages = g_slist_append( *messages, g_strdup( msg ));
-		g_free( msg );
-	}
-
-	na_utils_free_string_list( value );
-	g_free( path );
-
-	return( ret );
-}
-
-/**
- * na_gconf_utils_get_subdirs:
- * @gconf: a  #GConfClient instance.
- * @path: a full path to be readen.
- *
- * Loads the subdirs of the given path.
- *
- * Returns: a GSList of full path subdirectories.
- *
- * The returned list should be na_gconf_utils_free_subdirs() by the
- * caller.
- */
-static GSList *
-na_gconf_utils_get_subdirs( GConfClient *gconf, const gchar *path )
-{
-	static const gchar *thisfn = "na_gconf_utils_get_subdirs";
-	GError *error = NULL;
-	GSList *list_subdirs;
-
-	list_subdirs = gconf_client_all_dirs( gconf, path, &error );
-
-	if( error ){
-		g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
-		g_error_free( error );
-		return(( GSList * ) NULL );
-	}
-
-	return( list_subdirs );
-}
-
-/**
- * na_gconf_utils_free_subdirs:
- * @subdirs: a list of subdirs as returned by na_gconf_utils_get_subdirs().
- *
- * Release the list of subdirs.
- */
-static void
-na_gconf_utils_free_subdirs( GSList *subdirs )
-{
-	na_utils_free_string_list( subdirs );
-}
-
-/**
- * na_gconf_utils_have_subdir:
- * @gconf: a  #GConfClient instance.
- * @path: a full path to be readen.
- *
- * Returns: %TRUE if the specified path has at least one subdirectory,
- * %FALSE else.
- */
-/*static gboolean
-na_gconf_utils_have_subdir( GConfClient *gconf, const gchar *path )
-{
-	GSList *listpath;
-	gboolean have_subdir;
-
-	listpath = na_gconf_utils_get_subdirs( gconf, path );
-	have_subdir = ( listpath && g_slist_length( listpath ));
-	na_gconf_utils_free_subdirs( listpath );
-
-	return( have_subdir );
-}*/
-
-/**
- * na_gconf_utils_have_entry:
- * @gconf: a  #GConfClient instance.
- * @path: the full path of a key.
- * @entry: the entry to be tested.
- *
- * Returns: %TRUE if the given @entry exists for the given @path,
- * %FALSE else.
- */
-static gboolean
-na_gconf_utils_have_entry( GConfClient *gconf, const gchar *path, const gchar *entry )
-{
-	static const gchar *thisfn = "na_gconf_utils_have_entry";
-	gboolean have_entry = FALSE;
-	GError *error = NULL;
-	gchar *key;
-	GConfValue *value;
-
-	key = g_strdup_printf( "%s/%s", path, entry );
-
-	value = gconf_client_get_without_default( gconf, key, &error );
-
-	if( error ){
-		g_warning( "%s: key=%s, error=%s", thisfn, key, error->message );
-		g_error_free( error );
-		if( value ){
-			gconf_value_free( value );
-			value = NULL;
-		}
-	}
-
-	if( value ){
-		have_entry = TRUE;
-		gconf_value_free( value );
-	}
-
-	g_free( key );
-
-	return( have_entry );
-}
diff --git a/nautilus-actions/io-provider-gconf/nagp-gconf-provider.h b/nautilus-actions/io-provider-gconf/nagp-gconf-provider.h
index 0030e35..7c06e56 100644
--- a/nautilus-actions/io-provider-gconf/nagp-gconf-provider.h
+++ b/nautilus-actions/io-provider-gconf/nagp-gconf-provider.h
@@ -46,6 +46,7 @@
 
 #include <glib.h>
 #include <glib-object.h>
+#include <gconf/gconf-client.h>
 
 G_BEGIN_DECLS
 
@@ -56,7 +57,17 @@ G_BEGIN_DECLS
 #define NAGP_IS_GCONF_PROVIDER_CLASS( klass )	( G_TYPE_CHECK_CLASS_TYPE(( klass ), NAGP_GCONF_PROVIDER_TYPE ))
 #define NAGP_GCONF_PROVIDER_GET_CLASS( object )	( G_TYPE_INSTANCE_GET_CLASS(( object ), NAGP_GCONF_PROVIDER_TYPE, NagpGConfProviderClass ))
 
-typedef struct NagpGConfProviderPrivate NagpGConfProviderPrivate;
+/* private instance data
+ */
+typedef struct NagpGConfProviderPrivate {
+	gboolean     dispose_has_run;
+	GConfClient *gconf;
+	GList       *monitors;
+	GTimeVal     last_event;
+	guint        event_source_id;
+	gchar       *last_triggered_id;
+}
+	NagpGConfProviderPrivate;
 
 typedef struct {
 	GObject                   parent;
diff --git a/nautilus-actions/io-provider-gconf/nagp-read.c b/nautilus-actions/io-provider-gconf/nagp-read.c
new file mode 100644
index 0000000..e68ffd8
--- /dev/null
+++ b/nautilus-actions/io-provider-gconf/nagp-read.c
@@ -0,0 +1,580 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 2 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 Library; see the file COPYING.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *   Frederic Ruaudel <grumz grumz net>
+ *   Rodrigo Moya <rodrigo gnome-db org>
+ *   Pierre Wieser <pwieser trychlos org>
+ *   ... and many others (see AUTHORS)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <nautilus-actions/api/na-iio-provider.h>
+#include <nautilus-actions/api/na-object-api.h>
+
+/* only possible because we are an internal plugin */
+#include <runtime/na-gconf-utils.h>
+
+#include "nagp-gconf-provider.h"
+#include "nagp-keys.h"
+#include "nagp-read.h"
+#include "nagp-write.h"
+
+static NAObjectItem  *read_item( NagpGConfProvider *provider, const gchar *path );
+static void           read_item_action( NagpGConfProvider *provider, const gchar *path, NAObjectAction *action );
+static void           read_item_action_properties( NagpGConfProvider *provider, GSList *entries, NAObjectAction *action );
+static void           read_item_action_properties_v1( NagpGConfProvider *gconf, GSList *entries, NAObjectAction *action );
+static void           read_item_action_profile( NagpGConfProvider *provider, NAObjectAction *action, const gchar *path );
+static void           read_item_action_profile_properties( NagpGConfProvider *provider, GSList *entries, NAObjectProfile *profile );
+static void           read_item_menu( NagpGConfProvider *provider, const gchar *path, NAObjectMenu *menu );
+static void           read_item_menu_properties( NagpGConfProvider *provider, GSList *entries, NAObjectMenu *menu );
+static void           read_object_item_properties( NagpGConfProvider *provider, GSList *entries, NAObjectItem *item );
+
+static GSList        *get_subdirs( GConfClient *gconf, const gchar *path );
+static void           free_subdirs( GSList *subdirs );
+static gboolean       has_entry( GConfClient *gconf, const gchar *path, const gchar *entry );
+static GSList        *remove_from_gslist( GSList *list, const gchar *str );
+static void           free_gslist( GSList *list );
+
+/*
+ * nagp_iio_provider_read_items:
+ *
+ * Note that whatever be the version of the readen action, it will be
+ * stored as a #NAObjectAction and its set of #NAObjectProfile of the same,
+ * latest, version of these classes.
+ */
+GList *
+nagp_iio_provider_read_items( const NAIIOProvider *provider, GSList **messages )
+{
+	static const gchar *thisfn = "nagp_gconf_provider_iio_provider_read_items";
+	NagpGConfProvider *self;
+	GList *items_list = NULL;
+	GSList *listpath, *ip;
+	NAObjectItem *item;
+
+	g_debug( "%s: provider=%p, messages=%p", thisfn, ( void * ) provider, ( void * ) messages );
+
+	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), NULL );
+	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), NULL );
+	self = NAGP_GCONF_PROVIDER( provider );
+
+	if( !self->private->dispose_has_run ){
+
+		listpath = get_subdirs( self->private->gconf, NA_GCONF_CONFIG_PATH );
+
+		for( ip = listpath ; ip ; ip = ip->next ){
+
+			const gchar *path = ( const gchar * ) ip->data;
+			g_debug( "path=%s", path );
+			item = read_item( self, path );
+			if( item ){
+				items_list = g_list_prepend( items_list, item );
+			}
+		}
+
+		free_subdirs( listpath );
+	}
+
+	return( items_list );
+}
+
+static NAObjectItem *
+read_item( NagpGConfProvider *provider, const gchar *path )
+{
+	static const gchar *thisfn = "nagp_gconf_provider_read_item";
+	NAObjectItem *item;
+	gboolean have_type;
+	gchar *full_path;
+	gchar *type;
+
+	g_debug( "%s: provider=%p, path=%s", thisfn, ( void * ) provider, path );
+	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), NULL );
+	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), NULL );
+	g_return_val_if_fail( !provider->private->dispose_has_run, NULL );
+
+	have_type = has_entry( provider->private->gconf, path, OBJECT_ITEM_TYPE_ENTRY );
+	full_path = gconf_concat_dir_and_key( path, OBJECT_ITEM_TYPE_ENTRY );
+	type = na_gconf_utils_read_string( provider->private->gconf, full_path, TRUE, OBJECT_ITEM_TYPE_ACTION );
+	g_free( full_path );
+	item = NULL;
+
+	/* a menu has a type='Menu'
+	 */
+	if( have_type && !strcmp( type, OBJECT_ITEM_TYPE_MENU )){
+		item = NA_OBJECT_ITEM( na_object_menu_new());
+		read_item_menu( provider, path, NA_OBJECT_MENU( item ));
+
+	/* else this should be an action (no type, or type='Action')
+	 */
+	} else if( !have_type || !strcmp( type, OBJECT_ITEM_TYPE_ACTION )){
+		item = NA_OBJECT_ITEM( na_object_action_new());
+		read_item_action( provider, path, NA_OBJECT_ACTION( item ));
+
+	} else {
+		g_warning( "%s: unknown type '%s' at %s", thisfn, type, path );
+	}
+
+	g_free( type );
+
+	return( item );
+}
+
+/*
+ * load and set the properties of the specified action
+ * at least we must have a label, as all other entries can have
+ * suitable default values
+ *
+ * we have to deal with successive versions of action schema :
+ *
+ * - version = '1.0'
+ *   action+= uuid+label+tooltip+icon
+ *   action+= path+parameters+basenames+isdir+isfile+multiple+schemes
+ *
+ * - version > '1.0'
+ *   action+= matchcase+mimetypes
+ *
+ * - version = '2.0' which introduces the 'profile' notion
+ *   profile += name+label
+ *
+ * Profiles are kept in the order specified in 'items' entry if it exists.
+ */
+static void
+read_item_action( NagpGConfProvider *provider, const gchar *path, NAObjectAction *action )
+{
+	static const gchar *thisfn = "nagp_gconf_provider_read_item_action";
+	gchar *uuid;
+	GSList *entries, *list_profiles, *ip;
+	GSList *order;
+	gchar *profile_path;
+
+	g_debug( "%s: provider=%p, path=%s, action=%p",
+			thisfn, ( void * ) provider, path, ( void * ) action );
+	g_return_if_fail( NA_IS_OBJECT_ACTION( action ));
+
+	uuid = na_gconf_utils_path_to_key( path );
+	na_object_set_id( action, uuid );
+	g_free( uuid );
+
+	entries = na_gconf_utils_get_entries( provider->private->gconf, path );
+	read_item_action_properties( provider, entries, action  );
+
+	order = na_object_item_get_items_string_list( NA_OBJECT_ITEM( action ));
+	list_profiles = get_subdirs( provider->private->gconf, path );
+
+	if( list_profiles ){
+
+		/* read profiles in the specified order
+		 */
+		for( ip = order ; ip ; ip = ip->next ){
+			profile_path = gconf_concat_dir_and_key( path, ( gchar * ) ip->data );
+			read_item_action_profile( provider, action, profile_path );
+			list_profiles = remove_from_gslist( list_profiles, profile_path );
+			g_free( profile_path );
+		}
+
+		/* read other profiles
+		 */
+		for( ip = list_profiles ; ip ; ip = ip->next ){
+			profile_path = g_strdup(( gchar * ) ip->data );
+			read_item_action_profile( provider, action, profile_path );
+			g_free( profile_path );
+		}
+
+	/* if there is no subdir, this may be a valid v1 or an invalid v2
+	 * at least try to read some properties
+	 */
+	} else {
+		read_item_action_properties_v1( provider, entries, action );
+	}
+
+	free_gslist( order );
+	free_subdirs( list_profiles );
+	na_gconf_utils_free_entries( entries );
+
+	na_object_action_set_readonly( action, !nagp_key_is_writable( provider, path ));
+}
+
+/*
+ * set the item properties into the action, dealing with successive
+ * versions
+ */
+static void
+read_item_action_properties( NagpGConfProvider *provider, GSList *entries, NAObjectAction *action )
+{
+	gchar *version;
+	gboolean target_selection, target_background, target_toolbar;
+	gboolean toolbar_same_label;
+	gchar *toolbar_label;
+
+	read_object_item_properties( provider, entries, NA_OBJECT_ITEM( action ) );
+
+	if( na_gconf_utils_get_string_from_entries( entries, ACTION_VERSION_ENTRY, &version )){
+		na_object_action_set_version( action, version );
+		g_free( version );
+	}
+
+	if( na_gconf_utils_get_bool_from_entries( entries, OBJECT_ITEM_TARGET_SELECTION_ENTRY, &target_selection )){
+		na_object_action_set_target_selection( action, target_selection );
+	}
+
+	if( na_gconf_utils_get_bool_from_entries( entries, OBJECT_ITEM_TARGET_BACKGROUND_ENTRY, &target_background )){
+		na_object_action_set_target_background( action, target_background );
+	}
+
+	if( na_gconf_utils_get_bool_from_entries( entries, OBJECT_ITEM_TARGET_TOOLBAR_ENTRY, &target_toolbar )){
+		na_object_action_set_target_toolbar( action, target_toolbar );
+	}
+
+	if( na_gconf_utils_get_bool_from_entries( entries, OBJECT_ITEM_TOOLBAR_SAME_LABEL_ENTRY, &toolbar_same_label )){
+		na_object_action_toolbar_set_same_label( action, toolbar_same_label );
+
+	} else {
+		toolbar_same_label = na_object_action_toolbar_use_same_label( action );
+	}
+
+	if( na_gconf_utils_get_string_from_entries( entries, OBJECT_ITEM_TOOLBAR_LABEL_ENTRY, &toolbar_label )){
+		na_object_action_toolbar_set_label( action, toolbar_label );
+		g_free( toolbar_label );
+
+	} else if( toolbar_same_label ){
+		toolbar_label = na_object_get_label( action );
+		na_object_action_toolbar_set_label( action, toolbar_label );
+		g_free( toolbar_label );
+	}
+}
+
+/*
+ * version is marked as less than "2.0"
+ * we handle so only one profile, which is already loaded
+ * action+= path+parameters+basenames+isdir+isfile+multiple+schemes
+ * if version greater than "1.0", we have also matchcase+mimetypes
+ */
+static void
+read_item_action_properties_v1( NagpGConfProvider *provider, GSList *entries, NAObjectAction *action )
+{
+	NAObjectProfile *profile = na_object_profile_new();
+
+	na_object_action_attach_profile( action, profile );
+
+	read_item_action_profile_properties( provider, entries, profile );
+}
+
+static void
+read_item_action_profile( NagpGConfProvider *provider, NAObjectAction *action, const gchar *path )
+{
+	NAObjectProfile *profile;
+	gchar *name;
+	GSList *entries;
+
+	g_return_if_fail( NA_IS_OBJECT_ACTION( action ));
+
+	profile = na_object_profile_new();
+
+	name = na_gconf_utils_path_to_key( path );
+	na_object_set_id( profile, name );
+	g_free( name );
+
+	entries = na_gconf_utils_get_entries( provider->private->gconf, path );
+	read_item_action_profile_properties( provider, entries, profile );
+	na_gconf_utils_free_entries( entries );
+
+	na_object_action_attach_profile( action, profile );
+}
+
+static void
+read_item_action_profile_properties( NagpGConfProvider *provider, GSList *entries, NAObjectProfile *profile )
+{
+	/*static const gchar *thisfn = "nagp_gconf_provider_read_item_action_profile_properties";*/
+	gchar *label, *path, *parameters;
+	GSList *basenames, *schemes, *mimetypes;
+	gboolean isfile, isdir, multiple, matchcase;
+	GSList *folders;
+
+	if( na_gconf_utils_get_string_from_entries( entries, ACTION_PROFILE_LABEL_ENTRY, &label )){
+		na_object_set_label( profile, label );
+		g_free( label );
+	}
+
+	if( na_gconf_utils_get_string_from_entries( entries, ACTION_PATH_ENTRY, &path )){
+		na_object_profile_set_path( profile, path );
+		g_free( path );
+	}
+
+	if( na_gconf_utils_get_string_from_entries( entries, ACTION_PARAMETERS_ENTRY, &parameters )){
+		na_object_profile_set_parameters( profile, parameters );
+		g_free( parameters );
+	}
+
+	if( na_gconf_utils_get_string_list_from_entries( entries, ACTION_BASENAMES_ENTRY, &basenames )){
+		na_object_profile_set_basenames( profile, basenames );
+		free_gslist( basenames );
+	}
+
+	if( na_gconf_utils_get_bool_from_entries( entries, ACTION_ISFILE_ENTRY, &isfile )){
+		na_object_profile_set_isfile( profile, isfile );
+	}
+
+	if( na_gconf_utils_get_bool_from_entries( entries, ACTION_ISDIR_ENTRY, &isdir )){
+		na_object_profile_set_isdir( profile, isdir );
+	}
+
+	if( na_gconf_utils_get_bool_from_entries( entries, ACTION_MULTIPLE_ENTRY, &multiple )){
+		na_object_profile_set_multiple( profile, multiple );
+	}
+
+	if( na_gconf_utils_get_string_list_from_entries( entries, ACTION_SCHEMES_ENTRY, &schemes )){
+		na_object_profile_set_schemes( profile, schemes );
+		free_gslist( schemes );
+	}
+
+	/* handle matchcase+mimetypes
+	 * note that default values for 1.0 version have been set
+	 * in na_object_profile_instance_init
+	 */
+	if( na_gconf_utils_get_bool_from_entries( entries, ACTION_MATCHCASE_ENTRY, &matchcase )){
+		na_object_profile_set_matchcase( profile, matchcase );
+	}
+
+	if( na_gconf_utils_get_string_list_from_entries( entries, ACTION_MIMETYPES_ENTRY, &mimetypes )){
+		na_object_profile_set_mimetypes( profile, mimetypes );
+		free_gslist( mimetypes );
+	}
+
+	if( na_gconf_utils_get_string_list_from_entries( entries, ACTION_FOLDERS_ENTRY, &folders )){
+		na_object_profile_set_folders( profile, folders );
+		free_gslist( folders );
+	}
+}
+
+static void
+read_item_menu( NagpGConfProvider *provider, const gchar *path, NAObjectMenu *menu )
+{
+	static const gchar *thisfn = "nagp_gconf_provider_read_item_menu";
+	gchar *uuid;
+	GSList *entries;
+
+	g_debug( "%s: provider=%p, path=%s, menu=%p",
+			thisfn, ( void * ) provider, path, ( void * ) menu );
+	g_return_if_fail( NA_IS_OBJECT_MENU( menu ));
+
+	uuid = na_gconf_utils_path_to_key( path );
+	na_object_set_id( menu, uuid );
+	g_free( uuid );
+
+	entries = na_gconf_utils_get_entries( provider->private->gconf, path );
+	read_item_menu_properties( provider, entries, menu  );
+	na_gconf_utils_free_entries( entries );
+}
+
+static void
+read_item_menu_properties( NagpGConfProvider *provider, GSList *entries, NAObjectMenu *menu )
+{
+	read_object_item_properties( provider, entries, NA_OBJECT_ITEM( menu ) );
+}
+
+/*
+ * set the properties into the NAObjectItem
+ */
+static void
+read_object_item_properties( NagpGConfProvider *provider, GSList *entries, NAObjectItem *item )
+{
+	static const gchar *thisfn = "nagp_gconf_provider_read_object_item_properties";
+	gchar *id, *label, *tooltip, *icon;
+	gboolean enabled;
+	GSList *subitems;
+
+	if( !na_gconf_utils_get_string_from_entries( entries, OBJECT_ITEM_LABEL_ENTRY, &label )){
+		id = na_object_get_id( item );
+		g_warning( "%s: no label found for NAObjectItem %s", thisfn, id );
+		g_free( id );
+		label = g_strdup( "" );
+	}
+	na_object_set_label( item, label );
+	g_free( label );
+
+	if( na_gconf_utils_get_string_from_entries( entries, OBJECT_ITEM_TOOLTIP_ENTRY, &tooltip )){
+		na_object_set_tooltip( item, tooltip );
+		g_free( tooltip );
+	}
+
+	if( na_gconf_utils_get_string_from_entries( entries, OBJECT_ITEM_ICON_ENTRY, &icon )){
+		na_object_set_icon( item, icon );
+		g_free( icon );
+	}
+
+	if( na_gconf_utils_get_bool_from_entries( entries, OBJECT_ITEM_ENABLED_ENTRY, &enabled )){
+		na_object_set_enabled( item, enabled );
+	}
+
+	if( na_gconf_utils_get_string_list_from_entries( entries, OBJECT_ITEM_LIST_ENTRY, &subitems )){
+		na_object_item_set_items_string_list( item, subitems );
+		free_gslist( subitems );
+	}
+}
+
+/**
+ * get_subdirs:
+ * @gconf: a  #GConfClient instance.
+ * @path: a full path to be readen.
+ *
+ * Loads the subdirs of the given path.
+ *
+ * Returns: a GSList of full path subdirectories.
+ *
+ * The returned list should be free_subdirs() by the
+ * caller.
+ */
+static GSList *
+get_subdirs( GConfClient *gconf, const gchar *path )
+{
+	static const gchar *thisfn = "get_subdirs";
+	GError *error = NULL;
+	GSList *list_subdirs;
+
+	list_subdirs = gconf_client_all_dirs( gconf, path, &error );
+
+	if( error ){
+		g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
+		g_error_free( error );
+		return(( GSList * ) NULL );
+	}
+
+	return( list_subdirs );
+}
+
+/**
+ * free_subdirs:
+ * @subdirs: a list of subdirs as returned by get_subdirs().
+ *
+ * Release the list of subdirs.
+ */
+static void
+free_subdirs( GSList *subdirs )
+{
+	free_gslist( subdirs );
+}
+
+/**
+ * na_gconf_utils_have_subdir:
+ * @gconf: a  #GConfClient instance.
+ * @path: a full path to be readen.
+ *
+ * Returns: %TRUE if the specified path has at least one subdirectory,
+ * %FALSE else.
+ */
+/*static gboolean
+na_gconf_utils_have_subdir( GConfClient *gconf, const gchar *path )
+{
+	GSList *listpath;
+	gboolean have_subdir;
+
+	listpath = get_subdirs( gconf, path );
+	have_subdir = ( listpath && g_slist_length( listpath ));
+	free_subdirs( listpath );
+
+	return( have_subdir );
+}*/
+
+/**
+ * has_entry:
+ * @gconf: a  #GConfClient instance.
+ * @path: the full path of a key.
+ * @entry: the entry to be tested.
+ *
+ * Returns: %TRUE if the given @entry exists for the given @path,
+ * %FALSE else.
+ */
+static gboolean
+has_entry( GConfClient *gconf, const gchar *path, const gchar *entry )
+{
+	static const gchar *thisfn = "has_entry";
+	gboolean have_entry = FALSE;
+	GError *error = NULL;
+	gchar *key;
+	GConfValue *value;
+
+	key = g_strdup_printf( "%s/%s", path, entry );
+
+	value = gconf_client_get_without_default( gconf, key, &error );
+
+	if( error ){
+		g_warning( "%s: key=%s, error=%s", thisfn, key, error->message );
+		g_error_free( error );
+		if( value ){
+			gconf_value_free( value );
+			value = NULL;
+		}
+	}
+
+	if( value ){
+		have_entry = TRUE;
+		gconf_value_free( value );
+	}
+
+	g_free( key );
+
+	return( have_entry );
+}
+
+/*
+ * remove_from_gslist:
+ * @list: the GSList to be updated.
+ * @str: the string to be removed.
+ *
+ * Removes from the @list the item which has a string which is equal to
+ * @str.
+ *
+ * Returns: the new @list start position.
+ */
+static GSList *
+remove_from_gslist( GSList *list, const gchar *str )
+{
+	GSList *is;
+
+	for( is = list ; is ; is = is->next ){
+		const gchar *istr = ( const gchar * ) is->data;
+		if( !g_utf8_collate( str, istr )){
+			g_free( is->data );
+			list = g_slist_delete_link( list, is );
+			break;
+		}
+	}
+
+	return( list );
+}
+
+/*
+ * free_gslist:
+ * @list: the GSList to be freed.
+ *
+ * Frees a GSList of strings.
+ */
+static void
+free_gslist( GSList *list )
+{
+	g_slist_foreach( list, ( GFunc ) g_free, NULL );
+	g_slist_free( list );
+}
diff --git a/nautilus-actions/io-provider-gconf/nagp-read.h b/nautilus-actions/io-provider-gconf/nagp-read.h
new file mode 100644
index 0000000..9dcdc8d
--- /dev/null
+++ b/nautilus-actions/io-provider-gconf/nagp-read.h
@@ -0,0 +1,55 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 2 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 Library; see the file COPYING.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *   Frederic Ruaudel <grumz grumz net>
+ *   Rodrigo Moya <rodrigo gnome-db org>
+ *   Pierre Wieser <pwieser trychlos org>
+ *   ... and many others (see AUTHORS)
+ */
+
+#ifndef __NAGP_READ_H__
+#define __NAGP_READ_H__
+
+/**
+ * SECTION: nagp_gconf_provider
+ * @short_description: #NagpGConfProvider class definition.
+ * @include: na-gconf-provider.h
+ *
+ * This class manages the GConf I/O storage subsystem, or, in other words,
+ * the GConf subsystem as an NAIIOProvider. As this, it should only be
+ * used through the NAIIOProvider interface.
+ *
+ * #NagpGConfProvider uses #NAGConfMonitor to watch at the configuration
+ * tree. Modifications are notified to the NAIIOProvider interface.
+ */
+
+#include <nautilus-actions/api/na-iio-provider.h>
+
+G_BEGIN_DECLS
+
+GList *nagp_iio_provider_read_items( const NAIIOProvider *provider, GSList **messages );
+
+G_END_DECLS
+
+#endif /* __NAGP_READ_H__ */
diff --git a/nautilus-actions/io-provider-gconf/nagp-write.c b/nautilus-actions/io-provider-gconf/nagp-write.c
new file mode 100644
index 0000000..93ea94a
--- /dev/null
+++ b/nautilus-actions/io-provider-gconf/nagp-write.c
@@ -0,0 +1,419 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 2 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 Library; see the file COPYING.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *   Frederic Ruaudel <grumz grumz net>
+ *   Rodrigo Moya <rodrigo gnome-db org>
+ *   Pierre Wieser <pwieser trychlos org>
+ *   ... and many others (see AUTHORS)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* only possible because we are an internal plugin */
+#include <runtime/na-gconf-utils.h>
+
+#include "nagp-gconf-provider.h"
+#include "nagp-write.h"
+#include "nagp-keys.h"
+
+static gboolean       write_item_action( NagpGConfProvider *gconf, const NAObjectAction *action, GSList **message );
+static gboolean       write_item_menu( NagpGConfProvider *gconf, const NAObjectMenu *menu, GSList **message );
+static gboolean       write_object_item( NagpGConfProvider *gconf, const NAObjectItem *item, GSList **message );
+
+static gboolean       write_str( NagpGConfProvider *gconf, const gchar *uuid, const gchar *name, const gchar *key, gchar *value, GSList **message );
+static gboolean       write_bool( NagpGConfProvider *gconf, const gchar *uuid, const gchar *name, const gchar *key, gboolean value, GSList **message );
+static gboolean       write_list( NagpGConfProvider *gconf, const gchar *uuid, const gchar *name, const gchar *key, GSList *value, GSList **message );
+static void           free_gslist( GSList *list );
+
+/*
+ *
+ */
+gboolean
+nagp_iio_provider_is_willing_to_write( const NAIIOProvider *provider )
+{
+	NagpGConfProvider *self;
+	gboolean willing_to = FALSE;
+
+	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), FALSE );
+	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), FALSE );
+	self = NAGP_GCONF_PROVIDER( provider );
+
+	/* TODO: nagp_gconf_provider_iio_provider_is_willing_to_write */
+	if( !self->private->dispose_has_run ){
+		willing_to = TRUE;
+	}
+
+	return( willing_to );
+}
+
+/*
+ *
+ */
+gboolean
+nagp_iio_provider_is_writable( const NAIIOProvider *provider, const NAObjectItem *item )
+{
+	NagpGConfProvider *self;
+	gboolean willing_to = FALSE;
+
+	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), FALSE );
+	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), FALSE );
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), FALSE );
+	self = NAGP_GCONF_PROVIDER( provider );
+
+	/* TODO: nagp_gconf_provider_iio_provider_is_writable */
+	if( !self->private->dispose_has_run ){
+		willing_to = TRUE;
+	}
+
+	return( willing_to );
+}
+
+/*
+ *
+ */
+guint
+nagp_iio_provider_write_item( const NAIIOProvider *provider, const NAObjectItem *item, GSList **messages )
+{
+	static const gchar *thisfn = "nagp_gconf_provider_iio_provider_write_item";
+	NagpGConfProvider *self;
+
+	g_debug( "%s: provider=%p, item=%p (%s), messages=%p",
+			thisfn, ( void * ) provider,
+			( void * ) item, G_OBJECT_TYPE_NAME( item ), ( void * ) messages );
+	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+
+	self = NAGP_GCONF_PROVIDER( provider );
+
+	if( self->private->dispose_has_run ){
+		return( NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE );
+	}
+
+	if( NA_IS_OBJECT_ACTION( item )){
+		if( !write_item_action( self, NA_OBJECT_ACTION( item ), messages )){
+			return( NA_IIO_PROVIDER_WRITE_ERROR );
+		}
+	}
+
+	if( NA_IS_OBJECT_MENU( item )){
+		if( !write_item_menu( self, NA_OBJECT_MENU( item ), messages )){
+			return( NA_IIO_PROVIDER_WRITE_ERROR );
+		}
+	}
+
+	gconf_client_suggest_sync( self->private->gconf, NULL );
+
+	return( NA_IIO_PROVIDER_WRITE_OK );
+}
+
+static gboolean
+write_item_action( NagpGConfProvider *provider, const NAObjectAction *action, GSList **messages )
+{
+	gchar *uuid, *name;
+	gboolean ret;
+	GList *profiles, *ip;
+	NAObjectProfile *profile;
+
+	uuid = na_object_get_id( action );
+
+	ret =
+		write_object_item( provider, NA_OBJECT_ITEM( action ), messages ) &&
+		write_str( provider, uuid, NULL, ACTION_VERSION_ENTRY, na_object_action_get_version( action ), messages ) &&
+		write_bool( provider, uuid, NULL, OBJECT_ITEM_TARGET_SELECTION_ENTRY, na_object_action_is_target_selection( action ), messages ) &&
+		write_bool( provider, uuid, NULL, OBJECT_ITEM_TARGET_BACKGROUND_ENTRY, na_object_action_is_target_background( action ), messages ) &&
+		write_bool( provider, uuid, NULL, OBJECT_ITEM_TARGET_TOOLBAR_ENTRY, na_object_action_is_target_toolbar( action ), messages ) &&
+		write_bool( provider, uuid, NULL, OBJECT_ITEM_TOOLBAR_SAME_LABEL_ENTRY, na_object_action_toolbar_use_same_label( action ), messages ) &&
+		write_str( provider, uuid, NULL, OBJECT_ITEM_TOOLBAR_LABEL_ENTRY, na_object_action_toolbar_get_label( action ), messages ) &&
+		write_str( provider, uuid, NULL, OBJECT_ITEM_TYPE_ENTRY, g_strdup( OBJECT_ITEM_TYPE_ACTION ), messages );
+
+	profiles = na_object_get_items_list( action );
+
+	for( ip = profiles ; ip && ret ; ip = ip->next ){
+
+		profile = NA_OBJECT_PROFILE( ip->data );
+		name = na_object_get_id( profile );
+
+		ret =
+			write_str( provider, uuid, name, ACTION_PROFILE_LABEL_ENTRY, na_object_get_label( profile ), messages ) &&
+			write_str( provider, uuid, name, ACTION_PATH_ENTRY, na_object_profile_get_path( profile ), messages ) &&
+			write_str( provider, uuid, name, ACTION_PARAMETERS_ENTRY, na_object_profile_get_parameters( profile ), messages ) &&
+			write_list( provider, uuid, name, ACTION_BASENAMES_ENTRY, na_object_profile_get_basenames( profile ), messages ) &&
+			write_bool( provider, uuid, name, ACTION_MATCHCASE_ENTRY, na_object_profile_get_matchcase( profile ), messages ) &&
+			write_list( provider, uuid, name, ACTION_MIMETYPES_ENTRY, na_object_profile_get_mimetypes( profile ), messages ) &&
+			write_bool( provider, uuid, name, ACTION_ISFILE_ENTRY, na_object_profile_get_is_file( profile ), messages ) &&
+			write_bool( provider, uuid, name, ACTION_ISDIR_ENTRY, na_object_profile_get_is_dir( profile ), messages ) &&
+			write_bool( provider, uuid, name, ACTION_MULTIPLE_ENTRY, na_object_profile_get_multiple( profile ), messages ) &&
+			write_list( provider, uuid, name, ACTION_SCHEMES_ENTRY, na_object_profile_get_schemes( profile ), messages ) &&
+			write_list( provider, uuid, name, ACTION_FOLDERS_ENTRY, na_object_profile_get_folders( profile ), messages );
+
+		g_free( name );
+	}
+
+	g_free( uuid );
+
+	return( ret );
+}
+
+static gboolean
+write_item_menu( NagpGConfProvider *provider, const NAObjectMenu *menu, GSList **messages )
+{
+	gboolean ret;
+	gchar *uuid;
+
+	uuid = na_object_get_id( menu );
+
+	ret =
+		write_object_item( provider, NA_OBJECT_ITEM( menu ), messages ) &&
+		write_str( provider, uuid, NULL, OBJECT_ITEM_TYPE_ENTRY, g_strdup( OBJECT_ITEM_TYPE_MENU ), messages );
+
+	g_free( uuid );
+
+	return( ret );
+}
+
+static gboolean
+write_object_item( NagpGConfProvider *provider, const NAObjectItem *item, GSList **messages )
+{
+	gchar *uuid;
+	gboolean ret;
+
+	uuid = na_object_get_id( NA_OBJECT( item ));
+
+	ret =
+		write_str( provider, uuid, NULL, OBJECT_ITEM_LABEL_ENTRY, na_object_get_label( NA_OBJECT( item )), messages ) &&
+		write_str( provider, uuid, NULL, OBJECT_ITEM_TOOLTIP_ENTRY, na_object_get_tooltip( item ), messages ) &&
+		write_str( provider, uuid, NULL, OBJECT_ITEM_ICON_ENTRY, na_object_get_icon( item ), messages ) &&
+		write_bool( provider, uuid, NULL, OBJECT_ITEM_ENABLED_ENTRY, na_object_is_enabled( item ), messages ) &&
+		write_list( provider, uuid, NULL, OBJECT_ITEM_LIST_ENTRY, na_object_item_rebuild_items_list( item ), messages );
+
+	g_free( uuid );
+	return( ret );
+}
+
+/*
+ * also delete the schema which may be directly attached to this action
+ * cf. http://bugzilla.gnome.org/show_bug.cgi?id=325585
+ */
+guint
+nagp_iio_provider_delete_item( const NAIIOProvider *provider, const NAObjectItem *item, GSList **messages )
+{
+	static const gchar *thisfn = "nagp_gconf_provider_iio_provider_delete_item";
+	NagpGConfProvider *self;
+	guint ret;
+	gchar *uuid, *path;
+	GError *error = NULL;
+
+	g_debug( "%s: provider=%p, item=%p (%s), messages=%p",
+			thisfn, ( void * ) provider,
+			( void * ) item, G_OBJECT_TYPE_NAME( item ), ( void * ) messages );
+
+	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+
+	self = NAGP_GCONF_PROVIDER( provider );
+
+	if( self->private->dispose_has_run ){
+		return( NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE );
+	}
+
+	ret = NA_IIO_PROVIDER_WRITE_OK;
+	uuid = na_object_get_id( NA_OBJECT( item ));
+
+	path = g_strdup_printf( "%s%s/%s", NAUTILUS_ACTIONS_GCONF_SCHEMASDIR, NA_GCONF_CONFIG_PATH, uuid );
+	gconf_client_recursive_unset( self->private->gconf, path, 0, &error );
+	if( error ){
+		g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
+		*messages = g_slist_append( *messages, g_strdup( error->message ));
+		g_error_free( error );
+		error = NULL;
+	}
+	g_free( path );
+
+
+	path = g_strdup_printf( "%s/%s", NA_GCONF_CONFIG_PATH, uuid );
+	if( !gconf_client_recursive_unset( self->private->gconf, path, 0, &error )){
+		g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
+		*messages = g_slist_append( *messages, g_strdup( error->message ));
+		g_error_free( error );
+		error = NULL;
+		ret = NA_IIO_PROVIDER_WRITE_ERROR;
+
+	} else {
+		gconf_client_suggest_sync( self->private->gconf, NULL );
+	}
+	g_free( path );
+
+	g_free( uuid );
+
+	return( ret );
+}
+
+/*
+ * gconf_client_key_is_writable doesn't work as I expect: it returns
+ * FALSE without error for our keys !
+ * So I have to actually try a fake write to the key to get the real
+ * writability status...
+ *
+ * TODO: having a NAPivot as Nautilus extension and another NAPivot in
+ * the UI leads to a sort of notification loop: extension's pivot is
+ * not aware of UI's one, and so get notifications from GConf, reloads
+ * the list of actions, retrying to test the writability.
+ * In the meanwhile, UI's pivot has reauthorized notifications, and is
+ * notified of extension's pivot tests, and so on......
+ *
+ * -> Nautilus extension's pivot should not test for writability, as it
+ *    uses actions as read-only, reloading the whole list when one
+ *    action is modified ; this can break the loop
+ *
+ * -> the UI may use the pivot inside of Nautilus extension via a sort
+ *    of API, falling back to its own pivot, when the extension is not
+ *    present.
+ */
+gboolean
+nagp_key_is_writable( NagpGConfProvider *gconf, const gchar *path )
+{
+	/*static const gchar *thisfn = "nagp_gconf_provider_key_is_writable";
+	GError *error = NULL;
+
+	remove_gconf_watched_dir( gconf );
+
+	gboolean ret_gconf = gconf_client_key_is_writable( gconf->private->gconf, path, &error );
+	if( error ){
+		g_warning( "%s: gconf_client_key_is_writable: %s", thisfn, error->message );
+		g_error_free( error );
+		error = NULL;
+	}
+	gboolean ret_try = FALSE;
+	gchar *path_try = g_strdup_printf( "%s/%s", path, "fake_key" );
+	ret_try = gconf_client_set_string( gconf->private->gconf, path_try, "fake_value", &error );
+	if( error ){
+		g_warning( "%s: gconf_client_set_string: %s", thisfn, error->message );
+		g_error_free( error );
+		error = NULL;
+	}
+	if( ret_try ){
+		gconf_client_unset( gconf->private->gconf, path_try, NULL );
+	}
+	g_free( path_try );
+	g_debug( "%s: ret_gconf=%s, ret_try=%s", thisfn, ret_gconf ? "True":"False", ret_try ? "True":"False" );
+
+	install_gconf_watched_dir( gconf );
+	return( ret_try );*/
+
+	return( TRUE );
+}
+
+static gboolean
+write_str( NagpGConfProvider *provider, const gchar *uuid, const gchar *name, const gchar *key, gchar *value, GSList **messages )
+{
+	gchar *path;
+	gboolean ret;
+	gchar *msg;
+
+	if( name && strlen( name )){
+		path = g_strdup_printf( "%s/%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, name, key );
+	} else {
+		path = g_strdup_printf( "%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, key );
+	}
+
+	msg = NULL;
+	ret = na_gconf_utils_write_string( provider->private->gconf, path, value, &msg );
+	if( msg ){
+		*messages = g_slist_append( *messages, g_strdup( msg ));
+		g_free( msg );
+	}
+
+	g_free( value );
+	g_free( path );
+
+	return( ret );
+}
+
+static gboolean
+write_bool( NagpGConfProvider *provider, const gchar *uuid, const gchar *name, const gchar *key, gboolean value, GSList **messages )
+{
+	gboolean ret;
+	gchar *path;
+	gchar *msg;
+
+	if( name && strlen( name )){
+		path = g_strdup_printf( "%s/%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, name, key );
+	} else {
+		path = g_strdup_printf( "%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, key );
+	}
+
+	msg = NULL;
+	ret = na_gconf_utils_write_bool( provider->private->gconf, path, value, &msg );
+	if( msg ){
+		*messages = g_slist_append( *messages, g_strdup( msg ));
+		g_free( msg );
+	}
+
+	g_free( path );
+
+	return( ret );
+}
+
+static gboolean
+write_list( NagpGConfProvider *provider, const gchar *uuid, const gchar *name, const gchar *key, GSList *value, GSList **messages )
+{
+	gboolean ret;
+	gchar *path;
+	gchar *msg;
+
+	if( name && strlen( name )){
+		path = g_strdup_printf( "%s/%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, name, key );
+	} else {
+		path = g_strdup_printf( "%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, key );
+	}
+
+	msg = NULL;
+	ret = na_gconf_utils_write_string_list( provider->private->gconf, path, value, &msg );
+	if( msg ){
+		*messages = g_slist_append( *messages, g_strdup( msg ));
+		g_free( msg );
+	}
+
+	free_gslist( value );
+	g_free( path );
+
+	return( ret );
+}
+
+/*
+ * free_gslist:
+ * @list: the GSList to be freed.
+ *
+ * Frees a GSList of strings.
+ */
+static void
+free_gslist( GSList *list )
+{
+	g_slist_foreach( list, ( GFunc ) g_free, NULL );
+	g_slist_free( list );
+}
diff --git a/nautilus-actions/io-provider-gconf/nagp-write.h b/nautilus-actions/io-provider-gconf/nagp-write.h
new file mode 100644
index 0000000..bb626fc
--- /dev/null
+++ b/nautilus-actions/io-provider-gconf/nagp-write.h
@@ -0,0 +1,66 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 2 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 Library; see the file COPYING.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *   Frederic Ruaudel <grumz grumz net>
+ *   Rodrigo Moya <rodrigo gnome-db org>
+ *   Pierre Wieser <pwieser trychlos org>
+ *   ... and many others (see AUTHORS)
+ */
+
+#ifndef __NAGP_WRITE_H__
+#define __NAGP_WRITE_H__
+
+/**
+ * SECTION: nagp_gconf_provider
+ * @short_description: #NagpGConfProvider class definition.
+ * @include: na-gconf-provider.h
+ *
+ * This class manages the GConf I/O storage subsystem, or, in other words,
+ * the GConf subsystem as an NAIIOProvider. As this, it should only be
+ * used through the NAIIOProvider interface.
+ *
+ * #NagpGConfProvider uses #NAGConfMonitor to watch at the configuration
+ * tree. Modifications are notified to the NAIIOProvider interface.
+ */
+
+#include <nautilus-actions/api/na-iio-provider.h>
+#include <nautilus-actions/api/na-object-api.h>
+
+#include "nagp-gconf-provider.h"
+
+G_BEGIN_DECLS
+
+gboolean nagp_iio_provider_is_willing_to_write( const NAIIOProvider *provider );
+
+gboolean nagp_iio_provider_is_writable( const NAIIOProvider *provider, const NAObjectItem *item );
+
+gboolean nagp_key_is_writable( NagpGConfProvider *gconf, const gchar *path );
+
+guint    nagp_iio_provider_write_item( const NAIIOProvider *provider, const NAObjectItem *item, GSList **message );
+
+guint    nagp_iio_provider_delete_item( const NAIIOProvider *provider, const NAObjectItem *item, GSList **message );
+
+G_END_DECLS
+
+#endif /* __NAGP_WRITE_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]