[nautilus-actions: 4/19] Install action changed notification system



commit 0721ec9055c38b91743d536f2917ce594da3d5ec
Author: Pierre Wieser <pwieser trychlos org>
Date:   Sun Jun 7 22:13:28 2009 +0200

    Install action changed notification system
---
 ChangeLog                            |   16 +
 src/common/nact-action-profile.c     |   50 +++-
 src/common/nact-action-profile.h     |    2 +
 src/common/nact-action.c             |   57 +++-
 src/common/nact-action.h             |    4 +-
 src/common/nact-gconf.c              |  606 +++++++++++++++++-----------------
 src/common/nact-gconf.h              |    2 +-
 src/common/nact-iio-provider.c       |    2 +
 src/common/nact-object.c             |   10 +-
 src/common/nact-pivot.c              |  394 ++++++++++------------
 src/common/nact-pivot.h              |   48 ++--
 src/common/nact-uti-lists.h          |    1 +
 src/common/nautilus-actions-config.c |    2 +-
 src/plugin/nautilus-actions.c        |  267 ++++++++++------
 14 files changed, 794 insertions(+), 667 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 2500c74..593c435 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2009-06-07 Pierre Wieser <pwieser trychlos org>
+
+	Install the notification system.
+
+	* src/common/nautilus-actions.c:
+	Define new message "notify_nautilus_of_action_changed".
+
+	* src/common/nact-pivot.c:
+	Define new message "notify_pivot_of_action_changed".
+
+	* src/common/nact-pivot.h:
+	Rename and update nactPivotValue structure to NactPivotNotify.
+
+	* src/common/gconf.c:
+	Send message to NactPivot on action changed.
+
 2009-06-06 Pierre Wieser <pwieser trychlos org>
 
 	Remove NactIIOClient interface.
diff --git a/src/common/nact-action-profile.c b/src/common/nact-action-profile.c
index c4b65ca..0db7238 100644
--- a/src/common/nact-action-profile.c
+++ b/src/common/nact-action-profile.c
@@ -40,6 +40,13 @@
 #include "nact-action-profile.h"
 #include "nact-uti-lists.h"
 
+/* private class data
+ */
+struct NactActionProfileClassPrivate {
+};
+
+/* private instance data
+ */
 struct NactActionProfilePrivate {
 	gboolean  dispose_has_run;
 
@@ -62,9 +69,10 @@ struct NactActionProfilePrivate {
 	GSList   *schemes;
 };
 
-struct NactActionProfileClassPrivate {
-};
-
+/* private instance properties
+ * please note that property names must have the same spelling as the
+ * NactIIOProvider parameters
+ */
 enum {
 	PROP_ACTION = 1,
 	PROP_PROFILE_NAME,
@@ -80,9 +88,6 @@ enum {
 	PROP_SCHEMES
 };
 
-/* please note that property names must have the same spelling as the
- * NactIIOProvider parameters
- */
 #define PROP_ACTION_STR					"action"
 #define PROP_PROFILE_NAME_STR			"name"
 #define PROP_LABEL_STR					"desc-name"
@@ -489,6 +494,39 @@ do_dump_list( const gchar *thisfn, const gchar *label, GSList *list )
 	g_string_free( str, TRUE );
 }
 
+/*
+ * Check if the given profile is empty, i.e. all its attributes are
+ * empty.
+ */
+gboolean
+nact_action_profile_is_empty( const NactActionProfile *profile )
+{
+	g_assert( NACT_IS_ACTION_PROFILE( profile ));
+
+	if( profile->private->name && strlen( profile->private->name )){
+		return( FALSE );
+	}
+	if( profile->private->label && strlen( profile->private->label )){
+		return( FALSE );
+	}
+	if( profile->private->path && strlen( profile->private->path )){
+		return( FALSE );
+	}
+	if( profile->private->parameters && strlen( profile->private->parameters )){
+		return( FALSE );
+	}
+	if( !nactuti_is_empty_string_list( profile->private->basenames )){
+		return( FALSE );
+	}
+	if( !nactuti_is_empty_string_list( profile->private->mimetypes )){
+		return( FALSE );
+	}
+	if( !nactuti_is_empty_string_list( profile->private->schemes )){
+		return( FALSE );
+	}
+	return( TRUE );
+}
+
 /**
  * Returns a pointer to the action for this profile.
  */
diff --git a/src/common/nact-action-profile.h b/src/common/nact-action-profile.h
index eede629..315b921 100644
--- a/src/common/nact-action-profile.h
+++ b/src/common/nact-action-profile.h
@@ -74,6 +74,8 @@ NactActionProfile *nact_action_profile_new( const NactObject *action, const gcha
 
 void               nact_action_profile_load( NactObject *profile );
 
+gboolean           nact_action_profile_is_empty( const NactActionProfile *profile );
+
 NactObject        *nact_action_profile_get_action( const NactActionProfile *profile );
 gchar             *nact_action_profile_get_name( const NactActionProfile *profile );
 gchar             *nact_action_profile_get_path( const NactActionProfile *profile );
diff --git a/src/common/nact-action.c b/src/common/nact-action.c
index 61addad..3113ca2 100644
--- a/src/common/nact-action.c
+++ b/src/common/nact-action.c
@@ -38,6 +38,13 @@
 #include "nact-action-profile.h"
 #include "nact-uti-lists.h"
 
+/* private class data
+ */
+struct NactActionClassPrivate {
+};
+
+/* private instance data
+ */
 struct NactActionPrivate {
 	gboolean  dispose_has_run;
 
@@ -55,9 +62,10 @@ struct NactActionPrivate {
 	GSList   *profiles;
 };
 
-struct NactActionClassPrivate {
-};
-
+/* private instance properties
+ * please note that property names must have the same spelling as the
+ * NactIIOProvider parameters
+ */
 enum {
 	PROP_UUID = 1,
 	PROP_VERSION,
@@ -66,9 +74,6 @@ enum {
 	PROP_ICON
 };
 
-/* please note that property names must have the same spelling as the
- * NactIIOProvider parameters
- */
 #define PROP_UUID_STR		"uuid"
 #define PROP_VERSION_STR	"version"
 #define PROP_LABEL_STR		"label"
@@ -338,7 +343,7 @@ free_profiles( NactAction *action )
  *
  * Note that the parm may actually be a profile's parm.
  */
-NactAction *
+/*NactAction *
 nact_action_create( const gchar *key, const gchar *parm, const NactPivotValue *value )
 {
 	static const gchar *thisfn = "nact_action_create";
@@ -347,17 +352,17 @@ nact_action_create( const gchar *key, const gchar *parm, const NactPivotValue *v
 	NactAction *action = g_object_new( NACT_ACTION_TYPE, NULL );
 	nact_action_update( action, parm, value );
 	return( action );
-}
+}*/
 
 /**
  * Update the given parameter of an action.
  */
-void
+/*void
 nact_action_update( NactAction *action, const gchar *parm, const NactPivotValue *value )
 {
 	static const gchar *thisfn = "nact_action_update";
 	g_debug( "%s: action=%p, parm='%s', value=%p", thisfn, action, parm, value );
-}
+}*/
 
 static void
 do_dump( const NactObject *action )
@@ -386,6 +391,38 @@ do_dump( const NactObject *action )
 }
 
 /**
+ * Check if the given action is empty, i.e. all its attributes are empty.
+ */
+gboolean
+nact_action_is_empty( const NactAction *action )
+{
+	g_assert( NACT_IS_ACTION( action ));
+
+	if( action->private->uuid && strlen( action->private->uuid )){
+		return( FALSE );
+	}
+	if( action->private->version && strlen( action->private->version )){
+		return( FALSE );
+	}
+	if( action->private->label && strlen( action->private->label )){
+		return( FALSE );
+	}
+	if( action->private->tooltip && strlen( action->private->tooltip )){
+		return( FALSE );
+	}
+	if( action->private->icon && strlen( action->private->icon )){
+		return( FALSE );
+	}
+	GSList *ip;
+	for( ip = action->private->profiles ; ip ; ip = ip->next ){
+		if( !nact_action_profile_is_empty( NACT_ACTION_PROFILE( ip->data ))){
+			return( FALSE );
+		}
+	}
+	return( TRUE );
+}
+
+/**
  * Return the globally unique identifier (UUID) of the action.
  *
  * @action: an NactAction object.
diff --git a/src/common/nact-action.h b/src/common/nact-action.h
index 5e017bb..3702e5c 100644
--- a/src/common/nact-action.h
+++ b/src/common/nact-action.h
@@ -71,8 +71,8 @@ GType       nact_action_get_type( void );
 
 NactAction *nact_action_new( const gchar *uuid );
 
-NactAction *nact_action_create( const gchar *key, const gchar *parm, const NactPivotValue *value );
-void        nact_action_update( NactAction *action, const gchar *parm, const NactPivotValue *value );
+/*NactAction *nact_action_create( const gchar *key, const gchar *parm, const NactPivotValue *value );
+void        nact_action_update( NactAction *action, const gchar *parm, const NactPivotValue *value );*/
 
 gboolean    nact_action_is_empty( const NactAction *action );
 
diff --git a/src/common/nact-gconf.c b/src/common/nact-gconf.c
index 9939eb4..9fb244a 100644
--- a/src/common/nact-gconf.c
+++ b/src/common/nact-gconf.c
@@ -44,54 +44,62 @@
 #include "nact-iio-provider.h"
 #include "nact-uti-lists.h"
 
+/* private class data
+ */
+struct NactGConfClassPrivate {
+};
+
+/* private instance data
+ */
 struct NactGConfPrivate {
 	gboolean     dispose_has_run;
-	GObject     *notification_handler;
+
+	/* instance to be notified of an action modification
+	 */
+	gpointer  notified;
+
 	GConfClient *gconf;
 	guint        notify_id;
 };
 
-struct NactGConfClassPrivate {
-};
-
+/* private instance properties
+ */
 enum {
-	PROP_NOTIFICATION_HANDLER = 1
+	PROP_NOTIFIED = 1
 };
 
-#define PROP_NOTIFICATION_HANDLER_STR	"notification-handler"
+#define PROP_NOTIFIED_STR				"to-be-notified"
 
 static GObjectClass *st_parent_class = NULL;
 
-static GType          register_type( void );
-static void           class_init( NactGConfClass *klass );
-static void           iio_provider_iface_init( NactIIOProviderInterface *iface );
-static void           instance_init( GTypeInstance *instance, gpointer klass );
-static void           instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
-static void           instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
-static void           instance_dispose( GObject *object );
-static void           instance_finalize( GObject *object );
-static guint          install_gconf_watch( NactGConf *gconf );
-static void           remove_gconf_watch( NactGConf *gconf );
-
-static void           action_changed_cb( GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data );
-
-static void           free_keys_values( GSList *keys );
-static GSList        *load_keys_values( const NactGConf *gconf, const gchar *path );
-static GSList        *load_subdirs( const NactGConf *gconf, const gchar *path );
-static gchar         *path_to_key( const gchar *path );
-/*static NactGConfIO   *path_to_struct( const gchar *path );*/
-static void           set_item_properties( NactObject *object, GSList *properties );
-static NactPivotValue *value_to_pivot( const GConfValue *value );
-
-static void           load_action_properties( NactGConf *gconf, NactAction *action );
-static GSList        *load_profiles( NactGConf *gconf, NactAction *action );
-static void           load_profile_properties( NactGConf *gconf, NactActionProfile *profile );
-static GSList        *do_load_actions( NactIIOProvider *provider );
+static GType            register_type( void );
+static void             class_init( NactGConfClass *klass );
+static void             iio_provider_iface_init( NactIIOProviderInterface *iface );
+static void             instance_init( GTypeInstance *instance, gpointer klass );
+static void             instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
+static void             instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
+static void             instance_dispose( GObject *object );
+static void             instance_finalize( GObject *object );
+
+static GSList          *do_load_actions( NactIIOProvider *provider );
+static void             load_action_properties( NactGConf *gconf, NactAction *action );
+static GSList          *load_profiles( NactGConf *gconf, NactAction *action );
+static void             load_profile_properties( NactGConf *gconf, NactActionProfile *profile );
+static GSList          *load_subdirs( const NactGConf *gconf, const gchar *path );
+static GSList          *load_keys_values( const NactGConf *gconf, const gchar *path );
+static void             free_keys_values( GSList *keys );
+static gchar           *path_to_key( const gchar *path );
+static void             set_item_properties( NactObject *object, GSList *properties );
+static NactPivotNotify *entry_to_notify( const GConfEntry *entry );
+
+static guint            install_gconf_watch( NactGConf *gconf );
+static void             remove_gconf_watch( NactGConf *gconf );
+static void             action_changed_cb( GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data );
 
 NactGConf *
 nact_gconf_new( const GObject *handler )
 {
-	return( g_object_new( NACT_GCONF_TYPE, PROP_NOTIFICATION_HANDLER_STR, handler, NULL ));
+	return( g_object_new( NACT_GCONF_TYPE, PROP_NOTIFIED_STR, handler, NULL ));
 }
 
 GType
@@ -150,11 +158,11 @@ class_init( NactGConfClass *klass )
 
 	GParamSpec *spec;
 	spec = g_param_spec_pointer(
-			PROP_NOTIFICATION_HANDLER_STR,
-			PROP_NOTIFICATION_HANDLER_STR,
+			PROP_NOTIFIED_STR,
+			PROP_NOTIFIED_STR,
 			"A pointer to a GObject which will receive action_changed notifications",
 			G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
-	g_object_class_install_property( object_class, PROP_NOTIFICATION_HANDLER, spec );
+	g_object_class_install_property( object_class, PROP_NOTIFIED, spec );
 
 	klass->private = g_new0( NactGConfClassPrivate, 1 );
 }
@@ -191,8 +199,8 @@ instance_get_property( GObject *object, guint property_id, GValue *value, GParam
 	NactGConf *self = NACT_GCONF( object );
 
 	switch( property_id ){
-		case PROP_NOTIFICATION_HANDLER:
-			g_value_set_pointer( value, self->private->notification_handler );
+		case PROP_NOTIFIED:
+			g_value_set_pointer( value, self->private->notified );
 			break;
 
 		default:
@@ -208,8 +216,8 @@ instance_set_property( GObject *object, guint property_id, const GValue *value,
 	NactGConf *self = NACT_GCONF( object );
 
 	switch( property_id ){
-		case PROP_NOTIFICATION_HANDLER:
-			self->private->notification_handler = g_value_get_pointer( value );
+		case PROP_NOTIFIED:
+			self->private->notified = g_value_get_pointer( value );
 			break;
 
 		default:
@@ -250,148 +258,130 @@ instance_finalize( GObject *object )
 }
 
 /*
- * note that we need the NactPivot object in action_changed_cb handler
- * but it is initialized as a construction property, and this watch is
- * installed from instance_init, i.e. before properties are set..
- *
- * we so pass NactGConf pointer which is already valid at this time.
+ * NactIIOProviderInterface implementation
+ * load the list of actions and returns them as a GSList
  */
-static guint
-install_gconf_watch( NactGConf *gconf )
+static GSList *
+do_load_actions( NactIIOProvider *provider )
 {
-	static const gchar *thisfn = "install_gconf_watch";
-	GError *error = NULL;
+	static const gchar *thisfn = "nacf_gconf_do_load_actions";
+	g_debug( "%s: provider=%p", thisfn, provider );
 
-	gconf_client_add_dir(
-			gconf->private->gconf, NACT_GCONF_CONFIG_PATH, GCONF_CLIENT_PRELOAD_RECURSIVE, &error );
-	if( error ){
-		g_error( "%s: error=%s", thisfn, error->message );
-		g_error_free( error );
-		return( 0 );
-	}
+	g_assert( NACT_IS_IIO_PROVIDER( provider ));
+	g_assert( NACT_IS_GCONF( provider ));
+	NactGConf *self = NACT_GCONF( provider );
 
-	guint notify_id =
-		gconf_client_notify_add(
-			gconf->private->gconf,
-			NACT_GCONF_CONFIG_PATH,
-			( GConfClientNotifyFunc ) action_changed_cb,
-			gconf,
-			NULL,
-			&error
-		);
-	if( error ){
-		g_error( "%s: error=%s", thisfn, error->message );
-		g_error_free( error );
-		return( 0 );
-	}
+	GSList *items = NULL;
+	GSList *ip;
+	GSList *listpath = load_subdirs( self, NACT_GCONF_CONFIG_PATH );
 
-	return( notify_id );
-}
+	for( ip = listpath ; ip ; ip = ip->next ){
 
-static void
-remove_gconf_watch( NactGConf *gconf )
-{
-	static const gchar *thisfn = "remove_gconf_watch";
-	GError *error = NULL;
+		gchar *key = path_to_key(( const gchar * ) ip->data );
 
-	if( gconf->private->notify_id ){
-		gconf_client_notify_remove( gconf->private->gconf, gconf->private->notify_id );
-	}
+		NactAction *action = nact_action_new( key );
+		load_action_properties( self, action );
+		nact_action_set_profiles( action, load_profiles( self, action ));
 
-	gconf_client_remove_dir( gconf->private->gconf, NACT_GCONF_CONFIG_PATH, &error );
-	if( error ){
-		g_error( "%s: error=%s", thisfn, error->message );
-		g_error_free( error );
+#ifdef NACT_MAINTAINER_MODE
+		nact_object_dump( NACT_OBJECT( action ));
+#endif
+
+		items = g_slist_prepend( items, action );
+		g_free( key );
 	}
+
+	nactuti_free_string_list( listpath );
+
+	return( items );
 }
 
 /*
- * this callback is triggered each time a value is changed under our
- * actions directory
- *
- * if the modification is made from nautilus-actions-config ui, then
- * the callback is triggered several times (one time for each rewritten
- * property) as action/profile are edited as blocs of data ; in this
- * case, the ui takes care (aso of 1.10) of also writing at last a
- * particular key of the form xxx:yyyyyyyy-yyyy-yyyy-..., where :
- *    xxx is a sequential number (inside of the ui session)
- *    yyyyyyyy-yyyy-yyyy-... is the uuid of the involved action
- *
- * this is so a sort of hack which simplifies a lot the notification
- * system (take the new action, replace it in the current global list)
- * but doesn't work if the modification is made from outside of the ui
- *
- * if the modification is made elsewhere (an action is imported as a
- * xml file in gconf, of gconf is directly edited), we'd have to rely
- * on the standard watch mechanism
+ * load and set the properties of the specified action
  */
 static void
-action_changed_cb( GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data )
+load_action_properties( NactGConf *gconf, NactAction *action )
 {
-	/*static const gchar *thisfn = "action_changed_cb";
-	g_debug( "%s: client=%p, cnxnid=%u, entry=%p, user_data=%p", thisfn, client, cnxn_id, entry, user_data );*/
+	/*static const gchar *thisfn = "nacf_gconf_load_action_properties";
+	g_debug( "%s: gconf=%p, action=%p", thisfn, gconf, action );*/
 
-	g_assert( NACT_IS_GCONF( user_data ));
-	NactGConf *gconf = NACT_GCONF( user_data );
+	g_assert( NACT_IS_GCONF( gconf ));
+	g_assert( NACT_IS_ACTION( action ));
 
-	const gchar *path = gconf_entry_get_key( entry );
-	const gchar *subpath = path + strlen( NACT_GCONF_CONFIG_PATH ) + 1;
-	gchar **split = g_strsplit( subpath, "/", 2 );
-	gchar *key = g_strdup( split[0] );
-	gchar *parm = g_strdup( split[1] );
-	g_strfreev( split );
+	gchar *uuid = nact_action_get_uuid( action );
+	gchar *path = g_strdup_printf( "%s/%s", NACT_GCONF_CONFIG_PATH, uuid );
 
-	NactPivotValue *value = value_to_pivot( gconf_entry_get_value( entry ));
+	GSList *properties = load_keys_values( gconf, path );
 
-	nact_pivot_on_action_changed( NACT_PIVOT( gconf->private->notification_handler ), key, parm, value );
+	set_item_properties( NACT_OBJECT( action ), properties );
 
-	g_free( key );
-	nact_pivot_free_pivot_value( value );
+	free_keys_values( properties );
+	g_free( uuid );
+	g_free( path );
 }
 
-static void
-free_keys_values( GSList *list )
+/*
+ * load the list of profiles for an action and returns them as a GSList
+ */
+static GSList *
+load_profiles( NactGConf *gconf, NactAction *action )
 {
-	GSList *item;
-	for( item = list ; item != NULL ; item = item->next ){
-		GConfEntry *entry = ( GConfEntry * ) item->data;
-		gconf_entry_unref( entry );
+	/*static const gchar *thisfn = "nacf_gconf_load_profiles";
+	g_debug( "%s: gconf=%p, action=%p", thisfn, gconf, action );*/
+
+	g_assert( NACT_IS_GCONF( gconf ));
+	g_assert( NACT_IS_ACTION( action ));
+
+	gchar *uuid = nact_action_get_uuid( action );
+	gchar *path = g_strdup_printf( "%s/%s", NACT_GCONF_CONFIG_PATH, uuid );
+
+	GSList *ip;
+	GSList *items = NULL;
+	GSList *listpath = load_subdirs( gconf, path );
+
+	for( ip = listpath ; ip ; ip = ip->next ){
+
+		gchar *key = path_to_key(( const gchar * ) ip->data );
+		NactActionProfile *profile = nact_action_profile_new( NACT_OBJECT( action ), key );
+		load_profile_properties( gconf, profile );
+
+		items = g_slist_prepend( items, profile );
 	}
-	g_slist_free( list );
+
+	nactuti_free_string_list( listpath );
+	g_free( path );
+	g_free( uuid );
+
+	return( items );
 }
 
 /*
- * load all the key=value pairs of this key (specified as a full path)
- * The list is not recursive, it contains only the immediate children of
- * path.
- * To free the returned hash table, call free_key_values
+ * load and set the properties of the specified profile
  */
-static GSList *
-load_keys_values( const NactGConf *gconf, const gchar *path )
+static void
+load_profile_properties( NactGConf *gconf, NactActionProfile *profile )
 {
-	static const gchar *thisfn = "nact_gconf_load_keys_values";
+	/*static const gchar *thisfn = "nacf_gconf_load_profile_properties";
+	g_debug( "%s: gconf=%p, profile=%p", thisfn, gconf, profile );*/
 
-	GError *error = NULL;
-	GSList *list_path = gconf_client_all_entries( gconf->private->gconf, path, &error );
-	if( error ){
-		g_error( "%s: path=%s, error=%s", thisfn, path, error->message );
-		g_error_free( error );
-		return(( GSList * ) NULL );
-	}
+	g_assert( NACT_IS_GCONF( gconf ));
+	g_assert( NACT_IS_ACTION_PROFILE( profile ));
 
-	GSList *list_keys = NULL;
-	GSList *item;
-	for( item = list_path ; item != NULL ; item = item->next ){
-		GConfEntry *entry = ( GConfEntry * ) item->data;
-		gchar *key = path_to_key( gconf_entry_get_key( entry ));
-		GConfEntry *entry_new = gconf_entry_new( key, gconf_entry_get_value( entry ));
-		g_free( key );
-		list_keys = g_slist_prepend( list_keys, entry_new );
-	}
+	NactAction *action =
+		NACT_ACTION( nact_action_profile_get_action( NACT_ACTION_PROFILE( profile )));
+	g_assert( NACT_IS_ACTION( action ));
 
-	free_keys_values( list_path );
+	gchar *uuid = nact_action_get_uuid( action );
+	gchar *path = g_strdup_printf(
+			"%s/%s/%s", NACT_GCONF_CONFIG_PATH, uuid, nact_action_profile_get_name( profile ));
 
-	return( list_keys );
+	GSList *properties = load_keys_values( gconf, path );
+
+	set_item_properties( NACT_OBJECT( profile ), properties );
+
+	free_keys_values( properties );
+	g_free( path );
+	g_free( uuid );
 }
 
 /*
@@ -415,6 +405,39 @@ load_subdirs( const NactGConf *gconf, const gchar *path )
 }
 
 /*
+ * load all the key=value pairs of this key (specified as a full path)
+ * The list is not recursive, it contains only the immediate children of
+ * path.
+ * To free the returned list, call free_key_values
+ */
+static GSList *
+load_keys_values( const NactGConf *gconf, const gchar *path )
+{
+	static const gchar *thisfn = "nact_gconf_load_keys_values";
+
+	GError *error = NULL;
+	GSList *list_path = gconf_client_all_entries( gconf->private->gconf, path, &error );
+	if( error ){
+		g_error( "%s: path=%s, error=%s", thisfn, path, error->message );
+		g_error_free( error );
+		return(( GSList * ) NULL );
+	}
+
+	return( list_path );
+}
+
+static void
+free_keys_values( GSList *list )
+{
+	GSList *item;
+	for( item = list ; item != NULL ; item = item->next ){
+		GConfEntry *entry = ( GConfEntry * ) item->data;
+		gconf_entry_unref( entry );
+	}
+	g_slist_free( list );
+}
+
+/*
  * extract the key part (the last part) of a full path
  * returns a newly allocated string which must be g_freed by the caller
  */
@@ -429,20 +452,9 @@ path_to_key( const gchar *path )
 }
 
 /*
- * allocate a new NactGConfIO structure
- * to be freed via nact_gconf_dispose
- */
-/*static NactGConfIO *
-path_to_struct( const gchar *path )
-{
-	NactGConfIO *io = g_new0( NactGConfIO, 1 );
-	io->key = path_to_key( path );
-	io->path = g_strdup( path );
-	return( io );
-}*/
-
-/*
  * set the item properties into the object
+ * as we make use of NactPivotNotify structure, 'uuid' field must be
+ * read as the GConf key, i.e. the parameter name
  */
 static void
 set_item_properties( NactObject *object, GSList *properties )
@@ -453,199 +465,175 @@ set_item_properties( NactObject *object, GSList *properties )
 	for( item = properties ; item != NULL ; item = item->next ){
 
 		GConfEntry *entry = ( GConfEntry * ) item->data;
-		const char *key = gconf_entry_get_key( entry );
-		NactPivotValue *value = value_to_pivot( gconf_entry_get_value( entry ));
+		NactPivotNotify *npn = entry_to_notify( entry );
+		if( npn ){
 
-		if( value ){
-			switch( value->type ){
+			gchar **split = g_strsplit( npn->parm, "/", -1 );
+			gchar *parm = g_strdup( split[ g_strv_length( split ) -1 ] );
+			g_strfreev( split );
+
+			switch( npn->type ){
 
 				case NACT_PIVOT_STR:
 				case NACT_PIVOT_BOOL:
 				case NACT_PIVOT_STRLIST:
-					g_object_set( G_OBJECT( object ), key, value->data, NULL );
+					g_object_set( G_OBJECT( object ), parm, npn->data, NULL );
 					break;
 
 				default:
 					g_assert_not_reached();
 					break;
 			}
-			nact_pivot_free_pivot_value( value );
+			nact_pivot_free_notify( npn );
+			g_free( parm );
 		}
 	}
 }
 
 /*
- * convert a GConfValue to our internal data type
+ * convert a GConfEntry to a structure suitable to notify NactPivot
  */
-static NactPivotValue *
-value_to_pivot( const GConfValue *value )
+static NactPivotNotify *
+entry_to_notify( const GConfEntry *entry )
 {
-	NactPivotValue *pivot_value = NULL;
+	/*static const gchar *thisfn = "nact_gconf_entry_to_notify";*/
 	GSList *listvalues, *iv, *strings;
 
-	if( !value ){
-		return(( NactPivotValue * ) NULL );
-	}
-
-	switch( value->type ){
+	g_assert( entry );
 
-		case GCONF_VALUE_STRING:
-			pivot_value = g_new0( NactPivotValue, 1 );
-			pivot_value->type = NACT_PIVOT_STR;
-			pivot_value->data = ( gpointer ) g_strdup( gconf_value_get_string( value ));
-			break;
-
-		case GCONF_VALUE_BOOL:
-			pivot_value = g_new0( NactPivotValue, 1 );
-			pivot_value->type = NACT_PIVOT_BOOL;
-			pivot_value->data = ( gpointer ) gconf_value_get_bool( value );
-			break;
-
-		case GCONF_VALUE_LIST:
-			listvalues = gconf_value_get_list( value );
-			strings = NULL;
-			for( iv = listvalues ; iv != NULL ; iv = iv->next ){
-				strings = g_slist_prepend( strings,
-						( gpointer ) gconf_value_get_string(( GConfValue * ) iv->data ));
-			}
+	const gchar *path = gconf_entry_get_key( entry );
+	g_assert( path );
 
-			pivot_value = g_new0( NactPivotValue, 1 );
-			pivot_value->type = NACT_PIVOT_STRLIST;
-			pivot_value->data = ( gpointer ) nactuti_duplicate_string_list( strings );
-			/*nactuti_free_string_list( strings );*/
-			break;
+	NactPivotNotify *npn = g_new0( NactPivotNotify, 1 );
 
-		default:
-			g_assert_not_reached();
-			break;
+	const gchar *subpath = path + strlen( NACT_GCONF_CONFIG_PATH ) + 1;
+	gchar **split = g_strsplit( subpath, "/", 2 );
+	/*g_debug( "%s: [0]=%s, [1]=%s", thisfn, split[0], split[1] );*/
+	npn->uuid = g_strdup( split[0] );
+	if( split[1] ){
+		npn->parm = g_strdup( split[1] );
 	}
+	g_strfreev( split );
 
-	return( pivot_value );
-}
-
-/*
- * load and set the properties of the specified action
- */
-static void
-load_action_properties( NactGConf *gconf, NactAction *action )
-{
-	/*static const gchar *thisfn = "nacf_gconf_load_action_properties";
-	g_debug( "%s: gconf=%p, action=%p", thisfn, gconf, action );*/
-
-	g_assert( NACT_IS_GCONF( gconf ));
-	g_assert( NACT_IS_ACTION( action ));
-
-	gchar *uuid = nact_action_get_uuid( action );
-	gchar *path = g_strdup_printf( "%s/%s", NACT_GCONF_CONFIG_PATH, uuid );
-
-	GSList *properties = load_keys_values( gconf, path );
-
-	set_item_properties( NACT_OBJECT( action ), properties );
-
-	free_keys_values( properties );
-	g_free( uuid );
-	g_free( path );
+	const GConfValue *value = gconf_entry_get_value( entry );
+	if( value ){
+		switch( value->type ){
+
+			case GCONF_VALUE_STRING:
+				npn->type = NACT_PIVOT_STR;
+				npn->data = ( gpointer ) g_strdup( gconf_value_get_string( value ));
+				break;
+
+			case GCONF_VALUE_BOOL:
+				npn->type = NACT_PIVOT_BOOL;
+				npn->data = ( gpointer ) gconf_value_get_bool( value );
+				break;
+
+			case GCONF_VALUE_LIST:
+				listvalues = gconf_value_get_list( value );
+				strings = NULL;
+				for( iv = listvalues ; iv != NULL ; iv = iv->next ){
+					strings = g_slist_prepend( strings,
+							( gpointer ) gconf_value_get_string(( GConfValue * ) iv->data ));
+				}
+
+				npn->type = NACT_PIVOT_STRLIST;
+				npn->data = ( gpointer ) nactuti_duplicate_string_list( strings );
+				/*nactuti_free_string_list( strings );*/
+				break;
+
+			default:
+				g_assert_not_reached();
+				break;
+		}
+	}
+	return( npn );
 }
 
 /*
- * load the list of profiles for an action and returns them as a GSList
+ * note that we need the NactPivot object in action_changed_cb handler
+ * but it is initialized as a construction property, and this watch is
+ * installed from instance_init, i.e. before properties are set..
+ * we so pass NactGConf pointer which is already valid at this time.
  */
-static GSList *
-load_profiles( NactGConf *gconf, NactAction *action )
+static guint
+install_gconf_watch( NactGConf *gconf )
 {
-	/*static const gchar *thisfn = "nacf_gconf_load_profiles";
-	g_debug( "%s: gconf=%p, action=%p", thisfn, gconf, action );*/
-
-	g_assert( NACT_IS_GCONF( gconf ));
-	g_assert( NACT_IS_ACTION( action ));
-
-	gchar *uuid = nact_action_get_uuid( action );
-	gchar *path = g_strdup_printf( "%s/%s", NACT_GCONF_CONFIG_PATH, uuid );
-
-	GSList *ip;
-	GSList *items = NULL;
-	GSList *listpath = load_subdirs( gconf, path );
-
-	for( ip = listpath ; ip ; ip = ip->next ){
-
-		gchar *key = path_to_key(( const gchar * ) ip->data );
-		NactActionProfile *profile = nact_action_profile_new( NACT_OBJECT( action ), key );
-		load_profile_properties( gconf, profile );
+	static const gchar *thisfn = "nact_gconf_install_gconf_watch";
+	GError *error = NULL;
 
-		items = g_slist_prepend( items, profile );
+	gconf_client_add_dir(
+			gconf->private->gconf, NACT_GCONF_CONFIG_PATH, GCONF_CLIENT_PRELOAD_RECURSIVE, &error );
+	if( error ){
+		g_error( "%s: error=%s", thisfn, error->message );
+		g_error_free( error );
+		return( 0 );
 	}
 
-	nactuti_free_string_list( listpath );
-	g_free( path );
-	g_free( uuid );
+	guint notify_id =
+		gconf_client_notify_add(
+			gconf->private->gconf,
+			NACT_GCONF_CONFIG_PATH,
+			( GConfClientNotifyFunc ) action_changed_cb,
+			gconf,
+			NULL,
+			&error
+		);
+	if( error ){
+		g_error( "%s: error=%s", thisfn, error->message );
+		g_error_free( error );
+		return( 0 );
+	}
 
-	return( items );
+	return( notify_id );
 }
 
-/*
- * load and set the properties of the specified profile
- */
 static void
-load_profile_properties( NactGConf *gconf, NactActionProfile *profile )
+remove_gconf_watch( NactGConf *gconf )
 {
-	/*static const gchar *thisfn = "nacf_gconf_load_profile_properties";
-	g_debug( "%s: gconf=%p, profile=%p", thisfn, gconf, profile );*/
-
-	g_assert( NACT_IS_GCONF( gconf ));
-	g_assert( NACT_IS_ACTION_PROFILE( profile ));
-
-	NactAction *action =
-		NACT_ACTION( nact_action_profile_get_action( NACT_ACTION_PROFILE( profile )));
-	g_assert( NACT_IS_ACTION( action ));
-
-	gchar *uuid = nact_action_get_uuid( action );
-	gchar *path = g_strdup_printf(
-			"%s/%s/%s", NACT_GCONF_CONFIG_PATH, uuid, nact_action_profile_get_name( profile ));
-
-	GSList *properties = load_keys_values( gconf, path );
+	static const gchar *thisfn = "nact_gconf_remove_gconf_watch";
+	GError *error = NULL;
 
-	set_item_properties( NACT_OBJECT( profile ), properties );
+	if( gconf->private->notify_id ){
+		gconf_client_notify_remove( gconf->private->gconf, gconf->private->notify_id );
+	}
 
-	free_keys_values( properties );
-	g_free( path );
-	g_free( uuid );
+	gconf_client_remove_dir( gconf->private->gconf, NACT_GCONF_CONFIG_PATH, &error );
+	if( error ){
+		g_error( "%s: error=%s", thisfn, error->message );
+		g_error_free( error );
+	}
 }
 
 /*
- * NactIIOProviderInterface implementation
- * load the list of actions and returns them as a GSList
+ * this callback is triggered each time a value is changed under our
+ * actions directory
+ *
+ * if the modification is made from nautilus-actions-config ui, then
+ * the callback is triggered several times (one time for each rewritten
+ * property) as action/profile are edited as blocs of data ; in this
+ * case, the ui takes care (aso of 1.10) of also writing at last a
+ * particular key of the form xxx:yyyyyyyy-yyyy-yyyy-..., where :
+ *    xxx is a sequential number (inside of the ui session)
+ *    yyyyyyyy-yyyy-yyyy-... is the uuid of the involved action
+ *
+ * this is so a sort of hack which simplifies a lot the notification
+ * system (take the new action, replace it in the current global list)
+ * but doesn't work if the modification is made from outside of the ui
+ *
+ * if the modification is made elsewhere (an action is imported as a
+ * xml file in gconf, or gconf is directly edited), we'd have to rely
+ * only on the standard watch mechanism
  */
-static GSList *
-do_load_actions( NactIIOProvider *provider )
+static void
+action_changed_cb( GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data )
 {
-	static const gchar *thisfn = "nacf_gconf_do_load_actions";
-	g_debug( "%s: provider=%p", thisfn, provider );
-
-	g_assert( NACT_IS_IIO_PROVIDER( provider ));
-	g_assert( NACT_IS_GCONF( provider ));
-	NactGConf *self = NACT_GCONF( provider );
-
-	GSList *items = NULL;
-	GSList *ip;
-	GSList *listpath = load_subdirs( self, NACT_GCONF_CONFIG_PATH );
-
-	for( ip = listpath ; ip ; ip = ip->next ){
-
-		gchar *key = path_to_key(( const gchar * ) ip->data );
-
-		NactAction *action = nact_action_new( key );
-		load_action_properties( self, action );
-		nact_action_set_profiles( action, load_profiles( self, action ));
-
-#ifdef NACT_MAINTAINER_MODE
-		nact_object_dump( NACT_OBJECT( action ));
-#endif
-
-		items = g_slist_prepend( items, action );
-		g_free( key );
-	}
+	/*static const gchar *thisfn = "action_changed_cb";
+	g_debug( "%s: client=%p, cnxnid=%u, entry=%p, user_data=%p", thisfn, client, cnxn_id, entry, user_data );*/
 
-	nactuti_free_string_list( listpath );
+	g_assert( NACT_IS_GCONF( user_data ));
+	NactGConf *gconf = NACT_GCONF( user_data );
 
-	return( items );
+	NactPivotNotify *npn = entry_to_notify( entry );
+	g_signal_emit_by_name( gconf->private->notified, "notify_pivot_of_action_changed", npn );
 }
diff --git a/src/common/nact-gconf.h b/src/common/nact-gconf.h
index b04d821..4062e2a 100644
--- a/src/common/nact-gconf.h
+++ b/src/common/nact-gconf.h
@@ -66,7 +66,7 @@ typedef struct {
 
 GType      nact_gconf_get_type( void );
 
-NactGConf *nact_gconf_new( const GObject *notification_handler );
+NactGConf *nact_gconf_new( const GObject *notified );
 
 G_END_DECLS
 
diff --git a/src/common/nact-iio-provider.c b/src/common/nact-iio-provider.c
index 2c5bfe8..47ae424 100644
--- a/src/common/nact-iio-provider.c
+++ b/src/common/nact-iio-provider.c
@@ -35,6 +35,8 @@
 #include "nact-iio-provider.h"
 #include "nact-pivot.h"
 
+/* private interface data
+ */
 struct NactIIOProviderInterfacePrivate {
 };
 
diff --git a/src/common/nact-object.c b/src/common/nact-object.c
index b13b6d4..57c0d3f 100644
--- a/src/common/nact-object.c
+++ b/src/common/nact-object.c
@@ -35,11 +35,15 @@
 #include "nact-object.h"
 #include "nact-uti-lists.h"
 
-struct NactObjectPrivate {
-	gboolean dispose_has_run;
+/* private class data
+ */
+struct NactObjectClassPrivate {
 };
 
-struct NactObjectClassPrivate {
+/* private instance data
+ */
+struct NactObjectPrivate {
+	gboolean dispose_has_run;
 };
 
 static GObjectClass *st_parent_class = NULL;
diff --git a/src/common/nact-pivot.c b/src/common/nact-pivot.c
index 25803ce..d007296 100644
--- a/src/common/nact-pivot.c
+++ b/src/common/nact-pivot.c
@@ -32,25 +32,28 @@
 #include <config.h>
 #endif
 
+#include <string.h>
+
 #include "nact-action.h"
 #include "nact-gconf.h"
 #include "nact-pivot.h"
 #include "nact-iio-provider.h"
 #include "nact-uti-lists.h"
 
-/* action_changed_cb send events which are stacked in a static GSList
- * we so hope to optimize updating the global list of actions
+/* private class data
  */
-typedef struct {
-	gchar          *uuid;
-	gchar          *parm;
-	NactPivotValue *value;
-}
-	stackItem;
+struct NactPivotClassPrivate {
+};
 
+/* private instance data
+ */
 struct NactPivotPrivate {
 	gboolean  dispose_has_run;
 
+	/* instance to be notified of an action modification
+	 */
+	gpointer  notified;
+
 	/* list of interface providers
 	 * needs to be in the instance rather than in the class to be able
 	 * to pass NactPivot object to the IO provider, so that the later
@@ -63,35 +66,48 @@ struct NactPivotPrivate {
 	GSList   *actions;
 };
 
-struct NactPivotClassPrivate {
+/* private instance properties
+ */
+enum {
+	PROP_NOTIFIED = 1
 };
 
+#define PROP_NOTIFIED_STR				"to-be-notified"
+
+/* signal definition
+ */
+enum {
+	ACTION_CHANGED,
+	LAST_SIGNAL
+};
+
+#define SIGNAL_ACTION_CHANGED_NAME		"notify_pivot_of_action_changed"
+
 static GObjectClass *st_parent_class = NULL;
-static GSList       *st_stack_events = NULL;
+static gint          st_signals[ LAST_SIGNAL ] = { 0 };
 static GTimeVal      st_last_event;
 static guint         st_event_source_id = 0;
+static gint          st_timeout_usec = 500000;
 
 static GType       register_type( void );
 static void        class_init( NactPivotClass *klass );
 static void        instance_init( GTypeInstance *instance, gpointer klass );
 static GSList     *register_interface_providers( const NactPivot *pivot );
+static void        instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
+static void        instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
 static void        instance_dispose( GObject *object );
 static void        instance_finalize( GObject *object );
 
-static void        check_for_remove_action( NactPivot *pivot, NactAction *action );
-static gint        cmp_events( gconstpointer a, gconstpointer b );
-static void        free_stack_events( GSList *stack );
+static void        action_changed_handler( NactPivot *pivot, gpointer user_data );
+static void        update_action( GSList *actions, NactPivotNotify *notify );
+static NactAction *get_action( GSList *list, const gchar *uuid );
 static gboolean    on_action_changed_timeout( gpointer user_data );
-static stackItem  *stack_item_new( const gchar *uuid, const gchar *parm, const NactPivotValue *value );
-static void        stack_item_free( stackItem *item );
 static gulong      time_val_diff( const GTimeVal *recent, const GTimeVal *old );
-static void        update_actions( NactPivot *pivot, GSList *stack );
-static NactAction *get_action( GSList *list, const gchar *uuid );
 
 NactPivot *
-nact_pivot_new( void )
+nact_pivot_new( const GObject *target )
 {
-	return( g_object_new( NACT_PIVOT_TYPE, NULL ));
+	return( g_object_new( NACT_PIVOT_TYPE, PROP_NOTIFIED_STR, target, NULL ));
 }
 
 GType
@@ -135,8 +151,33 @@ class_init( NactPivotClass *klass )
 	GObjectClass *object_class = G_OBJECT_CLASS( klass );
 	object_class->dispose = instance_dispose;
 	object_class->finalize = instance_finalize;
+	object_class->set_property = instance_set_property;
+	object_class->get_property = instance_get_property;
+
+	GParamSpec *spec;
+	spec = g_param_spec_pointer(
+			PROP_NOTIFIED_STR,
+			PROP_NOTIFIED_STR,
+			"A pointer to a GObject which will receive action_changed notifications",
+			G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, PROP_NOTIFIED, spec );
 
 	klass->private = g_new0( NactPivotClassPrivate, 1 );
+
+	/* see nautilus_actions_class_init for why we use this function
+	 */
+	st_signals[ ACTION_CHANGED ] = g_signal_new_class_handler(
+				SIGNAL_ACTION_CHANGED_NAME,
+				G_TYPE_FROM_CLASS( klass ),
+				G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
+				( GCallback ) action_changed_handler,
+				NULL,
+				NULL,
+				g_cclosure_marshal_VOID__POINTER,
+				G_TYPE_NONE,
+				1,
+				G_TYPE_POINTER
+	);
 }
 
 static void
@@ -154,6 +195,40 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	self->private->actions = nact_iio_provider_load_actions( G_OBJECT( self ));
 }
 
+static void
+instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
+{
+	g_assert( NACT_IS_PIVOT( object ));
+	NactPivot *self = NACT_PIVOT( object );
+
+	switch( property_id ){
+		case PROP_NOTIFIED:
+			g_value_set_pointer( value, self->private->notified );
+			break;
+
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+			break;
+	}
+}
+
+static void
+instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec )
+{
+	g_assert( NACT_IS_PIVOT( object ));
+	NactPivot *self = NACT_PIVOT( object );
+
+	switch( property_id ){
+		case PROP_NOTIFIED:
+			self->private->notified = g_value_get_pointer( value );
+			break;
+
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+			break;
+	}
+}
+
 static GSList *
 register_interface_providers( const NactPivot *pivot )
 {
@@ -218,6 +293,13 @@ instance_finalize( GObject *object )
 
 /**
  * Returns the list of providers of the required interface.
+ *
+ * This function is called by interfaces API in order to find the
+ * list of providers registered for this given interface.
+ *
+ * @pivot: this instance.
+ *
+ * @type: the type of searched interface.
  */
 GSList *
 nact_pivot_get_providers( const NactPivot *pivot, GType type )
@@ -238,136 +320,71 @@ nact_pivot_get_providers( const NactPivot *pivot, GType type )
 	return( list );
 }
 
-/**
- * This function should be called when a storage subsystem detects that
- * a stored action has changed.
- * As a Nautilus extension, NactPivot will take care of updating menu
- * characteristics accordingly.
- *
- * @pivot: the NactPivot object.
- *
- * @uuid: identifiant of the action.
- *
- * @parm: the parameter path (e.g. "profile-main/path")
- *
- * @value: the new value as a NactPivotValue structure ; do not free it
- * here as it is the responsability of the allocater subsystem.
- *
- * Depending of the sort of update which occurs, we may receive many
- * notifications for the same action. We so stack the notifications and
- * start a one sec. timeout before updating the whole stack.
- */
-void
-nact_pivot_on_action_changed( NactPivot *pivot, const gchar *uuid, const gchar *parm, NactPivotValue *value )
+static void
+action_changed_handler( NactPivot *self, gpointer user_data  )
 {
-	static const gchar *thisfn = "nact_pivot_on_action_changed";
-	g_debug( "%s: pivot=%p, uuid='%s', parm='%s', value=%p", thisfn, pivot, uuid, parm, value );
+	/*static const gchar *thisfn = "nact_pivot_action_changed_handler";
+	g_debug( "%s: self=%p, data=%p", thisfn, self, user_data );*/
+
+	g_assert( NACT_IS_PIVOT( self ));
+	g_assert( user_data );
+	if( self->private->dispose_has_run ){
+		return;
+	}
 
-	stackItem *item = ( stackItem * ) stack_item_new( uuid, parm, value );
-	st_stack_events = g_slist_prepend( st_stack_events, item );
+	/* apply the change to the list of actions */
+	update_action( self->private->actions, ( NactPivotNotify * ) user_data );
 
+	/* set a timeout to notify nautilus at the end of the serie */
 	g_get_current_time( &st_last_event );
-
 	if( !st_event_source_id ){
-		st_event_source_id = g_timeout_add_seconds( 1, ( GSourceFunc ) on_action_changed_timeout, pivot );
+		st_event_source_id = g_timeout_add_seconds( 1, ( GSourceFunc ) on_action_changed_timeout, self );
 	}
 }
 
-/**
- * Duplicate a NactPivotValue structure and its content.
- */
-NactPivotValue *
-nact_pivot_duplicate_pivot_value( const NactPivotValue *value )
+static void
+update_action( GSList *actions, NactPivotNotify *notify )
 {
-	if( !value ){
-		return(( NactPivotValue * ) NULL );
-	}
-
-	NactPivotValue *newvalue = g_new0( NactPivotValue, 1 );
-
-	switch( value->type ){
-
-		case NACT_PIVOT_STR:
-			newvalue->data = g_strdup(( gchar * ) value->data );
-			break;
+	g_assert( notify );
+	if( notify->uuid && strlen( notify->uuid )){
 
-		case NACT_PIVOT_BOOL:
-			newvalue->data = value->data;
-			break;
-
-		case NACT_PIVOT_STRLIST:
-			newvalue->data = nactuti_duplicate_string_list(( GSList * ) value->data );
-			break;
+		NactAction *action = get_action( actions, notify->uuid );
+		g_debug( "nact_pivot_update_action: uuid='%s', parm='%s', action=%p", notify->uuid, notify->parm, action );
+		if( !action ){
+			/* this is a creation */
 
-		default:
-			g_assert_not_reached();
-			break;
+		} else {
+			/* this is an update or a deletion */
+		}
 	}
 
-	return( newvalue );
+	nact_pivot_free_notify( notify );
 }
 
-/**
- * Free a NactPivotValue structure and its content.
- */
-void
-nact_pivot_free_pivot_value( NactPivotValue *value )
+static NactAction *
+get_action( GSList *list, const gchar *uuid )
 {
-	if( value ){
-		switch( value->type ){
-
-			case NACT_PIVOT_STR:
-				g_free(( gchar * ) value->data );
-				break;
-
-			case NACT_PIVOT_BOOL:
-				break;
-
-			case NACT_PIVOT_STRLIST:
-				nactuti_free_string_list(( GSList * ) value->data );
-				break;
-
-			default:
-				g_assert_not_reached();
-				break;
+	NactAction *found = NULL;
+	GSList *ia;
+	for( ia = list ; ia && !found ; ia = ia->next ){
+		NactAction *action = ( NactAction * ) ia->data;
+		gchar *id = nact_action_get_uuid( action );
+		if( !g_strcmp0( id, uuid )){
+			found = action;
 		}
-		g_free( value );
-	}
-}
-
-static void
-check_for_remove_action( NactPivot *pivot, NactAction *action )
-{
-	static const gchar *thisfn ="check_for_remove_action";
-
-	g_assert( NACT_IS_PIVOT( pivot ));
-	g_assert( NACT_IS_ACTION( action ));
-
-	if( nact_action_is_empty( action )){
-		g_debug( "%s: removing action %p", thisfn, action );
-		pivot->private->actions = g_slist_remove( pivot->private->actions, action );
+		g_free( id );
 	}
+	return( found );
 }
 
-/*
- * comparaison function between two stack items
+/**
+ * Returns the searched NactAction, or NULL.
  */
-static gint
-cmp_events( gconstpointer a, gconstpointer b )
-{
-	stackItem *sa = ( stackItem * ) a;
-	stackItem *sb = ( stackItem * ) b;
-	return( g_strcmp0( sa->uuid, sb->uuid ));
-}
-
-static void
-free_stack_events( GSList *stack )
+GObject *
+nact_pivot_get_action( NactPivot *pivot, const gchar *uuid )
 {
-	GSList *is;
-	for( is = stack ; is ; is = is->next ){
-		stack_item_free(( stackItem * ) is->data );
-	}
-	g_slist_free( stack );
+	g_assert( NACT_IS_PIVOT( pivot ));
+	return( G_OBJECT( get_action( pivot->private->actions, uuid )));
 }
 
 /*
@@ -376,47 +393,29 @@ free_stack_events( GSList *stack )
  * second old
  *
  * there is no race condition here as we are not multithreaded
+ * or .. is there ?
  */
 static gboolean
 on_action_changed_timeout( gpointer user_data )
 {
-	static const gchar *thisfn = "on_action_changed_timeout";
+	/*static const gchar *thisfn = "nact_pivot_on_action_changed_timeout";
+	g_debug( "%s: pivot=%p", thisfn, user_data );*/
+
 	GTimeVal now;
 
 	g_assert( NACT_IS_PIVOT( user_data ));
+	NactPivot *pivot = NACT_PIVOT( user_data );
 
 	g_get_current_time( &now );
 	gulong diff = time_val_diff( &now, &st_last_event );
-	if( diff < 500000 ){
+	if( diff < st_timeout_usec ){
 		return( TRUE );
 	}
 
-	g_debug( "%s: treating stack with %d events", thisfn, g_slist_length( st_stack_events ));
-	update_actions( NACT_PIVOT( user_data ), st_stack_events );
-
+	g_signal_emit_by_name( G_OBJECT( pivot->private->notified ), "notify_nautilus_of_action_changed" );
 	st_event_source_id = 0;
-	free_stack_events( st_stack_events );
-	st_stack_events = NULL;
-	return( FALSE );
-}
 
-static stackItem *
-stack_item_new( const gchar *uuid, const gchar *parm, const NactPivotValue *value )
-{
-	stackItem *item = g_new0( stackItem, 1 );
-	item->uuid = g_strdup( uuid );
-	item->parm = g_strdup( parm );
-	item->value = nact_pivot_duplicate_pivot_value( value );
-	return( item );
-}
-
-static void
-stack_item_free( stackItem *item )
-{
-	g_free( item->uuid );
-	g_free( item->parm );
-	nact_pivot_free_pivot_value( item->value );
-	g_free( item );
+	return( FALSE );
 }
 
 /*
@@ -430,70 +429,35 @@ time_val_diff( const GTimeVal *recent, const GTimeVal *old )
 	return( microsec );
 }
 
-/*
- * iterate through the list of events, sorted by action id
- * on new action, add it to the list, creating the object
- * when all events have been treated, check to see if the action was
- * actually removed (all fields, including key, are blank or null)
- *
- * remove = key + parm=null and value=null
+/**
+ * Free a NactPivotValue structure and its content.
  */
-static void
-update_actions( NactPivot *pivot, GSList *stack )
-{
-	GSList *it;
-	NactAction *action = NULL;
-	gchar *previd = NULL;
-
-	GSList *sorted = g_slist_sort( stack, cmp_events );
-
-	for( it = sorted ; it ; it = it->next ){
-		stackItem *item = ( stackItem * ) it->data;
-
-		if( action && g_strcmp0( previd, item->uuid )){
-			g_assert( action && NACT_IS_ACTION( action ));
-			check_for_remove_action( pivot, action );
-			g_free( previd );
-		}
-		previd = g_strdup( item->uuid );
-		action = get_action( pivot->private->actions, item->uuid );
-
-		if( action ){
-			nact_action_update( action, item->parm, item->value );
-		} else {
-			action = nact_action_create( item->uuid, item->parm, item->value );
-			pivot->private->actions = g_slist_prepend( pivot->private->actions, action );
-		}
-	}
-	if( action ){
-		g_assert( action && NACT_IS_ACTION( action ));
-		check_for_remove_action( pivot, action );
-		g_free( previd );
-	}
-}
-
-static NactAction *
-get_action( GSList *list, const gchar *uuid )
+void
+nact_pivot_free_notify( NactPivotNotify *npn )
 {
-	NactAction *found = NULL;
-	GSList *ia;
-	for( ia = list ; ia && !found ; ia = ia->next ){
-		NactAction *action = ( NactAction * ) ia->data;
-		gchar *id = nact_action_get_uuid( action );
-		if( !g_strcmp0( id, uuid )){
-			found = action;
+	if( npn ){
+		if( npn->type ){
+			switch( npn->type ){
+
+				case NACT_PIVOT_STR:
+					g_free(( gchar * ) npn->data );
+					break;
+
+				case NACT_PIVOT_BOOL:
+					break;
+
+				case NACT_PIVOT_STRLIST:
+					nactuti_free_string_list(( GSList * ) npn->data );
+					break;
+
+				default:
+					g_debug( "nact_pivot_free_notify: uuid=%s, parm=%s, type=%d", npn->uuid, npn->parm, npn->type );
+					g_assert_not_reached();
+					break;
+			}
 		}
-		g_free( id );
+		g_free( npn->uuid );
+		g_free( npn->parm );
+		g_free( npn );
 	}
-	return( found );
-}
-
-/**
- * Returns the searched NactAction, or NULL.
- */
-GObject *
-nact_pivot_get_action( NactPivot *pivot, const gchar *uuid )
-{
-	g_assert( NACT_IS_PIVOT( pivot ));
-	return( G_OBJECT( get_action( pivot->private->actions, uuid )));
 }
diff --git a/src/common/nact-pivot.h b/src/common/nact-pivot.h
index 0ea8b0e..6f8ff91 100644
--- a/src/common/nact-pivot.h
+++ b/src/common/nact-pivot.h
@@ -44,24 +44,6 @@
 
 G_BEGIN_DECLS
 
-/*
- * We would want have a sort of GConfValue, but which is not named with
- * GConf, in order to propose this same structure to other storage
- * subsystems.
- * We so define this, with only the data types we need.
- */
-enum {
-	NACT_PIVOT_STR = 1,
-	NACT_PIVOT_BOOL,
-	NACT_PIVOT_STRLIST
-};
-
-typedef struct {
-	guint    type;
-	gpointer data;
-}
-	NactPivotValue;
-
 #define NACT_PIVOT_TYPE					( nact_pivot_get_type())
 #define NACT_PIVOT( object )			( G_TYPE_CHECK_INSTANCE_CAST( object, NACT_PIVOT_TYPE, NactPivot ))
 #define NACT_PIVOT_CLASS( klass )		( G_TYPE_CHECK_CLASS_CAST( klass, NACT_PIVOT_TYPE, NactPivotClass ))
@@ -85,17 +67,33 @@ typedef struct {
 }
 	NactPivotClass;
 
-GType           nact_pivot_get_type( void );
+GType      nact_pivot_get_type( void );
 
-NactPivot      *nact_pivot_new( void );
+NactPivot *nact_pivot_new( const GObject *notified );
 
-GSList         *nact_pivot_get_providers( const NactPivot *pivot, GType type );
+GSList    *nact_pivot_get_providers( const NactPivot *pivot, GType type );
 
-GObject        *nact_pivot_get_action( NactPivot *pivot, const gchar *uuid );
-void            nact_pivot_on_action_changed( NactPivot *pivot, const gchar *uuid, const gchar *parm, NactPivotValue *value );
+GObject   *nact_pivot_get_action( NactPivot *pivot, const gchar *uuid );
+
+/*void       nact_pivot_on_action_changed( NactPivot *pivot, const gchar *uuid, const gchar *parm, NactPivotValue *value );*/
+
+/* data passed from the storage subsystem when an action is changed
+ */
+enum {
+	NACT_PIVOT_STR = 1,
+	NACT_PIVOT_BOOL,
+	NACT_PIVOT_STRLIST
+};
+
+typedef struct {
+	gchar   *uuid;
+	gchar   *parm;
+	guint    type;
+	gpointer data;
+}
+	NactPivotNotify;
 
-NactPivotValue *nact_pivot_duplicate_pivot_value( const NactPivotValue *value );
-void            nact_pivot_free_pivot_value( NactPivotValue *value );
+void       nact_pivot_free_notify( NactPivotNotify *data );
 
 G_END_DECLS
 
diff --git a/src/common/nact-uti-lists.h b/src/common/nact-uti-lists.h
index 42772d3..bd178e3 100644
--- a/src/common/nact-uti-lists.h
+++ b/src/common/nact-uti-lists.h
@@ -41,6 +41,7 @@ G_BEGIN_DECLS
 
 void     nactuti_free_object_list( GSList *list );
 
+gboolean nactuti_is_empty_string_list( GSList *list );
 GSList  *nactuti_duplicate_string_list( GSList *list );
 void     nactuti_free_string_list( GSList *list );
 
diff --git a/src/common/nautilus-actions-config.c b/src/common/nautilus-actions-config.c
index bff7756..92ecbc1 100644
--- a/src/common/nautilus-actions-config.c
+++ b/src/common/nautilus-actions-config.c
@@ -94,7 +94,7 @@ nautilus_actions_config_class_init (NautilusActionsConfigClass *klass)
 														NULL, NULL,
 														g_cclosure_marshal_VOID__POINTER,
 														G_TYPE_NONE, 1, G_TYPE_POINTER);
-	signals[ACTION_CHANGED] = g_signal_new ("action_changed",
+	signals[ACTION_CHANGED] = g_signal_new ("action_changed_old",
 														G_TYPE_FROM_CLASS (object_class),
 														G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
 														G_STRUCT_OFFSET (NautilusActionsConfigClass, action_changed),
diff --git a/src/plugin/nautilus-actions.c b/src/plugin/nautilus-actions.c
index 3876642..bf38a80 100644
--- a/src/plugin/nautilus-actions.c
+++ b/src/plugin/nautilus-actions.c
@@ -51,6 +51,13 @@
 #include "nautilus-actions-test.h"
 #include "nautilus-actions-utils.h"
 
+/* private class data
+ */
+struct NautilusActionsClassPrivate {
+};
+
+/* private instance data
+ */
 struct NautilusActionsPrivate {
 	gboolean   dispose_has_run;
 
@@ -62,11 +69,31 @@ struct NautilusActionsPrivate {
 	GSList* config_list;
 };
 
-struct NautilusActionsClassPrivate {
+/* We have a double stage notification system :
+ *
+ * 1. when the storage subsystems detects a change on an action, it must
+ *    emit a signal to notify us of this change ; we so have to update
+ *    accordingly the list of actions we maintain
+ *
+ * 2. when we have successfully updated the list of actions, we have to
+ *    notify nautilus to update its contextual menu ; this is left to
+ *    NautilusActions class
+ *
+ * This same signal is then first emitted by the IIOProvider to the
+ * NactPivot object which handles it. When all modifications have been
+ * treated, NactPivot notifies NautilusActions which itself asks
+ * Nautilus for updating its menu
+ */
+enum {
+	ACTION_CHANGED,
+	LAST_SIGNAL
 };
 
+#define SIGNAL_ACTION_CHANGED_NAME		"notify_nautilus_of_action_changed"
+
 static GObjectClass *st_parent_class = NULL;
 static GType         st_actions_type = 0;
+static gint          st_signals[ LAST_SIGNAL ] = { 0 };
 
 static void class_init( NautilusActionsClass *klass );
 static void menu_provider_iface_init( NautilusMenuProviderIface *iface );
@@ -74,12 +101,13 @@ static void instance_init( GTypeInstance *instance, gpointer klass );
 static void instance_dispose( GObject *object );
 static void instance_finalize( GObject *object );
 
-static void              action_changed_handler( NautilusActionsConfig* config, NautilusActionsConfigAction* action, gpointer user_data );
-static NautilusMenuItem *create_menu_item( NautilusActionsConfigAction *action, GList *files, NautilusActionsConfigActionProfile* action_profile );
-static void              execute_action( NautilusMenuItem *item, NautilusActionsConfigActionProfile *action_profile );
 static GList            *get_background_items( NautilusMenuProvider *provider, GtkWidget *window, NautilusFileInfo *current_folder );
 static GList            *get_file_items( NautilusMenuProvider *provider, GtkWidget *window, GList *files );
 static const gchar      *get_verified_icon_name( const gchar* icon_name );
+static NautilusMenuItem *create_menu_item( NautilusActionsConfigAction *action, GList *files, NautilusActionsConfigActionProfile* action_profile );
+static void              execute_action( NautilusMenuItem *item, NautilusActionsConfigActionProfile *action_profile );
+static void              action_changed_handler( NautilusActions *instance, gpointer user_data );
+static void              action_changed_handler_old( NautilusActionsConfig* config, NautilusActionsConfigAction* action, gpointer user_data );
 
 GType
 nautilus_actions_get_type( void )
@@ -132,6 +160,26 @@ class_init( NautilusActionsClass *klass )
 	gobject_class->finalize = instance_finalize;
 
 	klass->private = g_new0( NautilusActionsClassPrivate, 1 );
+
+	/* we could have set a default handler here, which have been
+	 * avoided us to connect to the signal ; but a default handler is
+	 * addressed via a class structure offset, and thus cannot work
+	 * when defined in a private structure
+	 *
+	 * the previous point applies to g_signal_new
+	 * g_signal_new_class_handler let us specify a standard C callback
+	 */
+	st_signals[ ACTION_CHANGED ] = g_signal_new_class_handler(
+				SIGNAL_ACTION_CHANGED_NAME,
+				G_TYPE_FROM_CLASS( klass ),
+				G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
+				( GCallback ) action_changed_handler,
+				NULL,
+				NULL,
+				g_cclosure_marshal_VOID__VOID,
+				G_TYPE_NONE,
+				0
+	);
 }
 
 static void
@@ -170,7 +218,19 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	self->private = g_new0( NautilusActionsPrivate, 1 );
 
 	/* from nact-pivot */
-	self->private->pivot = nact_pivot_new();
+	self->private->pivot = nact_pivot_new( G_OBJECT( self ));
+
+	/* see nautilus_actions_class_init for why we have to connect an
+	 * handler to our signal instead of relying on default handler
+	 * see also nautilus_actions_class_init for why g_signal_connect is
+	 * no more needed
+	 */
+	/*g_signal_connect(
+			G_OBJECT( self ),
+			SIGNAL_ACTION_CHANGED_NAME,
+			( GCallback ) action_changed_handler,
+			NULL
+	);*/
 
 	self->private->configs = NULL;
 	self->private->configs = nautilus_actions_config_gconf_reader_get ();
@@ -181,19 +241,19 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	g_signal_connect_after(
 			G_OBJECT( self->private->configs ),
 			"action_added",
-			( GCallback ) action_changed_handler,
+			( GCallback ) action_changed_handler_old,
 			self
 	);
 	g_signal_connect_after(
 			G_OBJECT( self->private->configs ),
-			"action_changed",
-			( GCallback ) action_changed_handler,
+			"action_changed_old",
+			( GCallback ) action_changed_handler_old,
 			self
 	);
 	g_signal_connect_after(
 			G_OBJECT( self->private->configs ),
 			"action_removed",
-			( GCallback ) action_changed_handler,
+			( GCallback ) action_changed_handler_old,
 			self
 	);
 }
@@ -240,92 +300,6 @@ static void nautilus_menu_provider_emit_items_updated_signal (NautilusMenuProvid
 }
 #endif
 
-static void
-action_changed_handler( NautilusActionsConfig* config,
-						NautilusActionsConfigAction* action,
-						gpointer user_data )
-{
-	static const gchar *thisfn = "nautilus_actions_action_changed_handler";
-	g_debug( "%s", thisfn );
-
-	NautilusActions* self = NAUTILUS_ACTIONS (user_data);
-
-	g_return_if_fail (NAUTILUS_IS_ACTIONS (self));
-
-	if (!self->private->dispose_has_run)
-	{
-		nautilus_menu_provider_emit_items_updated_signal(( NautilusMenuProvider * ) self );
-
-		nautilus_actions_config_free_actions_list (self->private->config_list);
-		self->private->config_list = nautilus_actions_config_get_actions (NAUTILUS_ACTIONS_CONFIG (self->private->configs));
-	}
-}
-
-static NautilusMenuItem *
-create_menu_item( NautilusActionsConfigAction *action, GList *files, NautilusActionsConfigActionProfile* action_profile )
-{
-	static const gchar *thisfn = "nautilus_actions_create_menu_item";
-	g_debug( "%s", thisfn );
-
-	NautilusMenuItem *item;
-	gchar* name;
-	const gchar* icon_name = get_verified_icon_name (g_strstrip (action->icon));
-	NautilusActionsConfigActionProfile* action_profile4menu = nautilus_actions_config_action_profile_dup (action_profile);
-
-	name = g_strdup_printf ("NautilusActions::%s", action->uuid);
-
-	item = nautilus_menu_item_new (name,
-				action->label,
-				action->tooltip,
-				icon_name);
-
-	g_signal_connect_data (item,
-				"activate",
-				G_CALLBACK (execute_action),
-				action_profile4menu,
-				(GClosureNotify)nautilus_actions_config_action_profile_free,
-				0);
-
-	g_object_set_data_full (G_OBJECT (item),
-			"files",
-			nautilus_file_info_list_copy (files),
-			(GDestroyNotify) nautilus_file_info_list_free);
-
-
-	g_free (name);
-
-	return item;
-}
-
-static void
-execute_action( NautilusMenuItem *item, NautilusActionsConfigActionProfile *action_profile )
-{
-	static const gchar *thisfn = "nautilus_actions_execute_action";
-	g_debug( "%s", thisfn );
-
-	GList *files;
-	GString *cmd;
-	gchar* param = NULL;
-
-	files = (GList*)g_object_get_data (G_OBJECT (item), "files");
-
-	cmd = g_string_new (action_profile->path);
-
-	param = nautilus_actions_utils_parse_parameter (action_profile->parameters, files);
-
-	if (param != NULL)
-	{
-		g_string_append_printf (cmd, " %s", param);
-		g_free (param);
-	}
-
-	g_spawn_command_line_async (cmd->str, NULL);
-	g_debug( "%s: commande='%s'", thisfn, cmd->str );
-
-	g_string_free (cmd, TRUE);
-
-}
-
 /*
  * this function is called when nautilus has to paint a folder background
  * one of the first calls is with current_folder = 'x-nautilus-desktop:///'
@@ -418,3 +392,106 @@ get_verified_icon_name( const gchar* icon_name )
 
 	return icon_name;
 }
+
+static NautilusMenuItem *
+create_menu_item( NautilusActionsConfigAction *action, GList *files, NautilusActionsConfigActionProfile* action_profile )
+{
+	static const gchar *thisfn = "nautilus_actions_create_menu_item";
+	g_debug( "%s", thisfn );
+
+	NautilusMenuItem *item;
+	gchar* name;
+	const gchar* icon_name = get_verified_icon_name (g_strstrip (action->icon));
+	NautilusActionsConfigActionProfile* action_profile4menu = nautilus_actions_config_action_profile_dup (action_profile);
+
+	name = g_strdup_printf ("NautilusActions::%s", action->uuid);
+
+	item = nautilus_menu_item_new (name,
+				action->label,
+				action->tooltip,
+				icon_name);
+
+	g_signal_connect_data (item,
+				"activate",
+				G_CALLBACK (execute_action),
+				action_profile4menu,
+				(GClosureNotify)nautilus_actions_config_action_profile_free,
+				0);
+
+	g_object_set_data_full (G_OBJECT (item),
+			"files",
+			nautilus_file_info_list_copy (files),
+			(GDestroyNotify) nautilus_file_info_list_free);
+
+
+	g_free (name);
+
+	return item;
+}
+
+static void
+execute_action( NautilusMenuItem *item, NautilusActionsConfigActionProfile *action_profile )
+{
+	static const gchar *thisfn = "nautilus_actions_execute_action";
+	g_debug( "%s", thisfn );
+
+	GList *files;
+	GString *cmd;
+	gchar* param = NULL;
+
+	files = (GList*)g_object_get_data (G_OBJECT (item), "files");
+
+	cmd = g_string_new (action_profile->path);
+
+	param = nautilus_actions_utils_parse_parameter (action_profile->parameters, files);
+
+	if (param != NULL)
+	{
+		g_string_append_printf (cmd, " %s", param);
+		g_free (param);
+	}
+
+	g_spawn_command_line_async (cmd->str, NULL);
+	g_debug( "%s: commande='%s'", thisfn, cmd->str );
+
+	g_string_free (cmd, TRUE);
+
+}
+
+static void
+action_changed_handler( NautilusActions *self, gpointer user_data )
+{
+	static const gchar *thisfn = "nautilus_actions_action_changed_handler";
+	g_debug( "%s: self=%p, user_data=%p", thisfn, self, user_data );
+
+	g_return_if_fail( NAUTILUS_IS_ACTIONS( self ));
+
+	if( !self->private->dispose_has_run ){
+
+		nautilus_menu_provider_emit_items_updated_signal( NAUTILUS_MENU_PROVIDER( self ));
+
+		/*nautilus_actions_config_free_actions_list (self->private->config_list);
+		self->private->config_list = nautilus_actions_config_get_actions (NAUTILUS_ACTIONS_CONFIG (self->private->configs));*/
+	}
+}
+
+static void
+action_changed_handler_old( NautilusActionsConfig* config,
+						NautilusActionsConfigAction* action,
+						gpointer user_data )
+{
+	static const gchar *thisfn = "nautilus_actions_action_changed_handler_old";
+	g_debug( "%s", thisfn );
+
+	NautilusActions* self = NAUTILUS_ACTIONS (user_data);
+
+	g_return_if_fail (NAUTILUS_IS_ACTIONS (self));
+
+	if (!self->private->dispose_has_run)
+	{
+		nautilus_menu_provider_emit_items_updated_signal(( NautilusMenuProvider * ) self );
+
+		nautilus_actions_config_free_actions_list (self->private->config_list);
+		self->private->config_list = nautilus_actions_config_get_actions (NAUTILUS_ACTIONS_CONFIG (self->private->configs));
+	}
+}



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